Skip to content

Commit a785fd2

Browse files
committed
Merge tag 'for-6.5-rc5-tag' of git://git.kernel.org/pub/scm/linux/kernel/git/kdave/linux
Pull btrfs fixes from David Sterba: "More fixes, some of them going back to older releases and there are fixes for hangs in stress tests regarding space caching: - fixes and progress tracking for hangs in free space caching, found by test generic/475 - writeback fixes, write pages in integrity mode and skip writing pages that have been written meanwhile - properly clear end of extent range after an error - relocation fixes: - fix race betwen qgroup tree creation and relocation - detect and report invalid reloc roots" * tag 'for-6.5-rc5-tag' of git://git.kernel.org/pub/scm/linux/kernel/git/kdave/linux: btrfs: set cache_block_group_error if we find an error btrfs: reject invalid reloc tree root keys with stack dump btrfs: exit gracefully if reloc roots don't match btrfs: avoid race between qgroup tree creation and relocation btrfs: properly clear end of the unreserved range in cow_file_range btrfs: don't wait for writeback on clean pages in extent_write_cache_pages btrfs: don't stop integrity writeback too early btrfs: wait for actual caching progress during allocation
2 parents ae545c3 + 92fb94b commit a785fd2

File tree

8 files changed

+99
-20
lines changed

8 files changed

+99
-20
lines changed

fs/btrfs/block-group.c

Lines changed: 15 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -441,13 +441,23 @@ void btrfs_wait_block_group_cache_progress(struct btrfs_block_group *cache,
441441
u64 num_bytes)
442442
{
443443
struct btrfs_caching_control *caching_ctl;
444+
int progress;
444445

445446
caching_ctl = btrfs_get_caching_control(cache);
446447
if (!caching_ctl)
447448
return;
448449

450+
/*
451+
* We've already failed to allocate from this block group, so even if
452+
* there's enough space in the block group it isn't contiguous enough to
453+
* allow for an allocation, so wait for at least the next wakeup tick,
454+
* or for the thing to be done.
455+
*/
456+
progress = atomic_read(&caching_ctl->progress);
457+
449458
wait_event(caching_ctl->wait, btrfs_block_group_done(cache) ||
450-
(cache->free_space_ctl->free_space >= num_bytes));
459+
(progress != atomic_read(&caching_ctl->progress) &&
460+
(cache->free_space_ctl->free_space >= num_bytes)));
451461

452462
btrfs_put_caching_control(caching_ctl);
453463
}
@@ -802,8 +812,10 @@ static int load_extent_tree_free(struct btrfs_caching_control *caching_ctl)
802812

803813
if (total_found > CACHING_CTL_WAKE_UP) {
804814
total_found = 0;
805-
if (wakeup)
815+
if (wakeup) {
816+
atomic_inc(&caching_ctl->progress);
806817
wake_up(&caching_ctl->wait);
818+
}
807819
}
808820
}
809821
path->slots[0]++;
@@ -910,6 +922,7 @@ int btrfs_cache_block_group(struct btrfs_block_group *cache, bool wait)
910922
init_waitqueue_head(&caching_ctl->wait);
911923
caching_ctl->block_group = cache;
912924
refcount_set(&caching_ctl->count, 2);
925+
atomic_set(&caching_ctl->progress, 0);
913926
btrfs_init_work(&caching_ctl->work, caching_thread, NULL, NULL);
914927

915928
spin_lock(&cache->lock);

fs/btrfs/block-group.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -90,6 +90,8 @@ struct btrfs_caching_control {
9090
wait_queue_head_t wait;
9191
struct btrfs_work work;
9292
struct btrfs_block_group *block_group;
93+
/* Track progress of caching during allocation. */
94+
atomic_t progress;
9395
refcount_t count;
9496
};
9597

fs/btrfs/disk-io.c

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1103,7 +1103,8 @@ static int btrfs_init_fs_root(struct btrfs_root *root, dev_t anon_dev)
11031103
btrfs_drew_lock_init(&root->snapshot_lock);
11041104

11051105
if (root->root_key.objectid != BTRFS_TREE_LOG_OBJECTID &&
1106-
!btrfs_is_data_reloc_root(root)) {
1106+
!btrfs_is_data_reloc_root(root) &&
1107+
is_fstree(root->root_key.objectid)) {
11071108
set_bit(BTRFS_ROOT_SHAREABLE, &root->state);
11081109
btrfs_check_and_init_root_item(&root->root_item);
11091110
}
@@ -1300,6 +1301,16 @@ static struct btrfs_root *btrfs_get_root_ref(struct btrfs_fs_info *fs_info,
13001301
root = btrfs_get_global_root(fs_info, objectid);
13011302
if (root)
13021303
return root;
1304+
1305+
/*
1306+
* If we're called for non-subvolume trees, and above function didn't
1307+
* find one, do not try to read it from disk.
1308+
*
1309+
* This is namely for free-space-tree and quota tree, which can change
1310+
* at runtime and should only be grabbed from fs_info.
1311+
*/
1312+
if (!is_fstree(objectid) && objectid != BTRFS_DATA_RELOC_TREE_OBJECTID)
1313+
return ERR_PTR(-ENOENT);
13031314
again:
13041315
root = btrfs_lookup_fs_root(fs_info, objectid);
13051316
if (root) {

fs/btrfs/extent-tree.c

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4310,8 +4310,11 @@ static noinline int find_free_extent(struct btrfs_root *root,
43104310
ret = 0;
43114311
}
43124312

4313-
if (unlikely(block_group->cached == BTRFS_CACHE_ERROR))
4313+
if (unlikely(block_group->cached == BTRFS_CACHE_ERROR)) {
4314+
if (!cache_block_group_error)
4315+
cache_block_group_error = -EIO;
43144316
goto loop;
4317+
}
43154318

43164319
if (!find_free_extent_check_size_class(ffe_ctl, block_group))
43174320
goto loop;

fs/btrfs/extent_io.c

Lines changed: 10 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2145,6 +2145,12 @@ static int extent_write_cache_pages(struct address_space *mapping,
21452145
continue;
21462146
}
21472147

2148+
if (!folio_test_dirty(folio)) {
2149+
/* Someone wrote it for us. */
2150+
folio_unlock(folio);
2151+
continue;
2152+
}
2153+
21482154
if (wbc->sync_mode != WB_SYNC_NONE) {
21492155
if (folio_test_writeback(folio))
21502156
submit_write_bio(bio_ctrl, 0);
@@ -2164,11 +2170,12 @@ static int extent_write_cache_pages(struct address_space *mapping,
21642170
}
21652171

21662172
/*
2167-
* the filesystem may choose to bump up nr_to_write.
2173+
* The filesystem may choose to bump up nr_to_write.
21682174
* We have to make sure to honor the new nr_to_write
2169-
* at any time
2175+
* at any time.
21702176
*/
2171-
nr_to_write_done = wbc->nr_to_write <= 0;
2177+
nr_to_write_done = (wbc->sync_mode == WB_SYNC_NONE &&
2178+
wbc->nr_to_write <= 0);
21722179
}
21732180
folio_batch_release(&fbatch);
21742181
cond_resched();

fs/btrfs/inode.c

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1654,8 +1654,6 @@ static noinline int cow_file_range(struct btrfs_inode *inode,
16541654
clear_bits,
16551655
page_ops);
16561656
start += cur_alloc_size;
1657-
if (start >= end)
1658-
return ret;
16591657
}
16601658

16611659
/*
@@ -1664,9 +1662,11 @@ static noinline int cow_file_range(struct btrfs_inode *inode,
16641662
* space_info's bytes_may_use counter, reserved in
16651663
* btrfs_check_data_free_space().
16661664
*/
1667-
extent_clear_unlock_delalloc(inode, start, end, locked_page,
1668-
clear_bits | EXTENT_CLEAR_DATA_RESV,
1669-
page_ops);
1665+
if (start < end) {
1666+
clear_bits |= EXTENT_CLEAR_DATA_RESV;
1667+
extent_clear_unlock_delalloc(inode, start, end, locked_page,
1668+
clear_bits, page_ops);
1669+
}
16701670
return ret;
16711671
}
16721672

fs/btrfs/relocation.c

Lines changed: 37 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1916,7 +1916,39 @@ int prepare_to_merge(struct reloc_control *rc, int err)
19161916
err = PTR_ERR(root);
19171917
break;
19181918
}
1919-
ASSERT(root->reloc_root == reloc_root);
1919+
1920+
if (unlikely(root->reloc_root != reloc_root)) {
1921+
if (root->reloc_root) {
1922+
btrfs_err(fs_info,
1923+
"reloc tree mismatch, root %lld has reloc root key (%lld %u %llu) gen %llu, expect reloc root key (%lld %u %llu) gen %llu",
1924+
root->root_key.objectid,
1925+
root->reloc_root->root_key.objectid,
1926+
root->reloc_root->root_key.type,
1927+
root->reloc_root->root_key.offset,
1928+
btrfs_root_generation(
1929+
&root->reloc_root->root_item),
1930+
reloc_root->root_key.objectid,
1931+
reloc_root->root_key.type,
1932+
reloc_root->root_key.offset,
1933+
btrfs_root_generation(
1934+
&reloc_root->root_item));
1935+
} else {
1936+
btrfs_err(fs_info,
1937+
"reloc tree mismatch, root %lld has no reloc root, expect reloc root key (%lld %u %llu) gen %llu",
1938+
root->root_key.objectid,
1939+
reloc_root->root_key.objectid,
1940+
reloc_root->root_key.type,
1941+
reloc_root->root_key.offset,
1942+
btrfs_root_generation(
1943+
&reloc_root->root_item));
1944+
}
1945+
list_add(&reloc_root->root_list, &reloc_roots);
1946+
btrfs_put_root(root);
1947+
btrfs_abort_transaction(trans, -EUCLEAN);
1948+
if (!err)
1949+
err = -EUCLEAN;
1950+
break;
1951+
}
19201952

19211953
/*
19221954
* set reference count to 1, so btrfs_recover_relocation
@@ -1989,7 +2021,7 @@ void merge_reloc_roots(struct reloc_control *rc)
19892021
root = btrfs_get_fs_root(fs_info, reloc_root->root_key.offset,
19902022
false);
19912023
if (btrfs_root_refs(&reloc_root->root_item) > 0) {
1992-
if (IS_ERR(root)) {
2024+
if (WARN_ON(IS_ERR(root))) {
19932025
/*
19942026
* For recovery we read the fs roots on mount,
19952027
* and if we didn't find the root then we marked
@@ -1998,17 +2030,14 @@ void merge_reloc_roots(struct reloc_control *rc)
19982030
* memory. However there's no reason we can't
19992031
* handle the error properly here just in case.
20002032
*/
2001-
ASSERT(0);
20022033
ret = PTR_ERR(root);
20032034
goto out;
20042035
}
2005-
if (root->reloc_root != reloc_root) {
2036+
if (WARN_ON(root->reloc_root != reloc_root)) {
20062037
/*
2007-
* This is actually impossible without something
2008-
* going really wrong (like weird race condition
2009-
* or cosmic rays).
2038+
* This can happen if on-disk metadata has some
2039+
* corruption, e.g. bad reloc tree key offset.
20102040
*/
2011-
ASSERT(0);
20122041
ret = -EINVAL;
20132042
goto out;
20142043
}

fs/btrfs/tree-checker.c

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -446,6 +446,20 @@ static int check_root_key(struct extent_buffer *leaf, struct btrfs_key *key,
446446
btrfs_item_key_to_cpu(leaf, &item_key, slot);
447447
is_root_item = (item_key.type == BTRFS_ROOT_ITEM_KEY);
448448

449+
/*
450+
* Bad rootid for reloc trees.
451+
*
452+
* Reloc trees are only for subvolume trees, other trees only need
453+
* to be COWed to be relocated.
454+
*/
455+
if (unlikely(is_root_item && key->objectid == BTRFS_TREE_RELOC_OBJECTID &&
456+
!is_fstree(key->offset))) {
457+
generic_err(leaf, slot,
458+
"invalid reloc tree for root %lld, root id is not a subvolume tree",
459+
key->offset);
460+
return -EUCLEAN;
461+
}
462+
449463
/* No such tree id */
450464
if (unlikely(key->objectid == 0)) {
451465
if (is_root_item)

0 commit comments

Comments
 (0)