return 0;
if (le64_to_cpu(ch->this_addr) != addr)
return 0;
- /* FIXME sanity check some values?? */
+ switch (le16_to_cpu(ch->verify_type)) {
+ case VerifyNull:
+ case VerifyNext:
+ case VerifyNext2:
+ break;
+ default:
+ return 0;
+ }
+ if (ch->pad0 != 0)
+ return 0;
+ if (le16_to_cpu(ch->Clength) > fs->max_segment)
+ return 0;
return 1;
}
static int
roll_locate(struct fs *fs, u64 start,
u64 *next, u64 *lastp, u64 *seqp,
- int *maxp)
+ int *maxp, struct page *p)
{
- struct page *p = alloc_page(GFP_KERNEL);
-
struct cluster_head *ch;
u64 this, prev, prev2, last;
u64 seq = 0;
int max = 0;
int prevtype, prev2type;
- if (!p)
- return -ENOMEM;
ch = (struct cluster_head *)page_address(p);
this = start; prev = start;
if (le16_to_cpu(ch->Hlength) > max)
max = le16_to_cpu(ch->Hlength);
- if (prev2type == VerifyNext2 && start != this) {
+ if (prev2type == VerifyNext2) {
start = prev; last = prev2;
}
if (prevtype == VerifyNext) {
prev2 = prev; prev2type = prevtype;
prev = this ; prevtype = le16_to_cpu(ch->verify_type);
this = le64_to_cpu(ch->next_addr);
+ if (prevtype == VerifyNull) {
+ start = this;
+ last = prev;
+ }
seq++;
}
u64 first, next = 0, last = 0, seq = 0;
int max = 0;
struct page *p, *pg;
- char *buf;
int err;
int blocksize = fs->blocksize;
int dev;
clear_bit(DelayYouth, &fs->fsstate);
first = fs->checkpointcluster;
- err = roll_locate(fs, first, &next, &last, &seq, &max);
- if (err)
- return err;
- if (max > PAGE_SIZE)
- return -EFBIG;
-
p = alloc_page(GFP_KERNEL);
if (!p)
return -ENOMEM;
+
+ err = roll_locate(fs, first, &next, &last, &seq, &max, p);
+
+ max = ((max + blocksize - 1) / blocksize) * blocksize;
+
+ if (!err && max > PAGE_SIZE)
+ err = -EFBIG;
+ if (err) {
+ put_page(p);
+ return err;
+ }
+
pg = alloc_page(GFP_KERNEL);
if (!pg) {
put_page(p);
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) {
- 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);
- }
+ while (first != next) {
+ int dev2;
+ u32 seg2;
- 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);
- }
+ 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);
}
- else
- err = -ENOMEM;
+
+ 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);
+ }
+ }
put_page(p);
put_page(pg);
- kfree(buf);
lafs_add_active(fs, next);