Skip to content

Commit

Permalink
Merge branch 'work.mkdir' of git://git.kernel.org/pub/scm/linux/kerne…
Browse files Browse the repository at this point in the history
…l/git/viro/vfs

Pull vfs icache updates from Al Viro:

 - NFS mkdir/open_by_handle race fix

 - analogous solution for FUSE, replacing the one currently in mainline

 - new primitive to be used when discarding halfway set up inodes on
   failed object creation; gives sane warranties re icache lookups not
   returning such doomed by still not freed inodes. A bunch of
   filesystems switched to that animal.

 - Miklos' fix for last cycle regression in iget5_locked(); -stable will
   need a slightly different variant, unfortunately.

 - misc bits and pieces around things icache-related (in adfs and jfs).

* 'work.mkdir' of git://git.kernel.org/pub/scm/linux/kernel/git/viro/vfs:
  jfs: don't bother with make_bad_inode() in ialloc()
  adfs: don't put inodes into icache
  new helper: inode_fake_hash()
  vfs: don't evict uninitialized inode
  jfs: switch to discard_new_inode()
  ext2: make sure that partially set up inodes won't be returned by ext2_iget()
  udf: switch to discard_new_inode()
  ufs: switch to discard_new_inode()
  btrfs: switch to discard_new_inode()
  new primitive: discard_new_inode()
  kill d_instantiate_no_diralias()
  nfs_instantiate(): prevent multiple aliases for directory inode
  • Loading branch information
torvalds committed Aug 14, 2018
2 parents a66b4cd + c7b15a8 commit 0ea97a2
Show file tree
Hide file tree
Showing 20 changed files with 146 additions and 159 deletions.
2 changes: 1 addition & 1 deletion fs/adfs/inode.c
Original file line number Diff line number Diff line change
Expand Up @@ -287,7 +287,7 @@ adfs_iget(struct super_block *sb, struct object_info *obj)
ADFS_I(inode)->mmu_private = inode->i_size;
}

insert_inode_hash(inode);
inode_fake_hash(inode);

out:
return inode;
Expand Down
1 change: 1 addition & 0 deletions fs/adfs/super.c
Original file line number Diff line number Diff line change
Expand Up @@ -291,6 +291,7 @@ static void destroy_inodecache(void)
static const struct super_operations adfs_sops = {
.alloc_inode = adfs_alloc_inode,
.destroy_inode = adfs_destroy_inode,
.drop_inode = generic_delete_inode,
.write_inode = adfs_write_inode,
.put_super = adfs_put_super,
.statfs = adfs_statfs,
Expand Down
106 changes: 39 additions & 67 deletions fs/btrfs/inode.c
Original file line number Diff line number Diff line change
Expand Up @@ -6335,8 +6335,10 @@ static struct inode *btrfs_new_inode(struct btrfs_trans_handle *trans,
location->type = BTRFS_INODE_ITEM_KEY;

ret = btrfs_insert_inode_locked(inode);
if (ret < 0)
if (ret < 0) {
iput(inode);
goto fail;
}

path->leave_spinning = 1;
ret = btrfs_insert_empty_items(trans, root, path, key, sizes, nitems);
Expand Down Expand Up @@ -6395,12 +6397,11 @@ static struct inode *btrfs_new_inode(struct btrfs_trans_handle *trans,
return inode;

fail_unlock:
unlock_new_inode(inode);
discard_new_inode(inode);
fail:
if (dir && name)
BTRFS_I(dir)->index_cnt--;
btrfs_free_path(path);
iput(inode);
return ERR_PTR(ret);
}

Expand Down Expand Up @@ -6505,7 +6506,6 @@ static int btrfs_mknod(struct inode *dir, struct dentry *dentry,
struct btrfs_root *root = BTRFS_I(dir)->root;
struct inode *inode = NULL;
int err;
int drop_inode = 0;
u64 objectid;
u64 index = 0;

Expand All @@ -6527,6 +6527,7 @@ static int btrfs_mknod(struct inode *dir, struct dentry *dentry,
mode, &index);
if (IS_ERR(inode)) {
err = PTR_ERR(inode);
inode = NULL;
goto out_unlock;
}

Expand All @@ -6541,31 +6542,24 @@ static int btrfs_mknod(struct inode *dir, struct dentry *dentry,

err = btrfs_init_inode_security(trans, inode, dir, &dentry->d_name);
if (err)
goto out_unlock_inode;
goto out_unlock;

err = btrfs_add_nondir(trans, BTRFS_I(dir), dentry, BTRFS_I(inode),
0, index);
if (err) {
goto out_unlock_inode;
} else {
btrfs_update_inode(trans, root, inode);
d_instantiate_new(dentry, inode);
}
if (err)
goto out_unlock;

btrfs_update_inode(trans, root, inode);
d_instantiate_new(dentry, inode);

out_unlock:
btrfs_end_transaction(trans);
btrfs_btree_balance_dirty(fs_info);
if (drop_inode) {
if (err && inode) {
inode_dec_link_count(inode);
iput(inode);
discard_new_inode(inode);
}
return err;

out_unlock_inode:
drop_inode = 1;
unlock_new_inode(inode);
goto out_unlock;

}

static int btrfs_create(struct inode *dir, struct dentry *dentry,
Expand All @@ -6575,7 +6569,6 @@ static int btrfs_create(struct inode *dir, struct dentry *dentry,
struct btrfs_trans_handle *trans;
struct btrfs_root *root = BTRFS_I(dir)->root;
struct inode *inode = NULL;
int drop_inode_on_err = 0;
int err;
u64 objectid;
u64 index = 0;
Expand All @@ -6598,9 +6591,9 @@ static int btrfs_create(struct inode *dir, struct dentry *dentry,
mode, &index);
if (IS_ERR(inode)) {
err = PTR_ERR(inode);
inode = NULL;
goto out_unlock;
}
drop_inode_on_err = 1;
/*
* If the active LSM wants to access the inode during
* d_instantiate it needs these. Smack checks to see
Expand All @@ -6613,33 +6606,28 @@ static int btrfs_create(struct inode *dir, struct dentry *dentry,

err = btrfs_init_inode_security(trans, inode, dir, &dentry->d_name);
if (err)
goto out_unlock_inode;
goto out_unlock;

err = btrfs_update_inode(trans, root, inode);
if (err)
goto out_unlock_inode;
goto out_unlock;

err = btrfs_add_nondir(trans, BTRFS_I(dir), dentry, BTRFS_I(inode),
0, index);
if (err)
goto out_unlock_inode;
goto out_unlock;

BTRFS_I(inode)->io_tree.ops = &btrfs_extent_io_ops;
d_instantiate_new(dentry, inode);

out_unlock:
btrfs_end_transaction(trans);
if (err && drop_inode_on_err) {
if (err && inode) {
inode_dec_link_count(inode);
iput(inode);
discard_new_inode(inode);
}
btrfs_btree_balance_dirty(fs_info);
return err;

out_unlock_inode:
unlock_new_inode(inode);
goto out_unlock;

}

static int btrfs_link(struct dentry *old_dentry, struct inode *dir,
Expand Down Expand Up @@ -6748,6 +6736,7 @@ static int btrfs_mkdir(struct inode *dir, struct dentry *dentry, umode_t mode)
S_IFDIR | mode, &index);
if (IS_ERR(inode)) {
err = PTR_ERR(inode);
inode = NULL;
goto out_fail;
}

Expand All @@ -6758,34 +6747,30 @@ static int btrfs_mkdir(struct inode *dir, struct dentry *dentry, umode_t mode)

err = btrfs_init_inode_security(trans, inode, dir, &dentry->d_name);
if (err)
goto out_fail_inode;
goto out_fail;

btrfs_i_size_write(BTRFS_I(inode), 0);
err = btrfs_update_inode(trans, root, inode);
if (err)
goto out_fail_inode;
goto out_fail;

err = btrfs_add_link(trans, BTRFS_I(dir), BTRFS_I(inode),
dentry->d_name.name,
dentry->d_name.len, 0, index);
if (err)
goto out_fail_inode;
goto out_fail;

d_instantiate_new(dentry, inode);
drop_on_err = 0;

out_fail:
btrfs_end_transaction(trans);
if (drop_on_err) {
if (err && inode) {
inode_dec_link_count(inode);
iput(inode);
discard_new_inode(inode);
}
btrfs_btree_balance_dirty(fs_info);
return err;

out_fail_inode:
unlock_new_inode(inode);
goto out_fail;
}

static noinline int uncompress_inline(struct btrfs_path *path,
Expand Down Expand Up @@ -10115,7 +10100,6 @@ static int btrfs_symlink(struct inode *dir, struct dentry *dentry,
struct btrfs_key key;
struct inode *inode = NULL;
int err;
int drop_inode = 0;
u64 objectid;
u64 index = 0;
int name_len;
Expand Down Expand Up @@ -10148,6 +10132,7 @@ static int btrfs_symlink(struct inode *dir, struct dentry *dentry,
objectid, S_IFLNK|S_IRWXUGO, &index);
if (IS_ERR(inode)) {
err = PTR_ERR(inode);
inode = NULL;
goto out_unlock;
}

Expand All @@ -10164,12 +10149,12 @@ static int btrfs_symlink(struct inode *dir, struct dentry *dentry,

err = btrfs_init_inode_security(trans, inode, dir, &dentry->d_name);
if (err)
goto out_unlock_inode;
goto out_unlock;

path = btrfs_alloc_path();
if (!path) {
err = -ENOMEM;
goto out_unlock_inode;
goto out_unlock;
}
key.objectid = btrfs_ino(BTRFS_I(inode));
key.offset = 0;
Expand All @@ -10179,7 +10164,7 @@ static int btrfs_symlink(struct inode *dir, struct dentry *dentry,
datasize);
if (err) {
btrfs_free_path(path);
goto out_unlock_inode;
goto out_unlock;
}
leaf = path->nodes[0];
ei = btrfs_item_ptr(leaf, path->slots[0],
Expand Down Expand Up @@ -10211,26 +10196,19 @@ static int btrfs_symlink(struct inode *dir, struct dentry *dentry,
if (!err)
err = btrfs_add_nondir(trans, BTRFS_I(dir), dentry,
BTRFS_I(inode), 0, index);
if (err) {
drop_inode = 1;
goto out_unlock_inode;
}
if (err)
goto out_unlock;

d_instantiate_new(dentry, inode);

out_unlock:
btrfs_end_transaction(trans);
if (drop_inode) {
if (err && inode) {
inode_dec_link_count(inode);
iput(inode);
discard_new_inode(inode);
}
btrfs_btree_balance_dirty(fs_info);
return err;

out_unlock_inode:
drop_inode = 1;
unlock_new_inode(inode);
goto out_unlock;
}

static int __btrfs_prealloc_file_range(struct inode *inode, int mode,
Expand Down Expand Up @@ -10439,14 +10417,14 @@ static int btrfs_tmpfile(struct inode *dir, struct dentry *dentry, umode_t mode)

ret = btrfs_init_inode_security(trans, inode, dir, NULL);
if (ret)
goto out_inode;
goto out;

ret = btrfs_update_inode(trans, root, inode);
if (ret)
goto out_inode;
goto out;
ret = btrfs_orphan_add(trans, BTRFS_I(inode));
if (ret)
goto out_inode;
goto out;

/*
* We set number of links to 0 in btrfs_new_inode(), and here we set
Expand All @@ -10456,21 +10434,15 @@ static int btrfs_tmpfile(struct inode *dir, struct dentry *dentry, umode_t mode)
* d_tmpfile() -> inode_dec_link_count() -> drop_nlink()
*/
set_nlink(inode, 1);
unlock_new_inode(inode);
d_tmpfile(dentry, inode);
unlock_new_inode(inode);
mark_inode_dirty(inode);

out:
btrfs_end_transaction(trans);
if (ret)
iput(inode);
if (ret && inode)
discard_new_inode(inode);
btrfs_btree_balance_dirty(fs_info);
return ret;

out_inode:
unlock_new_inode(inode);
goto out;

}

__attribute__((const))
Expand Down
29 changes: 1 addition & 28 deletions fs/dcache.c
Original file line number Diff line number Diff line change
Expand Up @@ -1889,40 +1889,13 @@ void d_instantiate_new(struct dentry *entry, struct inode *inode)
spin_lock(&inode->i_lock);
__d_instantiate(entry, inode);
WARN_ON(!(inode->i_state & I_NEW));
inode->i_state &= ~I_NEW;
inode->i_state &= ~I_NEW & ~I_CREATING;
smp_mb();
wake_up_bit(&inode->i_state, __I_NEW);
spin_unlock(&inode->i_lock);
}
EXPORT_SYMBOL(d_instantiate_new);

/**
* d_instantiate_no_diralias - instantiate a non-aliased dentry
* @entry: dentry to complete
* @inode: inode to attach to this dentry
*
* Fill in inode information in the entry. If a directory alias is found, then
* return an error (and drop inode). Together with d_materialise_unique() this
* guarantees that a directory inode may never have more than one alias.
*/
int d_instantiate_no_diralias(struct dentry *entry, struct inode *inode)
{
BUG_ON(!hlist_unhashed(&entry->d_u.d_alias));

security_d_instantiate(entry, inode);
spin_lock(&inode->i_lock);
if (S_ISDIR(inode->i_mode) && !hlist_empty(&inode->i_dentry)) {
spin_unlock(&inode->i_lock);
iput(inode);
return -EBUSY;
}
__d_instantiate(entry, inode);
spin_unlock(&inode->i_lock);

return 0;
}
EXPORT_SYMBOL(d_instantiate_no_diralias);

struct dentry *d_make_root(struct inode *root_inode)
{
struct dentry *res = NULL;
Expand Down
3 changes: 1 addition & 2 deletions fs/ext2/ialloc.c
Original file line number Diff line number Diff line change
Expand Up @@ -611,8 +611,7 @@ struct inode *ext2_new_inode(struct inode *dir, umode_t mode,
dquot_drop(inode);
inode->i_flags |= S_NOQUOTA;
clear_nlink(inode);
unlock_new_inode(inode);
iput(inode);
discard_new_inode(inode);
return ERR_PTR(err);

fail:
Expand Down
Loading

0 comments on commit 0ea97a2

Please sign in to comment.