diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2011-01-07 11:56:33 -0500 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2011-01-07 11:56:33 -0500 |
commit | b4a45f5fe8078bfc10837dbd5b98735058bc4698 (patch) | |
tree | df6f13a27610a3ec7eb4a661448cd779a8f84c79 /drivers | |
parent | 01539ba2a706ab7d35fc0667dff919ade7f87d63 (diff) | |
parent | b3e19d924b6eaf2ca7d22cba99a517c5171007b6 (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.c | 8 | ||||
-rw-r--r-- | drivers/infiniband/hw/qib/qib_fs.c | 5 | ||||
-rw-r--r-- | drivers/mtd/mtdchar.c | 2 | ||||
-rw-r--r-- | drivers/staging/autofs/root.c | 7 | ||||
-rw-r--r-- | drivers/staging/pohmelfs/inode.c | 9 | ||||
-rw-r--r-- | drivers/staging/pohmelfs/path_entry.c | 17 | ||||
-rw-r--r-- | drivers/staging/smbfs/cache.c | 16 | ||||
-rw-r--r-- | drivers/staging/smbfs/dir.c | 50 | ||||
-rw-r--r-- | drivers/staging/smbfs/file.c | 5 | ||||
-rw-r--r-- | drivers/staging/smbfs/inode.c | 9 | ||||
-rw-r--r-- | drivers/usb/core/inode.c | 12 |
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; |
294 | bail: | 290 | bail: |
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: | |||
1201 | static void __exit cleanup_mtdchar(void) | 1201 | static 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 | */ |
157 | static int autofs_revalidate(struct dentry * dentry, struct nameidata *nd) | 157 | static 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 | ||
829 | static 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: | |||
83 | int pohmelfs_path_length(struct pohmelfs_inode *pi) | 83 | int 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(¤t->fs->lock); | 97 | spin_unlock(¤t->fs->lock); |
97 | 98 | ||
98 | spin_lock(&dcache_lock); | 99 | rename_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; |
113 | out_unlock: | 113 | out_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 | */ |
276 | static int smb_lookup_validate(struct dentry *, struct nameidata *); | 277 | static int smb_lookup_validate(struct dentry *, struct nameidata *); |
277 | static int smb_hash_dentry(struct dentry *, struct qstr *); | 278 | static int smb_hash_dentry(const struct dentry *, const struct inode *, |
278 | static int smb_compare_dentry(struct dentry *, struct qstr *, struct qstr *); | 279 | struct qstr *); |
279 | static int smb_delete_dentry(struct dentry *); | 280 | static 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 *); | ||
284 | static int smb_delete_dentry(const struct dentry *); | ||
280 | 285 | ||
281 | static const struct dentry_operations smbfs_dentry_operations = | 286 | static 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 | */ |
299 | static int | 304 | static int |
300 | smb_lookup_validate(struct dentry * dentry, struct nameidata *nd) | 305 | smb_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 | ||
335 | static int | 347 | static int |
336 | smb_hash_dentry(struct dentry *dir, struct qstr *this) | 348 | smb_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 | ||
349 | static int | 362 | static int |
350 | smb_compare_dentry(struct dentry *dir, struct qstr *a, struct qstr *b) | 363 | smb_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 | */ |
369 | static int | 385 | static int |
370 | smb_delete_dentry(struct dentry * dentry) | 386 | smb_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 | */ |
409 | static int | 409 | static int |
410 | smb_file_permission(struct inode *inode, int mask) | 410 | smb_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 | ||
65 | static void smb_destroy_inode(struct inode *inode) | 65 | static 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 | ||
72 | static void smb_destroy_inode(struct inode *inode) | ||
73 | { | ||
74 | call_rcu(&inode->i_rcu, smb_i_callback); | ||
75 | } | ||
76 | |||
70 | static void init_once(void *foo) | 77 | static 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 | ||