diff options
author | Al Viro <viro@zeniv.linux.org.uk> | 2014-10-26 19:19:16 -0400 |
---|---|---|
committer | Al Viro <viro@zeniv.linux.org.uk> | 2014-11-03 15:20:29 -0500 |
commit | 946e51f2bf37f1656916eb75bd0742ba33983c28 (patch) | |
tree | e3d2672edeec1117ceda1e8e195eaa8d1c0f5135 /fs/dcache.c | |
parent | a7400222e3eb7d5ce3820d2234905bbeafabd171 (diff) |
move d_rcu from overlapping d_child to overlapping d_alias
Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
Diffstat (limited to 'fs/dcache.c')
-rw-r--r-- | fs/dcache.c | 53 |
1 files changed, 26 insertions, 27 deletions
diff --git a/fs/dcache.c b/fs/dcache.c index 3ffef7f4e5cd..8b4c45e40834 100644 --- a/fs/dcache.c +++ b/fs/dcache.c | |||
@@ -44,7 +44,7 @@ | |||
44 | /* | 44 | /* |
45 | * Usage: | 45 | * Usage: |
46 | * dcache->d_inode->i_lock protects: | 46 | * dcache->d_inode->i_lock protects: |
47 | * - i_dentry, d_alias, d_inode of aliases | 47 | * - i_dentry, d_u.d_alias, d_inode of aliases |
48 | * dcache_hash_bucket lock protects: | 48 | * dcache_hash_bucket lock protects: |
49 | * - the dcache hash table | 49 | * - the dcache hash table |
50 | * s_anon bl list spinlock protects: | 50 | * s_anon bl list spinlock protects: |
@@ -59,7 +59,7 @@ | |||
59 | * - d_unhashed() | 59 | * - d_unhashed() |
60 | * - d_parent and d_subdirs | 60 | * - d_parent and d_subdirs |
61 | * - childrens' d_child and d_parent | 61 | * - childrens' d_child and d_parent |
62 | * - d_alias, d_inode | 62 | * - d_u.d_alias, d_inode |
63 | * | 63 | * |
64 | * Ordering: | 64 | * Ordering: |
65 | * dentry->d_inode->i_lock | 65 | * dentry->d_inode->i_lock |
@@ -252,14 +252,12 @@ static void __d_free(struct rcu_head *head) | |||
252 | { | 252 | { |
253 | struct dentry *dentry = container_of(head, struct dentry, d_u.d_rcu); | 253 | struct dentry *dentry = container_of(head, struct dentry, d_u.d_rcu); |
254 | 254 | ||
255 | WARN_ON(!hlist_unhashed(&dentry->d_alias)); | ||
256 | kmem_cache_free(dentry_cache, dentry); | 255 | kmem_cache_free(dentry_cache, dentry); |
257 | } | 256 | } |
258 | 257 | ||
259 | static void __d_free_external(struct rcu_head *head) | 258 | static void __d_free_external(struct rcu_head *head) |
260 | { | 259 | { |
261 | struct dentry *dentry = container_of(head, struct dentry, d_u.d_rcu); | 260 | struct dentry *dentry = container_of(head, struct dentry, d_u.d_rcu); |
262 | WARN_ON(!hlist_unhashed(&dentry->d_alias)); | ||
263 | kfree(external_name(dentry)); | 261 | kfree(external_name(dentry)); |
264 | kmem_cache_free(dentry_cache, dentry); | 262 | kmem_cache_free(dentry_cache, dentry); |
265 | } | 263 | } |
@@ -271,6 +269,7 @@ static inline int dname_external(const struct dentry *dentry) | |||
271 | 269 | ||
272 | static void dentry_free(struct dentry *dentry) | 270 | static void dentry_free(struct dentry *dentry) |
273 | { | 271 | { |
272 | WARN_ON(!hlist_unhashed(&dentry->d_u.d_alias)); | ||
274 | if (unlikely(dname_external(dentry))) { | 273 | if (unlikely(dname_external(dentry))) { |
275 | struct external_name *p = external_name(dentry); | 274 | struct external_name *p = external_name(dentry); |
276 | if (likely(atomic_dec_and_test(&p->u.count))) { | 275 | if (likely(atomic_dec_and_test(&p->u.count))) { |
@@ -311,7 +310,7 @@ static void dentry_iput(struct dentry * dentry) | |||
311 | struct inode *inode = dentry->d_inode; | 310 | struct inode *inode = dentry->d_inode; |
312 | if (inode) { | 311 | if (inode) { |
313 | dentry->d_inode = NULL; | 312 | dentry->d_inode = NULL; |
314 | hlist_del_init(&dentry->d_alias); | 313 | hlist_del_init(&dentry->d_u.d_alias); |
315 | spin_unlock(&dentry->d_lock); | 314 | spin_unlock(&dentry->d_lock); |
316 | spin_unlock(&inode->i_lock); | 315 | spin_unlock(&inode->i_lock); |
317 | if (!inode->i_nlink) | 316 | if (!inode->i_nlink) |
@@ -336,7 +335,7 @@ static void dentry_unlink_inode(struct dentry * dentry) | |||
336 | struct inode *inode = dentry->d_inode; | 335 | struct inode *inode = dentry->d_inode; |
337 | __d_clear_type(dentry); | 336 | __d_clear_type(dentry); |
338 | dentry->d_inode = NULL; | 337 | dentry->d_inode = NULL; |
339 | hlist_del_init(&dentry->d_alias); | 338 | hlist_del_init(&dentry->d_u.d_alias); |
340 | dentry_rcuwalk_barrier(dentry); | 339 | dentry_rcuwalk_barrier(dentry); |
341 | spin_unlock(&dentry->d_lock); | 340 | spin_unlock(&dentry->d_lock); |
342 | spin_unlock(&inode->i_lock); | 341 | spin_unlock(&inode->i_lock); |
@@ -496,7 +495,7 @@ static void __dentry_kill(struct dentry *dentry) | |||
496 | } | 495 | } |
497 | /* if it was on the hash then remove it */ | 496 | /* if it was on the hash then remove it */ |
498 | __d_drop(dentry); | 497 | __d_drop(dentry); |
499 | list_del(&dentry->d_u.d_child); | 498 | list_del(&dentry->d_child); |
500 | /* | 499 | /* |
501 | * Inform d_walk() that we are no longer attached to the | 500 | * Inform d_walk() that we are no longer attached to the |
502 | * dentry tree | 501 | * dentry tree |
@@ -722,7 +721,7 @@ static struct dentry *__d_find_alias(struct inode *inode) | |||
722 | 721 | ||
723 | again: | 722 | again: |
724 | discon_alias = NULL; | 723 | discon_alias = NULL; |
725 | hlist_for_each_entry(alias, &inode->i_dentry, d_alias) { | 724 | hlist_for_each_entry(alias, &inode->i_dentry, d_u.d_alias) { |
726 | spin_lock(&alias->d_lock); | 725 | spin_lock(&alias->d_lock); |
727 | if (S_ISDIR(inode->i_mode) || !d_unhashed(alias)) { | 726 | if (S_ISDIR(inode->i_mode) || !d_unhashed(alias)) { |
728 | if (IS_ROOT(alias) && | 727 | if (IS_ROOT(alias) && |
@@ -772,7 +771,7 @@ void d_prune_aliases(struct inode *inode) | |||
772 | struct dentry *dentry; | 771 | struct dentry *dentry; |
773 | restart: | 772 | restart: |
774 | spin_lock(&inode->i_lock); | 773 | spin_lock(&inode->i_lock); |
775 | hlist_for_each_entry(dentry, &inode->i_dentry, d_alias) { | 774 | hlist_for_each_entry(dentry, &inode->i_dentry, d_u.d_alias) { |
776 | spin_lock(&dentry->d_lock); | 775 | spin_lock(&dentry->d_lock); |
777 | if (!dentry->d_lockref.count) { | 776 | if (!dentry->d_lockref.count) { |
778 | struct dentry *parent = lock_parent(dentry); | 777 | struct dentry *parent = lock_parent(dentry); |
@@ -1050,7 +1049,7 @@ repeat: | |||
1050 | resume: | 1049 | resume: |
1051 | while (next != &this_parent->d_subdirs) { | 1050 | while (next != &this_parent->d_subdirs) { |
1052 | struct list_head *tmp = next; | 1051 | struct list_head *tmp = next; |
1053 | struct dentry *dentry = list_entry(tmp, struct dentry, d_u.d_child); | 1052 | struct dentry *dentry = list_entry(tmp, struct dentry, d_child); |
1054 | next = tmp->next; | 1053 | next = tmp->next; |
1055 | 1054 | ||
1056 | spin_lock_nested(&dentry->d_lock, DENTRY_D_LOCK_NESTED); | 1055 | spin_lock_nested(&dentry->d_lock, DENTRY_D_LOCK_NESTED); |
@@ -1102,7 +1101,7 @@ resume: | |||
1102 | goto rename_retry; | 1101 | goto rename_retry; |
1103 | } | 1102 | } |
1104 | rcu_read_unlock(); | 1103 | rcu_read_unlock(); |
1105 | next = child->d_u.d_child.next; | 1104 | next = child->d_child.next; |
1106 | goto resume; | 1105 | goto resume; |
1107 | } | 1106 | } |
1108 | if (need_seqretry(&rename_lock, seq)) { | 1107 | if (need_seqretry(&rename_lock, seq)) { |
@@ -1454,8 +1453,8 @@ struct dentry *__d_alloc(struct super_block *sb, const struct qstr *name) | |||
1454 | INIT_HLIST_BL_NODE(&dentry->d_hash); | 1453 | INIT_HLIST_BL_NODE(&dentry->d_hash); |
1455 | INIT_LIST_HEAD(&dentry->d_lru); | 1454 | INIT_LIST_HEAD(&dentry->d_lru); |
1456 | INIT_LIST_HEAD(&dentry->d_subdirs); | 1455 | INIT_LIST_HEAD(&dentry->d_subdirs); |
1457 | INIT_HLIST_NODE(&dentry->d_alias); | 1456 | INIT_HLIST_NODE(&dentry->d_u.d_alias); |
1458 | INIT_LIST_HEAD(&dentry->d_u.d_child); | 1457 | INIT_LIST_HEAD(&dentry->d_child); |
1459 | d_set_d_op(dentry, dentry->d_sb->s_d_op); | 1458 | d_set_d_op(dentry, dentry->d_sb->s_d_op); |
1460 | 1459 | ||
1461 | this_cpu_inc(nr_dentry); | 1460 | this_cpu_inc(nr_dentry); |
@@ -1485,7 +1484,7 @@ struct dentry *d_alloc(struct dentry * parent, const struct qstr *name) | |||
1485 | */ | 1484 | */ |
1486 | __dget_dlock(parent); | 1485 | __dget_dlock(parent); |
1487 | dentry->d_parent = parent; | 1486 | dentry->d_parent = parent; |
1488 | list_add(&dentry->d_u.d_child, &parent->d_subdirs); | 1487 | list_add(&dentry->d_child, &parent->d_subdirs); |
1489 | spin_unlock(&parent->d_lock); | 1488 | spin_unlock(&parent->d_lock); |
1490 | 1489 | ||
1491 | return dentry; | 1490 | return dentry; |
@@ -1578,7 +1577,7 @@ static void __d_instantiate(struct dentry *dentry, struct inode *inode) | |||
1578 | spin_lock(&dentry->d_lock); | 1577 | spin_lock(&dentry->d_lock); |
1579 | __d_set_type(dentry, add_flags); | 1578 | __d_set_type(dentry, add_flags); |
1580 | if (inode) | 1579 | if (inode) |
1581 | hlist_add_head(&dentry->d_alias, &inode->i_dentry); | 1580 | hlist_add_head(&dentry->d_u.d_alias, &inode->i_dentry); |
1582 | dentry->d_inode = inode; | 1581 | dentry->d_inode = inode; |
1583 | dentry_rcuwalk_barrier(dentry); | 1582 | dentry_rcuwalk_barrier(dentry); |
1584 | spin_unlock(&dentry->d_lock); | 1583 | spin_unlock(&dentry->d_lock); |
@@ -1602,7 +1601,7 @@ static void __d_instantiate(struct dentry *dentry, struct inode *inode) | |||
1602 | 1601 | ||
1603 | void d_instantiate(struct dentry *entry, struct inode * inode) | 1602 | void d_instantiate(struct dentry *entry, struct inode * inode) |
1604 | { | 1603 | { |
1605 | BUG_ON(!hlist_unhashed(&entry->d_alias)); | 1604 | BUG_ON(!hlist_unhashed(&entry->d_u.d_alias)); |
1606 | if (inode) | 1605 | if (inode) |
1607 | spin_lock(&inode->i_lock); | 1606 | spin_lock(&inode->i_lock); |
1608 | __d_instantiate(entry, inode); | 1607 | __d_instantiate(entry, inode); |
@@ -1641,7 +1640,7 @@ static struct dentry *__d_instantiate_unique(struct dentry *entry, | |||
1641 | return NULL; | 1640 | return NULL; |
1642 | } | 1641 | } |
1643 | 1642 | ||
1644 | hlist_for_each_entry(alias, &inode->i_dentry, d_alias) { | 1643 | hlist_for_each_entry(alias, &inode->i_dentry, d_u.d_alias) { |
1645 | /* | 1644 | /* |
1646 | * Don't need alias->d_lock here, because aliases with | 1645 | * Don't need alias->d_lock here, because aliases with |
1647 | * d_parent == entry->d_parent are not subject to name or | 1646 | * d_parent == entry->d_parent are not subject to name or |
@@ -1667,7 +1666,7 @@ struct dentry *d_instantiate_unique(struct dentry *entry, struct inode *inode) | |||
1667 | { | 1666 | { |
1668 | struct dentry *result; | 1667 | struct dentry *result; |
1669 | 1668 | ||
1670 | BUG_ON(!hlist_unhashed(&entry->d_alias)); | 1669 | BUG_ON(!hlist_unhashed(&entry->d_u.d_alias)); |
1671 | 1670 | ||
1672 | if (inode) | 1671 | if (inode) |
1673 | spin_lock(&inode->i_lock); | 1672 | spin_lock(&inode->i_lock); |
@@ -1698,7 +1697,7 @@ EXPORT_SYMBOL(d_instantiate_unique); | |||
1698 | */ | 1697 | */ |
1699 | int d_instantiate_no_diralias(struct dentry *entry, struct inode *inode) | 1698 | int d_instantiate_no_diralias(struct dentry *entry, struct inode *inode) |
1700 | { | 1699 | { |
1701 | BUG_ON(!hlist_unhashed(&entry->d_alias)); | 1700 | BUG_ON(!hlist_unhashed(&entry->d_u.d_alias)); |
1702 | 1701 | ||
1703 | spin_lock(&inode->i_lock); | 1702 | spin_lock(&inode->i_lock); |
1704 | if (S_ISDIR(inode->i_mode) && !hlist_empty(&inode->i_dentry)) { | 1703 | if (S_ISDIR(inode->i_mode) && !hlist_empty(&inode->i_dentry)) { |
@@ -1737,7 +1736,7 @@ static struct dentry * __d_find_any_alias(struct inode *inode) | |||
1737 | 1736 | ||
1738 | if (hlist_empty(&inode->i_dentry)) | 1737 | if (hlist_empty(&inode->i_dentry)) |
1739 | return NULL; | 1738 | return NULL; |
1740 | alias = hlist_entry(inode->i_dentry.first, struct dentry, d_alias); | 1739 | alias = hlist_entry(inode->i_dentry.first, struct dentry, d_u.d_alias); |
1741 | __dget(alias); | 1740 | __dget(alias); |
1742 | return alias; | 1741 | return alias; |
1743 | } | 1742 | } |
@@ -1799,7 +1798,7 @@ static struct dentry *__d_obtain_alias(struct inode *inode, int disconnected) | |||
1799 | spin_lock(&tmp->d_lock); | 1798 | spin_lock(&tmp->d_lock); |
1800 | tmp->d_inode = inode; | 1799 | tmp->d_inode = inode; |
1801 | tmp->d_flags |= add_flags; | 1800 | tmp->d_flags |= add_flags; |
1802 | hlist_add_head(&tmp->d_alias, &inode->i_dentry); | 1801 | hlist_add_head(&tmp->d_u.d_alias, &inode->i_dentry); |
1803 | hlist_bl_lock(&tmp->d_sb->s_anon); | 1802 | hlist_bl_lock(&tmp->d_sb->s_anon); |
1804 | hlist_bl_add_head(&tmp->d_hash, &tmp->d_sb->s_anon); | 1803 | hlist_bl_add_head(&tmp->d_hash, &tmp->d_sb->s_anon); |
1805 | hlist_bl_unlock(&tmp->d_sb->s_anon); | 1804 | hlist_bl_unlock(&tmp->d_sb->s_anon); |
@@ -2234,7 +2233,7 @@ int d_validate(struct dentry *dentry, struct dentry *dparent) | |||
2234 | struct dentry *child; | 2233 | struct dentry *child; |
2235 | 2234 | ||
2236 | spin_lock(&dparent->d_lock); | 2235 | spin_lock(&dparent->d_lock); |
2237 | list_for_each_entry(child, &dparent->d_subdirs, d_u.d_child) { | 2236 | list_for_each_entry(child, &dparent->d_subdirs, d_child) { |
2238 | if (dentry == child) { | 2237 | if (dentry == child) { |
2239 | spin_lock_nested(&dentry->d_lock, DENTRY_D_LOCK_NESTED); | 2238 | spin_lock_nested(&dentry->d_lock, DENTRY_D_LOCK_NESTED); |
2240 | __dget_dlock(dentry); | 2239 | __dget_dlock(dentry); |
@@ -2525,13 +2524,13 @@ static void __d_move(struct dentry *dentry, struct dentry *target, | |||
2525 | /* splicing a tree */ | 2524 | /* splicing a tree */ |
2526 | dentry->d_parent = target->d_parent; | 2525 | dentry->d_parent = target->d_parent; |
2527 | target->d_parent = target; | 2526 | target->d_parent = target; |
2528 | list_del_init(&target->d_u.d_child); | 2527 | list_del_init(&target->d_child); |
2529 | list_move(&dentry->d_u.d_child, &dentry->d_parent->d_subdirs); | 2528 | list_move(&dentry->d_child, &dentry->d_parent->d_subdirs); |
2530 | } else { | 2529 | } else { |
2531 | /* swapping two dentries */ | 2530 | /* swapping two dentries */ |
2532 | swap(dentry->d_parent, target->d_parent); | 2531 | swap(dentry->d_parent, target->d_parent); |
2533 | list_move(&target->d_u.d_child, &target->d_parent->d_subdirs); | 2532 | list_move(&target->d_child, &target->d_parent->d_subdirs); |
2534 | list_move(&dentry->d_u.d_child, &dentry->d_parent->d_subdirs); | 2533 | list_move(&dentry->d_child, &dentry->d_parent->d_subdirs); |
2535 | if (exchange) | 2534 | if (exchange) |
2536 | fsnotify_d_move(target); | 2535 | fsnotify_d_move(target); |
2537 | fsnotify_d_move(dentry); | 2536 | fsnotify_d_move(dentry); |
@@ -3320,7 +3319,7 @@ void d_tmpfile(struct dentry *dentry, struct inode *inode) | |||
3320 | { | 3319 | { |
3321 | inode_dec_link_count(inode); | 3320 | inode_dec_link_count(inode); |
3322 | BUG_ON(dentry->d_name.name != dentry->d_iname || | 3321 | BUG_ON(dentry->d_name.name != dentry->d_iname || |
3323 | !hlist_unhashed(&dentry->d_alias) || | 3322 | !hlist_unhashed(&dentry->d_u.d_alias) || |
3324 | !d_unlinked(dentry)); | 3323 | !d_unlinked(dentry)); |
3325 | spin_lock(&dentry->d_parent->d_lock); | 3324 | spin_lock(&dentry->d_parent->d_lock); |
3326 | spin_lock_nested(&dentry->d_lock, DENTRY_D_LOCK_NESTED); | 3325 | spin_lock_nested(&dentry->d_lock, DENTRY_D_LOCK_NESTED); |