From: NeilBrown Date: Sun, 11 Jul 2010 09:13:47 +0000 (+1000) Subject: Fix (Again) handling of new segment for final cluster X-Git-Url: http://git.neil.brown.name/?a=commitdiff_plain;h=9a50ab6940efadc936498b768dae35455065ca70;p=LaFS.git Fix (Again) handling of new segment for final cluster 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 --- diff --git a/segments.c b/segments.c index d9b7a8b..984ab10 100644 --- a/segments.c +++ b/segments.c @@ -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 */