aboutsummaryrefslogtreecommitdiffstats
path: root/drivers
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2011-01-07 11:56:33 -0500
committerLinus Torvalds <torvalds@linux-foundation.org>2011-01-07 11:56:33 -0500
commitb4a45f5fe8078bfc10837dbd5b98735058bc4698 (patch)
treedf6f13a27610a3ec7eb4a661448cd779a8f84c79 /drivers
parent01539ba2a706ab7d35fc0667dff919ade7f87d63 (diff)
parentb3e19d924b6eaf2ca7d22cba99a517c5171007b6 (diff)
Merge branch 'vfs-scale-working' of git://git.kernel.org/pub/scm/linux/kernel/git/npiggin/linux-npiggin
* 'vfs-scale-working' of git://git.kernel.org/pub/scm/linux/kernel/git/npiggin/linux-npiggin: (57 commits) fs: scale mntget/mntput fs: rename vfsmount counter helpers fs: implement faster dentry memcmp fs: prefetch inode data in dcache lookup fs: improve scalability of pseudo filesystems fs: dcache per-inode inode alias locking fs: dcache per-bucket dcache hash locking bit_spinlock: add required includes kernel: add bl_list xfs: provide simple rcu-walk ACL implementation btrfs: provide simple rcu-walk ACL implementation ext2,3,4: provide simple rcu-walk ACL implementation fs: provide simple rcu-walk generic_check_acl implementation fs: provide rcu-walk aware permission i_ops fs: rcu-walk aware d_revalidate method fs: cache optimise dentry and inode for rcu-walk fs: dcache reduce branches in lookup path fs: dcache remove d_mounted fs: fs_struct use seqlock fs: rcu-walk for path lookup ...
Diffstat (limited to 'drivers')
-rw-r--r--drivers/infiniband/hw/ipath/ipath_fs.c8
-rw-r--r--drivers/infiniband/hw/qib/qib_fs.c5
-rw-r--r--drivers/mtd/mtdchar.c2
-rw-r--r--drivers/staging/autofs/root.c7
-rw-r--r--drivers/staging/pohmelfs/inode.c9
-rw-r--r--drivers/staging/pohmelfs/path_entry.c17
-rw-r--r--drivers/staging/smbfs/cache.c16
-rw-r--r--drivers/staging/smbfs/dir.c50
-rw-r--r--drivers/staging/smbfs/file.c5
-rw-r--r--drivers/staging/smbfs/inode.c9
-rw-r--r--drivers/usb/core/inode.c12
11 files changed, 89 insertions, 51 deletions
diff --git a/drivers/infiniband/hw/ipath/ipath_fs.c b/drivers/infiniband/hw/ipath/ipath_fs.c
index 8c8afc716b98..31ae1b108aea 100644
--- a/drivers/infiniband/hw/ipath/ipath_fs.c
+++ b/drivers/infiniband/hw/ipath/ipath_fs.c
@@ -277,18 +277,14 @@ static int remove_file(struct dentry *parent, char *name)
277 goto bail; 277 goto bail;
278 } 278 }
279 279
280 spin_lock(&dcache_lock);
281 spin_lock(&tmp->d_lock); 280 spin_lock(&tmp->d_lock);
282 if (!(d_unhashed(tmp) && tmp->d_inode)) { 281 if (!(d_unhashed(tmp) && tmp->d_inode)) {
283 dget_locked(tmp); 282 dget_dlock(tmp);
284 __d_drop(tmp); 283 __d_drop(tmp);
285 spin_unlock(&tmp->d_lock); 284 spin_unlock(&tmp->d_lock);
286 spin_unlock(&dcache_lock);
287 simple_unlink(parent->d_inode, tmp); 285 simple_unlink(parent->d_inode, tmp);
288 } else { 286 } else
289 spin_unlock(&tmp->d_lock); 287 spin_unlock(&tmp->d_lock);
290 spin_unlock(&dcache_lock);
291 }
292 288
293 ret = 0; 289 ret = 0;
294bail: 290bail:
diff --git a/drivers/infiniband/hw/qib/qib_fs.c b/drivers/infiniband/hw/qib/qib_fs.c
index f99bddc01716..df7fa251dcdc 100644
--- a/drivers/infiniband/hw/qib/qib_fs.c
+++ b/drivers/infiniband/hw/qib/qib_fs.c
@@ -453,17 +453,14 @@ static int remove_file(struct dentry *parent, char *name)
453 goto bail; 453 goto bail;
454 } 454 }
455 455
456 spin_lock(&dcache_lock);
457 spin_lock(&tmp->d_lock); 456 spin_lock(&tmp->d_lock);
458 if (!(d_unhashed(tmp) && tmp->d_inode)) { 457 if (!(d_unhashed(tmp) && tmp->d_inode)) {
459 dget_locked(tmp); 458 dget_dlock(tmp);
460 __d_drop(tmp); 459 __d_drop(tmp);
461 spin_unlock(&tmp->d_lock); 460 spin_unlock(&tmp->d_lock);
462 spin_unlock(&dcache_lock);
463 simple_unlink(parent->d_inode, tmp); 461 simple_unlink(parent->d_inode, tmp);
464 } else { 462 } else {
465 spin_unlock(&tmp->d_lock); 463 spin_unlock(&tmp->d_lock);
466 spin_unlock(&dcache_lock);
467 } 464 }
468 465
469 ret = 0; 466 ret = 0;
diff --git a/drivers/mtd/mtdchar.c b/drivers/mtd/mtdchar.c
index 4759d827e8c7..f511dd15fd31 100644
--- a/drivers/mtd/mtdchar.c
+++ b/drivers/mtd/mtdchar.c
@@ -1201,7 +1201,7 @@ err_unregister_chdev:
1201static void __exit cleanup_mtdchar(void) 1201static void __exit cleanup_mtdchar(void)
1202{ 1202{
1203 unregister_mtd_user(&mtdchar_notifier); 1203 unregister_mtd_user(&mtdchar_notifier);
1204 mntput(mtd_inode_mnt); 1204 mntput_long(mtd_inode_mnt);
1205 unregister_filesystem(&mtd_inodefs_type); 1205 unregister_filesystem(&mtd_inodefs_type);
1206 __unregister_chrdev(MTD_CHAR_MAJOR, 0, 1 << MINORBITS, "mtd"); 1206 __unregister_chrdev(MTD_CHAR_MAJOR, 0, 1 << MINORBITS, "mtd");
1207} 1207}
diff --git a/drivers/staging/autofs/root.c b/drivers/staging/autofs/root.c
index 0fdec4befd84..bf0e9755da67 100644
--- a/drivers/staging/autofs/root.c
+++ b/drivers/staging/autofs/root.c
@@ -154,13 +154,16 @@ static int try_to_fill_dentry(struct dentry *dentry, struct super_block *sb, str
154 * yet completely filled in, and revalidate has to delay such 154 * yet completely filled in, and revalidate has to delay such
155 * lookups.. 155 * lookups..
156 */ 156 */
157static int autofs_revalidate(struct dentry * dentry, struct nameidata *nd) 157static int autofs_revalidate(struct dentry *dentry, struct nameidata *nd)
158{ 158{
159 struct inode * dir; 159 struct inode * dir;
160 struct autofs_sb_info *sbi; 160 struct autofs_sb_info *sbi;
161 struct autofs_dir_ent *ent; 161 struct autofs_dir_ent *ent;
162 int res; 162 int res;
163 163
164 if (nd->flags & LOOKUP_RCU)
165 return -ECHILD;
166
164 lock_kernel(); 167 lock_kernel();
165 dir = dentry->d_parent->d_inode; 168 dir = dentry->d_parent->d_inode;
166 sbi = autofs_sbi(dir->i_sb); 169 sbi = autofs_sbi(dir->i_sb);
@@ -237,7 +240,7 @@ static struct dentry *autofs_root_lookup(struct inode *dir, struct dentry *dentr
237 * 240 *
238 * We need to do this before we release the directory semaphore. 241 * We need to do this before we release the directory semaphore.
239 */ 242 */
240 dentry->d_op = &autofs_dentry_operations; 243 d_set_d_op(dentry, &autofs_dentry_operations);
241 dentry->d_flags |= DCACHE_AUTOFS_PENDING; 244 dentry->d_flags |= DCACHE_AUTOFS_PENDING;
242 d_add(dentry, NULL); 245 d_add(dentry, NULL);
243 246
diff --git a/drivers/staging/pohmelfs/inode.c b/drivers/staging/pohmelfs/inode.c
index 61685ccceda8..cc8d2840f9b6 100644
--- a/drivers/staging/pohmelfs/inode.c
+++ b/drivers/staging/pohmelfs/inode.c
@@ -826,6 +826,13 @@ const struct address_space_operations pohmelfs_aops = {
826 .set_page_dirty = __set_page_dirty_nobuffers, 826 .set_page_dirty = __set_page_dirty_nobuffers,
827}; 827};
828 828
829static void pohmelfs_i_callback(struct rcu_head *head)
830{
831 struct inode *inode = container_of(head, struct inode, i_rcu);
832 INIT_LIST_HEAD(&inode->i_dentry);
833 kmem_cache_free(pohmelfs_inode_cache, POHMELFS_I(inode));
834}
835
829/* 836/*
830 * ->detroy_inode() callback. Deletes inode from the caches 837 * ->detroy_inode() callback. Deletes inode from the caches
831 * and frees private data. 838 * and frees private data.
@@ -842,8 +849,8 @@ static void pohmelfs_destroy_inode(struct inode *inode)
842 849
843 dprintk("%s: pi: %p, inode: %p, ino: %llu.\n", 850 dprintk("%s: pi: %p, inode: %p, ino: %llu.\n",
844 __func__, pi, &pi->vfs_inode, pi->ino); 851 __func__, pi, &pi->vfs_inode, pi->ino);
845 kmem_cache_free(pohmelfs_inode_cache, pi);
846 atomic_long_dec(&psb->total_inodes); 852 atomic_long_dec(&psb->total_inodes);
853 call_rcu(&inode->i_rcu, pohmelfs_i_callback);
847} 854}
848 855
849/* 856/*
diff --git a/drivers/staging/pohmelfs/path_entry.c b/drivers/staging/pohmelfs/path_entry.c
index 8ec83d2dffb7..400a9fc386ad 100644
--- a/drivers/staging/pohmelfs/path_entry.c
+++ b/drivers/staging/pohmelfs/path_entry.c
@@ -83,10 +83,11 @@ out:
83int pohmelfs_path_length(struct pohmelfs_inode *pi) 83int pohmelfs_path_length(struct pohmelfs_inode *pi)
84{ 84{
85 struct dentry *d, *root, *first; 85 struct dentry *d, *root, *first;
86 int len = 1; /* Root slash */ 86 int len;
87 unsigned seq;
87 88
88 first = d = d_find_alias(&pi->vfs_inode); 89 first = d_find_alias(&pi->vfs_inode);
89 if (!d) { 90 if (!first) {
90 dprintk("%s: ino: %llu, mode: %o.\n", __func__, pi->ino, pi->vfs_inode.i_mode); 91 dprintk("%s: ino: %llu, mode: %o.\n", __func__, pi->ino, pi->vfs_inode.i_mode);
91 return -ENOENT; 92 return -ENOENT;
92 } 93 }
@@ -95,7 +96,11 @@ int pohmelfs_path_length(struct pohmelfs_inode *pi)
95 root = dget(current->fs->root.dentry); 96 root = dget(current->fs->root.dentry);
96 spin_unlock(&current->fs->lock); 97 spin_unlock(&current->fs->lock);
97 98
98 spin_lock(&dcache_lock); 99rename_retry:
100 len = 1; /* Root slash */
101 d = first;
102 seq = read_seqbegin(&rename_lock);
103 rcu_read_lock();
99 104
100 if (!IS_ROOT(d) && d_unhashed(d)) 105 if (!IS_ROOT(d) && d_unhashed(d))
101 len += UNHASHED_OBSCURE_STRING_SIZE; /* Obscure " (deleted)" string */ 106 len += UNHASHED_OBSCURE_STRING_SIZE; /* Obscure " (deleted)" string */
@@ -104,7 +109,9 @@ int pohmelfs_path_length(struct pohmelfs_inode *pi)
104 len += d->d_name.len + 1; /* Plus slash */ 109 len += d->d_name.len + 1; /* Plus slash */
105 d = d->d_parent; 110 d = d->d_parent;
106 } 111 }
107 spin_unlock(&dcache_lock); 112 rcu_read_unlock();
113 if (read_seqretry(&rename_lock, seq))
114 goto rename_retry;
108 115
109 dput(root); 116 dput(root);
110 dput(first); 117 dput(first);
diff --git a/drivers/staging/smbfs/cache.c b/drivers/staging/smbfs/cache.c
index dbb98658148b..f2a1323ca827 100644
--- a/drivers/staging/smbfs/cache.c
+++ b/drivers/staging/smbfs/cache.c
@@ -62,7 +62,7 @@ smb_invalidate_dircache_entries(struct dentry *parent)
62 struct list_head *next; 62 struct list_head *next;
63 struct dentry *dentry; 63 struct dentry *dentry;
64 64
65 spin_lock(&dcache_lock); 65 spin_lock(&parent->d_lock);
66 next = parent->d_subdirs.next; 66 next = parent->d_subdirs.next;
67 while (next != &parent->d_subdirs) { 67 while (next != &parent->d_subdirs) {
68 dentry = list_entry(next, struct dentry, d_u.d_child); 68 dentry = list_entry(next, struct dentry, d_u.d_child);
@@ -70,7 +70,7 @@ smb_invalidate_dircache_entries(struct dentry *parent)
70 smb_age_dentry(server, dentry); 70 smb_age_dentry(server, dentry);
71 next = next->next; 71 next = next->next;
72 } 72 }
73 spin_unlock(&dcache_lock); 73 spin_unlock(&parent->d_lock);
74} 74}
75 75
76/* 76/*
@@ -96,13 +96,13 @@ smb_dget_fpos(struct dentry *dentry, struct dentry *parent, unsigned long fpos)
96 } 96 }
97 97
98 /* If a pointer is invalid, we search the dentry. */ 98 /* If a pointer is invalid, we search the dentry. */
99 spin_lock(&dcache_lock); 99 spin_lock(&parent->d_lock);
100 next = parent->d_subdirs.next; 100 next = parent->d_subdirs.next;
101 while (next != &parent->d_subdirs) { 101 while (next != &parent->d_subdirs) {
102 dent = list_entry(next, struct dentry, d_u.d_child); 102 dent = list_entry(next, struct dentry, d_u.d_child);
103 if ((unsigned long)dent->d_fsdata == fpos) { 103 if ((unsigned long)dent->d_fsdata == fpos) {
104 if (dent->d_inode) 104 if (dent->d_inode)
105 dget_locked(dent); 105 dget(dent);
106 else 106 else
107 dent = NULL; 107 dent = NULL;
108 goto out_unlock; 108 goto out_unlock;
@@ -111,7 +111,7 @@ smb_dget_fpos(struct dentry *dentry, struct dentry *parent, unsigned long fpos)
111 } 111 }
112 dent = NULL; 112 dent = NULL;
113out_unlock: 113out_unlock:
114 spin_unlock(&dcache_lock); 114 spin_unlock(&parent->d_lock);
115 return dent; 115 return dent;
116} 116}
117 117
@@ -134,7 +134,7 @@ smb_fill_cache(struct file *filp, void *dirent, filldir_t filldir,
134 qname->hash = full_name_hash(qname->name, qname->len); 134 qname->hash = full_name_hash(qname->name, qname->len);
135 135
136 if (dentry->d_op && dentry->d_op->d_hash) 136 if (dentry->d_op && dentry->d_op->d_hash)
137 if (dentry->d_op->d_hash(dentry, qname) != 0) 137 if (dentry->d_op->d_hash(dentry, inode, qname) != 0)
138 goto end_advance; 138 goto end_advance;
139 139
140 newdent = d_lookup(dentry, qname); 140 newdent = d_lookup(dentry, qname);
@@ -145,8 +145,8 @@ smb_fill_cache(struct file *filp, void *dirent, filldir_t filldir,
145 goto end_advance; 145 goto end_advance;
146 } else { 146 } else {
147 hashed = 1; 147 hashed = 1;
148 memcpy((char *) newdent->d_name.name, qname->name, 148 /* dir i_mutex is locked because we're in readdir */
149 newdent->d_name.len); 149 dentry_update_name_case(newdent, qname);
150 } 150 }
151 151
152 if (!newdent->d_inode) { 152 if (!newdent->d_inode) {
diff --git a/drivers/staging/smbfs/dir.c b/drivers/staging/smbfs/dir.c
index f088ea2f6ac9..dd612f50749f 100644
--- a/drivers/staging/smbfs/dir.c
+++ b/drivers/staging/smbfs/dir.c
@@ -14,6 +14,7 @@
14#include <linux/ctype.h> 14#include <linux/ctype.h>
15#include <linux/net.h> 15#include <linux/net.h>
16#include <linux/sched.h> 16#include <linux/sched.h>
17#include <linux/namei.h>
17 18
18#include "smb_fs.h" 19#include "smb_fs.h"
19#include "smb_mount.h" 20#include "smb_mount.h"
@@ -274,9 +275,13 @@ smb_dir_open(struct inode *dir, struct file *file)
274 * Dentry operations routines 275 * Dentry operations routines
275 */ 276 */
276static int smb_lookup_validate(struct dentry *, struct nameidata *); 277static int smb_lookup_validate(struct dentry *, struct nameidata *);
277static int smb_hash_dentry(struct dentry *, struct qstr *); 278static int smb_hash_dentry(const struct dentry *, const struct inode *,
278static int smb_compare_dentry(struct dentry *, struct qstr *, struct qstr *); 279 struct qstr *);
279static int smb_delete_dentry(struct dentry *); 280static int smb_compare_dentry(const struct dentry *,
281 const struct inode *,
282 const struct dentry *, const struct inode *,
283 unsigned int, const char *, const struct qstr *);
284static int smb_delete_dentry(const struct dentry *);
280 285
281static const struct dentry_operations smbfs_dentry_operations = 286static const struct dentry_operations smbfs_dentry_operations =
282{ 287{
@@ -297,13 +302,20 @@ static const struct dentry_operations smbfs_dentry_operations_case =
297 * This is the callback when the dcache has a lookup hit. 302 * This is the callback when the dcache has a lookup hit.
298 */ 303 */
299static int 304static int
300smb_lookup_validate(struct dentry * dentry, struct nameidata *nd) 305smb_lookup_validate(struct dentry *dentry, struct nameidata *nd)
301{ 306{
302 struct smb_sb_info *server = server_from_dentry(dentry); 307 struct smb_sb_info *server;
303 struct inode * inode = dentry->d_inode; 308 struct inode *inode;
304 unsigned long age = jiffies - dentry->d_time; 309 unsigned long age;
305 int valid; 310 int valid;
306 311
312 if (nd->flags & LOOKUP_RCU)
313 return -ECHILD;
314
315 server = server_from_dentry(dentry);
316 inode = dentry->d_inode;
317 age = jiffies - dentry->d_time;
318
307 /* 319 /*
308 * The default validation is based on dentry age: 320 * The default validation is based on dentry age:
309 * we believe in dentries for a few seconds. (But each 321 * we believe in dentries for a few seconds. (But each
@@ -333,7 +345,8 @@ smb_lookup_validate(struct dentry * dentry, struct nameidata *nd)
333} 345}
334 346
335static int 347static int
336smb_hash_dentry(struct dentry *dir, struct qstr *this) 348smb_hash_dentry(const struct dentry *dir, const struct inode *inode,
349 struct qstr *this)
337{ 350{
338 unsigned long hash; 351 unsigned long hash;
339 int i; 352 int i;
@@ -347,14 +360,17 @@ smb_hash_dentry(struct dentry *dir, struct qstr *this)
347} 360}
348 361
349static int 362static int
350smb_compare_dentry(struct dentry *dir, struct qstr *a, struct qstr *b) 363smb_compare_dentry(const struct dentry *parent,
364 const struct inode *pinode,
365 const struct dentry *dentry, const struct inode *inode,
366 unsigned int len, const char *str, const struct qstr *name)
351{ 367{
352 int i, result = 1; 368 int i, result = 1;
353 369
354 if (a->len != b->len) 370 if (len != name->len)
355 goto out; 371 goto out;
356 for (i=0; i < a->len; i++) { 372 for (i=0; i < len; i++) {
357 if (tolower(a->name[i]) != tolower(b->name[i])) 373 if (tolower(str[i]) != tolower(name->name[i]))
358 goto out; 374 goto out;
359 } 375 }
360 result = 0; 376 result = 0;
@@ -367,7 +383,7 @@ out:
367 * We use this to unhash dentries with bad inodes. 383 * We use this to unhash dentries with bad inodes.
368 */ 384 */
369static int 385static int
370smb_delete_dentry(struct dentry * dentry) 386smb_delete_dentry(const struct dentry *dentry)
371{ 387{
372 if (dentry->d_inode) { 388 if (dentry->d_inode) {
373 if (is_bad_inode(dentry->d_inode)) { 389 if (is_bad_inode(dentry->d_inode)) {
@@ -390,9 +406,9 @@ smb_new_dentry(struct dentry *dentry)
390 struct smb_sb_info *server = server_from_dentry(dentry); 406 struct smb_sb_info *server = server_from_dentry(dentry);
391 407
392 if (server->mnt->flags & SMB_MOUNT_CASE) 408 if (server->mnt->flags & SMB_MOUNT_CASE)
393 dentry->d_op = &smbfs_dentry_operations_case; 409 d_set_d_op(dentry, &smbfs_dentry_operations_case);
394 else 410 else
395 dentry->d_op = &smbfs_dentry_operations; 411 d_set_d_op(dentry, &smbfs_dentry_operations);
396 dentry->d_time = jiffies; 412 dentry->d_time = jiffies;
397} 413}
398 414
@@ -454,9 +470,9 @@ smb_lookup(struct inode *dir, struct dentry *dentry, struct nameidata *nd)
454 add_entry: 470 add_entry:
455 server = server_from_dentry(dentry); 471 server = server_from_dentry(dentry);
456 if (server->mnt->flags & SMB_MOUNT_CASE) 472 if (server->mnt->flags & SMB_MOUNT_CASE)
457 dentry->d_op = &smbfs_dentry_operations_case; 473 d_set_d_op(dentry, &smbfs_dentry_operations_case);
458 else 474 else
459 dentry->d_op = &smbfs_dentry_operations; 475 d_set_d_op(dentry, &smbfs_dentry_operations);
460 476
461 d_add(dentry, inode); 477 d_add(dentry, inode);
462 smb_renew_times(dentry); 478 smb_renew_times(dentry);
diff --git a/drivers/staging/smbfs/file.c b/drivers/staging/smbfs/file.c
index 5dcd19c60eb9..31372e7b12de 100644
--- a/drivers/staging/smbfs/file.c
+++ b/drivers/staging/smbfs/file.c
@@ -407,11 +407,14 @@ smb_file_release(struct inode *inode, struct file * file)
407 * privileges, so we need our own check for this. 407 * privileges, so we need our own check for this.
408 */ 408 */
409static int 409static int
410smb_file_permission(struct inode *inode, int mask) 410smb_file_permission(struct inode *inode, int mask, unsigned int flags)
411{ 411{
412 int mode = inode->i_mode; 412 int mode = inode->i_mode;
413 int error = 0; 413 int error = 0;
414 414
415 if (flags & IPERM_FLAG_RCU)
416 return -ECHILD;
417
415 VERBOSE("mode=%x, mask=%x\n", mode, mask); 418 VERBOSE("mode=%x, mask=%x\n", mode, mask);
416 419
417 /* Look at user permissions */ 420 /* Look at user permissions */
diff --git a/drivers/staging/smbfs/inode.c b/drivers/staging/smbfs/inode.c
index 540a984bb516..244319dc9702 100644
--- a/drivers/staging/smbfs/inode.c
+++ b/drivers/staging/smbfs/inode.c
@@ -62,11 +62,18 @@ static struct inode *smb_alloc_inode(struct super_block *sb)
62 return &ei->vfs_inode; 62 return &ei->vfs_inode;
63} 63}
64 64
65static void smb_destroy_inode(struct inode *inode) 65static void smb_i_callback(struct rcu_head *head)
66{ 66{
67 struct inode *inode = container_of(head, struct inode, i_rcu);
68 INIT_LIST_HEAD(&inode->i_dentry);
67 kmem_cache_free(smb_inode_cachep, SMB_I(inode)); 69 kmem_cache_free(smb_inode_cachep, SMB_I(inode));
68} 70}
69 71
72static void smb_destroy_inode(struct inode *inode)
73{
74 call_rcu(&inode->i_rcu, smb_i_callback);
75}
76
70static void init_once(void *foo) 77static void init_once(void *foo)
71{ 78{
72 struct smb_inode_info *ei = (struct smb_inode_info *) foo; 79 struct smb_inode_info *ei = (struct smb_inode_info *) foo;
diff --git a/drivers/usb/core/inode.c b/drivers/usb/core/inode.c
index b690aa35df9a..1b125c224dcf 100644
--- a/drivers/usb/core/inode.c
+++ b/drivers/usb/core/inode.c
@@ -343,17 +343,19 @@ static int usbfs_empty (struct dentry *dentry)
343{ 343{
344 struct list_head *list; 344 struct list_head *list;
345 345
346 spin_lock(&dcache_lock); 346 spin_lock(&dentry->d_lock);
347
348 list_for_each(list, &dentry->d_subdirs) { 347 list_for_each(list, &dentry->d_subdirs) {
349 struct dentry *de = list_entry(list, struct dentry, d_u.d_child); 348 struct dentry *de = list_entry(list, struct dentry, d_u.d_child);
349
350 spin_lock_nested(&de->d_lock, DENTRY_D_LOCK_NESTED);
350 if (usbfs_positive(de)) { 351 if (usbfs_positive(de)) {
351 spin_unlock(&dcache_lock); 352 spin_unlock(&de->d_lock);
353 spin_unlock(&dentry->d_lock);
352 return 0; 354 return 0;
353 } 355 }
356 spin_unlock(&de->d_lock);
354 } 357 }
355 358 spin_unlock(&dentry->d_lock);
356 spin_unlock(&dcache_lock);
357 return 1; 359 return 1;
358} 360}
359 361