aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAl Viro <viro@zeniv.linux.org.uk>2016-05-29 20:13:30 -0400
committerAl Viro <viro@zeniv.linux.org.uk>2016-05-29 20:28:22 -0400
commit550dce01dd606c88a837138aa448ccd367fb0cbb (patch)
treee6cc564fc18e012ed2bdd76ee5e5d0785c310c50
parentea7d4c046ba6e2c6135c98721f4f09efd1adaabc (diff)
unify dentry_iput() and dentry_unlink_inode()
There is a lot of duplication between dentry_unlink_inode() and dentry_iput(). The only real difference is that dentry_unlink_inode() bumps ->d_seq and dentry_iput() doesn't. The argument of the latter is known to have been unhashed, so anybody who might've found it in RCU lookup would already be doomed to a ->d_seq mismatch. And we want to avoid pointless smp_rmb() there. This patch makes dentry_unlink_inode() bump ->d_seq only for hashed dentries. It's safe (d_delete() calls that sucker only if we are holding the only reference to dentry, so rehash is not going to happen) and it allows to use dentry_unlink_inode() in __dentry_kill() and get rid of dentry_iput(). The interesting question here is profiling; it *is* a hot path, and extra conditional jumps in there might or might not be painful. Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
-rw-r--r--fs/dcache.c45
1 files changed, 10 insertions, 35 deletions
diff --git a/fs/dcache.c b/fs/dcache.c
index f9c63c108881..fe7cde2f2fe5 100644
--- a/fs/dcache.c
+++ b/fs/dcache.c
@@ -335,44 +335,21 @@ static inline void dentry_rcuwalk_invalidate(struct dentry *dentry)
335 335
336/* 336/*
337 * Release the dentry's inode, using the filesystem 337 * Release the dentry's inode, using the filesystem
338 * d_iput() operation if defined. Dentry has no refcount 338 * d_iput() operation if defined.
339 * and is unhashed.
340 */
341static void dentry_iput(struct dentry * dentry)
342 __releases(dentry->d_lock)
343 __releases(dentry->d_inode->i_lock)
344{
345 struct inode *inode = dentry->d_inode;
346 if (inode) {
347 __d_clear_type_and_inode(dentry);
348 hlist_del_init(&dentry->d_u.d_alias);
349 spin_unlock(&dentry->d_lock);
350 spin_unlock(&inode->i_lock);
351 if (!inode->i_nlink)
352 fsnotify_inoderemove(inode);
353 if (dentry->d_op && dentry->d_op->d_iput)
354 dentry->d_op->d_iput(dentry, inode);
355 else
356 iput(inode);
357 } else {
358 spin_unlock(&dentry->d_lock);
359 }
360}
361
362/*
363 * Release the dentry's inode, using the filesystem
364 * d_iput() operation if defined. dentry remains in-use.
365 */ 339 */
366static void dentry_unlink_inode(struct dentry * dentry) 340static void dentry_unlink_inode(struct dentry * dentry)
367 __releases(dentry->d_lock) 341 __releases(dentry->d_lock)
368 __releases(dentry->d_inode->i_lock) 342 __releases(dentry->d_inode->i_lock)
369{ 343{
370 struct inode *inode = dentry->d_inode; 344 struct inode *inode = dentry->d_inode;
345 bool hashed = !d_unhashed(dentry);
371 346
372 raw_write_seqcount_begin(&dentry->d_seq); 347 if (hashed)
348 raw_write_seqcount_begin(&dentry->d_seq);
373 __d_clear_type_and_inode(dentry); 349 __d_clear_type_and_inode(dentry);
374 hlist_del_init(&dentry->d_u.d_alias); 350 hlist_del_init(&dentry->d_u.d_alias);
375 raw_write_seqcount_end(&dentry->d_seq); 351 if (hashed)
352 raw_write_seqcount_end(&dentry->d_seq);
376 spin_unlock(&dentry->d_lock); 353 spin_unlock(&dentry->d_lock);
377 spin_unlock(&inode->i_lock); 354 spin_unlock(&inode->i_lock);
378 if (!inode->i_nlink) 355 if (!inode->i_nlink)
@@ -540,12 +517,10 @@ static void __dentry_kill(struct dentry *dentry)
540 dentry->d_flags |= DCACHE_DENTRY_KILLED; 517 dentry->d_flags |= DCACHE_DENTRY_KILLED;
541 if (parent) 518 if (parent)
542 spin_unlock(&parent->d_lock); 519 spin_unlock(&parent->d_lock);
543 dentry_iput(dentry); 520 if (dentry->d_inode)
544 /* 521 dentry_unlink_inode(dentry);
545 * dentry_iput drops the locks, at which point nobody (except 522 else
546 * transient RCU lookups) can reach this dentry. 523 spin_unlock(&dentry->d_lock);
547 */
548 BUG_ON(dentry->d_lockref.count > 0);
549 this_cpu_dec(nr_dentry); 524 this_cpu_dec(nr_dentry);
550 if (dentry->d_op && dentry->d_op->d_release) 525 if (dentry->d_op && dentry->d_op->d_release)
551 dentry->d_op->d_release(dentry); 526 dentry->d_op->d_release(dentry);