From: NeilBrown Date: Sun, 19 Sep 2010 04:05:41 +0000 (+1000) Subject: Generalise segunused to seg_pop X-Git-Url: http://git.neil.brown.name/?a=commitdiff_plain;h=b9ffc03ff998e4626a092f46d0052a162e949ad3;p=LaFS.git Generalise segunused to seg_pop And use seg_pop more broadly, and re-arrange some code. Signed-off-by: NeilBrown --- diff --git a/segments.c b/segments.c index 12a6453..8b3acb3 100644 --- a/segments.c +++ b/segments.c @@ -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;