diff options
Diffstat (limited to 'fs')
-rw-r--r-- | fs/nfs/nfs4proc.c | 36 |
1 files changed, 28 insertions, 8 deletions
diff --git a/fs/nfs/nfs4proc.c b/fs/nfs/nfs4proc.c index e6a9322a321f..21482b2518f6 100644 --- a/fs/nfs/nfs4proc.c +++ b/fs/nfs/nfs4proc.c | |||
@@ -2918,6 +2918,10 @@ static int nfs4_proc_unlck(struct nfs4_state *state, int cmd, struct file_lock * | |||
2918 | struct nfs4_lock_state *lsp; | 2918 | struct nfs4_lock_state *lsp; |
2919 | int status; | 2919 | int status; |
2920 | 2920 | ||
2921 | /* Is this a delegated lock? */ | ||
2922 | if (test_bit(NFS_DELEGATED_STATE, &state->flags)) | ||
2923 | return do_vfs_lock(request->fl_file, request); | ||
2924 | |||
2921 | status = nfs4_set_lock_state(state, request); | 2925 | status = nfs4_set_lock_state(state, request); |
2922 | if (status != 0) | 2926 | if (status != 0) |
2923 | return status; | 2927 | return status; |
@@ -3032,6 +3036,9 @@ static int nfs4_lock_reclaim(struct nfs4_state *state, struct file_lock *request | |||
3032 | struct nfs4_exception exception = { }; | 3036 | struct nfs4_exception exception = { }; |
3033 | int err; | 3037 | int err; |
3034 | 3038 | ||
3039 | /* Cache the lock if possible... */ | ||
3040 | if (test_bit(NFS_DELEGATED_STATE, &state->flags)) | ||
3041 | return 0; | ||
3035 | do { | 3042 | do { |
3036 | err = _nfs4_do_setlk(state, F_SETLK, request, 1); | 3043 | err = _nfs4_do_setlk(state, F_SETLK, request, 1); |
3037 | if (err != -NFS4ERR_DELAY) | 3044 | if (err != -NFS4ERR_DELAY) |
@@ -3047,6 +3054,9 @@ static int nfs4_lock_expired(struct nfs4_state *state, struct file_lock *request | |||
3047 | struct nfs4_exception exception = { }; | 3054 | struct nfs4_exception exception = { }; |
3048 | int err; | 3055 | int err; |
3049 | 3056 | ||
3057 | err = nfs4_set_lock_state(state, request); | ||
3058 | if (err != 0) | ||
3059 | return err; | ||
3050 | do { | 3060 | do { |
3051 | err = _nfs4_do_setlk(state, F_SETLK, request, 0); | 3061 | err = _nfs4_do_setlk(state, F_SETLK, request, 0); |
3052 | if (err != -NFS4ERR_DELAY) | 3062 | if (err != -NFS4ERR_DELAY) |
@@ -3062,15 +3072,25 @@ static int _nfs4_proc_setlk(struct nfs4_state *state, int cmd, struct file_lock | |||
3062 | int status; | 3072 | int status; |
3063 | 3073 | ||
3064 | down_read(&clp->cl_sem); | 3074 | down_read(&clp->cl_sem); |
3065 | status = nfs4_set_lock_state(state, request); | 3075 | /* Is this a delegated open? */ |
3066 | if (status == 0) | 3076 | if (test_bit(NFS_DELEGATED_STATE, &state->flags)) { |
3067 | status = _nfs4_do_setlk(state, cmd, request, 0); | 3077 | /* Yes: cache locks! */ |
3068 | if (status == 0) { | 3078 | status = do_vfs_lock(request->fl_file, request); |
3069 | /* Note: we always want to sleep here! */ | 3079 | /* ...but avoid races with delegation recall... */ |
3070 | request->fl_flags |= FL_SLEEP; | 3080 | if (status < 0 || test_bit(NFS_DELEGATED_STATE, &state->flags)) |
3071 | if (do_vfs_lock(request->fl_file, request) < 0) | 3081 | goto out; |
3072 | printk(KERN_WARNING "%s: VFS is out of sync with lock manager!\n", __FUNCTION__); | ||
3073 | } | 3082 | } |
3083 | status = nfs4_set_lock_state(state, request); | ||
3084 | if (status != 0) | ||
3085 | goto out; | ||
3086 | status = _nfs4_do_setlk(state, cmd, request, 0); | ||
3087 | if (status != 0) | ||
3088 | goto out; | ||
3089 | /* Note: we always want to sleep here! */ | ||
3090 | request->fl_flags |= FL_SLEEP; | ||
3091 | if (do_vfs_lock(request->fl_file, request) < 0) | ||
3092 | printk(KERN_WARNING "%s: VFS is out of sync with lock manager!\n", __FUNCTION__); | ||
3093 | out: | ||
3074 | up_read(&clp->cl_sem); | 3094 | up_read(&clp->cl_sem); |
3075 | return status; | 3095 | return status; |
3076 | } | 3096 | } |