]> git.neil.brown.name Git - LaFS.git/commitdiff
Fix (Again) handling of new segment for final cluster
authorNeilBrown <neilb@suse.de>
Sun, 11 Jul 2010 09:13:47 +0000 (19:13 +1000)
committerNeilBrown <neilb@suse.de>
Sun, 25 Jul 2010 05:34:26 +0000 (15:34 +1000)
There were other things that were being missed when
allocating the final cluster.  So change code to take the
same path and make exceptions only where exceptions are clearly
needed.

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

index d9b7a8b06c1b39dfc6d927ffffa771938cb339f0..984ab10568c9a1867b0f69f0b5f91d9d0b4980f0 100644 (file)
@@ -1086,28 +1086,17 @@ again:
        *dev = ss->dev;
        *seg = ss->segment;
 
-       if (test_bit(FinalCheckpoint, &fs->fsstate)) {
-               /* skip youth update, roll forward will do it. */
-               /* FIXME should more generally delay the update if we
-                * are in any checkpoint.
-                */
-
-               /* FIXME avoid this code duplication?? see below */
-               fs->segtrack->free.first = ss->next;
-               if (fs->segtrack->free.first == 0xFFFF)
-                       fs->segtrack->free.last = 0xFFFF;
-               fs->segtrack->free.cnt--;
-               ss->score = SCORE_ACTIVE;
-               /* still in table, but unlinked */
-               spin_unlock(&fs->lock);
-               putdref(db, MKREF(youth));
-               return;
-       }
-
-       if (db &&
-           db->b.inode == fs->devs[*dev].segsum &&
-           db->b.fileaddr == ((*seg) >> (fs->prime_sb->s_blocksize_bits
-                                         - 1))) {
+       /* On the final checkpoint we skip the youth update as
+        * rollforward will do it for us, and it is too late
+        * the write the new youth block anyway.
+        * FIXME there should be a more general way to delay
+        * updates to the Youth block.
+        */
+       if (test_bit(FinalCheckpoint, &fs->fsstate) ||
+           (db &&
+            db->b.inode == fs->devs[*dev].segsum &&
+            db->b.fileaddr == ((*seg) >> (fs->prime_sb->s_blocksize_bits
+                                          - 1)))) {
                /* HACK youth_next should always be at least 0x8000 so that
                 * cleanable score differentiates well for new segments.
                 * old code would sometimes set youth_next very low, so
@@ -1118,11 +1107,18 @@ again:
                if (fs->youth_next < 0x8000)
                        fs->youth_next = 0x8000;
 
-               youthp = map_dblock(db);
-               youthp[(*seg) & ((1 << (fs->prime_sb->s_blocksize_bits
-                                       - 1)) - 1)]
-                       = fs->youth_next;
-               unmap_dblock(db, youthp);
+               if (db && test_bit(FinalCheckpoint, &fs->fsstate)) {
+                       putdref(db, MKREF(youth));
+                       db = NULL;
+               }
+
+               if (db) {
+                       youthp = map_dblock(db);
+                       youthp[(*seg) & ((1 << (fs->prime_sb->s_blocksize_bits
+                                               - 1)) - 1)]
+                               = fs->youth_next;
+                       unmap_dblock(db, youthp);
+               }
                fs->youth_next++;
 
                fs->segtrack->free.first = ss->next;
@@ -1144,15 +1140,17 @@ again:
                                /* ?? what do I need to release etc */
                                /* Maybe this cannot fail because we own references
                                 * to the two blocks !! */
-                               LAFS_BUG(1, &db->b);
+                               LAFS_BUG(1, db ? &db->b : NULL);
                        lafs_checkpoint_lock(fs);
                        (void)lafs_pin_dblock(ssum->ssblk, AccountSpace);
                        if (ssnum == 0)
                                (void)lafs_pin_dblock(ssum->youthblk, AccountSpace);
                        lafs_checkpoint_unlock(fs);
                }
-               lafs_dirty_dblock(db);
-               putdref(db, MKREF(youth));
+               if (db) {
+                       lafs_dirty_dblock(db);
+                       putdref(db, MKREF(youth));
+               }
                dprintk("NEXT segment found %d/%d youth %d\n",
                        *dev, *seg, fs->youth_next - 1);
                /* Note that we return an implicit reference to the ssum */