[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 <[email protected]>
This commit is contained in:
Al Viro 2013-05-15 20:23:06 -04:00
commit 5f99f4e79a
4 changed files with 65 additions and 60 deletions

View file

@ -135,60 +135,40 @@ 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:
spin_lock(&dentry->d_lock);
if (filp->f_pos == 2)
list_move(q, &dentry->d_subdirs);
if (!dir_emit_dots(file, ctx))
return 0;
spin_lock(&dentry->d_lock);
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);
spin_lock_nested(&next->d_lock, DENTRY_D_LOCK_NESTED);
if (!simple_positive(next)) {
spin_unlock(&next->d_lock);
continue;
}
for (p = q->next; p != &dentry->d_subdirs; p = p->next) {
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);
continue;
}
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)
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;
filp->f_pos++;
}
spin_unlock(&dentry->d_lock);
spin_unlock(&next->d_lock);
spin_unlock(&dentry->d_lock);
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);
/* next is still alive */
list_move(q, p);
spin_unlock(&next->d_lock);
p = q;
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,
};