Commit 888e694c authored by Trond Myklebust's avatar Trond Myklebust

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: default avatarTrond Myklebust <Trond.Myklebust@netapp.com>
parent 43b2a33a
...@@ -31,11 +31,42 @@ static void nfs_free_delegation(struct nfs_delegation *delegation) ...@@ -31,11 +31,42 @@ static void nfs_free_delegation(struct nfs_delegation *delegation)
kfree(delegation); kfree(delegation);
} }
static int nfs_delegation_claim_locks(struct nfs_open_context *ctx, struct nfs4_state *state)
{
struct inode *inode = state->inode;
struct file_lock *fl;
int status;
for (fl = inode->i_flock; fl != 0; fl = fl->fl_next) {
if (!(fl->fl_flags & (FL_POSIX|FL_FLOCK)))
continue;
if ((struct nfs_open_context *)fl->fl_file->private_data != ctx)
continue;
status = nfs4_lock_delegation_recall(state, fl);
if (status >= 0)
continue;
switch (status) {
default:
printk(KERN_ERR "%s: unhandled error %d.\n",
__FUNCTION__, status);
case -NFS4ERR_EXPIRED:
/* kill_proc(fl->fl_pid, SIGLOST, 1); */
case -NFS4ERR_STALE_CLIENTID:
nfs4_schedule_state_recovery(NFS_SERVER(inode)->nfs4_state);
goto out_err;
}
}
return 0;
out_err:
return status;
}
static void nfs_delegation_claim_opens(struct inode *inode) static void nfs_delegation_claim_opens(struct inode *inode)
{ {
struct nfs_inode *nfsi = NFS_I(inode); struct nfs_inode *nfsi = NFS_I(inode);
struct nfs_open_context *ctx; struct nfs_open_context *ctx;
struct nfs4_state *state; struct nfs4_state *state;
int err;
again: again:
spin_lock(&inode->i_lock); spin_lock(&inode->i_lock);
...@@ -47,9 +78,12 @@ again: ...@@ -47,9 +78,12 @@ again:
continue; continue;
get_nfs_open_context(ctx); get_nfs_open_context(ctx);
spin_unlock(&inode->i_lock); spin_unlock(&inode->i_lock);
if (nfs4_open_delegation_recall(ctx->dentry, state) < 0) err = nfs4_open_delegation_recall(ctx->dentry, state);
return; if (err >= 0)
err = nfs_delegation_claim_locks(ctx, state);
put_nfs_open_context(ctx); put_nfs_open_context(ctx);
if (err != 0)
return;
goto again; goto again;
} }
spin_unlock(&inode->i_lock); spin_unlock(&inode->i_lock);
......
...@@ -38,6 +38,7 @@ void nfs_delegation_reap_unclaimed(struct nfs4_client *clp); ...@@ -38,6 +38,7 @@ void nfs_delegation_reap_unclaimed(struct nfs4_client *clp);
/* NFSv4 delegation-related procedures */ /* NFSv4 delegation-related procedures */
int nfs4_proc_delegreturn(struct inode *inode, struct rpc_cred *cred, const nfs4_stateid *stateid); int nfs4_proc_delegreturn(struct inode *inode, struct rpc_cred *cred, const nfs4_stateid *stateid);
int nfs4_open_delegation_recall(struct dentry *dentry, struct nfs4_state *state); int nfs4_open_delegation_recall(struct dentry *dentry, struct nfs4_state *state);
int nfs4_lock_delegation_recall(struct nfs4_state *state, struct file_lock *fl);
static inline int nfs_have_delegation(struct inode *inode, int flags) static inline int nfs_have_delegation(struct inode *inode, int flags)
{ {
......
...@@ -3124,6 +3124,24 @@ nfs4_proc_lock(struct file *filp, int cmd, struct file_lock *request) ...@@ -3124,6 +3124,24 @@ nfs4_proc_lock(struct file *filp, int cmd, struct file_lock *request)
return status; return status;
} }
int nfs4_lock_delegation_recall(struct nfs4_state *state, struct file_lock *fl)
{
struct nfs_server *server = NFS_SERVER(state->inode);
struct nfs4_exception exception = { };
int err;
err = nfs4_set_lock_state(state, fl);
if (err != 0)
goto out;
do {
err = _nfs4_do_setlk(state, F_SETLK, fl, 0);
if (err != -NFS4ERR_DELAY)
break;
err = nfs4_handle_exception(server, err, &exception);
} while (exception.retry);
out:
return err;
}
#define XATTR_NAME_NFSV4_ACL "system.nfs4_acl" #define XATTR_NAME_NFSV4_ACL "system.nfs4_acl"
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment