]> git.neil.brown.name Git - LaFS.git/commitdiff
Filter empty block from uninc change before incorporation.
authorNeilBrown <neilb@suse.de>
Tue, 22 Jun 2010 02:32:07 +0000 (12:32 +1000)
committerNeilBrown <neilb@suse.de>
Tue, 22 Jun 2010 20:59:46 +0000 (06:59 +1000)
It is possible (though unusual) for an uninc chain to have
two block with the same fileaddr, one that is empty and being ignored,
and one that is newly split off and needs to be incorporated.
We need to detect this possibility after sorting and discard the
empty block so it doesn't confuse further incorporation.

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

index a306313d6f7d9d6e8e490f73deb1e5b774c99316..8dc192217f80db30de053db5751fa9879b4ae990 100644 (file)
--- a/modify.c
+++ b/modify.c
@@ -1634,6 +1634,32 @@ static void readdress_index(struct inode *ino, u32 addr, int depth,
        }
 }
 
+static void filter_empties(struct block **uninc)
+{
+       /* If any block has phys==0 and there is another block
+        * with same address, incorp_index the phys==0 block
+        */
+       struct block *b = *uninc;
+       while (b && b->chain) {
+               if (b->fileaddr == b->chain->fileaddr) {
+                       struct block *t;
+                       if (b->physaddr == 0) {
+                               t = b;
+                               *uninc = b->chain;
+                       } else if (b->chain->physaddr == 0) {
+                               t = b->chain;
+                               b->chain = t->chain;
+                       } else
+                               LAFS_BUG(1, b);
+                       t->chain = NULL;
+                       incorp_index(t);
+               } else {
+                       uninc = &b->chain;
+                       b = *uninc;
+               }
+       }
+}
+
 /* Incorporate all the addresses in uninc_table into this
  * indexblock.  Each address carried a credit to allow for
  * indexblock splitting etc.
@@ -1744,6 +1770,7 @@ void lafs_incorporate(struct fs *fs, struct indexblock *ib)
                        goto out;
 
                sort_blocks(&uninc);
+               filter_empties(&uninc);
 
                LAFS_BUG(!test_bit(B_Dirty, &ib->b.flags) &&
                       !test_bit(B_Realloc, &ib->b.flags), &ib->b);