summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorKent Overstreet <kent.overstreet@linux.dev>2022-10-11 04:32:41 -0400
committerKent Overstreet <kent.overstreet@linux.dev>2022-11-30 12:32:30 -0500
commit834328f5a21ee73332b8d9573a91753c6447189c (patch)
treeaf4f434b279f5c8a54037aa214b2b0fae2a96aee
parent470a52cf891b47b563ea1681775b64966ca59766 (diff)
bcachefs: Use for_each_btree_key_upto() more consistently
It's important that in BTREE_ITER_FILTER_SNAPSHOTS mode we always use peek_upto() and provide an end for the interval we're searching for - otherwise, when we hit the end of the inode the next inode be in a different subvolume and not have any keys in the current snapshot, and we'd iterate over arbitrarily many keys before returning one. Signed-off-by: Kent Overstreet <kent.overstreet@linux.dev>
-rw-r--r--fs/bcachefs/btree_iter.c28
-rw-r--r--fs/bcachefs/btree_iter.h44
-rw-r--r--fs/bcachefs/btree_update_leaf.c5
-rw-r--r--fs/bcachefs/ec.c2
-rw-r--r--fs/bcachefs/extent_update.c5
-rw-r--r--fs/bcachefs/fs-io.c26
-rw-r--r--fs/bcachefs/io.c20
-rw-r--r--fs/bcachefs/quota.c6
-rw-r--r--fs/bcachefs/reflink.c5
-rw-r--r--fs/bcachefs/tests.c55
10 files changed, 124 insertions, 72 deletions
diff --git a/fs/bcachefs/btree_iter.c b/fs/bcachefs/btree_iter.c
index 60d9f2a6fc29..9ed5fe03969f 100644
--- a/fs/bcachefs/btree_iter.c
+++ b/fs/bcachefs/btree_iter.c
@@ -1975,6 +1975,7 @@ struct bkey_s_c bch2_btree_iter_peek_upto(struct btree_iter *iter, struct bpos e
int ret;
EBUG_ON(iter->flags & BTREE_ITER_ALL_LEVELS);
+ EBUG_ON((iter->flags & BTREE_ITER_FILTER_SNAPSHOTS) && bkey_eq(end, POS_MAX));
if (iter->update_path) {
bch2_path_put_nokeep(trans, iter->update_path,
@@ -1986,7 +1987,9 @@ struct bkey_s_c bch2_btree_iter_peek_upto(struct btree_iter *iter, struct bpos e
while (1) {
k = __bch2_btree_iter_peek(iter, search_key);
- if (!k.k || bkey_err(k))
+ if (unlikely(!k.k))
+ goto end;
+ if (unlikely(bkey_err(k)))
goto out_no_locked;
/*
@@ -1999,11 +2002,10 @@ struct bkey_s_c bch2_btree_iter_peek_upto(struct btree_iter *iter, struct bpos e
else
iter_pos = bkey_max(iter->pos, bkey_start_pos(k.k));
- if (bkey_gt(iter_pos, end)) {
- bch2_btree_iter_set_pos(iter, end);
- k = bkey_s_c_null;
- goto out_no_locked;
- }
+ if (unlikely(!(iter->flags & BTREE_ITER_IS_EXTENTS)
+ ? bkey_gt(iter_pos, end)
+ : bkey_ge(iter_pos, end)))
+ goto end;
if (iter->update_path &&
!bkey_eq(iter->update_path->pos, k.k->p)) {
@@ -2087,6 +2089,10 @@ out_no_locked:
bch2_btree_iter_verify_entry_exit(iter);
return k;
+end:
+ bch2_btree_iter_set_pos(iter, end);
+ k = bkey_s_c_null;
+ goto out_no_locked;
}
/**
@@ -2399,15 +2405,15 @@ struct bkey_s_c bch2_btree_iter_peek_slot(struct btree_iter *iter)
goto out_no_locked;
} else {
struct bpos next;
+ struct bpos end = iter->pos;
+
+ if (iter->flags & BTREE_ITER_IS_EXTENTS)
+ end.offset = U64_MAX;
EBUG_ON(iter->path->level);
if (iter->flags & BTREE_ITER_INTENT) {
struct btree_iter iter2;
- struct bpos end = iter->pos;
-
- if (iter->flags & BTREE_ITER_IS_EXTENTS)
- end.offset = U64_MAX;
bch2_trans_copy_iter(&iter2, iter);
k = bch2_btree_iter_peek_upto(&iter2, end);
@@ -2420,7 +2426,7 @@ struct bkey_s_c bch2_btree_iter_peek_slot(struct btree_iter *iter)
} else {
struct bpos pos = iter->pos;
- k = bch2_btree_iter_peek(iter);
+ k = bch2_btree_iter_peek_upto(iter, end);
if (unlikely(bkey_err(k)))
bch2_btree_iter_set_pos(iter, pos);
else
diff --git a/fs/bcachefs/btree_iter.h b/fs/bcachefs/btree_iter.h
index b747e73ef8b8..c630ab56a875 100644
--- a/fs/bcachefs/btree_iter.h
+++ b/fs/bcachefs/btree_iter.h
@@ -632,6 +632,36 @@ __bch2_btree_iter_peek_and_restart(struct btree_trans *trans,
_ret; \
})
+#define for_each_btree_key2_upto(_trans, _iter, _btree_id, \
+ _start, _end, _flags, _k, _do) \
+({ \
+ int _ret = 0; \
+ \
+ bch2_trans_iter_init((_trans), &(_iter), (_btree_id), \
+ (_start), (_flags)); \
+ \
+ while (1) { \
+ u32 _restart_count = bch2_trans_begin(_trans); \
+ \
+ _ret = 0; \
+ (_k) = bch2_btree_iter_peek_upto_type(&(_iter), _end, (_flags));\
+ if (!(_k).k) \
+ break; \
+ \
+ _ret = bkey_err(_k) ?: (_do); \
+ if (bch2_err_matches(_ret, BCH_ERR_transaction_restart))\
+ continue; \
+ if (_ret) \
+ break; \
+ bch2_trans_verify_not_restarted(_trans, _restart_count);\
+ if (!bch2_btree_iter_advance(&(_iter))) \
+ break; \
+ } \
+ \
+ bch2_trans_iter_exit((_trans), &(_iter)); \
+ _ret; \
+})
+
#define for_each_btree_key_reverse(_trans, _iter, _btree_id, \
_start, _flags, _k, _do) \
({ \
@@ -670,6 +700,14 @@ __bch2_btree_iter_peek_and_restart(struct btree_trans *trans,
(_do) ?: bch2_trans_commit(_trans, (_disk_res),\
(_journal_seq), (_commit_flags)))
+#define for_each_btree_key_upto_commit(_trans, _iter, _btree_id, \
+ _start, _end, _iter_flags, _k, \
+ _disk_res, _journal_seq, _commit_flags,\
+ _do) \
+ for_each_btree_key2_upto(_trans, _iter, _btree_id, _start, _end, _iter_flags, _k,\
+ (_do) ?: bch2_trans_commit(_trans, (_disk_res),\
+ (_journal_seq), (_commit_flags)))
+
#define for_each_btree_key(_trans, _iter, _btree_id, \
_start, _flags, _k, _ret) \
for (bch2_trans_iter_init((_trans), &(_iter), (_btree_id), \
@@ -706,6 +744,12 @@ __bch2_btree_iter_peek_and_restart(struct btree_trans *trans,
!((_ret) = bkey_err(_k)) && (_k).k; \
bch2_btree_iter_advance(&(_iter)))
+#define for_each_btree_key_upto_continue_norestart(_iter, _end, _flags, _k, _ret)\
+ for (; \
+ (_k) = bch2_btree_iter_peek_upto_type(&(_iter), _end, _flags), \
+ !((_ret) = bkey_err(_k)) && (_k).k; \
+ bch2_btree_iter_advance(&(_iter)))
+
/* new multiple iterator interface: */
void bch2_trans_updates_to_text(struct printbuf *, struct btree_trans *);
diff --git a/fs/bcachefs/btree_update_leaf.c b/fs/bcachefs/btree_update_leaf.c
index 32ac9be10d79..cd23d7df9f75 100644
--- a/fs/bcachefs/btree_update_leaf.c
+++ b/fs/bcachefs/btree_update_leaf.c
@@ -1645,7 +1645,7 @@ int bch2_btree_delete_range_trans(struct btree_trans *trans, enum btree_id id,
int ret = 0;
bch2_trans_iter_init(trans, &iter, id, start, BTREE_ITER_INTENT);
- while ((k = bch2_btree_iter_peek(&iter)).k) {
+ while ((k = bch2_btree_iter_peek_upto(&iter, end)).k) {
struct disk_reservation disk_res =
bch2_disk_reservation_init(trans->c, 0);
struct bkey_i delete;
@@ -1654,9 +1654,6 @@ int bch2_btree_delete_range_trans(struct btree_trans *trans, enum btree_id id,
if (ret)
goto err;
- if (bkey_ge(iter.pos, end))
- break;
-
bkey_init(&delete.k);
/*
diff --git a/fs/bcachefs/ec.c b/fs/bcachefs/ec.c
index 0f5e0ee280fd..53f0d8209a27 100644
--- a/fs/bcachefs/ec.c
+++ b/fs/bcachefs/ec.c
@@ -684,7 +684,7 @@ static int ec_stripe_delete(struct bch_fs *c, size_t idx)
{
return bch2_btree_delete_range(c, BTREE_ID_stripes,
POS(0, idx),
- POS(0, idx + 1),
+ POS(0, idx),
0, NULL);
}
diff --git a/fs/bcachefs/extent_update.c b/fs/bcachefs/extent_update.c
index 21d6f88c7397..21af6fb8cecf 100644
--- a/fs/bcachefs/extent_update.c
+++ b/fs/bcachefs/extent_update.c
@@ -128,12 +128,9 @@ int bch2_extent_atomic_end(struct btree_trans *trans,
bch2_trans_copy_iter(&copy, iter);
- for_each_btree_key_continue_norestart(copy, 0, k, ret) {
+ for_each_btree_key_upto_continue_norestart(copy, insert->k.p, 0, k, ret) {
unsigned offset = 0;
- if (bkey_ge(bkey_start_pos(k.k), *end))
- break;
-
if (bkey_gt(bkey_start_pos(&insert->k), bkey_start_pos(k.k)))
offset = bkey_start_offset(&insert->k) -
bkey_start_offset(k.k);
diff --git a/fs/bcachefs/fs-io.c b/fs/bcachefs/fs-io.c
index 1ce0c93126c1..e7ebb01b4d09 100644
--- a/fs/bcachefs/fs-io.c
+++ b/fs/bcachefs/fs-io.c
@@ -2607,15 +2607,11 @@ retry:
if (ret)
goto err;
- for_each_btree_key_norestart(&trans, iter, BTREE_ID_extents, start, 0, k, ret) {
- if (bkey_ge(bkey_start_pos(k.k), end))
- break;
-
+ for_each_btree_key_upto_norestart(&trans, iter, BTREE_ID_extents, start, end, 0, k, ret)
if (bkey_extent_is_data(k.k)) {
ret = 1;
break;
}
- }
start = iter.pos;
bch2_trans_iter_exit(&trans, &iter);
err:
@@ -2655,8 +2651,8 @@ static int __bch2_truncate_page(struct bch_inode_info *inode,
* page
*/
ret = range_has_data(c, inode->ei_subvol,
- POS(inode->v.i_ino, index << PAGE_SECTORS_SHIFT),
- POS(inode->v.i_ino, (index + 1) << PAGE_SECTORS_SHIFT));
+ POS(inode->v.i_ino, (index << PAGE_SECTORS_SHIFT)),
+ POS(inode->v.i_ino, (index << PAGE_SECTORS_SHIFT) + PAGE_SECTORS));
if (ret <= 0)
return ret;
@@ -3038,7 +3034,7 @@ static long bchfs_fcollapse_finsert(struct bch_inode_info *inode,
k = insert
? bch2_btree_iter_peek_prev(&src)
- : bch2_btree_iter_peek(&src);
+ : bch2_btree_iter_peek_upto(&src, POS(inode->v.i_ino, U64_MAX));
if ((ret = bkey_err(k)))
continue;
@@ -3313,6 +3309,10 @@ err:
return bch2_err_class(ret);
}
+/*
+ * Take a quota reservation for unallocated blocks in a given file range
+ * Does not check pagecache
+ */
static int quota_reserve_range(struct bch_inode_info *inode,
struct quota_res *res,
u64 start, u64 end)
@@ -3528,11 +3528,11 @@ retry:
if (ret)
goto err;
- for_each_btree_key_norestart(&trans, iter, BTREE_ID_extents,
- SPOS(inode->v.i_ino, offset >> 9, snapshot), 0, k, ret) {
- if (k.k->p.inode != inode->v.i_ino) {
- break;
- } else if (bkey_extent_is_data(k.k)) {
+ for_each_btree_key_upto_norestart(&trans, iter, BTREE_ID_extents,
+ SPOS(inode->v.i_ino, offset >> 9, snapshot),
+ POS(inode->v.i_ino, U64_MAX),
+ 0, k, ret) {
+ if (bkey_extent_is_data(k.k)) {
next_data = max(offset, bkey_start_offset(k.k) << 9);
break;
} else if (k.k->p.offset >> 9 > isize)
diff --git a/fs/bcachefs/io.c b/fs/bcachefs/io.c
index ab19bc392759..f0fca861b901 100644
--- a/fs/bcachefs/io.c
+++ b/fs/bcachefs/io.c
@@ -501,16 +501,19 @@ int bch2_fpunch_at(struct btree_trans *trans, struct btree_iter *iter,
bch2_btree_iter_set_snapshot(iter, snapshot);
- k = bch2_btree_iter_peek(iter);
- if (bkey_ge(iter->pos, end_pos)) {
- bch2_btree_iter_set_pos(iter, end_pos);
+ /*
+ * peek_upto() doesn't have ideal semantics for extents:
+ */
+ k = bch2_btree_iter_peek_upto(iter, end_pos);
+ if (!k.k)
break;
- }
ret = bkey_err(k);
if (ret)
continue;
+ BUG_ON(bkey_ge(iter->pos, end_pos));
+
bkey_init(&delete.k);
delete.k.p = iter->pos;
@@ -523,6 +526,8 @@ int bch2_fpunch_at(struct btree_trans *trans, struct btree_iter *iter,
bch2_disk_reservation_put(c, &disk_res);
}
+ BUG_ON(bkey_gt(iter->pos, end_pos));
+
return ret ?: ret2;
}
@@ -1348,12 +1353,11 @@ static void bch2_nocow_write_convert_unwritten(struct bch_write_op *op)
bch2_trans_init(&trans, c, 0, 0);
for_each_keylist_key(&op->insert_keys, orig) {
- ret = for_each_btree_key_commit(&trans, iter, BTREE_ID_extents,
- bkey_start_pos(&orig->k),
+ ret = for_each_btree_key_upto_commit(&trans, iter, BTREE_ID_extents,
+ bkey_start_pos(&orig->k), orig->k.p,
BTREE_ITER_INTENT, k,
NULL, NULL, BTREE_INSERT_NOFAIL, ({
- if (bkey_ge(bkey_start_pos(k.k), orig->k.p))
- break;
+ BUG_ON(bkey_ge(bkey_start_pos(k.k), orig->k.p));
bch2_nocow_write_convert_one_unwritten(&trans, &iter, orig, k, op->new_i_size);
}));
diff --git a/fs/bcachefs/quota.c b/fs/bcachefs/quota.c
index ededc826e9a0..4b663f320bfc 100644
--- a/fs/bcachefs/quota.c
+++ b/fs/bcachefs/quota.c
@@ -709,7 +709,7 @@ static int bch2_quota_remove(struct super_block *sb, unsigned uflags)
ret = bch2_btree_delete_range(c, BTREE_ID_quotas,
POS(QTYP_USR, 0),
- POS(QTYP_USR + 1, 0),
+ POS(QTYP_USR, U64_MAX),
0, NULL);
if (ret)
return ret;
@@ -721,7 +721,7 @@ static int bch2_quota_remove(struct super_block *sb, unsigned uflags)
ret = bch2_btree_delete_range(c, BTREE_ID_quotas,
POS(QTYP_GRP, 0),
- POS(QTYP_GRP + 1, 0),
+ POS(QTYP_GRP, U64_MAX),
0, NULL);
if (ret)
return ret;
@@ -733,7 +733,7 @@ static int bch2_quota_remove(struct super_block *sb, unsigned uflags)
ret = bch2_btree_delete_range(c, BTREE_ID_quotas,
POS(QTYP_PRJ, 0),
- POS(QTYP_PRJ + 1, 0),
+ POS(QTYP_PRJ, U64_MAX),
0, NULL);
if (ret)
return ret;
diff --git a/fs/bcachefs/reflink.c b/fs/bcachefs/reflink.c
index eed4ad38b21d..ec672fedbd16 100644
--- a/fs/bcachefs/reflink.c
+++ b/fs/bcachefs/reflink.c
@@ -251,10 +251,7 @@ static struct bkey_s_c get_next_src(struct btree_iter *iter, struct bpos end)
struct bkey_s_c k;
int ret;
- for_each_btree_key_continue_norestart(*iter, 0, k, ret) {
- if (bkey_ge(iter->pos, end))
- break;
-
+ for_each_btree_key_upto_continue_norestart(*iter, end, 0, k, ret) {
if (bkey_extent_is_unwritten(k))
continue;
diff --git a/fs/bcachefs/tests.c b/fs/bcachefs/tests.c
index 43f974eb9b7e..b99a9e421f98 100644
--- a/fs/bcachefs/tests.c
+++ b/fs/bcachefs/tests.c
@@ -15,13 +15,14 @@ static void delete_test_keys(struct bch_fs *c)
int ret;
ret = bch2_btree_delete_range(c, BTREE_ID_extents,
- SPOS(0, 0, U32_MAX), SPOS_MAX,
- 0,
- NULL);
+ SPOS(0, 0, U32_MAX),
+ POS(0, U64_MAX),
+ 0, NULL);
BUG_ON(ret);
ret = bch2_btree_delete_range(c, BTREE_ID_xattrs,
- SPOS(0, 0, U32_MAX), SPOS_MAX,
+ SPOS(0, 0, U32_MAX),
+ POS(0, U64_MAX),
0, NULL);
BUG_ON(ret);
}
@@ -145,8 +146,9 @@ static int test_iterate(struct bch_fs *c, u64 nr)
i = 0;
- ret = for_each_btree_key2(&trans, iter, BTREE_ID_xattrs,
- SPOS(0, 0, U32_MAX), 0, k, ({
+ ret = for_each_btree_key2_upto(&trans, iter, BTREE_ID_xattrs,
+ SPOS(0, 0, U32_MAX), POS(0, U64_MAX),
+ 0, k, ({
BUG_ON(k.k->p.offset != i++);
0;
}));
@@ -211,8 +213,9 @@ static int test_iterate_extents(struct bch_fs *c, u64 nr)
i = 0;
- ret = for_each_btree_key2(&trans, iter, BTREE_ID_extents,
- SPOS(0, 0, U32_MAX), 0, k, ({
+ ret = for_each_btree_key2_upto(&trans, iter, BTREE_ID_extents,
+ SPOS(0, 0, U32_MAX), POS(0, U64_MAX),
+ 0, k, ({
BUG_ON(bkey_start_offset(k.k) != i);
i = k.k->p.offset;
0;
@@ -278,8 +281,9 @@ static int test_iterate_slots(struct bch_fs *c, u64 nr)
i = 0;
- ret = for_each_btree_key2(&trans, iter, BTREE_ID_xattrs,
- SPOS(0, 0, U32_MAX), 0, k, ({
+ ret = for_each_btree_key2_upto(&trans, iter, BTREE_ID_xattrs,
+ SPOS(0, 0, U32_MAX), POS(0, U64_MAX),
+ 0, k, ({
BUG_ON(k.k->p.offset != i);
i += 2;
0;
@@ -295,8 +299,8 @@ static int test_iterate_slots(struct bch_fs *c, u64 nr)
i = 0;
- ret = for_each_btree_key2(&trans, iter, BTREE_ID_xattrs,
- SPOS(0, 0, U32_MAX),
+ ret = for_each_btree_key2_upto(&trans, iter, BTREE_ID_xattrs,
+ SPOS(0, 0, U32_MAX), POS(0, U64_MAX),
BTREE_ITER_SLOTS, k, ({
if (i >= nr * 2)
break;
@@ -351,8 +355,9 @@ static int test_iterate_slots_extents(struct bch_fs *c, u64 nr)
i = 0;
- ret = for_each_btree_key2(&trans, iter, BTREE_ID_extents,
- SPOS(0, 0, U32_MAX), 0, k, ({
+ ret = for_each_btree_key2_upto(&trans, iter, BTREE_ID_extents,
+ SPOS(0, 0, U32_MAX), POS(0, U64_MAX),
+ 0, k, ({
BUG_ON(bkey_start_offset(k.k) != i + 8);
BUG_ON(k.k->size != 8);
i += 16;
@@ -369,8 +374,8 @@ static int test_iterate_slots_extents(struct bch_fs *c, u64 nr)
i = 0;
- ret = for_each_btree_key2(&trans, iter, BTREE_ID_extents,
- SPOS(0, 0, U32_MAX),
+ ret = for_each_btree_key2_upto(&trans, iter, BTREE_ID_extents,
+ SPOS(0, 0, U32_MAX), POS(0, U64_MAX),
BTREE_ITER_SLOTS, k, ({
if (i == nr)
break;
@@ -405,10 +410,10 @@ static int test_peek_end(struct bch_fs *c, u64 nr)
bch2_trans_iter_init(&trans, &iter, BTREE_ID_xattrs,
SPOS(0, 0, U32_MAX), 0);
- lockrestart_do(&trans, bkey_err(k = bch2_btree_iter_peek(&iter)));
+ lockrestart_do(&trans, bkey_err(k = bch2_btree_iter_peek_upto(&iter, POS(0, U64_MAX))));
BUG_ON(k.k);
- lockrestart_do(&trans, bkey_err(k = bch2_btree_iter_peek(&iter)));
+ lockrestart_do(&trans, bkey_err(k = bch2_btree_iter_peek_upto(&iter, POS(0, U64_MAX))));
BUG_ON(k.k);
bch2_trans_iter_exit(&trans, &iter);
@@ -426,10 +431,10 @@ static int test_peek_end_extents(struct bch_fs *c, u64 nr)
bch2_trans_iter_init(&trans, &iter, BTREE_ID_extents,
SPOS(0, 0, U32_MAX), 0);
- lockrestart_do(&trans, bkey_err(k = bch2_btree_iter_peek(&iter)));
+ lockrestart_do(&trans, bkey_err(k = bch2_btree_iter_peek_upto(&iter, POS(0, U64_MAX))));
BUG_ON(k.k);
- lockrestart_do(&trans, bkey_err(k = bch2_btree_iter_peek(&iter)));
+ lockrestart_do(&trans, bkey_err(k = bch2_btree_iter_peek_upto(&iter, POS(0, U64_MAX))));
BUG_ON(k.k);
bch2_trans_iter_exit(&trans, &iter);
@@ -519,7 +524,7 @@ static int test_snapshot_filter(struct bch_fs *c, u32 snapid_lo, u32 snapid_hi)
bch2_trans_init(&trans, c, 0, 0);
bch2_trans_iter_init(&trans, &iter, BTREE_ID_xattrs,
SPOS(0, 0, snapid_lo), 0);
- lockrestart_do(&trans, bkey_err(k = bch2_btree_iter_peek(&iter)));
+ lockrestart_do(&trans, bkey_err(k = bch2_btree_iter_peek_upto(&iter, POS(0, U64_MAX))));
BUG_ON(k.k->p.snapshot != U32_MAX);
@@ -798,8 +803,9 @@ static int seq_lookup(struct bch_fs *c, u64 nr)
bch2_trans_init(&trans, c, 0, 0);
- ret = for_each_btree_key2(&trans, iter, BTREE_ID_xattrs,
- SPOS(0, 0, U32_MAX), 0, k,
+ ret = for_each_btree_key2_upto(&trans, iter, BTREE_ID_xattrs,
+ SPOS(0, 0, U32_MAX), POS(0, U64_MAX),
+ 0, k,
0);
if (ret)
bch_err(c, "%s(): error %s", __func__, bch2_err_str(ret));
@@ -839,7 +845,8 @@ static int seq_delete(struct bch_fs *c, u64 nr)
int ret;
ret = bch2_btree_delete_range(c, BTREE_ID_xattrs,
- SPOS(0, 0, U32_MAX), SPOS_MAX,
+ SPOS(0, 0, U32_MAX),
+ POS(0, U64_MAX),
0, NULL);
if (ret)
bch_err(c, "%s(): error %s", __func__, bch2_err_str(ret));