aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorTrond Myklebust <Trond.Myklebust@netapp.com>2005-11-04 15:38:11 -0500
committerTrond Myklebust <Trond.Myklebust@netapp.com>2005-11-04 15:38:11 -0500
commit888e694c167975709f17526dbbed2d98f84e8f85 (patch)
tree11dbbdf2591946f490d4cb28194a80fd3cec4094
parent43b2a33aa868054bd477ab2c1cd20f1ba1af2c3e (diff)
NFSv4: Recover locks too when returning a delegation
Delegations allow us to cache posix and BSD locks, however when the delegation is recalled, we need to "flush the cache" and send the cached LOCK requests to the server. This patch sets up the mechanism for doing so. Signed-off-by: Trond Myklebust <Trond.Myklebust@netapp.com>
-rw-r--r--fs/nfs/delegation.c38
-rw-r--r--fs/nfs/delegation.h1
-rw-r--r--fs/nfs/nfs4proc.c18
3 files changed, 55 insertions, 2 deletions
diff --git a/fs/nfs/delegation.c b/fs/nfs/delegation.c
index 44135af9894c..3976c177a7d0 100644
--- a/fs/nfs/delegation.c
+++ b/fs/nfs/delegation.c
@@ -31,11 +31,42 @@ static void nfs_free_delegation(struct nfs_delegation *delegation)
31 kfree(delegation); 31 kfree(delegation);
32} 32}
33 33
34static int nfs_delegation_claim_locks(struct nfs_open_context *ctx, struct nfs4_state *state)
35{
36 struct inode *inode = state->inode;
37 struct file_lock *fl;
38 int status;
39
40 for (fl = inode->i_flock; fl != 0; fl = fl->fl_next) {
41 if (!(fl->fl_flags & (FL_POSIX|FL_FLOCK)))
42 continue;
43 if ((struct nfs_open_context *)fl->fl_file->private_data != ctx)
44 continue;
45 status = nfs4_lock_delegation_recall(state, fl);
46 if (status >= 0)
47 continue;
48 switch (status) {
49 default:
50 printk(KERN_ERR "%s: unhandled error %d.\n",
51 __FUNCTION__, status);
52 case -NFS4ERR_EXPIRED:
53 /* kill_proc(fl->fl_pid, SIGLOST, 1); */
54 case -NFS4ERR_STALE_CLIENTID:
55 nfs4_schedule_state_recovery(NFS_SERVER(inode)->nfs4_state);
56 goto out_err;
57 }
58 }
59 return 0;
60out_err:
61 return status;
62}
63
34static void nfs_delegation_claim_opens(struct inode *inode) 64static void nfs_delegation_claim_opens(struct inode *inode)
35{ 65{
36 struct nfs_inode *nfsi = NFS_I(inode); 66 struct nfs_inode *nfsi = NFS_I(inode);
37 struct nfs_open_context *ctx; 67 struct nfs_open_context *ctx;
38 struct nfs4_state *state; 68 struct nfs4_state *state;
69 int err;
39 70
40again: 71again:
41 spin_lock(&inode->i_lock); 72 spin_lock(&inode->i_lock);
@@ -47,9 +78,12 @@ again:
47 continue; 78 continue;
48 get_nfs_open_context(ctx); 79 get_nfs_open_context(ctx);
49 spin_unlock(&inode->i_lock); 80 spin_unlock(&inode->i_lock);
50 if (nfs4_open_delegation_recall(ctx->dentry, state) < 0) 81 err = nfs4_open_delegation_recall(ctx->dentry, state);
51 return; 82 if (err >= 0)
83 err = nfs_delegation_claim_locks(ctx, state);
52 put_nfs_open_context(ctx); 84 put_nfs_open_context(ctx);
85 if (err != 0)
86 return;
53 goto again; 87 goto again;
54 } 88 }
55 spin_unlock(&inode->i_lock); 89 spin_unlock(&inode->i_lock);
diff --git a/fs/nfs/delegation.h b/fs/nfs/delegation.h
index 8017846b561f..2fcc30de924b 100644
--- a/fs/nfs/delegation.h
+++ b/fs/nfs/delegation.h
@@ -38,6 +38,7 @@ void nfs_delegation_reap_unclaimed(struct nfs4_client *clp);
38/* NFSv4 delegation-related procedures */ 38/* NFSv4 delegation-related procedures */
39int nfs4_proc_delegreturn(struct inode *inode, struct rpc_cred *cred, const nfs4_stateid *stateid); 39int nfs4_proc_delegreturn(struct inode *inode, struct rpc_cred *cred, const nfs4_stateid *stateid);
40int nfs4_open_delegation_recall(struct dentry *dentry, struct nfs4_state *state); 40int nfs4_open_delegation_recall(struct dentry *dentry, struct nfs4_state *state);
41int nfs4_lock_delegation_recall(struct nfs4_state *state, struct file_lock *fl);
41 42
42static inline int nfs_have_delegation(struct inode *inode, int flags) 43static inline int nfs_have_delegation(struct inode *inode, int flags)
43{ 44{
diff --git a/fs/nfs/nfs4proc.c b/fs/nfs/nfs4proc.c
index 54ff465cf7cf..e6a9322a321f 100644
--- a/fs/nfs/nfs4proc.c
+++ b/fs/nfs/nfs4proc.c
@@ -3124,6 +3124,24 @@ nfs4_proc_lock(struct file *filp, int cmd, struct file_lock *request)
3124 return status; 3124 return status;
3125} 3125}
3126 3126
3127int nfs4_lock_delegation_recall(struct nfs4_state *state, struct file_lock *fl)
3128{
3129 struct nfs_server *server = NFS_SERVER(state->inode);
3130 struct nfs4_exception exception = { };
3131 int err;
3132
3133 err = nfs4_set_lock_state(state, fl);
3134 if (err != 0)
3135 goto out;
3136 do {
3137 err = _nfs4_do_setlk(state, F_SETLK, fl, 0);
3138 if (err != -NFS4ERR_DELAY)
3139 break;
3140 err = nfs4_handle_exception(server, err, &exception);
3141 } while (exception.retry);
3142out:
3143 return err;
3144}
3127 3145
3128#define XATTR_NAME_NFSV4_ACL "system.nfs4_acl" 3146#define XATTR_NAME_NFSV4_ACL "system.nfs4_acl"
3129 3147