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

Commit a01b3007 authored by Al Viro's avatar Al Viro
Browse files

configfs_readdir(): make safe under shared lock



Signed-off-by: default avatarAl Viro <viro@zeniv.linux.org.uk>
parent 884be175
Loading
Loading
Loading
Loading
+7 −13
Original line number Diff line number Diff line
@@ -1633,11 +1633,9 @@ static int configfs_readdir(struct file *file, struct dir_context *ctx)

	if (!dir_emit_dots(file, ctx))
		return 0;
	if (ctx->pos == 2) {
	spin_lock(&configfs_dirent_lock);
	if (ctx->pos == 2)
		list_move(q, &parent_sd->s_children);
		spin_unlock(&configfs_dirent_lock);
	}
	for (p = q->next; p != &parent_sd->s_children; p = p->next) {
		struct configfs_dirent *next;
		const char *name;
@@ -1648,9 +1646,6 @@ static int configfs_readdir(struct file *file, struct dir_context *ctx)
		if (!next->s_element)
			continue;

		name = configfs_get_name(next);
		len = strlen(name);

		/*
		 * We'll have a dentry and an inode for
		 * PINNED items and for open attribute
@@ -1664,7 +1659,6 @@ static int configfs_readdir(struct file *file, struct dir_context *ctx)
		 * they close it.  Beyond that, we don't
		 * care.
		 */
		spin_lock(&configfs_dirent_lock);
		dentry = next->s_dentry;
		if (dentry)
			inode = d_inode(dentry);
@@ -1674,15 +1668,18 @@ static int configfs_readdir(struct file *file, struct dir_context *ctx)
		if (!inode)
			ino = iunique(sb, 2);

		name = configfs_get_name(next);
		len = strlen(name);

		if (!dir_emit(ctx, name, len, ino, dt_type(next)))
			return 0;

		spin_lock(&configfs_dirent_lock);
		list_move(q, p);
		spin_unlock(&configfs_dirent_lock);
		p = q;
		ctx->pos++;
	}
	spin_unlock(&configfs_dirent_lock);
	return 0;
}

@@ -1690,7 +1687,6 @@ static loff_t configfs_dir_lseek(struct file *file, loff_t offset, int whence)
{
	struct dentry * dentry = file->f_path.dentry;

	inode_lock(d_inode(dentry));
	switch (whence) {
		case 1:
			offset += file->f_pos;
@@ -1698,7 +1694,6 @@ static loff_t configfs_dir_lseek(struct file *file, loff_t offset, int whence)
			if (offset >= 0)
				break;
		default:
			inode_unlock(d_inode(dentry));
			return -EINVAL;
	}
	if (offset != file->f_pos) {
@@ -1724,7 +1719,6 @@ static loff_t configfs_dir_lseek(struct file *file, loff_t offset, int whence)
			spin_unlock(&configfs_dirent_lock);
		}
	}
	inode_unlock(d_inode(dentry));
	return offset;
}

@@ -1733,7 +1727,7 @@ const struct file_operations configfs_dir_operations = {
	.release	= configfs_dir_close,
	.llseek		= configfs_dir_lseek,
	.read		= generic_read_dir,
	.iterate	= configfs_readdir,
	.iterate_shared	= configfs_readdir,
};

/**