From 39d3cd97c2f9c5872c36854bd9b936d11fa33bb6 Mon Sep 17 00:00:00 2001 From: Mike Fleetwood Date: Wed, 19 Sep 2018 15:31:46 +0100 Subject: [PATCH] Disallow resizing btrfs if any of it's mount points are read-only (#10) No other file system allows this, but btrfs allows simultaneous mounting with different read-write permission. Further, btrfs allows resizing via read-write mounts, but not via read-only mounts. # mkfs.btrfs /dev/sdb1 btrfs-progs v4.15.1 ... Filesystem size: 512.00MiB ... Number of devices: 1 Devices: ID SIZE PATH 1 512.00MiB /dev/sdb1 # mount -o ro /dev/sdb1 /mnt/1 # mount -o rw /dev/sdb1 /mnt/2 # grep sdb1 /proc/mounts /dev/sdb1 /mnt/1 btrfs ro,relatime,space_cache,subvolid=5,subvol=/ 0 0 /dev/sdb1 /mnt/2 btrfs rw,relatime,space_cache,subvolid=5,subvol=/ 0 0 # btrfs filesystem resize 1:500M /mnt/1 Resize '/mnt/1' of '1:500M' ERROR: unable to resize '/mnt/1': Read-only file system # echo $? 1 # btrfs file system resize 1:500M /mnt/2 Resize '/mnt/2' of '1:500M' # echo $? 0 # btrfs filesystem show /dev/sdb1 Label: none uuid: 74ccd37a-e665-4f25-b77e-a305b8a025e9 Total devices 1 FS bytes used 128.00KiB devid 1 size 500.00MiB used 88.00MiB path /dev/sdb1 Also with the above order of the read-only mount listed in /proc/mounts first and the read-write mount second, GParted again allows a resize operational to be tried, but if fails just like before: Grow /dev/sdb1 from 512.00 MiB to 1.0 GiB (ERROR) * calibrate /dev/sdb1 (SUCCESS) * grow partition from 512.00 MiB to 1.00 GiB (SUCCESS) * grow filesystem to fill the partition (ERROR) * btrfs filesystem resize 1:max '/mnt/1' (ERROR) Resize '/mnt/1 to '1:max' ERROR: unable to resize '/mnt/1': Read-only file system What happened is that the Mount_Info module only stores single read-only flag against the mounted block device, not for each mount point, and as the first and second sdb1 lines from /proc/mounts were processed, the MountEntry became: 1st) mount_info[BS("/dev/sdb1")] -> {true , ["/mnt/1"] 2nd) mount_info[BS("/dev/sdb1")] -> {false, ["/mnt/1", "/mnt/2"] So GParted thought the file system was mounted read-write, but used the first mount point, /mnt/1, which was mounted read-only. This is a very unusual situation so unlikely to be encountered by users. Fix simply and safely by treating the mounted block device as mounted read-only if any of the mount points are mounted read-only, rather than just the last processed mount point. Closes #10 - Gparted fails to resize btrfs partition that is mounted read-only --- src/Mount_Info.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Mount_Info.cc b/src/Mount_Info.cc index 0981c5e6..09936c57 100644 --- a/src/Mount_Info.cc +++ b/src/Mount_Info.cc @@ -169,7 +169,7 @@ void Mount_Info::add_mountpoint_entry( MountMapping & map, { // Map::operator[] default constructs MountEntry for new keys (nodes). MountEntry & mountentry = map[BlockSpecial( node )]; - mountentry.readonly = readonly; + mountentry.readonly = mountentry.readonly || readonly; mountentry.mountpoints.push_back( mountpoint ); } }