[gparted] Pass devid when resizing btrfs file systems (#723842)
- From: Curtis Gedak <gedakc src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [gparted] Pass devid when resizing btrfs file systems (#723842)
- Date: Wed, 30 Jul 2014 17:34:58 +0000 (UTC)
commit 0e980a47a24b2f030252ddc6e5106a7d0b1e303b
Author: Mike Fleetwood <mike fleetwood googlemail com>
Date: Fri Apr 11 11:27:18 2014 +0100
Pass devid when resizing btrfs file systems (#723842)
GParted doesn't specify the devid when resizing a btrfs file system, so
the kernel defaults to resizing devid 1. On a multi-device btrfs this
may not be the same partition which GParted is resizing. This will
result in file system truncation and corruption. Shrinking the wrong
partition example:
1) Create a btrfs file system spanning 2 partitions:
# mkfs.btrfs /dev/sdb1 /dev/sdb2
# btrfs filesystem show /dev/sdb1
Label: none uuid: 41654265-9840-45c4-aca1-55989da358d6
Total devices 2 FS bytes used 112.00KiB
devid 1 size 2.00GiB used 437.50MiB path /dev/sdb1
devid 2 size 2.00GiB used 417.50MiB path /dev/sdb2
2) Resize /dev/sdb2 down to 1 GiB using GParted. This command was
run:
btrfs filesystem resize 1048576K /tmp/gparted-ddyGRh
which resized devid 1 (/dev/sdb1) to 1 GiB:
# btrfs filesystem show /dev/sdb1
Label: none uuid: 41654265-9840-45c4-aca1-55989da358d6
Total devices 2 FS bytes used 256.00KiB
devid 1 size 1.00GiB used 437.50MiB path /dev/sdb1
devid 2 size 2.00GiB used 417.50MiB path /dev/sdb2
but GParted instead resized /dev/sdb2 to 1 GiB:
# sfdisk -s /dev/sdb1
2097152
# sfdisk -s /dev/sdb2
1048576
Even on a single device btrfs devid 1 may no longer exist if the file
system has had the initial device removed from it. Example:
1) Create a single btrfs file system, add a second device and
remove the first:
# mkfs.btrfs /dev/sdb1
# mount /dev/sdb1 /mnt/1
# btrfs device add /dev/sdb2 /mnt/1
# btrfs device remove /dev/sdb1 /mnt/1
# umount /mnt/1
# btrfs filesystem show /dev/sdb2
Label: none uuid: 2cbf3ac3-1344-472a-a0c7-1476d23bdc9f
Total devices 1 FS bytes used 256.00KiB
devid 2 size 2.00GiB used 480.00MiB path /dev/sdb2
2) Again resize /dev/sdb2 down to 1 GiB using GParted. This
command was run:
btrfs filesystem resize 1048576K /tmp/gparted-ddyGRh
but it failed with:
ERROR: unable to resize 'tmp/gparted-lEyGaY' - No such device
A more informative error message was written to syslog:
# tail -1 /var/log/messages
Mar 12 14:15:01 localhost kernel: btrfs: resizer unable to find device 1
This is with Linux kernel 3.13.5 on Fedora 20, circa March 2014.
Fix by specifying the devid when resizing (part of) a btrfs file system.
Example command specifying devid 2:
btrfs filesystem resize 2:1048576K /tmp/1
This will always work because it is the kernel which interprets the
devid colon size parameter and has always done so since btrfs was first
added to the kernel in version 2.6.32 [1].
Reference:
[1] linux v2.6.32 fs/btrfs/ioctl.c btrfs_ioctl_resize()
https://git.kernel.org/cgit/linux/kernel/git/torvalds/linux.git/tree/fs/btrfs/ioctl.c?id=v2.6.32#n578
Bug #723842 - GParted resizes the wrong filesystem (does not pass the
devid to btrfs filesystem resize)
src/btrfs.cc | 16 +++++++++++++---
1 files changed, 13 insertions(+), 3 deletions(-)
---
diff --git a/src/btrfs.cc b/src/btrfs.cc
index 52e4480..48f6aed 100644
--- a/src/btrfs.cc
+++ b/src/btrfs.cc
@@ -291,6 +291,16 @@ bool btrfs::write_label( const Partition & partition, OperationDetail & operatio
bool btrfs::resize( const Partition & partition_new, OperationDetail & operationdetail, bool fill_partition )
{
bool success = true ;
+ Glib::ustring path = partition_new .get_path() ;
+
+ BTRFS_Device btrfs_dev = get_cache_entry( path ) ;
+ if ( btrfs_dev .devid == -1 )
+ {
+ operationdetail .add_child( OperationDetail(
+ String::ucompose( _("Failed to find devid for path %1"), path ), STATUS_ERROR
) ) ;
+ return false ;
+ }
+ Glib::ustring devid_str = Utils::num_to_str( btrfs_dev .devid ) ;
Glib::ustring mount_point ;
if ( ! partition_new .busy )
@@ -298,7 +308,7 @@ bool btrfs::resize( const Partition & partition_new, OperationDetail & operation
mount_point = mk_temp_dir( "", operationdetail ) ;
if ( mount_point .empty() )
return false ;
- success &= ! execute_command( "mount -v -t btrfs " + partition_new .get_path() + " " +
mount_point,
+ success &= ! execute_command( "mount -v -t btrfs " + path + " " + mount_point,
operationdetail, true ) ;
}
else
@@ -314,9 +324,9 @@ bool btrfs::resize( const Partition & partition_new, OperationDetail & operation
size = "max" ;
Glib::ustring cmd ;
if ( btrfs_found )
- cmd = "btrfs filesystem resize " + size + " " + mount_point ;
+ cmd = "btrfs filesystem resize " + devid_str + ":" + size + " " + mount_point ;
else
- cmd = "btrfsctl -r " + size + " " + mount_point ;
+ cmd = "btrfsctl -r " + devid_str + ":" + size + " " + mount_point ;
exit_status = execute_command( cmd, operationdetail, false ) ;
bool resize_succeeded = ( exit_status == 0 ) ;
if ( resize_to_same_size_fails )
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]