Commit 0ea97a2d authored by Linus Torvalds's avatar Linus Torvalds

Merge branch 'work.mkdir' of git://git.kernel.org/pub/scm/linux/kernel/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
parents a66b4cd1 c7b15a86
...@@ -287,7 +287,7 @@ adfs_iget(struct super_block *sb, struct object_info *obj) ...@@ -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;
......
...@@ -291,6 +291,7 @@ static void destroy_inodecache(void) ...@@ -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,
......
...@@ -6335,8 +6335,10 @@ static struct inode *btrfs_new_inode(struct btrfs_trans_handle *trans, ...@@ -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, ...@@ -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, ...@@ -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, ...@@ -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, ...@@ -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, ...@@ -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, ...@@ -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, ...@@ -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) ...@@ -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) ...@@ -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, ...@@ -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, ...@@ -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, ...@@ -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, ...@@ -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, ...@@ -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) ...@@ -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) ...@@ -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))
......
...@@ -1889,40 +1889,13 @@ void d_instantiate_new(struct dentry *entry, struct inode *inode) ...@@ -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;
......
...@@ -611,8 +611,7 @@ struct inode *ext2_new_inode(struct inode *dir, umode_t mode, ...@@ -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:
......
...@@ -45,8 +45,7 @@ static inline int ext2_add_nondir(struct dentry *dentry, struct inode *inode) ...@@ -45,8 +45,7 @@ static inline int ext2_add_nondir(struct dentry *dentry, struct inode *inode)
return 0; return 0;
} }
inode_dec_link_count(inode); inode_dec_link_count(inode);
unlock_new_inode(inode); discard_new_inode(inode);
iput(inode);
return err; return err;
} }
...@@ -192,8 +191,7 @@ static int ext2_symlink (struct inode * dir, struct dentry * dentry, ...@@ -192,8 +191,7 @@ static int ext2_symlink (struct inode * dir, struct dentry * dentry,
out_fail: out_fail:
inode_dec_link_count(inode); inode_dec_link_count(inode);
unlock_new_inode(inode); discard_new_inode(inode);
iput (inode);
goto out; goto out;
} }
...@@ -261,8 +259,7 @@ static int ext2_mkdir(struct inode * dir, struct dentry * dentry, umode_t mode) ...@@ -261,8 +259,7 @@ static int ext2_mkdir(struct inode * dir, struct dentry * dentry, umode_t mode)
out_fail: out_fail:
inode_dec_link_count(inode); inode_dec_link_count(inode);
inode_dec_link_count(inode); inode_dec_link_count(inode);
unlock_new_inode(inode); discard_new_inode(inode);
iput(inode);
out_dir: out_dir:
inode_dec_link_count(dir); inode_dec_link_count(dir);
goto out; goto out;
......
...@@ -539,6 +539,7 @@ static int create_new_entry(struct fuse_conn *fc, struct fuse_args *args, ...@@ -539,6 +539,7 @@ static int create_new_entry(struct fuse_conn *fc, struct fuse_args *args,
{ {
struct fuse_entry_out outarg; struct fuse_entry_out outarg;
struct inode *inode; struct inode *inode;
struct dentry *d;
int err; int err;
struct fuse_forget_link *forget; struct fuse_forget_link *forget;
...@@ -570,11 +571,17 @@ static int create_new_entry(struct fuse_conn *fc, struct fuse_args *args, ...@@ -570,11 +571,17 @@ static int create_new_entry(struct fuse_conn *fc, struct fuse_args *args,
} }
kfree(forget); kfree(forget);
err = d_instantiate_no_diralias(entry, inode); d_drop(entry);
if (err) d = d_splice_alias(inode, entry);
return err; if (IS_ERR(d))
return PTR_ERR(d);
if (d) {
fuse_change_entry_timeout(d, &outarg);
dput(d);
} else {
fuse_change_entry_timeout(entry, &outarg); fuse_change_entry_timeout(entry, &outarg);
}
fuse_invalidate_attr(dir); fuse_invalidate_attr(dir);
return 0; return 0;
......
...@@ -541,7 +541,7 @@ static struct dentry *hfs_file_lookup(struct inode *dir, struct dentry *dentry, ...@@ -541,7 +541,7 @@ static struct dentry *hfs_file_lookup(struct inode *dir, struct dentry *dentry,
HFS_I(inode)->rsrc_inode = dir; HFS_I(inode)->rsrc_inode = dir;
HFS_I(dir)->rsrc_inode = inode; HFS_I(dir)->rsrc_inode = inode;
igrab(dir); igrab(dir);
hlist_add_fake(&inode->i_hash); inode_fake_hash(inode);
mark_inode_dirty(inode); mark_inode_dirty(inode);
dont_mount(dentry); dont_mount(dentry);
out: out:
......
...@@ -804,6 +804,10 @@ static struct inode *find_inode(struct super_block *sb, ...@@ -804,6 +804,10 @@ static struct inode *find_inode(struct super_block *sb,
__wait_on_freeing_inode(inode); __wait_on_freeing_inode(inode);
goto repeat; goto repeat;
} }
if (unlikely(inode->i_state & I_CREATING)) {
spin_unlock(&inode->i_lock);
return ERR_PTR(-ESTALE);
}
__iget(inode); __iget(inode);
spin_unlock(&inode->i_lock); spin_unlock(&inode->i_lock);
return inode; return inode;
...@@ -831,6 +835,10 @@ static struct inode *find_inode_fast(struct super_block *sb, ...@@ -831,6 +835,10 @@ static struct inode *find_inode_fast(struct super_block *sb,
__wait_on_freeing_inode(inode); __wait_on_freeing_inode(inode);
goto repeat; goto repeat;
} }
if (unlikely(inode->i_state & I_CREATING)) {
spin_unlock(&inode->i_lock);
return ERR_PTR(-ESTALE);
}
__iget(inode); __iget(inode);
spin_unlock(&inode->i_lock); spin_unlock(&inode->i_lock);
return inode; return inode;
...@@ -961,13 +969,26 @@ void unlock_new_inode(struct inode *inode) ...@@ -961,13 +969,26 @@ void unlock_new_inode(struct inode *inode)
lockdep_annotate_inode_mutex_key(inode); lockdep_annotate_inode_mutex_key(inode);
spin_lock(&inode->i_lock); spin_lock(&inode->i_lock);
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(unlock_new_inode); EXPORT_SYMBOL(unlock_new_inode);
void discard_new_inode(struct inode *inode)
{
lockdep_annotate_inode_mutex_key(inode);
spin_lock(&inode->i_lock);
WARN_ON(!(inode->i_state & I_NEW));
inode->i_state &= ~I_NEW;
smp_mb();
wake_up_bit(&inode->i_state, __I_NEW);
spin_unlock(&inode->i_lock);
iput(inode);
}
EXPORT_SYMBOL(discard_new_inode);
/** /**
* lock_two_nondirectories - take two i_mutexes on non-directory objects * lock_two_nondirectories - take two i_mutexes on non-directory objects
* *
...@@ -1029,6 +1050,7 @@ struct inode *inode_insert5(struct inode *inode, unsigned long hashval, ...@@ -1029,6 +1050,7 @@ struct inode *inode_insert5(struct inode *inode, unsigned long hashval,
{ {
struct hlist_head *head = inode_hashtable + hash(inode->i_sb, hashval); struct hlist_head *head = inode_hashtable + hash(inode->i_sb, hashval);
struct inode *old; struct inode *old;
bool creating = inode->i_state & I_CREATING;
again: again:
spin_lock(&inode_hash_lock); spin_lock(&inode_hash_lock);
...@@ -1039,6 +1061,8 @@ struct inode *inode_insert5(struct inode *inode, unsigned long hashval, ...@@ -1039,6 +1061,8 @@ struct inode *inode_insert5(struct inode *inode, unsigned long hashval,
* Use the old inode instead of the preallocated one. * Use the old inode instead of the preallocated one.
*/ */
spin_unlock(&inode_hash_lock); spin_unlock(&inode_hash_lock);
if (IS_ERR(old))
return NULL;
wait_on_inode(old); wait_on_inode(old);
if (unlikely(inode_unhashed(old))) { if (unlikely(inode_unhashed(old))) {
iput(old); iput(old);
...@@ -1060,6 +1084,8 @@ struct inode *inode_insert5(struct inode *inode, unsigned long hashval, ...@@ -1060,6 +1084,8 @@ struct inode *inode_insert5(struct inode *inode, unsigned long hashval,
inode->i_state |= I_NEW; inode->i_state |= I_NEW;
hlist_add_head(&inode->i_hash, head); hlist_add_head(&inode->i_hash, head);
spin_unlock(&inode->i_lock); spin_unlock(&inode->i_lock);
if (!creating)
inode_sb_list_add(inode);
unlock: unlock:
spin_unlock(&inode_hash_lock); spin_unlock(&inode_hash_lock);
...@@ -1094,12 +1120,13 @@ struct inode *iget5_locked(struct super_block *sb, unsigned long hashval, ...@@ -1094,12 +1120,13 @@ struct inode *iget5_locked(struct super_block *sb, unsigned long hashval,
struct inode *inode = ilookup5(sb, hashval, test, data); struct inode *inode = ilookup5(sb, hashval, test, data);
if (!inode) { if (!inode) {
struct inode *new = new_inode(sb); struct inode *new = alloc_inode(sb);
if (new) { if (new) {
new->i_state = 0;
inode = inode_insert5(new, hashval, test, set, data); inode = inode_insert5(new, hashval, test, set, data);
if (unlikely(inode != new)) if (unlikely(inode != new))
iput(new); destroy_inode(new);
} }
} }
return inode; return inode;
...@@ -1128,6 +1155,8 @@ struct inode *iget_locked(struct super_block *sb, unsigned long ino) ...@@ -1128,6 +1155,8 @@ struct inode *iget_locked(struct super_block *sb, unsigned long ino)
inode = find_inode_fast(sb, head, ino); inode = find_inode_fast(sb, head, ino);
spin_unlock(&inode_hash_lock); spin_unlock(&inode_hash_lock);
if (inode) { if (inode) {
if (IS_ERR(inode))
return NULL;
wait_on_inode(inode); wait_on_inode(inode);
if (unlikely(inode_unhashed(inode))) { if (unlikely(inode_unhashed(inode))) {
iput(inode); iput(inode);
...@@ -1165,6 +1194,8 @@ struct inode *iget_locked(struct super_block *sb, unsigned long ino) ...@@ -1165,6 +1194,8 @@ struct inode *iget_locked(struct super_block *sb, unsigned long ino)
*/ */
spin_unlock(&inode_hash_lock); spin_unlock(&inode_hash_lock);
destroy_inode(inode); destroy_inode(inode);
if (IS_ERR(old))
return NULL;
inode = old; inode = old;
wait_on_inode(inode); wait_on_inode(inode);
if (unlikely(inode_unhashed(inode))) { if (unlikely(inode_unhashed(inode))) {
...@@ -1282,7 +1313,7 @@ struct inode *ilookup5_nowait(struct super_block *sb, unsigned long hashval, ...@@ -1282,7 +1313,7 @@ struct inode *ilookup5_nowait(struct super_block *sb, unsigned long hashval,
inode = find_inode(sb, head, test, data); inode = find_inode(sb, head, test, data);
spin_unlock(&inode_hash_lock); spin_unlock(&inode_hash_lock);
return inode; return IS_ERR(inode) ? NULL : inode;
} }
EXPORT_SYMBOL(ilookup5_nowait); EXPORT_SYMBOL(ilookup5_nowait);
...@@ -1338,6 +1369,8 @@ struct inode *ilookup(struct super_block *sb, unsigned long ino) ...@@ -1338,6 +1369,8 @@ struct inode *ilookup(struct super_block *sb, unsigned long ino)
spin_unlock(&inode_hash_lock); spin_unlock(&inode_hash_lock);
if (inode) { if (inode) {
if (IS_ERR(inode))
return NULL;
wait_on_inode(inode); wait_on_inode(inode);
if (unlikely(inode_unhashed(inode))) { if (unlikely(inode_unhashed(inode))) {
iput(inode); iput(inode);
...@@ -1421,12 +1454,17 @@ int insert_inode_locked(struct inode *inode) ...@@ -1421,12 +1454,17 @@ int insert_inode_locked(struct inode *inode)
} }
if (likely(!old)) { if (likely(!old)) {
spin_lock(&inode->i_lock); spin_lock(&inode->i_lock);
inode->i_state |= I_NEW; inode->i_state |= I_NEW | I_CREATING;
hlist_add_head(&inode->i_hash, head); hlist_add_head(&inode->i_hash, head);
spin_unlock(&inode->i_lock); spin_unlock(&inode->i_lock);
spin_unlock(&inode_hash_lock); spin_unlock(&inode_hash_lock);
return 0; return 0;
} }
if (unlikely(old->i_state & I_CREATING)) {
spin_unlock(&old->i_lock);
spin_unlock(&inode_hash_lock);
return -EBUSY;
}
__iget(old); __iget(old);
spin_unlock(&old->i_lock); spin_unlock(&old->i_lock);
spin_unlock(&inode_hash_lock); spin_unlock(&inode_hash_lock);
...@@ -1443,7 +1481,10 @@ EXPORT_SYMBOL(insert_inode_locked); ...@@ -1443,7 +1481,10 @@ EXPORT_SYMBOL(insert_inode_locked);
int insert_inode_locked4(struct inode *inode, unsigned long hashval, int insert_inode_locked4(struct inode *inode, unsigned long hashval,
int (*test)(struct inode *, void *), void *data) int (*test)(struct inode *, void *), void *data)
{ {
struct inode *old = inode_insert5(inode, hashval, test, NULL, data); struct inode *old;
inode->i_state |= I_CREATING;
old = inode_insert5(inode, hashval, test, NULL, data);
if (old != inode) { if (old != inode) {
iput(old); iput(old);
......
...@@ -491,13 +491,7 @@ struct inode *diReadSpecial(struct super_block *sb, ino_t inum, int secondary) ...@@ -491,13 +491,7 @@ struct inode *diReadSpecial(struct super_block *sb, ino_t inum, int secondary)
/* release the page */ /* release the page */
release_metapage(mp); release_metapage(mp);
/* inode_fake_hash(ip);
* __mark_inode_dirty expects inodes to be hashed. Since we don't
* want special inodes in the fileset inode space, we make them
* appear hashed, but do not put on any lists. hlist_del()
* will work fine and require no locking.
*/
hlist_add_fake(&ip->i_hash);
return (ip); return (ip);
} }
......
...@@ -61,8 +61,7 @@ struct inode *ialloc(struct inode *parent, umode_t mode) ...@@ -61,8 +61,7 @@ struct inode *ialloc(struct inode *parent, umode_t mode)
inode = new_inode(sb); inode = new_inode(sb);
if (!inode) { if (!inode) {
jfs_warn("ialloc: new_inode returned NULL!"); jfs_warn("ialloc: new_inode returned NULL!");
rc = -ENOMEM; return ERR_PTR(-ENOMEM);
goto fail;
} }
jfs_inode = JFS_IP(inode); jfs_inode = JFS_IP(inode);
...@@ -70,8 +69,6 @@ struct inode *ialloc(struct inode *parent, umode_t mode) ...@@ -70,8 +69,6 @@ struct inode *ialloc(struct inode *parent, umode_t mode)
rc = diAlloc(parent, S_ISDIR(mode), inode); rc = diAlloc(parent, S_ISDIR(mode), inode);
if (rc) { if (rc) {
jfs_warn("ialloc: diAlloc returned %d!", rc); jfs_warn("ialloc: diAlloc returned %d!", rc);
if (rc == -EIO)
make_bad_inode(inode);
goto fail_put; goto fail_put;
} }
...@@ -141,9 +138,10 @@ struct inode *ialloc(struct inode *parent, umode_t mode) ...@@ -141,9 +138,10 @@ struct inode *ialloc(struct inode *parent, 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);
return ERR_PTR(rc);
fail_put: fail_put:
iput(inode); iput(inode);
fail:
return ERR_PTR(rc); return ERR_PTR(rc);
} }
...@@ -175,8 +175,7 @@ static int jfs_create(struct inode *dip, struct dentry *dentry, umode_t mode, ...@@ -175,8 +175,7 @@ static int jfs_create(struct inode *dip, struct dentry *dentry, umode_t mode,
if (rc) { if (rc) {
free_ea_wmap(ip); free_ea_wmap(ip);
clear_nlink(ip); clear_nlink(ip);
unlock_new_inode(ip); discard_new_inode(ip);
iput(ip);
} else { } else {
d_instantiate_new(dentry, ip); d_instantiate_new(dentry, ip);
} }
...@@ -309,8 +308,7 @@ static int jfs_mkdir(struct inode *dip, struct dentry *dentry, umode_t mode) ...@@ -309,8 +308,7 @@ static int jfs_mkdir(struct inode *dip, struct dentry *dentry, umode_t mode)
if (rc) { if (rc) {
free_ea_wmap(ip); free_ea_wmap(ip);
clear_nlink(ip); clear_nlink(ip);
unlock_new_inode(ip); discard_new_inode(ip);
iput(ip);
} else { } else {
d_instantiate_new(dentry, ip); d_instantiate_new(dentry, ip);
} }
...@@ -1054,8 +1052,7 @@ static int jfs_symlink(struct inode *dip, struct dentry *dentry, ...@@ -1054,8 +1052,7 @@ static int jfs_symlink(struct inode *dip, struct dentry *dentry,
if (rc) { if (rc) {
free_ea_wmap(ip); free_ea_wmap(ip);
clear_nlink(ip); clear_nlink(ip);
unlock_new_inode(ip); discard_new_inode(ip);
iput(ip);
} else { } else {
d_instantiate_new(dentry, ip); d_instantiate_new(dentry, ip);
} }
...@@ -1441,8 +1438,7 @@ static int jfs_mknod(struct inode *dir, struct dentry *dentry, ...@@ -1441,8 +1438,7 @@ static int jfs_mknod(struct inode *dir, struct dentry *dentry,
if (rc) { if (rc) {
free_ea_wmap(ip); free_ea_wmap(ip);
clear_nlink(ip); clear_nlink(ip);
unlock_new_inode(ip); discard_new_inode(ip);
iput(ip);
} else { } else {
d_instantiate_new(dentry, ip); d_instantiate_new(dentry, ip);
} }
......
...@@ -581,7 +581,7 @@ static int jfs_fill_super(struct super_block *sb, void *data, int silent) ...@@ -581,7 +581,7 @@ static int jfs_fill_super(struct super_block *sb, void *data, int silent)
inode->i_ino = 0; inode->i_ino = 0;
inode->i_size = i_size_read(sb->s_bdev->bd_inode); inode->i_size = i_size_read(sb->s_bdev->bd_inode);
inode->i_mapping->a_ops = &jfs_metapage_aops; inode->i_mapping->a_ops = &jfs_metapage_aops;
hlist_add_fake(&inode->i_hash); inode_fake_hash(inode);
mapping_set_gfp_mask(inode->i_mapping, GFP_NOFS); mapping_set_gfp_mask(inode->i_mapping, GFP_NOFS);
sbi->direct_inode = inode; sbi->direct_inode = inode;
......
...@@ -1643,6 +1643,7 @@ int nfs_instantiate(struct dentry *dentry, struct nfs_fh *fhandle, ...@@ -1643,6 +1643,7 @@ int nfs_instantiate(struct dentry *dentry, struct nfs_fh *fhandle,
struct dentry *parent = dget_parent(dentry); struct dentry *parent = dget_parent(dentry);
struct inode *dir = d_inode(parent); struct inode *dir = d_inode(parent);
struct inode *inode; struct inode *inode;
struct dentry *d;
int error = -EACCES; int error = -EACCES;
d_drop(dentry); d_drop(dentry);
...@@ -1664,10 +1665,12 @@ int nfs_instantiate(struct dentry *dentry, struct nfs_fh *fhandle, ...@@ -1664,10 +1665,12 @@ int nfs_instantiate(struct dentry *dentry, struct nfs_fh *fhandle,
goto out_error; goto out_error;
} }
inode = nfs_fhget(dentry->d_sb, fhandle, fattr, label); inode = nfs_fhget(dentry->d_sb, fhandle, fattr, label);
error = PTR_ERR(inode); d = d_splice_alias(inode, dentry);
if (IS_ERR(inode)) if (IS_ERR(d)) {
error = PTR_ERR(d);
goto out_error; goto out_error;
d_add(dentry, inode); }
dput(d);
out: out:
dput(parent); dput(parent);
return 0; return 0;
......
...@@ -602,8 +602,7 @@ static int udf_add_nondir(struct dentry *dentry, struct inode *inode) ...@@ -602,8 +602,7 @@ static int udf_add_nondir(struct dentry *dentry, struct inode *inode)
fi = udf_add_entry(dir, dentry, &fibh, &cfi, &err); fi = udf_add_entry(dir, dentry, &fibh, &cfi, &err);
if (unlikely(!fi)) { if (unlikely(!fi)) {
inode_dec_link_count(inode); inode_dec_link_count(inode);
unlock_new_inode(inode); discard_new_inode(inode);
iput(inode);
return err; return err;
} }
cfi.icb.extLength = cpu_to_le32(inode->i_sb->s_blocksize); cfi.icb.extLength = cpu_to_le32(inode->i_sb->s_blocksize);
...@@ -694,8 +693,7 @@ static int udf_mkdir(struct inode *dir, struct dentry *dentry, umode_t mode) ...@@ -694,8 +693,7 @@ static int udf_mkdir(struct inode *dir, struct dentry *dentry, umode_t mode)
fi = udf_add_entry(inode, NULL, &fibh, &cfi, &err); fi = udf_add_entry(inode, NULL, &fibh, &cfi, &err);
if (!fi) { if (!fi) {
inode_dec_link_count(inode); inode_dec_link_count(inode);
unlock_new_inode(inode); discard_new_inode(inode);
iput(inode);
goto out; goto out;
} }
set_nlink(inode, 2); set_nlink(inode, 2);
...@@ -713,8 +711,7 @@ static int udf_mkdir(struct inode *dir, struct dentry *dentry, umode_t mode) ...@@ -713,8 +711,7 @@ static int udf_mkdir(struct inode *dir, struct dentry *dentry, umode_t mode)
if (!fi) { if (!fi) {
clear_nlink(inode); clear_nlink(inode);
mark_inode_dirty(inode); mark_inode_dirty(inode);
unlock_new_inode(inode); discard_new_inode(inode);
iput(inode);
goto out; goto out;
} }
cfi.icb.extLength = cpu_to_le32(inode->i_sb->s_blocksize); cfi.icb.extLength = cpu_to_le32(inode->i_sb->s_blocksize);
...@@ -1041,8 +1038,7 @@ static int udf_symlink(struct inode *dir, struct dentry *dentry, ...@@ -1041,8 +1038,7 @@ static int udf_symlink(struct inode *dir, struct dentry *dentry,
out_no_entry: out_no_entry:
up_write(&iinfo->i_data_sem); up_write(&iinfo->i_data_sem);
inode_dec_link_count(inode); inode_dec_link_count(inode);
unlock_new_inode(inode); discard_new_inode(inode);
iput(inode);
goto out; goto out;
} }
......
...@@ -343,8 +343,7 @@ struct inode *ufs_new_inode(struct inode *dir, umode_t mode) ...@@ -343,8 +343,7 @@ struct inode *ufs_new_inode(struct inode *dir, umode_t mode)
fail_remove_inode: fail_remove_inode:
mutex_unlock(&sbi->s_lock); mutex_unlock(&sbi->s_lock);
clear_nlink(inode); clear_nlink(inode);
unlock_new_inode(inode); discard_new_inode(inode);
iput(inode);
UFSD("EXIT (FAILED): err %d\n", err); UFSD("EXIT (FAILED): err %d\n", err);
return ERR_PTR(err); return ERR_PTR(err);
failed: failed:
......
...@@ -43,8 +43,7 @@ static inline int ufs_add_nondir(struct dentry *dentry, struct inode *inode) ...@@ -43,8 +43,7 @@ static inline int ufs_add_nondir(struct dentry *dentry, struct inode *inode)
return 0; return 0;
} }
inode_dec_link_count(inode); inode_dec_link_count(inode);
unlock_new_inode(inode); discard_new_inode(inode);
iput(inode);
return err; return err;
} }
...@@ -142,8 +141,7 @@ static int ufs_symlink (struct inode * dir, struct dentry * dentry, ...@@ -142,8 +141,7 @@ static int ufs_symlink (struct inode * dir, struct dentry * dentry,
out_fail: out_fail:
inode_dec_link_count(inode); inode_dec_link_count(inode);
unlock_new_inode(inode); discard_new_inode(inode);
iput(inode);
return err; return err;
} }
...@@ -198,8 +196,7 @@ static int ufs_mkdir(struct inode * dir, struct dentry * dentry, umode_t mode) ...@@ -198,8 +196,7 @@ static int ufs_mkdir(struct inode * dir, struct dentry * dentry, umode_t mode)
out_fail: out_fail:
inode_dec_link_count(inode); inode_dec_link_count(inode);
inode_dec_link_count(inode); inode_dec_link_count(inode);
unlock_new_inode(inode); discard_new_inode(inode);
iput (inode);
out_dir: out_dir:
inode_dec_link_count(dir); inode_dec_link_count(dir);
return err; return err;
......
...@@ -1253,7 +1253,7 @@ xfs_setup_inode( ...@@ -1253,7 +1253,7 @@ xfs_setup_inode(
inode_sb_list_add(inode); inode_sb_list_add(inode);
/* make the inode look hashed for the writeback code */ /* make the inode look hashed for the writeback code */
hlist_add_fake(&inode->i_hash); inode_fake_hash(inode);
inode->i_uid = xfs_uid_to_kuid(ip->i_d.di_uid); inode->i_uid = xfs_uid_to_kuid(ip->i_d.di_uid);
inode->i_gid = xfs_gid_to_kgid(ip->i_d.di_gid); inode->i_gid = xfs_gid_to_kgid(ip->i_d.di_gid);
......
...@@ -227,7 +227,6 @@ extern void d_instantiate(struct dentry *, struct inode *); ...@@ -227,7 +227,6 @@ extern void d_instantiate(struct dentry *, struct inode *);
extern void d_instantiate_new(struct dentry *, struct inode *); extern void d_instantiate_new(struct dentry *, struct inode *);
extern struct dentry * d_instantiate_unique(struct dentry *, struct inode *); extern struct dentry * d_instantiate_unique(struct dentry *, struct inode *);
extern struct dentry * d_instantiate_anon(struct dentry *, struct inode *); extern struct dentry * d_instantiate_anon(struct dentry *, struct inode *);
extern int d_instantiate_no_diralias(struct dentry *, struct inode *);
extern void __d_drop(struct dentry *dentry); extern void __d_drop(struct dentry *dentry);
extern void d_drop(struct dentry *dentry); extern void d_drop(struct dentry *dentry);
extern void d_delete(struct dentry *); extern void d_delete(struct dentry *);
......
...@@ -687,6 +687,17 @@ static inline int inode_unhashed(struct inode *inode) ...@@ -687,6 +687,17 @@ static inline int inode_unhashed(struct inode *inode)
return hlist_unhashed(&inode->i_hash); return hlist_unhashed(&inode->i_hash);
} }
/*
* __mark_inode_dirty expects inodes to be hashed. Since we don't
* want special inodes in the fileset inode space, we make them
* appear hashed, but do not put on any lists. hlist_del()
* will work fine and require no locking.
*/
static inline void inode_fake_hash(struct inode *inode)
{
hlist_add_fake(&inode->i_hash);
}
/* /*
* inode->i_mutex nesting subclasses for the lock validator: * inode->i_mutex nesting subclasses for the lock validator:
* *
...@@ -2017,6 +2028,8 @@ static inline void init_sync_kiocb(struct kiocb *kiocb, struct file *filp) ...@@ -2017,6 +2028,8 @@ static inline void init_sync_kiocb(struct kiocb *kiocb, struct file *filp)
* I_OVL_INUSE Used by overlayfs to get exclusive ownership on upper * I_OVL_INUSE Used by overlayfs to get exclusive ownership on upper
* and work dirs among overlayfs mounts. * and work dirs among overlayfs mounts.
* *
* I_CREATING New object's inode in the middle of setting up.
*
* Q: What is the difference between I_WILL_FREE and I_FREEING? * Q: What is the difference between I_WILL_FREE and I_FREEING?
*/ */
#define I_DIRTY_SYNC (1 << 0) #define I_DIRTY_SYNC (1 << 0)
...@@ -2038,6 +2051,7 @@ static inline void init_sync_kiocb(struct kiocb *kiocb, struct file *filp) ...@@ -2038,6 +2051,7 @@ static inline void init_sync_kiocb(struct kiocb *kiocb, struct file *filp)
#define I_DIRTY_TIME_EXPIRED (1 << __I_DIRTY_TIME_EXPIRED) #define I_DIRTY_TIME_EXPIRED (1 << __I_DIRTY_TIME_EXPIRED)
#define I_WB_SWITCH (1 << 13) #define I_WB_SWITCH (1 << 13)
#define I_OVL_INUSE (1 << 14) #define I_OVL_INUSE (1 << 14)
#define I_CREATING (1 << 15)
#define I_DIRTY_INODE (I_DIRTY_SYNC | I_DIRTY_DATASYNC) #define I_DIRTY_INODE (I_DIRTY_SYNC | I_DIRTY_DATASYNC)
#define I_DIRTY (I_DIRTY_INODE | I_DIRTY_PAGES) #define I_DIRTY (I_DIRTY_INODE | I_DIRTY_PAGES)
...@@ -2919,6 +2933,7 @@ extern void lockdep_annotate_inode_mutex_key(struct inode *inode); ...@@ -2919,6 +2933,7 @@ extern void lockdep_annotate_inode_mutex_key(struct inode *inode);
static inline void lockdep_annotate_inode_mutex_key(struct inode *inode) { }; static inline void lockdep_annotate_inode_mutex_key(struct inode *inode) { };
#endif #endif
extern void unlock_new_inode(struct inode *); extern void unlock_new_inode(struct inode *);
extern void discard_new_inode(struct inode *);
extern unsigned int get_next_ino(void); extern unsigned int get_next_ino(void);
extern void evict_inodes(struct super_block *sb); extern void evict_inodes(struct super_block *sb);
......
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