Commit 085ab693 authored by Kent Overstreet's avatar Kent Overstreet Committed by Kent Overstreet

bcachefs: Rework of cut_front & cut_back

This changes bch2_cut_front and bch2_cut_back so that they're able to
shorten the size of the value, and it also changes the extent update
path to update the accounting in the btree node when this happens.

When the size of the value is shortened, they zero out the space that's
no longer used, so it's interpreted as noops (as implemented in the last
patch).
Signed-off-by: default avatarKent Overstreet <kent.overstreet@gmail.com>
Signed-off-by: default avatarKent Overstreet <kent.overstreet@linux.dev>
parent ad44bdc3
...@@ -350,7 +350,7 @@ struct btree_nr_keys bch2_extent_sort_fix_overlapping(struct bch_fs *c, ...@@ -350,7 +350,7 @@ struct btree_nr_keys bch2_extent_sort_fix_overlapping(struct bch_fs *c,
if (bkey_cmp(l.k->p, r.k->p) >= 0) { if (bkey_cmp(l.k->p, r.k->p) >= 0) {
sort_key_next(iter, b, _r); sort_key_next(iter, b, _r);
} else { } else {
__bch2_cut_front(l.k->p, r); bch2_cut_front_s(l.k->p, r);
extent_save(b, rk, r.k); extent_save(b, rk, r.k);
} }
...@@ -362,9 +362,9 @@ struct btree_nr_keys bch2_extent_sort_fix_overlapping(struct bch_fs *c, ...@@ -362,9 +362,9 @@ struct btree_nr_keys bch2_extent_sort_fix_overlapping(struct bch_fs *c,
* r wins, but it overlaps in the middle of l - split l: * r wins, but it overlaps in the middle of l - split l:
*/ */
bkey_reassemble(split.k, l.s_c); bkey_reassemble(split.k, l.s_c);
bch2_cut_back(bkey_start_pos(r.k), &split.k->k); bch2_cut_back(bkey_start_pos(r.k), split.k);
__bch2_cut_front(r.k->p, l); bch2_cut_front_s(r.k->p, l);
extent_save(b, lk, l.k); extent_save(b, lk, l.k);
extent_sort_sift(iter, b, 0); extent_sort_sift(iter, b, 0);
...@@ -372,7 +372,7 @@ struct btree_nr_keys bch2_extent_sort_fix_overlapping(struct bch_fs *c, ...@@ -372,7 +372,7 @@ struct btree_nr_keys bch2_extent_sort_fix_overlapping(struct bch_fs *c,
extent_sort_append(c, f, &nr, dst->start, extent_sort_append(c, f, &nr, dst->start,
&prev, bkey_i_to_s(split.k)); &prev, bkey_i_to_s(split.k));
} else { } else {
bch2_cut_back(bkey_start_pos(r.k), l.k); bch2_cut_back_s(bkey_start_pos(r.k), l);
extent_save(b, lk, l.k); extent_save(b, lk, l.k);
} }
} }
......
...@@ -584,6 +584,16 @@ static inline void btree_keys_account_key(struct btree_nr_keys *n, ...@@ -584,6 +584,16 @@ static inline void btree_keys_account_key(struct btree_nr_keys *n,
n->unpacked_keys += sign; n->unpacked_keys += sign;
} }
static inline void btree_keys_account_val_delta(struct btree *b,
struct bkey_packed *k,
int delta)
{
struct bset_tree *t = bch2_bkey_to_bset(b, k);
b->nr.live_u64s += delta;
b->nr.bset_u64s[t - b->set] += delta;
}
#define btree_keys_account_key_add(_nr, _bset_idx, _k) \ #define btree_keys_account_key_add(_nr, _bset_idx, _k) \
btree_keys_account_key(_nr, _bset_idx, _k, 1) btree_keys_account_key(_nr, _bset_idx, _k, 1)
#define btree_keys_account_key_drop(_nr, _bset_idx, _k) \ #define btree_keys_account_key_drop(_nr, _bset_idx, _k) \
......
...@@ -884,7 +884,7 @@ int bch2_btree_delete_at_range(struct btree_trans *trans, ...@@ -884,7 +884,7 @@ int bch2_btree_delete_at_range(struct btree_trans *trans,
/* create the biggest key we can */ /* create the biggest key we can */
bch2_key_resize(&delete.k, max_sectors); bch2_key_resize(&delete.k, max_sectors);
bch2_cut_back(end, &delete.k); bch2_cut_back(end, &delete);
ret = bch2_extent_trim_atomic(&delete, iter); ret = bch2_extent_trim_atomic(&delete, iter);
if (ret) if (ret)
......
...@@ -720,12 +720,14 @@ void bch2_btree_ptr_to_text(struct printbuf *out, struct bch_fs *c, ...@@ -720,12 +720,14 @@ void bch2_btree_ptr_to_text(struct printbuf *out, struct bch_fs *c,
/* Extents */ /* Extents */
void __bch2_cut_front(struct bpos where, struct bkey_s k) int bch2_cut_front_s(struct bpos where, struct bkey_s k)
{ {
unsigned new_val_u64s = bkey_val_u64s(k.k);
int val_u64s_delta;
u64 sub; u64 sub;
if (bkey_cmp(where, bkey_start_pos(k.k)) <= 0) if (bkey_cmp(where, bkey_start_pos(k.k)) <= 0)
return; return 0;
EBUG_ON(bkey_cmp(where, k.k->p) > 0); EBUG_ON(bkey_cmp(where, k.k->p) > 0);
...@@ -733,8 +735,10 @@ void __bch2_cut_front(struct bpos where, struct bkey_s k) ...@@ -733,8 +735,10 @@ void __bch2_cut_front(struct bpos where, struct bkey_s k)
k.k->size -= sub; k.k->size -= sub;
if (!k.k->size) if (!k.k->size) {
k.k->type = KEY_TYPE_deleted; k.k->type = KEY_TYPE_deleted;
new_val_u64s = 0;
}
switch (k.k->type) { switch (k.k->type) {
case KEY_TYPE_deleted: case KEY_TYPE_deleted:
...@@ -784,26 +788,42 @@ void __bch2_cut_front(struct bpos where, struct bkey_s k) ...@@ -784,26 +788,42 @@ void __bch2_cut_front(struct bpos where, struct bkey_s k)
default: default:
BUG(); BUG();
} }
val_u64s_delta = bkey_val_u64s(k.k) - new_val_u64s;
BUG_ON(val_u64s_delta < 0);
set_bkey_val_u64s(k.k, new_val_u64s);
memset(bkey_val_end(k), 0, val_u64s_delta * sizeof(u64));
return -val_u64s_delta;
} }
bool bch2_cut_back(struct bpos where, struct bkey *k) int bch2_cut_back_s(struct bpos where, struct bkey_s k)
{ {
unsigned new_val_u64s = bkey_val_u64s(k.k);
int val_u64s_delta;
u64 len = 0; u64 len = 0;
if (bkey_cmp(where, k->p) >= 0) if (bkey_cmp(where, k.k->p) >= 0)
return false; return 0;
EBUG_ON(bkey_cmp(where, bkey_start_pos(k)) < 0); EBUG_ON(bkey_cmp(where, bkey_start_pos(k.k)) < 0);
len = where.offset - bkey_start_offset(k); len = where.offset - bkey_start_offset(k.k);
k->p = where; k.k->p = where;
k->size = len; k.k->size = len;
if (!len) if (!len) {
k->type = KEY_TYPE_deleted; k.k->type = KEY_TYPE_deleted;
new_val_u64s = 0;
}
return true; val_u64s_delta = bkey_val_u64s(k.k) - new_val_u64s;
BUG_ON(val_u64s_delta < 0);
set_bkey_val_u64s(k.k, new_val_u64s);
memset(bkey_val_end(k), 0, val_u64s_delta * sizeof(u64));
return -val_u64s_delta;
} }
static unsigned bch2_bkey_nr_alloc_ptrs(struct bkey_s_c k) static unsigned bch2_bkey_nr_alloc_ptrs(struct bkey_s_c k)
...@@ -942,7 +962,7 @@ int bch2_extent_trim_atomic(struct bkey_i *k, struct btree_iter *iter) ...@@ -942,7 +962,7 @@ int bch2_extent_trim_atomic(struct bkey_i *k, struct btree_iter *iter)
if (ret) if (ret)
return ret; return ret;
bch2_cut_back(end, &k->k); bch2_cut_back(end, k);
return 0; return 0;
} }
...@@ -1085,11 +1105,14 @@ extent_squash(struct bch_fs *c, struct btree_iter *iter, ...@@ -1085,11 +1105,14 @@ extent_squash(struct bch_fs *c, struct btree_iter *iter,
enum bch_extent_overlap overlap) enum bch_extent_overlap overlap)
{ {
struct btree_iter_level *l = &iter->l[0]; struct btree_iter_level *l = &iter->l[0];
int u64s_delta;
switch (overlap) { switch (overlap) {
case BCH_EXTENT_OVERLAP_FRONT: case BCH_EXTENT_OVERLAP_FRONT:
/* insert overlaps with start of k: */ /* insert overlaps with start of k: */
__bch2_cut_front(insert->k.p, k); u64s_delta = bch2_cut_front_s(insert->k.p, k);
btree_keys_account_val_delta(l->b, _k, u64s_delta);
EBUG_ON(bkey_deleted(k.k)); EBUG_ON(bkey_deleted(k.k));
extent_save(l->b, _k, k.k); extent_save(l->b, _k, k.k);
bch2_btree_iter_fix_key_modified(iter, l->b, _k); bch2_btree_iter_fix_key_modified(iter, l->b, _k);
...@@ -1097,7 +1120,9 @@ extent_squash(struct bch_fs *c, struct btree_iter *iter, ...@@ -1097,7 +1120,9 @@ extent_squash(struct bch_fs *c, struct btree_iter *iter,
case BCH_EXTENT_OVERLAP_BACK: case BCH_EXTENT_OVERLAP_BACK:
/* insert overlaps with end of k: */ /* insert overlaps with end of k: */
bch2_cut_back(bkey_start_pos(&insert->k), k.k); u64s_delta = bch2_cut_back_s(bkey_start_pos(&insert->k), k);
btree_keys_account_val_delta(l->b, _k, u64s_delta);
EBUG_ON(bkey_deleted(k.k)); EBUG_ON(bkey_deleted(k.k));
extent_save(l->b, _k, k.k); extent_save(l->b, _k, k.k);
...@@ -1155,10 +1180,12 @@ extent_squash(struct bch_fs *c, struct btree_iter *iter, ...@@ -1155,10 +1180,12 @@ extent_squash(struct bch_fs *c, struct btree_iter *iter,
bkey_reassemble(split.k, k.s_c); bkey_reassemble(split.k, k.s_c);
split.k->k.needs_whiteout |= bkey_written(l->b, _k); split.k->k.needs_whiteout |= bkey_written(l->b, _k);
bch2_cut_back(bkey_start_pos(&insert->k), &split.k->k); bch2_cut_back(bkey_start_pos(&insert->k), split.k);
BUG_ON(bkey_deleted(&split.k->k)); BUG_ON(bkey_deleted(&split.k->k));
__bch2_cut_front(insert->k.p, k); u64s_delta = bch2_cut_front_s(insert->k.p, k);
btree_keys_account_val_delta(l->b, _k, u64s_delta);
BUG_ON(bkey_deleted(k.k)); BUG_ON(bkey_deleted(k.k));
extent_save(l->b, _k, k.k); extent_save(l->b, _k, k.k);
bch2_btree_iter_fix_key_modified(iter, l->b, _k); bch2_btree_iter_fix_key_modified(iter, l->b, _k);
...@@ -1748,7 +1775,7 @@ enum merge_result bch2_reservation_merge(struct bch_fs *c, ...@@ -1748,7 +1775,7 @@ enum merge_result bch2_reservation_merge(struct bch_fs *c,
if ((u64) l.k->size + r.k->size > KEY_SIZE_MAX) { if ((u64) l.k->size + r.k->size > KEY_SIZE_MAX) {
bch2_key_resize(l.k, KEY_SIZE_MAX); bch2_key_resize(l.k, KEY_SIZE_MAX);
__bch2_cut_front(l.k->p, r.s); bch2_cut_front_s(l.k->p, r.s);
return BCH_MERGE_PARTIAL; return BCH_MERGE_PARTIAL;
} }
......
...@@ -534,14 +534,18 @@ do { \ ...@@ -534,14 +534,18 @@ do { \
} \ } \
} while (0) } while (0)
void __bch2_cut_front(struct bpos, struct bkey_s); int bch2_cut_front_s(struct bpos, struct bkey_s);
int bch2_cut_back_s(struct bpos, struct bkey_s);
static inline void bch2_cut_front(struct bpos where, struct bkey_i *k) static inline void bch2_cut_front(struct bpos where, struct bkey_i *k)
{ {
__bch2_cut_front(where, bkey_i_to_s(k)); bch2_cut_front_s(where, bkey_i_to_s(k));
} }
bool bch2_cut_back(struct bpos, struct bkey *); static inline void bch2_cut_back(struct bpos where, struct bkey_i *k)
{
bch2_cut_back_s(where, bkey_i_to_s(k));
}
/** /**
* bch_key_resize - adjust size of @k * bch_key_resize - adjust size of @k
......
...@@ -2485,7 +2485,7 @@ static long bchfs_fcollapse_finsert(struct bch_inode_info *inode, ...@@ -2485,7 +2485,7 @@ static long bchfs_fcollapse_finsert(struct bch_inode_info *inode,
move_pos.offset -= shift >> 9; move_pos.offset -= shift >> 9;
goto reassemble; goto reassemble;
} else { } else {
bch2_cut_back(atomic_end, &copy.k->k); bch2_cut_back(atomic_end, copy.k);
} }
} }
...@@ -2505,7 +2505,7 @@ static long bchfs_fcollapse_finsert(struct bch_inode_info *inode, ...@@ -2505,7 +2505,7 @@ static long bchfs_fcollapse_finsert(struct bch_inode_info *inode,
*/ */
if (insert && if (insert &&
bkey_cmp(bkey_start_pos(&copy.k->k), delete.k.p) < 0) { bkey_cmp(bkey_start_pos(&copy.k->k), delete.k.p) < 0) {
bch2_cut_back(bkey_start_pos(&copy.k->k), &delete.k); bch2_cut_back(bkey_start_pos(&copy.k->k), &delete);
} else if (!insert && } else if (!insert &&
bkey_cmp(copy.k->k.p, bkey_cmp(copy.k->k.p,
bkey_start_pos(&delete.k)) > 0) { bkey_start_pos(&delete.k)) > 0) {
...@@ -2653,7 +2653,7 @@ static long bchfs_fallocate(struct bch_inode_info *inode, int mode, ...@@ -2653,7 +2653,7 @@ static long bchfs_fallocate(struct bch_inode_info *inode, int mode,
reservation.k.size = k.k->size; reservation.k.size = k.k->size;
bch2_cut_front(iter->pos, &reservation.k_i); bch2_cut_front(iter->pos, &reservation.k_i);
bch2_cut_back(end_pos, &reservation.k); bch2_cut_back(end_pos, &reservation.k_i);
sectors = reservation.k.size; sectors = reservation.k.size;
reservation.v.nr_replicas = bch2_bkey_nr_dirty_ptrs(k); reservation.v.nr_replicas = bch2_bkey_nr_dirty_ptrs(k);
......
...@@ -345,7 +345,7 @@ int bch2_fpunch_at(struct btree_trans *trans, struct btree_iter *iter, ...@@ -345,7 +345,7 @@ int bch2_fpunch_at(struct btree_trans *trans, struct btree_iter *iter,
/* create the biggest key we can */ /* create the biggest key we can */
bch2_key_resize(&delete.k, max_sectors); bch2_key_resize(&delete.k, max_sectors);
bch2_cut_back(end, &delete.k); bch2_cut_back(end, &delete);
bch2_trans_begin_updates(trans); bch2_trans_begin_updates(trans);
...@@ -414,6 +414,7 @@ int bch2_write_index_default(struct bch_write_op *op) ...@@ -414,6 +414,7 @@ int bch2_write_index_default(struct bch_write_op *op)
bkey_on_stack_realloc(&sk, c, k->k.u64s); bkey_on_stack_realloc(&sk, c, k->k.u64s);
bkey_copy(sk.k, k); bkey_copy(sk.k, k);
bch2_cut_front(iter->pos, sk.k);
bch2_trans_begin_updates(&trans); bch2_trans_begin_updates(&trans);
...@@ -425,9 +426,7 @@ int bch2_write_index_default(struct bch_write_op *op) ...@@ -425,9 +426,7 @@ int bch2_write_index_default(struct bch_write_op *op)
if (ret) if (ret)
break; break;
if (bkey_cmp(iter->pos, k->k.p) < 0) if (bkey_cmp(iter->pos, k->k.p) >= 0)
bch2_cut_front(iter->pos, k);
else
bch2_keylist_pop_front(keys); bch2_keylist_pop_front(keys);
} while (!bch2_keylist_empty(keys)); } while (!bch2_keylist_empty(keys));
......
...@@ -96,10 +96,11 @@ static int bch2_migrate_index_update(struct bch_write_op *op) ...@@ -96,10 +96,11 @@ static int bch2_migrate_index_update(struct bch_write_op *op)
bkey_copy(&_new.k, bch2_keylist_front(keys)); bkey_copy(&_new.k, bch2_keylist_front(keys));
new = bkey_i_to_extent(&_new.k); new = bkey_i_to_extent(&_new.k);
bch2_cut_front(iter->pos, &new->k_i);
bch2_cut_front(iter->pos, insert); bch2_cut_front(iter->pos, insert);
bch2_cut_back(new->k.p, &insert->k); bch2_cut_back(new->k.p, insert);
bch2_cut_back(insert->k.p, &new->k); bch2_cut_back(insert->k.p, &new->k_i);
if (m->data_cmd == DATA_REWRITE) if (m->data_cmd == DATA_REWRITE)
bch2_bkey_drop_device(bkey_i_to_s(insert), bch2_bkey_drop_device(bkey_i_to_s(insert),
...@@ -168,8 +169,6 @@ static int bch2_migrate_index_update(struct bch_write_op *op) ...@@ -168,8 +169,6 @@ static int bch2_migrate_index_update(struct bch_write_op *op)
if (bch2_keylist_empty(keys)) if (bch2_keylist_empty(keys))
goto out; goto out;
} }
bch2_cut_front(iter->pos, bch2_keylist_front(keys));
continue; continue;
nomatch: nomatch:
if (m->ctxt) if (m->ctxt)
......
...@@ -177,7 +177,7 @@ static struct journal_keys journal_keys_sort(struct list_head *journal_entries) ...@@ -177,7 +177,7 @@ static struct journal_keys journal_keys_sort(struct list_head *journal_entries)
if ((cmp_int(i[0].journal_seq, i[1].journal_seq) ?: if ((cmp_int(i[0].journal_seq, i[1].journal_seq) ?:
cmp_int(i[0].journal_offset, i[1].journal_offset)) < 0) { cmp_int(i[0].journal_offset, i[1].journal_offset)) < 0) {
if (bkey_cmp(i[0].k->k.p, i[1].k->k.p) <= 0) { if (bkey_cmp(i[0].k->k.p, i[1].k->k.p) <= 0) {
bch2_cut_back(bkey_start_pos(&i[1].k->k), &i[0].k->k); bch2_cut_back(bkey_start_pos(&i[1].k->k), i[0].k);
} else { } else {
struct bkey_i *split = struct bkey_i *split =
kmalloc(bkey_bytes(i[0].k), GFP_KERNEL); kmalloc(bkey_bytes(i[0].k), GFP_KERNEL);
...@@ -186,7 +186,7 @@ static struct journal_keys journal_keys_sort(struct list_head *journal_entries) ...@@ -186,7 +186,7 @@ static struct journal_keys journal_keys_sort(struct list_head *journal_entries)
goto err; goto err;
bkey_copy(split, i[0].k); bkey_copy(split, i[0].k);
bch2_cut_back(bkey_start_pos(&i[1].k->k), &split->k); bch2_cut_back(bkey_start_pos(&i[1].k->k), split);
keys_deduped.d[keys_deduped.nr++] = (struct journal_key) { keys_deduped.d[keys_deduped.nr++] = (struct journal_key) {
.btree_id = i[0].btree_id, .btree_id = i[0].btree_id,
.allocated = true, .allocated = true,
...@@ -298,7 +298,7 @@ static int bch2_extent_replay_key(struct bch_fs *c, enum btree_id btree_id, ...@@ -298,7 +298,7 @@ static int bch2_extent_replay_key(struct bch_fs *c, enum btree_id btree_id,
bkey_copy(split, k); bkey_copy(split, k);
bch2_cut_front(split_iter->pos, split); bch2_cut_front(split_iter->pos, split);
bch2_cut_back(atomic_end, &split->k); bch2_cut_back(atomic_end, split);
bch2_trans_update(&trans, split_iter, split); bch2_trans_update(&trans, split_iter, split);
bch2_btree_iter_set_pos(iter, split->k.p); bch2_btree_iter_set_pos(iter, split->k.p);
......
...@@ -40,7 +40,7 @@ enum merge_result bch2_reflink_p_merge(struct bch_fs *c, ...@@ -40,7 +40,7 @@ enum merge_result bch2_reflink_p_merge(struct bch_fs *c,
if ((u64) l.k->size + r.k->size > KEY_SIZE_MAX) { if ((u64) l.k->size + r.k->size > KEY_SIZE_MAX) {
bch2_key_resize(l.k, KEY_SIZE_MAX); bch2_key_resize(l.k, KEY_SIZE_MAX);
__bch2_cut_front(l.k->p, _r); bch2_cut_front_s(l.k->p, _r);
return BCH_MERGE_PARTIAL; return BCH_MERGE_PARTIAL;
} }
...@@ -230,7 +230,7 @@ s64 bch2_remap_range(struct bch_fs *c, ...@@ -230,7 +230,7 @@ s64 bch2_remap_range(struct bch_fs *c,
src_k = bkey_i_to_s_c(new_src.k); src_k = bkey_i_to_s_c(new_src.k);
bch2_cut_front(src_iter->pos, new_src.k); bch2_cut_front(src_iter->pos, new_src.k);
bch2_cut_back(src_end, &new_src.k->k); bch2_cut_back(src_end, new_src.k);
ret = bch2_make_extent_indirect(&trans, src_iter, ret = bch2_make_extent_indirect(&trans, src_iter,
bkey_i_to_extent(new_src.k)); bkey_i_to_extent(new_src.k));
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment