NFSv4: Close another NFSv4 recovery race
State recovery currently relies on being able to find a valid nfs_open_context in the inode->open_files list. We therefore need to put the nfs_open_context on the list while we're still protected by the sp->so_reclaim_seqcount in order to avoid reboot races. Signed-off-by: Trond Myklebust <Trond.Myklebust@netapp.com>
This commit is contained in:
parent
275bb30786
commit
c45ffdd269
@ -713,16 +713,23 @@ EXPORT_SYMBOL_GPL(put_nfs_open_context);
|
||||
* Ensure that mmap has a recent RPC credential for use when writing out
|
||||
* shared pages
|
||||
*/
|
||||
void nfs_file_set_open_context(struct file *filp, struct nfs_open_context *ctx)
|
||||
void nfs_inode_attach_open_context(struct nfs_open_context *ctx)
|
||||
{
|
||||
struct inode *inode = file_inode(filp);
|
||||
struct inode *inode = ctx->dentry->d_inode;
|
||||
struct nfs_inode *nfsi = NFS_I(inode);
|
||||
|
||||
filp->private_data = get_nfs_open_context(ctx);
|
||||
spin_lock(&inode->i_lock);
|
||||
list_add(&ctx->list, &nfsi->open_files);
|
||||
spin_unlock(&inode->i_lock);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(nfs_inode_attach_open_context);
|
||||
|
||||
void nfs_file_set_open_context(struct file *filp, struct nfs_open_context *ctx)
|
||||
{
|
||||
filp->private_data = get_nfs_open_context(ctx);
|
||||
if (list_empty(&ctx->list))
|
||||
nfs_inode_attach_open_context(ctx);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(nfs_file_set_open_context);
|
||||
|
||||
/*
|
||||
@ -748,10 +755,11 @@ struct nfs_open_context *nfs_find_open_context(struct inode *inode, struct rpc_c
|
||||
|
||||
static void nfs_file_clear_open_context(struct file *filp)
|
||||
{
|
||||
struct inode *inode = file_inode(filp);
|
||||
struct nfs_open_context *ctx = nfs_file_open_context(filp);
|
||||
|
||||
if (ctx) {
|
||||
struct inode *inode = ctx->dentry->d_inode;
|
||||
|
||||
filp->private_data = NULL;
|
||||
spin_lock(&inode->i_lock);
|
||||
list_move_tail(&ctx->list, &NFS_I(inode)->open_files);
|
||||
|
@ -2002,8 +2002,11 @@ static int _nfs4_open_and_get_state(struct nfs4_opendata *opendata,
|
||||
goto out;
|
||||
|
||||
ctx->state = state;
|
||||
if (dentry->d_inode == state->inode) {
|
||||
nfs_inode_attach_open_context(ctx);
|
||||
if (read_seqcount_retry(&sp->so_reclaim_seqcount, seq))
|
||||
nfs4_schedule_stateid_recovery(server, state);
|
||||
}
|
||||
out:
|
||||
return ret;
|
||||
}
|
||||
|
@ -356,6 +356,7 @@ extern struct nfs_open_context *get_nfs_open_context(struct nfs_open_context *ct
|
||||
extern void put_nfs_open_context(struct nfs_open_context *ctx);
|
||||
extern struct nfs_open_context *nfs_find_open_context(struct inode *inode, struct rpc_cred *cred, fmode_t mode);
|
||||
extern struct nfs_open_context *alloc_nfs_open_context(struct dentry *dentry, fmode_t f_mode);
|
||||
extern void nfs_inode_attach_open_context(struct nfs_open_context *ctx);
|
||||
extern void nfs_file_set_open_context(struct file *filp, struct nfs_open_context *ctx);
|
||||
extern struct nfs_lock_context *nfs_get_lock_context(struct nfs_open_context *ctx);
|
||||
extern void nfs_put_lock_context(struct nfs_lock_context *l_ctx);
|
||||
|
Loading…
Reference in New Issue
Block a user