Messages in this thread Patch in this message | | | Date | Sat, 17 Dec 2011 08:49:44 +0000 | From | Al Viro <> | Subject | Re: Linux 3.2-rc6 |
| |
On Fri, Dec 16, 2011 at 06:53:17PM -0800, Linus Torvalds wrote:
> Casey Schaufler (1): > BTRFS: Establish i_ops before calling d_instantiate
I'm sorry, but that's nowhere near enough. As I said in followup to the original posting of that patch, it still leaves a race window where inode is already associated with dentry but still doesn't have ->a_ops, etc. set up. Hell, ->symlink() doesn't write the symlink body until after that point...
Signed-off-by: Al Viro <viro@zeniv.linux.org.uk> --- diff --git a/fs/btrfs/inode.c b/fs/btrfs/inode.c index 329a5c6..d9501f5 100644 --- a/fs/btrfs/inode.c +++ b/fs/btrfs/inode.c @@ -4590,10 +4590,6 @@ static int btrfs_add_nondir(struct btrfs_trans_handle *trans, int err = btrfs_add_link(trans, dir, inode, dentry->d_name.name, dentry->d_name.len, backref, index); - if (!err) { - d_instantiate(dentry, inode); - return 0; - } if (err > 0) err = -EEXIST; return err; @@ -4655,6 +4651,7 @@ static int btrfs_mknod(struct inode *dir, struct dentry *dentry, else { init_special_inode(inode, inode->i_mode, rdev); btrfs_update_inode(trans, root, inode); + d_instantiate(dentry, inode); } out_unlock: nr = trans->blocks_used; @@ -4722,6 +4719,7 @@ static int btrfs_create(struct inode *dir, struct dentry *dentry, inode->i_mapping->a_ops = &btrfs_aops; inode->i_mapping->backing_dev_info = &root->fs_info->bdi; BTRFS_I(inode)->io_tree.ops = &btrfs_extent_io_ops; + d_instantiate(dentry, inode); } out_unlock: nr = trans->blocks_used; @@ -4780,6 +4778,7 @@ static int btrfs_link(struct dentry *old_dentry, struct inode *dir, err = btrfs_update_inode(trans, root, inode); BUG_ON(err); btrfs_log_new_name(trans, inode, NULL, parent); + d_instantiate(dentry, inode); } nr = trans->blocks_used; @@ -7244,6 +7243,8 @@ static int btrfs_symlink(struct inode *dir, struct dentry *dentry, drop_inode = 1; out_unlock: + if (!err) + d_instantiate(dentry, inode); nr = trans->blocks_used; btrfs_end_transaction_throttle(trans, root); if (drop_inode) {
| |