#undef x
};
+struct bkey_alloc_buf {
+ struct bkey_i k;
+ struct bch_alloc_v3 v;
+
+#define x(_name, _bits) + _bits / 8
+ u8 _pad[0 + BCH_ALLOC_FIELDS_V2()];
+#undef x
+} __attribute__((packed, aligned(8)));
+
/* Persistent alloc info: */
static inline u64 alloc_field_v1_get(const struct bch_alloc *a,
return ret;
}
-void bch2_alloc_pack(struct bch_fs *c,
- struct bkey_alloc_buf *dst,
- const struct bkey_alloc_unpacked src)
+static void bch2_alloc_pack(struct bch_fs *c,
+ struct bkey_alloc_buf *dst,
+ const struct bkey_alloc_unpacked src)
{
bch2_alloc_pack_v3(dst, src);
}
+int bch2_alloc_write(struct btree_trans *trans, struct btree_iter *iter,
+ struct bkey_alloc_unpacked *u, unsigned trigger_flags)
+{
+ struct bkey_alloc_buf *a;
+
+ a = bch2_trans_kmalloc(trans, sizeof(struct bkey_alloc_buf));
+ if (IS_ERR(a))
+ return PTR_ERR(a);
+
+ bch2_alloc_pack(trans->c, a, *u);
+ return bch2_trans_update(trans, iter, &a->k, trigger_flags);
+}
+
static unsigned bch_alloc_v1_val_u64s(const struct bch_alloc *a)
{
unsigned i, bytes = offsetof(struct bch_alloc, data);
struct bucket *g;
struct bucket_mark m;
struct bkey_alloc_unpacked old_u, new_u;
- struct bkey_alloc_buf a;
int ret;
retry:
bch2_trans_begin(trans);
if (!bkey_alloc_unpacked_cmp(old_u, new_u))
return 0;
- bch2_alloc_pack(c, &a, new_u);
- ret = bch2_trans_update(trans, iter, &a.k,
+ ret = bch2_alloc_write(trans, iter, &new_u,
BTREE_TRIGGER_NORUN) ?:
bch2_trans_commit(trans, NULL, NULL,
BTREE_INSERT_NOFAIL|flags);
return ret;
}
-int bch2_alloc_write(struct bch_fs *c, unsigned flags)
+int bch2_alloc_write_all(struct bch_fs *c, unsigned flags)
{
struct btree_trans trans;
struct btree_iter iter;
struct bch_dev *ca = bch_dev_bkey_exists(c, dev);
struct btree_iter iter;
struct bucket *g;
- struct bkey_alloc_buf *a;
struct bkey_alloc_unpacked u;
u64 *time, now;
int ret = 0;
if (ret)
goto out;
- a = bch2_trans_kmalloc(trans, sizeof(struct bkey_alloc_buf));
- ret = PTR_ERR_OR_ZERO(a);
- if (ret)
- goto out;
-
percpu_down_read(&c->mark_lock);
g = bucket(ca, bucket_nr);
u = alloc_mem_to_key(&iter, g, READ_ONCE(g->mark));
*time = now;
- bch2_alloc_pack(c, a, u);
- ret = bch2_trans_update(trans, &iter, &a->k, 0) ?:
+ ret = bch2_alloc_write(trans, &iter, &u, 0) ?:
bch2_trans_commit(trans, NULL, NULL, 0);
out:
bch2_trans_iter_exit(trans, &iter);
struct bch_dev *ca, u64 b)
{
struct bch_fs *c = trans->c;
- struct bkey_alloc_buf *a;
struct bkey_alloc_unpacked u;
struct bucket *g;
struct bucket_mark m;
BTREE_ITER_CACHED_NOFILL|
BTREE_ITER_INTENT);
- a = bch2_trans_kmalloc(trans, sizeof(*a));
- ret = PTR_ERR_OR_ZERO(a);
- if (ret)
- goto err;
-
ret = bch2_btree_iter_traverse(&iter);
if (ret)
goto err;
u.read_time = atomic64_read(&c->io_clock[READ].now);
u.write_time = atomic64_read(&c->io_clock[WRITE].now);
- bch2_alloc_pack(c, a, u);
- ret = bch2_trans_update(trans, &iter, &a->k,
- BTREE_TRIGGER_BUCKET_INVALIDATE);
+ ret = bch2_alloc_write(trans, &iter, &u,
+ BTREE_TRIGGER_BUCKET_INVALIDATE);
err:
bch2_trans_iter_exit(trans, &iter);
return ret;
#undef x
};
-struct bkey_alloc_buf {
- struct bkey_i k;
- struct bch_alloc_v3 v;
-
-#define x(_name, _bits) + _bits / 8
- u8 _pad[0 + BCH_ALLOC_FIELDS_V2()];
-#undef x
-} __attribute__((packed, aligned(8)));
-
/* How out of date a pointer gen is allowed to be: */
#define BUCKET_GC_GEN_MAX 96U
}
struct bkey_alloc_unpacked bch2_alloc_unpack(struct bkey_s_c);
-void bch2_alloc_pack(struct bch_fs *, struct bkey_alloc_buf *,
- const struct bkey_alloc_unpacked);
+int bch2_alloc_write(struct btree_trans *, struct btree_iter *,
+ struct bkey_alloc_unpacked *, unsigned);
int bch2_bucket_io_time_reset(struct btree_trans *, unsigned, size_t, int);
void bch2_dev_allocator_stop(struct bch_dev *);
int bch2_dev_allocator_start(struct bch_dev *);
-int bch2_alloc_write(struct bch_fs *, unsigned);
+int bch2_alloc_write_all(struct bch_fs *, unsigned);
void bch2_fs_allocator_background_init(struct bch_fs *);
void bch2_open_buckets_to_text(struct printbuf *, struct bch_fs *);
/* trans_mark: */
-static struct bkey_alloc_buf *
-bch2_trans_start_alloc_update(struct btree_trans *trans, struct btree_iter *iter,
+static int bch2_trans_start_alloc_update(struct btree_trans *trans, struct btree_iter *iter,
const struct bch_extent_ptr *ptr,
struct bkey_alloc_unpacked *u)
{
struct bch_dev *ca = bch_dev_bkey_exists(c, ptr->dev);
struct bpos pos = POS(ptr->dev, PTR_BUCKET_NR(ca, ptr));
struct bucket *g;
- struct bkey_alloc_buf *a;
struct bkey_i *update;
int ret;
- a = bch2_trans_kmalloc(trans, sizeof(struct bkey_alloc_buf));
- if (IS_ERR(a))
- return a;
-
bch2_trans_iter_init(trans, iter, BTREE_ID_alloc, pos,
BTREE_ITER_CACHED|
BTREE_ITER_CACHED_NOFILL|
ret = bch2_btree_iter_traverse(iter);
if (ret) {
bch2_trans_iter_exit(trans, iter);
- return ERR_PTR(ret);
+ return ret;
}
update = __bch2_btree_trans_peek_updates(iter);
percpu_up_read(&c->mark_lock);
}
- return a;
+ return 0;
}
static int bch2_trans_mark_pointer(struct btree_trans *trans,
struct bkey_s_c k, struct extent_ptr_decoded p,
s64 sectors, enum bch_data_type data_type)
{
- struct bch_fs *c = trans->c;
struct btree_iter iter;
struct bkey_alloc_unpacked u;
- struct bkey_alloc_buf *a;
int ret;
- a = bch2_trans_start_alloc_update(trans, &iter, &p.ptr, &u);
- if (IS_ERR(a))
- return PTR_ERR(a);
+ ret = bch2_trans_start_alloc_update(trans, &iter, &p.ptr, &u);
+ if (ret)
+ return ret;
ret = __mark_pointer(trans, k, &p.ptr, sectors, data_type,
u.gen, &u.data_type,
if (ret)
goto out;
- bch2_alloc_pack(c, a, u);
- ret = bch2_trans_update(trans, &iter, &a->k, 0);
+ ret = bch2_alloc_write(trans, &iter, &u, 0);
if (ret)
goto out;
out:
{
struct bch_fs *c = trans->c;
const struct bch_extent_ptr *ptr = &s.v->ptrs[idx];
- struct bkey_alloc_buf *a;
struct btree_iter iter;
struct bkey_alloc_unpacked u;
enum bch_data_type data_type = idx >= s.v->nr_blocks - s.v->nr_redundant
if (deleting)
sectors = -sectors;
- a = bch2_trans_start_alloc_update(trans, &iter, ptr, &u);
- if (IS_ERR(a))
- return PTR_ERR(a);
+ ret = bch2_trans_start_alloc_update(trans, &iter, ptr, &u);
+ if (ret)
+ return ret;
ret = check_bucket_ref(c, s.s_c, ptr, sectors, data_type,
u.gen, u.data_type,
if (data_type)
u.data_type = !deleting ? data_type : 0;
- bch2_alloc_pack(c, a, u);
- ret = bch2_trans_update(trans, &iter, &a->k, 0);
+ ret = bch2_alloc_write(trans, &iter, &u, 0);
if (ret)
goto err;
err:
struct bch_fs *c = trans->c;
struct btree_iter iter;
struct bkey_alloc_unpacked u;
- struct bkey_alloc_buf *a;
struct bch_extent_ptr ptr = {
.dev = ca->dev_idx,
.offset = bucket_to_sector(ca, b),
if (b >= ca->mi.nbuckets)
return 0;
- a = bch2_trans_start_alloc_update(trans, &iter, &ptr, &u);
- if (IS_ERR(a))
- return PTR_ERR(a);
+ ret = bch2_trans_start_alloc_update(trans, &iter, &ptr, &u);
+ if (ret)
+ return ret;
if (u.data_type && u.data_type != type) {
bch2_fsck_err(c, FSCK_CAN_IGNORE|FSCK_NEED_FSCK,
u.data_type = type;
u.dirty_sectors = sectors;
- bch2_alloc_pack(c, a, u);
- ret = bch2_trans_update(trans, &iter, &a->k, 0);
+ ret = bch2_alloc_write(trans, &iter, &u, 0);
if (ret)
goto out;
out:
*/
bch_verbose(c, "writing allocation info");
err = "error writing out alloc info";
- ret = bch2_alloc_write(c, BTREE_INSERT_LAZY_RW);
+ ret = bch2_alloc_write_all(c, BTREE_INSERT_LAZY_RW);
if (ret) {
bch_err(c, "error writing alloc info");
goto err;