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

Commit 5f99f4e7 authored by Al Viro's avatar Al Viro
Browse files

[readdir] switch dcache_readdir() users to ->iterate()



new helpers - dir_emit_dot(file, ctx, dentry), dir_emit_dotdot(file, ctx),
dir_emit_dots(file, ctx).

Signed-off-by: default avatarAl Viro <viro@zeniv.linux.org.uk>
parent 80886298
Loading
Loading
Loading
Loading
+1 −1
Original line number Diff line number Diff line
@@ -238,7 +238,7 @@ const struct file_operations spufs_context_fops = {
	.release	= spufs_dir_close,
	.llseek		= dcache_dir_lseek,
	.read		= generic_read_dir,
	.readdir	= dcache_readdir,
	.iterate	= dcache_readdir,
	.fsync		= noop_fsync,
};
EXPORT_SYMBOL_GPL(spufs_context_fops);
+2 −2
Original line number Diff line number Diff line
@@ -41,7 +41,7 @@ const struct file_operations autofs4_root_operations = {
	.open		= dcache_dir_open,
	.release	= dcache_dir_close,
	.read		= generic_read_dir,
	.readdir	= dcache_readdir,
	.iterate	= dcache_readdir,
	.llseek		= dcache_dir_lseek,
	.unlocked_ioctl	= autofs4_root_ioctl,
#ifdef CONFIG_COMPAT
@@ -53,7 +53,7 @@ const struct file_operations autofs4_dir_operations = {
	.open		= autofs4_dir_open,
	.release	= dcache_dir_close,
	.read		= generic_read_dir,
	.readdir	= dcache_readdir,
	.iterate	= dcache_readdir,
	.llseek		= dcache_dir_lseek,
};

+30 −50
Original line number Diff line number Diff line
@@ -135,37 +135,20 @@ static inline unsigned char dt_type(struct inode *inode)
 * both impossible due to the lock on directory.
 */

int dcache_readdir(struct file * filp, void * dirent, filldir_t filldir)
int dcache_readdir(struct file *file, struct dir_context *ctx)
{
	struct dentry *dentry = filp->f_path.dentry;
	struct dentry *cursor = filp->private_data;
	struct dentry *dentry = file->f_path.dentry;
	struct dentry *cursor = file->private_data;
	struct list_head *p, *q = &cursor->d_u.d_child;
	ino_t ino;
	int i = filp->f_pos;

	switch (i) {
		case 0:
			ino = dentry->d_inode->i_ino;
			if (filldir(dirent, ".", 1, i, ino, DT_DIR) < 0)
				break;
			filp->f_pos++;
			i++;
			/* fallthrough */
		case 1:
			ino = parent_ino(dentry);
			if (filldir(dirent, "..", 2, i, ino, DT_DIR) < 0)
				break;
			filp->f_pos++;
			i++;
			/* fallthrough */
		default:
	if (!dir_emit_dots(file, ctx))
		return 0;
	spin_lock(&dentry->d_lock);
			if (filp->f_pos == 2)
	if (ctx->pos == 2)
		list_move(q, &dentry->d_subdirs);

	for (p = q->next; p != &dentry->d_subdirs; p = p->next) {
				struct dentry *next;
				next = list_entry(p, struct dentry, d_u.d_child);
		struct dentry *next = list_entry(p, struct dentry, d_u.d_child);
		spin_lock_nested(&next->d_lock, DENTRY_D_LOCK_NESTED);
		if (!simple_positive(next)) {
			spin_unlock(&next->d_lock);
@@ -174,10 +157,8 @@ int dcache_readdir(struct file * filp, void * dirent, filldir_t filldir)

		spin_unlock(&next->d_lock);
		spin_unlock(&dentry->d_lock);
				if (filldir(dirent, next->d_name.name, 
					    next->d_name.len, filp->f_pos, 
					    next->d_inode->i_ino, 
					    dt_type(next->d_inode)) < 0)
		if (!dir_emit(ctx, next->d_name.name, next->d_name.len,
			      next->d_inode->i_ino, dt_type(next->d_inode)))
			return 0;
		spin_lock(&dentry->d_lock);
		spin_lock_nested(&next->d_lock, DENTRY_D_LOCK_NESTED);
@@ -185,10 +166,9 @@ int dcache_readdir(struct file * filp, void * dirent, filldir_t filldir)
		list_move(q, p);
		spin_unlock(&next->d_lock);
		p = q;
				filp->f_pos++;
		ctx->pos++;
	}
	spin_unlock(&dentry->d_lock);
	}
	return 0;
}

@@ -202,7 +182,7 @@ const struct file_operations simple_dir_operations = {
	.release	= dcache_dir_close,
	.llseek		= dcache_dir_lseek,
	.read		= generic_read_dir,
	.readdir	= dcache_readdir,
	.iterate	= dcache_readdir,
	.fsync		= noop_fsync,
};

+32 −7
Original line number Diff line number Diff line
@@ -1511,12 +1511,6 @@ struct dir_context {
	loff_t pos;
};

static inline bool dir_emit(struct dir_context *ctx,
			    const char *name, int namelen,
			    u64 ino, unsigned type)
{
	return ctx->actor(ctx, name, namelen, ctx->pos, ino, type) == 0;
}
struct block_device_operations;

/* These macros are for out of kernel modules to test that
@@ -2537,7 +2531,7 @@ extern void iterate_supers_type(struct file_system_type *,
extern int dcache_dir_open(struct inode *, struct file *);
extern int dcache_dir_close(struct inode *, struct file *);
extern loff_t dcache_dir_lseek(struct file *, loff_t, int);
extern int dcache_readdir(struct file *, void *, filldir_t);
extern int dcache_readdir(struct file *, struct dir_context *);
extern int simple_setattr(struct dentry *, struct iattr *);
extern int simple_getattr(struct vfsmount *, struct dentry *, struct kstat *);
extern int simple_statfs(struct dentry *, struct kstatfs *);
@@ -2701,4 +2695,35 @@ static inline void inode_has_no_xattr(struct inode *inode)
		inode->i_flags |= S_NOSEC;
}

static inline bool dir_emit(struct dir_context *ctx,
			    const char *name, int namelen,
			    u64 ino, unsigned type)
{
	return ctx->actor(ctx, name, namelen, ctx->pos, ino, type) == 0;
}
static inline bool dir_emit_dot(struct file *file, struct dir_context *ctx)
{
	return ctx->actor(ctx, ".", 1, ctx->pos,
			  file->f_path.dentry->d_inode->i_ino, DT_DIR) == 0;
}
static inline bool dir_emit_dotdot(struct file *file, struct dir_context *ctx)
{
	return ctx->actor(ctx, "..", 2, ctx->pos,
			  parent_ino(file->f_path.dentry), DT_DIR) == 0;
}
static inline bool dir_emit_dots(struct file *file, struct dir_context *ctx)
{
	if (ctx->pos == 0) {
		if (!dir_emit_dot(file, ctx))
			return false;
		ctx->pos = 1;
	}
	if (ctx->pos == 1) {
		if (!dir_emit_dotdot(file, ctx))
			return false;
		ctx->pos = 2;
	}
	return true;
}

#endif /* _LINUX_FS_H */