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
This commit is contained in:
parent
6b62b9c8da
commit
59b3fd068f
|
@ -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 ) ;
|
||||
|
||||
|
|
13
src/Utils.cc
13
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 )
|
||||
{
|
||||
|
|
12
src/btrfs.cc
12
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 )
|
||||
{
|
||||
|
|
Loading…
Reference in New Issue