Skip to content

Commit eb952c4

Browse files
committed
Merge tag 'for-6.12-rc2-tag' of git://git.kernel.org/pub/scm/linux/kernel/git/kdave/linux
Pull btrfs fixes from David Sterba: - update fstrim loop and add more cancellation points, fix reported delayed or blocked suspend if there's a huge chunk queued - fix error handling in recent qgroup xarray conversion - in zoned mode, fix warning printing device path without RCU protection - again fix invalid extent xarray state (6252690), lost due to refactoring * tag 'for-6.12-rc2-tag' of git://git.kernel.org/pub/scm/linux/kernel/git/kdave/linux: btrfs: fix clear_dirty and writeback ordering in submit_one_sector() btrfs: zoned: fix missing RCU locking in error message when loading zone info btrfs: fix missing error handling when adding delayed ref with qgroups enabled btrfs: add cancellation points to trim loops btrfs: split remaining space to discard in chunks
2 parents 5870963 + e761be2 commit eb952c4

File tree

7 files changed

+76
-24
lines changed

7 files changed

+76
-24
lines changed

fs/btrfs/delayed-ref.c

Lines changed: 33 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -840,6 +840,8 @@ static void init_delayed_ref_head(struct btrfs_delayed_ref_head *head_ref,
840840
* helper function to actually insert a head node into the rbtree.
841841
* this does all the dirty work in terms of maintaining the correct
842842
* overall modification count.
843+
*
844+
* Returns an error pointer in case of an error.
843845
*/
844846
static noinline struct btrfs_delayed_ref_head *
845847
add_delayed_ref_head(struct btrfs_trans_handle *trans,
@@ -862,6 +864,9 @@ add_delayed_ref_head(struct btrfs_trans_handle *trans,
862864
if (ret) {
863865
/* Clean up if insertion fails or item exists. */
864866
xa_release(&delayed_refs->dirty_extents, qrecord->bytenr);
867+
/* Caller responsible for freeing qrecord on error. */
868+
if (ret < 0)
869+
return ERR_PTR(ret);
865870
kfree(qrecord);
866871
} else {
867872
qrecord_inserted = true;
@@ -1000,27 +1005,35 @@ static int add_delayed_ref(struct btrfs_trans_handle *trans,
10001005
struct btrfs_fs_info *fs_info = trans->fs_info;
10011006
struct btrfs_delayed_ref_node *node;
10021007
struct btrfs_delayed_ref_head *head_ref;
1008+
struct btrfs_delayed_ref_head *new_head_ref;
10031009
struct btrfs_delayed_ref_root *delayed_refs;
10041010
struct btrfs_qgroup_extent_record *record = NULL;
10051011
bool qrecord_inserted;
10061012
int action = generic_ref->action;
10071013
bool merged;
1014+
int ret;
10081015

10091016
node = kmem_cache_alloc(btrfs_delayed_ref_node_cachep, GFP_NOFS);
10101017
if (!node)
10111018
return -ENOMEM;
10121019

10131020
head_ref = kmem_cache_alloc(btrfs_delayed_ref_head_cachep, GFP_NOFS);
1014-
if (!head_ref)
1021+
if (!head_ref) {
1022+
ret = -ENOMEM;
10151023
goto free_node;
1024+
}
10161025

10171026
if (btrfs_qgroup_full_accounting(fs_info) && !generic_ref->skip_qgroup) {
10181027
record = kzalloc(sizeof(*record), GFP_NOFS);
1019-
if (!record)
1028+
if (!record) {
1029+
ret = -ENOMEM;
10201030
goto free_head_ref;
1031+
}
10211032
if (xa_reserve(&trans->transaction->delayed_refs.dirty_extents,
1022-
generic_ref->bytenr, GFP_NOFS))
1033+
generic_ref->bytenr, GFP_NOFS)) {
1034+
ret = -ENOMEM;
10231035
goto free_record;
1036+
}
10241037
}
10251038

10261039
init_delayed_ref_common(fs_info, node, generic_ref);
@@ -1034,8 +1047,14 @@ static int add_delayed_ref(struct btrfs_trans_handle *trans,
10341047
* insert both the head node and the new ref without dropping
10351048
* the spin lock
10361049
*/
1037-
head_ref = add_delayed_ref_head(trans, head_ref, record,
1038-
action, &qrecord_inserted);
1050+
new_head_ref = add_delayed_ref_head(trans, head_ref, record,
1051+
action, &qrecord_inserted);
1052+
if (IS_ERR(new_head_ref)) {
1053+
spin_unlock(&delayed_refs->lock);
1054+
ret = PTR_ERR(new_head_ref);
1055+
goto free_record;
1056+
}
1057+
head_ref = new_head_ref;
10391058

10401059
merged = insert_delayed_ref(trans, head_ref, node);
10411060
spin_unlock(&delayed_refs->lock);
@@ -1063,7 +1082,7 @@ static int add_delayed_ref(struct btrfs_trans_handle *trans,
10631082
kmem_cache_free(btrfs_delayed_ref_head_cachep, head_ref);
10641083
free_node:
10651084
kmem_cache_free(btrfs_delayed_ref_node_cachep, node);
1066-
return -ENOMEM;
1085+
return ret;
10671086
}
10681087

10691088
/*
@@ -1094,6 +1113,7 @@ int btrfs_add_delayed_extent_op(struct btrfs_trans_handle *trans,
10941113
struct btrfs_delayed_extent_op *extent_op)
10951114
{
10961115
struct btrfs_delayed_ref_head *head_ref;
1116+
struct btrfs_delayed_ref_head *head_ref_ret;
10971117
struct btrfs_delayed_ref_root *delayed_refs;
10981118
struct btrfs_ref generic_ref = {
10991119
.type = BTRFS_REF_METADATA,
@@ -1113,11 +1133,15 @@ int btrfs_add_delayed_extent_op(struct btrfs_trans_handle *trans,
11131133
delayed_refs = &trans->transaction->delayed_refs;
11141134
spin_lock(&delayed_refs->lock);
11151135

1116-
add_delayed_ref_head(trans, head_ref, NULL, BTRFS_UPDATE_DELAYED_HEAD,
1117-
NULL);
1118-
1136+
head_ref_ret = add_delayed_ref_head(trans, head_ref, NULL,
1137+
BTRFS_UPDATE_DELAYED_HEAD, NULL);
11191138
spin_unlock(&delayed_refs->lock);
11201139

1140+
if (IS_ERR(head_ref_ret)) {
1141+
kmem_cache_free(btrfs_delayed_ref_head_cachep, head_ref);
1142+
return PTR_ERR(head_ref_ret);
1143+
}
1144+
11211145
/*
11221146
* Need to update the delayed_refs_rsv with any changes we may have
11231147
* made.

fs/btrfs/extent-tree.c

Lines changed: 21 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1300,13 +1300,29 @@ static int btrfs_issue_discard(struct block_device *bdev, u64 start, u64 len,
13001300
bytes_left = end - start;
13011301
}
13021302

1303-
if (bytes_left) {
1303+
while (bytes_left) {
1304+
u64 bytes_to_discard = min(BTRFS_MAX_DISCARD_CHUNK_SIZE, bytes_left);
1305+
13041306
ret = blkdev_issue_discard(bdev, start >> SECTOR_SHIFT,
1305-
bytes_left >> SECTOR_SHIFT,
1307+
bytes_to_discard >> SECTOR_SHIFT,
13061308
GFP_NOFS);
1307-
if (!ret)
1308-
*discarded_bytes += bytes_left;
1309+
1310+
if (ret) {
1311+
if (ret != -EOPNOTSUPP)
1312+
break;
1313+
continue;
1314+
}
1315+
1316+
start += bytes_to_discard;
1317+
bytes_left -= bytes_to_discard;
1318+
*discarded_bytes += bytes_to_discard;
1319+
1320+
if (btrfs_trim_interrupted()) {
1321+
ret = -ERESTARTSYS;
1322+
break;
1323+
}
13091324
}
1325+
13101326
return ret;
13111327
}
13121328

@@ -6459,7 +6475,7 @@ static int btrfs_trim_free_extents(struct btrfs_device *device, u64 *trimmed)
64596475
start += len;
64606476
*trimmed += bytes;
64616477

6462-
if (fatal_signal_pending(current)) {
6478+
if (btrfs_trim_interrupted()) {
64636479
ret = -ERESTARTSYS;
64646480
break;
64656481
}

fs/btrfs/extent_io.c

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1306,6 +1306,13 @@ static int submit_one_sector(struct btrfs_inode *inode,
13061306
free_extent_map(em);
13071307
em = NULL;
13081308

1309+
/*
1310+
* Although the PageDirty bit is cleared before entering this
1311+
* function, subpage dirty bit is not cleared.
1312+
* So clear subpage dirty bit here so next time we won't submit
1313+
* a folio for a range already written to disk.
1314+
*/
1315+
btrfs_folio_clear_dirty(fs_info, folio, filepos, sectorsize);
13091316
btrfs_set_range_writeback(inode, filepos, filepos + sectorsize - 1);
13101317
/*
13111318
* Above call should set the whole folio with writeback flag, even
@@ -1315,13 +1322,6 @@ static int submit_one_sector(struct btrfs_inode *inode,
13151322
*/
13161323
ASSERT(folio_test_writeback(folio));
13171324

1318-
/*
1319-
* Although the PageDirty bit is cleared before entering this
1320-
* function, subpage dirty bit is not cleared.
1321-
* So clear subpage dirty bit here so next time we won't submit
1322-
* folio for range already written to disk.
1323-
*/
1324-
btrfs_folio_clear_dirty(fs_info, folio, filepos, sectorsize);
13251325
submit_extent_folio(bio_ctrl, disk_bytenr, folio,
13261326
sectorsize, filepos - folio_pos(folio));
13271327
return 0;

fs/btrfs/free-space-cache.c

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3809,7 +3809,7 @@ static int trim_no_bitmap(struct btrfs_block_group *block_group,
38093809
if (async && *total_trimmed)
38103810
break;
38113811

3812-
if (fatal_signal_pending(current)) {
3812+
if (btrfs_trim_interrupted()) {
38133813
ret = -ERESTARTSYS;
38143814
break;
38153815
}
@@ -4000,7 +4000,7 @@ static int trim_bitmaps(struct btrfs_block_group *block_group,
40004000
}
40014001
block_group->discard_cursor = start;
40024002

4003-
if (fatal_signal_pending(current)) {
4003+
if (btrfs_trim_interrupted()) {
40044004
if (start != offset)
40054005
reset_trimming_bitmap(ctl, offset);
40064006
ret = -ERESTARTSYS;

fs/btrfs/free-space-cache.h

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@
1010
#include <linux/list.h>
1111
#include <linux/spinlock.h>
1212
#include <linux/mutex.h>
13+
#include <linux/freezer.h>
1314
#include "fs.h"
1415

1516
struct inode;
@@ -56,6 +57,11 @@ static inline bool btrfs_free_space_trimming_bitmap(
5657
return (info->trim_state == BTRFS_TRIM_STATE_TRIMMING);
5758
}
5859

60+
static inline bool btrfs_trim_interrupted(void)
61+
{
62+
return fatal_signal_pending(current) || freezing(current);
63+
}
64+
5965
/*
6066
* Deltas are an effective way to populate global statistics. Give macro names
6167
* to make it clear what we're doing. An example is discard_extents in

fs/btrfs/volumes.h

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,12 @@ struct btrfs_zoned_device_info;
3030

3131
#define BTRFS_MAX_DATA_CHUNK_SIZE (10ULL * SZ_1G)
3232

33+
/*
34+
* Arbitratry maximum size of one discard request to limit potentially long time
35+
* spent in blkdev_issue_discard().
36+
*/
37+
#define BTRFS_MAX_DISCARD_CHUNK_SIZE (SZ_1G)
38+
3339
extern struct mutex uuid_mutex;
3440

3541
#define BTRFS_STRIPE_LEN SZ_64K

fs/btrfs/zoned.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1340,7 +1340,7 @@ static int btrfs_load_zone_info(struct btrfs_fs_info *fs_info, int zone_idx,
13401340
switch (zone.cond) {
13411341
case BLK_ZONE_COND_OFFLINE:
13421342
case BLK_ZONE_COND_READONLY:
1343-
btrfs_err(fs_info,
1343+
btrfs_err_in_rcu(fs_info,
13441344
"zoned: offline/readonly zone %llu on device %s (devid %llu)",
13451345
(info->physical >> device->zone_info->zone_size_shift),
13461346
rcu_str_deref(device->name), device->devid);

0 commit comments

Comments
 (0)