aboutsummaryrefslogtreecommitdiffstats
path: root/fs/nfs/nfs4proc.c
diff options
context:
space:
mode:
Diffstat (limited to 'fs/nfs/nfs4proc.c')
-rw-r--r--fs/nfs/nfs4proc.c103
1 files changed, 68 insertions, 35 deletions
diff --git a/fs/nfs/nfs4proc.c b/fs/nfs/nfs4proc.c
index b4916b092194..153898e1331f 100644
--- a/fs/nfs/nfs4proc.c
+++ b/fs/nfs/nfs4proc.c
@@ -2668,7 +2668,7 @@ out:
2668 nfs4_set_cached_acl(inode, acl); 2668 nfs4_set_cached_acl(inode, acl);
2669} 2669}
2670 2670
2671static inline ssize_t nfs4_get_acl_uncached(struct inode *inode, void *buf, size_t buflen) 2671static ssize_t __nfs4_get_acl_uncached(struct inode *inode, void *buf, size_t buflen)
2672{ 2672{
2673 struct page *pages[NFS4ACL_MAXPAGES]; 2673 struct page *pages[NFS4ACL_MAXPAGES];
2674 struct nfs_getaclargs args = { 2674 struct nfs_getaclargs args = {
@@ -2721,6 +2721,19 @@ out_free:
2721 return ret; 2721 return ret;
2722} 2722}
2723 2723
2724static ssize_t nfs4_get_acl_uncached(struct inode *inode, void *buf, size_t buflen)
2725{
2726 struct nfs4_exception exception = { };
2727 ssize_t ret;
2728 do {
2729 ret = __nfs4_get_acl_uncached(inode, buf, buflen);
2730 if (ret >= 0)
2731 break;
2732 ret = nfs4_handle_exception(NFS_SERVER(inode), ret, &exception);
2733 } while (exception.retry);
2734 return ret;
2735}
2736
2724static ssize_t nfs4_proc_get_acl(struct inode *inode, void *buf, size_t buflen) 2737static ssize_t nfs4_proc_get_acl(struct inode *inode, void *buf, size_t buflen)
2725{ 2738{
2726 struct nfs_server *server = NFS_SERVER(inode); 2739 struct nfs_server *server = NFS_SERVER(inode);
@@ -2737,7 +2750,7 @@ static ssize_t nfs4_proc_get_acl(struct inode *inode, void *buf, size_t buflen)
2737 return nfs4_get_acl_uncached(inode, buf, buflen); 2750 return nfs4_get_acl_uncached(inode, buf, buflen);
2738} 2751}
2739 2752
2740static int nfs4_proc_set_acl(struct inode *inode, const void *buf, size_t buflen) 2753static int __nfs4_proc_set_acl(struct inode *inode, const void *buf, size_t buflen)
2741{ 2754{
2742 struct nfs_server *server = NFS_SERVER(inode); 2755 struct nfs_server *server = NFS_SERVER(inode);
2743 struct page *pages[NFS4ACL_MAXPAGES]; 2756 struct page *pages[NFS4ACL_MAXPAGES];
@@ -2763,6 +2776,18 @@ static int nfs4_proc_set_acl(struct inode *inode, const void *buf, size_t buflen
2763 return ret; 2776 return ret;
2764} 2777}
2765 2778
2779static int nfs4_proc_set_acl(struct inode *inode, const void *buf, size_t buflen)
2780{
2781 struct nfs4_exception exception = { };
2782 int err;
2783 do {
2784 err = nfs4_handle_exception(NFS_SERVER(inode),
2785 __nfs4_proc_set_acl(inode, buf, buflen),
2786 &exception);
2787 } while (exception.retry);
2788 return err;
2789}
2790
2766static int 2791static int
2767nfs4_async_handle_error(struct rpc_task *task, const struct nfs_server *server) 2792nfs4_async_handle_error(struct rpc_task *task, const struct nfs_server *server)
2768{ 2793{
@@ -3144,9 +3169,6 @@ static int do_vfs_lock(struct file *file, struct file_lock *fl)
3144 default: 3169 default:
3145 BUG(); 3170 BUG();
3146 } 3171 }
3147 if (res < 0)
3148 printk(KERN_WARNING "%s: VFS is out of sync with lock manager!\n",
3149 __FUNCTION__);
3150 return res; 3172 return res;
3151} 3173}
3152 3174
@@ -3258,8 +3280,6 @@ static struct rpc_task *nfs4_do_unlck(struct file_lock *fl,
3258 return ERR_PTR(-ENOMEM); 3280 return ERR_PTR(-ENOMEM);
3259 } 3281 }
3260 3282
3261 /* Unlock _before_ we do the RPC call */
3262 do_vfs_lock(fl->fl_file, fl);
3263 return rpc_run_task(NFS_CLIENT(lsp->ls_state->inode), RPC_TASK_ASYNC, &nfs4_locku_ops, data); 3283 return rpc_run_task(NFS_CLIENT(lsp->ls_state->inode), RPC_TASK_ASYNC, &nfs4_locku_ops, data);
3264} 3284}
3265 3285
@@ -3270,30 +3290,28 @@ static int nfs4_proc_unlck(struct nfs4_state *state, int cmd, struct file_lock *
3270 struct rpc_task *task; 3290 struct rpc_task *task;
3271 int status = 0; 3291 int status = 0;
3272 3292
3273 /* Is this a delegated lock? */
3274 if (test_bit(NFS_DELEGATED_STATE, &state->flags))
3275 goto out_unlock;
3276 /* Is this open_owner holding any locks on the server? */
3277 if (test_bit(LK_STATE_IN_USE, &state->flags) == 0)
3278 goto out_unlock;
3279
3280 status = nfs4_set_lock_state(state, request); 3293 status = nfs4_set_lock_state(state, request);
3294 /* Unlock _before_ we do the RPC call */
3295 request->fl_flags |= FL_EXISTS;
3296 if (do_vfs_lock(request->fl_file, request) == -ENOENT)
3297 goto out;
3281 if (status != 0) 3298 if (status != 0)
3282 goto out_unlock; 3299 goto out;
3300 /* Is this a delegated lock? */
3301 if (test_bit(NFS_DELEGATED_STATE, &state->flags))
3302 goto out;
3283 lsp = request->fl_u.nfs4_fl.owner; 3303 lsp = request->fl_u.nfs4_fl.owner;
3284 status = -ENOMEM;
3285 seqid = nfs_alloc_seqid(&lsp->ls_seqid); 3304 seqid = nfs_alloc_seqid(&lsp->ls_seqid);
3305 status = -ENOMEM;
3286 if (seqid == NULL) 3306 if (seqid == NULL)
3287 goto out_unlock; 3307 goto out;
3288 task = nfs4_do_unlck(request, request->fl_file->private_data, lsp, seqid); 3308 task = nfs4_do_unlck(request, request->fl_file->private_data, lsp, seqid);
3289 status = PTR_ERR(task); 3309 status = PTR_ERR(task);
3290 if (IS_ERR(task)) 3310 if (IS_ERR(task))
3291 goto out_unlock; 3311 goto out;
3292 status = nfs4_wait_for_completion_rpc_task(task); 3312 status = nfs4_wait_for_completion_rpc_task(task);
3293 rpc_release_task(task); 3313 rpc_release_task(task);
3294 return status; 3314out:
3295out_unlock:
3296 do_vfs_lock(request->fl_file, request);
3297 return status; 3315 return status;
3298} 3316}
3299 3317
@@ -3461,10 +3479,10 @@ static int nfs4_lock_reclaim(struct nfs4_state *state, struct file_lock *request
3461 struct nfs4_exception exception = { }; 3479 struct nfs4_exception exception = { };
3462 int err; 3480 int err;
3463 3481
3464 /* Cache the lock if possible... */
3465 if (test_bit(NFS_DELEGATED_STATE, &state->flags))
3466 return 0;
3467 do { 3482 do {
3483 /* Cache the lock if possible... */
3484 if (test_bit(NFS_DELEGATED_STATE, &state->flags) != 0)
3485 return 0;
3468 err = _nfs4_do_setlk(state, F_SETLK, request, 1); 3486 err = _nfs4_do_setlk(state, F_SETLK, request, 1);
3469 if (err != -NFS4ERR_DELAY) 3487 if (err != -NFS4ERR_DELAY)
3470 break; 3488 break;
@@ -3483,6 +3501,8 @@ static int nfs4_lock_expired(struct nfs4_state *state, struct file_lock *request
3483 if (err != 0) 3501 if (err != 0)
3484 return err; 3502 return err;
3485 do { 3503 do {
3504 if (test_bit(NFS_DELEGATED_STATE, &state->flags) != 0)
3505 return 0;
3486 err = _nfs4_do_setlk(state, F_SETLK, request, 0); 3506 err = _nfs4_do_setlk(state, F_SETLK, request, 0);
3487 if (err != -NFS4ERR_DELAY) 3507 if (err != -NFS4ERR_DELAY)
3488 break; 3508 break;
@@ -3494,29 +3514,42 @@ static int nfs4_lock_expired(struct nfs4_state *state, struct file_lock *request
3494static int _nfs4_proc_setlk(struct nfs4_state *state, int cmd, struct file_lock *request) 3514static int _nfs4_proc_setlk(struct nfs4_state *state, int cmd, struct file_lock *request)
3495{ 3515{
3496 struct nfs4_client *clp = state->owner->so_client; 3516 struct nfs4_client *clp = state->owner->so_client;
3517 unsigned char fl_flags = request->fl_flags;
3497 int status; 3518 int status;
3498 3519
3499 /* Is this a delegated open? */ 3520 /* Is this a delegated open? */
3500 if (NFS_I(state->inode)->delegation_state != 0) {
3501 /* Yes: cache locks! */
3502 status = do_vfs_lock(request->fl_file, request);
3503 /* ...but avoid races with delegation recall... */
3504 if (status < 0 || test_bit(NFS_DELEGATED_STATE, &state->flags))
3505 return status;
3506 }
3507 down_read(&clp->cl_sem);
3508 status = nfs4_set_lock_state(state, request); 3521 status = nfs4_set_lock_state(state, request);
3509 if (status != 0) 3522 if (status != 0)
3510 goto out; 3523 goto out;
3524 request->fl_flags |= FL_ACCESS;
3525 status = do_vfs_lock(request->fl_file, request);
3526 if (status < 0)
3527 goto out;
3528 down_read(&clp->cl_sem);
3529 if (test_bit(NFS_DELEGATED_STATE, &state->flags)) {
3530 struct nfs_inode *nfsi = NFS_I(state->inode);
3531 /* Yes: cache locks! */
3532 down_read(&nfsi->rwsem);
3533 /* ...but avoid races with delegation recall... */
3534 if (test_bit(NFS_DELEGATED_STATE, &state->flags)) {
3535 request->fl_flags = fl_flags & ~FL_SLEEP;
3536 status = do_vfs_lock(request->fl_file, request);
3537 up_read(&nfsi->rwsem);
3538 goto out_unlock;
3539 }
3540 up_read(&nfsi->rwsem);
3541 }
3511 status = _nfs4_do_setlk(state, cmd, request, 0); 3542 status = _nfs4_do_setlk(state, cmd, request, 0);
3512 if (status != 0) 3543 if (status != 0)
3513 goto out; 3544 goto out_unlock;
3514 /* Note: we always want to sleep here! */ 3545 /* Note: we always want to sleep here! */
3515 request->fl_flags |= FL_SLEEP; 3546 request->fl_flags = fl_flags | FL_SLEEP;
3516 if (do_vfs_lock(request->fl_file, request) < 0) 3547 if (do_vfs_lock(request->fl_file, request) < 0)
3517 printk(KERN_WARNING "%s: VFS is out of sync with lock manager!\n", __FUNCTION__); 3548 printk(KERN_WARNING "%s: VFS is out of sync with lock manager!\n", __FUNCTION__);
3518out: 3549out_unlock:
3519 up_read(&clp->cl_sem); 3550 up_read(&clp->cl_sem);
3551out:
3552 request->fl_flags = fl_flags;
3520 return status; 3553 return status;
3521} 3554}
3522 3555