diff options
author | Al Viro <viro@zeniv.linux.org.uk> | 2016-06-06 18:55:57 -0400 |
---|---|---|
committer | Al Viro <viro@zeniv.linux.org.uk> | 2016-06-20 17:11:26 -0400 |
commit | 274f5b041d3c9c0974a7dd1f66b67c33bb5b0f42 (patch) | |
tree | b67a10ee704422c2674462c9edec183c6c493a78 /fs/libfs.c | |
parent | e7d6ef9790bc281f5c29d0132b68031248523fe8 (diff) |
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.c | 12 |
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++; } |