}
}
+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)
{
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);
}
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
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
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;
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;