Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 0ea97a2d authored by Linus Torvalds's avatar Linus Torvalds
Browse files
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
parents a66b4cd1 c7b15a86
Loading
Loading
Loading
Loading
+1 −1
Original line number Original line Diff line number Diff line
@@ -287,7 +287,7 @@ adfs_iget(struct super_block *sb, struct object_info *obj)
		ADFS_I(inode)->mmu_private = inode->i_size;
		ADFS_I(inode)->mmu_private = inode->i_size;
	}
	}


	insert_inode_hash(inode);
	inode_fake_hash(inode);


out:
out:
	return inode;
	return inode;
+1 −0
Original line number Original line Diff line number Diff line
@@ -291,6 +291,7 @@ static void destroy_inodecache(void)
static const struct super_operations adfs_sops = {
static const struct super_operations adfs_sops = {
	.alloc_inode	= adfs_alloc_inode,
	.alloc_inode	= adfs_alloc_inode,
	.destroy_inode	= adfs_destroy_inode,
	.destroy_inode	= adfs_destroy_inode,
	.drop_inode	= generic_delete_inode,
	.write_inode	= adfs_write_inode,
	.write_inode	= adfs_write_inode,
	.put_super	= adfs_put_super,
	.put_super	= adfs_put_super,
	.statfs		= adfs_statfs,
	.statfs		= adfs_statfs,
+39 −67
Original line number Original line Diff line number Diff line
@@ -6335,8 +6335,10 @@ static struct inode *btrfs_new_inode(struct btrfs_trans_handle *trans,
	location->type = BTRFS_INODE_ITEM_KEY;
	location->type = BTRFS_INODE_ITEM_KEY;


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


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


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


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


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


@@ -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);
	err = btrfs_init_inode_security(trans, inode, dir, &dentry->d_name);
	if (err)
	if (err)
		goto out_unlock_inode;
		goto out_unlock;


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

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


out_unlock:
out_unlock:
	btrfs_end_transaction(trans);
	btrfs_end_transaction(trans);
	btrfs_btree_balance_dirty(fs_info);
	btrfs_btree_balance_dirty(fs_info);
	if (drop_inode) {
	if (err && inode) {
		inode_dec_link_count(inode);
		inode_dec_link_count(inode);
		iput(inode);
		discard_new_inode(inode);
	}
	}
	return err;
	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,
static int btrfs_create(struct inode *dir, struct dentry *dentry,
@@ -6575,7 +6569,6 @@ static int btrfs_create(struct inode *dir, struct dentry *dentry,
	struct btrfs_trans_handle *trans;
	struct btrfs_trans_handle *trans;
	struct btrfs_root *root = BTRFS_I(dir)->root;
	struct btrfs_root *root = BTRFS_I(dir)->root;
	struct inode *inode = NULL;
	struct inode *inode = NULL;
	int drop_inode_on_err = 0;
	int err;
	int err;
	u64 objectid;
	u64 objectid;
	u64 index = 0;
	u64 index = 0;
@@ -6598,9 +6591,9 @@ static int btrfs_create(struct inode *dir, struct dentry *dentry,
			mode, &index);
			mode, &index);
	if (IS_ERR(inode)) {
	if (IS_ERR(inode)) {
		err = PTR_ERR(inode);
		err = PTR_ERR(inode);
		inode = NULL;
		goto out_unlock;
		goto out_unlock;
	}
	}
	drop_inode_on_err = 1;
	/*
	/*
	* If the active LSM wants to access the inode during
	* If the active LSM wants to access the inode during
	* d_instantiate it needs these. Smack checks to see
	* d_instantiate it needs these. Smack checks to see
@@ -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);
	err = btrfs_init_inode_security(trans, inode, dir, &dentry->d_name);
	if (err)
	if (err)
		goto out_unlock_inode;
		goto out_unlock;


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


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


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


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

out_unlock_inode:
	unlock_new_inode(inode);
	goto out_unlock;

}
}


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


@@ -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);
	err = btrfs_init_inode_security(trans, inode, dir, &dentry->d_name);
	if (err)
	if (err)
		goto out_fail_inode;
		goto out_fail;


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


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


	d_instantiate_new(dentry, inode);
	d_instantiate_new(dentry, inode);
	drop_on_err = 0;
	drop_on_err = 0;


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

out_fail_inode:
	unlock_new_inode(inode);
	goto out_fail;
}
}


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


@@ -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);
	err = btrfs_init_inode_security(trans, inode, dir, &dentry->d_name);
	if (err)
	if (err)
		goto out_unlock_inode;
		goto out_unlock;


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


	d_instantiate_new(dentry, inode);
	d_instantiate_new(dentry, inode);


out_unlock:
out_unlock:
	btrfs_end_transaction(trans);
	btrfs_end_transaction(trans);
	if (drop_inode) {
	if (err && inode) {
		inode_dec_link_count(inode);
		inode_dec_link_count(inode);
		iput(inode);
		discard_new_inode(inode);
	}
	}
	btrfs_btree_balance_dirty(fs_info);
	btrfs_btree_balance_dirty(fs_info);
	return err;
	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,
static int __btrfs_prealloc_file_range(struct inode *inode, int mode,
@@ -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);
	ret = btrfs_init_inode_security(trans, inode, dir, NULL);
	if (ret)
	if (ret)
		goto out_inode;
		goto out;


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


	/*
	/*
	 * We set number of links to 0 in btrfs_new_inode(), and here we set
	 * We set number of links to 0 in btrfs_new_inode(), and here we set
@@ -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()
	 *    d_tmpfile() -> inode_dec_link_count() -> drop_nlink()
	 */
	 */
	set_nlink(inode, 1);
	set_nlink(inode, 1);
	unlock_new_inode(inode);
	d_tmpfile(dentry, inode);
	d_tmpfile(dentry, inode);
	unlock_new_inode(inode);
	mark_inode_dirty(inode);
	mark_inode_dirty(inode);

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

out_inode:
	unlock_new_inode(inode);
	goto out;

}
}


__attribute__((const))
__attribute__((const))
+1 −28
Original line number Original line Diff line number Diff line
@@ -1889,40 +1889,13 @@ void d_instantiate_new(struct dentry *entry, struct inode *inode)
	spin_lock(&inode->i_lock);
	spin_lock(&inode->i_lock);
	__d_instantiate(entry, inode);
	__d_instantiate(entry, inode);
	WARN_ON(!(inode->i_state & I_NEW));
	WARN_ON(!(inode->i_state & I_NEW));
	inode->i_state &= ~I_NEW;
	inode->i_state &= ~I_NEW & ~I_CREATING;
	smp_mb();
	smp_mb();
	wake_up_bit(&inode->i_state, __I_NEW);
	wake_up_bit(&inode->i_state, __I_NEW);
	spin_unlock(&inode->i_lock);
	spin_unlock(&inode->i_lock);
}
}
EXPORT_SYMBOL(d_instantiate_new);
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 *d_make_root(struct inode *root_inode)
{
{
	struct dentry *res = NULL;
	struct dentry *res = NULL;
+1 −2
Original line number Original line Diff line number Diff line
@@ -611,8 +611,7 @@ struct inode *ext2_new_inode(struct inode *dir, umode_t mode,
	dquot_drop(inode);
	dquot_drop(inode);
	inode->i_flags |= S_NOQUOTA;
	inode->i_flags |= S_NOQUOTA;
	clear_nlink(inode);
	clear_nlink(inode);
	unlock_new_inode(inode);
	discard_new_inode(inode);
	iput(inode);
	return ERR_PTR(err);
	return ERR_PTR(err);


fail:
fail:
Loading