aboutsummaryrefslogtreecommitdiffstats
path: root/fs
diff options
context:
space:
mode:
authorWeston Andros Adamson <dros@netapp.com>2011-04-13 10:53:51 -0400
committerTrond Myklebust <Trond.Myklebust@netapp.com>2011-04-13 13:15:51 -0400
commit79a48a1f5d99ab66cf83d2d5d805e7a0e08452ed (patch)
tree158e953b809b93d93334cc91662136af27b69a8d /fs
parentc0d0e96b840dcc73f9b9d45bf8f405dbce72a079 (diff)
Don't mark_inode_dirty_sync() while holding lock
mark_inode_dirty_sync() grabs the same inode lock! race conditions between holding the lock in pnfs_set_layoutcommit() and in mark_inode_dirty_sync() can result in a second call to pnfs_layoutcommit_inode(), but this will be a noop as NFS_INO_LAYOUTCOMMIT won't be set in the second call Signed-off-by: Weston Andros Adamson <dros@netapp.com> Signed-off-by: Trond Myklebust <Trond.Myklebust@netapp.com>
Diffstat (limited to 'fs')
-rw-r--r--fs/nfs/pnfs.c8
1 files changed, 7 insertions, 1 deletions
diff --git a/fs/nfs/pnfs.c b/fs/nfs/pnfs.c
index d9ab97269ce6..ff681ab65d31 100644
--- a/fs/nfs/pnfs.c
+++ b/fs/nfs/pnfs.c
@@ -1004,6 +1004,7 @@ pnfs_set_layoutcommit(struct nfs_write_data *wdata)
1004{ 1004{
1005 struct nfs_inode *nfsi = NFS_I(wdata->inode); 1005 struct nfs_inode *nfsi = NFS_I(wdata->inode);
1006 loff_t end_pos = wdata->args.offset + wdata->res.count; 1006 loff_t end_pos = wdata->args.offset + wdata->res.count;
1007 bool mark_as_dirty = false;
1007 1008
1008 spin_lock(&nfsi->vfs_inode.i_lock); 1009 spin_lock(&nfsi->vfs_inode.i_lock);
1009 if (!test_and_set_bit(NFS_INO_LAYOUTCOMMIT, &nfsi->flags)) { 1010 if (!test_and_set_bit(NFS_INO_LAYOUTCOMMIT, &nfsi->flags)) {
@@ -1011,13 +1012,18 @@ pnfs_set_layoutcommit(struct nfs_write_data *wdata)
1011 get_lseg(wdata->lseg); 1012 get_lseg(wdata->lseg);
1012 wdata->lseg->pls_lc_cred = 1013 wdata->lseg->pls_lc_cred =
1013 get_rpccred(wdata->args.context->state->owner->so_cred); 1014 get_rpccred(wdata->args.context->state->owner->so_cred);
1014 mark_inode_dirty_sync(wdata->inode); 1015 mark_as_dirty = true;
1015 dprintk("%s: Set layoutcommit for inode %lu ", 1016 dprintk("%s: Set layoutcommit for inode %lu ",
1016 __func__, wdata->inode->i_ino); 1017 __func__, wdata->inode->i_ino);
1017 } 1018 }
1018 if (end_pos > wdata->lseg->pls_end_pos) 1019 if (end_pos > wdata->lseg->pls_end_pos)
1019 wdata->lseg->pls_end_pos = end_pos; 1020 wdata->lseg->pls_end_pos = end_pos;
1020 spin_unlock(&nfsi->vfs_inode.i_lock); 1021 spin_unlock(&nfsi->vfs_inode.i_lock);
1022
1023 /* if pnfs_layoutcommit_inode() runs between inode locks, the next one
1024 * will be a noop because NFS_INO_LAYOUTCOMMIT will not be set */
1025 if (mark_as_dirty)
1026 mark_inode_dirty_sync(wdata->inode);
1021} 1027}
1022EXPORT_SYMBOL_GPL(pnfs_set_layoutcommit); 1028EXPORT_SYMBOL_GPL(pnfs_set_layoutcommit);
1023 1029