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

[readdir] convert omfs



Signed-off-by: default avatarAl Viro <viro@zeniv.linux.org.uk>
parent 1616abe8
Loading
Loading
Loading
Loading
+38 −56
Original line number Diff line number Diff line
@@ -327,26 +327,23 @@ int omfs_is_bad(struct omfs_sb_info *sbi, struct omfs_header *header,
	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)
{
	struct inode *dir = file_inode(filp);
	struct buffer_head *bh;
	/* follow chain in this bucket */
	while (fsblock != ~0) {
		struct buffer_head *bh = omfs_bread(dir->i_sb, fsblock);
		struct omfs_inode *oi;
		u64 self;
	int res = 0;
		unsigned char d_type;

	/* follow chain in this bucket */
	while (fsblock != ~0) {
		bh = omfs_bread(dir->i_sb, fsblock);
		if (!bh)
			goto out;
			return true;

		oi = (struct omfs_inode *) bh->b_data;
		if (omfs_is_bad(OMFS_SB(dir->i_sb), &oi->i_head, fsblock)) {
			brelse(bh);
			goto out;
			return true;
		}

		self = fsblock;
@@ -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;

		res = filldir(dirent, oi->i_name, strnlen(oi->i_name,
			OMFS_NAMELEN), filp->f_pos, self, d_type);
		if (!dir_emit(ctx, oi->i_name,
			      strnlen(oi->i_name, OMFS_NAMELEN),
			      self, d_type)) {
			brelse(bh);
		if (res < 0)
			break;
		filp->f_pos++;
			return false;
		}
out:
	return res;
		brelse(bh);
		ctx->pos++;
	}
	return true;
}

static int omfs_rename(struct inode *old_dir, struct dentry *old_dentry,
@@ -403,60 +401,44 @@ out:
	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;
	loff_t offset, res;
	__be64 *p;
	unsigned int hchain, hindex;
	int nbuckets;
	u64 fsblock;
	int ret = -EINVAL;

	if (filp->f_pos >> 32)
		goto success;

	switch ((unsigned long) filp->f_pos) {
	case 0:
		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 */

	if (ctx->pos >> 32)
		return -EINVAL;

	if (ctx->pos < 1 << 20) {
		if (!dir_emit_dots(file, ctx))
			return 0;
		ctx->pos = 1 << 20;
	}

	nbuckets = (dir->i_size - OMFS_DIR_START) / 8;

	/* high 12 bits store bucket + 1 and low 20 bits store hash index */
	hchain = (filp->f_pos >> 20) - 1;
	hindex = filp->f_pos & 0xfffff;
	hchain = (ctx->pos >> 20) - 1;
	hindex = ctx->pos & 0xfffff;

	bh = omfs_bread(dir->i_sb, dir->i_ino);
	if (!bh)
		goto out;

	offset = OMFS_DIR_START + hchain * 8;
		return -EINVAL;

	for (; hchain < nbuckets; hchain++, offset += 8) {
		fsblock = be64_to_cpu(*((__be64 *) &bh->b_data[offset]));
	p = (__be64 *)(bh->b_data + OMFS_DIR_START) + hchain;

		res = omfs_fill_chain(filp, dirent, filldir, fsblock, hindex);
		hindex = 0;
		if (res < 0)
	for (; hchain < nbuckets; hchain++) {
		__u64 fsblock = be64_to_cpu(*p++);
		if (!omfs_fill_chain(dir, ctx, fsblock, hindex))
			break;

		filp->f_pos = (hchain+2) << 20;
		hindex = 0;
		ctx->pos = (hchain+2) << 20;
	}
	brelse(bh);
success:
	ret = 0;
out:
	return ret;
	return 0;
}

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 = {
	.read = generic_read_dir,
	.readdir = omfs_readdir,
	.iterate = omfs_readdir,
	.llseek = generic_file_llseek,
};