mirror of
https://github.com/torvalds/linux.git
synced 2024-11-22 20:22:09 +00:00
bcachefs: bch2_alloc_write()
This adds a new helper that much like the one we have for inode updates, that allocates the packed alloc key, packs it and calls bch2_trans_update. Signed-off-by: Kent Overstreet <kent.overstreet@linux.dev>
This commit is contained in:
parent
991ba02112
commit
fb0e480872
@ -38,6 +38,15 @@ static const unsigned BCH_ALLOC_V1_FIELD_BYTES[] = {
|
||||
#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,
|
||||
@ -244,13 +253,26 @@ struct bkey_alloc_unpacked bch2_alloc_unpack(struct bkey_s_c k)
|
||||
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);
|
||||
@ -375,7 +397,6 @@ static int bch2_alloc_write_key(struct btree_trans *trans,
|
||||
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);
|
||||
@ -402,8 +423,7 @@ retry:
|
||||
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);
|
||||
@ -413,7 +433,7 @@ err:
|
||||
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;
|
||||
@ -453,7 +473,6 @@ int bch2_bucket_io_time_reset(struct btree_trans *trans, unsigned dev,
|
||||
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;
|
||||
@ -466,11 +485,6 @@ int bch2_bucket_io_time_reset(struct btree_trans *trans, unsigned dev,
|
||||
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));
|
||||
@ -483,8 +497,7 @@ int bch2_bucket_io_time_reset(struct btree_trans *trans, unsigned dev,
|
||||
|
||||
*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);
|
||||
@ -752,7 +765,6 @@ static int bucket_invalidate_btree(struct btree_trans *trans,
|
||||
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;
|
||||
@ -765,11 +777,6 @@ static int bucket_invalidate_btree(struct btree_trans *trans,
|
||||
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;
|
||||
@ -787,9 +794,8 @@ static int bucket_invalidate_btree(struct btree_trans *trans,
|
||||
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;
|
||||
|
@ -20,15 +20,6 @@ struct bkey_alloc_unpacked {
|
||||
#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
|
||||
|
||||
@ -46,8 +37,8 @@ static inline bool bkey_alloc_unpacked_cmp(struct bkey_alloc_unpacked l,
|
||||
}
|
||||
|
||||
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);
|
||||
|
||||
@ -137,7 +128,7 @@ void bch2_dev_allocator_quiesce(struct bch_fs *, struct bch_dev *);
|
||||
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 *);
|
||||
|
@ -1485,8 +1485,7 @@ need_mark:
|
||||
|
||||
/* 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)
|
||||
{
|
||||
@ -1494,14 +1493,9 @@ bch2_trans_start_alloc_update(struct btree_trans *trans, struct btree_iter *iter
|
||||
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|
|
||||
@ -1509,7 +1503,7 @@ bch2_trans_start_alloc_update(struct btree_trans *trans, struct btree_iter *iter
|
||||
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);
|
||||
@ -1522,22 +1516,20 @@ bch2_trans_start_alloc_update(struct btree_trans *trans, struct btree_iter *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,
|
||||
@ -1545,8 +1537,7 @@ static int bch2_trans_mark_pointer(struct btree_trans *trans,
|
||||
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:
|
||||
@ -1676,7 +1667,6 @@ static int bch2_trans_mark_stripe_bucket(struct btree_trans *trans,
|
||||
{
|
||||
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
|
||||
@ -1687,9 +1677,9 @@ static int bch2_trans_mark_stripe_bucket(struct btree_trans *trans,
|
||||
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,
|
||||
@ -1739,8 +1729,7 @@ static int bch2_trans_mark_stripe_bucket(struct btree_trans *trans,
|
||||
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:
|
||||
@ -1988,7 +1977,6 @@ static int __bch2_trans_mark_metadata_bucket(struct btree_trans *trans,
|
||||
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),
|
||||
@ -2001,9 +1989,9 @@ static int __bch2_trans_mark_metadata_bucket(struct btree_trans *trans,
|
||||
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,
|
||||
@ -2020,8 +2008,7 @@ static int __bch2_trans_mark_metadata_bucket(struct btree_trans *trans,
|
||||
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:
|
||||
|
@ -1238,7 +1238,7 @@ use_clean:
|
||||
*/
|
||||
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;
|
||||
|
Loading…
Reference in New Issue
Block a user