Message ID | 55de39aa.W9GYAubwGm54CvY6%akpm@linux-foundation.org (mailing list archive) |
---|---|
State | New, archived |
Headers | show |
On Wed, Aug 26, 2015 at 03:11:54PM -0700, Andrew Morton wrote: > ocfs2_setattr must not drop inode lock ex in this code path. If it does, > takes it again before the trans, say in ocfs2_set_acl, another cluster node can > get in between, execute another setattr, overwriting the one in progress > on this node, resulting in a mode acl size combo that is a mix of the two. > > Signed-off-by: Tariq Saeed <tariq.x.saeed@oracle.com> > Cc: Mark Fasheh <mfasheh@suse.com> > Cc: Joel Becker <jlbec@evilplan.org> > Cc: Joseph Qi <joseph.qi@huawei.com> > Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Reviewed-by: Mark Fasheh <mfasheh@suse.de> -- Mark Fasheh
diff -puN fs/ocfs2/file.c~resubmit-bug_onlockres-l_level-=-dlm_lock_ex-checkpointed-tripped-in-ocfs2_ci_checkpointed fs/ocfs2/file.c --- a/fs/ocfs2/file.c~resubmit-bug_onlockres-l_level-=-dlm_lock_ex-checkpointed-tripped-in-ocfs2_ci_checkpointed +++ a/fs/ocfs2/file.c @@ -1127,6 +1127,7 @@ out: int ocfs2_setattr(struct dentry *dentry, struct iattr *attr) { int status = 0, size_change; + int inode_locked = 0; struct inode *inode = d_inode(dentry); struct super_block *sb = inode->i_sb; struct ocfs2_super *osb = OCFS2_SB(sb); @@ -1172,6 +1173,7 @@ int ocfs2_setattr(struct dentry *dentry, mlog_errno(status); goto bail_unlock_rw; } + inode_locked = 1; if (size_change) { status = inode_newsize_ok(inode, attr->ia_size); @@ -1252,7 +1254,10 @@ int ocfs2_setattr(struct dentry *dentry, bail_commit: ocfs2_commit_trans(osb, handle); bail_unlock: - ocfs2_inode_unlock(inode, 1); + if (status) { + ocfs2_inode_unlock(inode, 1); + inode_locked = 0; + } bail_unlock_rw: if (size_change) ocfs2_rw_unlock(inode, 1); @@ -1268,6 +1273,8 @@ bail: if (status < 0) mlog_errno(status); } + if (inode_locked) + ocfs2_inode_unlock(inode, 1); return status; }