Commit 1a5ad5dd authored by Jeff Mahoney's avatar Jeff Mahoney Committed by Linus Torvalds

[PATCH] Fix for default ACL handling on ReiserFS

reiserfs_set_xattr() explicitly updates the ctime for the host inode.

This works for direct setfacl/setfattr calls, but for the more common case
of an inherited default ACL, it breaks.  The ACL is inherited in the middle
of the new inode creation, before the inode has been hashed.

When mark_inode_dirty is called, one of the checks bails out if the inode
is unhashed -- but AFTER inode->i_state is updated, so the inode is marked
dirty but never placed on any dirty list.

Since the inode is never placed on a dirty list, __sync_single_inode from
the writeback_inodes() path can never be called on it to clear the dirty
flags.  Once the inode is hashed and mark_inode_dirty is called for it
again, it's too late -- it will bail early assuming (correctly) that the
inode is already marked dirty.  This ultimately results in I/O stalls that
can't be resolved by the fs path, only be the memory allocation path that
uses pages directly.

The attached patch makes the update of the ctime conditional on the inode
being hashed already.
Signed-off-by: default avatarAndrew Morton <akpm@osdl.org>
Signed-off-by: default avatarLinus Torvalds <torvalds@osdl.org>
parent c88d19d6
......@@ -589,8 +589,14 @@ reiserfs_xattr_set (struct inode *inode, const char *name, const void *buffer,
break;
}
/* We can't mark the inode dirty if it's not hashed. This is the case
* when we're inheriting the default ACL. If we dirty it, the inode
* gets marked dirty, but won't (ever) make it onto the dirty list until
* it's synced explicitly to clear I_DIRTY. This is bad. */
if (!hlist_unhashed(&inode->i_hash)) {
inode->i_ctime = CURRENT_TIME;
mark_inode_dirty (inode);
}
out_filp:
up (&xinode->i_sem);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment