Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

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

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
Loading
Loading
Loading
Loading
+3 −9
Original line number Diff line number Diff line
@@ -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++;
	}