aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorNick Piggin <npiggin@kernel.dk>2011-01-07 01:49:32 -0500
committerNick Piggin <npiggin@kernel.dk>2011-01-07 01:50:21 -0500
commitb7ab39f631f505edc2bbdb86620d5493f995c9da (patch)
tree62be97ebc7fc69ceb601f23312d335ebb8038ee7
parent2304450783dfde7b0b94ae234edd0dbffa865073 (diff)
fs: dcache scale dentry refcount
Make d_count non-atomic and protect it with d_lock. This allows us to ensure a 0 refcount dentry remains 0 without dcache_lock. It is also fairly natural when we start protecting many other dentry members with d_lock. Signed-off-by: Nick Piggin <npiggin@kernel.dk>
-rw-r--r--arch/powerpc/platforms/cell/spufs/inode.c2
-rw-r--r--drivers/infiniband/hw/ipath/ipath_fs.c2
-rw-r--r--drivers/infiniband/hw/qib/qib_fs.c2
-rw-r--r--fs/autofs4/expire.c8
-rw-r--r--fs/autofs4/root.c6
-rw-r--r--fs/ceph/dir.c4
-rw-r--r--fs/ceph/inode.c4
-rw-r--r--fs/ceph/mds_client.c2
-rw-r--r--fs/coda/dir.c2
-rw-r--r--fs/configfs/dir.c3
-rw-r--r--fs/configfs/inode.c2
-rw-r--r--fs/dcache.c106
-rw-r--r--fs/ecryptfs/inode.c2
-rw-r--r--fs/locks.c2
-rw-r--r--fs/namei.c2
-rw-r--r--fs/nfs/dir.c6
-rw-r--r--fs/nfs/unlink.c2
-rw-r--r--fs/nfsd/vfs.c5
-rw-r--r--fs/nilfs2/super.c2
-rw-r--r--include/linux/dcache.h29
-rw-r--r--kernel/cgroup.c2
21 files changed, 126 insertions, 69 deletions
diff --git a/arch/powerpc/platforms/cell/spufs/inode.c b/arch/powerpc/platforms/cell/spufs/inode.c
index 3532b92de98..29a406a7754 100644
--- a/arch/powerpc/platforms/cell/spufs/inode.c
+++ b/arch/powerpc/platforms/cell/spufs/inode.c
@@ -162,7 +162,7 @@ static void spufs_prune_dir(struct dentry *dir)
162 spin_lock(&dcache_lock); 162 spin_lock(&dcache_lock);
163 spin_lock(&dentry->d_lock); 163 spin_lock(&dentry->d_lock);
164 if (!(d_unhashed(dentry)) && dentry->d_inode) { 164 if (!(d_unhashed(dentry)) && dentry->d_inode) {
165 dget_locked(dentry); 165 dget_locked_dlock(dentry);
166 __d_drop(dentry); 166 __d_drop(dentry);
167 spin_unlock(&dentry->d_lock); 167 spin_unlock(&dentry->d_lock);
168 simple_unlink(dir->d_inode, dentry); 168 simple_unlink(dir->d_inode, dentry);
diff --git a/drivers/infiniband/hw/ipath/ipath_fs.c b/drivers/infiniband/hw/ipath/ipath_fs.c
index 8c8afc716b9..18aee04a841 100644
--- a/drivers/infiniband/hw/ipath/ipath_fs.c
+++ b/drivers/infiniband/hw/ipath/ipath_fs.c
@@ -280,7 +280,7 @@ static int remove_file(struct dentry *parent, char *name)
280 spin_lock(&dcache_lock); 280 spin_lock(&dcache_lock);
281 spin_lock(&tmp->d_lock); 281 spin_lock(&tmp->d_lock);
282 if (!(d_unhashed(tmp) && tmp->d_inode)) { 282 if (!(d_unhashed(tmp) && tmp->d_inode)) {
283 dget_locked(tmp); 283 dget_locked_dlock(tmp);
284 __d_drop(tmp); 284 __d_drop(tmp);
285 spin_unlock(&tmp->d_lock); 285 spin_unlock(&tmp->d_lock);
286 spin_unlock(&dcache_lock); 286 spin_unlock(&dcache_lock);
diff --git a/drivers/infiniband/hw/qib/qib_fs.c b/drivers/infiniband/hw/qib/qib_fs.c
index f99bddc0171..fe4b242f009 100644
--- a/drivers/infiniband/hw/qib/qib_fs.c
+++ b/drivers/infiniband/hw/qib/qib_fs.c
@@ -456,7 +456,7 @@ static int remove_file(struct dentry *parent, char *name)
456 spin_lock(&dcache_lock); 456 spin_lock(&dcache_lock);
457 spin_lock(&tmp->d_lock); 457 spin_lock(&tmp->d_lock);
458 if (!(d_unhashed(tmp) && tmp->d_inode)) { 458 if (!(d_unhashed(tmp) && tmp->d_inode)) {
459 dget_locked(tmp); 459 dget_locked_dlock(tmp);
460 __d_drop(tmp); 460 __d_drop(tmp);
461 spin_unlock(&tmp->d_lock); 461 spin_unlock(&tmp->d_lock);
462 spin_unlock(&dcache_lock); 462 spin_unlock(&dcache_lock);
diff --git a/fs/autofs4/expire.c b/fs/autofs4/expire.c
index a796c9417fb..413b5642e6c 100644
--- a/fs/autofs4/expire.c
+++ b/fs/autofs4/expire.c
@@ -198,7 +198,7 @@ static int autofs4_tree_busy(struct vfsmount *mnt,
198 else 198 else
199 ino_count++; 199 ino_count++;
200 200
201 if (atomic_read(&p->d_count) > ino_count) { 201 if (p->d_count > ino_count) {
202 top_ino->last_used = jiffies; 202 top_ino->last_used = jiffies;
203 dput(p); 203 dput(p);
204 return 1; 204 return 1;
@@ -347,7 +347,7 @@ struct dentry *autofs4_expire_indirect(struct super_block *sb,
347 347
348 /* Path walk currently on this dentry? */ 348 /* Path walk currently on this dentry? */
349 ino_count = atomic_read(&ino->count) + 2; 349 ino_count = atomic_read(&ino->count) + 2;
350 if (atomic_read(&dentry->d_count) > ino_count) 350 if (dentry->d_count > ino_count)
351 goto next; 351 goto next;
352 352
353 /* Can we umount this guy */ 353 /* Can we umount this guy */
@@ -369,7 +369,7 @@ struct dentry *autofs4_expire_indirect(struct super_block *sb,
369 if (!exp_leaves) { 369 if (!exp_leaves) {
370 /* Path walk currently on this dentry? */ 370 /* Path walk currently on this dentry? */
371 ino_count = atomic_read(&ino->count) + 1; 371 ino_count = atomic_read(&ino->count) + 1;
372 if (atomic_read(&dentry->d_count) > ino_count) 372 if (dentry->d_count > ino_count)
373 goto next; 373 goto next;
374 374
375 if (!autofs4_tree_busy(mnt, dentry, timeout, do_now)) { 375 if (!autofs4_tree_busy(mnt, dentry, timeout, do_now)) {
@@ -383,7 +383,7 @@ struct dentry *autofs4_expire_indirect(struct super_block *sb,
383 } else { 383 } else {
384 /* Path walk currently on this dentry? */ 384 /* Path walk currently on this dentry? */
385 ino_count = atomic_read(&ino->count) + 1; 385 ino_count = atomic_read(&ino->count) + 1;
386 if (atomic_read(&dentry->d_count) > ino_count) 386 if (dentry->d_count > ino_count)
387 goto next; 387 goto next;
388 388
389 expired = autofs4_check_leaves(mnt, dentry, timeout, do_now); 389 expired = autofs4_check_leaves(mnt, dentry, timeout, do_now);
diff --git a/fs/autofs4/root.c b/fs/autofs4/root.c
index d34896cfb19..7922509b5b2 100644
--- a/fs/autofs4/root.c
+++ b/fs/autofs4/root.c
@@ -436,7 +436,7 @@ static struct dentry *autofs4_lookup_active(struct dentry *dentry)
436 spin_lock(&active->d_lock); 436 spin_lock(&active->d_lock);
437 437
438 /* Already gone? */ 438 /* Already gone? */
439 if (atomic_read(&active->d_count) == 0) 439 if (active->d_count == 0)
440 goto next; 440 goto next;
441 441
442 qstr = &active->d_name; 442 qstr = &active->d_name;
@@ -452,7 +452,7 @@ static struct dentry *autofs4_lookup_active(struct dentry *dentry)
452 goto next; 452 goto next;
453 453
454 if (d_unhashed(active)) { 454 if (d_unhashed(active)) {
455 dget(active); 455 dget_dlock(active);
456 spin_unlock(&active->d_lock); 456 spin_unlock(&active->d_lock);
457 spin_unlock(&sbi->lookup_lock); 457 spin_unlock(&sbi->lookup_lock);
458 spin_unlock(&dcache_lock); 458 spin_unlock(&dcache_lock);
@@ -507,7 +507,7 @@ static struct dentry *autofs4_lookup_expiring(struct dentry *dentry)
507 goto next; 507 goto next;
508 508
509 if (d_unhashed(expiring)) { 509 if (d_unhashed(expiring)) {
510 dget(expiring); 510 dget_dlock(expiring);
511 spin_unlock(&expiring->d_lock); 511 spin_unlock(&expiring->d_lock);
512 spin_unlock(&sbi->lookup_lock); 512 spin_unlock(&sbi->lookup_lock);
513 spin_unlock(&dcache_lock); 513 spin_unlock(&dcache_lock);
diff --git a/fs/ceph/dir.c b/fs/ceph/dir.c
index d902948a90d..3ecf915a455 100644
--- a/fs/ceph/dir.c
+++ b/fs/ceph/dir.c
@@ -150,7 +150,9 @@ more:
150 di = ceph_dentry(dentry); 150 di = ceph_dentry(dentry);
151 } 151 }
152 152
153 atomic_inc(&dentry->d_count); 153 spin_lock(&dentry->d_lock);
154 dentry->d_count++;
155 spin_unlock(&dentry->d_lock);
154 spin_unlock(&dcache_lock); 156 spin_unlock(&dcache_lock);
155 157
156 dout(" %llu (%llu) dentry %p %.*s %p\n", di->offset, filp->f_pos, 158 dout(" %llu (%llu) dentry %p %.*s %p\n", di->offset, filp->f_pos,
diff --git a/fs/ceph/inode.c b/fs/ceph/inode.c
index bf1286588f2..bb68c799074 100644
--- a/fs/ceph/inode.c
+++ b/fs/ceph/inode.c
@@ -879,8 +879,8 @@ static struct dentry *splice_dentry(struct dentry *dn, struct inode *in,
879 } else if (realdn) { 879 } else if (realdn) {
880 dout("dn %p (%d) spliced with %p (%d) " 880 dout("dn %p (%d) spliced with %p (%d) "
881 "inode %p ino %llx.%llx\n", 881 "inode %p ino %llx.%llx\n",
882 dn, atomic_read(&dn->d_count), 882 dn, dn->d_count,
883 realdn, atomic_read(&realdn->d_count), 883 realdn, realdn->d_count,
884 realdn->d_inode, ceph_vinop(realdn->d_inode)); 884 realdn->d_inode, ceph_vinop(realdn->d_inode));
885 dput(dn); 885 dput(dn);
886 dn = realdn; 886 dn = realdn;
diff --git a/fs/ceph/mds_client.c b/fs/ceph/mds_client.c
index 38800eaa81d..a50fca1e03b 100644
--- a/fs/ceph/mds_client.c
+++ b/fs/ceph/mds_client.c
@@ -1486,7 +1486,7 @@ retry:
1486 *base = ceph_ino(temp->d_inode); 1486 *base = ceph_ino(temp->d_inode);
1487 *plen = len; 1487 *plen = len;
1488 dout("build_path on %p %d built %llx '%.*s'\n", 1488 dout("build_path on %p %d built %llx '%.*s'\n",
1489 dentry, atomic_read(&dentry->d_count), *base, len, path); 1489 dentry, dentry->d_count, *base, len, path);
1490 return path; 1490 return path;
1491} 1491}
1492 1492
diff --git a/fs/coda/dir.c b/fs/coda/dir.c
index 4cce3b07d9d..9e37e8bc9b8 100644
--- a/fs/coda/dir.c
+++ b/fs/coda/dir.c
@@ -559,7 +559,7 @@ static int coda_dentry_revalidate(struct dentry *de, struct nameidata *nd)
559 if (cii->c_flags & C_FLUSH) 559 if (cii->c_flags & C_FLUSH)
560 coda_flag_inode_children(inode, C_FLUSH); 560 coda_flag_inode_children(inode, C_FLUSH);
561 561
562 if (atomic_read(&de->d_count) > 1) 562 if (de->d_count > 1)
563 /* pretend it's valid, but don't change the flags */ 563 /* pretend it's valid, but don't change the flags */
564 goto out; 564 goto out;
565 565
diff --git a/fs/configfs/dir.c b/fs/configfs/dir.c
index 20024a9ef5a..e9acea440ff 100644
--- a/fs/configfs/dir.c
+++ b/fs/configfs/dir.c
@@ -394,8 +394,7 @@ static void remove_dir(struct dentry * d)
394 if (d->d_inode) 394 if (d->d_inode)
395 simple_rmdir(parent->d_inode,d); 395 simple_rmdir(parent->d_inode,d);
396 396
397 pr_debug(" o %s removing done (%d)\n",d->d_name.name, 397 pr_debug(" o %s removing done (%d)\n",d->d_name.name, d->d_count);
398 atomic_read(&d->d_count));
399 398
400 dput(parent); 399 dput(parent);
401} 400}
diff --git a/fs/configfs/inode.c b/fs/configfs/inode.c
index 253476d78ed..79b37765d8f 100644
--- a/fs/configfs/inode.c
+++ b/fs/configfs/inode.c
@@ -253,7 +253,7 @@ void configfs_drop_dentry(struct configfs_dirent * sd, struct dentry * parent)
253 spin_lock(&dcache_lock); 253 spin_lock(&dcache_lock);
254 spin_lock(&dentry->d_lock); 254 spin_lock(&dentry->d_lock);
255 if (!(d_unhashed(dentry) && dentry->d_inode)) { 255 if (!(d_unhashed(dentry) && dentry->d_inode)) {
256 dget_locked(dentry); 256 dget_locked_dlock(dentry);
257 __d_drop(dentry); 257 __d_drop(dentry);
258 spin_unlock(&dentry->d_lock); 258 spin_unlock(&dentry->d_lock);
259 spin_unlock(&dcache_lock); 259 spin_unlock(&dcache_lock);
diff --git a/fs/dcache.c b/fs/dcache.c
index 3d3c843c36e..81e91502b29 100644
--- a/fs/dcache.c
+++ b/fs/dcache.c
@@ -45,6 +45,7 @@
45 * - d_flags 45 * - d_flags
46 * - d_name 46 * - d_name
47 * - d_lru 47 * - d_lru
48 * - d_count
48 * 49 *
49 * Ordering: 50 * Ordering:
50 * dcache_lock 51 * dcache_lock
@@ -125,6 +126,7 @@ static void __d_free(struct rcu_head *head)
125 */ 126 */
126static void d_free(struct dentry *dentry) 127static void d_free(struct dentry *dentry)
127{ 128{
129 BUG_ON(dentry->d_count);
128 this_cpu_dec(nr_dentry); 130 this_cpu_dec(nr_dentry);
129 if (dentry->d_op && dentry->d_op->d_release) 131 if (dentry->d_op && dentry->d_op->d_release)
130 dentry->d_op->d_release(dentry); 132 dentry->d_op->d_release(dentry);
@@ -222,8 +224,11 @@ static struct dentry *d_kill(struct dentry *dentry)
222 struct dentry *parent; 224 struct dentry *parent;
223 225
224 list_del(&dentry->d_u.d_child); 226 list_del(&dentry->d_u.d_child);
225 /*drops the locks, at that point nobody can reach this dentry */
226 dentry_iput(dentry); 227 dentry_iput(dentry);
228 /*
229 * dentry_iput drops the locks, at which point nobody (except
230 * transient RCU lookups) can reach this dentry.
231 */
227 if (IS_ROOT(dentry)) 232 if (IS_ROOT(dentry))
228 parent = NULL; 233 parent = NULL;
229 else 234 else
@@ -303,13 +308,23 @@ void dput(struct dentry *dentry)
303 return; 308 return;
304 309
305repeat: 310repeat:
306 if (atomic_read(&dentry->d_count) == 1) 311 if (dentry->d_count == 1)
307 might_sleep(); 312 might_sleep();
308 if (!atomic_dec_and_lock(&dentry->d_count, &dcache_lock))
309 return;
310
311 spin_lock(&dentry->d_lock); 313 spin_lock(&dentry->d_lock);
312 if (atomic_read(&dentry->d_count)) { 314 if (dentry->d_count == 1) {
315 if (!spin_trylock(&dcache_lock)) {
316 /*
317 * Something of a livelock possibility we could avoid
318 * by taking dcache_lock and trying again, but we
319 * want to reduce dcache_lock anyway so this will
320 * get improved.
321 */
322 spin_unlock(&dentry->d_lock);
323 goto repeat;
324 }
325 }
326 dentry->d_count--;
327 if (dentry->d_count) {
313 spin_unlock(&dentry->d_lock); 328 spin_unlock(&dentry->d_lock);
314 spin_unlock(&dcache_lock); 329 spin_unlock(&dcache_lock);
315 return; 330 return;
@@ -389,7 +404,7 @@ int d_invalidate(struct dentry * dentry)
389 * working directory or similar). 404 * working directory or similar).
390 */ 405 */
391 spin_lock(&dentry->d_lock); 406 spin_lock(&dentry->d_lock);
392 if (atomic_read(&dentry->d_count) > 1) { 407 if (dentry->d_count > 1) {
393 if (dentry->d_inode && S_ISDIR(dentry->d_inode->i_mode)) { 408 if (dentry->d_inode && S_ISDIR(dentry->d_inode->i_mode)) {
394 spin_unlock(&dentry->d_lock); 409 spin_unlock(&dentry->d_lock);
395 spin_unlock(&dcache_lock); 410 spin_unlock(&dcache_lock);
@@ -404,29 +419,61 @@ int d_invalidate(struct dentry * dentry)
404} 419}
405EXPORT_SYMBOL(d_invalidate); 420EXPORT_SYMBOL(d_invalidate);
406 421
407/* This should be called _only_ with dcache_lock held */ 422/* This must be called with dcache_lock and d_lock held */
408static inline struct dentry * __dget_locked_dlock(struct dentry *dentry) 423static inline struct dentry * __dget_locked_dlock(struct dentry *dentry)
409{ 424{
410 atomic_inc(&dentry->d_count); 425 dentry->d_count++;
411 dentry_lru_del(dentry); 426 dentry_lru_del(dentry);
412 return dentry; 427 return dentry;
413} 428}
414 429
430/* This should be called _only_ with dcache_lock held */
415static inline struct dentry * __dget_locked(struct dentry *dentry) 431static inline struct dentry * __dget_locked(struct dentry *dentry)
416{ 432{
417 atomic_inc(&dentry->d_count);
418 spin_lock(&dentry->d_lock); 433 spin_lock(&dentry->d_lock);
419 dentry_lru_del(dentry); 434 __dget_locked_dlock(dentry);
420 spin_unlock(&dentry->d_lock); 435 spin_unlock(&dentry->d_lock);
421 return dentry; 436 return dentry;
422} 437}
423 438
439struct dentry * dget_locked_dlock(struct dentry *dentry)
440{
441 return __dget_locked_dlock(dentry);
442}
443
424struct dentry * dget_locked(struct dentry *dentry) 444struct dentry * dget_locked(struct dentry *dentry)
425{ 445{
426 return __dget_locked(dentry); 446 return __dget_locked(dentry);
427} 447}
428EXPORT_SYMBOL(dget_locked); 448EXPORT_SYMBOL(dget_locked);
429 449
450struct dentry *dget_parent(struct dentry *dentry)
451{
452 struct dentry *ret;
453
454repeat:
455 spin_lock(&dentry->d_lock);
456 ret = dentry->d_parent;
457 if (!ret)
458 goto out;
459 if (dentry == ret) {
460 ret->d_count++;
461 goto out;
462 }
463 if (!spin_trylock(&ret->d_lock)) {
464 spin_unlock(&dentry->d_lock);
465 cpu_relax();
466 goto repeat;
467 }
468 BUG_ON(!ret->d_count);
469 ret->d_count++;
470 spin_unlock(&ret->d_lock);
471out:
472 spin_unlock(&dentry->d_lock);
473 return ret;
474}
475EXPORT_SYMBOL(dget_parent);
476
430/** 477/**
431 * d_find_alias - grab a hashed alias of inode 478 * d_find_alias - grab a hashed alias of inode
432 * @inode: inode in question 479 * @inode: inode in question
@@ -495,7 +542,7 @@ restart:
495 spin_lock(&dcache_lock); 542 spin_lock(&dcache_lock);
496 list_for_each_entry(dentry, &inode->i_dentry, d_alias) { 543 list_for_each_entry(dentry, &inode->i_dentry, d_alias) {
497 spin_lock(&dentry->d_lock); 544 spin_lock(&dentry->d_lock);
498 if (!atomic_read(&dentry->d_count)) { 545 if (!dentry->d_count) {
499 __dget_locked_dlock(dentry); 546 __dget_locked_dlock(dentry);
500 __d_drop(dentry); 547 __d_drop(dentry);
501 spin_unlock(&dentry->d_lock); 548 spin_unlock(&dentry->d_lock);
@@ -530,7 +577,10 @@ static void prune_one_dentry(struct dentry * dentry)
530 */ 577 */
531 while (dentry) { 578 while (dentry) {
532 spin_lock(&dcache_lock); 579 spin_lock(&dcache_lock);
533 if (!atomic_dec_and_lock(&dentry->d_count, &dentry->d_lock)) { 580 spin_lock(&dentry->d_lock);
581 dentry->d_count--;
582 if (dentry->d_count) {
583 spin_unlock(&dentry->d_lock);
534 spin_unlock(&dcache_lock); 584 spin_unlock(&dcache_lock);
535 return; 585 return;
536 } 586 }
@@ -562,7 +612,7 @@ static void shrink_dentry_list(struct list_head *list)
562 * the LRU because of laziness during lookup. Do not free 612 * the LRU because of laziness during lookup. Do not free
563 * it - just keep it off the LRU list. 613 * it - just keep it off the LRU list.
564 */ 614 */
565 if (atomic_read(&dentry->d_count)) { 615 if (dentry->d_count) {
566 spin_unlock(&dentry->d_lock); 616 spin_unlock(&dentry->d_lock);
567 continue; 617 continue;
568 } 618 }
@@ -783,7 +833,7 @@ static void shrink_dcache_for_umount_subtree(struct dentry *dentry)
783 do { 833 do {
784 struct inode *inode; 834 struct inode *inode;
785 835
786 if (atomic_read(&dentry->d_count) != 0) { 836 if (dentry->d_count != 0) {
787 printk(KERN_ERR 837 printk(KERN_ERR
788 "BUG: Dentry %p{i=%lx,n=%s}" 838 "BUG: Dentry %p{i=%lx,n=%s}"
789 " still in use (%d)" 839 " still in use (%d)"
@@ -792,7 +842,7 @@ static void shrink_dcache_for_umount_subtree(struct dentry *dentry)
792 dentry->d_inode ? 842 dentry->d_inode ?
793 dentry->d_inode->i_ino : 0UL, 843 dentry->d_inode->i_ino : 0UL,
794 dentry->d_name.name, 844 dentry->d_name.name,
795 atomic_read(&dentry->d_count), 845 dentry->d_count,
796 dentry->d_sb->s_type->name, 846 dentry->d_sb->s_type->name,
797 dentry->d_sb->s_id); 847 dentry->d_sb->s_id);
798 BUG(); 848 BUG();
@@ -802,7 +852,9 @@ static void shrink_dcache_for_umount_subtree(struct dentry *dentry)
802 parent = NULL; 852 parent = NULL;
803 else { 853 else {
804 parent = dentry->d_parent; 854 parent = dentry->d_parent;
805 atomic_dec(&parent->d_count); 855 spin_lock(&parent->d_lock);
856 parent->d_count--;
857 spin_unlock(&parent->d_lock);
806 } 858 }
807 859
808 list_del(&dentry->d_u.d_child); 860 list_del(&dentry->d_u.d_child);
@@ -853,7 +905,9 @@ void shrink_dcache_for_umount(struct super_block *sb)
853 905
854 dentry = sb->s_root; 906 dentry = sb->s_root;
855 sb->s_root = NULL; 907 sb->s_root = NULL;
856 atomic_dec(&dentry->d_count); 908 spin_lock(&dentry->d_lock);
909 dentry->d_count--;
910 spin_unlock(&dentry->d_lock);
857 shrink_dcache_for_umount_subtree(dentry); 911 shrink_dcache_for_umount_subtree(dentry);
858 912
859 while (!hlist_empty(&sb->s_anon)) { 913 while (!hlist_empty(&sb->s_anon)) {
@@ -950,7 +1004,7 @@ resume:
950 * move only zero ref count dentries to the end 1004 * move only zero ref count dentries to the end
951 * of the unused list for prune_dcache 1005 * of the unused list for prune_dcache
952 */ 1006 */
953 if (!atomic_read(&dentry->d_count)) { 1007 if (!dentry->d_count) {
954 dentry_lru_move_tail(dentry); 1008 dentry_lru_move_tail(dentry);
955 found++; 1009 found++;
956 } else { 1010 } else {
@@ -1068,7 +1122,7 @@ struct dentry *d_alloc(struct dentry * parent, const struct qstr *name)
1068 memcpy(dname, name->name, name->len); 1122 memcpy(dname, name->name, name->len);
1069 dname[name->len] = 0; 1123 dname[name->len] = 0;
1070 1124
1071 atomic_set(&dentry->d_count, 1); 1125 dentry->d_count = 1;
1072 dentry->d_flags = DCACHE_UNHASHED; 1126 dentry->d_flags = DCACHE_UNHASHED;
1073 spin_lock_init(&dentry->d_lock); 1127 spin_lock_init(&dentry->d_lock);
1074 dentry->d_inode = NULL; 1128 dentry->d_inode = NULL;
@@ -1556,7 +1610,7 @@ struct dentry * __d_lookup(struct dentry * parent, struct qstr * name)
1556 goto next; 1610 goto next;
1557 } 1611 }
1558 1612
1559 atomic_inc(&dentry->d_count); 1613 dentry->d_count++;
1560 found = dentry; 1614 found = dentry;
1561 spin_unlock(&dentry->d_lock); 1615 spin_unlock(&dentry->d_lock);
1562 break; 1616 break;
@@ -1653,7 +1707,7 @@ void d_delete(struct dentry * dentry)
1653 spin_lock(&dcache_lock); 1707 spin_lock(&dcache_lock);
1654 spin_lock(&dentry->d_lock); 1708 spin_lock(&dentry->d_lock);
1655 isdir = S_ISDIR(dentry->d_inode->i_mode); 1709 isdir = S_ISDIR(dentry->d_inode->i_mode);
1656 if (atomic_read(&dentry->d_count) == 1) { 1710 if (dentry->d_count == 1) {
1657 dentry->d_flags &= ~DCACHE_CANT_MOUNT; 1711 dentry->d_flags &= ~DCACHE_CANT_MOUNT;
1658 dentry_iput(dentry); 1712 dentry_iput(dentry);
1659 fsnotify_nameremove(dentry, isdir); 1713 fsnotify_nameremove(dentry, isdir);
@@ -2494,11 +2548,15 @@ resume:
2494 this_parent = dentry; 2548 this_parent = dentry;
2495 goto repeat; 2549 goto repeat;
2496 } 2550 }
2497 atomic_dec(&dentry->d_count); 2551 spin_lock(&dentry->d_lock);
2552 dentry->d_count--;
2553 spin_unlock(&dentry->d_lock);
2498 } 2554 }
2499 if (this_parent != root) { 2555 if (this_parent != root) {
2500 next = this_parent->d_u.d_child.next; 2556 next = this_parent->d_u.d_child.next;
2501 atomic_dec(&this_parent->d_count); 2557 spin_lock(&this_parent->d_lock);
2558 this_parent->d_count--;
2559 spin_unlock(&this_parent->d_lock);
2502 this_parent = this_parent->d_parent; 2560 this_parent = this_parent->d_parent;
2503 goto resume; 2561 goto resume;
2504 } 2562 }
diff --git a/fs/ecryptfs/inode.c b/fs/ecryptfs/inode.c
index a1ed7a7cb17..5e5c7ec1fc9 100644
--- a/fs/ecryptfs/inode.c
+++ b/fs/ecryptfs/inode.c
@@ -260,7 +260,7 @@ int ecryptfs_lookup_and_interpose_lower(struct dentry *ecryptfs_dentry,
260 ecryptfs_dentry->d_parent)); 260 ecryptfs_dentry->d_parent));
261 lower_inode = lower_dentry->d_inode; 261 lower_inode = lower_dentry->d_inode;
262 fsstack_copy_attr_atime(ecryptfs_dir_inode, lower_dir_dentry->d_inode); 262 fsstack_copy_attr_atime(ecryptfs_dir_inode, lower_dir_dentry->d_inode);
263 BUG_ON(!atomic_read(&lower_dentry->d_count)); 263 BUG_ON(!lower_dentry->d_count);
264 ecryptfs_set_dentry_private(ecryptfs_dentry, 264 ecryptfs_set_dentry_private(ecryptfs_dentry,
265 kmem_cache_alloc(ecryptfs_dentry_info_cache, 265 kmem_cache_alloc(ecryptfs_dentry_info_cache,
266 GFP_KERNEL)); 266 GFP_KERNEL));
diff --git a/fs/locks.c b/fs/locks.c
index 8729347bcd1..08415b2a6d3 100644
--- a/fs/locks.c
+++ b/fs/locks.c
@@ -1389,7 +1389,7 @@ int generic_setlease(struct file *filp, long arg, struct file_lock **flp)
1389 if ((arg == F_RDLCK) && (atomic_read(&inode->i_writecount) > 0)) 1389 if ((arg == F_RDLCK) && (atomic_read(&inode->i_writecount) > 0))
1390 goto out; 1390 goto out;
1391 if ((arg == F_WRLCK) 1391 if ((arg == F_WRLCK)
1392 && ((atomic_read(&dentry->d_count) > 1) 1392 && ((dentry->d_count > 1)
1393 || (atomic_read(&inode->i_count) > 1))) 1393 || (atomic_read(&inode->i_count) > 1)))
1394 goto out; 1394 goto out;
1395 } 1395 }
diff --git a/fs/namei.c b/fs/namei.c
index f3b5ca40465..cbfa5fb3107 100644
--- a/fs/namei.c
+++ b/fs/namei.c
@@ -2133,7 +2133,7 @@ void dentry_unhash(struct dentry *dentry)
2133 shrink_dcache_parent(dentry); 2133 shrink_dcache_parent(dentry);
2134 spin_lock(&dcache_lock); 2134 spin_lock(&dcache_lock);
2135 spin_lock(&dentry->d_lock); 2135 spin_lock(&dentry->d_lock);
2136 if (atomic_read(&dentry->d_count) == 2) 2136 if (dentry->d_count == 2)
2137 __d_drop(dentry); 2137 __d_drop(dentry);
2138 spin_unlock(&dentry->d_lock); 2138 spin_unlock(&dentry->d_lock);
2139 spin_unlock(&dcache_lock); 2139 spin_unlock(&dcache_lock);
diff --git a/fs/nfs/dir.c b/fs/nfs/dir.c
index 9184c7c80f7..12de824edb5 100644
--- a/fs/nfs/dir.c
+++ b/fs/nfs/dir.c
@@ -1720,7 +1720,7 @@ static int nfs_unlink(struct inode *dir, struct dentry *dentry)
1720 1720
1721 spin_lock(&dcache_lock); 1721 spin_lock(&dcache_lock);
1722 spin_lock(&dentry->d_lock); 1722 spin_lock(&dentry->d_lock);
1723 if (atomic_read(&dentry->d_count) > 1) { 1723 if (dentry->d_count > 1) {
1724 spin_unlock(&dentry->d_lock); 1724 spin_unlock(&dentry->d_lock);
1725 spin_unlock(&dcache_lock); 1725 spin_unlock(&dcache_lock);
1726 /* Start asynchronous writeout of the inode */ 1726 /* Start asynchronous writeout of the inode */
@@ -1868,7 +1868,7 @@ static int nfs_rename(struct inode *old_dir, struct dentry *old_dentry,
1868 dfprintk(VFS, "NFS: rename(%s/%s -> %s/%s, ct=%d)\n", 1868 dfprintk(VFS, "NFS: rename(%s/%s -> %s/%s, ct=%d)\n",
1869 old_dentry->d_parent->d_name.name, old_dentry->d_name.name, 1869 old_dentry->d_parent->d_name.name, old_dentry->d_name.name,
1870 new_dentry->d_parent->d_name.name, new_dentry->d_name.name, 1870 new_dentry->d_parent->d_name.name, new_dentry->d_name.name,
1871 atomic_read(&new_dentry->d_count)); 1871 new_dentry->d_count);
1872 1872
1873 /* 1873 /*
1874 * For non-directories, check whether the target is busy and if so, 1874 * For non-directories, check whether the target is busy and if so,
@@ -1886,7 +1886,7 @@ static int nfs_rename(struct inode *old_dir, struct dentry *old_dentry,
1886 rehash = new_dentry; 1886 rehash = new_dentry;
1887 } 1887 }
1888 1888
1889 if (atomic_read(&new_dentry->d_count) > 2) { 1889 if (new_dentry->d_count > 2) {
1890 int err; 1890 int err;
1891 1891
1892 /* copy the target dentry's name */ 1892 /* copy the target dentry's name */
diff --git a/fs/nfs/unlink.c b/fs/nfs/unlink.c
index 7bdec853140..8fe9eb47a97 100644
--- a/fs/nfs/unlink.c
+++ b/fs/nfs/unlink.c
@@ -496,7 +496,7 @@ nfs_sillyrename(struct inode *dir, struct dentry *dentry)
496 496
497 dfprintk(VFS, "NFS: silly-rename(%s/%s, ct=%d)\n", 497 dfprintk(VFS, "NFS: silly-rename(%s/%s, ct=%d)\n",
498 dentry->d_parent->d_name.name, dentry->d_name.name, 498 dentry->d_parent->d_name.name, dentry->d_name.name,
499 atomic_read(&dentry->d_count)); 499 dentry->d_count);
500 nfs_inc_stats(dir, NFSIOS_SILLYRENAME); 500 nfs_inc_stats(dir, NFSIOS_SILLYRENAME);
501 501
502 /* 502 /*
diff --git a/fs/nfsd/vfs.c b/fs/nfsd/vfs.c
index 184938fcff0..3a359023c9f 100644
--- a/fs/nfsd/vfs.c
+++ b/fs/nfsd/vfs.c
@@ -1756,8 +1756,7 @@ nfsd_rename(struct svc_rqst *rqstp, struct svc_fh *ffhp, char *fname, int flen,
1756 goto out_dput_new; 1756 goto out_dput_new;
1757 1757
1758 if (svc_msnfs(ffhp) && 1758 if (svc_msnfs(ffhp) &&
1759 ((atomic_read(&odentry->d_count) > 1) 1759 ((odentry->d_count > 1) || (ndentry->d_count > 1))) {
1760 || (atomic_read(&ndentry->d_count) > 1))) {
1761 host_err = -EPERM; 1760 host_err = -EPERM;
1762 goto out_dput_new; 1761 goto out_dput_new;
1763 } 1762 }
@@ -1843,7 +1842,7 @@ nfsd_unlink(struct svc_rqst *rqstp, struct svc_fh *fhp, int type,
1843 if (type != S_IFDIR) { /* It's UNLINK */ 1842 if (type != S_IFDIR) { /* It's UNLINK */
1844#ifdef MSNFS 1843#ifdef MSNFS
1845 if ((fhp->fh_export->ex_flags & NFSEXP_MSNFS) && 1844 if ((fhp->fh_export->ex_flags & NFSEXP_MSNFS) &&
1846 (atomic_read(&rdentry->d_count) > 1)) { 1845 (rdentry->d_count > 1)) {
1847 host_err = -EPERM; 1846 host_err = -EPERM;
1848 } else 1847 } else
1849#endif 1848#endif
diff --git a/fs/nilfs2/super.c b/fs/nilfs2/super.c
index f804d41ec9d..d36fc7ee615 100644
--- a/fs/nilfs2/super.c
+++ b/fs/nilfs2/super.c
@@ -838,7 +838,7 @@ static int nilfs_attach_snapshot(struct super_block *s, __u64 cno,
838 838
839static int nilfs_tree_was_touched(struct dentry *root_dentry) 839static int nilfs_tree_was_touched(struct dentry *root_dentry)
840{ 840{
841 return atomic_read(&root_dentry->d_count) > 1; 841 return root_dentry->d_count > 1;
842} 842}
843 843
844/** 844/**
diff --git a/include/linux/dcache.h b/include/linux/dcache.h
index 2feb624b67f..b0ade2d4680 100644
--- a/include/linux/dcache.h
+++ b/include/linux/dcache.h
@@ -87,7 +87,7 @@ full_name_hash(const unsigned char *name, unsigned int len)
87#endif 87#endif
88 88
89struct dentry { 89struct dentry {
90 atomic_t d_count; 90 unsigned int d_count; /* protected by d_lock */
91 unsigned int d_flags; /* protected by d_lock */ 91 unsigned int d_flags; /* protected by d_lock */
92 spinlock_t d_lock; /* per dentry lock */ 92 spinlock_t d_lock; /* per dentry lock */
93 int d_mounted; 93 int d_mounted;
@@ -297,17 +297,28 @@ extern char *dentry_path(struct dentry *, char *, int);
297 * needs and they take necessary precautions) you should hold dcache_lock 297 * needs and they take necessary precautions) you should hold dcache_lock
298 * and call dget_locked() instead of dget(). 298 * and call dget_locked() instead of dget().
299 */ 299 */
300 300static inline struct dentry *dget_dlock(struct dentry *dentry)
301{
302 if (dentry) {
303 BUG_ON(!dentry->d_count);
304 dentry->d_count++;
305 }
306 return dentry;
307}
301static inline struct dentry *dget(struct dentry *dentry) 308static inline struct dentry *dget(struct dentry *dentry)
302{ 309{
303 if (dentry) { 310 if (dentry) {
304 BUG_ON(!atomic_read(&dentry->d_count)); 311 spin_lock(&dentry->d_lock);
305 atomic_inc(&dentry->d_count); 312 dget_dlock(dentry);
313 spin_unlock(&dentry->d_lock);
306 } 314 }
307 return dentry; 315 return dentry;
308} 316}
309 317
310extern struct dentry * dget_locked(struct dentry *); 318extern struct dentry * dget_locked(struct dentry *);
319extern struct dentry * dget_locked_dlock(struct dentry *);
320
321extern struct dentry *dget_parent(struct dentry *dentry);
311 322
312/** 323/**
313 * d_unhashed - is dentry hashed 324 * d_unhashed - is dentry hashed
@@ -338,16 +349,6 @@ static inline void dont_mount(struct dentry *dentry)
338 spin_unlock(&dentry->d_lock); 349 spin_unlock(&dentry->d_lock);
339} 350}
340 351
341static inline struct dentry *dget_parent(struct dentry *dentry)
342{
343 struct dentry *ret;
344
345 spin_lock(&dentry->d_lock);
346 ret = dget(dentry->d_parent);
347 spin_unlock(&dentry->d_lock);
348 return ret;
349}
350
351extern void dput(struct dentry *); 352extern void dput(struct dentry *);
352 353
353static inline int d_mountpoint(struct dentry *dentry) 354static inline int d_mountpoint(struct dentry *dentry)
diff --git a/kernel/cgroup.c b/kernel/cgroup.c
index 746055b214d..eb7af39350c 100644
--- a/kernel/cgroup.c
+++ b/kernel/cgroup.c
@@ -3655,9 +3655,7 @@ again:
3655 list_del(&cgrp->sibling); 3655 list_del(&cgrp->sibling);
3656 cgroup_unlock_hierarchy(cgrp->root); 3656 cgroup_unlock_hierarchy(cgrp->root);
3657 3657
3658 spin_lock(&cgrp->dentry->d_lock);
3659 d = dget(cgrp->dentry); 3658 d = dget(cgrp->dentry);
3660 spin_unlock(&d->d_lock);
3661 3659
3662 cgroup_d_remove_dir(d); 3660 cgroup_d_remove_dir(d);
3663 dput(d); 3661 dput(d);