aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorTrond Myklebust <Trond.Myklebust@netapp.com>2013-05-29 13:34:46 -0400
committerTrond Myklebust <Trond.Myklebust@netapp.com>2013-06-06 16:24:44 -0400
commitc45ffdd26961302ec5eeac7311553d6f1e348e9c (patch)
tree2e7afeafe15c0a6c3886cd16a4cc601337ee3ea5
parent275bb307865a316cef390e01e6ab5e21e97023a2 (diff)
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>
-rw-r--r--fs/nfs/inode.c16
-rw-r--r--fs/nfs/nfs4proc.c7
-rw-r--r--include/linux/nfs_fs.h1
3 files changed, 18 insertions, 6 deletions
diff --git a/fs/nfs/inode.c b/fs/nfs/inode.c
index c1c7a9d78722..c121982659a2 100644
--- a/fs/nfs/inode.c
+++ b/fs/nfs/inode.c
@@ -713,16 +713,23 @@ EXPORT_SYMBOL_GPL(put_nfs_open_context);
713 * Ensure that mmap has a recent RPC credential for use when writing out 713 * Ensure that mmap has a recent RPC credential for use when writing out
714 * shared pages 714 * shared pages
715 */ 715 */
716void nfs_file_set_open_context(struct file *filp, struct nfs_open_context *ctx) 716void nfs_inode_attach_open_context(struct nfs_open_context *ctx)
717{ 717{
718 struct inode *inode = file_inode(filp); 718 struct inode *inode = ctx->dentry->d_inode;
719 struct nfs_inode *nfsi = NFS_I(inode); 719 struct nfs_inode *nfsi = NFS_I(inode);
720 720
721 filp->private_data = get_nfs_open_context(ctx);
722 spin_lock(&inode->i_lock); 721 spin_lock(&inode->i_lock);
723 list_add(&ctx->list, &nfsi->open_files); 722 list_add(&ctx->list, &nfsi->open_files);
724 spin_unlock(&inode->i_lock); 723 spin_unlock(&inode->i_lock);
725} 724}
725EXPORT_SYMBOL_GPL(nfs_inode_attach_open_context);
726
727void nfs_file_set_open_context(struct file *filp, struct nfs_open_context *ctx)
728{
729 filp->private_data = get_nfs_open_context(ctx);
730 if (list_empty(&ctx->list))
731 nfs_inode_attach_open_context(ctx);
732}
726EXPORT_SYMBOL_GPL(nfs_file_set_open_context); 733EXPORT_SYMBOL_GPL(nfs_file_set_open_context);
727 734
728/* 735/*
@@ -748,10 +755,11 @@ struct nfs_open_context *nfs_find_open_context(struct inode *inode, struct rpc_c
748 755
749static void nfs_file_clear_open_context(struct file *filp) 756static void nfs_file_clear_open_context(struct file *filp)
750{ 757{
751 struct inode *inode = file_inode(filp);
752 struct nfs_open_context *ctx = nfs_file_open_context(filp); 758 struct nfs_open_context *ctx = nfs_file_open_context(filp);
753 759
754 if (ctx) { 760 if (ctx) {
761 struct inode *inode = ctx->dentry->d_inode;
762
755 filp->private_data = NULL; 763 filp->private_data = NULL;
756 spin_lock(&inode->i_lock); 764 spin_lock(&inode->i_lock);
757 list_move_tail(&ctx->list, &NFS_I(inode)->open_files); 765 list_move_tail(&ctx->list, &NFS_I(inode)->open_files);
diff --git a/fs/nfs/nfs4proc.c b/fs/nfs/nfs4proc.c
index aaf2c1324be7..65467abbd5a6 100644
--- a/fs/nfs/nfs4proc.c
+++ b/fs/nfs/nfs4proc.c
@@ -2002,8 +2002,11 @@ static int _nfs4_open_and_get_state(struct nfs4_opendata *opendata,
2002 goto out; 2002 goto out;
2003 2003
2004 ctx->state = state; 2004 ctx->state = state;
2005 if (read_seqcount_retry(&sp->so_reclaim_seqcount, seq)) 2005 if (dentry->d_inode == state->inode) {
2006 nfs4_schedule_stateid_recovery(server, state); 2006 nfs_inode_attach_open_context(ctx);
2007 if (read_seqcount_retry(&sp->so_reclaim_seqcount, seq))
2008 nfs4_schedule_stateid_recovery(server, state);
2009 }
2007out: 2010out:
2008 return ret; 2011 return ret;
2009} 2012}
diff --git a/include/linux/nfs_fs.h b/include/linux/nfs_fs.h
index fc01d5cb4cf1..1384ed92cad6 100644
--- a/include/linux/nfs_fs.h
+++ b/include/linux/nfs_fs.h
@@ -356,6 +356,7 @@ extern struct nfs_open_context *get_nfs_open_context(struct nfs_open_context *ct
356extern void put_nfs_open_context(struct nfs_open_context *ctx); 356extern void put_nfs_open_context(struct nfs_open_context *ctx);
357extern struct nfs_open_context *nfs_find_open_context(struct inode *inode, struct rpc_cred *cred, fmode_t mode); 357extern struct nfs_open_context *nfs_find_open_context(struct inode *inode, struct rpc_cred *cred, fmode_t mode);
358extern struct nfs_open_context *alloc_nfs_open_context(struct dentry *dentry, fmode_t f_mode); 358extern struct nfs_open_context *alloc_nfs_open_context(struct dentry *dentry, fmode_t f_mode);
359extern void nfs_inode_attach_open_context(struct nfs_open_context *ctx);
359extern void nfs_file_set_open_context(struct file *filp, struct nfs_open_context *ctx); 360extern void nfs_file_set_open_context(struct file *filp, struct nfs_open_context *ctx);
360extern struct nfs_lock_context *nfs_get_lock_context(struct nfs_open_context *ctx); 361extern struct nfs_lock_context *nfs_get_lock_context(struct nfs_open_context *ctx);
361extern void nfs_put_lock_context(struct nfs_lock_context *l_ctx); 362extern void nfs_put_lock_context(struct nfs_lock_context *l_ctx);