Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit d40c4d46 authored by Fabian Frederick's avatar Fabian Frederick Committed by Linus Torvalds
Browse files

fs/affs/dir.c: unlock/brelse dir on failure + code clean-up



Commit 0edf977d ("[readdir] convert affs") returns directly -EIO
without unlocking dir inode and releasing dir bh when second affs_bread
sequence fails.  This patch restores initial behaviour.  It also fixes
pr_debug and affs_error to fit in 80 columns + removes reference to
filldir (replaced by dir_emit in the commit above).

Signed-off-by: default avatarFabian Frederick <fabf@skynet.be>
Cc: Al Viro <viro@zeniv.linux.org.uk>
Signed-off-by: default avatarAndrew Morton <akpm@linux-foundation.org>
Signed-off-by: default avatarLinus Torvalds <torvalds@linux-foundation.org>
parent adbd319e
Loading
Loading
Loading
Loading
+18 −10
Original line number Diff line number Diff line
@@ -52,8 +52,10 @@ affs_readdir(struct file *file, struct dir_context *ctx)
	int			 hash_pos;
	int			 chain_pos;
	u32			 ino;
	int			 error = 0;

	pr_debug("AFFS: readdir(ino=%lu,f_pos=%lx)\n",inode->i_ino,(unsigned long)ctx->pos);
	pr_debug("AFFS: readdir(ino=%lu,f_pos=%lx)\n",
		 inode->i_ino, (unsigned long)ctx->pos);

	if (ctx->pos < 2) {
		file->private_data = (void *)0;
@@ -72,7 +74,7 @@ affs_readdir(struct file *file, struct dir_context *ctx)
	}
	dir_bh = affs_bread(sb, inode->i_ino);
	if (!dir_bh)
		goto readdir_out;
		goto out_unlock_dir;

	/* If the directory hasn't changed since the last call to readdir(),
	 * we can jump directly to where we left off.
@@ -88,7 +90,8 @@ affs_readdir(struct file *file, struct dir_context *ctx)
		fh_bh = affs_bread(sb, ino);
		if (!fh_bh) {
			affs_error(sb, "readdir","Cannot read block %d", i);
			return -EIO;
			error = -EIO;
			goto out_brelse_dir;
		}
		ino = be32_to_cpu(AFFS_TAIL(sb, fh_bh)->hash_chain);
		affs_brelse(fh_bh);
@@ -107,29 +110,34 @@ affs_readdir(struct file *file, struct dir_context *ctx)
		do {
			fh_bh = affs_bread(sb, ino);
			if (!fh_bh) {
				affs_error(sb, "readdir","Cannot read block %d", ino);
				affs_error(sb, "readdir",
					   "Cannot read block %d", ino);
				break;
			}

			namelen = min(AFFS_TAIL(sb, fh_bh)->name[0], (u8)30);
			name = AFFS_TAIL(sb, fh_bh)->name + 1;
			pr_debug("AFFS: readdir(): filldir(\"%.*s\", ino=%u), hash=%d, f_pos=%x\n",
			pr_debug("AFFS: readdir(): dir_emit(\"%.*s\", "
				 "ino=%u), hash=%d, f_pos=%x\n",
				 namelen, name, ino, hash_pos, (u32)ctx->pos);

			if (!dir_emit(ctx, name, namelen, ino, DT_UNKNOWN))
				goto readdir_done;
				goto done;
			ctx->pos++;
			ino = be32_to_cpu(AFFS_TAIL(sb, fh_bh)->hash_chain);
			affs_brelse(fh_bh);
			fh_bh = NULL;
		} while (ino);
	}
readdir_done:
done:
	file->f_version = inode->i_version;
	file->private_data = (void *)(long)ino;
	affs_brelse(fh_bh);

readdir_out:
out_brelse_dir:
	affs_brelse(dir_bh);
	affs_brelse(fh_bh);

out_unlock_dir:
	affs_unlock_dir(inode);
	return 0;
	return error;
}