diff options
author | Kent Overstreet <kent.overstreet@gmail.com> | 2018-06-30 23:54:41 -0400 |
---|---|---|
committer | Kent Overstreet <kent.overstreet@gmail.com> | 2018-07-01 01:20:57 -0400 |
commit | f293925453aa0a992e4f80fef2f0104e0fe28e40 (patch) | |
tree | 32615f0db940d9c542228ab8f742761f0ea06631 | |
parent | 48d18c0a175427388138493c8e7e4b85702a7847 (diff) |
bcachefs: don't expose extent whiteouts outside of btree code
-rw-r--r-- | fs/bcachefs/bset.h | 6 | ||||
-rw-r--r-- | fs/bcachefs/btree_iter.c | 25 | ||||
-rw-r--r-- | fs/bcachefs/btree_update_leaf.c | 15 | ||||
-rw-r--r-- | fs/bcachefs/extents.c | 24 | ||||
-rw-r--r-- | fs/bcachefs/fs-io.c | 50 | ||||
-rw-r--r-- | fs/bcachefs/fsck.c | 3 |
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(©.k, k); - if (bkey_deleted(©.k.k)) - copy.k.k.type = KEY_TYPE_DISCARD; - bch2_cut_front(src.pos, ©.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; |