]> git.neil.brown.name Git - LaFS.git/commitdiff
roll forward clean up
authorNeilBrown <neilb@suse.de>
Sat, 2 Oct 2010 11:56:29 +0000 (21:56 +1000)
committerNeilBrown <neilb@suse.de>
Sun, 10 Oct 2010 23:33:56 +0000 (10:33 +1100)
More validation
improved mem allocation
general clean up

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

diff --git a/roll.c b/roll.c
index ba986cb8b8e600a0e440825054121a39c9048f4e..a4dea4b778fa1c97951dd2ef837b517495ea874b 100644 (file)
--- a/roll.c
+++ b/roll.c
@@ -23,7 +23,18 @@ roll_valid(struct fs *fs, struct cluster_head *ch, unsigned long long addr)
                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;
 }
 
@@ -36,18 +47,14 @@ roll_valid(struct fs *fs, struct cluster_head *ch, unsigned long long addr)
 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;
@@ -136,7 +143,7 @@ roll_locate(struct fs *fs, u64 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) {
@@ -148,6 +155,10 @@ roll_locate(struct fs *fs, u64 start,
                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++;
        }
 
@@ -477,7 +488,6 @@ static int roll_forward(struct fs *fs)
        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;
@@ -490,15 +500,21 @@ static int roll_forward(struct fs *fs)
        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);
@@ -513,42 +529,36 @@ 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) {
-                       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);