aboutsummaryrefslogtreecommitdiffstats
path: root/fs/dcache.c
diff options
context:
space:
mode:
Diffstat (limited to 'fs/dcache.c')
-rw-r--r--fs/dcache.c178
1 files changed, 156 insertions, 22 deletions
diff --git a/fs/dcache.c b/fs/dcache.c
index 313b54b2b8f2..17b392a2049e 100644
--- a/fs/dcache.c
+++ b/fs/dcache.c
@@ -14,7 +14,6 @@
14 * the dcache entry is deleted or garbage collected. 14 * the dcache entry is deleted or garbage collected.
15 */ 15 */
16 16
17#include <linux/config.h>
18#include <linux/syscalls.h> 17#include <linux/syscalls.h>
19#include <linux/string.h> 18#include <linux/string.h>
20#include <linux/mm.h> 19#include <linux/mm.h>
@@ -39,7 +38,7 @@ int sysctl_vfs_cache_pressure __read_mostly = 100;
39EXPORT_SYMBOL_GPL(sysctl_vfs_cache_pressure); 38EXPORT_SYMBOL_GPL(sysctl_vfs_cache_pressure);
40 39
41 __cacheline_aligned_in_smp DEFINE_SPINLOCK(dcache_lock); 40 __cacheline_aligned_in_smp DEFINE_SPINLOCK(dcache_lock);
42static seqlock_t rename_lock __cacheline_aligned_in_smp = SEQLOCK_UNLOCKED; 41static __cacheline_aligned_in_smp DEFINE_SEQLOCK(rename_lock);
43 42
44EXPORT_SYMBOL(dcache_lock); 43EXPORT_SYMBOL(dcache_lock);
45 44
@@ -406,7 +405,7 @@ static void prune_dcache(int count, struct super_block *sb)
406 cond_resched_lock(&dcache_lock); 405 cond_resched_lock(&dcache_lock);
407 406
408 tmp = dentry_unused.prev; 407 tmp = dentry_unused.prev;
409 if (unlikely(sb)) { 408 if (sb) {
410 /* Try to find a dentry for this sb, but don't try 409 /* Try to find a dentry for this sb, but don't try
411 * too hard, if they aren't near the tail they will 410 * too hard, if they aren't near the tail they will
412 * be moved down again soon 411 * be moved down again soon
@@ -522,8 +521,7 @@ void shrink_dcache_sb(struct super_block * sb)
522 dentry = list_entry(tmp, struct dentry, d_lru); 521 dentry = list_entry(tmp, struct dentry, d_lru);
523 if (dentry->d_sb != sb) 522 if (dentry->d_sb != sb)
524 continue; 523 continue;
525 list_del(tmp); 524 list_move(tmp, &dentry_unused);
526 list_add(tmp, &dentry_unused);
527 } 525 }
528 526
529 /* 527 /*
@@ -638,7 +636,7 @@ resume:
638 * of the unused list for prune_dcache 636 * of the unused list for prune_dcache
639 */ 637 */
640 if (!atomic_read(&dentry->d_count)) { 638 if (!atomic_read(&dentry->d_count)) {
641 list_add(&dentry->d_lru, dentry_unused.prev); 639 list_add_tail(&dentry->d_lru, &dentry_unused);
642 dentry_stat.nr_unused++; 640 dentry_stat.nr_unused++;
643 found++; 641 found++;
644 } 642 }
@@ -830,17 +828,19 @@ void d_instantiate(struct dentry *entry, struct inode * inode)
830 * (or otherwise set) by the caller to indicate that it is now 828 * (or otherwise set) by the caller to indicate that it is now
831 * in use by the dcache. 829 * in use by the dcache.
832 */ 830 */
833struct dentry *d_instantiate_unique(struct dentry *entry, struct inode *inode) 831static struct dentry *__d_instantiate_unique(struct dentry *entry,
832 struct inode *inode)
834{ 833{
835 struct dentry *alias; 834 struct dentry *alias;
836 int len = entry->d_name.len; 835 int len = entry->d_name.len;
837 const char *name = entry->d_name.name; 836 const char *name = entry->d_name.name;
838 unsigned int hash = entry->d_name.hash; 837 unsigned int hash = entry->d_name.hash;
839 838
840 BUG_ON(!list_empty(&entry->d_alias)); 839 if (!inode) {
841 spin_lock(&dcache_lock); 840 entry->d_inode = NULL;
842 if (!inode) 841 return NULL;
843 goto do_negative; 842 }
843
844 list_for_each_entry(alias, &inode->i_dentry, d_alias) { 844 list_for_each_entry(alias, &inode->i_dentry, d_alias) {
845 struct qstr *qstr = &alias->d_name; 845 struct qstr *qstr = &alias->d_name;
846 846
@@ -853,19 +853,35 @@ struct dentry *d_instantiate_unique(struct dentry *entry, struct inode *inode)
853 if (memcmp(qstr->name, name, len)) 853 if (memcmp(qstr->name, name, len))
854 continue; 854 continue;
855 dget_locked(alias); 855 dget_locked(alias);
856 spin_unlock(&dcache_lock);
857 BUG_ON(!d_unhashed(alias));
858 iput(inode);
859 return alias; 856 return alias;
860 } 857 }
858
861 list_add(&entry->d_alias, &inode->i_dentry); 859 list_add(&entry->d_alias, &inode->i_dentry);
862do_negative:
863 entry->d_inode = inode; 860 entry->d_inode = inode;
864 fsnotify_d_instantiate(entry, inode); 861 fsnotify_d_instantiate(entry, inode);
865 spin_unlock(&dcache_lock);
866 security_d_instantiate(entry, inode);
867 return NULL; 862 return NULL;
868} 863}
864
865struct dentry *d_instantiate_unique(struct dentry *entry, struct inode *inode)
866{
867 struct dentry *result;
868
869 BUG_ON(!list_empty(&entry->d_alias));
870
871 spin_lock(&dcache_lock);
872 result = __d_instantiate_unique(entry, inode);
873 spin_unlock(&dcache_lock);
874
875 if (!result) {
876 security_d_instantiate(entry, inode);
877 return NULL;
878 }
879
880 BUG_ON(!d_unhashed(result));
881 iput(inode);
882 return result;
883}
884
869EXPORT_SYMBOL(d_instantiate_unique); 885EXPORT_SYMBOL(d_instantiate_unique);
870 886
871/** 887/**
@@ -1237,6 +1253,11 @@ static void __d_rehash(struct dentry * entry, struct hlist_head *list)
1237 hlist_add_head_rcu(&entry->d_hash, list); 1253 hlist_add_head_rcu(&entry->d_hash, list);
1238} 1254}
1239 1255
1256static void _d_rehash(struct dentry * entry)
1257{
1258 __d_rehash(entry, d_hash(entry->d_parent, entry->d_name.hash));
1259}
1260
1240/** 1261/**
1241 * d_rehash - add an entry back to the hash 1262 * d_rehash - add an entry back to the hash
1242 * @entry: dentry to add to the hash 1263 * @entry: dentry to add to the hash
@@ -1246,11 +1267,9 @@ static void __d_rehash(struct dentry * entry, struct hlist_head *list)
1246 1267
1247void d_rehash(struct dentry * entry) 1268void d_rehash(struct dentry * entry)
1248{ 1269{
1249 struct hlist_head *list = d_hash(entry->d_parent, entry->d_name.hash);
1250
1251 spin_lock(&dcache_lock); 1270 spin_lock(&dcache_lock);
1252 spin_lock(&entry->d_lock); 1271 spin_lock(&entry->d_lock);
1253 __d_rehash(entry, list); 1272 _d_rehash(entry);
1254 spin_unlock(&entry->d_lock); 1273 spin_unlock(&entry->d_lock);
1255 spin_unlock(&dcache_lock); 1274 spin_unlock(&dcache_lock);
1256} 1275}
@@ -1341,10 +1360,10 @@ void d_move(struct dentry * dentry, struct dentry * target)
1341 */ 1360 */
1342 if (target < dentry) { 1361 if (target < dentry) {
1343 spin_lock(&target->d_lock); 1362 spin_lock(&target->d_lock);
1344 spin_lock(&dentry->d_lock); 1363 spin_lock_nested(&dentry->d_lock, DENTRY_D_LOCK_NESTED);
1345 } else { 1364 } else {
1346 spin_lock(&dentry->d_lock); 1365 spin_lock(&dentry->d_lock);
1347 spin_lock(&target->d_lock); 1366 spin_lock_nested(&target->d_lock, DENTRY_D_LOCK_NESTED);
1348 } 1367 }
1349 1368
1350 /* Move the dentry to the target hash queue, if on different bucket */ 1369 /* Move the dentry to the target hash queue, if on different bucket */
@@ -1388,6 +1407,120 @@ already_unhashed:
1388 spin_unlock(&dcache_lock); 1407 spin_unlock(&dcache_lock);
1389} 1408}
1390 1409
1410/*
1411 * Prepare an anonymous dentry for life in the superblock's dentry tree as a
1412 * named dentry in place of the dentry to be replaced.
1413 */
1414static void __d_materialise_dentry(struct dentry *dentry, struct dentry *anon)
1415{
1416 struct dentry *dparent, *aparent;
1417
1418 switch_names(dentry, anon);
1419 do_switch(dentry->d_name.len, anon->d_name.len);
1420 do_switch(dentry->d_name.hash, anon->d_name.hash);
1421
1422 dparent = dentry->d_parent;
1423 aparent = anon->d_parent;
1424
1425 dentry->d_parent = (aparent == anon) ? dentry : aparent;
1426 list_del(&dentry->d_u.d_child);
1427 if (!IS_ROOT(dentry))
1428 list_add(&dentry->d_u.d_child, &dentry->d_parent->d_subdirs);
1429 else
1430 INIT_LIST_HEAD(&dentry->d_u.d_child);
1431
1432 anon->d_parent = (dparent == dentry) ? anon : dparent;
1433 list_del(&anon->d_u.d_child);
1434 if (!IS_ROOT(anon))
1435 list_add(&anon->d_u.d_child, &anon->d_parent->d_subdirs);
1436 else
1437 INIT_LIST_HEAD(&anon->d_u.d_child);
1438
1439 anon->d_flags &= ~DCACHE_DISCONNECTED;
1440}
1441
1442/**
1443 * d_materialise_unique - introduce an inode into the tree
1444 * @dentry: candidate dentry
1445 * @inode: inode to bind to the dentry, to which aliases may be attached
1446 *
1447 * Introduces an dentry into the tree, substituting an extant disconnected
1448 * root directory alias in its place if there is one
1449 */
1450struct dentry *d_materialise_unique(struct dentry *dentry, struct inode *inode)
1451{
1452 struct dentry *alias, *actual;
1453
1454 BUG_ON(!d_unhashed(dentry));
1455
1456 spin_lock(&dcache_lock);
1457
1458 if (!inode) {
1459 actual = dentry;
1460 dentry->d_inode = NULL;
1461 goto found_lock;
1462 }
1463
1464 /* See if a disconnected directory already exists as an anonymous root
1465 * that we should splice into the tree instead */
1466 if (S_ISDIR(inode->i_mode) && (alias = __d_find_alias(inode, 1))) {
1467 spin_lock(&alias->d_lock);
1468
1469 /* Is this a mountpoint that we could splice into our tree? */
1470 if (IS_ROOT(alias))
1471 goto connect_mountpoint;
1472
1473 if (alias->d_name.len == dentry->d_name.len &&
1474 alias->d_parent == dentry->d_parent &&
1475 memcmp(alias->d_name.name,
1476 dentry->d_name.name,
1477 dentry->d_name.len) == 0)
1478 goto replace_with_alias;
1479
1480 spin_unlock(&alias->d_lock);
1481
1482 /* Doh! Seem to be aliasing directories for some reason... */
1483 dput(alias);
1484 }
1485
1486 /* Add a unique reference */
1487 actual = __d_instantiate_unique(dentry, inode);
1488 if (!actual)
1489 actual = dentry;
1490 else if (unlikely(!d_unhashed(actual)))
1491 goto shouldnt_be_hashed;
1492
1493found_lock:
1494 spin_lock(&actual->d_lock);
1495found:
1496 _d_rehash(actual);
1497 spin_unlock(&actual->d_lock);
1498 spin_unlock(&dcache_lock);
1499
1500 if (actual == dentry) {
1501 security_d_instantiate(dentry, inode);
1502 return NULL;
1503 }
1504
1505 iput(inode);
1506 return actual;
1507
1508 /* Convert the anonymous/root alias into an ordinary dentry */
1509connect_mountpoint:
1510 __d_materialise_dentry(dentry, alias);
1511
1512 /* Replace the candidate dentry with the alias in the tree */
1513replace_with_alias:
1514 __d_drop(alias);
1515 actual = alias;
1516 goto found;
1517
1518shouldnt_be_hashed:
1519 spin_unlock(&dcache_lock);
1520 BUG();
1521 goto shouldnt_be_hashed;
1522}
1523
1391/** 1524/**
1392 * d_path - return the path of a dentry 1525 * d_path - return the path of a dentry
1393 * @dentry: dentry to report 1526 * @dentry: dentry to report
@@ -1786,6 +1919,7 @@ EXPORT_SYMBOL(d_instantiate);
1786EXPORT_SYMBOL(d_invalidate); 1919EXPORT_SYMBOL(d_invalidate);
1787EXPORT_SYMBOL(d_lookup); 1920EXPORT_SYMBOL(d_lookup);
1788EXPORT_SYMBOL(d_move); 1921EXPORT_SYMBOL(d_move);
1922EXPORT_SYMBOL_GPL(d_materialise_unique);
1789EXPORT_SYMBOL(d_path); 1923EXPORT_SYMBOL(d_path);
1790EXPORT_SYMBOL(d_prune_aliases); 1924EXPORT_SYMBOL(d_prune_aliases);
1791EXPORT_SYMBOL(d_rehash); 1925EXPORT_SYMBOL(d_rehash);