else {
if (!hlist_unhashed(&ss->hash))
hlist_del(&ss->hash);
+ if (!fs->stable_changed)
+ fs->stable_changed = 1;
spin_unlock(&fs->stable_lock);
putdref(ss->ssblk, MKREF(ss));
putdref(ss->youthblk, MKREF(ssyouth));
if (!hlist_empty(&fs->stable[i])) {
struct segsum *ss;
struct datablock *b, *y;
- struct hlist_node *n;
- /* FIXME this is quadratic */
- retry:
+ struct hlist_node *n, *pos;
+
spin_lock(&fs->stable_lock);
- hlist_for_each_entry(ss, n, &fs->stable[i], hash) {
+ retry:
+ hlist_for_each_entry_safe(ss, pos, n, &fs->stable[i], hash) {
b = ss->ssblk;
y = ss->youthblk;
if (!b && !y)
putdref(y, MKREF(async));
putdref(b, MKREF(ss));
putdref(y, MKREF(ssyouth));
- goto retry;
+ spin_lock(&fs->stable_lock);
+ if (fs->stable_changed)
+ goto retry;
}
spin_unlock(&fs->stable_lock);
}
struct segsum *ss;
struct hlist_node *n, *pos;
spin_lock(&fs->stable_lock);
+ retry:
+ fs->stable_changed = 0;
hlist_for_each_entry_safe(ss, pos, n, head, hash) {
+ if (atomic_read(&ss->delayed) == 0)
+ continue;
atomic_inc(&ss->refcnt);
spin_unlock(&fs->stable_lock);
seg_apply(fs, ss);
ss_put(ss, fs);
spin_lock(&fs->stable_lock);
- // FIXME this still isn't safe - 'n' could
- // disappear while unlocked.
+ if (fs->stable_changed)
+ goto retry;
}
spin_unlock(&fs->stable_lock);
}