Skip to content

Commit

Permalink
[readdir] convert ubifs
Browse files Browse the repository at this point in the history
Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
  • Loading branch information
Al Viro committed Jun 29, 2013
1 parent 5add2ee commit 01122e0
Showing 1 changed file with 16 additions and 41 deletions.
57 changes: 16 additions & 41 deletions fs/ubifs/dir.c
Original file line number Diff line number Diff line change
Expand Up @@ -346,19 +346,18 @@ static unsigned int vfs_dent_type(uint8_t type)
* This means that UBIFS cannot support NFS which requires full
* 'seekdir()'/'telldir()' support.
*/
static int ubifs_readdir(struct file *file, void *dirent, filldir_t filldir)
static int ubifs_readdir(struct file *file, struct dir_context *ctx)
{
int err, over = 0;
loff_t pos = file->f_pos;
int err;
struct qstr nm;
union ubifs_key key;
struct ubifs_dent_node *dent;
struct inode *dir = file_inode(file);
struct ubifs_info *c = dir->i_sb->s_fs_info;

dbg_gen("dir ino %lu, f_pos %#llx", dir->i_ino, pos);
dbg_gen("dir ino %lu, f_pos %#llx", dir->i_ino, ctx->pos);

if (pos > UBIFS_S_KEY_HASH_MASK || pos == 2)
if (ctx->pos > UBIFS_S_KEY_HASH_MASK || ctx->pos == 2)
/*
* The directory was seek'ed to a senseless position or there
* are no more entries.
Expand All @@ -384,19 +383,9 @@ static int ubifs_readdir(struct file *file, void *dirent, filldir_t filldir)
file->f_version = 1;

/* File positions 0 and 1 correspond to "." and ".." */
if (pos == 0) {
ubifs_assert(!file->private_data);
over = filldir(dirent, ".", 1, 0, dir->i_ino, DT_DIR);
if (over)
return 0;
file->f_pos = pos = 1;
}

if (pos == 1) {
if (ctx->pos < 2) {
ubifs_assert(!file->private_data);
over = filldir(dirent, "..", 2, 1,
parent_ino(file->f_path.dentry), DT_DIR);
if (over)
if (!dir_emit_dots(file, ctx))
return 0;

/* Find the first entry in TNC and save it */
Expand All @@ -408,24 +397,24 @@ static int ubifs_readdir(struct file *file, void *dirent, filldir_t filldir)
goto out;
}

file->f_pos = pos = key_hash_flash(c, &dent->key);
ctx->pos = key_hash_flash(c, &dent->key);
file->private_data = dent;
}

dent = file->private_data;
if (!dent) {
/*
* The directory was seek'ed to and is now readdir'ed.
* Find the entry corresponding to @pos or the closest one.
* Find the entry corresponding to @ctx->pos or the closest one.
*/
dent_key_init_hash(c, &key, dir->i_ino, pos);
dent_key_init_hash(c, &key, dir->i_ino, ctx->pos);
nm.name = NULL;
dent = ubifs_tnc_next_ent(c, &key, &nm);
if (IS_ERR(dent)) {
err = PTR_ERR(dent);
goto out;
}
file->f_pos = pos = key_hash_flash(c, &dent->key);
ctx->pos = key_hash_flash(c, &dent->key);
file->private_data = dent;
}

Expand All @@ -437,10 +426,9 @@ static int ubifs_readdir(struct file *file, void *dirent, filldir_t filldir)
ubifs_inode(dir)->creat_sqnum);

nm.len = le16_to_cpu(dent->nlen);
over = filldir(dirent, dent->name, nm.len, pos,
if (!dir_emit(ctx, dent->name, nm.len,
le64_to_cpu(dent->inum),
vfs_dent_type(dent->type));
if (over)
vfs_dent_type(dent->type)))
return 0;

/* Switch to the next entry */
Expand All @@ -453,17 +441,9 @@ static int ubifs_readdir(struct file *file, void *dirent, filldir_t filldir)
}

kfree(file->private_data);
file->f_pos = pos = key_hash_flash(c, &dent->key);
ctx->pos = key_hash_flash(c, &dent->key);
file->private_data = dent;
cond_resched();

if (file->f_version == 0)
/*
* The file was seek'ed meanwhile, lets return and start
* reading direntries from the new position on the next
* invocation.
*/
return 0;
}

out:
Expand All @@ -475,15 +455,10 @@ static int ubifs_readdir(struct file *file, void *dirent, filldir_t filldir)
kfree(file->private_data);
file->private_data = NULL;
/* 2 is a special value indicating that there are no more direntries */
file->f_pos = 2;
ctx->pos = 2;
return 0;
}

static loff_t ubifs_dir_llseek(struct file *file, loff_t offset, int whence)
{
return generic_file_llseek(file, offset, whence);
}

/* Free saved readdir() state when the directory is closed */
static int ubifs_dir_release(struct inode *dir, struct file *file)
{
Expand Down Expand Up @@ -1201,10 +1176,10 @@ const struct inode_operations ubifs_dir_inode_operations = {
};

const struct file_operations ubifs_dir_operations = {
.llseek = ubifs_dir_llseek,
.llseek = generic_file_llseek,
.release = ubifs_dir_release,
.read = generic_read_dir,
.readdir = ubifs_readdir,
.iterate = ubifs_readdir,
.fsync = ubifs_fsync,
.unlocked_ioctl = ubifs_ioctl,
#ifdef CONFIG_COMPAT
Expand Down

0 comments on commit 01122e0

Please sign in to comment.