[gparted] Always use directory mount point when resizing btrfs (#193)
- From: Mike Fleetwood <mfleetwo src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [gparted] Always use directory mount point when resizing btrfs (#193)
- Date: Tue, 31 May 2022 20:57:44 +0000 (UTC)
commit 59b3fd068f22147603169f8b75b81800fa79c9b8
Author: Mike Fleetwood <mike fleetwood googlemail com>
Date: Sun May 22 09:30:24 2022 +0100
Always use directory mount point when resizing btrfs (#193)
A user received the following error when attempting to resize a mounted
btrfs file system on their NixOS distribution:
Shrink /dev/nvme0n1p3 from 933.38 GiB to 894.32 GiB (ERROR)
+ calibrate /dev/nvme0n1p3 00:00:00 (SUCCESS)
+ btrfs filesystem resize 1:937759744K '/etc/machine-id' (ERROR)
ERROR: not a directory: /etc/machine-id
ERROR: resize works on mounted filesystems and accepts only
directories as argument. Passing file containing a btrfs image
would resize the underlying filesystem instead of the image.
In the partition table section of the gparted_details /dev/nvme0n1p3 was
reported with these mount points:
/etc/machine-id, /etc/NetworkManager/system-connections,
/etc/ssh/ssh_host_ed25519_key, /etc/ssh/ssh_host_ed25519_key.pub,
/etc/ssh/ssh_host_rsa_key, /etc/ssh/ssh_host_rsa_key.pub, /home,
/nix, /nix/store, /state, /var
The user had a common configuration of NixOS which boots with an empty
tmpfs as root with a few bind mounted files and directories to provide
the needed persistent data [1][2].
Re-create an equivalent situation:
1. Create a btrfs file system and mount it:
# mkfs.btrfs /dev/sdb1
# mkdir /mnt/store
# mount /dev/sdb1 /mnt/store
2. Bind mount a file from this file system else where in the hierarchy.
The only criteria is that this mount point sorts before /mnt/store.
# echo 'Test contents' > /mnt/store/test
# touch /boot/test
# mount --bind /mnt/store/test /boot/test
The kernel reports these mount mounts:
# grep sdb1 /proc/mounts
/dev/sdb1 /mnt/store btrfs rw,seclabel,relatime,space_cache=v2,subvolid=5,subvol=/ 0 0
/dev/sdb1 /boot/test btrfs rw,seclabel,relatime,space_cache=v2,subvolid=5,subvol=/ 0 0
3. Use GParted to resize this mounted btrfs file system. It fails with
the above error.
GParted read the mount points from /proc/mounts and sorted them. (See
the end of Mount_Info::load_cache() for the sorting). When resizing the
btrfs file system GParted just used the first sorted mount point. This
was the file /etc/machine-id for the user and file /boot/test in the
re-creation, hence the error.
Fix by selecting the first directory mount point to pass to the btrfs
resize command.
[1] NixOS tmpfs as root
https://elis.nu/blog/2020/05/nixos-tmpfs-as-root/
[2] Erase your darlings
https://grahamc.com/blog/erase-your-darlings
Closes #193 - path used to resize btrfs needs to be a directory
include/Utils.h | 1 +
src/Utils.cc | 13 +++++++++++++
src/btrfs.cc | 12 +++++++++++-
3 files changed, 25 insertions(+), 1 deletion(-)
---
diff --git a/include/Utils.h b/include/Utils.h
index 477411e6..d887250e 100644
--- a/include/Utils.h
+++ b/include/Utils.h
@@ -184,6 +184,7 @@ public:
Byte_Value & fs_size, Byte_Value & fs_free,
Glib::ustring & error_message ) ;
static bool is_dev_busy(const Glib::ustring& path);
+ static const Glib::ustring& first_directory(const std::vector<Glib::ustring>& paths);
static Byte_Value floor_size( Byte_Value value, Byte_Value rounding_size ) ;
static Byte_Value ceil_size( Byte_Value value, Byte_Value rounding_size ) ;
diff --git a/src/Utils.cc b/src/Utils.cc
index f3f3b281..8089b198 100644
--- a/src/Utils.cc
+++ b/src/Utils.cc
@@ -30,6 +30,7 @@
#include <glibmm/ustring.h>
#include <glibmm/stringutils.h>
#include <glibmm/shell.h>
+#include <glibmm/fileutils.h>
#include <gtkmm/main.h>
#include <gtkmm/enums.h>
#include <gtkmm/stock.h>
@@ -943,6 +944,18 @@ bool Utils::is_dev_busy(const Glib::ustring& path)
}
+// Return the first path that is a directory, or the empty string.
+const Glib::ustring& Utils::first_directory(const std::vector<Glib::ustring>& paths)
+{
+ for (unsigned int i = 0; i < paths.size(); i++)
+ if (file_test(paths[i], Glib::FILE_TEST_IS_DIR))
+ return paths[i];
+
+ static const Glib::ustring not_found;
+ return not_found;
+}
+
+
//Round down to multiple of rounding_size
Byte_Value Utils::floor_size( Byte_Value value, Byte_Value rounding_size )
{
diff --git a/src/btrfs.cc b/src/btrfs.cc
index b465908a..99461347 100644
--- a/src/btrfs.cc
+++ b/src/btrfs.cc
@@ -306,7 +306,17 @@ bool btrfs::resize( const Partition & partition_new, OperationDetail & operation
operationdetail, EXEC_CHECK_STATUS );
}
else
- mount_point = partition_new .get_mountpoint() ;
+ {
+ mount_point = Utils::first_directory(partition_new.get_mountpoints());
+ if (mount_point.empty())
+ {
+ Glib::ustring mount_list = Glib::build_path(", ", partition_new.get_mountpoints());
+ operationdetail.add_child(OperationDetail(
+ Glib::ustring::compose(_("No directory mount point found in %1"),
mount_list),
+ STATUS_ERROR));
+ return false;
+ }
+ }
if ( success )
{
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]