Commit 9fd4d059 authored by Al Viro's avatar Al Viro

[readdir] convert omfs

Signed-off-by: default avatarAl Viro <viro@zeniv.linux.org.uk>
parent 1616abe8
...@@ -327,26 +327,23 @@ int omfs_is_bad(struct omfs_sb_info *sbi, struct omfs_header *header, ...@@ -327,26 +327,23 @@ int omfs_is_bad(struct omfs_sb_info *sbi, struct omfs_header *header,
return is_bad; return is_bad;
} }
static int omfs_fill_chain(struct file *filp, void *dirent, filldir_t filldir, static bool omfs_fill_chain(struct inode *dir, struct dir_context *ctx,
u64 fsblock, int hindex) u64 fsblock, int hindex)
{ {
struct inode *dir = file_inode(filp);
struct buffer_head *bh;
struct omfs_inode *oi;
u64 self;
int res = 0;
unsigned char d_type;
/* follow chain in this bucket */ /* follow chain in this bucket */
while (fsblock != ~0) { while (fsblock != ~0) {
bh = omfs_bread(dir->i_sb, fsblock); struct buffer_head *bh = omfs_bread(dir->i_sb, fsblock);
struct omfs_inode *oi;
u64 self;
unsigned char d_type;
if (!bh) if (!bh)
goto out; return true;
oi = (struct omfs_inode *) bh->b_data; oi = (struct omfs_inode *) bh->b_data;
if (omfs_is_bad(OMFS_SB(dir->i_sb), &oi->i_head, fsblock)) { if (omfs_is_bad(OMFS_SB(dir->i_sb), &oi->i_head, fsblock)) {
brelse(bh); brelse(bh);
goto out; return true;
} }
self = fsblock; self = fsblock;
...@@ -361,15 +358,16 @@ static int omfs_fill_chain(struct file *filp, void *dirent, filldir_t filldir, ...@@ -361,15 +358,16 @@ static int omfs_fill_chain(struct file *filp, void *dirent, filldir_t filldir,
d_type = (oi->i_type == OMFS_DIR) ? DT_DIR : DT_REG; d_type = (oi->i_type == OMFS_DIR) ? DT_DIR : DT_REG;
res = filldir(dirent, oi->i_name, strnlen(oi->i_name, if (!dir_emit(ctx, oi->i_name,
OMFS_NAMELEN), filp->f_pos, self, d_type); strnlen(oi->i_name, OMFS_NAMELEN),
self, d_type)) {
brelse(bh);
return false;
}
brelse(bh); brelse(bh);
if (res < 0) ctx->pos++;
break;
filp->f_pos++;
} }
out: return true;
return res;
} }
static int omfs_rename(struct inode *old_dir, struct dentry *old_dentry, static int omfs_rename(struct inode *old_dir, struct dentry *old_dentry,
...@@ -403,60 +401,44 @@ static int omfs_rename(struct inode *old_dir, struct dentry *old_dentry, ...@@ -403,60 +401,44 @@ static int omfs_rename(struct inode *old_dir, struct dentry *old_dentry,
return err; return err;
} }
static int omfs_readdir(struct file *filp, void *dirent, filldir_t filldir) static int omfs_readdir(struct file *file, struct dir_context *ctx)
{ {
struct inode *dir = file_inode(filp); struct inode *dir = file_inode(file);
struct buffer_head *bh; struct buffer_head *bh;
loff_t offset, res; __be64 *p;
unsigned int hchain, hindex; unsigned int hchain, hindex;
int nbuckets; int nbuckets;
u64 fsblock;
int ret = -EINVAL; if (ctx->pos >> 32)
return -EINVAL;
if (filp->f_pos >> 32)
goto success; if (ctx->pos < 1 << 20) {
if (!dir_emit_dots(file, ctx))
switch ((unsigned long) filp->f_pos) { return 0;
case 0: ctx->pos = 1 << 20;
if (filldir(dirent, ".", 1, 0, dir->i_ino, DT_DIR) < 0)
goto success;
filp->f_pos++;
/* fall through */
case 1:
if (filldir(dirent, "..", 2, 1,
parent_ino(filp->f_dentry), DT_DIR) < 0)
goto success;
filp->f_pos = 1 << 20;
/* fall through */
} }
nbuckets = (dir->i_size - OMFS_DIR_START) / 8; nbuckets = (dir->i_size - OMFS_DIR_START) / 8;
/* high 12 bits store bucket + 1 and low 20 bits store hash index */ /* high 12 bits store bucket + 1 and low 20 bits store hash index */
hchain = (filp->f_pos >> 20) - 1; hchain = (ctx->pos >> 20) - 1;
hindex = filp->f_pos & 0xfffff; hindex = ctx->pos & 0xfffff;
bh = omfs_bread(dir->i_sb, dir->i_ino); bh = omfs_bread(dir->i_sb, dir->i_ino);
if (!bh) if (!bh)
goto out; return -EINVAL;
offset = OMFS_DIR_START + hchain * 8; p = (__be64 *)(bh->b_data + OMFS_DIR_START) + hchain;
for (; hchain < nbuckets; hchain++, offset += 8) { for (; hchain < nbuckets; hchain++) {
fsblock = be64_to_cpu(*((__be64 *) &bh->b_data[offset])); __u64 fsblock = be64_to_cpu(*p++);
if (!omfs_fill_chain(dir, ctx, fsblock, hindex))
res = omfs_fill_chain(filp, dirent, filldir, fsblock, hindex);
hindex = 0;
if (res < 0)
break; break;
hindex = 0;
filp->f_pos = (hchain+2) << 20; ctx->pos = (hchain+2) << 20;
} }
brelse(bh); brelse(bh);
success: return 0;
ret = 0;
out:
return ret;
} }
const struct inode_operations omfs_dir_inops = { const struct inode_operations omfs_dir_inops = {
...@@ -470,6 +452,6 @@ const struct inode_operations omfs_dir_inops = { ...@@ -470,6 +452,6 @@ const struct inode_operations omfs_dir_inops = {
const struct file_operations omfs_dir_operations = { const struct file_operations omfs_dir_operations = {
.read = generic_read_dir, .read = generic_read_dir,
.readdir = omfs_readdir, .iterate = omfs_readdir,
.llseek = generic_file_llseek, .llseek = generic_file_llseek,
}; };
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