Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

Merge tag 'for-6.6-rc7-tag' of git://git.kernel.org/pub/scm/linux/kernel/git/kdave/linux

Pull btrfs fix from David Sterba:
"One more fix for a problem with snapshot of a newly created subvolume
that can lead to inconsistent data under some circumstances. Kernel
6.5 added a performance optimization to skip transaction commit for
subvolume creation but this could end up with newer data on disk but
not linked to other structures.

The fix itself is an added condition, the rest of the patch is a
parameter added to several functions"

* tag 'for-6.6-rc7-tag' of git://git.kernel.org/pub/scm/linux/kernel/git/kdave/linux:
btrfs: fix unwritten extent buffer after snapshotting a new subvolume

+33 -15
+9 -5
fs/btrfs/backref.c
··· 3196 3196 * We still need to do a tree search to find out the parents. This is for 3197 3197 * TREE_BLOCK_REF backref (keyed or inlined). 3198 3198 * 3199 + * @trans: Transaction handle. 3199 3200 * @ref_key: The same as @ref_key in handle_direct_tree_backref() 3200 3201 * @tree_key: The first key of this tree block. 3201 3202 * @path: A clean (released) path, to avoid allocating path every time 3202 3203 * the function get called. 3203 3204 */ 3204 - static int handle_indirect_tree_backref(struct btrfs_backref_cache *cache, 3205 + static int handle_indirect_tree_backref(struct btrfs_trans_handle *trans, 3206 + struct btrfs_backref_cache *cache, 3205 3207 struct btrfs_path *path, 3206 3208 struct btrfs_key *ref_key, 3207 3209 struct btrfs_key *tree_key, ··· 3317 3315 * If we know the block isn't shared we can avoid 3318 3316 * checking its backrefs. 3319 3317 */ 3320 - if (btrfs_block_can_be_shared(root, eb)) 3318 + if (btrfs_block_can_be_shared(trans, root, eb)) 3321 3319 upper->checked = 0; 3322 3320 else 3323 3321 upper->checked = 1; ··· 3365 3363 * links aren't yet bi-directional. Needs to finish such links. 3366 3364 * Use btrfs_backref_finish_upper_links() to finish such linkage. 3367 3365 * 3366 + * @trans: Transaction handle. 3368 3367 * @path: Released path for indirect tree backref lookup 3369 3368 * @iter: Released backref iter for extent tree search 3370 3369 * @node_key: The first key of the tree block 3371 3370 */ 3372 - int btrfs_backref_add_tree_node(struct btrfs_backref_cache *cache, 3371 + int btrfs_backref_add_tree_node(struct btrfs_trans_handle *trans, 3372 + struct btrfs_backref_cache *cache, 3373 3373 struct btrfs_path *path, 3374 3374 struct btrfs_backref_iter *iter, 3375 3375 struct btrfs_key *node_key, ··· 3471 3467 * offset means the root objectid. We need to search 3472 3468 * the tree to get its parent bytenr. 3473 3469 */ 3474 - ret = handle_indirect_tree_backref(cache, path, &key, node_key, 3475 - cur); 3470 + ret = handle_indirect_tree_backref(trans, cache, path, 3471 + &key, node_key, cur); 3476 3472 if (ret < 0) 3477 3473 goto out; 3478 3474 }
+2 -1
fs/btrfs/backref.h
··· 540 540 bytenr); 541 541 } 542 542 543 - int btrfs_backref_add_tree_node(struct btrfs_backref_cache *cache, 543 + int btrfs_backref_add_tree_node(struct btrfs_trans_handle *trans, 544 + struct btrfs_backref_cache *cache, 544 545 struct btrfs_path *path, 545 546 struct btrfs_backref_iter *iter, 546 547 struct btrfs_key *node_key,
+16 -5
fs/btrfs/ctree.c
··· 367 367 /* 368 368 * check if the tree block can be shared by multiple trees 369 369 */ 370 - int btrfs_block_can_be_shared(struct btrfs_root *root, 370 + int btrfs_block_can_be_shared(struct btrfs_trans_handle *trans, 371 + struct btrfs_root *root, 371 372 struct extent_buffer *buf) 372 373 { 373 374 /* ··· 377 376 * not allocated by tree relocation, we know the block is not shared. 378 377 */ 379 378 if (test_bit(BTRFS_ROOT_SHAREABLE, &root->state) && 380 - buf != root->node && buf != root->commit_root && 379 + buf != root->node && 381 380 (btrfs_header_generation(buf) <= 382 381 btrfs_root_last_snapshot(&root->root_item) || 383 - btrfs_header_flag(buf, BTRFS_HEADER_FLAG_RELOC))) 384 - return 1; 382 + btrfs_header_flag(buf, BTRFS_HEADER_FLAG_RELOC))) { 383 + if (buf != root->commit_root) 384 + return 1; 385 + /* 386 + * An extent buffer that used to be the commit root may still be 387 + * shared because the tree height may have increased and it 388 + * became a child of a higher level root. This can happen when 389 + * snapshotting a subvolume created in the current transaction. 390 + */ 391 + if (btrfs_header_generation(buf) == trans->transid) 392 + return 1; 393 + } 385 394 386 395 return 0; 387 396 } ··· 426 415 * are only allowed for blocks use full backrefs. 427 416 */ 428 417 429 - if (btrfs_block_can_be_shared(root, buf)) { 418 + if (btrfs_block_can_be_shared(trans, root, buf)) { 430 419 ret = btrfs_lookup_extent_info(trans, fs_info, buf->start, 431 420 btrfs_header_level(buf), 1, 432 421 &refs, &flags);
+2 -1
fs/btrfs/ctree.h
··· 540 540 struct btrfs_root *root, 541 541 struct extent_buffer *buf, 542 542 struct extent_buffer **cow_ret, u64 new_root_objectid); 543 - int btrfs_block_can_be_shared(struct btrfs_root *root, 543 + int btrfs_block_can_be_shared(struct btrfs_trans_handle *trans, 544 + struct btrfs_root *root, 544 545 struct extent_buffer *buf); 545 546 int btrfs_del_ptr(struct btrfs_trans_handle *trans, struct btrfs_root *root, 546 547 struct btrfs_path *path, int level, int slot);
+4 -3
fs/btrfs/relocation.c
··· 466 466 * cached. 467 467 */ 468 468 static noinline_for_stack struct btrfs_backref_node *build_backref_tree( 469 + struct btrfs_trans_handle *trans, 469 470 struct reloc_control *rc, struct btrfs_key *node_key, 470 471 int level, u64 bytenr) 471 472 { ··· 500 499 501 500 /* Breadth-first search to build backref cache */ 502 501 do { 503 - ret = btrfs_backref_add_tree_node(cache, path, iter, node_key, 504 - cur); 502 + ret = btrfs_backref_add_tree_node(trans, cache, path, iter, 503 + node_key, cur); 505 504 if (ret < 0) { 506 505 err = ret; 507 506 goto out; ··· 2804 2803 2805 2804 /* Do tree relocation */ 2806 2805 rbtree_postorder_for_each_entry_safe(block, next, blocks, rb_node) { 2807 - node = build_backref_tree(rc, &block->key, 2806 + node = build_backref_tree(trans, rc, &block->key, 2808 2807 block->level, block->bytenr); 2809 2808 if (IS_ERR(node)) { 2810 2809 err = PTR_ERR(node);