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

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
...@@ -52,8 +52,10 @@ affs_readdir(struct file *file, struct dir_context *ctx) ...@@ -52,8 +52,10 @@ affs_readdir(struct file *file, struct dir_context *ctx)
int hash_pos; int hash_pos;
int chain_pos; int chain_pos;
u32 ino; 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) { if (ctx->pos < 2) {
file->private_data = (void *)0; file->private_data = (void *)0;
...@@ -72,7 +74,7 @@ affs_readdir(struct file *file, struct dir_context *ctx) ...@@ -72,7 +74,7 @@ affs_readdir(struct file *file, struct dir_context *ctx)
} }
dir_bh = affs_bread(sb, inode->i_ino); dir_bh = affs_bread(sb, inode->i_ino);
if (!dir_bh) if (!dir_bh)
goto readdir_out; goto out_unlock_dir;
/* If the directory hasn't changed since the last call to readdir(), /* If the directory hasn't changed since the last call to readdir(),
* we can jump directly to where we left off. * we can jump directly to where we left off.
...@@ -88,7 +90,8 @@ affs_readdir(struct file *file, struct dir_context *ctx) ...@@ -88,7 +90,8 @@ affs_readdir(struct file *file, struct dir_context *ctx)
fh_bh = affs_bread(sb, ino); fh_bh = affs_bread(sb, ino);
if (!fh_bh) { if (!fh_bh) {
affs_error(sb, "readdir","Cannot read block %d", i); 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); ino = be32_to_cpu(AFFS_TAIL(sb, fh_bh)->hash_chain);
affs_brelse(fh_bh); affs_brelse(fh_bh);
...@@ -107,29 +110,34 @@ affs_readdir(struct file *file, struct dir_context *ctx) ...@@ -107,29 +110,34 @@ affs_readdir(struct file *file, struct dir_context *ctx)
do { do {
fh_bh = affs_bread(sb, ino); fh_bh = affs_bread(sb, ino);
if (!fh_bh) { if (!fh_bh) {
affs_error(sb, "readdir","Cannot read block %d", ino); affs_error(sb, "readdir",
"Cannot read block %d", ino);
break; break;
} }
namelen = min(AFFS_TAIL(sb, fh_bh)->name[0], (u8)30); namelen = min(AFFS_TAIL(sb, fh_bh)->name[0], (u8)30);
name = AFFS_TAIL(sb, fh_bh)->name + 1; 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); namelen, name, ino, hash_pos, (u32)ctx->pos);
if (!dir_emit(ctx, name, namelen, ino, DT_UNKNOWN)) if (!dir_emit(ctx, name, namelen, ino, DT_UNKNOWN))
goto readdir_done; goto done;
ctx->pos++; ctx->pos++;
ino = be32_to_cpu(AFFS_TAIL(sb, fh_bh)->hash_chain); ino = be32_to_cpu(AFFS_TAIL(sb, fh_bh)->hash_chain);
affs_brelse(fh_bh); affs_brelse(fh_bh);
fh_bh = NULL; fh_bh = NULL;
} while (ino); } while (ino);
} }
readdir_done: done:
file->f_version = inode->i_version; file->f_version = inode->i_version;
file->private_data = (void *)(long)ino; file->private_data = (void *)(long)ino;
affs_brelse(fh_bh);
readdir_out: out_brelse_dir:
affs_brelse(dir_bh); affs_brelse(dir_bh);
affs_brelse(fh_bh);
out_unlock_dir:
affs_unlock_dir(inode); affs_unlock_dir(inode);
return 0; return error;
} }
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