Skip to content
This repository was archived by the owner on Nov 8, 2023. It is now read-only.

Commit 02c438b

Browse files
committed
Merge tag 'for-6.10-tag' of git://git.kernel.org/pub/scm/linux/kernel/git/kdave/linux
Pull more btrfs updates from David Sterba: "A few more updates, mostly stability fixes or user visible changes: - fix race in zoned mode during device replace that can lead to use-after-free - update return codes and lower message levels for quota rescan where it's causing false alerts - fix unexpected qgroup id reuse under some conditions - fix condition when looking up extent refs - add option norecovery (removed in 6.8), the intended replacements haven't been used and some aplications still rely on the old one - build warning fixes" * tag 'for-6.10-tag' of git://git.kernel.org/pub/scm/linux/kernel/git/kdave/linux: btrfs: re-introduce 'norecovery' mount option btrfs: fix end of tree detection when searching for data extent ref btrfs: scrub: initialize ret in scrub_simple_mirror() to fix compilation warning btrfs: zoned: fix use-after-free due to race with dev replace btrfs: qgroup: fix qgroup id collision across mounts btrfs: qgroup: update rescan message levels and error codes
2 parents dcb9f48 + 440861b commit 02c438b

File tree

5 files changed

+45
-12
lines changed

5 files changed

+45
-12
lines changed

fs/btrfs/extent-tree.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -477,7 +477,7 @@ static noinline int lookup_extent_data_ref(struct btrfs_trans_handle *trans,
477477
if (path->slots[0] >= nritems) {
478478
ret = btrfs_next_leaf(root, path);
479479
if (ret) {
480-
if (ret > 1)
480+
if (ret > 0)
481481
return -ENOENT;
482482
return ret;
483483
}

fs/btrfs/qgroup.c

Lines changed: 25 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -468,13 +468,33 @@ int btrfs_read_qgroup_config(struct btrfs_fs_info *fs_info)
468468
}
469469
if (!qgroup) {
470470
struct btrfs_qgroup *prealloc;
471+
struct btrfs_root *tree_root = fs_info->tree_root;
471472

472473
prealloc = kzalloc(sizeof(*prealloc), GFP_KERNEL);
473474
if (!prealloc) {
474475
ret = -ENOMEM;
475476
goto out;
476477
}
477478
qgroup = add_qgroup_rb(fs_info, prealloc, found_key.offset);
479+
/*
480+
* If a qgroup exists for a subvolume ID, it is possible
481+
* that subvolume has been deleted, in which case
482+
* re-using that ID would lead to incorrect accounting.
483+
*
484+
* Ensure that we skip any such subvol ids.
485+
*
486+
* We don't need to lock because this is only called
487+
* during mount before we start doing things like creating
488+
* subvolumes.
489+
*/
490+
if (is_fstree(qgroup->qgroupid) &&
491+
qgroup->qgroupid > tree_root->free_objectid)
492+
/*
493+
* Don't need to check against BTRFS_LAST_FREE_OBJECTID,
494+
* as it will get checked on the next call to
495+
* btrfs_get_free_objectid.
496+
*/
497+
tree_root->free_objectid = qgroup->qgroupid + 1;
478498
}
479499
ret = btrfs_sysfs_add_one_qgroup(fs_info, qgroup);
480500
if (ret < 0)
@@ -3820,14 +3840,14 @@ qgroup_rescan_init(struct btrfs_fs_info *fs_info, u64 progress_objectid,
38203840
/* we're resuming qgroup rescan at mount time */
38213841
if (!(fs_info->qgroup_flags &
38223842
BTRFS_QGROUP_STATUS_FLAG_RESCAN)) {
3823-
btrfs_warn(fs_info,
3843+
btrfs_debug(fs_info,
38243844
"qgroup rescan init failed, qgroup rescan is not queued");
38253845
ret = -EINVAL;
38263846
} else if (!(fs_info->qgroup_flags &
38273847
BTRFS_QGROUP_STATUS_FLAG_ON)) {
3828-
btrfs_warn(fs_info,
3848+
btrfs_debug(fs_info,
38293849
"qgroup rescan init failed, qgroup is not enabled");
3830-
ret = -EINVAL;
3850+
ret = -ENOTCONN;
38313851
}
38323852

38333853
if (ret)
@@ -3838,14 +3858,12 @@ qgroup_rescan_init(struct btrfs_fs_info *fs_info, u64 progress_objectid,
38383858

38393859
if (init_flags) {
38403860
if (fs_info->qgroup_flags & BTRFS_QGROUP_STATUS_FLAG_RESCAN) {
3841-
btrfs_warn(fs_info,
3842-
"qgroup rescan is already in progress");
38433861
ret = -EINPROGRESS;
38443862
} else if (!(fs_info->qgroup_flags &
38453863
BTRFS_QGROUP_STATUS_FLAG_ON)) {
3846-
btrfs_warn(fs_info,
3864+
btrfs_debug(fs_info,
38473865
"qgroup rescan init failed, qgroup is not enabled");
3848-
ret = -EINVAL;
3866+
ret = -ENOTCONN;
38493867
} else if (btrfs_qgroup_mode(fs_info) == BTRFS_QGROUP_MODE_DISABLED) {
38503868
/* Quota disable is in progress */
38513869
ret = -EBUSY;

fs/btrfs/scrub.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2100,7 +2100,7 @@ static int scrub_simple_mirror(struct scrub_ctx *sctx,
21002100
struct btrfs_fs_info *fs_info = sctx->fs_info;
21012101
const u64 logical_end = logical_start + logical_length;
21022102
u64 cur_logical = logical_start;
2103-
int ret;
2103+
int ret = 0;
21042104

21052105
/* The range must be inside the bg */
21062106
ASSERT(logical_start >= bg->start && logical_end <= bg->start + bg->length);

fs/btrfs/super.c

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -119,6 +119,7 @@ enum {
119119
Opt_thread_pool,
120120
Opt_treelog,
121121
Opt_user_subvol_rm_allowed,
122+
Opt_norecovery,
122123

123124
/* Rescue options */
124125
Opt_rescue,
@@ -245,6 +246,8 @@ static const struct fs_parameter_spec btrfs_fs_parameters[] = {
245246
__fsparam(NULL, "nologreplay", Opt_nologreplay, fs_param_deprecated, NULL),
246247
/* Deprecated, with alias rescue=usebackuproot */
247248
__fsparam(NULL, "usebackuproot", Opt_usebackuproot, fs_param_deprecated, NULL),
249+
/* For compatibility only, alias for "rescue=nologreplay". */
250+
fsparam_flag("norecovery", Opt_norecovery),
248251

249252
/* Debugging options. */
250253
fsparam_flag_no("enospc_debug", Opt_enospc_debug),
@@ -438,6 +441,11 @@ static int btrfs_parse_param(struct fs_context *fc, struct fs_parameter *param)
438441
"'nologreplay' is deprecated, use 'rescue=nologreplay' instead");
439442
btrfs_set_opt(ctx->mount_opt, NOLOGREPLAY);
440443
break;
444+
case Opt_norecovery:
445+
btrfs_info(NULL,
446+
"'norecovery' is for compatibility only, recommended to use 'rescue=nologreplay'");
447+
btrfs_set_opt(ctx->mount_opt, NOLOGREPLAY);
448+
break;
441449
case Opt_flushoncommit:
442450
if (result.negated)
443451
btrfs_clear_opt(ctx->mount_opt, FLUSHONCOMMIT);

fs/btrfs/zoned.c

Lines changed: 10 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1290,15 +1290,19 @@ static int btrfs_load_zone_info(struct btrfs_fs_info *fs_info, int zone_idx,
12901290
struct btrfs_chunk_map *map)
12911291
{
12921292
struct btrfs_dev_replace *dev_replace = &fs_info->dev_replace;
1293-
struct btrfs_device *device = map->stripes[zone_idx].dev;
1293+
struct btrfs_device *device;
12941294
int dev_replace_is_ongoing = 0;
12951295
unsigned int nofs_flag;
12961296
struct blk_zone zone;
12971297
int ret;
12981298

12991299
info->physical = map->stripes[zone_idx].physical;
13001300

1301+
down_read(&dev_replace->rwsem);
1302+
device = map->stripes[zone_idx].dev;
1303+
13011304
if (!device->bdev) {
1305+
up_read(&dev_replace->rwsem);
13021306
info->alloc_offset = WP_MISSING_DEV;
13031307
return 0;
13041308
}
@@ -1308,18 +1312,17 @@ static int btrfs_load_zone_info(struct btrfs_fs_info *fs_info, int zone_idx,
13081312
__set_bit(zone_idx, active);
13091313

13101314
if (!btrfs_dev_is_sequential(device, info->physical)) {
1315+
up_read(&dev_replace->rwsem);
13111316
info->alloc_offset = WP_CONVENTIONAL;
13121317
return 0;
13131318
}
13141319

13151320
/* This zone will be used for allocation, so mark this zone non-empty. */
13161321
btrfs_dev_clear_zone_empty(device, info->physical);
13171322

1318-
down_read(&dev_replace->rwsem);
13191323
dev_replace_is_ongoing = btrfs_dev_replace_is_ongoing(dev_replace);
13201324
if (dev_replace_is_ongoing && dev_replace->tgtdev != NULL)
13211325
btrfs_dev_clear_zone_empty(dev_replace->tgtdev, info->physical);
1322-
up_read(&dev_replace->rwsem);
13231326

13241327
/*
13251328
* The group is mapped to a sequential zone. Get the zone write pointer
@@ -1330,6 +1333,7 @@ static int btrfs_load_zone_info(struct btrfs_fs_info *fs_info, int zone_idx,
13301333
ret = btrfs_get_dev_zone(device, info->physical, &zone);
13311334
memalloc_nofs_restore(nofs_flag);
13321335
if (ret) {
1336+
up_read(&dev_replace->rwsem);
13331337
if (ret != -EIO && ret != -EOPNOTSUPP)
13341338
return ret;
13351339
info->alloc_offset = WP_MISSING_DEV;
@@ -1341,6 +1345,7 @@ static int btrfs_load_zone_info(struct btrfs_fs_info *fs_info, int zone_idx,
13411345
"zoned: unexpected conventional zone %llu on device %s (devid %llu)",
13421346
zone.start << SECTOR_SHIFT, rcu_str_deref(device->name),
13431347
device->devid);
1348+
up_read(&dev_replace->rwsem);
13441349
return -EIO;
13451350
}
13461351

@@ -1368,6 +1373,8 @@ static int btrfs_load_zone_info(struct btrfs_fs_info *fs_info, int zone_idx,
13681373
break;
13691374
}
13701375

1376+
up_read(&dev_replace->rwsem);
1377+
13711378
return 0;
13721379
}
13731380

0 commit comments

Comments
 (0)