]> git.neil.brown.name Git - LaFS.git/commitdiff
Generalise segunused to seg_pop
authorNeilBrown <neilb@suse.de>
Sun, 19 Sep 2010 04:05:41 +0000 (14:05 +1000)
committerNeilBrown <neilb@suse.de>
Sun, 19 Sep 2010 04:05:41 +0000 (14:05 +1000)
And use seg_pop more broadly,
and re-arrange some code.

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

index 12a6453f6e6007f45ccaf46cb5d41355ddd024b5..8b3acb385f32fd940c9652f0897553d05c6dc11b 100644 (file)
@@ -1055,6 +1055,61 @@ static void segdelete_all(struct segtracker *st, struct fs *fs)
        }
 }
 
+static u16 seg_pop(struct segtracker *st, struct slist *which)
+{
+       struct segstat *ss;
+       u16 rv = which->first;
+       if (rv == 0xFFFF)
+               return rv;
+       ss = segfollow(st, rv);
+       which->first = ss->next;
+       which->cnt--;
+       if (ss->next == 0xFFFF)
+               which->last = 0xFFFF;
+       return rv;
+}
+
+static struct segstat *seg_add_new(struct segtracker *st, struct slist *which, int atend,
+                                  int dev, u32 seg, int score, int usage,
+                                  u16 *where[SEG_NUM_HEIGHTS])
+{
+       int ssn;
+       struct segstat *ss;
+
+       ssn = seg_pop(st, &st->unused);
+       ss = segfollow(st, ssn);
+       if (!ss)
+               return ss;
+
+       if (which) {
+               if (atend) {
+                       int l = which->last;
+                       ss->next = 0xFFFF;
+                       if (l == 0xFFFF) {
+                               which->first = ssn;
+                               which->last = ssn;
+                       } else {
+                               which->last = ssn;
+                               BUG_ON(segfollow(st, l)->next != 0xFFFF);
+                               segfollow(st, l)->next = ssn;
+                       }
+               } else {
+                       ss->next = which->first;
+                       which->first = ssn;
+                       if (which->last == 0xFFFF)
+                               which->last = ssn;
+               }
+               which->cnt++;
+       }
+       ss->dev = dev;
+       ss->segment = seg;
+       ss->score = score;
+       ss->usage = usage;
+       seginsert(st, ssn, where);
+       lafs_check_seg_cnt(st);
+       return ss;
+}
+
 void lafs_free_get(struct fs *fs, unsigned int *dev, u32 *seg,
                   int nonlogged)
 {
@@ -1108,13 +1163,10 @@ again:
                lafs_pin_dblock(ssum->youthblk, AccountSpace);
                goto again;
        }
-       /* 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
-        * over-ride that
-        */
-       if (fs->youth_next < 0x8000)
-               fs->youth_next = 0x8000;
+       seg_pop(fs->segtrack, &fs->segtrack->free);
+
+       ss->score = SCORE_ACTIVE;
+       /* still in table, but unlinked */
 
        if (ssum && test_bit(DelayYouth, &fs->fsstate)) {
                ss_put(ssum, fs);
@@ -1122,7 +1174,16 @@ again:
        }
 
        if (ssum) {
-               u16 y = fs->youth_next;
+               u16 y;
+               /* 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
+                * over-ride that
+                */
+
+               if (fs->youth_next < 0x8000)
+                       fs->youth_next = 0x8000;
+               y = fs->youth_next;
                if (fs->scan.do_decay &&
                    (fs->scan.free_dev < ss->dev
                     || (fs->scan.free_dev == ss->dev 
@@ -1135,17 +1196,11 @@ again:
                youthp[(*seg) & ((1 << (fs->blocksize_bits
                                        - 1)) - 1)]
                        = cpu_to_le16(y);
+               fs->youth_next++;
                unmap_dblock(ssum->youthblk, youthp);
                lafs_dirty_dblock(ssum->youthblk);
        }
-       fs->youth_next++;
 
-       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);
 
        /* now need to reserve/dirty/reference the youth and
@@ -1198,60 +1253,6 @@ void lafs_seg_forget(struct fs *fs, int dev, u32 seg)
        ss_put(ss, fs);
 }
 
-static u16 segunused(struct segtracker *st)
-{
-       struct segstat *ss;
-       u16 rv = st->unused.first;
-       if (rv == 0xFFFF)
-               return rv;
-       ss = segfollow(st, rv);
-       st->unused.first = ss->next;
-       st->unused.cnt--;
-       ss->next = 0xFFFF;
-       return rv;
-}
-
-static struct segstat *seg_add_new(struct segtracker *st, struct slist *which, int atend,
-                                  int dev, u32 seg, int score, int usage,
-                                  u16 *where[SEG_NUM_HEIGHTS])
-{
-       int ssn;
-       struct segstat *ss;
-
-       ssn = segunused(st);
-       ss = segfollow(st, ssn);
-       if (!ss)
-               return ss;
-
-       if (which) {
-               if (atend) {
-                       int l = which->last;
-                       ss->next = 0xFFFF;
-                       if (l == 0xFFFF) {
-                               which->first = ssn;
-                               which->last = ssn;
-                       } else {
-                               which->last = ssn;
-                               BUG_ON(segfollow(st, l)->next != 0xFFFF);
-                               segfollow(st, l)->next = ssn;
-                       }
-               } else {
-                       ss->next = which->first;
-                       which->first = ssn;
-                       if (which->last == 0xFFFF)
-                               which->last = ssn;
-               }
-               which->cnt++;
-       }
-       ss->dev = dev;
-       ss->segment = seg;
-       ss->score = score;
-       ss->usage = usage;
-       seginsert(st, ssn, where);
-       lafs_check_seg_cnt(st);
-       return ss;
-}
-
 int lafs_clean_count(struct fs *fs, int *any_clean)
 {
        int rv;
@@ -1527,11 +1528,7 @@ retry:
 
        lafs_check_seg_cnt(fs->segtrack);
 
-       ss = segfollow(st, st->cleanable.first);
-       st->cleanable.first = ss->next;
-       st->cleanable.cnt--;
-       if (ss->next == 0xffff)
-               st->cleanable.last = 0xffff;
+       ss = segfollow(st, seg_pop(st, &st->cleanable));
 
        if (lafs_check_seg_cnt(fs->segtrack)) {
                int sj;