From 86313891a6b4f465c0fe875d78b6e8c261c5ae21 Mon Sep 17 00:00:00 2001 From: "Richard W.M. Jones" Date: Thu, 15 May 2025 21:18:14 +0100 Subject: [PATCH] New API: Replace btrfs-fsck with btrfs-scrub-full The old btrfs-fsck API used "btrfs check" which appears to be broken or deprecated. The real tool you should use is "btrfs scrub". We have already implemented that API, but it is very awkward to use from libguestfs. In particular there's no existing way to run the scrub and wait for it to finish. Fix this by deprecating btrfs-fsck. Implement a new API btrfs-scrub-full which runs btrfs scrub in the foreground, waits for it to finish, and handles errors. It's much more like fsck tools in other filesystems. Thanks: Eric Sandeen Fixes: https://issues.redhat.com/browse/RHEL-91936 --- daemon/btrfs.c | 41 ++++++++++++++++++++++++++++ docs/guestfs-release-notes-1.56.pod | 3 ++ generator/actions_core.ml | 29 ++++++++++---------- generator/actions_core_deprecated.ml | 15 ++++++++++ generator/proc_nr.ml | 1 + gobject/Makefile.inc | 2 ++ lib/MAX_PROC_NR | 2 +- 7 files changed, 78 insertions(+), 15 deletions(-) diff --git a/daemon/btrfs.c b/daemon/btrfs.c index bfd19a845..4b6059621 100644 --- a/daemon/btrfs.c +++ b/daemon/btrfs.c @@ -1450,6 +1450,47 @@ do_btrfs_scrub_resume (const char *path) return 0; } +/* Takes optional arguments, consult optargs_bitmask. */ +int +do_btrfs_scrub_full (const char *path, int readonly) +{ + const size_t MAX_ARGS = 64; + const char *argv[MAX_ARGS]; + size_t i = 0; + CLEANUP_FREE char *path_buf = NULL; + CLEANUP_FREE char *out = NULL, *err = NULL; + int r; + + path_buf = sysroot_path (path); + if (path_buf == NULL) { + reply_with_perror ("malloc"); + return -1; + } + + ADD_ARG (argv, i, "btrfs"); + ADD_ARG (argv, i, "scrub"); + ADD_ARG (argv, i, "start"); + ADD_ARG (argv, i, "-B"); /* foreground */ + + /* Optional arguments. */ + if ((optargs_bitmask & GUESTFS_BTRFS_SCRUB_FULL_READONLY_BITMASK) && + readonly) + ADD_ARG (argv, i, "-r"); + + ADD_ARG (argv, i, path_buf); + ADD_ARG (argv, i, NULL); + + r = commandvf (&out, &err, + COMMAND_FLAG_FOLD_STDOUT_ON_STDERR, + argv); + if (r == -1) { + reply_with_error ("%s: %s", path, err); + return -1; + } + + return 0; +} + int do_btrfs_balance_pause (const char *path) { diff --git a/docs/guestfs-release-notes-1.56.pod b/docs/guestfs-release-notes-1.56.pod index bab14c139..5005837d2 100644 --- a/docs/guestfs-release-notes-1.56.pod +++ b/docs/guestfs-release-notes-1.56.pod @@ -26,6 +26,9 @@ New C and C APIs which allow you to capture output from guest commands that generate more output than the protocol limit allows. +New C API which runs a full Btrfs scrub, +synchronously. It works more like fsck for other filesystems. + The C API has been modified to work around several issues in upstream and RHEL 9 kernels related to XFS support (Eric Sandeen, Dave Chinner). diff --git a/generator/actions_core.ml b/generator/actions_core.ml index 53fa129f5..2cb8cc430 100644 --- a/generator/actions_core.ml +++ b/generator/actions_core.ml @@ -7344,20 +7344,6 @@ If C is an empty list, this does nothing." }; Enable or disable the seeding feature of a device that contains a btrfs filesystem." }; - { defaults with - name = "btrfs_fsck"; added = (1, 17, 43); - style = RErr, [String (Device, "device")], [OInt64 "superblock"; OBool "repair"]; - optional = Some "btrfs"; - tests = [ - InitPartition, Always, TestRun ( - [["mkfs_btrfs"; "/dev/sda1"; ""; ""; "NOARG"; ""; "NOARG"; "NOARG"; ""; ""]; - ["btrfs_fsck"; "/dev/sda1"; ""; ""]]), [] - ]; - shortdesc = "check a btrfs filesystem"; - longdesc = "\ -Used to check a btrfs filesystem, C is the device file where the -filesystem is stored." }; - { defaults with name = "filesystem_available"; added = (1, 19, 5); style = RBool "fsavail", [String (PlainString, "filesystem")], []; @@ -9082,6 +9068,21 @@ Show the status of a running or paused balance on a btrfs filesystem." }; longdesc = "\ Show status of running or finished scrub on a btrfs filesystem." }; + { defaults with + name = "btrfs_scrub_full"; added = (1, 55, 12); + style = RErr, [String (Pathname, "path")], [OBool "readonly"]; + optional = Some "btrfs"; camel_name = "BTRFSScrubFull"; + tests = [ + InitPartition, Always, TestRun ( + [["mkfs_btrfs"; "/dev/sda1"; ""; ""; "NOARG"; ""; "NOARG"; "NOARG"; ""; ""]; + ["mount"; "/dev/sda1"; "/"]; + ["btrfs_scrub_full"; "/"; "false"]]), []; + ]; + shortdesc = "run a full scrub on a btrfs filesystem"; + longdesc = "\ +Run a full scrub on a btrfs filesystem and wait for it to finish. +If the filesystem has errors this will return an error." }; + { defaults with name = "btrfstune_seeding"; added = (1, 29, 29); style = RErr, [String (Device, "device"); Bool "seeding"], []; diff --git a/generator/actions_core_deprecated.ml b/generator/actions_core_deprecated.ml index 258b9b279..9d4b29f9d 100644 --- a/generator/actions_core_deprecated.ml +++ b/generator/actions_core_deprecated.ml @@ -927,4 +927,19 @@ This call does nothing and returns an error." }; longdesc = "\ This call does nothing and returns an error." }; + { defaults with + name = "btrfs_fsck"; added = (1, 17, 43); + style = RErr, [String (Device, "device")], [OInt64 "superblock"; OBool "repair"]; + optional = Some "btrfs"; + deprecated_by = Replaced_by "btrfs_scrub_full"; + tests = [ + InitPartition, Always, TestRun ( + [["mkfs_btrfs"; "/dev/sda1"; ""; ""; "NOARG"; ""; "NOARG"; "NOARG"; ""; ""]; + ["btrfs_fsck"; "/dev/sda1"; ""; ""]]), [] + ]; + shortdesc = "check a btrfs filesystem"; + longdesc = "\ +Used to check a btrfs filesystem, C is the device file where the +filesystem is stored." }; + ] diff --git a/generator/proc_nr.ml b/generator/proc_nr.ml index db6ba0974..63cd72a3c 100644 --- a/generator/proc_nr.ml +++ b/generator/proc_nr.ml @@ -520,6 +520,7 @@ let proc_nr = [ 515, "findfs_partlabel"; 516, "command_out"; 517, "sh_out"; +518, "btrfs_scrub_full"; ] (* End of list. If adding a new entry, add it at the end of the list diff --git a/gobject/Makefile.inc b/gobject/Makefile.inc index b5517fd08..b54245977 100644 --- a/gobject/Makefile.inc +++ b/gobject/Makefile.inc @@ -59,6 +59,7 @@ guestfs_gobject_headers= \ include/guestfs-gobject/optargs-btrfs_filesystem_resize.h \ include/guestfs-gobject/optargs-btrfs_fsck.h \ include/guestfs-gobject/optargs-btrfs_image.h \ + include/guestfs-gobject/optargs-btrfs_scrub_full.h \ include/guestfs-gobject/optargs-btrfs_subvolume_create.h \ include/guestfs-gobject/optargs-btrfs_subvolume_snapshot.h \ include/guestfs-gobject/optargs-compress_device_out.h \ @@ -153,6 +154,7 @@ guestfs_gobject_sources= \ src/optargs-btrfs_filesystem_resize.c \ src/optargs-btrfs_fsck.c \ src/optargs-btrfs_image.c \ + src/optargs-btrfs_scrub_full.c \ src/optargs-btrfs_subvolume_create.c \ src/optargs-btrfs_subvolume_snapshot.c \ src/optargs-compress_device_out.c \ diff --git a/lib/MAX_PROC_NR b/lib/MAX_PROC_NR index ac953cd01..9a26b94d0 100644 --- a/lib/MAX_PROC_NR +++ b/lib/MAX_PROC_NR @@ -1 +1 @@ -517 +518