diff options
Diffstat (limited to 'fs/nfs/mount_clnt.c')
-rw-r--r-- | fs/nfs/mount_clnt.c | 83 |
1 files changed, 81 insertions, 2 deletions
diff --git a/fs/nfs/mount_clnt.c b/fs/nfs/mount_clnt.c index 38ef9eaec407..0adefc40cc89 100644 --- a/fs/nfs/mount_clnt.c +++ b/fs/nfs/mount_clnt.c | |||
@@ -209,6 +209,71 @@ out_mnt_err: | |||
209 | goto out; | 209 | goto out; |
210 | } | 210 | } |
211 | 211 | ||
212 | /** | ||
213 | * nfs_umount - Notify a server that we have unmounted this export | ||
214 | * @info: pointer to umount request arguments | ||
215 | * | ||
216 | * MOUNTPROC_UMNT is advisory, so we set a short timeout, and always | ||
217 | * use UDP. | ||
218 | */ | ||
219 | void nfs_umount(const struct nfs_mount_request *info) | ||
220 | { | ||
221 | static const struct rpc_timeout nfs_umnt_timeout = { | ||
222 | .to_initval = 1 * HZ, | ||
223 | .to_maxval = 3 * HZ, | ||
224 | .to_retries = 2, | ||
225 | }; | ||
226 | struct rpc_create_args args = { | ||
227 | .protocol = IPPROTO_UDP, | ||
228 | .address = info->sap, | ||
229 | .addrsize = info->salen, | ||
230 | .timeout = &nfs_umnt_timeout, | ||
231 | .servername = info->hostname, | ||
232 | .program = &mnt_program, | ||
233 | .version = info->version, | ||
234 | .authflavor = RPC_AUTH_UNIX, | ||
235 | .flags = RPC_CLNT_CREATE_NOPING, | ||
236 | }; | ||
237 | struct mountres result; | ||
238 | struct rpc_message msg = { | ||
239 | .rpc_argp = info->dirpath, | ||
240 | .rpc_resp = &result, | ||
241 | }; | ||
242 | struct rpc_clnt *clnt; | ||
243 | int status; | ||
244 | |||
245 | if (info->noresvport) | ||
246 | args.flags |= RPC_CLNT_CREATE_NONPRIVPORT; | ||
247 | |||
248 | clnt = rpc_create(&args); | ||
249 | if (unlikely(IS_ERR(clnt))) | ||
250 | goto out_clnt_err; | ||
251 | |||
252 | dprintk("NFS: sending UMNT request for %s:%s\n", | ||
253 | (info->hostname ? info->hostname : "server"), info->dirpath); | ||
254 | |||
255 | if (info->version == NFS_MNT3_VERSION) | ||
256 | msg.rpc_proc = &clnt->cl_procinfo[MOUNTPROC3_UMNT]; | ||
257 | else | ||
258 | msg.rpc_proc = &clnt->cl_procinfo[MOUNTPROC_UMNT]; | ||
259 | |||
260 | status = rpc_call_sync(clnt, &msg, 0); | ||
261 | rpc_shutdown_client(clnt); | ||
262 | |||
263 | if (unlikely(status < 0)) | ||
264 | goto out_call_err; | ||
265 | |||
266 | return; | ||
267 | |||
268 | out_clnt_err: | ||
269 | dprintk("NFS: failed to create UMNT RPC client, status=%ld\n", | ||
270 | PTR_ERR(clnt)); | ||
271 | return; | ||
272 | |||
273 | out_call_err: | ||
274 | dprintk("NFS: UMNT request failed, status=%d\n", status); | ||
275 | } | ||
276 | |||
212 | /* | 277 | /* |
213 | * XDR encode/decode functions for MOUNT | 278 | * XDR encode/decode functions for MOUNT |
214 | */ | 279 | */ |
@@ -258,7 +323,7 @@ static int decode_status(struct xdr_stream *xdr, struct mountres *res) | |||
258 | return -EIO; | 323 | return -EIO; |
259 | status = ntohl(*p); | 324 | status = ntohl(*p); |
260 | 325 | ||
261 | for (i = 0; i <= ARRAY_SIZE(mnt_errtbl); i++) { | 326 | for (i = 0; i < ARRAY_SIZE(mnt_errtbl); i++) { |
262 | if (mnt_errtbl[i].status == status) { | 327 | if (mnt_errtbl[i].status == status) { |
263 | res->errno = mnt_errtbl[i].errno; | 328 | res->errno = mnt_errtbl[i].errno; |
264 | return 0; | 329 | return 0; |
@@ -309,7 +374,7 @@ static int decode_fhs_status(struct xdr_stream *xdr, struct mountres *res) | |||
309 | return -EIO; | 374 | return -EIO; |
310 | status = ntohl(*p); | 375 | status = ntohl(*p); |
311 | 376 | ||
312 | for (i = 0; i <= ARRAY_SIZE(mnt3_errtbl); i++) { | 377 | for (i = 0; i < ARRAY_SIZE(mnt3_errtbl); i++) { |
313 | if (mnt3_errtbl[i].status == status) { | 378 | if (mnt3_errtbl[i].status == status) { |
314 | res->errno = mnt3_errtbl[i].errno; | 379 | res->errno = mnt3_errtbl[i].errno; |
315 | return 0; | 380 | return 0; |
@@ -407,6 +472,13 @@ static struct rpc_procinfo mnt_procedures[] = { | |||
407 | .p_statidx = MOUNTPROC_MNT, | 472 | .p_statidx = MOUNTPROC_MNT, |
408 | .p_name = "MOUNT", | 473 | .p_name = "MOUNT", |
409 | }, | 474 | }, |
475 | [MOUNTPROC_UMNT] = { | ||
476 | .p_proc = MOUNTPROC_UMNT, | ||
477 | .p_encode = (kxdrproc_t)mnt_enc_dirpath, | ||
478 | .p_arglen = MNT_enc_dirpath_sz, | ||
479 | .p_statidx = MOUNTPROC_UMNT, | ||
480 | .p_name = "UMOUNT", | ||
481 | }, | ||
410 | }; | 482 | }; |
411 | 483 | ||
412 | static struct rpc_procinfo mnt3_procedures[] = { | 484 | static struct rpc_procinfo mnt3_procedures[] = { |
@@ -419,6 +491,13 @@ static struct rpc_procinfo mnt3_procedures[] = { | |||
419 | .p_statidx = MOUNTPROC3_MNT, | 491 | .p_statidx = MOUNTPROC3_MNT, |
420 | .p_name = "MOUNT", | 492 | .p_name = "MOUNT", |
421 | }, | 493 | }, |
494 | [MOUNTPROC3_UMNT] = { | ||
495 | .p_proc = MOUNTPROC3_UMNT, | ||
496 | .p_encode = (kxdrproc_t)mnt_enc_dirpath, | ||
497 | .p_arglen = MNT_enc_dirpath_sz, | ||
498 | .p_statidx = MOUNTPROC3_UMNT, | ||
499 | .p_name = "UMOUNT", | ||
500 | }, | ||
422 | }; | 501 | }; |
423 | 502 | ||
424 | 503 | ||