]> git.neil.brown.name Git - LaFS.git/commitdiff
roll-forward: update youth block for new segments.
authorNeilBrown <neilb@suse.de>
Sun, 19 Sep 2010 04:39:31 +0000 (14:39 +1000)
committerNeilBrown <neilb@suse.de>
Sun, 19 Sep 2010 04:39:31 +0000 (14:39 +1000)
Any new segments found during roll-forward need their youth value set.

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

diff --git a/lafs.h b/lafs.h
index a8e59510fea3253e299d534d5bb84d63d7c97141..5426ee2e77f64ce1516a8339003aa7c2e54dec28 100644 (file)
--- a/lafs.h
+++ b/lafs.h
@@ -716,6 +716,7 @@ void lafs_seg_move(struct fs *fs, u64 oldaddr, u64 newaddr,
                   int ssnum, int phase, int moveref);
 int lafs_segtrack_init(struct segtracker *st);
 void lafs_segtrack_free(struct segtracker *st);
+void lafs_update_youth(struct fs *fs, int dev, u32 seg);
 
 extern int temp_credits;/* debugging */
 void lafs_free_get(struct fs *fs, unsigned int *dev, u32 *seg,
diff --git a/roll.c b/roll.c
index e9a20fa02476d1e866fa74bebf220b410b13684f..400f96604f0bc8686192f3342fa8f3424fc155bc 100644 (file)
--- a/roll.c
+++ b/roll.c
@@ -480,6 +480,9 @@ static int roll_forward(struct fs *fs)
        char *buf;
        int err;
        int blocksize = fs->blocksize;
+       int dev;
+       u32 seg;
+       u32 offset;
 
        fs->phase = 1;
        fs->qphase = 0;
@@ -509,23 +512,37 @@ static int roll_forward(struct fs *fs)
        }
        lafs_cluster_init(fs, 1, 0, 0, 0);
 
+       virttoseg(fs, first, &dev, &seg, &offset);
        max = ((max + blocksize - 1) / blocksize) * blocksize;
        dprintk("Max = %d\n", max);
        buf = kmalloc(max, GFP_KERNEL);
        if (buf)
                while (first != next) {
-                       /* FIXME if this cluster is in a new segment,
-                        * we need to set the youth number for it.
-                        */
+                       int dev2;
+                       u32 seg2;
+
+                       virttoseg(fs, first, &dev2, &seg2, &offset);
                        err = roll_one(fs, &first, p, pg, max);
                        if (err)
                                break;
+
                        if (fs->qphase == fs->phase &&
                            fs->checkpointing) {
                                fs->checkpointing = 0;
                                clear_bit(DelayYouth, &fs->fsstate);
                                lafs_seg_apply_all(fs);
                        }
+
+                       if (dev2 != dev || seg2 != seg) {
+                               /* New segment - need to make sure youth is correct */
+                               dev = dev2;
+                               seg = seg2;
+                               /* if fs->checkpointing, seg_apply_all will do the youth
+                                * update
+                                */
+                               if (fs->checkpointing == 0)
+                                       lafs_update_youth(fs, dev, seg);
+                       }
                }
        else
                err = -ENOMEM;
index 346102bc75cb8e6b5ba35e55fd8a84d480e4e730..eb4b8bfda6186bdd1098a4304a112d9352cabd51 100644 (file)
@@ -87,9 +87,7 @@ struct segsum {
        atomic_t        delayed;
 
        struct datablock *ssblk;
-       /* youthblk is only set when ssnum is 0 and
-        * usage is zero we are cleaning.
-        */
+       /* youthblk is only set when ssnum is 0 */
        struct datablock *youthblk;
 };
 
@@ -141,9 +139,10 @@ retry:
                        spin_unlock(&fs->stable_lock);
                        if (new)
                                ss_put(new, fs);
+                       if (!fs->rolled && fs->qphase != fs->phase)
+                               return ss;
                        if (ss->ssblk &&
-                           !test_bit(B_Valid, &ss->ssblk->b.flags) &&
-                           (fs->rolled || fs->qphase == fs->phase)) {
+                           !test_bit(B_Valid, &ss->ssblk->b.flags) ) {
                                /* need to read this now that roll forward
                                 * has progressed.
                                 */
@@ -153,6 +152,17 @@ retry:
                                        return ERR_PTR(err);
                                }
                        }
+                       if (ss->youthblk &&
+                           !test_bit(B_Valid, &ss->youthblk->b.flags)) {
+                               /* need to read this now that roll forward
+                                * has progressed.
+                                */
+                               err = lafs_read_block(ss->youthblk);
+                               if (err) {
+                                       ss_put(ss, fs);
+                                       return ERR_PTR(err);
+                               }
+                       }
                        return ss;
                }
        if (new) {
@@ -193,6 +203,8 @@ retry:
                goto retry;
        }
        err = lafs_read_block(new->ssblk);
+       if (new->youthblk && err == 0)
+               err = lafs_read_block(new->youthblk);
        if (err) {
                ss_put(new, fs);
                return ERR_PTR(err);
@@ -445,6 +457,9 @@ static void seg_apply(struct fs *fs, struct segsum *ss)
        dprintk("Seg apply %d %d\n", (int)ss->segnum, diff);
        err = lafs_read_block(ss->ssblk);
        BUG_ON(err); // FIXME do something useful here
+       if (ss->youthblk)
+               err = lafs_read_block(ss->youthblk);
+       BUG_ON(err);
        seg_inc(fs, ss, diff, 1);
 
        if (diff > 0 && ss->youthblk)
@@ -1175,12 +1190,6 @@ again:
        *dev = ss->dev;
        *seg = ss->segment;
 
-       /* 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(DelayYouth, &fs->fsstate) &&
            !(ssum &&
              ssum->devnum == ss->dev &&
@@ -1240,6 +1249,18 @@ again:
        /* Note that we return an implicit reference to the ssum */
 }
 
+void lafs_update_youth(struct fs *fs, int dev, u32 seg)
+{
+       struct segsum *ssum = NULL;
+       ssum = segsum_find(fs, seg, dev, 0);
+       set_bit(B_PinPending, &ssum->youthblk->b.flags);
+       lafs_pin_dblock(ssum->youthblk, AccountSpace);
+       spin_lock(&fs->lock);
+       set_youth(fs, ssum);
+       spin_unlock(&fs->lock);
+       ss_put(ssum, fs);
+}
+
 void lafs_seg_forget(struct fs *fs, int dev, u32 seg)
 {
        /* this segment was being filled and is now full.