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

[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
...@@ -238,7 +238,7 @@ const struct file_operations spufs_context_fops = { ...@@ -238,7 +238,7 @@ const struct file_operations spufs_context_fops = {
.release = spufs_dir_close, .release = spufs_dir_close,
.llseek = dcache_dir_lseek, .llseek = dcache_dir_lseek,
.read = generic_read_dir, .read = generic_read_dir,
.readdir = dcache_readdir, .iterate = dcache_readdir,
.fsync = noop_fsync, .fsync = noop_fsync,
}; };
EXPORT_SYMBOL_GPL(spufs_context_fops); EXPORT_SYMBOL_GPL(spufs_context_fops);
......
...@@ -41,7 +41,7 @@ const struct file_operations autofs4_root_operations = { ...@@ -41,7 +41,7 @@ const struct file_operations autofs4_root_operations = {
.open = dcache_dir_open, .open = dcache_dir_open,
.release = dcache_dir_close, .release = dcache_dir_close,
.read = generic_read_dir, .read = generic_read_dir,
.readdir = dcache_readdir, .iterate = dcache_readdir,
.llseek = dcache_dir_lseek, .llseek = dcache_dir_lseek,
.unlocked_ioctl = autofs4_root_ioctl, .unlocked_ioctl = autofs4_root_ioctl,
#ifdef CONFIG_COMPAT #ifdef CONFIG_COMPAT
...@@ -53,7 +53,7 @@ const struct file_operations autofs4_dir_operations = { ...@@ -53,7 +53,7 @@ const struct file_operations autofs4_dir_operations = {
.open = autofs4_dir_open, .open = autofs4_dir_open,
.release = dcache_dir_close, .release = dcache_dir_close,
.read = generic_read_dir, .read = generic_read_dir,
.readdir = dcache_readdir, .iterate = dcache_readdir,
.llseek = dcache_dir_lseek, .llseek = dcache_dir_lseek,
}; };
......
...@@ -135,60 +135,40 @@ static inline unsigned char dt_type(struct inode *inode) ...@@ -135,60 +135,40 @@ static inline unsigned char dt_type(struct inode *inode)
* both impossible due to the lock on directory. * 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 *dentry = file->f_path.dentry;
struct dentry *cursor = filp->private_data; struct dentry *cursor = file->private_data;
struct list_head *p, *q = &cursor->d_u.d_child; struct list_head *p, *q = &cursor->d_u.d_child;
ino_t ino;
int i = filp->f_pos;
switch (i) { if (!dir_emit_dots(file, ctx))
case 0: return 0;
ino = dentry->d_inode->i_ino; spin_lock(&dentry->d_lock);
if (filldir(dirent, ".", 1, i, ino, DT_DIR) < 0) if (ctx->pos == 2)
break; list_move(q, &dentry->d_subdirs);
filp->f_pos++;
i++; for (p = q->next; p != &dentry->d_subdirs; p = p->next) {
/* fallthrough */ struct dentry *next = list_entry(p, struct dentry, d_u.d_child);
case 1: spin_lock_nested(&next->d_lock, DENTRY_D_LOCK_NESTED);
ino = parent_ino(dentry); if (!simple_positive(next)) {
if (filldir(dirent, "..", 2, i, ino, DT_DIR) < 0) spin_unlock(&next->d_lock);
break; continue;
filp->f_pos++; }
i++;
/* fallthrough */
default:
spin_lock(&dentry->d_lock);
if (filp->f_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);
spin_lock_nested(&next->d_lock, DENTRY_D_LOCK_NESTED);
if (!simple_positive(next)) {
spin_unlock(&next->d_lock);
continue;
}
spin_unlock(&next->d_lock); spin_unlock(&next->d_lock);
spin_unlock(&dentry->d_lock); spin_unlock(&dentry->d_lock);
if (filldir(dirent, next->d_name.name, if (!dir_emit(ctx, next->d_name.name, next->d_name.len,
next->d_name.len, filp->f_pos, next->d_inode->i_ino, dt_type(next->d_inode)))
next->d_inode->i_ino, return 0;
dt_type(next->d_inode)) < 0) spin_lock(&dentry->d_lock);
return 0; spin_lock_nested(&next->d_lock, DENTRY_D_LOCK_NESTED);
spin_lock(&dentry->d_lock); /* next is still alive */
spin_lock_nested(&next->d_lock, DENTRY_D_LOCK_NESTED); list_move(q, p);
/* next is still alive */ spin_unlock(&next->d_lock);
list_move(q, p); p = q;
spin_unlock(&next->d_lock); ctx->pos++;
p = q;
filp->f_pos++;
}
spin_unlock(&dentry->d_lock);
} }
spin_unlock(&dentry->d_lock);
return 0; return 0;
} }
...@@ -202,7 +182,7 @@ const struct file_operations simple_dir_operations = { ...@@ -202,7 +182,7 @@ const struct file_operations simple_dir_operations = {
.release = dcache_dir_close, .release = dcache_dir_close,
.llseek = dcache_dir_lseek, .llseek = dcache_dir_lseek,
.read = generic_read_dir, .read = generic_read_dir,
.readdir = dcache_readdir, .iterate = dcache_readdir,
.fsync = noop_fsync, .fsync = noop_fsync,
}; };
......
...@@ -1511,12 +1511,6 @@ struct dir_context { ...@@ -1511,12 +1511,6 @@ struct dir_context {
loff_t pos; 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; struct block_device_operations;
/* These macros are for out of kernel modules to test that /* These macros are for out of kernel modules to test that
...@@ -2537,7 +2531,7 @@ extern void iterate_supers_type(struct file_system_type *, ...@@ -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_open(struct inode *, struct file *);
extern int dcache_dir_close(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 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_setattr(struct dentry *, struct iattr *);
extern int simple_getattr(struct vfsmount *, struct dentry *, struct kstat *); extern int simple_getattr(struct vfsmount *, struct dentry *, struct kstat *);
extern int simple_statfs(struct dentry *, struct kstatfs *); extern int simple_statfs(struct dentry *, struct kstatfs *);
...@@ -2701,4 +2695,35 @@ static inline void inode_has_no_xattr(struct inode *inode) ...@@ -2701,4 +2695,35 @@ static inline void inode_has_no_xattr(struct inode *inode)
inode->i_flags |= S_NOSEC; 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 */ #endif /* _LINUX_FS_H */
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