diff options
author | Nick Piggin <npiggin@kernel.dk> | 2011-01-07 01:50:06 -0500 |
---|---|---|
committer | Nick Piggin <npiggin@kernel.dk> | 2011-01-07 01:50:31 -0500 |
commit | 873feea09ebc980cbd3631b767356ce1eee65ec1 (patch) | |
tree | 59a8fce9b138086abee7cf845f62ff70a390cf81 | |
parent | ceb5bdc2d246f6d81cf61ed70f325308a11821d2 (diff) |
fs: dcache per-inode inode alias locking
dcache_inode_lock can be replaced with per-inode locking. Use existing
inode->i_lock for this. This is slightly non-trivial because we sometimes
need to find the inode from the dentry, which requires d_inode to be
stabilised (either with refcount or d_lock).
Signed-off-by: Nick Piggin <npiggin@kernel.dk>
-rw-r--r-- | fs/9p/vfs_inode.c | 4 | ||||
-rw-r--r-- | fs/affs/amigaffs.c | 4 | ||||
-rw-r--r-- | fs/cifs/inode.c | 6 | ||||
-rw-r--r-- | fs/dcache.c | 88 | ||||
-rw-r--r-- | fs/exportfs/expfs.c | 12 | ||||
-rw-r--r-- | fs/nfs/getroot.c | 4 | ||||
-rw-r--r-- | fs/notify/fsnotify.c | 4 | ||||
-rw-r--r-- | fs/ocfs2/dcache.c | 4 | ||||
-rw-r--r-- | include/linux/dcache.h | 1 |
9 files changed, 67 insertions, 60 deletions
diff --git a/fs/9p/vfs_inode.c b/fs/9p/vfs_inode.c index df8bbb358d54..59782981b225 100644 --- a/fs/9p/vfs_inode.c +++ b/fs/9p/vfs_inode.c | |||
@@ -277,11 +277,11 @@ static struct dentry *v9fs_dentry_from_dir_inode(struct inode *inode) | |||
277 | { | 277 | { |
278 | struct dentry *dentry; | 278 | struct dentry *dentry; |
279 | 279 | ||
280 | spin_lock(&dcache_inode_lock); | 280 | spin_lock(&inode->i_lock); |
281 | /* Directory should have only one entry. */ | 281 | /* Directory should have only one entry. */ |
282 | BUG_ON(S_ISDIR(inode->i_mode) && !list_is_singular(&inode->i_dentry)); | 282 | BUG_ON(S_ISDIR(inode->i_mode) && !list_is_singular(&inode->i_dentry)); |
283 | dentry = list_entry(inode->i_dentry.next, struct dentry, d_alias); | 283 | dentry = list_entry(inode->i_dentry.next, struct dentry, d_alias); |
284 | spin_unlock(&dcache_inode_lock); | 284 | spin_unlock(&inode->i_lock); |
285 | return dentry; | 285 | return dentry; |
286 | } | 286 | } |
287 | 287 | ||
diff --git a/fs/affs/amigaffs.c b/fs/affs/amigaffs.c index 600101a21ba2..3a4557e8325c 100644 --- a/fs/affs/amigaffs.c +++ b/fs/affs/amigaffs.c | |||
@@ -128,7 +128,7 @@ affs_fix_dcache(struct dentry *dentry, u32 entry_ino) | |||
128 | void *data = dentry->d_fsdata; | 128 | void *data = dentry->d_fsdata; |
129 | struct list_head *head, *next; | 129 | struct list_head *head, *next; |
130 | 130 | ||
131 | spin_lock(&dcache_inode_lock); | 131 | spin_lock(&inode->i_lock); |
132 | head = &inode->i_dentry; | 132 | head = &inode->i_dentry; |
133 | next = head->next; | 133 | next = head->next; |
134 | while (next != head) { | 134 | while (next != head) { |
@@ -139,7 +139,7 @@ affs_fix_dcache(struct dentry *dentry, u32 entry_ino) | |||
139 | } | 139 | } |
140 | next = next->next; | 140 | next = next->next; |
141 | } | 141 | } |
142 | spin_unlock(&dcache_inode_lock); | 142 | spin_unlock(&inode->i_lock); |
143 | } | 143 | } |
144 | 144 | ||
145 | 145 | ||
diff --git a/fs/cifs/inode.c b/fs/cifs/inode.c index 2a239d878e85..a853a89857a5 100644 --- a/fs/cifs/inode.c +++ b/fs/cifs/inode.c | |||
@@ -809,14 +809,14 @@ inode_has_hashed_dentries(struct inode *inode) | |||
809 | { | 809 | { |
810 | struct dentry *dentry; | 810 | struct dentry *dentry; |
811 | 811 | ||
812 | spin_lock(&dcache_inode_lock); | 812 | spin_lock(&inode->i_lock); |
813 | list_for_each_entry(dentry, &inode->i_dentry, d_alias) { | 813 | list_for_each_entry(dentry, &inode->i_dentry, d_alias) { |
814 | if (!d_unhashed(dentry) || IS_ROOT(dentry)) { | 814 | if (!d_unhashed(dentry) || IS_ROOT(dentry)) { |
815 | spin_unlock(&dcache_inode_lock); | 815 | spin_unlock(&inode->i_lock); |
816 | return true; | 816 | return true; |
817 | } | 817 | } |
818 | } | 818 | } |
819 | spin_unlock(&dcache_inode_lock); | 819 | spin_unlock(&inode->i_lock); |
820 | return false; | 820 | return false; |
821 | } | 821 | } |
822 | 822 | ||
diff --git a/fs/dcache.c b/fs/dcache.c index 9f04e1ba75b7..09ec945f3c98 100644 --- a/fs/dcache.c +++ b/fs/dcache.c | |||
@@ -39,8 +39,8 @@ | |||
39 | 39 | ||
40 | /* | 40 | /* |
41 | * Usage: | 41 | * Usage: |
42 | * dcache_inode_lock protects: | 42 | * dcache->d_inode->i_lock protects: |
43 | * - i_dentry, d_alias, d_inode | 43 | * - i_dentry, d_alias, d_inode of aliases |
44 | * dcache_hash_bucket lock protects: | 44 | * dcache_hash_bucket lock protects: |
45 | * - the dcache hash table | 45 | * - the dcache hash table |
46 | * s_anon bl list spinlock protects: | 46 | * s_anon bl list spinlock protects: |
@@ -58,7 +58,7 @@ | |||
58 | * - d_alias, d_inode | 58 | * - d_alias, d_inode |
59 | * | 59 | * |
60 | * Ordering: | 60 | * Ordering: |
61 | * dcache_inode_lock | 61 | * dentry->d_inode->i_lock |
62 | * dentry->d_lock | 62 | * dentry->d_lock |
63 | * dcache_lru_lock | 63 | * dcache_lru_lock |
64 | * dcache_hash_bucket lock | 64 | * dcache_hash_bucket lock |
@@ -78,12 +78,10 @@ | |||
78 | int sysctl_vfs_cache_pressure __read_mostly = 100; | 78 | int sysctl_vfs_cache_pressure __read_mostly = 100; |
79 | EXPORT_SYMBOL_GPL(sysctl_vfs_cache_pressure); | 79 | EXPORT_SYMBOL_GPL(sysctl_vfs_cache_pressure); |
80 | 80 | ||
81 | __cacheline_aligned_in_smp DEFINE_SPINLOCK(dcache_inode_lock); | ||
82 | static __cacheline_aligned_in_smp DEFINE_SPINLOCK(dcache_lru_lock); | 81 | static __cacheline_aligned_in_smp DEFINE_SPINLOCK(dcache_lru_lock); |
83 | __cacheline_aligned_in_smp DEFINE_SEQLOCK(rename_lock); | 82 | __cacheline_aligned_in_smp DEFINE_SEQLOCK(rename_lock); |
84 | 83 | ||
85 | EXPORT_SYMBOL(rename_lock); | 84 | EXPORT_SYMBOL(rename_lock); |
86 | EXPORT_SYMBOL(dcache_inode_lock); | ||
87 | 85 | ||
88 | static struct kmem_cache *dentry_cache __read_mostly; | 86 | static struct kmem_cache *dentry_cache __read_mostly; |
89 | 87 | ||
@@ -196,14 +194,14 @@ static inline void dentry_rcuwalk_barrier(struct dentry *dentry) | |||
196 | */ | 194 | */ |
197 | static void dentry_iput(struct dentry * dentry) | 195 | static void dentry_iput(struct dentry * dentry) |
198 | __releases(dentry->d_lock) | 196 | __releases(dentry->d_lock) |
199 | __releases(dcache_inode_lock) | 197 | __releases(dentry->d_inode->i_lock) |
200 | { | 198 | { |
201 | struct inode *inode = dentry->d_inode; | 199 | struct inode *inode = dentry->d_inode; |
202 | if (inode) { | 200 | if (inode) { |
203 | dentry->d_inode = NULL; | 201 | dentry->d_inode = NULL; |
204 | list_del_init(&dentry->d_alias); | 202 | list_del_init(&dentry->d_alias); |
205 | spin_unlock(&dentry->d_lock); | 203 | spin_unlock(&dentry->d_lock); |
206 | spin_unlock(&dcache_inode_lock); | 204 | spin_unlock(&inode->i_lock); |
207 | if (!inode->i_nlink) | 205 | if (!inode->i_nlink) |
208 | fsnotify_inoderemove(inode); | 206 | fsnotify_inoderemove(inode); |
209 | if (dentry->d_op && dentry->d_op->d_iput) | 207 | if (dentry->d_op && dentry->d_op->d_iput) |
@@ -212,7 +210,6 @@ static void dentry_iput(struct dentry * dentry) | |||
212 | iput(inode); | 210 | iput(inode); |
213 | } else { | 211 | } else { |
214 | spin_unlock(&dentry->d_lock); | 212 | spin_unlock(&dentry->d_lock); |
215 | spin_unlock(&dcache_inode_lock); | ||
216 | } | 213 | } |
217 | } | 214 | } |
218 | 215 | ||
@@ -222,14 +219,14 @@ static void dentry_iput(struct dentry * dentry) | |||
222 | */ | 219 | */ |
223 | static void dentry_unlink_inode(struct dentry * dentry) | 220 | static void dentry_unlink_inode(struct dentry * dentry) |
224 | __releases(dentry->d_lock) | 221 | __releases(dentry->d_lock) |
225 | __releases(dcache_inode_lock) | 222 | __releases(dentry->d_inode->i_lock) |
226 | { | 223 | { |
227 | struct inode *inode = dentry->d_inode; | 224 | struct inode *inode = dentry->d_inode; |
228 | dentry->d_inode = NULL; | 225 | dentry->d_inode = NULL; |
229 | list_del_init(&dentry->d_alias); | 226 | list_del_init(&dentry->d_alias); |
230 | dentry_rcuwalk_barrier(dentry); | 227 | dentry_rcuwalk_barrier(dentry); |
231 | spin_unlock(&dentry->d_lock); | 228 | spin_unlock(&dentry->d_lock); |
232 | spin_unlock(&dcache_inode_lock); | 229 | spin_unlock(&inode->i_lock); |
233 | if (!inode->i_nlink) | 230 | if (!inode->i_nlink) |
234 | fsnotify_inoderemove(inode); | 231 | fsnotify_inoderemove(inode); |
235 | if (dentry->d_op && dentry->d_op->d_iput) | 232 | if (dentry->d_op && dentry->d_op->d_iput) |
@@ -295,7 +292,7 @@ static void dentry_lru_move_tail(struct dentry *dentry) | |||
295 | static struct dentry *d_kill(struct dentry *dentry, struct dentry *parent) | 292 | static struct dentry *d_kill(struct dentry *dentry, struct dentry *parent) |
296 | __releases(dentry->d_lock) | 293 | __releases(dentry->d_lock) |
297 | __releases(parent->d_lock) | 294 | __releases(parent->d_lock) |
298 | __releases(dcache_inode_lock) | 295 | __releases(dentry->d_inode->i_lock) |
299 | { | 296 | { |
300 | dentry->d_parent = NULL; | 297 | dentry->d_parent = NULL; |
301 | list_del(&dentry->d_u.d_child); | 298 | list_del(&dentry->d_u.d_child); |
@@ -370,9 +367,11 @@ EXPORT_SYMBOL(d_drop); | |||
370 | static inline struct dentry *dentry_kill(struct dentry *dentry, int ref) | 367 | static inline struct dentry *dentry_kill(struct dentry *dentry, int ref) |
371 | __releases(dentry->d_lock) | 368 | __releases(dentry->d_lock) |
372 | { | 369 | { |
370 | struct inode *inode; | ||
373 | struct dentry *parent; | 371 | struct dentry *parent; |
374 | 372 | ||
375 | if (!spin_trylock(&dcache_inode_lock)) { | 373 | inode = dentry->d_inode; |
374 | if (inode && !spin_trylock(&inode->i_lock)) { | ||
376 | relock: | 375 | relock: |
377 | spin_unlock(&dentry->d_lock); | 376 | spin_unlock(&dentry->d_lock); |
378 | cpu_relax(); | 377 | cpu_relax(); |
@@ -383,7 +382,8 @@ relock: | |||
383 | else | 382 | else |
384 | parent = dentry->d_parent; | 383 | parent = dentry->d_parent; |
385 | if (parent && !spin_trylock(&parent->d_lock)) { | 384 | if (parent && !spin_trylock(&parent->d_lock)) { |
386 | spin_unlock(&dcache_inode_lock); | 385 | if (inode) |
386 | spin_unlock(&inode->i_lock); | ||
387 | goto relock; | 387 | goto relock; |
388 | } | 388 | } |
389 | 389 | ||
@@ -618,9 +618,9 @@ struct dentry *d_find_alias(struct inode *inode) | |||
618 | struct dentry *de = NULL; | 618 | struct dentry *de = NULL; |
619 | 619 | ||
620 | if (!list_empty(&inode->i_dentry)) { | 620 | if (!list_empty(&inode->i_dentry)) { |
621 | spin_lock(&dcache_inode_lock); | 621 | spin_lock(&inode->i_lock); |
622 | de = __d_find_alias(inode, 0); | 622 | de = __d_find_alias(inode, 0); |
623 | spin_unlock(&dcache_inode_lock); | 623 | spin_unlock(&inode->i_lock); |
624 | } | 624 | } |
625 | return de; | 625 | return de; |
626 | } | 626 | } |
@@ -634,20 +634,20 @@ void d_prune_aliases(struct inode *inode) | |||
634 | { | 634 | { |
635 | struct dentry *dentry; | 635 | struct dentry *dentry; |
636 | restart: | 636 | restart: |
637 | spin_lock(&dcache_inode_lock); | 637 | spin_lock(&inode->i_lock); |
638 | list_for_each_entry(dentry, &inode->i_dentry, d_alias) { | 638 | list_for_each_entry(dentry, &inode->i_dentry, d_alias) { |
639 | spin_lock(&dentry->d_lock); | 639 | spin_lock(&dentry->d_lock); |
640 | if (!dentry->d_count) { | 640 | if (!dentry->d_count) { |
641 | __dget_dlock(dentry); | 641 | __dget_dlock(dentry); |
642 | __d_drop(dentry); | 642 | __d_drop(dentry); |
643 | spin_unlock(&dentry->d_lock); | 643 | spin_unlock(&dentry->d_lock); |
644 | spin_unlock(&dcache_inode_lock); | 644 | spin_unlock(&inode->i_lock); |
645 | dput(dentry); | 645 | dput(dentry); |
646 | goto restart; | 646 | goto restart; |
647 | } | 647 | } |
648 | spin_unlock(&dentry->d_lock); | 648 | spin_unlock(&dentry->d_lock); |
649 | } | 649 | } |
650 | spin_unlock(&dcache_inode_lock); | 650 | spin_unlock(&inode->i_lock); |
651 | } | 651 | } |
652 | EXPORT_SYMBOL(d_prune_aliases); | 652 | EXPORT_SYMBOL(d_prune_aliases); |
653 | 653 | ||
@@ -1392,9 +1392,11 @@ static void __d_instantiate(struct dentry *dentry, struct inode *inode) | |||
1392 | void d_instantiate(struct dentry *entry, struct inode * inode) | 1392 | void d_instantiate(struct dentry *entry, struct inode * inode) |
1393 | { | 1393 | { |
1394 | BUG_ON(!list_empty(&entry->d_alias)); | 1394 | BUG_ON(!list_empty(&entry->d_alias)); |
1395 | spin_lock(&dcache_inode_lock); | 1395 | if (inode) |
1396 | spin_lock(&inode->i_lock); | ||
1396 | __d_instantiate(entry, inode); | 1397 | __d_instantiate(entry, inode); |
1397 | spin_unlock(&dcache_inode_lock); | 1398 | if (inode) |
1399 | spin_unlock(&inode->i_lock); | ||
1398 | security_d_instantiate(entry, inode); | 1400 | security_d_instantiate(entry, inode); |
1399 | } | 1401 | } |
1400 | EXPORT_SYMBOL(d_instantiate); | 1402 | EXPORT_SYMBOL(d_instantiate); |
@@ -1458,9 +1460,11 @@ struct dentry *d_instantiate_unique(struct dentry *entry, struct inode *inode) | |||
1458 | 1460 | ||
1459 | BUG_ON(!list_empty(&entry->d_alias)); | 1461 | BUG_ON(!list_empty(&entry->d_alias)); |
1460 | 1462 | ||
1461 | spin_lock(&dcache_inode_lock); | 1463 | if (inode) |
1464 | spin_lock(&inode->i_lock); | ||
1462 | result = __d_instantiate_unique(entry, inode); | 1465 | result = __d_instantiate_unique(entry, inode); |
1463 | spin_unlock(&dcache_inode_lock); | 1466 | if (inode) |
1467 | spin_unlock(&inode->i_lock); | ||
1464 | 1468 | ||
1465 | if (!result) { | 1469 | if (!result) { |
1466 | security_d_instantiate(entry, inode); | 1470 | security_d_instantiate(entry, inode); |
@@ -1542,10 +1546,10 @@ struct dentry *d_obtain_alias(struct inode *inode) | |||
1542 | tmp->d_parent = tmp; /* make sure dput doesn't croak */ | 1546 | tmp->d_parent = tmp; /* make sure dput doesn't croak */ |
1543 | 1547 | ||
1544 | 1548 | ||
1545 | spin_lock(&dcache_inode_lock); | 1549 | spin_lock(&inode->i_lock); |
1546 | res = __d_find_alias(inode, 0); | 1550 | res = __d_find_alias(inode, 0); |
1547 | if (res) { | 1551 | if (res) { |
1548 | spin_unlock(&dcache_inode_lock); | 1552 | spin_unlock(&inode->i_lock); |
1549 | dput(tmp); | 1553 | dput(tmp); |
1550 | goto out_iput; | 1554 | goto out_iput; |
1551 | } | 1555 | } |
@@ -1561,7 +1565,7 @@ struct dentry *d_obtain_alias(struct inode *inode) | |||
1561 | hlist_bl_add_head(&tmp->d_hash, &tmp->d_sb->s_anon); | 1565 | 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); | 1566 | __bit_spin_unlock(0, (unsigned long *)&tmp->d_sb->s_anon.first); |
1563 | spin_unlock(&tmp->d_lock); | 1567 | spin_unlock(&tmp->d_lock); |
1564 | spin_unlock(&dcache_inode_lock); | 1568 | spin_unlock(&inode->i_lock); |
1565 | 1569 | ||
1566 | return tmp; | 1570 | return tmp; |
1567 | 1571 | ||
@@ -1592,18 +1596,18 @@ struct dentry *d_splice_alias(struct inode *inode, struct dentry *dentry) | |||
1592 | struct dentry *new = NULL; | 1596 | struct dentry *new = NULL; |
1593 | 1597 | ||
1594 | if (inode && S_ISDIR(inode->i_mode)) { | 1598 | if (inode && S_ISDIR(inode->i_mode)) { |
1595 | spin_lock(&dcache_inode_lock); | 1599 | spin_lock(&inode->i_lock); |
1596 | new = __d_find_alias(inode, 1); | 1600 | new = __d_find_alias(inode, 1); |
1597 | if (new) { | 1601 | if (new) { |
1598 | BUG_ON(!(new->d_flags & DCACHE_DISCONNECTED)); | 1602 | BUG_ON(!(new->d_flags & DCACHE_DISCONNECTED)); |
1599 | spin_unlock(&dcache_inode_lock); | 1603 | spin_unlock(&inode->i_lock); |
1600 | security_d_instantiate(new, inode); | 1604 | security_d_instantiate(new, inode); |
1601 | d_move(new, dentry); | 1605 | d_move(new, dentry); |
1602 | iput(inode); | 1606 | iput(inode); |
1603 | } else { | 1607 | } else { |
1604 | /* already got dcache_inode_lock, so d_add() by hand */ | 1608 | /* already taking inode->i_lock, so d_add() by hand */ |
1605 | __d_instantiate(dentry, inode); | 1609 | __d_instantiate(dentry, inode); |
1606 | spin_unlock(&dcache_inode_lock); | 1610 | spin_unlock(&inode->i_lock); |
1607 | security_d_instantiate(dentry, inode); | 1611 | security_d_instantiate(dentry, inode); |
1608 | d_rehash(dentry); | 1612 | d_rehash(dentry); |
1609 | } | 1613 | } |
@@ -1676,10 +1680,10 @@ struct dentry *d_add_ci(struct dentry *dentry, struct inode *inode, | |||
1676 | * Negative dentry: instantiate it unless the inode is a directory and | 1680 | * Negative dentry: instantiate it unless the inode is a directory and |
1677 | * already has a dentry. | 1681 | * already has a dentry. |
1678 | */ | 1682 | */ |
1679 | spin_lock(&dcache_inode_lock); | 1683 | spin_lock(&inode->i_lock); |
1680 | if (!S_ISDIR(inode->i_mode) || list_empty(&inode->i_dentry)) { | 1684 | if (!S_ISDIR(inode->i_mode) || list_empty(&inode->i_dentry)) { |
1681 | __d_instantiate(found, inode); | 1685 | __d_instantiate(found, inode); |
1682 | spin_unlock(&dcache_inode_lock); | 1686 | spin_unlock(&inode->i_lock); |
1683 | security_d_instantiate(found, inode); | 1687 | security_d_instantiate(found, inode); |
1684 | return found; | 1688 | return found; |
1685 | } | 1689 | } |
@@ -1690,7 +1694,7 @@ struct dentry *d_add_ci(struct dentry *dentry, struct inode *inode, | |||
1690 | */ | 1694 | */ |
1691 | new = list_entry(inode->i_dentry.next, struct dentry, d_alias); | 1695 | new = list_entry(inode->i_dentry.next, struct dentry, d_alias); |
1692 | __dget(new); | 1696 | __dget(new); |
1693 | spin_unlock(&dcache_inode_lock); | 1697 | spin_unlock(&inode->i_lock); |
1694 | security_d_instantiate(found, inode); | 1698 | security_d_instantiate(found, inode); |
1695 | d_move(new, found); | 1699 | d_move(new, found); |
1696 | iput(inode); | 1700 | iput(inode); |
@@ -2004,15 +2008,17 @@ EXPORT_SYMBOL(d_validate); | |||
2004 | 2008 | ||
2005 | void d_delete(struct dentry * dentry) | 2009 | void d_delete(struct dentry * dentry) |
2006 | { | 2010 | { |
2011 | struct inode *inode; | ||
2007 | int isdir = 0; | 2012 | int isdir = 0; |
2008 | /* | 2013 | /* |
2009 | * Are we the only user? | 2014 | * Are we the only user? |
2010 | */ | 2015 | */ |
2011 | again: | 2016 | again: |
2012 | spin_lock(&dentry->d_lock); | 2017 | spin_lock(&dentry->d_lock); |
2013 | isdir = S_ISDIR(dentry->d_inode->i_mode); | 2018 | inode = dentry->d_inode; |
2019 | isdir = S_ISDIR(inode->i_mode); | ||
2014 | if (dentry->d_count == 1) { | 2020 | if (dentry->d_count == 1) { |
2015 | if (!spin_trylock(&dcache_inode_lock)) { | 2021 | if (inode && !spin_trylock(&inode->i_lock)) { |
2016 | spin_unlock(&dentry->d_lock); | 2022 | spin_unlock(&dentry->d_lock); |
2017 | cpu_relax(); | 2023 | cpu_relax(); |
2018 | goto again; | 2024 | goto again; |
@@ -2266,13 +2272,13 @@ struct dentry *d_ancestor(struct dentry *p1, struct dentry *p2) | |||
2266 | * This helper attempts to cope with remotely renamed directories | 2272 | * This helper attempts to cope with remotely renamed directories |
2267 | * | 2273 | * |
2268 | * It assumes that the caller is already holding | 2274 | * It assumes that the caller is already holding |
2269 | * dentry->d_parent->d_inode->i_mutex and the dcache_inode_lock | 2275 | * dentry->d_parent->d_inode->i_mutex and the inode->i_lock |
2270 | * | 2276 | * |
2271 | * Note: If ever the locking in lock_rename() changes, then please | 2277 | * Note: If ever the locking in lock_rename() changes, then please |
2272 | * remember to update this too... | 2278 | * remember to update this too... |
2273 | */ | 2279 | */ |
2274 | static struct dentry *__d_unalias(struct dentry *dentry, struct dentry *alias) | 2280 | static struct dentry *__d_unalias(struct inode *inode, |
2275 | __releases(dcache_inode_lock) | 2281 | struct dentry *dentry, struct dentry *alias) |
2276 | { | 2282 | { |
2277 | struct mutex *m1 = NULL, *m2 = NULL; | 2283 | struct mutex *m1 = NULL, *m2 = NULL; |
2278 | struct dentry *ret; | 2284 | struct dentry *ret; |
@@ -2298,7 +2304,7 @@ out_unalias: | |||
2298 | d_move(alias, dentry); | 2304 | d_move(alias, dentry); |
2299 | ret = alias; | 2305 | ret = alias; |
2300 | out_err: | 2306 | out_err: |
2301 | spin_unlock(&dcache_inode_lock); | 2307 | spin_unlock(&inode->i_lock); |
2302 | if (m2) | 2308 | if (m2) |
2303 | mutex_unlock(m2); | 2309 | mutex_unlock(m2); |
2304 | if (m1) | 2310 | if (m1) |
@@ -2371,7 +2377,7 @@ struct dentry *d_materialise_unique(struct dentry *dentry, struct inode *inode) | |||
2371 | goto out_nolock; | 2377 | goto out_nolock; |
2372 | } | 2378 | } |
2373 | 2379 | ||
2374 | spin_lock(&dcache_inode_lock); | 2380 | spin_lock(&inode->i_lock); |
2375 | 2381 | ||
2376 | if (S_ISDIR(inode->i_mode)) { | 2382 | if (S_ISDIR(inode->i_mode)) { |
2377 | struct dentry *alias; | 2383 | struct dentry *alias; |
@@ -2388,7 +2394,7 @@ struct dentry *d_materialise_unique(struct dentry *dentry, struct inode *inode) | |||
2388 | goto found; | 2394 | goto found; |
2389 | } | 2395 | } |
2390 | /* Nope, but we must(!) avoid directory aliasing */ | 2396 | /* Nope, but we must(!) avoid directory aliasing */ |
2391 | actual = __d_unalias(dentry, alias); | 2397 | actual = __d_unalias(inode, dentry, alias); |
2392 | if (IS_ERR(actual)) | 2398 | if (IS_ERR(actual)) |
2393 | dput(alias); | 2399 | dput(alias); |
2394 | goto out_nolock; | 2400 | goto out_nolock; |
@@ -2406,7 +2412,7 @@ struct dentry *d_materialise_unique(struct dentry *dentry, struct inode *inode) | |||
2406 | found: | 2412 | found: |
2407 | _d_rehash(actual); | 2413 | _d_rehash(actual); |
2408 | spin_unlock(&actual->d_lock); | 2414 | spin_unlock(&actual->d_lock); |
2409 | spin_unlock(&dcache_inode_lock); | 2415 | spin_unlock(&inode->i_lock); |
2410 | out_nolock: | 2416 | out_nolock: |
2411 | if (actual == dentry) { | 2417 | if (actual == dentry) { |
2412 | security_d_instantiate(dentry, inode); | 2418 | security_d_instantiate(dentry, inode); |
diff --git a/fs/exportfs/expfs.c b/fs/exportfs/expfs.c index f06a940065f6..4b6825740dd5 100644 --- a/fs/exportfs/expfs.c +++ b/fs/exportfs/expfs.c | |||
@@ -43,24 +43,26 @@ find_acceptable_alias(struct dentry *result, | |||
43 | void *context) | 43 | void *context) |
44 | { | 44 | { |
45 | struct dentry *dentry, *toput = NULL; | 45 | struct dentry *dentry, *toput = NULL; |
46 | struct inode *inode; | ||
46 | 47 | ||
47 | if (acceptable(context, result)) | 48 | if (acceptable(context, result)) |
48 | return result; | 49 | return result; |
49 | 50 | ||
50 | spin_lock(&dcache_inode_lock); | 51 | inode = result->d_inode; |
51 | list_for_each_entry(dentry, &result->d_inode->i_dentry, d_alias) { | 52 | spin_lock(&inode->i_lock); |
53 | list_for_each_entry(dentry, &inode->i_dentry, d_alias) { | ||
52 | dget(dentry); | 54 | dget(dentry); |
53 | spin_unlock(&dcache_inode_lock); | 55 | spin_unlock(&inode->i_lock); |
54 | if (toput) | 56 | if (toput) |
55 | dput(toput); | 57 | dput(toput); |
56 | if (dentry != result && acceptable(context, dentry)) { | 58 | if (dentry != result && acceptable(context, dentry)) { |
57 | dput(result); | 59 | dput(result); |
58 | return dentry; | 60 | return dentry; |
59 | } | 61 | } |
60 | spin_lock(&dcache_inode_lock); | 62 | spin_lock(&inode->i_lock); |
61 | toput = dentry; | 63 | toput = dentry; |
62 | } | 64 | } |
63 | spin_unlock(&dcache_inode_lock); | 65 | spin_unlock(&inode->i_lock); |
64 | 66 | ||
65 | if (toput) | 67 | if (toput) |
66 | dput(toput); | 68 | dput(toput); |
diff --git a/fs/nfs/getroot.c b/fs/nfs/getroot.c index c3a5a1126833..5596c6a2881e 100644 --- a/fs/nfs/getroot.c +++ b/fs/nfs/getroot.c | |||
@@ -63,11 +63,11 @@ static int nfs_superblock_set_dummy_root(struct super_block *sb, struct inode *i | |||
63 | * This again causes shrink_dcache_for_umount_subtree() to | 63 | * This again causes shrink_dcache_for_umount_subtree() to |
64 | * Oops, since the test for IS_ROOT() will fail. | 64 | * Oops, since the test for IS_ROOT() will fail. |
65 | */ | 65 | */ |
66 | spin_lock(&dcache_inode_lock); | 66 | spin_lock(&sb->s_root->d_inode->i_lock); |
67 | spin_lock(&sb->s_root->d_lock); | 67 | spin_lock(&sb->s_root->d_lock); |
68 | list_del_init(&sb->s_root->d_alias); | 68 | list_del_init(&sb->s_root->d_alias); |
69 | spin_unlock(&sb->s_root->d_lock); | 69 | spin_unlock(&sb->s_root->d_lock); |
70 | spin_unlock(&dcache_inode_lock); | 70 | spin_unlock(&sb->s_root->d_inode->i_lock); |
71 | } | 71 | } |
72 | return 0; | 72 | return 0; |
73 | } | 73 | } |
diff --git a/fs/notify/fsnotify.c b/fs/notify/fsnotify.c index 9be6ec1f36d8..79b47cbb5cd8 100644 --- a/fs/notify/fsnotify.c +++ b/fs/notify/fsnotify.c | |||
@@ -59,7 +59,7 @@ void __fsnotify_update_child_dentry_flags(struct inode *inode) | |||
59 | /* determine if the children should tell inode about their events */ | 59 | /* determine if the children should tell inode about their events */ |
60 | watched = fsnotify_inode_watches_children(inode); | 60 | watched = fsnotify_inode_watches_children(inode); |
61 | 61 | ||
62 | spin_lock(&dcache_inode_lock); | 62 | spin_lock(&inode->i_lock); |
63 | /* run all of the dentries associated with this inode. Since this is a | 63 | /* run all of the dentries associated with this inode. Since this is a |
64 | * directory, there damn well better only be one item on this list */ | 64 | * directory, there damn well better only be one item on this list */ |
65 | list_for_each_entry(alias, &inode->i_dentry, d_alias) { | 65 | list_for_each_entry(alias, &inode->i_dentry, d_alias) { |
@@ -82,7 +82,7 @@ void __fsnotify_update_child_dentry_flags(struct inode *inode) | |||
82 | } | 82 | } |
83 | spin_unlock(&alias->d_lock); | 83 | spin_unlock(&alias->d_lock); |
84 | } | 84 | } |
85 | spin_unlock(&dcache_inode_lock); | 85 | spin_unlock(&inode->i_lock); |
86 | } | 86 | } |
87 | 87 | ||
88 | /* Notify this dentry's parent about a child's events. */ | 88 | /* Notify this dentry's parent about a child's events. */ |
diff --git a/fs/ocfs2/dcache.c b/fs/ocfs2/dcache.c index 0310b16a7238..6d80ecc7834f 100644 --- a/fs/ocfs2/dcache.c +++ b/fs/ocfs2/dcache.c | |||
@@ -175,7 +175,7 @@ struct dentry *ocfs2_find_local_alias(struct inode *inode, | |||
175 | struct list_head *p; | 175 | struct list_head *p; |
176 | struct dentry *dentry = NULL; | 176 | struct dentry *dentry = NULL; |
177 | 177 | ||
178 | spin_lock(&dcache_inode_lock); | 178 | spin_lock(&inode->i_lock); |
179 | list_for_each(p, &inode->i_dentry) { | 179 | list_for_each(p, &inode->i_dentry) { |
180 | dentry = list_entry(p, struct dentry, d_alias); | 180 | dentry = list_entry(p, struct dentry, d_alias); |
181 | 181 | ||
@@ -193,7 +193,7 @@ struct dentry *ocfs2_find_local_alias(struct inode *inode, | |||
193 | dentry = NULL; | 193 | dentry = NULL; |
194 | } | 194 | } |
195 | 195 | ||
196 | spin_unlock(&dcache_inode_lock); | 196 | spin_unlock(&inode->i_lock); |
197 | 197 | ||
198 | return dentry; | 198 | return dentry; |
199 | } | 199 | } |
diff --git a/include/linux/dcache.h b/include/linux/dcache.h index 5f0392ef759b..d719e4de8046 100644 --- a/include/linux/dcache.h +++ b/include/linux/dcache.h | |||
@@ -191,7 +191,6 @@ struct dentry_operations { | |||
191 | #define DCACHE_OP_REVALIDATE 0x4000 | 191 | #define DCACHE_OP_REVALIDATE 0x4000 |
192 | #define DCACHE_OP_DELETE 0x8000 | 192 | #define DCACHE_OP_DELETE 0x8000 |
193 | 193 | ||
194 | extern spinlock_t dcache_inode_lock; | ||
195 | extern seqlock_t rename_lock; | 194 | extern seqlock_t rename_lock; |
196 | 195 | ||
197 | static inline int dname_external(struct dentry *dentry) | 196 | static inline int dname_external(struct dentry *dentry) |