]> git.neil.brown.name Git - LaFS.git/commitdiff
Allow cleaner_parse to request multiple inodes at once.
authorNeilBrown <neilb@suse.de>
Sat, 14 Aug 2010 10:52:11 +0000 (20:52 +1000)
committerNeilBrown <neilb@suse.de>
Sat, 14 Aug 2010 10:52:11 +0000 (20:52 +1000)
Currently cleaner_parse stops when it hits an inode that it cannot
load immediately.  This reduced the opportunities for parallelism.

Instream allow up to 16 -EAGAINs from inode lookups.
This requires that we mark headers for inodes which failed, and
always start again from the beginning of the cluster head.
We already reduce the bcnt to 0, so for inodes that can be
found, we won't lookup the blocks twice.

Signed-off-by: NeilBrown <neilb@suse.de>
clean.c

diff --git a/clean.c b/clean.c
index f2a8a7fc21977b270739954221890f3ad2c1d528..f5f48bdbe35674fd2de39b592bd7b4722a261e1e 100644 (file)
--- a/clean.c
+++ b/clean.c
@@ -166,8 +166,6 @@ static void cleaner_load(struct fs *fs, struct toclean *tc)
                        goto bad_header;
                }
        }
-       tc->gh = tc->ch->groups;
-       tc->desc = tc->gh->u.desc;
        if (lafs_calc_cluster_csum(tc->ch) != tc->ch->checksum) {
                //printk("Cluster header checksum is wrong!!\n");
                goto bad_header;
@@ -186,9 +184,15 @@ static void cleaner_parse(struct fs *fs, struct toclean *tc)
        int bcnt;
        u32 inum, fsnum;
        struct inode *ino = NULL;
-
        int again = 0;
-       while (tc->ch && again < 16) {
+
+       /* Always start at the beginning - we invalidate entries
+        * that we have finished with
+        */
+       tc->gh = tc->ch->groups;
+       tc->desc = tc->gh->u.desc;
+
+       while (again < 16) {
                /* Load the index block for each described data or index block.
                 * For data blocks, get the address and possibly load the
                 * data block too.
@@ -200,6 +204,9 @@ static void cleaner_parse(struct fs *fs, struct toclean *tc)
                    >= le16_to_cpu(tc->ch->Hlength)) {
                        /* Finished with that cluster, try another. */
                        u64 next;
+                       if (again)
+                               /* Need to come back later */
+                               break;
                        next = le64_to_cpu(tc->ch->next_addr);
                        if (next > tc->haddr &&
                            in_seg(fs, tc->dev, tc->seg, next)) {
@@ -251,6 +258,11 @@ static void cleaner_parse(struct fs *fs, struct toclean *tc)
                inum = le32_to_cpu(tc->gh->inum);
                fsnum = le32_to_cpu(tc->gh->fsnum);
 
+               if (inum == 0xFFFFFFFF &&
+                   fsnum == 0xFFFFFFFF) {
+                       tc->desc++;
+                       continue;
+               }
                dprintk("Cleaner looking at %d/%d %d+%d (%d)\n",
                        (int)fsnum, (int)inum, (int)bnum, (int)bcnt,
                        (int)le16_to_cpu(tc->desc->block_bytes));
@@ -265,22 +277,7 @@ static void cleaner_parse(struct fs *fs, struct toclean *tc)
                                iput(ino);
                        ino = lafs_iget_fs(fs, fsnum, inum, ASYNC);
                }
-               if (IS_ERR(ino)) {
-                       /* FIXME check that this is -EAGAIN
-                        * FIXME should have lafs_iget_fs return the
-                        * ino anyway, but lafs_find_block_async,
-                        * doesn't try until ino is uptodate.
-                        */
-                       int err = PTR_ERR(ino);
-                       ino = NULL;
-                       dprintk("iget gives error %d\n", err);
-                       if (err != -EAGAIN) {
-                               /* inode not found */
-                               tc->desc++;
-                               continue;
-                       }
-                       break;
-               } else {
+               if (!IS_ERR(ino)) {
                        struct datablock *b;
                        dprintk("got the inode\n");
                        /* Minor optimisation for files that have shrunk */
@@ -329,6 +326,22 @@ static void cleaner_parse(struct fs *fs, struct toclean *tc)
                                }
                        }
                        putdref(b, MKREF(cleaning));
+               } else  {
+                       int err = PTR_ERR(ino);
+                       ino = NULL;
+                       dprintk("iget gives error %d\n", err);
+                       if (err == -EAGAIN) {
+                               again++;
+                               tc->desc++;
+                               continue;
+                       }
+                       /* inode not found, make sure we never
+                        * look for it again
+                        */
+                       tc->gh->inum = 0xFFFFFFFF;
+                       tc->gh->fsnum = 0xFFFFFFFF;
+                       tc->desc++;
+                       continue;
                }
        skip:
                /* We modify the descriptor in-place to track where