d_drop should use per dentry lock
Subsystems (3)
PATCH 1/1 d_drop should use per dentry lock
d_drop() must use the dentry->d_lock spinlock. In some cases __d_drop() was used without holding the dentry->d_lock spinlock, too. This could end in a race with __d_lookup().
Regards,
Jan
Signed-off-by Jan Blunck <[email protected]>
fs/autofs4/root.c | 2 ++ fs/dcache.c | 3 +++ fs/namei.c | 14 +++++--------- fs/proc/base.c | 6 +++++- fs/sysfs/inode.c | 6 +++++- include/linux/dcache.h | 2 ++ 6 files changed, 22 insertions(+), 11 deletions(-)
include/linux/dcache.h +2 -0
@@ -186,7 +186,9 @@static inline void d_drop (struct dentry *dentry) {spin_lock (&dcache_lock); +spin_lock (&dentry->d_lock);__d_drop (dentry); +spin_unlock (&dentry->d_lock);spin_unlock (&dcache_lock); }
fs/namei.c +5 -9
@@ -1684,17 +1684,13 @@void dentry_unhash (struct dentry *dentry) {dget (dentry); -spin_lock (&dcache_lock); -switch (atomic_read (&dentry->d_count)) { -default : -spin_unlock (&dcache_lock); +if (atomic_read (&dentry->d_count))shrink_dcache_parent (dentry); -spin_lock (&dcache_lock); -if (atomic_read (&dentry->d_count) !=2 ) -break ; -case 2 : +spin_lock (&dcache_lock); +spin_lock (&dentry->d_lock); +if (atomic_read (&dentry->d_count) ==2 )__d_drop (dentry); - } +spin_unlock (&dentry->d_lock);spin_unlock (&dcache_lock); }
fs/sysfs/inode.c +5 -1
@@ -129,13 +129,17 @@if (dentry) {spin_lock (&dcache_lock); +spin_lock (&dentry->d_lock);if (!(d_unhashed (dentry) && dentry->d_inode)) {dget_locked (dentry);__d_drop (dentry); +spin_unlock (&dentry->d_lock);spin_unlock (&dcache_lock);simple_unlink (parent->d_inode, dentry); - }else + }else { +spin_unlock (&dentry->d_lock);spin_unlock (&dcache_lock); + } } }
fs/dcache.c +3 -0
@@ -340,13 +340,16 @@ tmp = head;while ((tmp = tmp->next) != head) { struct dentry *dentry = list_entry(tmp, struct dentry, d_alias); +spin_lock (&dentry->d_lock);if (!atomic_read (&dentry->d_count)) {__dget_locked (dentry);__d_drop (dentry); +spin_unlock (&dentry->d_lock);spin_unlock (&dcache_lock);dput (dentry); goto restart; } +spin_unlock (&dentry->d_lock); }spin_unlock (&dcache_lock); }
fs/autofs4/root.c +2 -0
@@ -605,7 +605,9 @@spin_unlock (&dcache_lock);return -ENOTEMPTY ; } +spin_lock (&dentry->d_lock);__d_drop (dentry); +spin_unlock (&dentry->d_lock);spin_unlock (&dcache_lock);dput (ino->dentry);
fs/proc/base.c +5 -1
@@ -1468,11 +1468,15 @@if (proc_dentry !=NULL ) {spin_lock (&dcache_lock); +spin_lock (&proc_dentry->d_lock);if (!d_unhashed (proc_dentry)) {dget_locked (proc_dentry);__d_drop (proc_dentry); - }else +spin_unlock (&proc_dentry->d_lock); + }else { +spin_unlock (&proc_dentry->d_lock); proc_dentry =NULL ; + }spin_unlock (&dcache_lock); }return proc_dentry;