diff options
author | Kent Overstreet <kent.overstreet@gmail.com> | 2018-08-04 17:01:22 -0400 |
---|---|---|
committer | Kent Overstreet <kent.overstreet@gmail.com> | 2018-08-11 19:28:09 -0400 |
commit | 353b8ddc5204dd3ccc61853f8d181b8c67f1c32c (patch) | |
tree | a6cee09a0cc7beb4d2b22b3ee8d7e2dca849c219 | |
parent | 512b560fc7732449abaa4748eb2670ac7bb8e8ab (diff) |
sequential id allocatordev2
-rw-r--r-- | fs/bcachefs/journal.c | 52 |
1 files changed, 52 insertions, 0 deletions
diff --git a/fs/bcachefs/journal.c b/fs/bcachefs/journal.c index 634123ebdf13..cb2eb16a8d4f 100644 --- a/fs/bcachefs/journal.c +++ b/fs/bcachefs/journal.c @@ -1110,3 +1110,55 @@ ssize_t bch2_journal_print_pins(struct journal *j, char *buf) return ret; } + + +struct seq_id { + u64 head, tail; +#define SEQ_ID_NR 1024 + unsigned long bits[BITS_TO_LONGS(SEQ_ID_NR)]; +}; + +static inline bool id_free_is_clear(u64 id) +{ + return (id >> ilog2(SEQ_ID_NR)) & 1; +} + +void seq_id_free(struct seq_id *s, u64 id) +{ + u64 v; + + (id_free_is_clear(id) + ? test_and_clear_bit + : test_and_set_bit)(id & (SEQ_ID_NR - 1), s->bits); + + smp_mb(); + /* must see s->tail _after_ clearing our id: */ + v = READ_ONCE(s->tail); + if (v != id) + return; + + do { + id = v; + + if (id == s->head || + id_free_is_clear(id) != + test_bit(id & (SEQ_ID_NR - 1), s->bits)) + return; + } while ((v = cmpxchg(&s->tail, id, id + 1)) != id); + + /* issue wakeup */ +} + +s64 seq_id_alloc(struct seq_id *s) +{ + u64 id, v = READ_ONCE(s->head); + + do { + id = v; + + if (id > s->tail + SEQ_ID_NR) + return -1; + } while ((v = cmpxchg(&s->head, id, id + 1)) != id); + + return id; +} |