aboutsummaryrefslogtreecommitdiffstats
path: root/fs/nfs
diff options
context:
space:
mode:
authorTrond Myklebust <Trond.Myklebust@netapp.com>2009-06-17 16:22:59 -0400
committerTrond Myklebust <Trond.Myklebust@netapp.com>2009-06-17 16:22:59 -0400
commit965b5d679146c9f69bc0325388bb9ed357863c4f (patch)
treed70fe13004404f1d3a203c8b9b90aa5f61150115 /fs/nfs
parentd5122201a7f90b2aa73092f158b84d1d74f1134d (diff)
NFSv4: Handle more errors when recovering open file and locking state
It is possible for servers to return NFS4ERR_BAD_STATEID when the state management code is recovering locks or is reclaiming state when returning a delegation. Ensure that we handle that case. While we're at it, add in handlers for NFS4ERR_STALE, NFS4ERR_ADMIN_REVOKED, NFS4ERR_OPENMODE, NFS4ERR_DENIED and NFS4ERR_STALE_STATEID, since the protocol appears to allow for them too. Also handle ENOMEM... Finally, rather than add new NFSv4.0-specific errors and error handling into the generic delegation code, move that open file and locking state error handling into the NFSv4 layer. Signed-off-by: Trond Myklebust <Trond.Myklebust@netapp.com>
Diffstat (limited to 'fs/nfs')
-rw-r--r--fs/nfs/nfs4proc.c44
-rw-r--r--fs/nfs/nfs4state.c28
2 files changed, 56 insertions, 16 deletions
diff --git a/fs/nfs/nfs4proc.c b/fs/nfs/nfs4proc.c
index d326193c9785..55314e721632 100644
--- a/fs/nfs/nfs4proc.c
+++ b/fs/nfs/nfs4proc.c
@@ -804,16 +804,30 @@ int nfs4_open_delegation_recall(struct nfs_open_context *ctx, struct nfs4_state
804 err = _nfs4_open_delegation_recall(ctx, state, stateid); 804 err = _nfs4_open_delegation_recall(ctx, state, stateid);
805 switch (err) { 805 switch (err) {
806 case 0: 806 case 0:
807 return err; 807 case -ENOENT:
808 case -ESTALE:
809 goto out;
808 case -NFS4ERR_STALE_CLIENTID: 810 case -NFS4ERR_STALE_CLIENTID:
809 case -NFS4ERR_STALE_STATEID: 811 case -NFS4ERR_STALE_STATEID:
810 case -NFS4ERR_EXPIRED: 812 case -NFS4ERR_EXPIRED:
811 /* Don't recall a delegation if it was lost */ 813 /* Don't recall a delegation if it was lost */
812 nfs4_schedule_state_recovery(server->nfs_client); 814 nfs4_schedule_state_recovery(server->nfs_client);
813 return err; 815 goto out;
816 case -ERESTARTSYS:
817 /*
818 * The show must go on: exit, but mark the
819 * stateid as needing recovery.
820 */
821 case -NFS4ERR_ADMIN_REVOKED:
822 case -NFS4ERR_BAD_STATEID:
823 nfs4_state_mark_reclaim_nograce(server->nfs_client, state);
824 case -ENOMEM:
825 err = 0;
826 goto out;
814 } 827 }
815 err = nfs4_handle_exception(server, err, &exception); 828 err = nfs4_handle_exception(server, err, &exception);
816 } while (exception.retry); 829 } while (exception.retry);
830out:
817 return err; 831 return err;
818} 832}
819 833
@@ -3487,8 +3501,6 @@ static int _nfs4_do_setlk(struct nfs4_state *state, int cmd, struct file_lock *f
3487 ret = nfs4_wait_for_completion_rpc_task(task); 3501 ret = nfs4_wait_for_completion_rpc_task(task);
3488 if (ret == 0) { 3502 if (ret == 0) {
3489 ret = data->rpc_status; 3503 ret = data->rpc_status;
3490 if (ret == -NFS4ERR_DENIED)
3491 ret = -EAGAIN;
3492 } else 3504 } else
3493 data->cancelled = 1; 3505 data->cancelled = 1;
3494 rpc_put_task(task); 3506 rpc_put_task(task);
@@ -3576,9 +3588,11 @@ static int nfs4_proc_setlk(struct nfs4_state *state, int cmd, struct file_lock *
3576 int err; 3588 int err;
3577 3589
3578 do { 3590 do {
3591 err = _nfs4_proc_setlk(state, cmd, request);
3592 if (err == -NFS4ERR_DENIED)
3593 err = -EAGAIN;
3579 err = nfs4_handle_exception(NFS_SERVER(state->inode), 3594 err = nfs4_handle_exception(NFS_SERVER(state->inode),
3580 _nfs4_proc_setlk(state, cmd, request), 3595 err, &exception);
3581 &exception);
3582 } while (exception.retry); 3596 } while (exception.retry);
3583 return err; 3597 return err;
3584} 3598}
@@ -3635,11 +3649,29 @@ int nfs4_lock_delegation_recall(struct nfs4_state *state, struct file_lock *fl)
3635 printk(KERN_ERR "%s: unhandled error %d.\n", 3649 printk(KERN_ERR "%s: unhandled error %d.\n",
3636 __func__, err); 3650 __func__, err);
3637 case 0: 3651 case 0:
3652 case -ESTALE:
3638 goto out; 3653 goto out;
3639 case -NFS4ERR_EXPIRED: 3654 case -NFS4ERR_EXPIRED:
3640 case -NFS4ERR_STALE_CLIENTID: 3655 case -NFS4ERR_STALE_CLIENTID:
3656 case -NFS4ERR_STALE_STATEID:
3641 nfs4_schedule_state_recovery(server->nfs_client); 3657 nfs4_schedule_state_recovery(server->nfs_client);
3642 goto out; 3658 goto out;
3659 case -ERESTARTSYS:
3660 /*
3661 * The show must go on: exit, but mark the
3662 * stateid as needing recovery.
3663 */
3664 case -NFS4ERR_ADMIN_REVOKED:
3665 case -NFS4ERR_BAD_STATEID:
3666 case -NFS4ERR_OPENMODE:
3667 nfs4_state_mark_reclaim_nograce(server->nfs_client, state);
3668 err = 0;
3669 goto out;
3670 case -ENOMEM:
3671 case -NFS4ERR_DENIED:
3672 /* kill_proc(fl->fl_pid, SIGLOST, 1); */
3673 err = 0;
3674 goto out;
3643 case -NFS4ERR_DELAY: 3675 case -NFS4ERR_DELAY:
3644 break; 3676 break;
3645 } 3677 }
diff --git a/fs/nfs/nfs4state.c b/fs/nfs/nfs4state.c
index 0298e909559f..6e094e95cf0f 100644
--- a/fs/nfs/nfs4state.c
+++ b/fs/nfs/nfs4state.c
@@ -854,25 +854,29 @@ static int nfs4_reclaim_locks(struct nfs4_state *state, const struct nfs4_state_
854 if (nfs_file_open_context(fl->fl_file)->state != state) 854 if (nfs_file_open_context(fl->fl_file)->state != state)
855 continue; 855 continue;
856 status = ops->recover_lock(state, fl); 856 status = ops->recover_lock(state, fl);
857 if (status >= 0)
858 continue;
859 switch (status) { 857 switch (status) {
858 case 0:
859 break;
860 case -ESTALE:
861 case -NFS4ERR_ADMIN_REVOKED:
862 case -NFS4ERR_STALE_STATEID:
863 case -NFS4ERR_BAD_STATEID:
864 case -NFS4ERR_EXPIRED:
865 case -NFS4ERR_NO_GRACE:
866 case -NFS4ERR_STALE_CLIENTID:
867 goto out;
860 default: 868 default:
861 printk(KERN_ERR "%s: unhandled error %d. Zeroing state\n", 869 printk(KERN_ERR "%s: unhandled error %d. Zeroing state\n",
862 __func__, status); 870 __func__, status);
863 case -NFS4ERR_EXPIRED: 871 case -ENOMEM:
864 case -NFS4ERR_NO_GRACE: 872 case -NFS4ERR_DENIED:
865 case -NFS4ERR_RECLAIM_BAD: 873 case -NFS4ERR_RECLAIM_BAD:
866 case -NFS4ERR_RECLAIM_CONFLICT: 874 case -NFS4ERR_RECLAIM_CONFLICT:
867 /* kill_proc(fl->fl_pid, SIGLOST, 1); */ 875 /* kill_proc(fl->fl_pid, SIGLOST, 1); */
868 break; 876 status = 0;
869 case -NFS4ERR_STALE_CLIENTID:
870 goto out_err;
871 } 877 }
872 } 878 }
873 up_write(&nfsi->rwsem); 879out:
874 return 0;
875out_err:
876 up_write(&nfsi->rwsem); 880 up_write(&nfsi->rwsem);
877 return status; 881 return status;
878} 882}
@@ -918,6 +922,7 @@ restart:
918 printk(KERN_ERR "%s: unhandled error %d. Zeroing state\n", 922 printk(KERN_ERR "%s: unhandled error %d. Zeroing state\n",
919 __func__, status); 923 __func__, status);
920 case -ENOENT: 924 case -ENOENT:
925 case -ENOMEM:
921 case -ESTALE: 926 case -ESTALE:
922 /* 927 /*
923 * Open state on this file cannot be recovered 928 * Open state on this file cannot be recovered
@@ -928,6 +933,9 @@ restart:
928 /* Mark the file as being 'closed' */ 933 /* Mark the file as being 'closed' */
929 state->state = 0; 934 state->state = 0;
930 break; 935 break;
936 case -NFS4ERR_ADMIN_REVOKED:
937 case -NFS4ERR_STALE_STATEID:
938 case -NFS4ERR_BAD_STATEID:
931 case -NFS4ERR_RECLAIM_BAD: 939 case -NFS4ERR_RECLAIM_BAD:
932 case -NFS4ERR_RECLAIM_CONFLICT: 940 case -NFS4ERR_RECLAIM_CONFLICT:
933 nfs4_state_mark_reclaim_nograce(sp->so_client, state); 941 nfs4_state_mark_reclaim_nograce(sp->so_client, state);