Skip to content

Commit 2761ece

Browse files
naotakdave
authored andcommitted
btrfs: introduce offload_csum_mode to tweak checksum offloading behavior
We disable offloading checksum to workqueues and do it synchronously when the checksum algorithm is fast. However, as reported in the link below, RAID0 with multiple devices may suffer from the sync checksum, because "fast checksum" is still not fast enough to catch up with RAID0 writing. We don't have an effective way to determine whether to offload or not, for now add a sysfs knob so this can be debugged. This is intentionally under CONFIG_BTRFS_DEBUG so ti's not exposed to users as it may be removed in the future agin. Introduce fs_devices->offload_csum_mode, so that a btrfs developer can change the behavior by writing to /sys/fs/btrfs/<uuid>/offload_csum. The default is "auto" which is the same as the previous behavior. Or, you can set "on" or "off" (or "y" or "n" whatever kstrtobool() accepts) to always/never offload checksum. More benchmark need to be collected with this knob to implement a proper criteria to enable/disable checksum offloading. Link: https://lore.kernel.org/linux-btrfs/20230731152223.4EFB.409509F4@e16-tech.com/ Link: https://lore.kernel.org/linux-btrfs/p3vo3g7pqn664mhmdhlotu5dzcna6vjtcoc2hb2lsgo2fwct7k@xzaxclba5tae/ Reviewed-by: Johannes Thumshirn <johannes.thumshirn@wdc.com> Signed-off-by: Naohiro Aota <naohiro.aota@wdc.com> Reviewed-by: David Sterba <dsterba@suse.com> Signed-off-by: David Sterba <dsterba@suse.com>
1 parent b2324e0 commit 2761ece

3 files changed

Lines changed: 81 additions & 1 deletion

File tree

fs/btrfs/bio.c

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -608,8 +608,20 @@ static void run_one_async_done(struct btrfs_work *work, bool do_free)
608608

609609
static bool should_async_write(struct btrfs_bio *bbio)
610610
{
611+
bool auto_csum_mode = true;
612+
613+
#ifdef CONFIG_BTRFS_DEBUG
614+
struct btrfs_fs_devices *fs_devices = bbio->fs_info->fs_devices;
615+
enum btrfs_offload_csum_mode csum_mode = READ_ONCE(fs_devices->offload_csum_mode);
616+
617+
if (csum_mode == BTRFS_OFFLOAD_CSUM_FORCE_OFF)
618+
return false;
619+
620+
auto_csum_mode = (csum_mode == BTRFS_OFFLOAD_CSUM_AUTO);
621+
#endif
622+
611623
/* Submit synchronously if the checksum implementation is fast. */
612-
if (test_bit(BTRFS_FS_CSUM_IMPL_FAST, &bbio->fs_info->flags))
624+
if (auto_csum_mode && test_bit(BTRFS_FS_CSUM_IMPL_FAST, &bbio->fs_info->flags))
613625
return false;
614626

615627
/*

fs/btrfs/sysfs.c

Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1307,6 +1307,47 @@ static ssize_t btrfs_bg_reclaim_threshold_store(struct kobject *kobj,
13071307
BTRFS_ATTR_RW(, bg_reclaim_threshold, btrfs_bg_reclaim_threshold_show,
13081308
btrfs_bg_reclaim_threshold_store);
13091309

1310+
#ifdef CONFIG_BTRFS_DEBUG
1311+
static ssize_t btrfs_offload_csum_show(struct kobject *kobj,
1312+
struct kobj_attribute *a, char *buf)
1313+
{
1314+
struct btrfs_fs_devices *fs_devices = to_fs_devs(kobj);
1315+
1316+
switch (READ_ONCE(fs_devices->offload_csum_mode)) {
1317+
case BTRFS_OFFLOAD_CSUM_AUTO:
1318+
return sysfs_emit(buf, "auto\n");
1319+
case BTRFS_OFFLOAD_CSUM_FORCE_ON:
1320+
return sysfs_emit(buf, "1\n");
1321+
case BTRFS_OFFLOAD_CSUM_FORCE_OFF:
1322+
return sysfs_emit(buf, "0\n");
1323+
default:
1324+
WARN_ON(1);
1325+
return -EINVAL;
1326+
}
1327+
}
1328+
1329+
static ssize_t btrfs_offload_csum_store(struct kobject *kobj,
1330+
struct kobj_attribute *a, const char *buf,
1331+
size_t len)
1332+
{
1333+
struct btrfs_fs_devices *fs_devices = to_fs_devs(kobj);
1334+
int ret;
1335+
bool val;
1336+
1337+
ret = kstrtobool(buf, &val);
1338+
if (ret == 0)
1339+
WRITE_ONCE(fs_devices->offload_csum_mode,
1340+
val ? BTRFS_OFFLOAD_CSUM_FORCE_ON : BTRFS_OFFLOAD_CSUM_FORCE_OFF);
1341+
else if (ret == -EINVAL && sysfs_streq(buf, "auto"))
1342+
WRITE_ONCE(fs_devices->offload_csum_mode, BTRFS_OFFLOAD_CSUM_AUTO);
1343+
else
1344+
return -EINVAL;
1345+
1346+
return len;
1347+
}
1348+
BTRFS_ATTR_RW(, offload_csum, btrfs_offload_csum_show, btrfs_offload_csum_store);
1349+
#endif
1350+
13101351
/*
13111352
* Per-filesystem information and stats.
13121353
*
@@ -1326,6 +1367,9 @@ static const struct attribute *btrfs_attrs[] = {
13261367
BTRFS_ATTR_PTR(, bg_reclaim_threshold),
13271368
BTRFS_ATTR_PTR(, commit_stats),
13281369
BTRFS_ATTR_PTR(, temp_fsid),
1370+
#ifdef CONFIG_BTRFS_DEBUG
1371+
BTRFS_ATTR_PTR(, offload_csum),
1372+
#endif
13291373
NULL,
13301374
};
13311375

fs/btrfs/volumes.h

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -291,6 +291,25 @@ enum btrfs_read_policy {
291291
BTRFS_NR_READ_POLICY,
292292
};
293293

294+
#ifdef CONFIG_BTRFS_DEBUG
295+
/*
296+
* Checksum mode - offload it to workqueues or do it synchronously in
297+
* btrfs_submit_chunk().
298+
*/
299+
enum btrfs_offload_csum_mode {
300+
/*
301+
* Choose offloading checksum or do it synchronously automatically.
302+
* Do it synchronously if the checksum is fast, or offload to workqueues
303+
* otherwise.
304+
*/
305+
BTRFS_OFFLOAD_CSUM_AUTO,
306+
/* Always offload checksum to workqueues. */
307+
BTRFS_OFFLOAD_CSUM_FORCE_ON,
308+
/* Never offload checksum to workqueues. */
309+
BTRFS_OFFLOAD_CSUM_FORCE_OFF,
310+
};
311+
#endif
312+
294313
struct btrfs_fs_devices {
295314
u8 fsid[BTRFS_FSID_SIZE]; /* FS specific uuid */
296315

@@ -395,6 +414,11 @@ struct btrfs_fs_devices {
395414

396415
/* Policy used to read the mirrored stripes. */
397416
enum btrfs_read_policy read_policy;
417+
418+
#ifdef CONFIG_BTRFS_DEBUG
419+
/* Checksum mode - offload it or do it synchronously. */
420+
enum btrfs_offload_csum_mode offload_csum_mode;
421+
#endif
398422
};
399423

400424
#define BTRFS_MAX_DEVS(info) ((BTRFS_MAX_ITEM_SIZE(info) \

0 commit comments

Comments
 (0)