diff options
author | Trond Myklebust <Trond.Myklebust@netapp.com> | 2013-05-29 13:34:46 -0400 |
---|---|---|
committer | Trond Myklebust <Trond.Myklebust@netapp.com> | 2013-06-06 16:24:44 -0400 |
commit | c45ffdd26961302ec5eeac7311553d6f1e348e9c (patch) | |
tree | 2e7afeafe15c0a6c3886cd16a4cc601337ee3ea5 /fs/nfs | |
parent | 275bb307865a316cef390e01e6ab5e21e97023a2 (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>
Diffstat (limited to 'fs/nfs')
-rw-r--r-- | fs/nfs/inode.c | 16 | ||||
-rw-r--r-- | fs/nfs/nfs4proc.c | 7 |
2 files changed, 17 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 | */ |
716 | void nfs_file_set_open_context(struct file *filp, struct nfs_open_context *ctx) | 716 | void 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 | } |
725 | EXPORT_SYMBOL_GPL(nfs_inode_attach_open_context); | ||
726 | |||
727 | void 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 | } | ||
726 | EXPORT_SYMBOL_GPL(nfs_file_set_open_context); | 733 | EXPORT_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 | ||
749 | static void nfs_file_clear_open_context(struct file *filp) | 756 | static 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 | } | ||
2007 | out: | 2010 | out: |
2008 | return ret; | 2011 | return ret; |
2009 | } | 2012 | } |