dcache_{readdir,dir_lseek}(): don't bother with nested ->d_lock
authorAl Viro <viro@zeniv.linux.org.uk>
Mon, 6 Jun 2016 22:55:57 +0000 (18:55 -0400)
committerAl Viro <viro@zeniv.linux.org.uk>
Mon, 20 Jun 2016 21:11:26 +0000 (17:11 -0400)
Make sure that directory is locked shared in dcache_dir_lseek();
for dcache_readdir() it's already tru, and that's enough to make
simple_positive() stable.

Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
fs/libfs.c

index cedeacb..f56acb1 100644 (file)
@@ -103,6 +103,7 @@ loff_t dcache_dir_lseek(struct file *file, loff_t offset, int whence)
                        struct dentry *cursor = file->private_data;
                        loff_t n = file->f_pos - 2;
 
+                       inode_lock_shared(dentry->d_inode);
                        spin_lock(&dentry->d_lock);
                        /* d_lock not required for cursor */
                        list_del(&cursor->d_child);
@@ -110,14 +111,13 @@ loff_t dcache_dir_lseek(struct file *file, loff_t offset, int whence)
                        while (n && p != &dentry->d_subdirs) {
                                struct dentry *next;
                                next = list_entry(p, struct dentry, d_child);
-                               spin_lock_nested(&next->d_lock, DENTRY_D_LOCK_NESTED);
                                if (simple_positive(next))
                                        n--;
-                               spin_unlock(&next->d_lock);
                                p = p->next;
                        }
                        list_add_tail(&cursor->d_child, p);
                        spin_unlock(&dentry->d_lock);
+                       inode_unlock_shared(dentry->d_inode);
                }
        }
        return offset;
@@ -150,22 +150,16 @@ int dcache_readdir(struct file *file, struct dir_context *ctx)
 
        for (p = q->next; p != &dentry->d_subdirs; p = p->next) {
                struct dentry *next = list_entry(p, struct dentry, d_child);
-               spin_lock_nested(&next->d_lock, DENTRY_D_LOCK_NESTED);
-               if (!simple_positive(next)) {
-                       spin_unlock(&next->d_lock);
+               if (!simple_positive(next))
                        continue;
-               }
 
-               spin_unlock(&next->d_lock);
                spin_unlock(&dentry->d_lock);
                if (!dir_emit(ctx, next->d_name.name, next->d_name.len,
                              d_inode(next)->i_ino, dt_type(d_inode(next))))
                        return 0;
                spin_lock(&dentry->d_lock);
-               spin_lock_nested(&next->d_lock, DENTRY_D_LOCK_NESTED);
                /* next is still alive */
                list_move(q, p);
-               spin_unlock(&next->d_lock);
                p = q;
                ctx->pos++;
        }