summaryrefslogtreecommitdiffstats
path: root/fs/libfs.c
diff options
context:
space:
mode:
authorAl Viro <viro@zeniv.linux.org.uk>2016-06-07 00:55:57 +0200
committerAl Viro <viro@zeniv.linux.org.uk>2016-06-20 23:11:26 +0200
commit274f5b041d3c9c0974a7dd1f66b67c33bb5b0f42 (patch)
treeb67a10ee704422c2674462c9edec183c6c493a78 /fs/libfs.c
parentfix idiotic braino in d_alloc_parallel() (diff)
downloadlinux-274f5b041d3c9c0974a7dd1f66b67c33bb5b0f42.tar.xz
linux-274f5b041d3c9c0974a7dd1f66b67c33bb5b0f42.zip
dcache_{readdir,dir_lseek}(): don't bother with nested ->d_lock
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>
Diffstat (limited to 'fs/libfs.c')
-rw-r--r--fs/libfs.c12
1 files changed, 3 insertions, 9 deletions
diff --git a/fs/libfs.c b/fs/libfs.c
index cedeacbae303..f56acb1e5fbc 100644
--- a/fs/libfs.c
+++ b/fs/libfs.c
@@ -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++;
}