fs/affs/dir.c: unlock/brelse dir on failure + code clean-up
authorFabian Frederick <fabf@skynet.be>
Mon, 7 Apr 2014 22:39:00 +0000 (15:39 -0700)
committerLinus Torvalds <torvalds@linux-foundation.org>
Mon, 7 Apr 2014 23:36:08 +0000 (16:36 -0700)
Commit 0edf977d2ae3 ("[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: Fabian Frederick <fabf@skynet.be>
Cc: Al Viro <viro@zeniv.linux.org.uk>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
fs/affs/dir.c

index f1eba8c3644e9800397f6d1b7cc3e6ceaf723bbd..cbbda476a8054e5409b843616e1a1b7023e63824 100644 (file)
@@ -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 @@ inside:
                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;
 }