]> git.sesse.net Git - bcachefs-tools-debian/blobdiff - libbcachefs/buckets.h
Update bcachefs sources to 171da96d76 bcachefs: Drop some anonymous structs, unions
[bcachefs-tools-debian] / libbcachefs / buckets.h
index 85e86ded86af4b70fe6f58b7770a0359f415b6c1..d677b0225c52bf1d9388790e8680805a124f572e 100644 (file)
@@ -75,6 +75,15 @@ static inline struct bpos PTR_BUCKET_POS(const struct bch_fs *c,
        return POS(ptr->dev, PTR_BUCKET_NR(ca, ptr));
 }
 
+static inline struct bpos PTR_BUCKET_POS_OFFSET(const struct bch_fs *c,
+                                               const struct bch_extent_ptr *ptr,
+                                               u32 *bucket_offset)
+{
+       struct bch_dev *ca = bch_dev_bkey_exists(c, ptr->dev);
+
+       return POS(ptr->dev, sector_to_bucket_and_offset(ca, ptr->offset, bucket_offset));
+}
+
 static inline struct bucket *PTR_GC_BUCKET(struct bch_dev *ca,
                                           const struct bch_extent_ptr *ptr)
 {
@@ -90,6 +99,16 @@ static inline enum bch_data_type ptr_data_type(const struct bkey *k,
        return ptr->cached ? BCH_DATA_cached : BCH_DATA_user;
 }
 
+static inline s64 ptr_disk_sectors(s64 sectors, struct extent_ptr_decoded p)
+{
+       EBUG_ON(sectors < 0);
+
+       return crc_is_compressed(p.crc)
+               ? DIV_ROUND_UP_ULL(sectors * p.crc.compressed_size,
+                                  p.crc.uncompressed_size)
+               : sectors;
+}
+
 static inline int gen_cmp(u8 a, u8 b)
 {
        return (s8) (a - b);
@@ -120,16 +139,27 @@ static inline u8 ptr_stale(struct bch_dev *ca,
 
 /* Device usage: */
 
-struct bch_dev_usage bch2_dev_usage_read(struct bch_dev *);
+void bch2_dev_usage_read_fast(struct bch_dev *, struct bch_dev_usage *);
+static inline struct bch_dev_usage bch2_dev_usage_read(struct bch_dev *ca)
+{
+       struct bch_dev_usage ret;
 
-static inline u64 __dev_buckets_available(struct bch_dev *ca,
-                                         struct bch_dev_usage stats,
-                                         enum alloc_reserve reserve)
+       bch2_dev_usage_read_fast(ca, &ret);
+       return ret;
+}
+
+void bch2_dev_usage_init(struct bch_dev *);
+
+static inline u64 bch2_dev_buckets_reserved(struct bch_dev *ca, enum alloc_reserve reserve)
 {
-       s64 total = ca->mi.nbuckets - ca->mi.first_bucket;
        s64 reserved = 0;
 
        switch (reserve) {
+       case RESERVE_NR:
+               unreachable();
+       case RESERVE_stripe:
+               reserved += ca->mi.nbuckets >> 6;
+               fallthrough;
        case RESERVE_none:
                reserved += ca->mi.nbuckets >> 6;
                fallthrough;
@@ -141,20 +171,32 @@ static inline u64 __dev_buckets_available(struct bch_dev *ca,
                fallthrough;
        case RESERVE_btree_movinggc:
                break;
-       default:
-               BUG();
        }
 
-       if (WARN_ONCE(stats.buckets_unavailable > total,
-                     "buckets_unavailable overflow (%llu > %llu)\n",
-                     stats.buckets_unavailable, total))
-               return 0;
+       return reserved;
+}
 
+static inline u64 dev_buckets_free(struct bch_dev *ca,
+                                  struct bch_dev_usage usage,
+                                  enum alloc_reserve reserve)
+{
        return max_t(s64, 0,
-                    total -
-                    stats.buckets_unavailable -
+                    usage.d[BCH_DATA_free].buckets -
                     ca->nr_open_buckets -
-                    reserved);
+                    bch2_dev_buckets_reserved(ca, reserve));
+}
+
+static inline u64 __dev_buckets_available(struct bch_dev *ca,
+                                         struct bch_dev_usage usage,
+                                         enum alloc_reserve reserve)
+{
+       return max_t(s64, 0,
+                      usage.d[BCH_DATA_free].buckets
+                    + usage.d[BCH_DATA_cached].buckets
+                    + usage.d[BCH_DATA_need_gc_gens].buckets
+                    + usage.d[BCH_DATA_need_discard].buckets
+                    - ca->nr_open_buckets
+                    - bch2_dev_buckets_reserved(ca, reserve));
 }
 
 static inline u64 dev_buckets_available(struct bch_dev *ca,
@@ -198,48 +240,26 @@ int bch2_mark_metadata_bucket(struct bch_fs *, struct bch_dev *,
                              size_t, enum bch_data_type, unsigned,
                              struct gc_pos, unsigned);
 
-int bch2_mark_alloc(struct btree_trans *, struct bkey_s_c, struct bkey_s_c, unsigned);
-int bch2_mark_extent(struct btree_trans *, struct bkey_s_c, struct bkey_s_c, unsigned);
-int bch2_mark_stripe(struct btree_trans *, struct bkey_s_c, struct bkey_s_c, unsigned);
-int bch2_mark_inode(struct btree_trans *, struct bkey_s_c, struct bkey_s_c, unsigned);
-int bch2_mark_reservation(struct btree_trans *, struct bkey_s_c, struct bkey_s_c, unsigned);
-int bch2_mark_reflink_p(struct btree_trans *, struct bkey_s_c, struct bkey_s_c, unsigned);
-
-int bch2_trans_mark_extent(struct btree_trans *, struct bkey_s_c, struct bkey_i *, unsigned);
-int bch2_trans_mark_stripe(struct btree_trans *, struct bkey_s_c, struct bkey_i *, unsigned);
-int bch2_trans_mark_inode(struct btree_trans *, struct bkey_s_c, struct bkey_i *, unsigned);
-int bch2_trans_mark_reservation(struct btree_trans *, struct bkey_s_c, struct bkey_i *, unsigned);
-int bch2_trans_mark_reflink_p(struct btree_trans *, struct bkey_s_c, struct bkey_i *, unsigned);
-
-int bch2_mark_key(struct btree_trans *, struct bkey_s_c, struct bkey_s_c, unsigned);
-
-int bch2_trans_mark_key(struct btree_trans *, struct bkey_s_c,
-                       struct bkey_i *, unsigned);
-
-static inline int bch2_trans_mark_old(struct btree_trans *trans,
-                                     struct bkey_s_c old, unsigned flags)
-{
-       struct bkey_i deleted;
-
-       bkey_init(&deleted.k);
-       deleted.k.p = old.k->p;
-
-       return bch2_trans_mark_key(trans, old, &deleted,
-                                  BTREE_TRIGGER_OVERWRITE|flags);
-}
-
-static inline int bch2_trans_mark_new(struct btree_trans *trans,
-                                     struct bkey_i *new, unsigned flags)
-{
-       struct bkey_i deleted;
-
-       bkey_init(&deleted.k);
-       deleted.k.p = new->k.p;
-
-       return bch2_trans_mark_key(trans, bkey_i_to_s_c(&deleted), new,
-                                  BTREE_TRIGGER_INSERT|flags);
-}
-
+int bch2_mark_alloc(struct btree_trans *, enum btree_id, unsigned,
+                   struct bkey_s_c, struct bkey_s_c, unsigned);
+int bch2_mark_extent(struct btree_trans *, enum btree_id, unsigned,
+                    struct bkey_s_c, struct bkey_s_c, unsigned);
+int bch2_mark_stripe(struct btree_trans *, enum btree_id, unsigned,
+                    struct bkey_s_c, struct bkey_s_c, unsigned);
+int bch2_mark_inode(struct btree_trans *, enum btree_id, unsigned,
+                   struct bkey_s_c, struct bkey_s_c, unsigned);
+int bch2_mark_reservation(struct btree_trans *, enum btree_id, unsigned,
+                         struct bkey_s_c, struct bkey_s_c, unsigned);
+int bch2_mark_reflink_p(struct btree_trans *, enum btree_id, unsigned,
+                       struct bkey_s_c, struct bkey_s_c, unsigned);
+
+int bch2_trans_mark_extent(struct btree_trans *, enum btree_id, unsigned, struct bkey_s_c, struct bkey_i *, unsigned);
+int bch2_trans_mark_stripe(struct btree_trans *, enum btree_id, unsigned, struct bkey_s_c, struct bkey_i *, unsigned);
+int bch2_trans_mark_inode(struct btree_trans *, enum btree_id, unsigned, struct bkey_s_c, struct bkey_i *, unsigned);
+int bch2_trans_mark_reservation(struct btree_trans *, enum btree_id, unsigned, struct bkey_s_c, struct bkey_i *, unsigned);
+int bch2_trans_mark_reflink_p(struct btree_trans *, enum btree_id, unsigned, struct bkey_s_c, struct bkey_i *, unsigned);
+
+void bch2_trans_fs_usage_revert(struct btree_trans *, struct replicas_delta_list *);
 int bch2_trans_fs_usage_apply(struct btree_trans *, struct replicas_delta_list *);
 
 int bch2_trans_mark_metadata_bucket(struct btree_trans *, struct bch_dev *,
@@ -251,15 +271,39 @@ 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)
+{
+#ifdef __KERNEL__
+       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;
+#else
+       return __bch2_disk_reservation_add(c, res, sectors, flags);
+#endif
+}
 
 static inline struct disk_reservation
 bch2_disk_reservation_init(struct bch_fs *c, unsigned nr_replicas)