diff options
author | Al Viro <viro@zeniv.linux.org.uk> | 2018-06-28 15:53:17 -0400 |
---|---|---|
committer | Al Viro <viro@zeniv.linux.org.uk> | 2018-08-03 15:55:30 -0400 |
commit | c2b6d621c4ffe9936adf7a55c8b1c769672c306f (patch) | |
tree | d13dbb52a33dd594a78b8996132c7e7bba6f296f /fs/dcache.c | |
parent | c971e6a006175bd0f195c6346c4e8bc4089bec00 (diff) | |
download | linux-c2b6d621c4ffe9936adf7a55c8b1c769672c306f.tar.bz2 |
new primitive: discard_new_inode()
We don't want open-by-handle picking half-set-up in-core
struct inode from e.g. mkdir() having failed halfway through.
In other words, we don't want such inodes returned by iget_locked()
on their way to extinction. However, we can't just have them
unhashed - otherwise open-by-handle immediately *after* that would've
ended up creating a new in-core inode over the on-disk one that
is in process of being freed right under us.
Solution: new flag (I_CREATING) set by insert_inode_locked() and
removed by unlock_new_inode() and a new primitive (discard_new_inode())
to be used by such halfway-through-setup failure exits instead of
unlock_new_inode() / iput() combinations. That primitive unlocks new
inode, but leaves I_CREATING in place.
iget_locked() treats finding an I_CREATING inode as failure
(-ESTALE, once we sort out the error propagation).
insert_inode_locked() treats the same as instant -EBUSY.
ilookup() treats those as icache miss.
[Fix by Dan Carpenter <dan.carpenter@oracle.com> folded in]
Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
Diffstat (limited to 'fs/dcache.c')
-rw-r--r-- | fs/dcache.c | 2 |
1 files changed, 1 insertions, 1 deletions
diff --git a/fs/dcache.c b/fs/dcache.c index a7d9e7a4c283..11b753d29409 100644 --- a/fs/dcache.c +++ b/fs/dcache.c @@ -1892,7 +1892,7 @@ 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); |