Commit 274f5b04 authored by Al Viro's avatar Al Viro

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: default avatarAl Viro <viro@zeniv.linux.org.uk>
parent e7d6ef97
...@@ -103,6 +103,7 @@ loff_t dcache_dir_lseek(struct file *file, loff_t offset, int whence) ...@@ -103,6 +103,7 @@ loff_t dcache_dir_lseek(struct file *file, loff_t offset, int whence)
struct dentry *cursor = file->private_data; struct dentry *cursor = file->private_data;
loff_t n = file->f_pos - 2; loff_t n = file->f_pos - 2;
inode_lock_shared(dentry->d_inode);
spin_lock(&dentry->d_lock); spin_lock(&dentry->d_lock);
/* d_lock not required for cursor */ /* d_lock not required for cursor */
list_del(&cursor->d_child); list_del(&cursor->d_child);
...@@ -110,14 +111,13 @@ loff_t dcache_dir_lseek(struct file *file, loff_t offset, int whence) ...@@ -110,14 +111,13 @@ loff_t dcache_dir_lseek(struct file *file, loff_t offset, int whence)
while (n && p != &dentry->d_subdirs) { while (n && p != &dentry->d_subdirs) {
struct dentry *next; struct dentry *next;
next = list_entry(p, struct dentry, d_child); next = list_entry(p, struct dentry, d_child);
spin_lock_nested(&next->d_lock, DENTRY_D_LOCK_NESTED);
if (simple_positive(next)) if (simple_positive(next))
n--; n--;
spin_unlock(&next->d_lock);
p = p->next; p = p->next;
} }
list_add_tail(&cursor->d_child, p); list_add_tail(&cursor->d_child, p);
spin_unlock(&dentry->d_lock); spin_unlock(&dentry->d_lock);
inode_unlock_shared(dentry->d_inode);
} }
} }
return offset; return offset;
...@@ -150,22 +150,16 @@ int dcache_readdir(struct file *file, struct dir_context *ctx) ...@@ -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) { for (p = q->next; p != &dentry->d_subdirs; p = p->next) {
struct dentry *next = list_entry(p, struct dentry, d_child); struct dentry *next = list_entry(p, struct dentry, d_child);
spin_lock_nested(&next->d_lock, DENTRY_D_LOCK_NESTED); if (!simple_positive(next))
if (!simple_positive(next)) {
spin_unlock(&next->d_lock);
continue; continue;
}
spin_unlock(&next->d_lock);
spin_unlock(&dentry->d_lock); spin_unlock(&dentry->d_lock);
if (!dir_emit(ctx, next->d_name.name, next->d_name.len, if (!dir_emit(ctx, next->d_name.name, next->d_name.len,
d_inode(next)->i_ino, dt_type(d_inode(next)))) d_inode(next)->i_ino, dt_type(d_inode(next))))
return 0; return 0;
spin_lock(&dentry->d_lock); spin_lock(&dentry->d_lock);
spin_lock_nested(&next->d_lock, DENTRY_D_LOCK_NESTED);
/* next is still alive */ /* next is still alive */
list_move(q, p); list_move(q, p);
spin_unlock(&next->d_lock);
p = q; p = q;
ctx->pos++; ctx->pos++;
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment