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,
char *buf;
int err;
int blocksize = fs->blocksize;
+ int dev;
+ u32 seg;
+ u32 offset;
fs->phase = 1;
fs->qphase = 0;
}
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;
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;
};
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.
*/
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) {
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);
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)
*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 &&
/* 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.