diff options
Diffstat (limited to 'fs/nfs/nfs4proc.c')
-rw-r--r-- | fs/nfs/nfs4proc.c | 182 |
1 files changed, 91 insertions, 91 deletions
diff --git a/fs/nfs/nfs4proc.c b/fs/nfs/nfs4proc.c index 0e5ff69455c7..ff5bddc49a2a 100644 --- a/fs/nfs/nfs4proc.c +++ b/fs/nfs/nfs4proc.c | |||
@@ -78,7 +78,6 @@ struct nfs4_opendata; | |||
78 | static int _nfs4_proc_open(struct nfs4_opendata *data); | 78 | static int _nfs4_proc_open(struct nfs4_opendata *data); |
79 | static int _nfs4_recover_proc_open(struct nfs4_opendata *data); | 79 | static int _nfs4_recover_proc_open(struct nfs4_opendata *data); |
80 | static int nfs4_do_fsinfo(struct nfs_server *, struct nfs_fh *, struct nfs_fsinfo *); | 80 | static int nfs4_do_fsinfo(struct nfs_server *, struct nfs_fh *, struct nfs_fsinfo *); |
81 | static int nfs4_async_handle_error(struct rpc_task *, const struct nfs_server *, struct nfs4_state *, long *); | ||
82 | static void nfs_fixup_referral_attributes(struct nfs_fattr *fattr); | 81 | static void nfs_fixup_referral_attributes(struct nfs_fattr *fattr); |
83 | static int nfs4_proc_getattr(struct nfs_server *, struct nfs_fh *, struct nfs_fattr *, struct nfs4_label *label); | 82 | static int nfs4_proc_getattr(struct nfs_server *, struct nfs_fh *, struct nfs_fattr *, struct nfs4_label *label); |
84 | static int _nfs4_proc_getattr(struct nfs_server *server, struct nfs_fh *fhandle, struct nfs_fattr *fattr, struct nfs4_label *label); | 83 | static int _nfs4_proc_getattr(struct nfs_server *server, struct nfs_fh *fhandle, struct nfs_fattr *fattr, struct nfs4_label *label); |
@@ -239,6 +238,7 @@ const u32 nfs4_fsinfo_bitmap[3] = { FATTR4_WORD0_MAXFILESIZE | |||
239 | FATTR4_WORD1_TIME_DELTA | 238 | FATTR4_WORD1_TIME_DELTA |
240 | | FATTR4_WORD1_FS_LAYOUT_TYPES, | 239 | | FATTR4_WORD1_FS_LAYOUT_TYPES, |
241 | FATTR4_WORD2_LAYOUT_BLKSIZE | 240 | FATTR4_WORD2_LAYOUT_BLKSIZE |
241 | | FATTR4_WORD2_CLONE_BLKSIZE | ||
242 | }; | 242 | }; |
243 | 243 | ||
244 | const u32 nfs4_fs_locations_bitmap[3] = { | 244 | const u32 nfs4_fs_locations_bitmap[3] = { |
@@ -344,13 +344,16 @@ static int nfs4_delay(struct rpc_clnt *clnt, long *timeout) | |||
344 | /* This is the error handling routine for processes that are allowed | 344 | /* This is the error handling routine for processes that are allowed |
345 | * to sleep. | 345 | * to sleep. |
346 | */ | 346 | */ |
347 | int nfs4_handle_exception(struct nfs_server *server, int errorcode, struct nfs4_exception *exception) | 347 | static int nfs4_do_handle_exception(struct nfs_server *server, |
348 | int errorcode, struct nfs4_exception *exception) | ||
348 | { | 349 | { |
349 | struct nfs_client *clp = server->nfs_client; | 350 | struct nfs_client *clp = server->nfs_client; |
350 | struct nfs4_state *state = exception->state; | 351 | struct nfs4_state *state = exception->state; |
351 | struct inode *inode = exception->inode; | 352 | struct inode *inode = exception->inode; |
352 | int ret = errorcode; | 353 | int ret = errorcode; |
353 | 354 | ||
355 | exception->delay = 0; | ||
356 | exception->recovering = 0; | ||
354 | exception->retry = 0; | 357 | exception->retry = 0; |
355 | switch(errorcode) { | 358 | switch(errorcode) { |
356 | case 0: | 359 | case 0: |
@@ -359,11 +362,9 @@ int nfs4_handle_exception(struct nfs_server *server, int errorcode, struct nfs4_ | |||
359 | case -NFS4ERR_DELEG_REVOKED: | 362 | case -NFS4ERR_DELEG_REVOKED: |
360 | case -NFS4ERR_ADMIN_REVOKED: | 363 | case -NFS4ERR_ADMIN_REVOKED: |
361 | case -NFS4ERR_BAD_STATEID: | 364 | case -NFS4ERR_BAD_STATEID: |
362 | if (inode && nfs4_have_delegation(inode, FMODE_READ)) { | 365 | if (inode && nfs_async_inode_return_delegation(inode, |
363 | nfs4_inode_return_delegation(inode); | 366 | NULL) == 0) |
364 | exception->retry = 1; | 367 | goto wait_on_recovery; |
365 | return 0; | ||
366 | } | ||
367 | if (state == NULL) | 368 | if (state == NULL) |
368 | break; | 369 | break; |
369 | ret = nfs4_schedule_stateid_recovery(server, state); | 370 | ret = nfs4_schedule_stateid_recovery(server, state); |
@@ -409,11 +410,12 @@ int nfs4_handle_exception(struct nfs_server *server, int errorcode, struct nfs4_ | |||
409 | ret = -EBUSY; | 410 | ret = -EBUSY; |
410 | break; | 411 | break; |
411 | } | 412 | } |
412 | case -NFS4ERR_GRACE: | ||
413 | case -NFS4ERR_DELAY: | 413 | case -NFS4ERR_DELAY: |
414 | ret = nfs4_delay(server->client, &exception->timeout); | 414 | nfs_inc_server_stats(server, NFSIOS_DELAY); |
415 | if (ret != 0) | 415 | case -NFS4ERR_GRACE: |
416 | break; | 416 | exception->delay = 1; |
417 | return 0; | ||
418 | |||
417 | case -NFS4ERR_RETRY_UNCACHED_REP: | 419 | case -NFS4ERR_RETRY_UNCACHED_REP: |
418 | case -NFS4ERR_OLD_STATEID: | 420 | case -NFS4ERR_OLD_STATEID: |
419 | exception->retry = 1; | 421 | exception->retry = 1; |
@@ -434,14 +436,85 @@ int nfs4_handle_exception(struct nfs_server *server, int errorcode, struct nfs4_ | |||
434 | /* We failed to handle the error */ | 436 | /* We failed to handle the error */ |
435 | return nfs4_map_errors(ret); | 437 | return nfs4_map_errors(ret); |
436 | wait_on_recovery: | 438 | wait_on_recovery: |
437 | ret = nfs4_wait_clnt_recover(clp); | 439 | exception->recovering = 1; |
440 | return 0; | ||
441 | } | ||
442 | |||
443 | /* This is the error handling routine for processes that are allowed | ||
444 | * to sleep. | ||
445 | */ | ||
446 | int nfs4_handle_exception(struct nfs_server *server, int errorcode, struct nfs4_exception *exception) | ||
447 | { | ||
448 | struct nfs_client *clp = server->nfs_client; | ||
449 | int ret; | ||
450 | |||
451 | ret = nfs4_do_handle_exception(server, errorcode, exception); | ||
452 | if (exception->delay) { | ||
453 | ret = nfs4_delay(server->client, &exception->timeout); | ||
454 | goto out_retry; | ||
455 | } | ||
456 | if (exception->recovering) { | ||
457 | ret = nfs4_wait_clnt_recover(clp); | ||
458 | if (test_bit(NFS_MIG_FAILED, &server->mig_status)) | ||
459 | return -EIO; | ||
460 | goto out_retry; | ||
461 | } | ||
462 | return ret; | ||
463 | out_retry: | ||
464 | if (ret == 0) | ||
465 | exception->retry = 1; | ||
466 | return ret; | ||
467 | } | ||
468 | |||
469 | static int | ||
470 | nfs4_async_handle_exception(struct rpc_task *task, struct nfs_server *server, | ||
471 | int errorcode, struct nfs4_exception *exception) | ||
472 | { | ||
473 | struct nfs_client *clp = server->nfs_client; | ||
474 | int ret; | ||
475 | |||
476 | ret = nfs4_do_handle_exception(server, errorcode, exception); | ||
477 | if (exception->delay) { | ||
478 | rpc_delay(task, nfs4_update_delay(&exception->timeout)); | ||
479 | goto out_retry; | ||
480 | } | ||
481 | if (exception->recovering) { | ||
482 | rpc_sleep_on(&clp->cl_rpcwaitq, task, NULL); | ||
483 | if (test_bit(NFS4CLNT_MANAGER_RUNNING, &clp->cl_state) == 0) | ||
484 | rpc_wake_up_queued_task(&clp->cl_rpcwaitq, task); | ||
485 | goto out_retry; | ||
486 | } | ||
438 | if (test_bit(NFS_MIG_FAILED, &server->mig_status)) | 487 | if (test_bit(NFS_MIG_FAILED, &server->mig_status)) |
439 | return -EIO; | 488 | ret = -EIO; |
489 | return ret; | ||
490 | out_retry: | ||
440 | if (ret == 0) | 491 | if (ret == 0) |
441 | exception->retry = 1; | 492 | exception->retry = 1; |
442 | return ret; | 493 | return ret; |
443 | } | 494 | } |
444 | 495 | ||
496 | static int | ||
497 | nfs4_async_handle_error(struct rpc_task *task, struct nfs_server *server, | ||
498 | struct nfs4_state *state, long *timeout) | ||
499 | { | ||
500 | struct nfs4_exception exception = { | ||
501 | .state = state, | ||
502 | }; | ||
503 | |||
504 | if (task->tk_status >= 0) | ||
505 | return 0; | ||
506 | if (timeout) | ||
507 | exception.timeout = *timeout; | ||
508 | task->tk_status = nfs4_async_handle_exception(task, server, | ||
509 | task->tk_status, | ||
510 | &exception); | ||
511 | if (exception.delay && timeout) | ||
512 | *timeout = exception.timeout; | ||
513 | if (exception.retry) | ||
514 | return -EAGAIN; | ||
515 | return 0; | ||
516 | } | ||
517 | |||
445 | /* | 518 | /* |
446 | * Return 'true' if 'clp' is using an rpc_client that is integrity protected | 519 | * Return 'true' if 'clp' is using an rpc_client that is integrity protected |
447 | * or 'false' otherwise. | 520 | * or 'false' otherwise. |
@@ -4530,7 +4603,7 @@ static inline int nfs4_server_supports_acls(struct nfs_server *server) | |||
4530 | #define NFS4ACL_MAXPAGES DIV_ROUND_UP(XATTR_SIZE_MAX, PAGE_SIZE) | 4603 | #define NFS4ACL_MAXPAGES DIV_ROUND_UP(XATTR_SIZE_MAX, PAGE_SIZE) |
4531 | 4604 | ||
4532 | static int buf_to_pages_noslab(const void *buf, size_t buflen, | 4605 | static int buf_to_pages_noslab(const void *buf, size_t buflen, |
4533 | struct page **pages, unsigned int *pgbase) | 4606 | struct page **pages) |
4534 | { | 4607 | { |
4535 | struct page *newpage, **spages; | 4608 | struct page *newpage, **spages; |
4536 | int rc = 0; | 4609 | int rc = 0; |
@@ -4674,7 +4747,6 @@ static ssize_t __nfs4_get_acl_uncached(struct inode *inode, void *buf, size_t bu | |||
4674 | goto out_free; | 4747 | goto out_free; |
4675 | 4748 | ||
4676 | args.acl_len = npages * PAGE_SIZE; | 4749 | args.acl_len = npages * PAGE_SIZE; |
4677 | args.acl_pgbase = 0; | ||
4678 | 4750 | ||
4679 | dprintk("%s buf %p buflen %zu npages %d args.acl_len %zu\n", | 4751 | dprintk("%s buf %p buflen %zu npages %d args.acl_len %zu\n", |
4680 | __func__, buf, buflen, npages, args.acl_len); | 4752 | __func__, buf, buflen, npages, args.acl_len); |
@@ -4766,7 +4838,7 @@ static int __nfs4_proc_set_acl(struct inode *inode, const void *buf, size_t bufl | |||
4766 | return -EOPNOTSUPP; | 4838 | return -EOPNOTSUPP; |
4767 | if (npages > ARRAY_SIZE(pages)) | 4839 | if (npages > ARRAY_SIZE(pages)) |
4768 | return -ERANGE; | 4840 | return -ERANGE; |
4769 | i = buf_to_pages_noslab(buf, buflen, arg.acl_pages, &arg.acl_pgbase); | 4841 | i = buf_to_pages_noslab(buf, buflen, arg.acl_pages); |
4770 | if (i < 0) | 4842 | if (i < 0) |
4771 | return i; | 4843 | return i; |
4772 | nfs4_inode_return_delegation(inode); | 4844 | nfs4_inode_return_delegation(inode); |
@@ -4955,79 +5027,6 @@ out: | |||
4955 | #endif /* CONFIG_NFS_V4_SECURITY_LABEL */ | 5027 | #endif /* CONFIG_NFS_V4_SECURITY_LABEL */ |
4956 | 5028 | ||
4957 | 5029 | ||
4958 | static int | ||
4959 | nfs4_async_handle_error(struct rpc_task *task, const struct nfs_server *server, | ||
4960 | struct nfs4_state *state, long *timeout) | ||
4961 | { | ||
4962 | struct nfs_client *clp = server->nfs_client; | ||
4963 | |||
4964 | if (task->tk_status >= 0) | ||
4965 | return 0; | ||
4966 | switch(task->tk_status) { | ||
4967 | case -NFS4ERR_DELEG_REVOKED: | ||
4968 | case -NFS4ERR_ADMIN_REVOKED: | ||
4969 | case -NFS4ERR_BAD_STATEID: | ||
4970 | case -NFS4ERR_OPENMODE: | ||
4971 | if (state == NULL) | ||
4972 | break; | ||
4973 | if (nfs4_schedule_stateid_recovery(server, state) < 0) | ||
4974 | goto recovery_failed; | ||
4975 | goto wait_on_recovery; | ||
4976 | case -NFS4ERR_EXPIRED: | ||
4977 | if (state != NULL) { | ||
4978 | if (nfs4_schedule_stateid_recovery(server, state) < 0) | ||
4979 | goto recovery_failed; | ||
4980 | } | ||
4981 | case -NFS4ERR_STALE_STATEID: | ||
4982 | case -NFS4ERR_STALE_CLIENTID: | ||
4983 | nfs4_schedule_lease_recovery(clp); | ||
4984 | goto wait_on_recovery; | ||
4985 | case -NFS4ERR_MOVED: | ||
4986 | if (nfs4_schedule_migration_recovery(server) < 0) | ||
4987 | goto recovery_failed; | ||
4988 | goto wait_on_recovery; | ||
4989 | case -NFS4ERR_LEASE_MOVED: | ||
4990 | nfs4_schedule_lease_moved_recovery(clp); | ||
4991 | goto wait_on_recovery; | ||
4992 | #if defined(CONFIG_NFS_V4_1) | ||
4993 | case -NFS4ERR_BADSESSION: | ||
4994 | case -NFS4ERR_BADSLOT: | ||
4995 | case -NFS4ERR_BAD_HIGH_SLOT: | ||
4996 | case -NFS4ERR_DEADSESSION: | ||
4997 | case -NFS4ERR_CONN_NOT_BOUND_TO_SESSION: | ||
4998 | case -NFS4ERR_SEQ_FALSE_RETRY: | ||
4999 | case -NFS4ERR_SEQ_MISORDERED: | ||
5000 | dprintk("%s ERROR %d, Reset session\n", __func__, | ||
5001 | task->tk_status); | ||
5002 | nfs4_schedule_session_recovery(clp->cl_session, task->tk_status); | ||
5003 | goto wait_on_recovery; | ||
5004 | #endif /* CONFIG_NFS_V4_1 */ | ||
5005 | case -NFS4ERR_DELAY: | ||
5006 | nfs_inc_server_stats(server, NFSIOS_DELAY); | ||
5007 | rpc_delay(task, nfs4_update_delay(timeout)); | ||
5008 | goto restart_call; | ||
5009 | case -NFS4ERR_GRACE: | ||
5010 | rpc_delay(task, NFS4_POLL_RETRY_MAX); | ||
5011 | case -NFS4ERR_RETRY_UNCACHED_REP: | ||
5012 | case -NFS4ERR_OLD_STATEID: | ||
5013 | goto restart_call; | ||
5014 | } | ||
5015 | task->tk_status = nfs4_map_errors(task->tk_status); | ||
5016 | return 0; | ||
5017 | recovery_failed: | ||
5018 | task->tk_status = -EIO; | ||
5019 | return 0; | ||
5020 | wait_on_recovery: | ||
5021 | rpc_sleep_on(&clp->cl_rpcwaitq, task, NULL); | ||
5022 | if (test_bit(NFS4CLNT_MANAGER_RUNNING, &clp->cl_state) == 0) | ||
5023 | rpc_wake_up_queued_task(&clp->cl_rpcwaitq, task); | ||
5024 | if (test_bit(NFS_MIG_FAILED, &server->mig_status)) | ||
5025 | goto recovery_failed; | ||
5026 | restart_call: | ||
5027 | task->tk_status = 0; | ||
5028 | return -EAGAIN; | ||
5029 | } | ||
5030 | |||
5031 | static void nfs4_init_boot_verifier(const struct nfs_client *clp, | 5030 | static void nfs4_init_boot_verifier(const struct nfs_client *clp, |
5032 | nfs4_verifier *bootverf) | 5031 | nfs4_verifier *bootverf) |
5033 | { | 5032 | { |
@@ -5522,7 +5521,7 @@ struct nfs4_unlockdata { | |||
5522 | struct nfs4_lock_state *lsp; | 5521 | struct nfs4_lock_state *lsp; |
5523 | struct nfs_open_context *ctx; | 5522 | struct nfs_open_context *ctx; |
5524 | struct file_lock fl; | 5523 | struct file_lock fl; |
5525 | const struct nfs_server *server; | 5524 | struct nfs_server *server; |
5526 | unsigned long timestamp; | 5525 | unsigned long timestamp; |
5527 | }; | 5526 | }; |
5528 | 5527 | ||
@@ -8718,7 +8717,8 @@ static const struct nfs4_minor_version_ops nfs_v4_2_minor_ops = { | |||
8718 | | NFS_CAP_ALLOCATE | 8717 | | NFS_CAP_ALLOCATE |
8719 | | NFS_CAP_DEALLOCATE | 8718 | | NFS_CAP_DEALLOCATE |
8720 | | NFS_CAP_SEEK | 8719 | | NFS_CAP_SEEK |
8721 | | NFS_CAP_LAYOUTSTATS, | 8720 | | NFS_CAP_LAYOUTSTATS |
8721 | | NFS_CAP_CLONE, | ||
8722 | .init_client = nfs41_init_client, | 8722 | .init_client = nfs41_init_client, |
8723 | .shutdown_client = nfs41_shutdown_client, | 8723 | .shutdown_client = nfs41_shutdown_client, |
8724 | .match_stateid = nfs41_match_stateid, | 8724 | .match_stateid = nfs41_match_stateid, |