diff options
Diffstat (limited to 'fs')
-rw-r--r-- | fs/bcachefs/buckets.c | 2 | ||||
-rw-r--r-- | fs/bcachefs/buckets.h | 30 |
2 files changed, 26 insertions, 6 deletions
diff --git a/fs/bcachefs/buckets.c b/fs/bcachefs/buckets.c index b37cdf7279de..6389ec7ba18b 100644 --- a/fs/bcachefs/buckets.c +++ b/fs/bcachefs/buckets.c @@ -2107,7 +2107,7 @@ int bch2_trans_mark_dev_sb(struct bch_fs *c, struct bch_dev *ca) #define SECTORS_CACHE 1024 -int bch2_disk_reservation_add(struct bch_fs *c, struct disk_reservation *res, +int __bch2_disk_reservation_add(struct bch_fs *c, struct disk_reservation *res, u64 sectors, int flags) { struct bch_fs_pcpu *pcpu; diff --git a/fs/bcachefs/buckets.h b/fs/bcachefs/buckets.h index 04a2a9310cdd..61be96a7b03d 100644 --- a/fs/bcachefs/buckets.h +++ b/fs/bcachefs/buckets.h @@ -261,15 +261,35 @@ int bch2_trans_mark_dev_sb(struct bch_fs *, struct bch_dev *); static inline void bch2_disk_reservation_put(struct bch_fs *c, struct disk_reservation *res) { - this_cpu_sub(*c->online_reserved, res->sectors); - res->sectors = 0; + if (res->sectors) { + this_cpu_sub(*c->online_reserved, res->sectors); + res->sectors = 0; + } } #define BCH_DISK_RESERVATION_NOFAIL (1 << 0) -int bch2_disk_reservation_add(struct bch_fs *, - struct disk_reservation *, - u64, int); +int __bch2_disk_reservation_add(struct bch_fs *, + struct disk_reservation *, + u64, int); + +static inline int bch2_disk_reservation_add(struct bch_fs *c, struct disk_reservation *res, + u64 sectors, int flags) +{ + u64 old, new; + + do { + old = this_cpu_read(c->pcpu->sectors_available); + if (sectors > old) + return __bch2_disk_reservation_add(c, res, sectors, flags); + + new = old - sectors; + } while (this_cpu_cmpxchg(c->pcpu->sectors_available, old, new) != old); + + this_cpu_add(*c->online_reserved, sectors); + res->sectors += sectors; + return 0; +} static inline struct disk_reservation bch2_disk_reservation_init(struct bch_fs *c, unsigned nr_replicas) |