diff options
Diffstat (limited to 'fs/bcachefs/journal_sb.c')
-rw-r--r-- | fs/bcachefs/journal_sb.c | 45 |
1 files changed, 41 insertions, 4 deletions
diff --git a/fs/bcachefs/journal_sb.c b/fs/bcachefs/journal_sb.c index 0cb9b93f13e7..dc0ecedb3a8f 100644 --- a/fs/bcachefs/journal_sb.c +++ b/fs/bcachefs/journal_sb.c @@ -30,7 +30,7 @@ static int bch2_sb_journal_validate(struct bch_sb *sb, struct bch_sb_field *f, if (!nr) return 0; - b = kmalloc_array(nr, sizeof(u64), GFP_KERNEL); + b = kvmalloc_array(nr, sizeof(u64), GFP_KERNEL); if (!b) return -BCH_ERR_ENOMEM_sb_journal_validate; @@ -64,7 +64,7 @@ static int bch2_sb_journal_validate(struct bch_sb *sb, struct bch_sb_field *f, ret = 0; err: - kfree(b); + kvfree(b); return ret; } @@ -113,7 +113,7 @@ static int bch2_sb_journal_v2_validate(struct bch_sb *sb, struct bch_sb_field *f if (!nr) return 0; - b = kmalloc_array(nr, sizeof(*b), GFP_KERNEL); + b = kvmalloc_array(nr, sizeof(*b), GFP_KERNEL); if (!b) return -BCH_ERR_ENOMEM_sb_journal_v2_validate; @@ -165,7 +165,7 @@ static int bch2_sb_journal_v2_validate(struct bch_sb *sb, struct bch_sb_field *f ret = 0; err: - kfree(b); + kvfree(b); return ret; } @@ -230,3 +230,40 @@ int bch2_journal_buckets_to_sb(struct bch_fs *c, struct bch_dev *ca, BUG_ON(dst + 1 != nr_compacted); return 0; } + +static inline bool journal_v2_unsorted(struct bch_sb_field_journal_v2 *j) +{ + unsigned nr = bch2_sb_field_journal_v2_nr_entries(j); + for (unsigned i = 0; i + 1 < nr; i++) + if (le64_to_cpu(j->d[i].start) > le64_to_cpu(j->d[i + 1].start)) + return true; + return false; +} + +int bch2_sb_journal_sort(struct bch_fs *c) +{ + BUG_ON(!c->sb.clean); + BUG_ON(test_bit(BCH_FS_rw, &c->flags)); + + guard(mutex)(&c->sb_lock); + bool write_sb = false; + + for_each_online_member(c, ca, BCH_DEV_READ_REF_sb_journal_sort) { + struct bch_sb_field_journal_v2 *j = bch2_sb_field_get(ca->disk_sb.sb, journal_v2); + if (!j) + continue; + + if ((j && journal_v2_unsorted(j)) || + bch2_sb_field_get(ca->disk_sb.sb, journal)) { + struct journal_device *ja = &ca->journal; + + sort(ja->buckets, ja->nr, sizeof(ja->buckets[0]), u64_cmp, NULL); + bch2_journal_buckets_to_sb(c, ca, ja->buckets, ja->nr); + write_sb = true; + } + } + + return write_sb + ? bch2_write_super(c) + : 0; +} |