diff options
author | Nick Piggin <npiggin@kernel.dk> | 2011-01-07 01:49:35 -0500 |
---|---|---|
committer | Nick Piggin <npiggin@kernel.dk> | 2011-01-07 01:50:22 -0500 |
commit | b23fb0a60379a95e10c671f646b259ea2558421e (patch) | |
tree | 7c3644b91241d32fda502a7be0b78e4c225f8091 /fs/dcache.c | |
parent | 2fd6b7f50797f2e993eea59e0a0b8c6399c811dc (diff) |
fs: scale inode alias list
Add a new lock, dcache_inode_lock, to protect the inode's i_dentry list
from concurrent modification. d_alias is also protected by d_lock.
Signed-off-by: Nick Piggin <npiggin@kernel.dk>
Diffstat (limited to 'fs/dcache.c')
-rw-r--r-- | fs/dcache.c | 66 |
1 files changed, 58 insertions, 8 deletions
diff --git a/fs/dcache.c b/fs/dcache.c index a661247a20d5..de38680ee0ed 100644 --- a/fs/dcache.c +++ b/fs/dcache.c | |||
@@ -37,6 +37,8 @@ | |||
37 | 37 | ||
38 | /* | 38 | /* |
39 | * Usage: | 39 | * Usage: |
40 | * dcache_inode_lock protects: | ||
41 | * - i_dentry, d_alias, d_inode | ||
40 | * dcache_hash_lock protects: | 42 | * dcache_hash_lock protects: |
41 | * - the dcache hash table, s_anon lists | 43 | * - the dcache hash table, s_anon lists |
42 | * dcache_lru_lock protects: | 44 | * dcache_lru_lock protects: |
@@ -49,12 +51,14 @@ | |||
49 | * - d_unhashed() | 51 | * - d_unhashed() |
50 | * - d_parent and d_subdirs | 52 | * - d_parent and d_subdirs |
51 | * - childrens' d_child and d_parent | 53 | * - childrens' d_child and d_parent |
54 | * - d_alias, d_inode | ||
52 | * | 55 | * |
53 | * Ordering: | 56 | * Ordering: |
54 | * dcache_lock | 57 | * dcache_lock |
55 | * dentry->d_lock | 58 | * dcache_inode_lock |
56 | * dcache_lru_lock | 59 | * dentry->d_lock |
57 | * dcache_hash_lock | 60 | * dcache_lru_lock |
61 | * dcache_hash_lock | ||
58 | * | 62 | * |
59 | * If there is an ancestor relationship: | 63 | * If there is an ancestor relationship: |
60 | * dentry->d_parent->...->d_parent->d_lock | 64 | * dentry->d_parent->...->d_parent->d_lock |
@@ -70,11 +74,13 @@ | |||
70 | int sysctl_vfs_cache_pressure __read_mostly = 100; | 74 | int sysctl_vfs_cache_pressure __read_mostly = 100; |
71 | EXPORT_SYMBOL_GPL(sysctl_vfs_cache_pressure); | 75 | EXPORT_SYMBOL_GPL(sysctl_vfs_cache_pressure); |
72 | 76 | ||
77 | __cacheline_aligned_in_smp DEFINE_SPINLOCK(dcache_inode_lock); | ||
73 | static __cacheline_aligned_in_smp DEFINE_SPINLOCK(dcache_hash_lock); | 78 | static __cacheline_aligned_in_smp DEFINE_SPINLOCK(dcache_hash_lock); |
74 | static __cacheline_aligned_in_smp DEFINE_SPINLOCK(dcache_lru_lock); | 79 | static __cacheline_aligned_in_smp DEFINE_SPINLOCK(dcache_lru_lock); |
75 | __cacheline_aligned_in_smp DEFINE_SPINLOCK(dcache_lock); | 80 | __cacheline_aligned_in_smp DEFINE_SPINLOCK(dcache_lock); |
76 | __cacheline_aligned_in_smp DEFINE_SEQLOCK(rename_lock); | 81 | __cacheline_aligned_in_smp DEFINE_SEQLOCK(rename_lock); |
77 | 82 | ||
83 | EXPORT_SYMBOL(dcache_inode_lock); | ||
78 | EXPORT_SYMBOL(dcache_lock); | 84 | EXPORT_SYMBOL(dcache_lock); |
79 | 85 | ||
80 | static struct kmem_cache *dentry_cache __read_mostly; | 86 | static struct kmem_cache *dentry_cache __read_mostly; |
@@ -154,6 +160,7 @@ static void d_free(struct dentry *dentry) | |||
154 | */ | 160 | */ |
155 | static void dentry_iput(struct dentry * dentry) | 161 | static void dentry_iput(struct dentry * dentry) |
156 | __releases(dentry->d_lock) | 162 | __releases(dentry->d_lock) |
163 | __releases(dcache_inode_lock) | ||
157 | __releases(dcache_lock) | 164 | __releases(dcache_lock) |
158 | { | 165 | { |
159 | struct inode *inode = dentry->d_inode; | 166 | struct inode *inode = dentry->d_inode; |
@@ -161,6 +168,7 @@ static void dentry_iput(struct dentry * dentry) | |||
161 | dentry->d_inode = NULL; | 168 | dentry->d_inode = NULL; |
162 | list_del_init(&dentry->d_alias); | 169 | list_del_init(&dentry->d_alias); |
163 | spin_unlock(&dentry->d_lock); | 170 | spin_unlock(&dentry->d_lock); |
171 | spin_unlock(&dcache_inode_lock); | ||
164 | spin_unlock(&dcache_lock); | 172 | spin_unlock(&dcache_lock); |
165 | if (!inode->i_nlink) | 173 | if (!inode->i_nlink) |
166 | fsnotify_inoderemove(inode); | 174 | fsnotify_inoderemove(inode); |
@@ -170,6 +178,7 @@ static void dentry_iput(struct dentry * dentry) | |||
170 | iput(inode); | 178 | iput(inode); |
171 | } else { | 179 | } else { |
172 | spin_unlock(&dentry->d_lock); | 180 | spin_unlock(&dentry->d_lock); |
181 | spin_unlock(&dcache_inode_lock); | ||
173 | spin_unlock(&dcache_lock); | 182 | spin_unlock(&dcache_lock); |
174 | } | 183 | } |
175 | } | 184 | } |
@@ -231,6 +240,7 @@ static void dentry_lru_move_tail(struct dentry *dentry) | |||
231 | static struct dentry *d_kill(struct dentry *dentry, struct dentry *parent) | 240 | static struct dentry *d_kill(struct dentry *dentry, struct dentry *parent) |
232 | __releases(dentry->d_lock) | 241 | __releases(dentry->d_lock) |
233 | __releases(parent->d_lock) | 242 | __releases(parent->d_lock) |
243 | __releases(dcache_inode_lock) | ||
234 | __releases(dcache_lock) | 244 | __releases(dcache_lock) |
235 | { | 245 | { |
236 | list_del(&dentry->d_u.d_child); | 246 | list_del(&dentry->d_u.d_child); |
@@ -332,13 +342,18 @@ repeat: | |||
332 | * want to reduce dcache_lock anyway so this will | 342 | * want to reduce dcache_lock anyway so this will |
333 | * get improved. | 343 | * get improved. |
334 | */ | 344 | */ |
345 | drop1: | ||
335 | spin_unlock(&dentry->d_lock); | 346 | spin_unlock(&dentry->d_lock); |
336 | goto repeat; | 347 | goto repeat; |
337 | } | 348 | } |
338 | if (parent && !spin_trylock(&parent->d_lock)) { | 349 | if (!spin_trylock(&dcache_inode_lock)) { |
339 | spin_unlock(&dentry->d_lock); | 350 | drop2: |
340 | spin_unlock(&dcache_lock); | 351 | spin_unlock(&dcache_lock); |
341 | goto repeat; | 352 | goto drop1; |
353 | } | ||
354 | if (parent && !spin_trylock(&parent->d_lock)) { | ||
355 | spin_unlock(&dcache_inode_lock); | ||
356 | goto drop2; | ||
342 | } | 357 | } |
343 | } | 358 | } |
344 | dentry->d_count--; | 359 | dentry->d_count--; |
@@ -369,6 +384,7 @@ repeat: | |||
369 | spin_unlock(&dentry->d_lock); | 384 | spin_unlock(&dentry->d_lock); |
370 | if (parent) | 385 | if (parent) |
371 | spin_unlock(&parent->d_lock); | 386 | spin_unlock(&parent->d_lock); |
387 | spin_unlock(&dcache_inode_lock); | ||
372 | spin_unlock(&dcache_lock); | 388 | spin_unlock(&dcache_lock); |
373 | return; | 389 | return; |
374 | 390 | ||
@@ -558,7 +574,9 @@ struct dentry *d_find_alias(struct inode *inode) | |||
558 | 574 | ||
559 | if (!list_empty(&inode->i_dentry)) { | 575 | if (!list_empty(&inode->i_dentry)) { |
560 | spin_lock(&dcache_lock); | 576 | spin_lock(&dcache_lock); |
577 | spin_lock(&dcache_inode_lock); | ||
561 | de = __d_find_alias(inode, 0); | 578 | de = __d_find_alias(inode, 0); |
579 | spin_unlock(&dcache_inode_lock); | ||
562 | spin_unlock(&dcache_lock); | 580 | spin_unlock(&dcache_lock); |
563 | } | 581 | } |
564 | return de; | 582 | return de; |
@@ -574,18 +592,21 @@ void d_prune_aliases(struct inode *inode) | |||
574 | struct dentry *dentry; | 592 | struct dentry *dentry; |
575 | restart: | 593 | restart: |
576 | spin_lock(&dcache_lock); | 594 | spin_lock(&dcache_lock); |
595 | spin_lock(&dcache_inode_lock); | ||
577 | list_for_each_entry(dentry, &inode->i_dentry, d_alias) { | 596 | list_for_each_entry(dentry, &inode->i_dentry, d_alias) { |
578 | spin_lock(&dentry->d_lock); | 597 | spin_lock(&dentry->d_lock); |
579 | if (!dentry->d_count) { | 598 | if (!dentry->d_count) { |
580 | __dget_locked_dlock(dentry); | 599 | __dget_locked_dlock(dentry); |
581 | __d_drop(dentry); | 600 | __d_drop(dentry); |
582 | spin_unlock(&dentry->d_lock); | 601 | spin_unlock(&dentry->d_lock); |
602 | spin_unlock(&dcache_inode_lock); | ||
583 | spin_unlock(&dcache_lock); | 603 | spin_unlock(&dcache_lock); |
584 | dput(dentry); | 604 | dput(dentry); |
585 | goto restart; | 605 | goto restart; |
586 | } | 606 | } |
587 | spin_unlock(&dentry->d_lock); | 607 | spin_unlock(&dentry->d_lock); |
588 | } | 608 | } |
609 | spin_unlock(&dcache_inode_lock); | ||
589 | spin_unlock(&dcache_lock); | 610 | spin_unlock(&dcache_lock); |
590 | } | 611 | } |
591 | EXPORT_SYMBOL(d_prune_aliases); | 612 | EXPORT_SYMBOL(d_prune_aliases); |
@@ -601,6 +622,7 @@ EXPORT_SYMBOL(d_prune_aliases); | |||
601 | static void prune_one_dentry(struct dentry *dentry, struct dentry *parent) | 622 | static void prune_one_dentry(struct dentry *dentry, struct dentry *parent) |
602 | __releases(dentry->d_lock) | 623 | __releases(dentry->d_lock) |
603 | __releases(parent->d_lock) | 624 | __releases(parent->d_lock) |
625 | __releases(dcache_inode_lock) | ||
604 | __releases(dcache_lock) | 626 | __releases(dcache_lock) |
605 | { | 627 | { |
606 | __d_drop(dentry); | 628 | __d_drop(dentry); |
@@ -612,6 +634,7 @@ static void prune_one_dentry(struct dentry *dentry, struct dentry *parent) | |||
612 | */ | 634 | */ |
613 | while (dentry) { | 635 | while (dentry) { |
614 | spin_lock(&dcache_lock); | 636 | spin_lock(&dcache_lock); |
637 | spin_lock(&dcache_inode_lock); | ||
615 | again: | 638 | again: |
616 | spin_lock(&dentry->d_lock); | 639 | spin_lock(&dentry->d_lock); |
617 | if (IS_ROOT(dentry)) | 640 | if (IS_ROOT(dentry)) |
@@ -627,6 +650,7 @@ again: | |||
627 | if (parent) | 650 | if (parent) |
628 | spin_unlock(&parent->d_lock); | 651 | spin_unlock(&parent->d_lock); |
629 | spin_unlock(&dentry->d_lock); | 652 | spin_unlock(&dentry->d_lock); |
653 | spin_unlock(&dcache_inode_lock); | ||
630 | spin_unlock(&dcache_lock); | 654 | spin_unlock(&dcache_lock); |
631 | return; | 655 | return; |
632 | } | 656 | } |
@@ -676,8 +700,9 @@ relock: | |||
676 | spin_unlock(&dcache_lru_lock); | 700 | spin_unlock(&dcache_lru_lock); |
677 | 701 | ||
678 | prune_one_dentry(dentry, parent); | 702 | prune_one_dentry(dentry, parent); |
679 | /* dcache_lock and dentry->d_lock dropped */ | 703 | /* dcache_lock, dcache_inode_lock and dentry->d_lock dropped */ |
680 | spin_lock(&dcache_lock); | 704 | spin_lock(&dcache_lock); |
705 | spin_lock(&dcache_inode_lock); | ||
681 | spin_lock(&dcache_lru_lock); | 706 | spin_lock(&dcache_lru_lock); |
682 | } | 707 | } |
683 | } | 708 | } |
@@ -699,6 +724,7 @@ static void __shrink_dcache_sb(struct super_block *sb, int *count, int flags) | |||
699 | int cnt = *count; | 724 | int cnt = *count; |
700 | 725 | ||
701 | spin_lock(&dcache_lock); | 726 | spin_lock(&dcache_lock); |
727 | spin_lock(&dcache_inode_lock); | ||
702 | relock: | 728 | relock: |
703 | spin_lock(&dcache_lru_lock); | 729 | spin_lock(&dcache_lru_lock); |
704 | while (!list_empty(&sb->s_dentry_lru)) { | 730 | while (!list_empty(&sb->s_dentry_lru)) { |
@@ -737,8 +763,8 @@ relock: | |||
737 | if (!list_empty(&referenced)) | 763 | if (!list_empty(&referenced)) |
738 | list_splice(&referenced, &sb->s_dentry_lru); | 764 | list_splice(&referenced, &sb->s_dentry_lru); |
739 | spin_unlock(&dcache_lru_lock); | 765 | spin_unlock(&dcache_lru_lock); |
766 | spin_unlock(&dcache_inode_lock); | ||
740 | spin_unlock(&dcache_lock); | 767 | spin_unlock(&dcache_lock); |
741 | |||
742 | } | 768 | } |
743 | 769 | ||
744 | /** | 770 | /** |
@@ -832,12 +858,14 @@ void shrink_dcache_sb(struct super_block *sb) | |||
832 | LIST_HEAD(tmp); | 858 | LIST_HEAD(tmp); |
833 | 859 | ||
834 | spin_lock(&dcache_lock); | 860 | spin_lock(&dcache_lock); |
861 | spin_lock(&dcache_inode_lock); | ||
835 | spin_lock(&dcache_lru_lock); | 862 | spin_lock(&dcache_lru_lock); |
836 | while (!list_empty(&sb->s_dentry_lru)) { | 863 | while (!list_empty(&sb->s_dentry_lru)) { |
837 | list_splice_init(&sb->s_dentry_lru, &tmp); | 864 | list_splice_init(&sb->s_dentry_lru, &tmp); |
838 | shrink_dentry_list(&tmp); | 865 | shrink_dentry_list(&tmp); |
839 | } | 866 | } |
840 | spin_unlock(&dcache_lru_lock); | 867 | spin_unlock(&dcache_lru_lock); |
868 | spin_unlock(&dcache_inode_lock); | ||
841 | spin_unlock(&dcache_lock); | 869 | spin_unlock(&dcache_lock); |
842 | } | 870 | } |
843 | EXPORT_SYMBOL(shrink_dcache_sb); | 871 | EXPORT_SYMBOL(shrink_dcache_sb); |
@@ -1255,9 +1283,11 @@ EXPORT_SYMBOL(d_alloc_name); | |||
1255 | /* the caller must hold dcache_lock */ | 1283 | /* the caller must hold dcache_lock */ |
1256 | static void __d_instantiate(struct dentry *dentry, struct inode *inode) | 1284 | static void __d_instantiate(struct dentry *dentry, struct inode *inode) |
1257 | { | 1285 | { |
1286 | spin_lock(&dentry->d_lock); | ||
1258 | if (inode) | 1287 | if (inode) |
1259 | list_add(&dentry->d_alias, &inode->i_dentry); | 1288 | list_add(&dentry->d_alias, &inode->i_dentry); |
1260 | dentry->d_inode = inode; | 1289 | dentry->d_inode = inode; |
1290 | spin_unlock(&dentry->d_lock); | ||
1261 | fsnotify_d_instantiate(dentry, inode); | 1291 | fsnotify_d_instantiate(dentry, inode); |
1262 | } | 1292 | } |
1263 | 1293 | ||
@@ -1280,7 +1310,9 @@ void d_instantiate(struct dentry *entry, struct inode * inode) | |||
1280 | { | 1310 | { |
1281 | BUG_ON(!list_empty(&entry->d_alias)); | 1311 | BUG_ON(!list_empty(&entry->d_alias)); |
1282 | spin_lock(&dcache_lock); | 1312 | spin_lock(&dcache_lock); |
1313 | spin_lock(&dcache_inode_lock); | ||
1283 | __d_instantiate(entry, inode); | 1314 | __d_instantiate(entry, inode); |
1315 | spin_unlock(&dcache_inode_lock); | ||
1284 | spin_unlock(&dcache_lock); | 1316 | spin_unlock(&dcache_lock); |
1285 | security_d_instantiate(entry, inode); | 1317 | security_d_instantiate(entry, inode); |
1286 | } | 1318 | } |
@@ -1341,7 +1373,9 @@ struct dentry *d_instantiate_unique(struct dentry *entry, struct inode *inode) | |||
1341 | BUG_ON(!list_empty(&entry->d_alias)); | 1373 | BUG_ON(!list_empty(&entry->d_alias)); |
1342 | 1374 | ||
1343 | spin_lock(&dcache_lock); | 1375 | spin_lock(&dcache_lock); |
1376 | spin_lock(&dcache_inode_lock); | ||
1344 | result = __d_instantiate_unique(entry, inode); | 1377 | result = __d_instantiate_unique(entry, inode); |
1378 | spin_unlock(&dcache_inode_lock); | ||
1345 | spin_unlock(&dcache_lock); | 1379 | spin_unlock(&dcache_lock); |
1346 | 1380 | ||
1347 | if (!result) { | 1381 | if (!result) { |
@@ -1432,8 +1466,10 @@ struct dentry *d_obtain_alias(struct inode *inode) | |||
1432 | tmp->d_parent = tmp; /* make sure dput doesn't croak */ | 1466 | tmp->d_parent = tmp; /* make sure dput doesn't croak */ |
1433 | 1467 | ||
1434 | spin_lock(&dcache_lock); | 1468 | spin_lock(&dcache_lock); |
1469 | spin_lock(&dcache_inode_lock); | ||
1435 | res = __d_find_alias(inode, 0); | 1470 | res = __d_find_alias(inode, 0); |
1436 | if (res) { | 1471 | if (res) { |
1472 | spin_unlock(&dcache_inode_lock); | ||
1437 | spin_unlock(&dcache_lock); | 1473 | spin_unlock(&dcache_lock); |
1438 | dput(tmp); | 1474 | dput(tmp); |
1439 | goto out_iput; | 1475 | goto out_iput; |
@@ -1450,6 +1486,7 @@ struct dentry *d_obtain_alias(struct inode *inode) | |||
1450 | hlist_add_head(&tmp->d_hash, &inode->i_sb->s_anon); | 1486 | hlist_add_head(&tmp->d_hash, &inode->i_sb->s_anon); |
1451 | spin_unlock(&dcache_hash_lock); | 1487 | spin_unlock(&dcache_hash_lock); |
1452 | spin_unlock(&tmp->d_lock); | 1488 | spin_unlock(&tmp->d_lock); |
1489 | spin_unlock(&dcache_inode_lock); | ||
1453 | 1490 | ||
1454 | spin_unlock(&dcache_lock); | 1491 | spin_unlock(&dcache_lock); |
1455 | return tmp; | 1492 | return tmp; |
@@ -1482,9 +1519,11 @@ struct dentry *d_splice_alias(struct inode *inode, struct dentry *dentry) | |||
1482 | 1519 | ||
1483 | if (inode && S_ISDIR(inode->i_mode)) { | 1520 | if (inode && S_ISDIR(inode->i_mode)) { |
1484 | spin_lock(&dcache_lock); | 1521 | spin_lock(&dcache_lock); |
1522 | spin_lock(&dcache_inode_lock); | ||
1485 | new = __d_find_alias(inode, 1); | 1523 | new = __d_find_alias(inode, 1); |
1486 | if (new) { | 1524 | if (new) { |
1487 | BUG_ON(!(new->d_flags & DCACHE_DISCONNECTED)); | 1525 | BUG_ON(!(new->d_flags & DCACHE_DISCONNECTED)); |
1526 | spin_unlock(&dcache_inode_lock); | ||
1488 | spin_unlock(&dcache_lock); | 1527 | spin_unlock(&dcache_lock); |
1489 | security_d_instantiate(new, inode); | 1528 | security_d_instantiate(new, inode); |
1490 | d_move(new, dentry); | 1529 | d_move(new, dentry); |
@@ -1492,6 +1531,7 @@ struct dentry *d_splice_alias(struct inode *inode, struct dentry *dentry) | |||
1492 | } else { | 1531 | } else { |
1493 | /* already taking dcache_lock, so d_add() by hand */ | 1532 | /* already taking dcache_lock, so d_add() by hand */ |
1494 | __d_instantiate(dentry, inode); | 1533 | __d_instantiate(dentry, inode); |
1534 | spin_unlock(&dcache_inode_lock); | ||
1495 | spin_unlock(&dcache_lock); | 1535 | spin_unlock(&dcache_lock); |
1496 | security_d_instantiate(dentry, inode); | 1536 | security_d_instantiate(dentry, inode); |
1497 | d_rehash(dentry); | 1537 | d_rehash(dentry); |
@@ -1566,8 +1606,10 @@ struct dentry *d_add_ci(struct dentry *dentry, struct inode *inode, | |||
1566 | * already has a dentry. | 1606 | * already has a dentry. |
1567 | */ | 1607 | */ |
1568 | spin_lock(&dcache_lock); | 1608 | spin_lock(&dcache_lock); |
1609 | spin_lock(&dcache_inode_lock); | ||
1569 | if (!S_ISDIR(inode->i_mode) || list_empty(&inode->i_dentry)) { | 1610 | if (!S_ISDIR(inode->i_mode) || list_empty(&inode->i_dentry)) { |
1570 | __d_instantiate(found, inode); | 1611 | __d_instantiate(found, inode); |
1612 | spin_unlock(&dcache_inode_lock); | ||
1571 | spin_unlock(&dcache_lock); | 1613 | spin_unlock(&dcache_lock); |
1572 | security_d_instantiate(found, inode); | 1614 | security_d_instantiate(found, inode); |
1573 | return found; | 1615 | return found; |
@@ -1579,6 +1621,7 @@ struct dentry *d_add_ci(struct dentry *dentry, struct inode *inode, | |||
1579 | */ | 1621 | */ |
1580 | new = list_entry(inode->i_dentry.next, struct dentry, d_alias); | 1622 | new = list_entry(inode->i_dentry.next, struct dentry, d_alias); |
1581 | dget_locked(new); | 1623 | dget_locked(new); |
1624 | spin_unlock(&dcache_inode_lock); | ||
1582 | spin_unlock(&dcache_lock); | 1625 | spin_unlock(&dcache_lock); |
1583 | security_d_instantiate(found, inode); | 1626 | security_d_instantiate(found, inode); |
1584 | d_move(new, found); | 1627 | d_move(new, found); |
@@ -1797,6 +1840,7 @@ void d_delete(struct dentry * dentry) | |||
1797 | * Are we the only user? | 1840 | * Are we the only user? |
1798 | */ | 1841 | */ |
1799 | spin_lock(&dcache_lock); | 1842 | spin_lock(&dcache_lock); |
1843 | spin_lock(&dcache_inode_lock); | ||
1800 | spin_lock(&dentry->d_lock); | 1844 | spin_lock(&dentry->d_lock); |
1801 | isdir = S_ISDIR(dentry->d_inode->i_mode); | 1845 | isdir = S_ISDIR(dentry->d_inode->i_mode); |
1802 | if (dentry->d_count == 1) { | 1846 | if (dentry->d_count == 1) { |
@@ -1810,6 +1854,7 @@ void d_delete(struct dentry * dentry) | |||
1810 | __d_drop(dentry); | 1854 | __d_drop(dentry); |
1811 | 1855 | ||
1812 | spin_unlock(&dentry->d_lock); | 1856 | spin_unlock(&dentry->d_lock); |
1857 | spin_unlock(&dcache_inode_lock); | ||
1813 | spin_unlock(&dcache_lock); | 1858 | spin_unlock(&dcache_lock); |
1814 | 1859 | ||
1815 | fsnotify_nameremove(dentry, isdir); | 1860 | fsnotify_nameremove(dentry, isdir); |
@@ -2067,6 +2112,7 @@ struct dentry *d_ancestor(struct dentry *p1, struct dentry *p2) | |||
2067 | */ | 2112 | */ |
2068 | static struct dentry *__d_unalias(struct dentry *dentry, struct dentry *alias) | 2113 | static struct dentry *__d_unalias(struct dentry *dentry, struct dentry *alias) |
2069 | __releases(dcache_lock) | 2114 | __releases(dcache_lock) |
2115 | __releases(dcache_inode_lock) | ||
2070 | { | 2116 | { |
2071 | struct mutex *m1 = NULL, *m2 = NULL; | 2117 | struct mutex *m1 = NULL, *m2 = NULL; |
2072 | struct dentry *ret; | 2118 | struct dentry *ret; |
@@ -2092,6 +2138,7 @@ out_unalias: | |||
2092 | d_move_locked(alias, dentry); | 2138 | d_move_locked(alias, dentry); |
2093 | ret = alias; | 2139 | ret = alias; |
2094 | out_err: | 2140 | out_err: |
2141 | spin_unlock(&dcache_inode_lock); | ||
2095 | spin_unlock(&dcache_lock); | 2142 | spin_unlock(&dcache_lock); |
2096 | if (m2) | 2143 | if (m2) |
2097 | mutex_unlock(m2); | 2144 | mutex_unlock(m2); |
@@ -2153,6 +2200,7 @@ struct dentry *d_materialise_unique(struct dentry *dentry, struct inode *inode) | |||
2153 | BUG_ON(!d_unhashed(dentry)); | 2200 | BUG_ON(!d_unhashed(dentry)); |
2154 | 2201 | ||
2155 | spin_lock(&dcache_lock); | 2202 | spin_lock(&dcache_lock); |
2203 | spin_lock(&dcache_inode_lock); | ||
2156 | 2204 | ||
2157 | if (!inode) { | 2205 | if (!inode) { |
2158 | actual = dentry; | 2206 | actual = dentry; |
@@ -2196,6 +2244,7 @@ found: | |||
2196 | _d_rehash(actual); | 2244 | _d_rehash(actual); |
2197 | spin_unlock(&dcache_hash_lock); | 2245 | spin_unlock(&dcache_hash_lock); |
2198 | spin_unlock(&actual->d_lock); | 2246 | spin_unlock(&actual->d_lock); |
2247 | spin_unlock(&dcache_inode_lock); | ||
2199 | spin_unlock(&dcache_lock); | 2248 | spin_unlock(&dcache_lock); |
2200 | out_nolock: | 2249 | out_nolock: |
2201 | if (actual == dentry) { | 2250 | if (actual == dentry) { |
@@ -2207,6 +2256,7 @@ out_nolock: | |||
2207 | return actual; | 2256 | return actual; |
2208 | 2257 | ||
2209 | shouldnt_be_hashed: | 2258 | shouldnt_be_hashed: |
2259 | spin_unlock(&dcache_inode_lock); | ||
2210 | spin_unlock(&dcache_lock); | 2260 | spin_unlock(&dcache_lock); |
2211 | BUG(); | 2261 | BUG(); |
2212 | } | 2262 | } |