summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorKent Overstreet <kent.overstreet@gmail.com>2018-06-30 23:54:41 -0400
committerKent Overstreet <kent.overstreet@gmail.com>2018-07-01 01:20:57 -0400
commitf293925453aa0a992e4f80fef2f0104e0fe28e40 (patch)
tree32615f0db940d9c542228ab8f742761f0ea06631
parent48d18c0a175427388138493c8e7e4b85702a7847 (diff)
bcachefs: don't expose extent whiteouts outside of btree code
-rw-r--r--fs/bcachefs/bset.h6
-rw-r--r--fs/bcachefs/btree_iter.c25
-rw-r--r--fs/bcachefs/btree_update_leaf.c15
-rw-r--r--fs/bcachefs/extents.c24
-rw-r--r--fs/bcachefs/fs-io.c50
-rw-r--r--fs/bcachefs/fsck.c3
6 files changed, 59 insertions, 64 deletions
diff --git a/fs/bcachefs/bset.h b/fs/bcachefs/bset.h
index 5895362e0af3..296c05b4f07a 100644
--- a/fs/bcachefs/bset.h
+++ b/fs/bcachefs/bset.h
@@ -406,7 +406,7 @@ bch2_bkey_prev_all(struct btree *b, struct bset_tree *t, struct bkey_packed *k)
static inline struct bkey_packed *
bch2_bkey_prev(struct btree *b, struct bset_tree *t, struct bkey_packed *k)
{
- return bch2_bkey_prev_filter(b, t, k, KEY_TYPE_DELETED + 1);
+ return bch2_bkey_prev_filter(b, t, k, KEY_TYPE_DISCARD + 1);
}
enum bch_extent_overlap {
@@ -552,7 +552,7 @@ bch2_btree_node_iter_peek_all(struct btree_node_iter *iter,
static inline struct bkey_packed *
bch2_btree_node_iter_peek(struct btree_node_iter *iter, struct btree *b)
{
- return bch2_btree_node_iter_peek_filter(iter, b, KEY_TYPE_DELETED + 1);
+ return bch2_btree_node_iter_peek_filter(iter, b, KEY_TYPE_DISCARD + 1);
}
static inline struct bkey_packed *
@@ -578,7 +578,7 @@ bch2_btree_node_iter_prev_all(struct btree_node_iter *iter, struct btree *b)
static inline struct bkey_packed *
bch2_btree_node_iter_prev(struct btree_node_iter *iter, struct btree *b)
{
- return bch2_btree_node_iter_prev_filter(iter, b, KEY_TYPE_DELETED + 1);
+ return bch2_btree_node_iter_prev_filter(iter, b, KEY_TYPE_DISCARD + 1);
}
/*
diff --git a/fs/bcachefs/btree_iter.c b/fs/bcachefs/btree_iter.c
index c44cadb8e784..a776869f3c78 100644
--- a/fs/bcachefs/btree_iter.c
+++ b/fs/bcachefs/btree_iter.c
@@ -1338,7 +1338,7 @@ struct bkey_s_c bch2_btree_iter_next(struct btree_iter *iter)
p = bch2_btree_node_iter_peek_all(&l->iter, l->b);
if (unlikely(!p))
return bch2_btree_iter_peek_next_leaf(iter);
- } while (bkey_deleted(p));
+ } while (bkey_whiteout(p));
k = __btree_iter_unpack(iter, l, &iter->k, p);
@@ -1406,13 +1406,6 @@ recheck:
bkey_cmp(bkey_start_pos(k.k), iter->pos) == 0)
__btree_iter_advance(l);
- if (k.k && bkey_cmp(bkey_start_pos(k.k), iter->pos) <= 0) {
- EBUG_ON(bkey_cmp(k.k->p, iter->pos) < 0);
- EBUG_ON(bkey_deleted(k.k));
- iter->uptodate = BTREE_ITER_UPTODATE;
- return k;
- }
-
/*
* If we got to the end of the node, check if we need to traverse to the
* next node:
@@ -1426,6 +1419,15 @@ recheck:
goto recheck;
}
+ if (k.k &&
+ !bkey_whiteout(k.k) &&
+ bkey_cmp(bkey_start_pos(k.k), iter->pos) <= 0) {
+ EBUG_ON(bkey_cmp(k.k->p, iter->pos) < 0);
+ EBUG_ON(bkey_deleted(k.k));
+ iter->uptodate = BTREE_ITER_UPTODATE;
+ return k;
+ }
+
/* hole */
bkey_init(&n);
n.p = iter->pos;
@@ -1439,6 +1441,13 @@ recheck:
goto recheck;
}
+ if (k.k && bkey_whiteout(k.k)) {
+ struct btree_node_iter node_iter = l->iter;
+
+ k = __btree_iter_unpack(iter, l, &iter->k,
+ bch2_btree_node_iter_peek(&node_iter, l->b));
+ }
+
if (!k.k)
k.k = &l->b->key.k;
diff --git a/fs/bcachefs/btree_update_leaf.c b/fs/bcachefs/btree_update_leaf.c
index 5149bcd6ca8a..ad3242efb42e 100644
--- a/fs/bcachefs/btree_update_leaf.c
+++ b/fs/bcachefs/btree_update_leaf.c
@@ -428,6 +428,7 @@ int __bch2_btree_insert_at(struct btree_insert *trans)
BUG_ON(i->iter->level);
BUG_ON(bkey_cmp(bkey_start_pos(&i->k->k), i->iter->pos));
BUG_ON(debug_check_bkeys(c) &&
+ !bkey_deleted(&i->k->k) &&
bch2_bkey_invalid(c, i->iter->btree_id,
bkey_i_to_s_c(i->k)));
}
@@ -644,11 +645,6 @@ int bch2_btree_delete_range(struct bch_fs *c, enum btree_id id,
if (bkey_cmp(iter.pos, end) >= 0)
break;
- if (k.k->type == KEY_TYPE_DISCARD) {
- bch2_btree_iter_next(&iter);
- continue;
- }
-
bkey_init(&delete.k);
/*
@@ -665,15 +661,6 @@ int bch2_btree_delete_range(struct bch_fs *c, enum btree_id id,
delete.k.version = version;
if (iter.flags & BTREE_ITER_IS_EXTENTS) {
- /*
- * The extents btree is special - KEY_TYPE_DISCARD is
- * used for deletions, not KEY_TYPE_DELETED. This is an
- * internal implementation detail that probably
- * shouldn't be exposed (internally, KEY_TYPE_DELETED is
- * used as a proxy for k->size == 0):
- */
- delete.k.type = KEY_TYPE_DISCARD;
-
/* create the biggest key we can */
bch2_key_resize(&delete.k, max_sectors);
bch2_cut_back(end, &delete.k);
diff --git a/fs/bcachefs/extents.c b/fs/bcachefs/extents.c
index e65ddb461b0b..fe4bb52717cf 100644
--- a/fs/bcachefs/extents.c
+++ b/fs/bcachefs/extents.c
@@ -1143,10 +1143,13 @@ static void extent_bset_insert(struct bch_fs *c, struct btree_iter *iter,
struct bset_tree *t = bset_tree_last(l->b);
struct bkey_packed *where =
bch2_btree_node_iter_bset_pos(&l->iter, l->b, t);
- struct bkey_packed *prev = bch2_bkey_prev(l->b, t, where);
+ struct bkey_packed *prev = bch2_bkey_prev_filter(l->b, t, where,
+ KEY_TYPE_DISCARD);
struct bkey_packed *next_live_key = where;
unsigned clobber_u64s;
+ EBUG_ON(bkey_deleted(&insert->k) || !insert->k.size);
+
if (prev)
where = bkey_next(prev);
@@ -1188,6 +1191,7 @@ static void extent_insert_committed(struct extent_insert_state *s)
: &s->whiteout;
BKEY_PADDED(k) split;
+ EBUG_ON(bkey_deleted(&insert->k) || !insert->k.size);
EBUG_ON(bkey_cmp(insert->k.p, s->committed) < 0);
EBUG_ON(bkey_cmp(s->committed, bkey_start_pos(&insert->k)) < 0);
@@ -1246,8 +1250,6 @@ __extent_insert_advance_pos(struct extent_insert_state *s,
else
ret = BTREE_INSERT_OK;
- EBUG_ON(bkey_deleted(&s->insert->k->k) || !s->insert->k->k.size);
-
if (ret == BTREE_INSERT_OK)
s->committed = next_pos;
@@ -1446,6 +1448,7 @@ __bch2_delete_fixup_extent(struct extent_insert_state *s)
EBUG_ON(bkey_cmp(iter->pos, bkey_start_pos(&insert->k)));
s->whiteout = *insert;
+ s->whiteout.k.type = KEY_TYPE_DISCARD;
while (bkey_cmp(s->committed, insert->k.p) < 0 &&
(ret = extent_insert_should_stop(s)) == BTREE_INSERT_OK &&
@@ -1488,6 +1491,8 @@ __bch2_delete_fixup_extent(struct extent_insert_state *s)
bset_written(b, bset(b, t))) {
struct bkey_i discard = *insert;
+ discard.k.type = KEY_TYPE_DISCARD;
+
switch (overlap) {
case BCH_EXTENT_OVERLAP_FRONT:
bch2_cut_front(bkey_start_pos(k.k), &discard);
@@ -1634,7 +1639,7 @@ bch2_insert_fixup_extent(struct btree_insert *trans,
};
EBUG_ON(iter->level);
- EBUG_ON(bkey_deleted(&insert->k->k) || !insert->k->k.size);
+ EBUG_ON(!insert->k->k.size);
/*
* As we process overlapping extents, we advance @iter->pos both to
@@ -2051,11 +2056,6 @@ int bch2_extent_pick_ptr(struct bch_fs *c, struct bkey_s_c k,
int ret;
switch (k.k->type) {
- case KEY_TYPE_DELETED:
- case KEY_TYPE_DISCARD:
- case KEY_TYPE_COOKIE:
- return 0;
-
case KEY_TYPE_ERROR:
return -EIO;
@@ -2069,11 +2069,8 @@ int bch2_extent_pick_ptr(struct bch_fs *c, struct bkey_s_c k,
return ret;
- case BCH_RESERVATION:
- return 0;
-
default:
- BUG();
+ return 0;
}
}
@@ -2099,7 +2096,6 @@ enum merge_result bch2_extent_merge(struct bch_fs *c, struct btree *b,
return BCH_MERGE_NOMERGE;
switch (l->k.type) {
- case KEY_TYPE_DELETED:
case KEY_TYPE_DISCARD:
case KEY_TYPE_ERROR:
/* These types are mergeable, and no val to check */
diff --git a/fs/bcachefs/fs-io.c b/fs/bcachefs/fs-io.c
index 737b9be33e0a..9e78798a4d08 100644
--- a/fs/bcachefs/fs-io.c
+++ b/fs/bcachefs/fs-io.c
@@ -2078,6 +2078,29 @@ out:
/* truncate: */
+static inline int range_has_data(struct bch_fs *c,
+ struct bpos start,
+ struct bpos end)
+{
+
+ struct btree_iter iter;
+ struct bkey_s_c k;
+ int ret = 0;
+
+ for_each_btree_key(&iter, c, BTREE_ID_EXTENTS,
+ start, 0, k) {
+ if (bkey_cmp(bkey_start_pos(k.k), end) >= 0)
+ break;
+
+ if (bkey_extent_is_data(k.k)) {
+ ret = 1;
+ break;
+ }
+ }
+
+ return bch2_btree_iter_unlock(&iter) ?: ret;
+}
+
static int __bch2_truncate_page(struct bch_inode_info *inode,
pgoff_t index, loff_t start, loff_t end)
{
@@ -2099,30 +2122,16 @@ static int __bch2_truncate_page(struct bch_inode_info *inode,
page = find_lock_page(mapping, index);
if (!page) {
- struct btree_iter iter;
- struct bkey_s_c k = bkey_s_c_null;
-
/*
* XXX: we're doing two index lookups when we end up reading the
* page
*/
- for_each_btree_key(&iter, c, BTREE_ID_EXTENTS,
- POS(inode->v.i_ino,
- index << PAGE_SECTOR_SHIFT), 0, k) {
- if (bkey_cmp(bkey_start_pos(k.k),
- POS(inode->v.i_ino,
- (index + 1) << PAGE_SECTOR_SHIFT)) >= 0)
- break;
+ ret = range_has_data(c,
+ POS(inode->v.i_ino, index << PAGE_SECTOR_SHIFT),
+ POS(inode->v.i_ino, (index + 1) << PAGE_SECTOR_SHIFT));
+ if (ret <= 0)
+ return ret;
- if (k.k->type != KEY_TYPE_DISCARD &&
- k.k->type != BCH_RESERVATION) {
- bch2_btree_iter_unlock(&iter);
- goto create;
- }
- }
- bch2_btree_iter_unlock(&iter);
- return 0;
-create:
page = find_or_create_page(mapping, index, GFP_KERNEL);
if (unlikely(!page)) {
ret = -ENOMEM;
@@ -2389,9 +2398,6 @@ static long bch2_fcollapse(struct bch_inode_info *inode,
bkey_reassemble(&copy.k, k);
- if (bkey_deleted(&copy.k.k))
- copy.k.k.type = KEY_TYPE_DISCARD;
-
bch2_cut_front(src.pos, &copy.k);
copy.k.k.p.offset -= len >> 9;
diff --git a/fs/bcachefs/fsck.c b/fs/bcachefs/fsck.c
index 048b5c103eb0..edf714f7b98d 100644
--- a/fs/bcachefs/fsck.c
+++ b/fs/bcachefs/fsck.c
@@ -252,9 +252,6 @@ static int check_extents(struct bch_fs *c)
for_each_btree_key(&iter, c, BTREE_ID_EXTENTS,
POS(BCACHEFS_ROOT_INO, 0), 0, k) {
- if (k.k->type == KEY_TYPE_DISCARD)
- continue;
-
ret = walk_inode(c, &w, k.k->p.inode);
if (ret)
break;