[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: Al Viro <viro@zeniv.linux.org.uk>
This commit is contained in:
parent
80886298c0
commit
5f99f4e79a
|
@ -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 = {
|
||||||
.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 = {
|
||||||
.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,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
78
fs/libfs.c
78
fs/libfs.c
|
@ -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++;
|
|
||||||
/* fallthrough */
|
|
||||||
case 1:
|
|
||||||
ino = parent_ino(dentry);
|
|
||||||
if (filldir(dirent, "..", 2, i, ino, DT_DIR) < 0)
|
|
||||||
break;
|
|
||||||
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) {
|
for (p = q->next; p != &dentry->d_subdirs; p = p->next) {
|
||||||
struct dentry *next;
|
struct dentry *next = list_entry(p, struct dentry, d_u.d_child);
|
||||||
next = list_entry(p, struct dentry, d_u.d_child);
|
spin_lock_nested(&next->d_lock, DENTRY_D_LOCK_NESTED);
|
||||||
spin_lock_nested(&next->d_lock, DENTRY_D_LOCK_NESTED);
|
if (!simple_positive(next)) {
|
||||||
if (!simple_positive(next)) {
|
spin_unlock(&next->d_lock);
|
||||||
spin_unlock(&next->d_lock);
|
continue;
|
||||||
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 = {
|
||||||
.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 {
|
||||||
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 *,
|
||||||
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)
|
||||||
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 */
|
||||||
|
|
Loading…
Reference in New Issue
Block a user