diff options
| -rw-r--r-- | fs/dcache.c | 133 | ||||
| -rw-r--r-- | fs/super.c | 3 | ||||
| -rw-r--r-- | include/linux/dcache.h | 3 | ||||
| -rw-r--r-- | include/linux/fs.h | 3 |
4 files changed, 89 insertions, 53 deletions
diff --git a/fs/dcache.c b/fs/dcache.c index 07d1f6862dc7..9f04e1ba75b7 100644 --- a/fs/dcache.c +++ b/fs/dcache.c | |||
| @@ -33,14 +33,18 @@ | |||
| 33 | #include <linux/bootmem.h> | 33 | #include <linux/bootmem.h> |
| 34 | #include <linux/fs_struct.h> | 34 | #include <linux/fs_struct.h> |
| 35 | #include <linux/hardirq.h> | 35 | #include <linux/hardirq.h> |
| 36 | #include <linux/bit_spinlock.h> | ||
| 37 | #include <linux/rculist_bl.h> | ||
| 36 | #include "internal.h" | 38 | #include "internal.h" |
| 37 | 39 | ||
| 38 | /* | 40 | /* |
| 39 | * Usage: | 41 | * Usage: |
| 40 | * dcache_inode_lock protects: | 42 | * dcache_inode_lock protects: |
| 41 | * - i_dentry, d_alias, d_inode | 43 | * - i_dentry, d_alias, d_inode |
| 42 | * dcache_hash_lock protects: | 44 | * dcache_hash_bucket lock protects: |
| 43 | * - the dcache hash table, s_anon lists | 45 | * - the dcache hash table |
| 46 | * s_anon bl list spinlock protects: | ||
| 47 | * - the s_anon list (see __d_drop) | ||
| 44 | * dcache_lru_lock protects: | 48 | * dcache_lru_lock protects: |
| 45 | * - the dcache lru lists and counters | 49 | * - the dcache lru lists and counters |
| 46 | * d_lock protects: | 50 | * d_lock protects: |
| @@ -57,7 +61,8 @@ | |||
| 57 | * dcache_inode_lock | 61 | * dcache_inode_lock |
| 58 | * dentry->d_lock | 62 | * dentry->d_lock |
| 59 | * dcache_lru_lock | 63 | * dcache_lru_lock |
| 60 | * dcache_hash_lock | 64 | * dcache_hash_bucket lock |
| 65 | * s_anon lock | ||
| 61 | * | 66 | * |
| 62 | * If there is an ancestor relationship: | 67 | * If there is an ancestor relationship: |
| 63 | * dentry->d_parent->...->d_parent->d_lock | 68 | * dentry->d_parent->...->d_parent->d_lock |
| @@ -74,7 +79,6 @@ int sysctl_vfs_cache_pressure __read_mostly = 100; | |||
| 74 | EXPORT_SYMBOL_GPL(sysctl_vfs_cache_pressure); | 79 | EXPORT_SYMBOL_GPL(sysctl_vfs_cache_pressure); |
| 75 | 80 | ||
| 76 | __cacheline_aligned_in_smp DEFINE_SPINLOCK(dcache_inode_lock); | 81 | __cacheline_aligned_in_smp DEFINE_SPINLOCK(dcache_inode_lock); |
| 77 | static __cacheline_aligned_in_smp DEFINE_SPINLOCK(dcache_hash_lock); | ||
| 78 | static __cacheline_aligned_in_smp DEFINE_SPINLOCK(dcache_lru_lock); | 82 | static __cacheline_aligned_in_smp DEFINE_SPINLOCK(dcache_lru_lock); |
| 79 | __cacheline_aligned_in_smp DEFINE_SEQLOCK(rename_lock); | 83 | __cacheline_aligned_in_smp DEFINE_SEQLOCK(rename_lock); |
| 80 | 84 | ||
| @@ -96,7 +100,29 @@ static struct kmem_cache *dentry_cache __read_mostly; | |||
| 96 | 100 | ||
| 97 | static unsigned int d_hash_mask __read_mostly; | 101 | static unsigned int d_hash_mask __read_mostly; |
| 98 | static unsigned int d_hash_shift __read_mostly; | 102 | static unsigned int d_hash_shift __read_mostly; |
| 99 | static struct hlist_head *dentry_hashtable __read_mostly; | 103 | |
| 104 | struct dcache_hash_bucket { | ||
| 105 | struct hlist_bl_head head; | ||
| 106 | }; | ||
| 107 | static struct dcache_hash_bucket *dentry_hashtable __read_mostly; | ||
| 108 | |||
| 109 | static inline struct dcache_hash_bucket *d_hash(struct dentry *parent, | ||
| 110 | unsigned long hash) | ||
| 111 | { | ||
| 112 | hash += ((unsigned long) parent ^ GOLDEN_RATIO_PRIME) / L1_CACHE_BYTES; | ||
| 113 | hash = hash ^ ((hash ^ GOLDEN_RATIO_PRIME) >> D_HASHBITS); | ||
| 114 | return dentry_hashtable + (hash & D_HASHMASK); | ||
| 115 | } | ||
| 116 | |||
| 117 | static inline void spin_lock_bucket(struct dcache_hash_bucket *b) | ||
| 118 | { | ||
| 119 | bit_spin_lock(0, (unsigned long *)&b->head.first); | ||
| 120 | } | ||
| 121 | |||
| 122 | static inline void spin_unlock_bucket(struct dcache_hash_bucket *b) | ||
| 123 | { | ||
| 124 | __bit_spin_unlock(0, (unsigned long *)&b->head.first); | ||
| 125 | } | ||
| 100 | 126 | ||
| 101 | /* Statistics gathering. */ | 127 | /* Statistics gathering. */ |
| 102 | struct dentry_stat_t dentry_stat = { | 128 | struct dentry_stat_t dentry_stat = { |
| @@ -144,7 +170,7 @@ static void d_free(struct dentry *dentry) | |||
| 144 | dentry->d_op->d_release(dentry); | 170 | dentry->d_op->d_release(dentry); |
| 145 | 171 | ||
| 146 | /* if dentry was never inserted into hash, immediate free is OK */ | 172 | /* if dentry was never inserted into hash, immediate free is OK */ |
| 147 | if (hlist_unhashed(&dentry->d_hash)) | 173 | if (hlist_bl_unhashed(&dentry->d_hash)) |
| 148 | __d_free(&dentry->d_u.d_rcu); | 174 | __d_free(&dentry->d_u.d_rcu); |
| 149 | else | 175 | else |
| 150 | call_rcu(&dentry->d_u.d_rcu, __d_free); | 176 | call_rcu(&dentry->d_u.d_rcu, __d_free); |
| @@ -302,11 +328,27 @@ static struct dentry *d_kill(struct dentry *dentry, struct dentry *parent) | |||
| 302 | void __d_drop(struct dentry *dentry) | 328 | void __d_drop(struct dentry *dentry) |
| 303 | { | 329 | { |
| 304 | if (!(dentry->d_flags & DCACHE_UNHASHED)) { | 330 | if (!(dentry->d_flags & DCACHE_UNHASHED)) { |
| 305 | dentry->d_flags |= DCACHE_UNHASHED; | 331 | if (unlikely(dentry->d_flags & DCACHE_DISCONNECTED)) { |
| 306 | spin_lock(&dcache_hash_lock); | 332 | bit_spin_lock(0, |
| 307 | hlist_del_rcu(&dentry->d_hash); | 333 | (unsigned long *)&dentry->d_sb->s_anon.first); |
| 308 | spin_unlock(&dcache_hash_lock); | 334 | dentry->d_flags |= DCACHE_UNHASHED; |
| 309 | dentry_rcuwalk_barrier(dentry); | 335 | hlist_bl_del_init(&dentry->d_hash); |
| 336 | __bit_spin_unlock(0, | ||
| 337 | (unsigned long *)&dentry->d_sb->s_anon.first); | ||
| 338 | } else { | ||
| 339 | struct dcache_hash_bucket *b; | ||
| 340 | b = d_hash(dentry->d_parent, dentry->d_name.hash); | ||
| 341 | spin_lock_bucket(b); | ||
| 342 | /* | ||
| 343 | * We may not actually need to put DCACHE_UNHASHED | ||
| 344 | * manipulations under the hash lock, but follow | ||
| 345 | * the principle of least surprise. | ||
| 346 | */ | ||
| 347 | dentry->d_flags |= DCACHE_UNHASHED; | ||
| 348 | hlist_bl_del_rcu(&dentry->d_hash); | ||
| 349 | spin_unlock_bucket(b); | ||
| 350 | dentry_rcuwalk_barrier(dentry); | ||
| 351 | } | ||
| 310 | } | 352 | } |
| 311 | } | 353 | } |
| 312 | EXPORT_SYMBOL(__d_drop); | 354 | EXPORT_SYMBOL(__d_drop); |
| @@ -961,8 +1003,8 @@ void shrink_dcache_for_umount(struct super_block *sb) | |||
| 961 | spin_unlock(&dentry->d_lock); | 1003 | spin_unlock(&dentry->d_lock); |
| 962 | shrink_dcache_for_umount_subtree(dentry); | 1004 | shrink_dcache_for_umount_subtree(dentry); |
| 963 | 1005 | ||
| 964 | while (!hlist_empty(&sb->s_anon)) { | 1006 | while (!hlist_bl_empty(&sb->s_anon)) { |
| 965 | dentry = hlist_entry(sb->s_anon.first, struct dentry, d_hash); | 1007 | dentry = hlist_bl_entry(hlist_bl_first(&sb->s_anon), struct dentry, d_hash); |
| 966 | shrink_dcache_for_umount_subtree(dentry); | 1008 | shrink_dcache_for_umount_subtree(dentry); |
| 967 | } | 1009 | } |
| 968 | } | 1010 | } |
| @@ -1263,7 +1305,7 @@ struct dentry *d_alloc(struct dentry * parent, const struct qstr *name) | |||
| 1263 | dentry->d_sb = NULL; | 1305 | dentry->d_sb = NULL; |
| 1264 | dentry->d_op = NULL; | 1306 | dentry->d_op = NULL; |
| 1265 | dentry->d_fsdata = NULL; | 1307 | dentry->d_fsdata = NULL; |
| 1266 | INIT_HLIST_NODE(&dentry->d_hash); | 1308 | INIT_HLIST_BL_NODE(&dentry->d_hash); |
| 1267 | INIT_LIST_HEAD(&dentry->d_lru); | 1309 | INIT_LIST_HEAD(&dentry->d_lru); |
| 1268 | INIT_LIST_HEAD(&dentry->d_subdirs); | 1310 | INIT_LIST_HEAD(&dentry->d_subdirs); |
| 1269 | INIT_LIST_HEAD(&dentry->d_alias); | 1311 | INIT_LIST_HEAD(&dentry->d_alias); |
| @@ -1459,14 +1501,6 @@ struct dentry * d_alloc_root(struct inode * root_inode) | |||
| 1459 | } | 1501 | } |
| 1460 | EXPORT_SYMBOL(d_alloc_root); | 1502 | EXPORT_SYMBOL(d_alloc_root); |
| 1461 | 1503 | ||
| 1462 | static inline struct hlist_head *d_hash(struct dentry *parent, | ||
| 1463 | unsigned long hash) | ||
| 1464 | { | ||
| 1465 | hash += ((unsigned long) parent ^ GOLDEN_RATIO_PRIME) / L1_CACHE_BYTES; | ||
| 1466 | hash = hash ^ ((hash ^ GOLDEN_RATIO_PRIME) >> D_HASHBITS); | ||
| 1467 | return dentry_hashtable + (hash & D_HASHMASK); | ||
| 1468 | } | ||
| 1469 | |||
| 1470 | /** | 1504 | /** |
| 1471 | * d_obtain_alias - find or allocate a dentry for a given inode | 1505 | * d_obtain_alias - find or allocate a dentry for a given inode |
| 1472 | * @inode: inode to allocate the dentry for | 1506 | * @inode: inode to allocate the dentry for |
| @@ -1521,11 +1555,11 @@ struct dentry *d_obtain_alias(struct inode *inode) | |||
| 1521 | tmp->d_sb = inode->i_sb; | 1555 | tmp->d_sb = inode->i_sb; |
| 1522 | tmp->d_inode = inode; | 1556 | tmp->d_inode = inode; |
| 1523 | tmp->d_flags |= DCACHE_DISCONNECTED; | 1557 | tmp->d_flags |= DCACHE_DISCONNECTED; |
| 1524 | tmp->d_flags &= ~DCACHE_UNHASHED; | ||
| 1525 | list_add(&tmp->d_alias, &inode->i_dentry); | 1558 | list_add(&tmp->d_alias, &inode->i_dentry); |
| 1526 | spin_lock(&dcache_hash_lock); | 1559 | bit_spin_lock(0, (unsigned long *)&tmp->d_sb->s_anon.first); |
| 1527 | hlist_add_head(&tmp->d_hash, &inode->i_sb->s_anon); | 1560 | tmp->d_flags &= ~DCACHE_UNHASHED; |
| 1528 | spin_unlock(&dcache_hash_lock); | 1561 | hlist_bl_add_head(&tmp->d_hash, &tmp->d_sb->s_anon); |
| 1562 | __bit_spin_unlock(0, (unsigned long *)&tmp->d_sb->s_anon.first); | ||
| 1529 | spin_unlock(&tmp->d_lock); | 1563 | spin_unlock(&tmp->d_lock); |
| 1530 | spin_unlock(&dcache_inode_lock); | 1564 | spin_unlock(&dcache_inode_lock); |
| 1531 | 1565 | ||
| @@ -1567,7 +1601,7 @@ struct dentry *d_splice_alias(struct inode *inode, struct dentry *dentry) | |||
| 1567 | d_move(new, dentry); | 1601 | d_move(new, dentry); |
| 1568 | iput(inode); | 1602 | iput(inode); |
| 1569 | } else { | 1603 | } else { |
| 1570 | /* already taking dcache_inode_lock, so d_add() by hand */ | 1604 | /* already got dcache_inode_lock, so d_add() by hand */ |
| 1571 | __d_instantiate(dentry, inode); | 1605 | __d_instantiate(dentry, inode); |
| 1572 | spin_unlock(&dcache_inode_lock); | 1606 | spin_unlock(&dcache_inode_lock); |
| 1573 | security_d_instantiate(dentry, inode); | 1607 | security_d_instantiate(dentry, inode); |
| @@ -1702,8 +1736,8 @@ struct dentry *__d_lookup_rcu(struct dentry *parent, struct qstr *name, | |||
| 1702 | unsigned int len = name->len; | 1736 | unsigned int len = name->len; |
| 1703 | unsigned int hash = name->hash; | 1737 | unsigned int hash = name->hash; |
| 1704 | const unsigned char *str = name->name; | ||
