Commit 0b524123 authored by Chuck Lever's avatar Chuck Lever Committed by Trond Myklebust

NFS: Add ability to send MOUNTPROC_UMNT to the kernel's mountd client

After certain failure modes of an NFS mount, an NFS client should send
a MOUNTPROC_UMNT request to remove the just-added mount entry from the
server's mount table.  While no-one should rely on the accuracy of the
server's mount table, sending a UMNT is simply being a good internet
neighbor.

Since NFS mount processing is handled in the kernel now, we will need
a function in the kernel's mountd client that can post a MOUNTRPC_UMNT
request, in order to handle these failure modes.
Signed-off-by: default avatarChuck Lever <chuck.lever@oracle.com>
Signed-off-by: default avatarTrond Myklebust <Trond.Myklebust@netapp.com>
parent f3f4f4ed
...@@ -102,6 +102,7 @@ struct nfs_mount_request { ...@@ -102,6 +102,7 @@ struct nfs_mount_request {
}; };
extern int nfs_mount(struct nfs_mount_request *info); extern int nfs_mount(struct nfs_mount_request *info);
extern void nfs_umount(const struct nfs_mount_request *info);
/* client.c */ /* client.c */
extern struct rpc_program nfs_program; extern struct rpc_program nfs_program;
......
...@@ -209,6 +209,71 @@ int nfs_mount(struct nfs_mount_request *info) ...@@ -209,6 +209,71 @@ int nfs_mount(struct nfs_mount_request *info)
goto out; goto out;
} }
/**
* nfs_umount - Notify a server that we have unmounted this export
* @info: pointer to umount request arguments
*
* MOUNTPROC_UMNT is advisory, so we set a short timeout, and always
* use UDP.
*/
void nfs_umount(const struct nfs_mount_request *info)
{
static const struct rpc_timeout nfs_umnt_timeout = {
.to_initval = 1 * HZ,
.to_maxval = 3 * HZ,
.to_retries = 2,
};
struct rpc_create_args args = {
.protocol = IPPROTO_UDP,
.address = info->sap,
.addrsize = info->salen,
.timeout = &nfs_umnt_timeout,
.servername = info->hostname,
.program = &mnt_program,
.version = info->version,
.authflavor = RPC_AUTH_UNIX,
.flags = RPC_CLNT_CREATE_NOPING,
};
struct mountres result;
struct rpc_message msg = {
.rpc_argp = info->dirpath,
.rpc_resp = &result,
};
struct rpc_clnt *clnt;
int status;
if (info->noresvport)
args.flags |= RPC_CLNT_CREATE_NONPRIVPORT;
clnt = rpc_create(&args);
if (unlikely(IS_ERR(clnt)))
goto out_clnt_err;
dprintk("NFS: sending UMNT request for %s:%s\n",
(info->hostname ? info->hostname : "server"), info->dirpath);
if (info->version == NFS_MNT3_VERSION)
msg.rpc_proc = &clnt->cl_procinfo[MOUNTPROC3_UMNT];
else
msg.rpc_proc = &clnt->cl_procinfo[MOUNTPROC_UMNT];
status = rpc_call_sync(clnt, &msg, 0);
rpc_shutdown_client(clnt);
if (unlikely(status < 0))
goto out_call_err;
return;
out_clnt_err:
dprintk("NFS: failed to create UMNT RPC client, status=%ld\n",
PTR_ERR(clnt));
return;
out_call_err:
dprintk("NFS: UMNT request failed, status=%d\n", status);
}
/* /*
* XDR encode/decode functions for MOUNT * XDR encode/decode functions for MOUNT
*/ */
...@@ -407,6 +472,13 @@ static struct rpc_procinfo mnt_procedures[] = { ...@@ -407,6 +472,13 @@ static struct rpc_procinfo mnt_procedures[] = {
.p_statidx = MOUNTPROC_MNT, .p_statidx = MOUNTPROC_MNT,
.p_name = "MOUNT", .p_name = "MOUNT",
}, },
[MOUNTPROC_UMNT] = {
.p_proc = MOUNTPROC_UMNT,
.p_encode = (kxdrproc_t)mnt_enc_dirpath,
.p_arglen = MNT_enc_dirpath_sz,
.p_statidx = MOUNTPROC_UMNT,
.p_name = "UMOUNT",
},
}; };
static struct rpc_procinfo mnt3_procedures[] = { static struct rpc_procinfo mnt3_procedures[] = {
...@@ -419,6 +491,13 @@ static struct rpc_procinfo mnt3_procedures[] = { ...@@ -419,6 +491,13 @@ static struct rpc_procinfo mnt3_procedures[] = {
.p_statidx = MOUNTPROC3_MNT, .p_statidx = MOUNTPROC3_MNT,
.p_name = "MOUNT", .p_name = "MOUNT",
}, },
[MOUNTPROC3_UMNT] = {
.p_proc = MOUNTPROC3_UMNT,
.p_encode = (kxdrproc_t)mnt_enc_dirpath,
.p_arglen = MNT_enc_dirpath_sz,
.p_statidx = MOUNTPROC3_UMNT,
.p_name = "UMOUNT",
},
}; };
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment