*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
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;
/* ?? 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 */