gparted/src/btrfs.cc

614 lines
22 KiB
C++
Raw Normal View History

/* Copyright (C) 2009,2010 Luca Bruno <lucab@debian.org>
* Copyright (C) 2010, 2011 Curtis Gedak
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, see <http://www.gnu.org/licenses/>.
*/
#include "btrfs.h"
#include "BlockSpecial.h"
#include "FileSystem.h"
#include "Mount_Info.h"
#include "Partition.h"
Handle btrfs tools rounding of figures (#499202) The btrfs programs only provide approximations of file system sizes because they display figures using binary prefix multipliers to two decimal places of precision. E.g. 2.00GB. For partition sizes where the contained file system size rounds upwards, GParted will fail to read the file system usage and report a warning because the file system will appear to be larger than the partition. For example, create a 2047 MiB partition containing a btrfs file system and display its size. # btrfs filesystem show Label: none uuid: 92535375-5e76-4a70-896a-8d796a577993 Total devices 1 FS bytes used 28.00KB devid 1 size 2.00GB used 240.62MB path /dev/sda12 The file system size appears to be 2048 MiB, but that is larger than the partition, hence the issue GParted has. (Actually uses the btrfs devid size which is the size of the btrfs file system within the partition in question). This issue is new with the fix for Bug #499202 because it queries the file system sizes for the first time. The same issue could theoretically occur previously, but with the used figure (FS bytes used). This would have been virtually impossible to trigger because btrfs file system would have to have been greater than 99% full, but btrfs has been notorious for early reporting of file system full. The fix is that if a btrfs file system size appears larger than the partition size, but the minimum possible size which could have been rounded to the reported figure is within the partition size use the smaller partition size instead. Apply the method to the used figure too, in case the file system is 100% full. Also if the btrfs file system size appears smaller than the partition size, but the maximum possible size which could have been rounded to the reported figure is within the partition size use the larger partition size instead to avoid reporting, presumably false, unallocated space. Not applied to file system used figure. Bug 499202 - gparted does not see the difference if partition size differs from filesystem size
2012-05-30 06:41:59 -06:00
#include <ctype.h>
#include <glibmm/miscutils.h>
#include <glibmm/shell.h>
Handle btrfs tools rounding of figures (#499202) The btrfs programs only provide approximations of file system sizes because they display figures using binary prefix multipliers to two decimal places of precision. E.g. 2.00GB. For partition sizes where the contained file system size rounds upwards, GParted will fail to read the file system usage and report a warning because the file system will appear to be larger than the partition. For example, create a 2047 MiB partition containing a btrfs file system and display its size. # btrfs filesystem show Label: none uuid: 92535375-5e76-4a70-896a-8d796a577993 Total devices 1 FS bytes used 28.00KB devid 1 size 2.00GB used 240.62MB path /dev/sda12 The file system size appears to be 2048 MiB, but that is larger than the partition, hence the issue GParted has. (Actually uses the btrfs devid size which is the size of the btrfs file system within the partition in question). This issue is new with the fix for Bug #499202 because it queries the file system sizes for the first time. The same issue could theoretically occur previously, but with the used figure (FS bytes used). This would have been virtually impossible to trigger because btrfs file system would have to have been greater than 99% full, but btrfs has been notorious for early reporting of file system full. The fix is that if a btrfs file system size appears larger than the partition size, but the minimum possible size which could have been rounded to the reported figure is within the partition size use the smaller partition size instead. Apply the method to the used figure too, in case the file system is 100% full. Also if the btrfs file system size appears smaller than the partition size, but the maximum possible size which could have been rounded to the reported figure is within the partition size use the larger partition size instead to avoid reporting, presumably false, unallocated space. Not applied to file system used figure. Bug 499202 - gparted does not see the difference if partition size differs from filesystem size
2012-05-30 06:41:59 -06:00
namespace GParted
{
bool btrfs_found = false ;
// Cache of required btrfs file system device information by device
// E.g. For a single device btrfs on /dev/sda2 and a three device btrfs
// on /dev/sd[bcd]1 the cache would be as follows. (Note that
// BS(str) is short hand for constructor BlockSpecial(str)).
// btrfs_device_cache[BS("/dev/sda2")] = {devid=1, members=[BS("/dev/sda2")]}
// btrfs_device_cache[BS("/dev/sdb1")] = {devid=1, members=[BS("/dev/sdd1"), BS("/dev/sdc1"), BS("/dev/sdb1")]}
// btrfs_device_cache[BS("/dev/sdc1")] = {devid=2, members=[BS("/dev/sdd1"), BS("/dev/sdc1"), BS("/dev/sdb1")]}
// btrfs_device_cache[BS("/dev/sdd1")] = {devid=3, members=[BS("/dev/sdd1"), BS("/dev/sdc1"), BS("/dev/sdb1")]}
std::map<BlockSpecial, BTRFS_Device> btrfs_device_cache;
Detect busy status of multi-device btrfs file systems (#723842) Busy detection of file systems works by checking if the device is mounted (appears in the mount_info map). For a multi-device btrfs file system this will only report one of the devices as busy, not all of them. # btrfs filesystem show /dev/sdb1 Label: none uuid: 36eb51a2-2927-4c92-820f-b2f0b5cdae50 Total devices 2 FS bytes used 156.00KB devid 2 size 2.00GB used 512.00MB path /dev/sdb2 devid 1 size 2.00GB used 240.75MB path /dev/sdb1 # mount /dev/sdb1 /mnt/1 # grep btrfs /proc/mounts /dev/sdb1 /mnt/1 btrfs rw,seclabel,relatime,ssd,space_cache 0 0 GParted will only report /dev/sdb1 as busy, but not /dev/sdb2. Add btrfs specific is_busy() method which reports the device as busy if any of the devices in the btrfs file system are mounted. This uses a cache which maps device membership in all btrfs file systems. The cache is cleared on GParted refresh and incrementally populated as each btrfs partition is checked for busy status. WARNING: Removal of the mounting device from a btrfs file system makes it impossible to determine whether the file system is mounted or not for linux <= 3.4. This is because /proc/mounts continues to show the old device which is no longer a member of the file system. # btrfs device delete /dev/sdb1 /mnt/1 # sync # grep btrfs /proc/mounts /dev/sdb1 /mnt/1 btrfs rw,seclabel,relatime,ssd,space_cache 0 0 # btrfs filesystem show /dev/sdb1 # btrfs filesystem show /dev/sdb2 Label: none uuid: 36eb51a2-2927-4c92-820f-b2f0b5cdae50 Total devices 1 FS bytes used 28.00KB devid 2 size 2.00GB used 1.02GB path /dev/sdb2 Fixed in linux 3.5 by commit: Btrfs: implement ->show_devname https://git.kernel.org/cgit/linux/kernel/git/torvalds/linux.git/commit/?id=9c5085c147989d48dfe74194b48affc23f376650 Bug #723842 - GParted resizes the wrong filesystem (does not pass the devid to btrfs filesystem resize)
2014-02-17 15:39:34 -07:00
FS btrfs::get_filesystem_support()
{
FS fs( FS_BTRFS );
Detect busy status of multi-device btrfs file systems (#723842) Busy detection of file systems works by checking if the device is mounted (appears in the mount_info map). For a multi-device btrfs file system this will only report one of the devices as busy, not all of them. # btrfs filesystem show /dev/sdb1 Label: none uuid: 36eb51a2-2927-4c92-820f-b2f0b5cdae50 Total devices 2 FS bytes used 156.00KB devid 2 size 2.00GB used 512.00MB path /dev/sdb2 devid 1 size 2.00GB used 240.75MB path /dev/sdb1 # mount /dev/sdb1 /mnt/1 # grep btrfs /proc/mounts /dev/sdb1 /mnt/1 btrfs rw,seclabel,relatime,ssd,space_cache 0 0 GParted will only report /dev/sdb1 as busy, but not /dev/sdb2. Add btrfs specific is_busy() method which reports the device as busy if any of the devices in the btrfs file system are mounted. This uses a cache which maps device membership in all btrfs file systems. The cache is cleared on GParted refresh and incrementally populated as each btrfs partition is checked for busy status. WARNING: Removal of the mounting device from a btrfs file system makes it impossible to determine whether the file system is mounted or not for linux <= 3.4. This is because /proc/mounts continues to show the old device which is no longer a member of the file system. # btrfs device delete /dev/sdb1 /mnt/1 # sync # grep btrfs /proc/mounts /dev/sdb1 /mnt/1 btrfs rw,seclabel,relatime,ssd,space_cache 0 0 # btrfs filesystem show /dev/sdb1 # btrfs filesystem show /dev/sdb2 Label: none uuid: 36eb51a2-2927-4c92-820f-b2f0b5cdae50 Total devices 1 FS bytes used 28.00KB devid 2 size 2.00GB used 1.02GB path /dev/sdb2 Fixed in linux 3.5 by commit: Btrfs: implement ->show_devname https://git.kernel.org/cgit/linux/kernel/git/torvalds/linux.git/commit/?id=9c5085c147989d48dfe74194b48affc23f376650 Bug #723842 - GParted resizes the wrong filesystem (does not pass the devid to btrfs filesystem resize)
2014-02-17 15:39:34 -07:00
fs .busy = FS::EXTERNAL ;
if ( ! Glib::find_program_in_path( "mkfs.btrfs" ) .empty() )
{
fs.create = FS::EXTERNAL;
fs.create_with_label = FS::EXTERNAL;
}
if ( ! Glib::find_program_in_path( "btrfsck" ) .empty() )
fs.check = FS::EXTERNAL;
btrfs_found = ( ! Glib::find_program_in_path( "btrfs" ) .empty() ) ;
if ( btrfs_found )
{
//Use newer btrfs multi-tool control command. No need
// to test for filesystem show and filesystem resize
// sub-commands as they were always included.
fs.read = FS::EXTERNAL;
fs .read_label = FS::EXTERNAL ;
fs .read_uuid = FS::EXTERNAL ;
//Resizing of btrfs requires mount, umount and kernel
// support as well as btrfs filesystem resize
if ( ! Glib::find_program_in_path( "mount" ) .empty()
&& ! Glib::find_program_in_path( "umount" ) .empty()
&& fs .check
&& Utils::kernel_supports_fs( "btrfs" )
)
{
fs .grow = FS::EXTERNAL ;
if ( fs .read ) //needed to determine a minimum file system size.
fs .shrink = FS::EXTERNAL ;
}
//Test for labelling capability in btrfs command
if ( ! Utils::execute_command( "btrfs filesystem label --help", output, error, true ) )
fs .write_label = FS::EXTERNAL;
}
else
{
//Fall back to using btrfs-show and btrfsctl, which
// were depreciated October 2011
if ( ! Glib::find_program_in_path( "btrfs-show" ) .empty() )
{
fs.read = FS::EXTERNAL;
fs .read_label = FS::EXTERNAL ;
fs .read_uuid = FS::EXTERNAL ;
}
//Resizing of btrfs requires btrfsctl, mount, umount
// and kernel support
if ( ! Glib::find_program_in_path( "btrfsctl" ) .empty()
&& ! Glib::find_program_in_path( "mount" ) .empty()
&& ! Glib::find_program_in_path( "umount" ) .empty()
&& fs .check
&& Utils::kernel_supports_fs( "btrfs" )
)
{
fs .grow = FS::EXTERNAL ;
if ( fs .read ) //needed to determine a minimum file system size.
fs .shrink = FS::EXTERNAL ;
}
}
if ( ! Glib::find_program_in_path( "btrfstune" ).empty() )
{
Utils::execute_command( "btrfstune --help", output, error, true );
if ( Utils::regexp_label( output + error, "^[[:blank:]]*(-u)[[:blank:]]" ) == "-u" )
fs.write_uuid = FS::EXTERNAL;
}
if ( fs .check )
{
fs.copy = FS::GPARTED;
fs.move = FS::GPARTED;
}
Display usage for multi-device btrfs file systems (#723842) Currently GParted fails to report the usage of a multi-device btrfs file system if it is mounted or if the used space is larger than the size of an individual member device. When GParted does display usage figures it also incorrectly reports the file system wide used figure against every member device. Mounted case: statvfs() provides an FS size which is larger than any individual device so is rejected. See: GParted_Core::mounted_set_used_sectors() Utils::get_mounted_filesystem_usage() partition .set_sector_usage() Unmounted case, FS used > device size: FS used figure is larger than any individual device so free space is calculated as a negative number and rejected. See: btrfs::set_used_sectors() Btrfs has a volume manager layer within the file system which allows it to provide multiple levels of data redundancy, RAID levels, and use multiple devices both of which can be changed while the file system is mounted. To achieve this btrfs has to allocate space at two different level: (1) chunks of 256 MiB or more at the volume manager level; and (2) extents at the file data level. References: * Btrfs: Working with multiple devices https://lwn.net/Articles/577961/ * Btrfs wiki: Glossary https://btrfs.wiki.kernel.org/index.php/Glossary This makes the question of how much disk space is being used in an individual device a complicated question to answer. Further, the current btrfs tools don't provide the required information. Btrfs filesystem show only provides space usage information at the chunk level per device. At the file extent level only a single figure for the whole file system is provided. It also reports size of the data and metadata being stored, not the larger figure of the amount of space taken after redundancy is applied. So it is impossible to answer the question of how much disk space is being used in an individual device. Example output: Label: none uuid: 36eb51a2-2927-4c92-820f-b2f0b5cdae50 Total devices 2 FS bytes used 156.00KB devid 2 size 2.00GB used 512.00MB path /dev/sdb2 devid 1 size 2.00GB used 240.75MB path /dev/sdb1 Fix by guesstimating the per device used figure as the fraction of the file system wide extent usage based on chunk usage per device. Calculation: ptn fs used = total fs used * devid used / sum devid used Positives: 1) Per device used figure will correctly be between zero and allocated chunk size. Known inaccuracies: [for single and multi-device btrfs file systems] 1) Btrfs filesystem show reports file system wide file extent usage without considering redundancy applied to that data. (By default btrfs stores two copies of metadata and one copy of data). 2) At minimum size when all data has been consolidated there will be a few partly filled chunks of 256 MiB or more for data and metadata of each storage profile (RAID level). [for multi-device btrfs file systems only] 3) Data may be far from evenly distributed between the chunks on multiple devices. 4) Extents can be and are relocated to other devices within the file system when shrinking a device. Bug #723842 - GParted resizes the wrong filesystem (does not pass the devid to btrfs filesystem resize)
2014-03-29 15:12:01 -06:00
fs .online_read = FS::EXTERNAL ;
#ifdef ENABLE_ONLINE_RESIZE
if ( Utils::kernel_version_at_least( 3, 6, 0 ) )
{
fs .online_grow = fs .grow ;
fs .online_shrink = fs .shrink ;
}
#endif
fs_limits.min_size = 256 * MEBIBYTE;
return fs ;
}
Detect busy status of multi-device btrfs file systems (#723842) Busy detection of file systems works by checking if the device is mounted (appears in the mount_info map). For a multi-device btrfs file system this will only report one of the devices as busy, not all of them. # btrfs filesystem show /dev/sdb1 Label: none uuid: 36eb51a2-2927-4c92-820f-b2f0b5cdae50 Total devices 2 FS bytes used 156.00KB devid 2 size 2.00GB used 512.00MB path /dev/sdb2 devid 1 size 2.00GB used 240.75MB path /dev/sdb1 # mount /dev/sdb1 /mnt/1 # grep btrfs /proc/mounts /dev/sdb1 /mnt/1 btrfs rw,seclabel,relatime,ssd,space_cache 0 0 GParted will only report /dev/sdb1 as busy, but not /dev/sdb2. Add btrfs specific is_busy() method which reports the device as busy if any of the devices in the btrfs file system are mounted. This uses a cache which maps device membership in all btrfs file systems. The cache is cleared on GParted refresh and incrementally populated as each btrfs partition is checked for busy status. WARNING: Removal of the mounting device from a btrfs file system makes it impossible to determine whether the file system is mounted or not for linux <= 3.4. This is because /proc/mounts continues to show the old device which is no longer a member of the file system. # btrfs device delete /dev/sdb1 /mnt/1 # sync # grep btrfs /proc/mounts /dev/sdb1 /mnt/1 btrfs rw,seclabel,relatime,ssd,space_cache 0 0 # btrfs filesystem show /dev/sdb1 # btrfs filesystem show /dev/sdb2 Label: none uuid: 36eb51a2-2927-4c92-820f-b2f0b5cdae50 Total devices 1 FS bytes used 28.00KB devid 2 size 2.00GB used 1.02GB path /dev/sdb2 Fixed in linux 3.5 by commit: Btrfs: implement ->show_devname https://git.kernel.org/cgit/linux/kernel/git/torvalds/linux.git/commit/?id=9c5085c147989d48dfe74194b48affc23f376650 Bug #723842 - GParted resizes the wrong filesystem (does not pass the devid to btrfs filesystem resize)
2014-02-17 15:39:34 -07:00
bool btrfs::is_busy( const Glib::ustring & path )
{
//A btrfs file system is busy if any of the member devices are mounted.
// WARNING:
// Removal of the mounting device from a btrfs file system makes it impossible to
// determine whether the file system is mounted or not for linux <= 3.4. This is
// because /proc/mounts continues to show the old device which is no longer a
// member of the file system. Fixed in linux 3.5 by commit:
// Btrfs: implement ->show_devname
// https://git.kernel.org/cgit/linux/kernel/git/torvalds/linux.git/commit/?id=9c5085c147989d48dfe74194b48affc23f376650
return ! get_mount_device( path ) .empty() ;
Detect busy status of multi-device btrfs file systems (#723842) Busy detection of file systems works by checking if the device is mounted (appears in the mount_info map). For a multi-device btrfs file system this will only report one of the devices as busy, not all of them. # btrfs filesystem show /dev/sdb1 Label: none uuid: 36eb51a2-2927-4c92-820f-b2f0b5cdae50 Total devices 2 FS bytes used 156.00KB devid 2 size 2.00GB used 512.00MB path /dev/sdb2 devid 1 size 2.00GB used 240.75MB path /dev/sdb1 # mount /dev/sdb1 /mnt/1 # grep btrfs /proc/mounts /dev/sdb1 /mnt/1 btrfs rw,seclabel,relatime,ssd,space_cache 0 0 GParted will only report /dev/sdb1 as busy, but not /dev/sdb2. Add btrfs specific is_busy() method which reports the device as busy if any of the devices in the btrfs file system are mounted. This uses a cache which maps device membership in all btrfs file systems. The cache is cleared on GParted refresh and incrementally populated as each btrfs partition is checked for busy status. WARNING: Removal of the mounting device from a btrfs file system makes it impossible to determine whether the file system is mounted or not for linux <= 3.4. This is because /proc/mounts continues to show the old device which is no longer a member of the file system. # btrfs device delete /dev/sdb1 /mnt/1 # sync # grep btrfs /proc/mounts /dev/sdb1 /mnt/1 btrfs rw,seclabel,relatime,ssd,space_cache 0 0 # btrfs filesystem show /dev/sdb1 # btrfs filesystem show /dev/sdb2 Label: none uuid: 36eb51a2-2927-4c92-820f-b2f0b5cdae50 Total devices 1 FS bytes used 28.00KB devid 2 size 2.00GB used 1.02GB path /dev/sdb2 Fixed in linux 3.5 by commit: Btrfs: implement ->show_devname https://git.kernel.org/cgit/linux/kernel/git/torvalds/linux.git/commit/?id=9c5085c147989d48dfe74194b48affc23f376650 Bug #723842 - GParted resizes the wrong filesystem (does not pass the devid to btrfs filesystem resize)
2014-02-17 15:39:34 -07:00
}
bool btrfs::create( const Partition & new_partition, OperationDetail & operationdetail )
{
Correctly quote and escape arguments passed to external commands (#787203) Trying to set a file system label to (including the double quotes): " --help " fails. For example labelling an ext4 file system would try to run this command: # e2label /dev/sdb1 "" --help "" Usage: e2label device [newlabel] # echo $? 1 Alternatively trying to create a file system with a label of just a double quote also fails. The Applying Pending Operations dialog waits forever and won't cancel or force cancel. Have to use the window manager close window button to close the dialog. Also GParted reports this error to the console: (gpartedbin:9648): glibmm-CRITICAL **: unhandled exception (type Glib::Error) in signal handler: domain: g-shell-error-quark code : 0 what : Text ended before matching quote was found for ". (The text was 'mkfs.xfs -f -L """ /dev/sdb2') Command strings are parsed and split into argv array by function Glib::shell_parse_argv() which calls internal glib function tokenize_command_line() for shell tokenization. It expects the command string to be properly quoted and escaped and after tokenization, calls g_shell_unquote() on every parsed argument. So to prevent constructing incorrect commands, every non-static string needs to be properly quoted. GParted only puts labels and mount points into double quotes, but has not escaped special characters in those values itself. This patch fixes all these problems by using Glib::shell_quote() on all variable values. Labels, mount points, paths and all others too. Probably a better solution would be to use a new function which takes argv array instead of one string with all the, correctly quoted and escaped, arguments concatenated together. Bug 787203 - Correctly quote and escape arguments of external programs passed to execute_command()
2017-09-03 01:52:54 -06:00
return ! execute_command( "mkfs.btrfs -L " + Glib::shell_quote( new_partition.get_filesystem_label() ) +
" " + Glib::shell_quote( new_partition.get_path() ),
Time and check nearly all file system action commands (#754684) There has been an undocumented rule that external commands displayed in the operation details, as part of file system manipulations, only get a time and check mark displayed when multiple commands are needed, and not otherwise. (GParted checks whether all commands are successful or not regardless of whether a check mark is displayed in the operation details or not). EXCEPTION 1: btrfs resize Since the following commit [1] from 2013-02-22, GParted stopped displaying the timing for the btrfs resize command in the operation details. It being part of a multi-command sequence to perform the step. This is because FileSystem::execute_command() since the commit can only check the exit status for zero / non-zero while timing and checking the command status but btrfs resize needs to consider some non-zero statuses as successful. [1] 52a2a9b00a32996921ace055e71d0e09fb33c5fe Reduce threading (#685740) EXCEPTION 2: ext2/3/4 move and copy using e2image When use of e2image was added [2] the single command steps were timed and check. [2] 86111fe12a26d23d9fc2a9e2d19281290ecaf985 Use e2image to move/copy ext[234] file systems (#721516) EXCEPTION 3: fat16/32 write label and UUID Uses Utils::execute_command() rather than FileSystem::execute_command() so can be separately changed. See the following commit for resolution of the final commands not yet timed and check mark displayed. CHANGE: Lets make a simpler rule of always displaying the time and a check mark for all external commands displayed in the operation details. However this makes several of the other single command actions need special exit status handling because zero success, non-zero failure is not correct for every case. Specifically affects resizing of reiserfs and check repair of ext2/3/4, fat16/32, jfs and reiserfs. After this change all external commands run as file system actions must follow one of these two patterns of using the EXEC_CHECK_STATUS flag or separately calling FileSystem::set_status() to register success or failure of the command: exit_status = execute_command(cmd, od, EXEC_CHECK_STATUS...); or: exit_status = execute_command(cmd, od, ...); bool success = (exit_status == 0 || exit_status == OTHER_SUCCESS_VALUE...); set_status(od, success ); Bug 754684 - Updates to FileSystem:: and Utils::execute_command() functions
2015-09-05 02:31:16 -06:00
operationdetail, EXEC_CHECK_STATUS );
}
bool btrfs::check_repair( const Partition & partition, OperationDetail & operationdetail )
{
Correctly quote and escape arguments passed to external commands (#787203) Trying to set a file system label to (including the double quotes): " --help " fails. For example labelling an ext4 file system would try to run this command: # e2label /dev/sdb1 "" --help "" Usage: e2label device [newlabel] # echo $? 1 Alternatively trying to create a file system with a label of just a double quote also fails. The Applying Pending Operations dialog waits forever and won't cancel or force cancel. Have to use the window manager close window button to close the dialog. Also GParted reports this error to the console: (gpartedbin:9648): glibmm-CRITICAL **: unhandled exception (type Glib::Error) in signal handler: domain: g-shell-error-quark code : 0 what : Text ended before matching quote was found for ". (The text was 'mkfs.xfs -f -L """ /dev/sdb2') Command strings are parsed and split into argv array by function Glib::shell_parse_argv() which calls internal glib function tokenize_command_line() for shell tokenization. It expects the command string to be properly quoted and escaped and after tokenization, calls g_shell_unquote() on every parsed argument. So to prevent constructing incorrect commands, every non-static string needs to be properly quoted. GParted only puts labels and mount points into double quotes, but has not escaped special characters in those values itself. This patch fixes all these problems by using Glib::shell_quote() on all variable values. Labels, mount points, paths and all others too. Probably a better solution would be to use a new function which takes argv array instead of one string with all the, correctly quoted and escaped, arguments concatenated together. Bug 787203 - Correctly quote and escape arguments of external programs passed to execute_command()
2017-09-03 01:52:54 -06:00
return ! execute_command( "btrfsck " + Glib::shell_quote( partition.get_path() ),
operationdetail, EXEC_CHECK_STATUS );
}
void btrfs::set_used_sectors( Partition & partition )
{
Display usage for multi-device btrfs file systems (#723842) Currently GParted fails to report the usage of a multi-device btrfs file system if it is mounted or if the used space is larger than the size of an individual member device. When GParted does display usage figures it also incorrectly reports the file system wide used figure against every member device. Mounted case: statvfs() provides an FS size which is larger than any individual device so is rejected. See: GParted_Core::mounted_set_used_sectors() Utils::get_mounted_filesystem_usage() partition .set_sector_usage() Unmounted case, FS used > device size: FS used figure is larger than any individual device so free space is calculated as a negative number and rejected. See: btrfs::set_used_sectors() Btrfs has a volume manager layer within the file system which allows it to provide multiple levels of data redundancy, RAID levels, and use multiple devices both of which can be changed while the file system is mounted. To achieve this btrfs has to allocate space at two different level: (1) chunks of 256 MiB or more at the volume manager level; and (2) extents at the file data level. References: * Btrfs: Working with multiple devices https://lwn.net/Articles/577961/ * Btrfs wiki: Glossary https://btrfs.wiki.kernel.org/index.php/Glossary This makes the question of how much disk space is being used in an individual device a complicated question to answer. Further, the current btrfs tools don't provide the required information. Btrfs filesystem show only provides space usage information at the chunk level per device. At the file extent level only a single figure for the whole file system is provided. It also reports size of the data and metadata being stored, not the larger figure of the amount of space taken after redundancy is applied. So it is impossible to answer the question of how much disk space is being used in an individual device. Example output: Label: none uuid: 36eb51a2-2927-4c92-820f-b2f0b5cdae50 Total devices 2 FS bytes used 156.00KB devid 2 size 2.00GB used 512.00MB path /dev/sdb2 devid 1 size 2.00GB used 240.75MB path /dev/sdb1 Fix by guesstimating the per device used figure as the fraction of the file system wide extent usage based on chunk usage per device. Calculation: ptn fs used = total fs used * devid used / sum devid used Positives: 1) Per device used figure will correctly be between zero and allocated chunk size. Known inaccuracies: [for single and multi-device btrfs file systems] 1) Btrfs filesystem show reports file system wide file extent usage without considering redundancy applied to that data. (By default btrfs stores two copies of metadata and one copy of data). 2) At minimum size when all data has been consolidated there will be a few partly filled chunks of 256 MiB or more for data and metadata of each storage profile (RAID level). [for multi-device btrfs file systems only] 3) Data may be far from evenly distributed between the chunks on multiple devices. 4) Extents can be and are relocated to other devices within the file system when shrinking a device. Bug #723842 - GParted resizes the wrong filesystem (does not pass the devid to btrfs filesystem resize)
2014-03-29 15:12:01 -06:00
//Called when the file system is unmounted *and* when mounted.
//
// Btrfs has a volume manager layer within the file system which allows it to
// provide multiple levels of data redundancy, RAID levels, and use multiple
// devices both of which can be changed while the file system is mounted. To
// achieve this btrfs has to allocate space at two different levels: (1) chunks
// of 256 MiB or more at the volume manager level; and (2) extents at the file
// data level.
// References:
// * Btrfs: Working with multiple devices
// https://lwn.net/Articles/577961/
// * Btrfs wiki: Glossary
// https://btrfs.wiki.kernel.org/index.php/Glossary
//
// This makes the question of how much disk space is being used in an individual
// device a complicated question to answer. Further, the current btrfs tools
// don't provide the required information.
//
// Btrfs filesystem show only provides space usage information at the chunk level
// per device. At the file extent level only a single figure for the whole file
// system is provided. It also reports size of the data and metadata being
// stored, not the larger figure of the amount of space taken after redundancy is
// applied. So it is impossible to answer the question of how much disk space is
// being used in an individual device. Example output:
//
// Label: none uuid: 36eb51a2-2927-4c92-820f-b2f0b5cdae50
// Total devices 2 FS bytes used 156.00KB
// devid 2 size 2.00GB used 512.00MB path /dev/sdb2
// devid 1 size 2.00GB used 240.75MB path /dev/sdb1
//
// Guesstimate the per device used figure as the fraction of the file system wide
// extent usage based on chunk usage per device.
//
// Positives:
// 1) Per device used figure will correctly be between zero and allocated chunk
// size.
//
// Known inaccuracies:
// [for single and multi-device btrfs file systems]
// 1) Btrfs filesystem show reports file system wide file extent usage without
// considering redundancy applied to that data. (By default btrfs stores two
// copies of metadata and one copy of data).
// 2) At minimum size when all data has been consolidated there will be a few
// partly filled chunks of 256 MiB or more for data and metadata of each
// storage profile (RAID level).
// [for multi-device btrfs file systems only]
// 3) Data may be far from evenly distributed between the chunks on multiple
// devices.
// 4) Extents can be and are relocated to other devices within the file system
// when shrinking a device.
if ( btrfs_found )
Correctly quote and escape arguments passed to external commands (#787203) Trying to set a file system label to (including the double quotes): " --help " fails. For example labelling an ext4 file system would try to run this command: # e2label /dev/sdb1 "" --help "" Usage: e2label device [newlabel] # echo $? 1 Alternatively trying to create a file system with a label of just a double quote also fails. The Applying Pending Operations dialog waits forever and won't cancel or force cancel. Have to use the window manager close window button to close the dialog. Also GParted reports this error to the console: (gpartedbin:9648): glibmm-CRITICAL **: unhandled exception (type Glib::Error) in signal handler: domain: g-shell-error-quark code : 0 what : Text ended before matching quote was found for ". (The text was 'mkfs.xfs -f -L """ /dev/sdb2') Command strings are parsed and split into argv array by function Glib::shell_parse_argv() which calls internal glib function tokenize_command_line() for shell tokenization. It expects the command string to be properly quoted and escaped and after tokenization, calls g_shell_unquote() on every parsed argument. So to prevent constructing incorrect commands, every non-static string needs to be properly quoted. GParted only puts labels and mount points into double quotes, but has not escaped special characters in those values itself. This patch fixes all these problems by using Glib::shell_quote() on all variable values. Labels, mount points, paths and all others too. Probably a better solution would be to use a new function which takes argv array instead of one string with all the, correctly quoted and escaped, arguments concatenated together. Bug 787203 - Correctly quote and escape arguments of external programs passed to execute_command()
2017-09-03 01:52:54 -06:00
Utils::execute_command( "btrfs filesystem show " + Glib::shell_quote( partition.get_path() ),
output, error, true );
else
Correctly quote and escape arguments passed to external commands (#787203) Trying to set a file system label to (including the double quotes): " --help " fails. For example labelling an ext4 file system would try to run this command: # e2label /dev/sdb1 "" --help "" Usage: e2label device [newlabel] # echo $? 1 Alternatively trying to create a file system with a label of just a double quote also fails. The Applying Pending Operations dialog waits forever and won't cancel or force cancel. Have to use the window manager close window button to close the dialog. Also GParted reports this error to the console: (gpartedbin:9648): glibmm-CRITICAL **: unhandled exception (type Glib::Error) in signal handler: domain: g-shell-error-quark code : 0 what : Text ended before matching quote was found for ". (The text was 'mkfs.xfs -f -L """ /dev/sdb2') Command strings are parsed and split into argv array by function Glib::shell_parse_argv() which calls internal glib function tokenize_command_line() for shell tokenization. It expects the command string to be properly quoted and escaped and after tokenization, calls g_shell_unquote() on every parsed argument. So to prevent constructing incorrect commands, every non-static string needs to be properly quoted. GParted only puts labels and mount points into double quotes, but has not escaped special characters in those values itself. This patch fixes all these problems by using Glib::shell_quote() on all variable values. Labels, mount points, paths and all others too. Probably a better solution would be to use a new function which takes argv array instead of one string with all the, correctly quoted and escaped, arguments concatenated together. Bug 787203 - Correctly quote and escape arguments of external programs passed to execute_command()
2017-09-03 01:52:54 -06:00
Utils::execute_command( "btrfs-show " + Glib::shell_quote( partition.get_path() ),
output, error, true );
//In many cases the exit status doesn't reflect valid output or an error condition
// so rely on parsing the output to determine success.
//Extract the per device size figure. Guesstimate the per device used
// figure as discussed above. Example output:
//
// Label: none uuid: 36eb51a2-2927-4c92-820f-b2f0b5cdae50
// Total devices 2 FS bytes used 156.00KB
// devid 2 size 2.00GB used 512.00MB path /dev/sdb2
// devid 1 size 2.00GB used 240.75MB path /dev/sdb1
//
// Calculations:
// ptn fs size = devid size
// ptn fs used = total fs used * devid used / sum devid used
Byte_Value ptn_size = partition .get_byte_length() ;
Byte_Value total_fs_used = -1 ; //total fs used
Byte_Value sum_devid_used = 0 ; //sum devid used
Byte_Value devid_used = -1 ; //devid used
Byte_Value devid_size = -1 ; //devid size
//Btrfs file system wide used bytes (extents and items)
Glib::ustring str ;
if ( ! ( str = Utils::regexp_label( output, "FS bytes used ([0-9\\.]+( ?[KMGTPE]?i?B)?)" ) ) .empty() )
total_fs_used = Utils::round( btrfs_size_to_gdouble( str ) ) ;
Glib::ustring::size_type offset = 0 ;
Glib::ustring::size_type index ;
while ( ( index = output .find( "devid ", offset ) ) != Glib::ustring::npos )
{
Glib::ustring devid_path = Utils::regexp_label( output .substr( index ),
"devid .* path (/dev/[[:graph:]]+)" ) ;
if ( ! devid_path .empty() )
Display usage for multi-device btrfs file systems (#723842) Currently GParted fails to report the usage of a multi-device btrfs file system if it is mounted or if the used space is larger than the size of an individual member device. When GParted does display usage figures it also incorrectly reports the file system wide used figure against every member device. Mounted case: statvfs() provides an FS size which is larger than any individual device so is rejected. See: GParted_Core::mounted_set_used_sectors() Utils::get_mounted_filesystem_usage() partition .set_sector_usage() Unmounted case, FS used > device size: FS used figure is larger than any individual device so free space is calculated as a negative number and rejected. See: btrfs::set_used_sectors() Btrfs has a volume manager layer within the file system which allows it to provide multiple levels of data redundancy, RAID levels, and use multiple devices both of which can be changed while the file system is mounted. To achieve this btrfs has to allocate space at two different level: (1) chunks of 256 MiB or more at the volume manager level; and (2) extents at the file data level. References: * Btrfs: Working with multiple devices https://lwn.net/Articles/577961/ * Btrfs wiki: Glossary https://btrfs.wiki.kernel.org/index.php/Glossary This makes the question of how much disk space is being used in an individual device a complicated question to answer. Further, the current btrfs tools don't provide the required information. Btrfs filesystem show only provides space usage information at the chunk level per device. At the file extent level only a single figure for the whole file system is provided. It also reports size of the data and metadata being stored, not the larger figure of the amount of space taken after redundancy is applied. So it is impossible to answer the question of how much disk space is being used in an individual device. Example output: Label: none uuid: 36eb51a2-2927-4c92-820f-b2f0b5cdae50 Total devices 2 FS bytes used 156.00KB devid 2 size 2.00GB used 512.00MB path /dev/sdb2 devid 1 size 2.00GB used 240.75MB path /dev/sdb1 Fix by guesstimating the per device used figure as the fraction of the file system wide extent usage based on chunk usage per device. Calculation: ptn fs used = total fs used * devid used / sum devid used Positives: 1) Per device used figure will correctly be between zero and allocated chunk size. Known inaccuracies: [for single and multi-device btrfs file systems] 1) Btrfs filesystem show reports file system wide file extent usage without considering redundancy applied to that data. (By default btrfs stores two copies of metadata and one copy of data). 2) At minimum size when all data has been consolidated there will be a few partly filled chunks of 256 MiB or more for data and metadata of each storage profile (RAID level). [for multi-device btrfs file systems only] 3) Data may be far from evenly distributed between the chunks on multiple devices. 4) Extents can be and are relocated to other devices within the file system when shrinking a device. Bug #723842 - GParted resizes the wrong filesystem (does not pass the devid to btrfs filesystem resize)
2014-03-29 15:12:01 -06:00
{
//Btrfs per devid used bytes (chunks)
Byte_Value used = -1 ;
if ( ! ( str = Utils::regexp_label( output .substr( index ),
"devid .* used ([0-9\\.]+( ?[KMGTPE]?i?B)?) path" ) ) .empty() )
Display usage for multi-device btrfs file systems (#723842) Currently GParted fails to report the usage of a multi-device btrfs file system if it is mounted or if the used space is larger than the size of an individual member device. When GParted does display usage figures it also incorrectly reports the file system wide used figure against every member device. Mounted case: statvfs() provides an FS size which is larger than any individual device so is rejected. See: GParted_Core::mounted_set_used_sectors() Utils::get_mounted_filesystem_usage() partition .set_sector_usage() Unmounted case, FS used > device size: FS used figure is larger than any individual device so free space is calculated as a negative number and rejected. See: btrfs::set_used_sectors() Btrfs has a volume manager layer within the file system which allows it to provide multiple levels of data redundancy, RAID levels, and use multiple devices both of which can be changed while the file system is mounted. To achieve this btrfs has to allocate space at two different level: (1) chunks of 256 MiB or more at the volume manager level; and (2) extents at the file data level. References: * Btrfs: Working with multiple devices https://lwn.net/Articles/577961/ * Btrfs wiki: Glossary https://btrfs.wiki.kernel.org/index.php/Glossary This makes the question of how much disk space is being used in an individual device a complicated question to answer. Further, the current btrfs tools don't provide the required information. Btrfs filesystem show only provides space usage information at the chunk level per device. At the file extent level only a single figure for the whole file system is provided. It also reports size of the data and metadata being stored, not the larger figure of the amount of space taken after redundancy is applied. So it is impossible to answer the question of how much disk space is being used in an individual device. Example output: Label: none uuid: 36eb51a2-2927-4c92-820f-b2f0b5cdae50 Total devices 2 FS bytes used 156.00KB devid 2 size 2.00GB used 512.00MB path /dev/sdb2 devid 1 size 2.00GB used 240.75MB path /dev/sdb1 Fix by guesstimating the per device used figure as the fraction of the file system wide extent usage based on chunk usage per device. Calculation: ptn fs used = total fs used * devid used / sum devid used Positives: 1) Per device used figure will correctly be between zero and allocated chunk size. Known inaccuracies: [for single and multi-device btrfs file systems] 1) Btrfs filesystem show reports file system wide file extent usage without considering redundancy applied to that data. (By default btrfs stores two copies of metadata and one copy of data). 2) At minimum size when all data has been consolidated there will be a few partly filled chunks of 256 MiB or more for data and metadata of each storage profile (RAID level). [for multi-device btrfs file systems only] 3) Data may be far from evenly distributed between the chunks on multiple devices. 4) Extents can be and are relocated to other devices within the file system when shrinking a device. Bug #723842 - GParted resizes the wrong filesystem (does not pass the devid to btrfs filesystem resize)
2014-03-29 15:12:01 -06:00
{
used = btrfs_size_to_num( str, ptn_size, false ) ;
sum_devid_used += used ;
Display usage for multi-device btrfs file systems (#723842) Currently GParted fails to report the usage of a multi-device btrfs file system if it is mounted or if the used space is larger than the size of an individual member device. When GParted does display usage figures it also incorrectly reports the file system wide used figure against every member device. Mounted case: statvfs() provides an FS size which is larger than any individual device so is rejected. See: GParted_Core::mounted_set_used_sectors() Utils::get_mounted_filesystem_usage() partition .set_sector_usage() Unmounted case, FS used > device size: FS used figure is larger than any individual device so free space is calculated as a negative number and rejected. See: btrfs::set_used_sectors() Btrfs has a volume manager layer within the file system which allows it to provide multiple levels of data redundancy, RAID levels, and use multiple devices both of which can be changed while the file system is mounted. To achieve this btrfs has to allocate space at two different level: (1) chunks of 256 MiB or more at the volume manager level; and (2) extents at the file data level. References: * Btrfs: Working with multiple devices https://lwn.net/Articles/577961/ * Btrfs wiki: Glossary https://btrfs.wiki.kernel.org/index.php/Glossary This makes the question of how much disk space is being used in an individual device a complicated question to answer. Further, the current btrfs tools don't provide the required information. Btrfs filesystem show only provides space usage information at the chunk level per device. At the file extent level only a single figure for the whole file system is provided. It also reports size of the data and metadata being stored, not the larger figure of the amount of space taken after redundancy is applied. So it is impossible to answer the question of how much disk space is being used in an individual device. Example output: Label: none uuid: 36eb51a2-2927-4c92-820f-b2f0b5cdae50 Total devices 2 FS bytes used 156.00KB devid 2 size 2.00GB used 512.00MB path /dev/sdb2 devid 1 size 2.00GB used 240.75MB path /dev/sdb1 Fix by guesstimating the per device used figure as the fraction of the file system wide extent usage based on chunk usage per device. Calculation: ptn fs used = total fs used * devid used / sum devid used Positives: 1) Per device used figure will correctly be between zero and allocated chunk size. Known inaccuracies: [for single and multi-device btrfs file systems] 1) Btrfs filesystem show reports file system wide file extent usage without considering redundancy applied to that data. (By default btrfs stores two copies of metadata and one copy of data). 2) At minimum size when all data has been consolidated there will be a few partly filled chunks of 256 MiB or more for data and metadata of each storage profile (RAID level). [for multi-device btrfs file systems only] 3) Data may be far from evenly distributed between the chunks on multiple devices. 4) Extents can be and are relocated to other devices within the file system when shrinking a device. Bug #723842 - GParted resizes the wrong filesystem (does not pass the devid to btrfs filesystem resize)
2014-03-29 15:12:01 -06:00
if ( devid_path == partition .get_path() )
devid_used = used ;
Display usage for multi-device btrfs file systems (#723842) Currently GParted fails to report the usage of a multi-device btrfs file system if it is mounted or if the used space is larger than the size of an individual member device. When GParted does display usage figures it also incorrectly reports the file system wide used figure against every member device. Mounted case: statvfs() provides an FS size which is larger than any individual device so is rejected. See: GParted_Core::mounted_set_used_sectors() Utils::get_mounted_filesystem_usage() partition .set_sector_usage() Unmounted case, FS used > device size: FS used figure is larger than any individual device so free space is calculated as a negative number and rejected. See: btrfs::set_used_sectors() Btrfs has a volume manager layer within the file system which allows it to provide multiple levels of data redundancy, RAID levels, and use multiple devices both of which can be changed while the file system is mounted. To achieve this btrfs has to allocate space at two different level: (1) chunks of 256 MiB or more at the volume manager level; and (2) extents at the file data level. References: * Btrfs: Working with multiple devices https://lwn.net/Articles/577961/ * Btrfs wiki: Glossary https://btrfs.wiki.kernel.org/index.php/Glossary This makes the question of how much disk space is being used in an individual device a complicated question to answer. Further, the current btrfs tools don't provide the required information. Btrfs filesystem show only provides space usage information at the chunk level per device. At the file extent level only a single figure for the whole file system is provided. It also reports size of the data and metadata being stored, not the larger figure of the amount of space taken after redundancy is applied. So it is impossible to answer the question of how much disk space is being used in an individual device. Example output: Label: none uuid: 36eb51a2-2927-4c92-820f-b2f0b5cdae50 Total devices 2 FS bytes used 156.00KB devid 2 size 2.00GB used 512.00MB path /dev/sdb2 devid 1 size 2.00GB used 240.75MB path /dev/sdb1 Fix by guesstimating the per device used figure as the fraction of the file system wide extent usage based on chunk usage per device. Calculation: ptn fs used = total fs used * devid used / sum devid used Positives: 1) Per device used figure will correctly be between zero and allocated chunk size. Known inaccuracies: [for single and multi-device btrfs file systems] 1) Btrfs filesystem show reports file system wide file extent usage without considering redundancy applied to that data. (By default btrfs stores two copies of metadata and one copy of data). 2) At minimum size when all data has been consolidated there will be a few partly filled chunks of 256 MiB or more for data and metadata of each storage profile (RAID level). [for multi-device btrfs file systems only] 3) Data may be far from evenly distributed between the chunks on multiple devices. 4) Extents can be and are relocated to other devices within the file system when shrinking a device. Bug #723842 - GParted resizes the wrong filesystem (does not pass the devid to btrfs filesystem resize)
2014-03-29 15:12:01 -06:00
}
if ( devid_path == partition .get_path() )
{
//Btrfs per device size bytes (chunks)
if ( ! ( str = Utils::regexp_label( output .substr( index ),
"devid .* size ([0-9\\.]+( ?[KMGTPE]?i?B)?) used " ) ) .empty() )
devid_size = btrfs_size_to_num( str, ptn_size, true ) ;
}
}
offset = index + 5 ; //Next find starts immediately after current "devid"
}
if ( total_fs_used > -1 && devid_size > -1 && devid_used > -1 && sum_devid_used > 0 )
{
T = Utils::round( devid_size / double(partition .sector_size) ) ; //ptn fs size
double ptn_fs_used = total_fs_used * ( devid_used / double(sum_devid_used) ) ; //ptn fs used
N = T - Utils::round( ptn_fs_used / double(partition .sector_size) ) ;
partition .set_sector_usage( T, N ) ;
}
else
{
if ( ! output .empty() )
Display messages for encrypted file systems (#760080) At the moment any messages for an encrypted file system aren't shown, only messages from the outer PartitionLUKS object are shown. Also in Win_GParted::activate_paste() the selected Partition object, possibly a derived PartitionLUKS, is cloned and the messages cleared. Therefore a set of accessor methods must be provided to query and modify partition messages. Messages will be stored in the Partition object to which they are added and retrieved from all. So in the case of a derived PartitionLUKS they will be retrieved from the messages vector of the PartitionLUKS object itself and the messages vector for the encrypted file system it contains. To replace code like this in GParted_Core: partition_temp->messages = messages; We might naturally provide a set_messages() method which assigns the messages vector and is used like this: partition_temp->set_messages( messages ); However on a PartitionLUKS object what should set_messages() do? By the name it will replace any existing messages in the PartitionLUKS object itself, but what should happen to the messages for the contained encrypted Partition object? Should they be cleared or left alone? Rather than implement set_messages() with unclear semantics implement append_messages(), which in the PartitionLUKS object case will clearly leave any messages for the contained encrypted Partition object alone. Append_messages() is then used to add messages as the Partition or PartitionLUKS objects when populating the data in GParted_Core. Bug 760080 - Implement read-only LUKS support
2015-12-31 09:32:08 -07:00
partition.push_back_message( output );
if ( ! error .empty() )
Display messages for encrypted file systems (#760080) At the moment any messages for an encrypted file system aren't shown, only messages from the outer PartitionLUKS object are shown. Also in Win_GParted::activate_paste() the selected Partition object, possibly a derived PartitionLUKS, is cloned and the messages cleared. Therefore a set of accessor methods must be provided to query and modify partition messages. Messages will be stored in the Partition object to which they are added and retrieved from all. So in the case of a derived PartitionLUKS they will be retrieved from the messages vector of the PartitionLUKS object itself and the messages vector for the encrypted file system it contains. To replace code like this in GParted_Core: partition_temp->messages = messages; We might naturally provide a set_messages() method which assigns the messages vector and is used like this: partition_temp->set_messages( messages ); However on a PartitionLUKS object what should set_messages() do? By the name it will replace any existing messages in the PartitionLUKS object itself, but what should happen to the messages for the contained encrypted Partition object? Should they be cleared or left alone? Rather than implement set_messages() with unclear semantics implement append_messages(), which in the PartitionLUKS object case will clearly leave any messages for the contained encrypted Partition object alone. Append_messages() is then used to add messages as the Partition or PartitionLUKS objects when populating the data in GParted_Core. Bug 760080 - Implement read-only LUKS support
2015-12-31 09:32:08 -07:00
partition.push_back_message( error );
}
}
bool btrfs::write_label( const Partition & partition, OperationDetail & operationdetail )
{
Correctly quote and escape arguments passed to external commands (#787203) Trying to set a file system label to (including the double quotes): " --help " fails. For example labelling an ext4 file system would try to run this command: # e2label /dev/sdb1 "" --help "" Usage: e2label device [newlabel] # echo $? 1 Alternatively trying to create a file system with a label of just a double quote also fails. The Applying Pending Operations dialog waits forever and won't cancel or force cancel. Have to use the window manager close window button to close the dialog. Also GParted reports this error to the console: (gpartedbin:9648): glibmm-CRITICAL **: unhandled exception (type Glib::Error) in signal handler: domain: g-shell-error-quark code : 0 what : Text ended before matching quote was found for ". (The text was 'mkfs.xfs -f -L """ /dev/sdb2') Command strings are parsed and split into argv array by function Glib::shell_parse_argv() which calls internal glib function tokenize_command_line() for shell tokenization. It expects the command string to be properly quoted and escaped and after tokenization, calls g_shell_unquote() on every parsed argument. So to prevent constructing incorrect commands, every non-static string needs to be properly quoted. GParted only puts labels and mount points into double quotes, but has not escaped special characters in those values itself. This patch fixes all these problems by using Glib::shell_quote() on all variable values. Labels, mount points, paths and all others too. Probably a better solution would be to use a new function which takes argv array instead of one string with all the, correctly quoted and escaped, arguments concatenated together. Bug 787203 - Correctly quote and escape arguments of external programs passed to execute_command()
2017-09-03 01:52:54 -06:00
return ! execute_command( "btrfs filesystem label " + Glib::shell_quote( partition.get_path() ) +
" " + Glib::shell_quote( partition.get_filesystem_label() ),
Time and check nearly all file system action commands (#754684) There has been an undocumented rule that external commands displayed in the operation details, as part of file system manipulations, only get a time and check mark displayed when multiple commands are needed, and not otherwise. (GParted checks whether all commands are successful or not regardless of whether a check mark is displayed in the operation details or not). EXCEPTION 1: btrfs resize Since the following commit [1] from 2013-02-22, GParted stopped displaying the timing for the btrfs resize command in the operation details. It being part of a multi-command sequence to perform the step. This is because FileSystem::execute_command() since the commit can only check the exit status for zero / non-zero while timing and checking the command status but btrfs resize needs to consider some non-zero statuses as successful. [1] 52a2a9b00a32996921ace055e71d0e09fb33c5fe Reduce threading (#685740) EXCEPTION 2: ext2/3/4 move and copy using e2image When use of e2image was added [2] the single command steps were timed and check. [2] 86111fe12a26d23d9fc2a9e2d19281290ecaf985 Use e2image to move/copy ext[234] file systems (#721516) EXCEPTION 3: fat16/32 write label and UUID Uses Utils::execute_command() rather than FileSystem::execute_command() so can be separately changed. See the following commit for resolution of the final commands not yet timed and check mark displayed. CHANGE: Lets make a simpler rule of always displaying the time and a check mark for all external commands displayed in the operation details. However this makes several of the other single command actions need special exit status handling because zero success, non-zero failure is not correct for every case. Specifically affects resizing of reiserfs and check repair of ext2/3/4, fat16/32, jfs and reiserfs. After this change all external commands run as file system actions must follow one of these two patterns of using the EXEC_CHECK_STATUS flag or separately calling FileSystem::set_status() to register success or failure of the command: exit_status = execute_command(cmd, od, EXEC_CHECK_STATUS...); or: exit_status = execute_command(cmd, od, ...); bool success = (exit_status == 0 || exit_status == OTHER_SUCCESS_VALUE...); set_status(od, success ); Bug 754684 - Updates to FileSystem:: and Utils::execute_command() functions
2015-09-05 02:31:16 -06:00
operationdetail, EXEC_CHECK_STATUS );
}
bool btrfs::resize( const Partition & partition_new, OperationDetail & operationdetail, bool fill_partition )
{
bool success = true ;
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)
2014-04-11 04:27:18 -06:00
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 )
{
mount_point = mk_temp_dir( "", operationdetail ) ;
if ( mount_point .empty() )
return false ;
Correctly quote and escape arguments passed to external commands (#787203) Trying to set a file system label to (including the double quotes): " --help " fails. For example labelling an ext4 file system would try to run this command: # e2label /dev/sdb1 "" --help "" Usage: e2label device [newlabel] # echo $? 1 Alternatively trying to create a file system with a label of just a double quote also fails. The Applying Pending Operations dialog waits forever and won't cancel or force cancel. Have to use the window manager close window button to close the dialog. Also GParted reports this error to the console: (gpartedbin:9648): glibmm-CRITICAL **: unhandled exception (type Glib::Error) in signal handler: domain: g-shell-error-quark code : 0 what : Text ended before matching quote was found for ". (The text was 'mkfs.xfs -f -L """ /dev/sdb2') Command strings are parsed and split into argv array by function Glib::shell_parse_argv() which calls internal glib function tokenize_command_line() for shell tokenization. It expects the command string to be properly quoted and escaped and after tokenization, calls g_shell_unquote() on every parsed argument. So to prevent constructing incorrect commands, every non-static string needs to be properly quoted. GParted only puts labels and mount points into double quotes, but has not escaped special characters in those values itself. This patch fixes all these problems by using Glib::shell_quote() on all variable values. Labels, mount points, paths and all others too. Probably a better solution would be to use a new function which takes argv array instead of one string with all the, correctly quoted and escaped, arguments concatenated together. Bug 787203 - Correctly quote and escape arguments of external programs passed to execute_command()
2017-09-03 01:52:54 -06:00
success &= ! execute_command( "mount -v -t btrfs " + Glib::shell_quote( path ) +
" " + Glib::shell_quote( mount_point ),
operationdetail, EXEC_CHECK_STATUS );
}
else
mount_point = partition_new .get_mountpoint() ;
if ( success )
{
Glib::ustring size ;
if ( ! fill_partition )
size = Utils::num_to_str( floor( Utils::sector_to_unit(
partition_new .get_sector_length(), partition_new .sector_size, UNIT_KIB ) ) ) + "K" ;
else
size = "max" ;
Glib::ustring cmd ;
if ( btrfs_found )
Correctly quote and escape arguments passed to external commands (#787203) Trying to set a file system label to (including the double quotes): " --help " fails. For example labelling an ext4 file system would try to run this command: # e2label /dev/sdb1 "" --help "" Usage: e2label device [newlabel] # echo $? 1 Alternatively trying to create a file system with a label of just a double quote also fails. The Applying Pending Operations dialog waits forever and won't cancel or force cancel. Have to use the window manager close window button to close the dialog. Also GParted reports this error to the console: (gpartedbin:9648): glibmm-CRITICAL **: unhandled exception (type Glib::Error) in signal handler: domain: g-shell-error-quark code : 0 what : Text ended before matching quote was found for ". (The text was 'mkfs.xfs -f -L """ /dev/sdb2') Command strings are parsed and split into argv array by function Glib::shell_parse_argv() which calls internal glib function tokenize_command_line() for shell tokenization. It expects the command string to be properly quoted and escaped and after tokenization, calls g_shell_unquote() on every parsed argument. So to prevent constructing incorrect commands, every non-static string needs to be properly quoted. GParted only puts labels and mount points into double quotes, but has not escaped special characters in those values itself. This patch fixes all these problems by using Glib::shell_quote() on all variable values. Labels, mount points, paths and all others too. Probably a better solution would be to use a new function which takes argv array instead of one string with all the, correctly quoted and escaped, arguments concatenated together. Bug 787203 - Correctly quote and escape arguments of external programs passed to execute_command()
2017-09-03 01:52:54 -06:00
cmd = "btrfs filesystem resize " + devid_str + ":" + size + " " + Glib::shell_quote( mount_point );
else
Correctly quote and escape arguments passed to external commands (#787203) Trying to set a file system label to (including the double quotes): " --help " fails. For example labelling an ext4 file system would try to run this command: # e2label /dev/sdb1 "" --help "" Usage: e2label device [newlabel] # echo $? 1 Alternatively trying to create a file system with a label of just a double quote also fails. The Applying Pending Operations dialog waits forever and won't cancel or force cancel. Have to use the window manager close window button to close the dialog. Also GParted reports this error to the console: (gpartedbin:9648): glibmm-CRITICAL **: unhandled exception (type Glib::Error) in signal handler: domain: g-shell-error-quark code : 0 what : Text ended before matching quote was found for ". (The text was 'mkfs.xfs -f -L """ /dev/sdb2') Command strings are parsed and split into argv array by function Glib::shell_parse_argv() which calls internal glib function tokenize_command_line() for shell tokenization. It expects the command string to be properly quoted and escaped and after tokenization, calls g_shell_unquote() on every parsed argument. So to prevent constructing incorrect commands, every non-static string needs to be properly quoted. GParted only puts labels and mount points into double quotes, but has not escaped special characters in those values itself. This patch fixes all these problems by using Glib::shell_quote() on all variable values. Labels, mount points, paths and all others too. Probably a better solution would be to use a new function which takes argv array instead of one string with all the, correctly quoted and escaped, arguments concatenated together. Bug 787203 - Correctly quote and escape arguments of external programs passed to execute_command()
2017-09-03 01:52:54 -06:00
cmd = "btrfsctl -r " + devid_str + ":" + size + " " + Glib::shell_quote( mount_point );
success &= ! execute_command(cmd, operationdetail, EXEC_CHECK_STATUS);
if ( ! partition_new .busy )
Correctly quote and escape arguments passed to external commands (#787203) Trying to set a file system label to (including the double quotes): " --help " fails. For example labelling an ext4 file system would try to run this command: # e2label /dev/sdb1 "" --help "" Usage: e2label device [newlabel] # echo $? 1 Alternatively trying to create a file system with a label of just a double quote also fails. The Applying Pending Operations dialog waits forever and won't cancel or force cancel. Have to use the window manager close window button to close the dialog. Also GParted reports this error to the console: (gpartedbin:9648): glibmm-CRITICAL **: unhandled exception (type Glib::Error) in signal handler: domain: g-shell-error-quark code : 0 what : Text ended before matching quote was found for ". (The text was 'mkfs.xfs -f -L """ /dev/sdb2') Command strings are parsed and split into argv array by function Glib::shell_parse_argv() which calls internal glib function tokenize_command_line() for shell tokenization. It expects the command string to be properly quoted and escaped and after tokenization, calls g_shell_unquote() on every parsed argument. So to prevent constructing incorrect commands, every non-static string needs to be properly quoted. GParted only puts labels and mount points into double quotes, but has not escaped special characters in those values itself. This patch fixes all these problems by using Glib::shell_quote() on all variable values. Labels, mount points, paths and all others too. Probably a better solution would be to use a new function which takes argv array instead of one string with all the, correctly quoted and escaped, arguments concatenated together. Bug 787203 - Correctly quote and escape arguments of external programs passed to execute_command()
2017-09-03 01:52:54 -06:00
success &= ! execute_command( "umount -v " + Glib::shell_quote( mount_point ),
operationdetail, EXEC_CHECK_STATUS );
}
if ( ! partition_new .busy )
rm_temp_dir( mount_point, operationdetail ) ;
return success ;
}
void btrfs::read_label( Partition & partition )
{
if ( btrfs_found )
Correctly quote and escape arguments passed to external commands (#787203) Trying to set a file system label to (including the double quotes): " --help " fails. For example labelling an ext4 file system would try to run this command: # e2label /dev/sdb1 "" --help "" Usage: e2label device [newlabel] # echo $? 1 Alternatively trying to create a file system with a label of just a double quote also fails. The Applying Pending Operations dialog waits forever and won't cancel or force cancel. Have to use the window manager close window button to close the dialog. Also GParted reports this error to the console: (gpartedbin:9648): glibmm-CRITICAL **: unhandled exception (type Glib::Error) in signal handler: domain: g-shell-error-quark code : 0 what : Text ended before matching quote was found for ". (The text was 'mkfs.xfs -f -L """ /dev/sdb2') Command strings are parsed and split into argv array by function Glib::shell_parse_argv() which calls internal glib function tokenize_command_line() for shell tokenization. It expects the command string to be properly quoted and escaped and after tokenization, calls g_shell_unquote() on every parsed argument. So to prevent constructing incorrect commands, every non-static string needs to be properly quoted. GParted only puts labels and mount points into double quotes, but has not escaped special characters in those values itself. This patch fixes all these problems by using Glib::shell_quote() on all variable values. Labels, mount points, paths and all others too. Probably a better solution would be to use a new function which takes argv array instead of one string with all the, correctly quoted and escaped, arguments concatenated together. Bug 787203 - Correctly quote and escape arguments of external programs passed to execute_command()
2017-09-03 01:52:54 -06:00
Utils::execute_command( "btrfs filesystem show " + Glib::shell_quote( partition.get_path() ),
output, error, true );
Update parsing of btrfs filesystem show for the label (#733601) Issue 2/2 - GParted doesn't show label for mounted btrfs file systems 'btrfs filesystem show /dev/PTN' command is used to query details of a btrfs file system including reading the file system label. When the file system is mounted the label is no longer enclosed in single quotes, but only when using btrfs-progs v3.12. This causes GParted to think the label is blank when the file system is mounted and therefore no longer display it. File system label not enclosed in single quotes when mounted: # fgrep sdb1 /proc/mounts /dev/sdb1 /mnt/1 btrfs rw,relatime,space_cache 0 0 # btrfs filesystem show /dev/sdb1 Label: test1-btrfs uuid: 1f78fa38-2f85-41d3-9be6-ae0356ae9469 Total devices 1 FS bytes used 192.00KiB devid 1 size 2.00GiB used 240.75MiB path /dev/sdb1 Btrfs v3.12 File system label enclosed in single quotes when unmounted: # umount /dev/sdb1 # btrfs filesystem show /dev/sdb1 Label: 'test1-btrfs' uuid: 1f78fa38-2f85-41d3-9be6-ae0356ae9469 Total devices 1 FS bytes used 192.00KiB devid 1 size 2.00GiB used 240.75MiB path /dev/sdb1 Btrfs v3.12 Removing the single quotes enclosing the label makes the output identical to that from the older 'btrfs-show' command. Fix by using a common parser to extract the label from both the 'btrfs filesystem show' and 'btrfs-show' commands which can read the label with and without enclosing single quotes. Patch 2/4 - btrfs::read_label() This patch changes the btrfs file system label parsing code to resolve issue 1/2 by ignoring the exit status from the 'btrfs filesystem show' command and relying on parsing the required information to determine success or failure. Issue 2/2 is also resolved as described above. Bug #733601 - Btrfs: Warnings and missing label with btrfs-progs 3.12 and 3.14
2014-07-22 17:19:32 -06:00
else
Correctly quote and escape arguments passed to external commands (#787203) Trying to set a file system label to (including the double quotes): " --help " fails. For example labelling an ext4 file system would try to run this command: # e2label /dev/sdb1 "" --help "" Usage: e2label device [newlabel] # echo $? 1 Alternatively trying to create a file system with a label of just a double quote also fails. The Applying Pending Operations dialog waits forever and won't cancel or force cancel. Have to use the window manager close window button to close the dialog. Also GParted reports this error to the console: (gpartedbin:9648): glibmm-CRITICAL **: unhandled exception (type Glib::Error) in signal handler: domain: g-shell-error-quark code : 0 what : Text ended before matching quote was found for ". (The text was 'mkfs.xfs -f -L """ /dev/sdb2') Command strings are parsed and split into argv array by function Glib::shell_parse_argv() which calls internal glib function tokenize_command_line() for shell tokenization. It expects the command string to be properly quoted and escaped and after tokenization, calls g_shell_unquote() on every parsed argument. So to prevent constructing incorrect commands, every non-static string needs to be properly quoted. GParted only puts labels and mount points into double quotes, but has not escaped special characters in those values itself. This patch fixes all these problems by using Glib::shell_quote() on all variable values. Labels, mount points, paths and all others too. Probably a better solution would be to use a new function which takes argv array instead of one string with all the, correctly quoted and escaped, arguments concatenated together. Bug 787203 - Correctly quote and escape arguments of external programs passed to execute_command()
2017-09-03 01:52:54 -06:00
Utils::execute_command( "btrfs-show " + Glib::shell_quote( partition.get_path() ),
output, error, true );
Update parsing of btrfs filesystem show for the label (#733601) Issue 2/2 - GParted doesn't show label for mounted btrfs file systems 'btrfs filesystem show /dev/PTN' command is used to query details of a btrfs file system including reading the file system label. When the file system is mounted the label is no longer enclosed in single quotes, but only when using btrfs-progs v3.12. This causes GParted to think the label is blank when the file system is mounted and therefore no longer display it. File system label not enclosed in single quotes when mounted: # fgrep sdb1 /proc/mounts /dev/sdb1 /mnt/1 btrfs rw,relatime,space_cache 0 0 # btrfs filesystem show /dev/sdb1 Label: test1-btrfs uuid: 1f78fa38-2f85-41d3-9be6-ae0356ae9469 Total devices 1 FS bytes used 192.00KiB devid 1 size 2.00GiB used 240.75MiB path /dev/sdb1 Btrfs v3.12 File system label enclosed in single quotes when unmounted: # umount /dev/sdb1 # btrfs filesystem show /dev/sdb1 Label: 'test1-btrfs' uuid: 1f78fa38-2f85-41d3-9be6-ae0356ae9469 Total devices 1 FS bytes used 192.00KiB devid 1 size 2.00GiB used 240.75MiB path /dev/sdb1 Btrfs v3.12 Removing the single quotes enclosing the label makes the output identical to that from the older 'btrfs-show' command. Fix by using a common parser to extract the label from both the 'btrfs filesystem show' and 'btrfs-show' commands which can read the label with and without enclosing single quotes. Patch 2/4 - btrfs::read_label() This patch changes the btrfs file system label parsing code to resolve issue 1/2 by ignoring the exit status from the 'btrfs filesystem show' command and relying on parsing the required information to determine success or failure. Issue 2/2 is also resolved as described above. Bug #733601 - Btrfs: Warnings and missing label with btrfs-progs 3.12 and 3.14
2014-07-22 17:19:32 -06:00
//In many cases the exit status doesn't reflect valid output or an error condition
// so rely on parsing the output to determine success.
if ( output .compare( 0, 18, "Label: none uuid:" ) == 0 )
{
Update parsing of btrfs filesystem show for the label (#733601) Issue 2/2 - GParted doesn't show label for mounted btrfs file systems 'btrfs filesystem show /dev/PTN' command is used to query details of a btrfs file system including reading the file system label. When the file system is mounted the label is no longer enclosed in single quotes, but only when using btrfs-progs v3.12. This causes GParted to think the label is blank when the file system is mounted and therefore no longer display it. File system label not enclosed in single quotes when mounted: # fgrep sdb1 /proc/mounts /dev/sdb1 /mnt/1 btrfs rw,relatime,space_cache 0 0 # btrfs filesystem show /dev/sdb1 Label: test1-btrfs uuid: 1f78fa38-2f85-41d3-9be6-ae0356ae9469 Total devices 1 FS bytes used 192.00KiB devid 1 size 2.00GiB used 240.75MiB path /dev/sdb1 Btrfs v3.12 File system label enclosed in single quotes when unmounted: # umount /dev/sdb1 # btrfs filesystem show /dev/sdb1 Label: 'test1-btrfs' uuid: 1f78fa38-2f85-41d3-9be6-ae0356ae9469 Total devices 1 FS bytes used 192.00KiB devid 1 size 2.00GiB used 240.75MiB path /dev/sdb1 Btrfs v3.12 Removing the single quotes enclosing the label makes the output identical to that from the older 'btrfs-show' command. Fix by using a common parser to extract the label from both the 'btrfs filesystem show' and 'btrfs-show' commands which can read the label with and without enclosing single quotes. Patch 2/4 - btrfs::read_label() This patch changes the btrfs file system label parsing code to resolve issue 1/2 by ignoring the exit status from the 'btrfs filesystem show' command and relying on parsing the required information to determine success or failure. Issue 2/2 is also resolved as described above. Bug #733601 - Btrfs: Warnings and missing label with btrfs-progs 3.12 and 3.14
2014-07-22 17:19:32 -06:00
//Indistinguishable cases of either no label or the label is actually set
// to "none". Assume no label case.
partition.set_filesystem_label( "" );
}
else
{
Update parsing of btrfs filesystem show for the label (#733601) Issue 2/2 - GParted doesn't show label for mounted btrfs file systems 'btrfs filesystem show /dev/PTN' command is used to query details of a btrfs file system including reading the file system label. When the file system is mounted the label is no longer enclosed in single quotes, but only when using btrfs-progs v3.12. This causes GParted to think the label is blank when the file system is mounted and therefore no longer display it. File system label not enclosed in single quotes when mounted: # fgrep sdb1 /proc/mounts /dev/sdb1 /mnt/1 btrfs rw,relatime,space_cache 0 0 # btrfs filesystem show /dev/sdb1 Label: test1-btrfs uuid: 1f78fa38-2f85-41d3-9be6-ae0356ae9469 Total devices 1 FS bytes used 192.00KiB devid 1 size 2.00GiB used 240.75MiB path /dev/sdb1 Btrfs v3.12 File system label enclosed in single quotes when unmounted: # umount /dev/sdb1 # btrfs filesystem show /dev/sdb1 Label: 'test1-btrfs' uuid: 1f78fa38-2f85-41d3-9be6-ae0356ae9469 Total devices 1 FS bytes used 192.00KiB devid 1 size 2.00GiB used 240.75MiB path /dev/sdb1 Btrfs v3.12 Removing the single quotes enclosing the label makes the output identical to that from the older 'btrfs-show' command. Fix by using a common parser to extract the label from both the 'btrfs filesystem show' and 'btrfs-show' commands which can read the label with and without enclosing single quotes. Patch 2/4 - btrfs::read_label() This patch changes the btrfs file system label parsing code to resolve issue 1/2 by ignoring the exit status from the 'btrfs filesystem show' command and relying on parsing the required information to determine success or failure. Issue 2/2 is also resolved as described above. Bug #733601 - Btrfs: Warnings and missing label with btrfs-progs 3.12 and 3.14
2014-07-22 17:19:32 -06:00
//Try matching a label enclosed in single quotes, as used by
// btrfs filesystem show, then without quotes, as used by btrfs-show.
Glib::ustring label = Utils::regexp_label( output, "^Label: '(.*)' uuid:" ) ;
if ( label .empty() )
label = Utils::regexp_label( output, "^Label: (.*) uuid:" ) ;
if ( ! label .empty() )
partition.set_filesystem_label( label );
Update parsing of btrfs filesystem show for the label (#733601) Issue 2/2 - GParted doesn't show label for mounted btrfs file systems 'btrfs filesystem show /dev/PTN' command is used to query details of a btrfs file system including reading the file system label. When the file system is mounted the label is no longer enclosed in single quotes, but only when using btrfs-progs v3.12. This causes GParted to think the label is blank when the file system is mounted and therefore no longer display it. File system label not enclosed in single quotes when mounted: # fgrep sdb1 /proc/mounts /dev/sdb1 /mnt/1 btrfs rw,relatime,space_cache 0 0 # btrfs filesystem show /dev/sdb1 Label: test1-btrfs uuid: 1f78fa38-2f85-41d3-9be6-ae0356ae9469 Total devices 1 FS bytes used 192.00KiB devid 1 size 2.00GiB used 240.75MiB path /dev/sdb1 Btrfs v3.12 File system label enclosed in single quotes when unmounted: # umount /dev/sdb1 # btrfs filesystem show /dev/sdb1 Label: 'test1-btrfs' uuid: 1f78fa38-2f85-41d3-9be6-ae0356ae9469 Total devices 1 FS bytes used 192.00KiB devid 1 size 2.00GiB used 240.75MiB path /dev/sdb1 Btrfs v3.12 Removing the single quotes enclosing the label makes the output identical to that from the older 'btrfs-show' command. Fix by using a common parser to extract the label from both the 'btrfs filesystem show' and 'btrfs-show' commands which can read the label with and without enclosing single quotes. Patch 2/4 - btrfs::read_label() This patch changes the btrfs file system label parsing code to resolve issue 1/2 by ignoring the exit status from the 'btrfs filesystem show' command and relying on parsing the required information to determine success or failure. Issue 2/2 is also resolved as described above. Bug #733601 - Btrfs: Warnings and missing label with btrfs-progs 3.12 and 3.14
2014-07-22 17:19:32 -06:00
else
{
Update parsing of btrfs filesystem show for the label (#733601) Issue 2/2 - GParted doesn't show label for mounted btrfs file systems 'btrfs filesystem show /dev/PTN' command is used to query details of a btrfs file system including reading the file system label. When the file system is mounted the label is no longer enclosed in single quotes, but only when using btrfs-progs v3.12. This causes GParted to think the label is blank when the file system is mounted and therefore no longer display it. File system label not enclosed in single quotes when mounted: # fgrep sdb1 /proc/mounts /dev/sdb1 /mnt/1 btrfs rw,relatime,space_cache 0 0 # btrfs filesystem show /dev/sdb1 Label: test1-btrfs uuid: 1f78fa38-2f85-41d3-9be6-ae0356ae9469 Total devices 1 FS bytes used 192.00KiB devid 1 size 2.00GiB used 240.75MiB path /dev/sdb1 Btrfs v3.12 File system label enclosed in single quotes when unmounted: # umount /dev/sdb1 # btrfs filesystem show /dev/sdb1 Label: 'test1-btrfs' uuid: 1f78fa38-2f85-41d3-9be6-ae0356ae9469 Total devices 1 FS bytes used 192.00KiB devid 1 size 2.00GiB used 240.75MiB path /dev/sdb1 Btrfs v3.12 Removing the single quotes enclosing the label makes the output identical to that from the older 'btrfs-show' command. Fix by using a common parser to extract the label from both the 'btrfs filesystem show' and 'btrfs-show' commands which can read the label with and without enclosing single quotes. Patch 2/4 - btrfs::read_label() This patch changes the btrfs file system label parsing code to resolve issue 1/2 by ignoring the exit status from the 'btrfs filesystem show' command and relying on parsing the required information to determine success or failure. Issue 2/2 is also resolved as described above. Bug #733601 - Btrfs: Warnings and missing label with btrfs-progs 3.12 and 3.14
2014-07-22 17:19:32 -06:00
if ( ! output .empty() )
Display messages for encrypted file systems (#760080) At the moment any messages for an encrypted file system aren't shown, only messages from the outer PartitionLUKS object are shown. Also in Win_GParted::activate_paste() the selected Partition object, possibly a derived PartitionLUKS, is cloned and the messages cleared. Therefore a set of accessor methods must be provided to query and modify partition messages. Messages will be stored in the Partition object to which they are added and retrieved from all. So in the case of a derived PartitionLUKS they will be retrieved from the messages vector of the PartitionLUKS object itself and the messages vector for the encrypted file system it contains. To replace code like this in GParted_Core: partition_temp->messages = messages; We might naturally provide a set_messages() method which assigns the messages vector and is used like this: partition_temp->set_messages( messages ); However on a PartitionLUKS object what should set_messages() do? By the name it will replace any existing messages in the PartitionLUKS object itself, but what should happen to the messages for the contained encrypted Partition object? Should they be cleared or left alone? Rather than implement set_messages() with unclear semantics implement append_messages(), which in the PartitionLUKS object case will clearly leave any messages for the contained encrypted Partition object alone. Append_messages() is then used to add messages as the Partition or PartitionLUKS objects when populating the data in GParted_Core. Bug 760080 - Implement read-only LUKS support
2015-12-31 09:32:08 -07:00
partition.push_back_message( output );
Update parsing of btrfs filesystem show for the label (#733601) Issue 2/2 - GParted doesn't show label for mounted btrfs file systems 'btrfs filesystem show /dev/PTN' command is used to query details of a btrfs file system including reading the file system label. When the file system is mounted the label is no longer enclosed in single quotes, but only when using btrfs-progs v3.12. This causes GParted to think the label is blank when the file system is mounted and therefore no longer display it. File system label not enclosed in single quotes when mounted: # fgrep sdb1 /proc/mounts /dev/sdb1 /mnt/1 btrfs rw,relatime,space_cache 0 0 # btrfs filesystem show /dev/sdb1 Label: test1-btrfs uuid: 1f78fa38-2f85-41d3-9be6-ae0356ae9469 Total devices 1 FS bytes used 192.00KiB devid 1 size 2.00GiB used 240.75MiB path /dev/sdb1 Btrfs v3.12 File system label enclosed in single quotes when unmounted: # umount /dev/sdb1 # btrfs filesystem show /dev/sdb1 Label: 'test1-btrfs' uuid: 1f78fa38-2f85-41d3-9be6-ae0356ae9469 Total devices 1 FS bytes used 192.00KiB devid 1 size 2.00GiB used 240.75MiB path /dev/sdb1 Btrfs v3.12 Removing the single quotes enclosing the label makes the output identical to that from the older 'btrfs-show' command. Fix by using a common parser to extract the label from both the 'btrfs filesystem show' and 'btrfs-show' commands which can read the label with and without enclosing single quotes. Patch 2/4 - btrfs::read_label() This patch changes the btrfs file system label parsing code to resolve issue 1/2 by ignoring the exit status from the 'btrfs filesystem show' command and relying on parsing the required information to determine success or failure. Issue 2/2 is also resolved as described above. Bug #733601 - Btrfs: Warnings and missing label with btrfs-progs 3.12 and 3.14
2014-07-22 17:19:32 -06:00
if ( ! error .empty() )
Display messages for encrypted file systems (#760080) At the moment any messages for an encrypted file system aren't shown, only messages from the outer PartitionLUKS object are shown. Also in Win_GParted::activate_paste() the selected Partition object, possibly a derived PartitionLUKS, is cloned and the messages cleared. Therefore a set of accessor methods must be provided to query and modify partition messages. Messages will be stored in the Partition object to which they are added and retrieved from all. So in the case of a derived PartitionLUKS they will be retrieved from the messages vector of the PartitionLUKS object itself and the messages vector for the encrypted file system it contains. To replace code like this in GParted_Core: partition_temp->messages = messages; We might naturally provide a set_messages() method which assigns the messages vector and is used like this: partition_temp->set_messages( messages ); However on a PartitionLUKS object what should set_messages() do? By the name it will replace any existing messages in the PartitionLUKS object itself, but what should happen to the messages for the contained encrypted Partition object? Should they be cleared or left alone? Rather than implement set_messages() with unclear semantics implement append_messages(), which in the PartitionLUKS object case will clearly leave any messages for the contained encrypted Partition object alone. Append_messages() is then used to add messages as the Partition or PartitionLUKS objects when populating the data in GParted_Core. Bug 760080 - Implement read-only LUKS support
2015-12-31 09:32:08 -07:00
partition.push_back_message( error );
Update parsing of btrfs filesystem show for the label (#733601) Issue 2/2 - GParted doesn't show label for mounted btrfs file systems 'btrfs filesystem show /dev/PTN' command is used to query details of a btrfs file system including reading the file system label. When the file system is mounted the label is no longer enclosed in single quotes, but only when using btrfs-progs v3.12. This causes GParted to think the label is blank when the file system is mounted and therefore no longer display it. File system label not enclosed in single quotes when mounted: # fgrep sdb1 /proc/mounts /dev/sdb1 /mnt/1 btrfs rw,relatime,space_cache 0 0 # btrfs filesystem show /dev/sdb1 Label: test1-btrfs uuid: 1f78fa38-2f85-41d3-9be6-ae0356ae9469 Total devices 1 FS bytes used 192.00KiB devid 1 size 2.00GiB used 240.75MiB path /dev/sdb1 Btrfs v3.12 File system label enclosed in single quotes when unmounted: # umount /dev/sdb1 # btrfs filesystem show /dev/sdb1 Label: 'test1-btrfs' uuid: 1f78fa38-2f85-41d3-9be6-ae0356ae9469 Total devices 1 FS bytes used 192.00KiB devid 1 size 2.00GiB used 240.75MiB path /dev/sdb1 Btrfs v3.12 Removing the single quotes enclosing the label makes the output identical to that from the older 'btrfs-show' command. Fix by using a common parser to extract the label from both the 'btrfs filesystem show' and 'btrfs-show' commands which can read the label with and without enclosing single quotes. Patch 2/4 - btrfs::read_label() This patch changes the btrfs file system label parsing code to resolve issue 1/2 by ignoring the exit status from the 'btrfs filesystem show' command and relying on parsing the required information to determine success or failure. Issue 2/2 is also resolved as described above. Bug #733601 - Btrfs: Warnings and missing label with btrfs-progs 3.12 and 3.14
2014-07-22 17:19:32 -06:00
}
}
}
void btrfs::read_uuid( Partition & partition )
{
if ( btrfs_found )
Correctly quote and escape arguments passed to external commands (#787203) Trying to set a file system label to (including the double quotes): " --help " fails. For example labelling an ext4 file system would try to run this command: # e2label /dev/sdb1 "" --help "" Usage: e2label device [newlabel] # echo $? 1 Alternatively trying to create a file system with a label of just a double quote also fails. The Applying Pending Operations dialog waits forever and won't cancel or force cancel. Have to use the window manager close window button to close the dialog. Also GParted reports this error to the console: (gpartedbin:9648): glibmm-CRITICAL **: unhandled exception (type Glib::Error) in signal handler: domain: g-shell-error-quark code : 0 what : Text ended before matching quote was found for ". (The text was 'mkfs.xfs -f -L """ /dev/sdb2') Command strings are parsed and split into argv array by function Glib::shell_parse_argv() which calls internal glib function tokenize_command_line() for shell tokenization. It expects the command string to be properly quoted and escaped and after tokenization, calls g_shell_unquote() on every parsed argument. So to prevent constructing incorrect commands, every non-static string needs to be properly quoted. GParted only puts labels and mount points into double quotes, but has not escaped special characters in those values itself. This patch fixes all these problems by using Glib::shell_quote() on all variable values. Labels, mount points, paths and all others too. Probably a better solution would be to use a new function which takes argv array instead of one string with all the, correctly quoted and escaped, arguments concatenated together. Bug 787203 - Correctly quote and escape arguments of external programs passed to execute_command()
2017-09-03 01:52:54 -06:00
Utils::execute_command( "btrfs filesystem show " + Glib::shell_quote( partition.get_path() ),
output, error, true );
Update parsing of btrfs filesystem show for the UUID (#733601) Issue 1/2 - GParted shows warnings for mounted btrfs file systems 'btrfs filesystem show /dev/PTN' command is used to query details of a btrfs file system. When the file system is mounted the command reports failed exit status 1, but only when using btrfs-progs v3.14 and v3.14.1. This causes GParted to: (1) report warnings from the failed commands for a mounted btrfs file system, (2) fail to determine file system usage figures and (3) fail to display the mount point and busy indicator for non-mounting devices in multi-device btrfs file systems. The label is also read using the secondary blkid method via the FS_Info cache. Failed exit status 1 when the btrfs file system is mounted: # fgrep sdb1 /proc/mounts /dev/sdb1 /mnt/1 btrfs rw,seclabel,relatime,space_cache 0 0 # btrfs filesystem show /dev/sdb1 Label: 'test1-btrfs' uuid: 033e6b07-ee6a-4620-a585-8580a2b83275 Total devices 1 FS bytes used 192.00KiB devid 1 size 2.00GiB used 240.75MiB path /dev/sdb1 Btrfs v3.14.1 # echo $? 1 Successful exit status 0 when the btrfs file system is unmounted: # umount /dev/sdb1 # btrfs filesystem show /dev/sdb1 Label: 'test1-btrfs' uuid: 033e6b07-ee6a-4620-a585-8580a2b83275 Total devices 1 FS bytes used 192.00KiB devid 1 size 2.00GiB used 240.75MiB path /dev/sdb1 Btrfs v3.14.1 # echo $? 0 Fix by ignoring the exit status of the 'btrfs filesystem show' command and rely on parsing the required information to determine success or failure. The output from the older 'btrfs-show' command is almost identical so the same code will parse it in all cases. Patch 1/4 - btrfs::read_uuid() This patch changes the secondary method used to read the btrfs UUID to resolve issue 1/2 as described above. Bug #733601 - Btrfs: Warnings and missing label with btrfs-progs 3.12 and 3.14
2014-07-22 10:57:33 -06:00
else
Correctly quote and escape arguments passed to external commands (#787203) Trying to set a file system label to (including the double quotes): " --help " fails. For example labelling an ext4 file system would try to run this command: # e2label /dev/sdb1 "" --help "" Usage: e2label device [newlabel] # echo $? 1 Alternatively trying to create a file system with a label of just a double quote also fails. The Applying Pending Operations dialog waits forever and won't cancel or force cancel. Have to use the window manager close window button to close the dialog. Also GParted reports this error to the console: (gpartedbin:9648): glibmm-CRITICAL **: unhandled exception (type Glib::Error) in signal handler: domain: g-shell-error-quark code : 0 what : Text ended before matching quote was found for ". (The text was 'mkfs.xfs -f -L """ /dev/sdb2') Command strings are parsed and split into argv array by function Glib::shell_parse_argv() which calls internal glib function tokenize_command_line() for shell tokenization. It expects the command string to be properly quoted and escaped and after tokenization, calls g_shell_unquote() on every parsed argument. So to prevent constructing incorrect commands, every non-static string needs to be properly quoted. GParted only puts labels and mount points into double quotes, but has not escaped special characters in those values itself. This patch fixes all these problems by using Glib::shell_quote() on all variable values. Labels, mount points, paths and all others too. Probably a better solution would be to use a new function which takes argv array instead of one string with all the, correctly quoted and escaped, arguments concatenated together. Bug 787203 - Correctly quote and escape arguments of external programs passed to execute_command()
2017-09-03 01:52:54 -06:00
Utils::execute_command( "btrfs-show " + Glib::shell_quote( partition.get_path() ),
output, error, true );
Update parsing of btrfs filesystem show for the UUID (#733601) Issue 1/2 - GParted shows warnings for mounted btrfs file systems 'btrfs filesystem show /dev/PTN' command is used to query details of a btrfs file system. When the file system is mounted the command reports failed exit status 1, but only when using btrfs-progs v3.14 and v3.14.1. This causes GParted to: (1) report warnings from the failed commands for a mounted btrfs file system, (2) fail to determine file system usage figures and (3) fail to display the mount point and busy indicator for non-mounting devices in multi-device btrfs file systems. The label is also read using the secondary blkid method via the FS_Info cache. Failed exit status 1 when the btrfs file system is mounted: # fgrep sdb1 /proc/mounts /dev/sdb1 /mnt/1 btrfs rw,seclabel,relatime,space_cache 0 0 # btrfs filesystem show /dev/sdb1 Label: 'test1-btrfs' uuid: 033e6b07-ee6a-4620-a585-8580a2b83275 Total devices 1 FS bytes used 192.00KiB devid 1 size 2.00GiB used 240.75MiB path /dev/sdb1 Btrfs v3.14.1 # echo $? 1 Successful exit status 0 when the btrfs file system is unmounted: # umount /dev/sdb1 # btrfs filesystem show /dev/sdb1 Label: 'test1-btrfs' uuid: 033e6b07-ee6a-4620-a585-8580a2b83275 Total devices 1 FS bytes used 192.00KiB devid 1 size 2.00GiB used 240.75MiB path /dev/sdb1 Btrfs v3.14.1 # echo $? 0 Fix by ignoring the exit status of the 'btrfs filesystem show' command and rely on parsing the required information to determine success or failure. The output from the older 'btrfs-show' command is almost identical so the same code will parse it in all cases. Patch 1/4 - btrfs::read_uuid() This patch changes the secondary method used to read the btrfs UUID to resolve issue 1/2 as described above. Bug #733601 - Btrfs: Warnings and missing label with btrfs-progs 3.12 and 3.14
2014-07-22 10:57:33 -06:00
//In many cases the exit status doesn't reflect valid output or an error condition
// so rely on parsing the output to determine success.
Glib::ustring uuid_str = Utils::regexp_label( output, "uuid:[[:blank:]]*(" RFC4122_NONE_NIL_UUID_REGEXP ")" ) ;
if ( ! uuid_str .empty() )
partition .uuid = uuid_str ;
else
{
if ( ! output .empty() )
Display messages for encrypted file systems (#760080) At the moment any messages for an encrypted file system aren't shown, only messages from the outer PartitionLUKS object are shown. Also in Win_GParted::activate_paste() the selected Partition object, possibly a derived PartitionLUKS, is cloned and the messages cleared. Therefore a set of accessor methods must be provided to query and modify partition messages. Messages will be stored in the Partition object to which they are added and retrieved from all. So in the case of a derived PartitionLUKS they will be retrieved from the messages vector of the PartitionLUKS object itself and the messages vector for the encrypted file system it contains. To replace code like this in GParted_Core: partition_temp->messages = messages; We might naturally provide a set_messages() method which assigns the messages vector and is used like this: partition_temp->set_messages( messages ); However on a PartitionLUKS object what should set_messages() do? By the name it will replace any existing messages in the PartitionLUKS object itself, but what should happen to the messages for the contained encrypted Partition object? Should they be cleared or left alone? Rather than implement set_messages() with unclear semantics implement append_messages(), which in the PartitionLUKS object case will clearly leave any messages for the contained encrypted Partition object alone. Append_messages() is then used to add messages as the Partition or PartitionLUKS objects when populating the data in GParted_Core. Bug 760080 - Implement read-only LUKS support
2015-12-31 09:32:08 -07:00
partition.push_back_message( output );
if ( ! error .empty() )
Display messages for encrypted file systems (#760080) At the moment any messages for an encrypted file system aren't shown, only messages from the outer PartitionLUKS object are shown. Also in Win_GParted::activate_paste() the selected Partition object, possibly a derived PartitionLUKS, is cloned and the messages cleared. Therefore a set of accessor methods must be provided to query and modify partition messages. Messages will be stored in the Partition object to which they are added and retrieved from all. So in the case of a derived PartitionLUKS they will be retrieved from the messages vector of the PartitionLUKS object itself and the messages vector for the encrypted file system it contains. To replace code like this in GParted_Core: partition_temp->messages = messages; We might naturally provide a set_messages() method which assigns the messages vector and is used like this: partition_temp->set_messages( messages ); However on a PartitionLUKS object what should set_messages() do? By the name it will replace any existing messages in the PartitionLUKS object itself, but what should happen to the messages for the contained encrypted Partition object? Should they be cleared or left alone? Rather than implement set_messages() with unclear semantics implement append_messages(), which in the PartitionLUKS object case will clearly leave any messages for the contained encrypted Partition object alone. Append_messages() is then used to add messages as the Partition or PartitionLUKS objects when populating the data in GParted_Core. Bug 760080 - Implement read-only LUKS support
2015-12-31 09:32:08 -07:00
partition.push_back_message( error );
}
}
bool btrfs::write_uuid( const Partition & partition, OperationDetail & operationdetail )
{
Correctly quote and escape arguments passed to external commands (#787203) Trying to set a file system label to (including the double quotes): " --help " fails. For example labelling an ext4 file system would try to run this command: # e2label /dev/sdb1 "" --help "" Usage: e2label device [newlabel] # echo $? 1 Alternatively trying to create a file system with a label of just a double quote also fails. The Applying Pending Operations dialog waits forever and won't cancel or force cancel. Have to use the window manager close window button to close the dialog. Also GParted reports this error to the console: (gpartedbin:9648): glibmm-CRITICAL **: unhandled exception (type Glib::Error) in signal handler: domain: g-shell-error-quark code : 0 what : Text ended before matching quote was found for ". (The text was 'mkfs.xfs -f -L """ /dev/sdb2') Command strings are parsed and split into argv array by function Glib::shell_parse_argv() which calls internal glib function tokenize_command_line() for shell tokenization. It expects the command string to be properly quoted and escaped and after tokenization, calls g_shell_unquote() on every parsed argument. So to prevent constructing incorrect commands, every non-static string needs to be properly quoted. GParted only puts labels and mount points into double quotes, but has not escaped special characters in those values itself. This patch fixes all these problems by using Glib::shell_quote() on all variable values. Labels, mount points, paths and all others too. Probably a better solution would be to use a new function which takes argv array instead of one string with all the, correctly quoted and escaped, arguments concatenated together. Bug 787203 - Correctly quote and escape arguments of external programs passed to execute_command()
2017-09-03 01:52:54 -06:00
return ! execute_command( "btrfstune -f -u " + Glib::shell_quote( partition.get_path() ),
operationdetail, EXEC_CHECK_STATUS );
}
Detect busy status of multi-device btrfs file systems (#723842) Busy detection of file systems works by checking if the device is mounted (appears in the mount_info map). For a multi-device btrfs file system this will only report one of the devices as busy, not all of them. # btrfs filesystem show /dev/sdb1 Label: none uuid: 36eb51a2-2927-4c92-820f-b2f0b5cdae50 Total devices 2 FS bytes used 156.00KB devid 2 size 2.00GB used 512.00MB path /dev/sdb2 devid 1 size 2.00GB used 240.75MB path /dev/sdb1 # mount /dev/sdb1 /mnt/1 # grep btrfs /proc/mounts /dev/sdb1 /mnt/1 btrfs rw,seclabel,relatime,ssd,space_cache 0 0 GParted will only report /dev/sdb1 as busy, but not /dev/sdb2. Add btrfs specific is_busy() method which reports the device as busy if any of the devices in the btrfs file system are mounted. This uses a cache which maps device membership in all btrfs file systems. The cache is cleared on GParted refresh and incrementally populated as each btrfs partition is checked for busy status. WARNING: Removal of the mounting device from a btrfs file system makes it impossible to determine whether the file system is mounted or not for linux <= 3.4. This is because /proc/mounts continues to show the old device which is no longer a member of the file system. # btrfs device delete /dev/sdb1 /mnt/1 # sync # grep btrfs /proc/mounts /dev/sdb1 /mnt/1 btrfs rw,seclabel,relatime,ssd,space_cache 0 0 # btrfs filesystem show /dev/sdb1 # btrfs filesystem show /dev/sdb2 Label: none uuid: 36eb51a2-2927-4c92-820f-b2f0b5cdae50 Total devices 1 FS bytes used 28.00KB devid 2 size 2.00GB used 1.02GB path /dev/sdb2 Fixed in linux 3.5 by commit: Btrfs: implement ->show_devname https://git.kernel.org/cgit/linux/kernel/git/torvalds/linux.git/commit/?id=9c5085c147989d48dfe74194b48affc23f376650 Bug #723842 - GParted resizes the wrong filesystem (does not pass the devid to btrfs filesystem resize)
2014-02-17 15:39:34 -07:00
void btrfs::clear_cache()
{
btrfs_device_cache .clear() ;
}
//Return the device which is mounting the btrfs in this partition.
// Return empty string if not found (not mounted).
Glib::ustring btrfs::get_mount_device( const Glib::ustring & path )
{
BTRFS_Device btrfs_dev = get_cache_entry( path ) ;
if ( btrfs_dev .devid == -1 || btrfs_dev .members .empty() )
{
//WARNING:
// No btrfs device cache entry found or entry without any member devices.
// Use fallback busy detection method which can only determine if the
// mounting device is mounted or not, not any of the other members of a
// multi-device btrfs file system.
if ( Mount_Info::is_dev_mounted( path ) )
return path ;
return "" ;
}
for ( unsigned int i = 0 ; i < btrfs_dev .members .size() ; i ++ )
if ( Mount_Info::is_dev_mounted( btrfs_dev.members[i] ) )
return btrfs_dev.members[i].m_name;
return "" ;
}
std::vector<Glib::ustring> btrfs::get_members( const Glib::ustring & path )
{
BTRFS_Device btrfs_dev = get_cache_entry( path ) ;
std::vector<Glib::ustring> membs;
for ( unsigned int i = 0 ; i < btrfs_dev.members.size() ; i ++ )
membs.push_back( btrfs_dev.members[i].m_name );
return membs;
}
Handle btrfs tools rounding of figures (#499202) The btrfs programs only provide approximations of file system sizes because they display figures using binary prefix multipliers to two decimal places of precision. E.g. 2.00GB. For partition sizes where the contained file system size rounds upwards, GParted will fail to read the file system usage and report a warning because the file system will appear to be larger than the partition. For example, create a 2047 MiB partition containing a btrfs file system and display its size. # btrfs filesystem show Label: none uuid: 92535375-5e76-4a70-896a-8d796a577993 Total devices 1 FS bytes used 28.00KB devid 1 size 2.00GB used 240.62MB path /dev/sda12 The file system size appears to be 2048 MiB, but that is larger than the partition, hence the issue GParted has. (Actually uses the btrfs devid size which is the size of the btrfs file system within the partition in question). This issue is new with the fix for Bug #499202 because it queries the file system sizes for the first time. The same issue could theoretically occur previously, but with the used figure (FS bytes used). This would have been virtually impossible to trigger because btrfs file system would have to have been greater than 99% full, but btrfs has been notorious for early reporting of file system full. The fix is that if a btrfs file system size appears larger than the partition size, but the minimum possible size which could have been rounded to the reported figure is within the partition size use the smaller partition size instead. Apply the method to the used figure too, in case the file system is 100% full. Also if the btrfs file system size appears smaller than the partition size, but the maximum possible size which could have been rounded to the reported figure is within the partition size use the larger partition size instead to avoid reporting, presumably false, unallocated space. Not applied to file system used figure. Bug 499202 - gparted does not see the difference if partition size differs from filesystem size
2012-05-30 06:41:59 -06:00
//Private methods
Detect busy status of multi-device btrfs file systems (#723842) Busy detection of file systems works by checking if the device is mounted (appears in the mount_info map). For a multi-device btrfs file system this will only report one of the devices as busy, not all of them. # btrfs filesystem show /dev/sdb1 Label: none uuid: 36eb51a2-2927-4c92-820f-b2f0b5cdae50 Total devices 2 FS bytes used 156.00KB devid 2 size 2.00GB used 512.00MB path /dev/sdb2 devid 1 size 2.00GB used 240.75MB path /dev/sdb1 # mount /dev/sdb1 /mnt/1 # grep btrfs /proc/mounts /dev/sdb1 /mnt/1 btrfs rw,seclabel,relatime,ssd,space_cache 0 0 GParted will only report /dev/sdb1 as busy, but not /dev/sdb2. Add btrfs specific is_busy() method which reports the device as busy if any of the devices in the btrfs file system are mounted. This uses a cache which maps device membership in all btrfs file systems. The cache is cleared on GParted refresh and incrementally populated as each btrfs partition is checked for busy status. WARNING: Removal of the mounting device from a btrfs file system makes it impossible to determine whether the file system is mounted or not for linux <= 3.4. This is because /proc/mounts continues to show the old device which is no longer a member of the file system. # btrfs device delete /dev/sdb1 /mnt/1 # sync # grep btrfs /proc/mounts /dev/sdb1 /mnt/1 btrfs rw,seclabel,relatime,ssd,space_cache 0 0 # btrfs filesystem show /dev/sdb1 # btrfs filesystem show /dev/sdb2 Label: none uuid: 36eb51a2-2927-4c92-820f-b2f0b5cdae50 Total devices 1 FS bytes used 28.00KB devid 2 size 2.00GB used 1.02GB path /dev/sdb2 Fixed in linux 3.5 by commit: Btrfs: implement ->show_devname https://git.kernel.org/cgit/linux/kernel/git/torvalds/linux.git/commit/?id=9c5085c147989d48dfe74194b48affc23f376650 Bug #723842 - GParted resizes the wrong filesystem (does not pass the devid to btrfs filesystem resize)
2014-02-17 15:39:34 -07:00
//Return btrfs device cache entry, incrementally loading cache as required
const BTRFS_Device & btrfs::get_cache_entry( const Glib::ustring & path )
Detect busy status of multi-device btrfs file systems (#723842) Busy detection of file systems works by checking if the device is mounted (appears in the mount_info map). For a multi-device btrfs file system this will only report one of the devices as busy, not all of them. # btrfs filesystem show /dev/sdb1 Label: none uuid: 36eb51a2-2927-4c92-820f-b2f0b5cdae50 Total devices 2 FS bytes used 156.00KB devid 2 size 2.00GB used 512.00MB path /dev/sdb2 devid 1 size 2.00GB used 240.75MB path /dev/sdb1 # mount /dev/sdb1 /mnt/1 # grep btrfs /proc/mounts /dev/sdb1 /mnt/1 btrfs rw,seclabel,relatime,ssd,space_cache 0 0 GParted will only report /dev/sdb1 as busy, but not /dev/sdb2. Add btrfs specific is_busy() method which reports the device as busy if any of the devices in the btrfs file system are mounted. This uses a cache which maps device membership in all btrfs file systems. The cache is cleared on GParted refresh and incrementally populated as each btrfs partition is checked for busy status. WARNING: Removal of the mounting device from a btrfs file system makes it impossible to determine whether the file system is mounted or not for linux <= 3.4. This is because /proc/mounts continues to show the old device which is no longer a member of the file system. # btrfs device delete /dev/sdb1 /mnt/1 # sync # grep btrfs /proc/mounts /dev/sdb1 /mnt/1 btrfs rw,seclabel,relatime,ssd,space_cache 0 0 # btrfs filesystem show /dev/sdb1 # btrfs filesystem show /dev/sdb2 Label: none uuid: 36eb51a2-2927-4c92-820f-b2f0b5cdae50 Total devices 1 FS bytes used 28.00KB devid 2 size 2.00GB used 1.02GB path /dev/sdb2 Fixed in linux 3.5 by commit: Btrfs: implement ->show_devname https://git.kernel.org/cgit/linux/kernel/git/torvalds/linux.git/commit/?id=9c5085c147989d48dfe74194b48affc23f376650 Bug #723842 - GParted resizes the wrong filesystem (does not pass the devid to btrfs filesystem resize)
2014-02-17 15:39:34 -07:00
{
std::map<BlockSpecial, BTRFS_Device>::const_iterator bd_iter = btrfs_device_cache.find( BlockSpecial( path ) );
if ( bd_iter != btrfs_device_cache .end() )
return bd_iter ->second ;
Detect busy status of multi-device btrfs file systems (#723842) Busy detection of file systems works by checking if the device is mounted (appears in the mount_info map). For a multi-device btrfs file system this will only report one of the devices as busy, not all of them. # btrfs filesystem show /dev/sdb1 Label: none uuid: 36eb51a2-2927-4c92-820f-b2f0b5cdae50 Total devices 2 FS bytes used 156.00KB devid 2 size 2.00GB used 512.00MB path /dev/sdb2 devid 1 size 2.00GB used 240.75MB path /dev/sdb1 # mount /dev/sdb1 /mnt/1 # grep btrfs /proc/mounts /dev/sdb1 /mnt/1 btrfs rw,seclabel,relatime,ssd,space_cache 0 0 GParted will only report /dev/sdb1 as busy, but not /dev/sdb2. Add btrfs specific is_busy() method which reports the device as busy if any of the devices in the btrfs file system are mounted. This uses a cache which maps device membership in all btrfs file systems. The cache is cleared on GParted refresh and incrementally populated as each btrfs partition is checked for busy status. WARNING: Removal of the mounting device from a btrfs file system makes it impossible to determine whether the file system is mounted or not for linux <= 3.4. This is because /proc/mounts continues to show the old device which is no longer a member of the file system. # btrfs device delete /dev/sdb1 /mnt/1 # sync # grep btrfs /proc/mounts /dev/sdb1 /mnt/1 btrfs rw,seclabel,relatime,ssd,space_cache 0 0 # btrfs filesystem show /dev/sdb1 # btrfs filesystem show /dev/sdb2 Label: none uuid: 36eb51a2-2927-4c92-820f-b2f0b5cdae50 Total devices 1 FS bytes used 28.00KB devid 2 size 2.00GB used 1.02GB path /dev/sdb2 Fixed in linux 3.5 by commit: Btrfs: implement ->show_devname https://git.kernel.org/cgit/linux/kernel/git/torvalds/linux.git/commit/?id=9c5085c147989d48dfe74194b48affc23f376650 Bug #723842 - GParted resizes the wrong filesystem (does not pass the devid to btrfs filesystem resize)
2014-02-17 15:39:34 -07:00
Glib::ustring output, error ;
std::vector<int> devid_list ;
std::vector<Glib::ustring> path_list ;
Detect busy status of multi-device btrfs file systems (#723842) Busy detection of file systems works by checking if the device is mounted (appears in the mount_info map). For a multi-device btrfs file system this will only report one of the devices as busy, not all of them. # btrfs filesystem show /dev/sdb1 Label: none uuid: 36eb51a2-2927-4c92-820f-b2f0b5cdae50 Total devices 2 FS bytes used 156.00KB devid 2 size 2.00GB used 512.00MB path /dev/sdb2 devid 1 size 2.00GB used 240.75MB path /dev/sdb1 # mount /dev/sdb1 /mnt/1 # grep btrfs /proc/mounts /dev/sdb1 /mnt/1 btrfs rw,seclabel,relatime,ssd,space_cache 0 0 GParted will only report /dev/sdb1 as busy, but not /dev/sdb2. Add btrfs specific is_busy() method which reports the device as busy if any of the devices in the btrfs file system are mounted. This uses a cache which maps device membership in all btrfs file systems. The cache is cleared on GParted refresh and incrementally populated as each btrfs partition is checked for busy status. WARNING: Removal of the mounting device from a btrfs file system makes it impossible to determine whether the file system is mounted or not for linux <= 3.4. This is because /proc/mounts continues to show the old device which is no longer a member of the file system. # btrfs device delete /dev/sdb1 /mnt/1 # sync # grep btrfs /proc/mounts /dev/sdb1 /mnt/1 btrfs rw,seclabel,relatime,ssd,space_cache 0 0 # btrfs filesystem show /dev/sdb1 # btrfs filesystem show /dev/sdb2 Label: none uuid: 36eb51a2-2927-4c92-820f-b2f0b5cdae50 Total devices 1 FS bytes used 28.00KB devid 2 size 2.00GB used 1.02GB path /dev/sdb2 Fixed in linux 3.5 by commit: Btrfs: implement ->show_devname https://git.kernel.org/cgit/linux/kernel/git/torvalds/linux.git/commit/?id=9c5085c147989d48dfe74194b48affc23f376650 Bug #723842 - GParted resizes the wrong filesystem (does not pass the devid to btrfs filesystem resize)
2014-02-17 15:39:34 -07:00
if ( btrfs_found )
Correctly quote and escape arguments passed to external commands (#787203) Trying to set a file system label to (including the double quotes): " --help " fails. For example labelling an ext4 file system would try to run this command: # e2label /dev/sdb1 "" --help "" Usage: e2label device [newlabel] # echo $? 1 Alternatively trying to create a file system with a label of just a double quote also fails. The Applying Pending Operations dialog waits forever and won't cancel or force cancel. Have to use the window manager close window button to close the dialog. Also GParted reports this error to the console: (gpartedbin:9648): glibmm-CRITICAL **: unhandled exception (type Glib::Error) in signal handler: domain: g-shell-error-quark code : 0 what : Text ended before matching quote was found for ". (The text was 'mkfs.xfs -f -L """ /dev/sdb2') Command strings are parsed and split into argv array by function Glib::shell_parse_argv() which calls internal glib function tokenize_command_line() for shell tokenization. It expects the command string to be properly quoted and escaped and after tokenization, calls g_shell_unquote() on every parsed argument. So to prevent constructing incorrect commands, every non-static string needs to be properly quoted. GParted only puts labels and mount points into double quotes, but has not escaped special characters in those values itself. This patch fixes all these problems by using Glib::shell_quote() on all variable values. Labels, mount points, paths and all others too. Probably a better solution would be to use a new function which takes argv array instead of one string with all the, correctly quoted and escaped, arguments concatenated together. Bug 787203 - Correctly quote and escape arguments of external programs passed to execute_command()
2017-09-03 01:52:54 -06:00
Utils::execute_command( "btrfs filesystem show " + Glib::shell_quote( path ), output, error, true );
Detect busy status of multi-device btrfs file systems (#723842) Busy detection of file systems works by checking if the device is mounted (appears in the mount_info map). For a multi-device btrfs file system this will only report one of the devices as busy, not all of them. # btrfs filesystem show /dev/sdb1 Label: none uuid: 36eb51a2-2927-4c92-820f-b2f0b5cdae50 Total devices 2 FS bytes used 156.00KB devid 2 size 2.00GB used 512.00MB path /dev/sdb2 devid 1 size 2.00GB used 240.75MB path /dev/sdb1 # mount /dev/sdb1 /mnt/1 # grep btrfs /proc/mounts /dev/sdb1 /mnt/1 btrfs rw,seclabel,relatime,ssd,space_cache 0 0 GParted will only report /dev/sdb1 as busy, but not /dev/sdb2. Add btrfs specific is_busy() method which reports the device as busy if any of the devices in the btrfs file system are mounted. This uses a cache which maps device membership in all btrfs file systems. The cache is cleared on GParted refresh and incrementally populated as each btrfs partition is checked for busy status. WARNING: Removal of the mounting device from a btrfs file system makes it impossible to determine whether the file system is mounted or not for linux <= 3.4. This is because /proc/mounts continues to show the old device which is no longer a member of the file system. # btrfs device delete /dev/sdb1 /mnt/1 # sync # grep btrfs /proc/mounts /dev/sdb1 /mnt/1 btrfs rw,seclabel,relatime,ssd,space_cache 0 0 # btrfs filesystem show /dev/sdb1 # btrfs filesystem show /dev/sdb2 Label: none uuid: 36eb51a2-2927-4c92-820f-b2f0b5cdae50 Total devices 1 FS bytes used 28.00KB devid 2 size 2.00GB used 1.02GB path /dev/sdb2 Fixed in linux 3.5 by commit: Btrfs: implement ->show_devname https://git.kernel.org/cgit/linux/kernel/git/torvalds/linux.git/commit/?id=9c5085c147989d48dfe74194b48affc23f376650 Bug #723842 - GParted resizes the wrong filesystem (does not pass the devid to btrfs filesystem resize)
2014-02-17 15:39:34 -07:00
else
Correctly quote and escape arguments passed to external commands (#787203) Trying to set a file system label to (including the double quotes): " --help " fails. For example labelling an ext4 file system would try to run this command: # e2label /dev/sdb1 "" --help "" Usage: e2label device [newlabel] # echo $? 1 Alternatively trying to create a file system with a label of just a double quote also fails. The Applying Pending Operations dialog waits forever and won't cancel or force cancel. Have to use the window manager close window button to close the dialog. Also GParted reports this error to the console: (gpartedbin:9648): glibmm-CRITICAL **: unhandled exception (type Glib::Error) in signal handler: domain: g-shell-error-quark code : 0 what : Text ended before matching quote was found for ". (The text was 'mkfs.xfs -f -L """ /dev/sdb2') Command strings are parsed and split into argv array by function Glib::shell_parse_argv() which calls internal glib function tokenize_command_line() for shell tokenization. It expects the command string to be properly quoted and escaped and after tokenization, calls g_shell_unquote() on every parsed argument. So to prevent constructing incorrect commands, every non-static string needs to be properly quoted. GParted only puts labels and mount points into double quotes, but has not escaped special characters in those values itself. This patch fixes all these problems by using Glib::shell_quote() on all variable values. Labels, mount points, paths and all others too. Probably a better solution would be to use a new function which takes argv array instead of one string with all the, correctly quoted and escaped, arguments concatenated together. Bug 787203 - Correctly quote and escape arguments of external programs passed to execute_command()
2017-09-03 01:52:54 -06:00
Utils::execute_command( "btrfs-show " + Glib::shell_quote( path ), output, error, true );
//In many cases the exit status doesn't reflect valid output or an error condition
// so rely on parsing the output to determine success.
//Extract devid and path for each device from output like this:
// Label: none uuid: 36eb51a2-2927-4c92-820f-b2f0b5cdae50
// Total devices 2 FS bytes used 156.00KB
// devid 2 size 2.00GB used 512.00MB path /dev/sdb2
// devid 1 size 2.00GB used 240.75MB path /dev/sdb1
Glib::ustring::size_type offset = 0 ;
Glib::ustring::size_type index ;
while ( ( index = output .find( "devid ", offset ) ) != Glib::ustring::npos )
Detect busy status of multi-device btrfs file systems (#723842) Busy detection of file systems works by checking if the device is mounted (appears in the mount_info map). For a multi-device btrfs file system this will only report one of the devices as busy, not all of them. # btrfs filesystem show /dev/sdb1 Label: none uuid: 36eb51a2-2927-4c92-820f-b2f0b5cdae50 Total devices 2 FS bytes used 156.00KB devid 2 size 2.00GB used 512.00MB path /dev/sdb2 devid 1 size 2.00GB used 240.75MB path /dev/sdb1 # mount /dev/sdb1 /mnt/1 # grep btrfs /proc/mounts /dev/sdb1 /mnt/1 btrfs rw,seclabel,relatime,ssd,space_cache 0 0 GParted will only report /dev/sdb1 as busy, but not /dev/sdb2. Add btrfs specific is_busy() method which reports the device as busy if any of the devices in the btrfs file system are mounted. This uses a cache which maps device membership in all btrfs file systems. The cache is cleared on GParted refresh and incrementally populated as each btrfs partition is checked for busy status. WARNING: Removal of the mounting device from a btrfs file system makes it impossible to determine whether the file system is mounted or not for linux <= 3.4. This is because /proc/mounts continues to show the old device which is no longer a member of the file system. # btrfs device delete /dev/sdb1 /mnt/1 # sync # grep btrfs /proc/mounts /dev/sdb1 /mnt/1 btrfs rw,seclabel,relatime,ssd,space_cache 0 0 # btrfs filesystem show /dev/sdb1 # btrfs filesystem show /dev/sdb2 Label: none uuid: 36eb51a2-2927-4c92-820f-b2f0b5cdae50 Total devices 1 FS bytes used 28.00KB devid 2 size 2.00GB used 1.02GB path /dev/sdb2 Fixed in linux 3.5 by commit: Btrfs: implement ->show_devname https://git.kernel.org/cgit/linux/kernel/git/torvalds/linux.git/commit/?id=9c5085c147989d48dfe74194b48affc23f376650 Bug #723842 - GParted resizes the wrong filesystem (does not pass the devid to btrfs filesystem resize)
2014-02-17 15:39:34 -07:00
{
int devid = -1 ;
sscanf( output .substr( index ) .c_str(), "devid %d", &devid ) ;
Glib::ustring devid_path = Utils::regexp_label( output .substr( index ),
"devid .* path (/dev/[[:graph:]]+)" ) ;
if ( devid > -1 && ! devid_path .empty() )
Detect busy status of multi-device btrfs file systems (#723842) Busy detection of file systems works by checking if the device is mounted (appears in the mount_info map). For a multi-device btrfs file system this will only report one of the devices as busy, not all of them. # btrfs filesystem show /dev/sdb1 Label: none uuid: 36eb51a2-2927-4c92-820f-b2f0b5cdae50 Total devices 2 FS bytes used 156.00KB devid 2 size 2.00GB used 512.00MB path /dev/sdb2 devid 1 size 2.00GB used 240.75MB path /dev/sdb1 # mount /dev/sdb1 /mnt/1 # grep btrfs /proc/mounts /dev/sdb1 /mnt/1 btrfs rw,seclabel,relatime,ssd,space_cache 0 0 GParted will only report /dev/sdb1 as busy, but not /dev/sdb2. Add btrfs specific is_busy() method which reports the device as busy if any of the devices in the btrfs file system are mounted. This uses a cache which maps device membership in all btrfs file systems. The cache is cleared on GParted refresh and incrementally populated as each btrfs partition is checked for busy status. WARNING: Removal of the mounting device from a btrfs file system makes it impossible to determine whether the file system is mounted or not for linux <= 3.4. This is because /proc/mounts continues to show the old device which is no longer a member of the file system. # btrfs device delete /dev/sdb1 /mnt/1 # sync # grep btrfs /proc/mounts /dev/sdb1 /mnt/1 btrfs rw,seclabel,relatime,ssd,space_cache 0 0 # btrfs filesystem show /dev/sdb1 # btrfs filesystem show /dev/sdb2 Label: none uuid: 36eb51a2-2927-4c92-820f-b2f0b5cdae50 Total devices 1 FS bytes used 28.00KB devid 2 size 2.00GB used 1.02GB path /dev/sdb2 Fixed in linux 3.5 by commit: Btrfs: implement ->show_devname https://git.kernel.org/cgit/linux/kernel/git/torvalds/linux.git/commit/?id=9c5085c147989d48dfe74194b48affc23f376650 Bug #723842 - GParted resizes the wrong filesystem (does not pass the devid to btrfs filesystem resize)
2014-02-17 15:39:34 -07:00
{
devid_list .push_back( devid ) ;
path_list .push_back( devid_path ) ;
Detect busy status of multi-device btrfs file systems (#723842) Busy detection of file systems works by checking if the device is mounted (appears in the mount_info map). For a multi-device btrfs file system this will only report one of the devices as busy, not all of them. # btrfs filesystem show /dev/sdb1 Label: none uuid: 36eb51a2-2927-4c92-820f-b2f0b5cdae50 Total devices 2 FS bytes used 156.00KB devid 2 size 2.00GB used 512.00MB path /dev/sdb2 devid 1 size 2.00GB used 240.75MB path /dev/sdb1 # mount /dev/sdb1 /mnt/1 # grep btrfs /proc/mounts /dev/sdb1 /mnt/1 btrfs rw,seclabel,relatime,ssd,space_cache 0 0 GParted will only report /dev/sdb1 as busy, but not /dev/sdb2. Add btrfs specific is_busy() method which reports the device as busy if any of the devices in the btrfs file system are mounted. This uses a cache which maps device membership in all btrfs file systems. The cache is cleared on GParted refresh and incrementally populated as each btrfs partition is checked for busy status. WARNING: Removal of the mounting device from a btrfs file system makes it impossible to determine whether the file system is mounted or not for linux <= 3.4. This is because /proc/mounts continues to show the old device which is no longer a member of the file system. # btrfs device delete /dev/sdb1 /mnt/1 # sync # grep btrfs /proc/mounts /dev/sdb1 /mnt/1 btrfs rw,seclabel,relatime,ssd,space_cache 0 0 # btrfs filesystem show /dev/sdb1 # btrfs filesystem show /dev/sdb2 Label: none uuid: 36eb51a2-2927-4c92-820f-b2f0b5cdae50 Total devices 1 FS bytes used 28.00KB devid 2 size 2.00GB used 1.02GB path /dev/sdb2 Fixed in linux 3.5 by commit: Btrfs: implement ->show_devname https://git.kernel.org/cgit/linux/kernel/git/torvalds/linux.git/commit/?id=9c5085c147989d48dfe74194b48affc23f376650 Bug #723842 - GParted resizes the wrong filesystem (does not pass the devid to btrfs filesystem resize)
2014-02-17 15:39:34 -07:00
}
offset = index + 5 ; //Next find starts immediately after current "devid"
Detect busy status of multi-device btrfs file systems (#723842) Busy detection of file systems works by checking if the device is mounted (appears in the mount_info map). For a multi-device btrfs file system this will only report one of the devices as busy, not all of them. # btrfs filesystem show /dev/sdb1 Label: none uuid: 36eb51a2-2927-4c92-820f-b2f0b5cdae50 Total devices 2 FS bytes used 156.00KB devid 2 size 2.00GB used 512.00MB path /dev/sdb2 devid 1 size 2.00GB used 240.75MB path /dev/sdb1 # mount /dev/sdb1 /mnt/1 # grep btrfs /proc/mounts /dev/sdb1 /mnt/1 btrfs rw,seclabel,relatime,ssd,space_cache 0 0 GParted will only report /dev/sdb1 as busy, but not /dev/sdb2. Add btrfs specific is_busy() method which reports the device as busy if any of the devices in the btrfs file system are mounted. This uses a cache which maps device membership in all btrfs file systems. The cache is cleared on GParted refresh and incrementally populated as each btrfs partition is checked for busy status. WARNING: Removal of the mounting device from a btrfs file system makes it impossible to determine whether the file system is mounted or not for linux <= 3.4. This is because /proc/mounts continues to show the old device which is no longer a member of the file system. # btrfs device delete /dev/sdb1 /mnt/1 # sync # grep btrfs /proc/mounts /dev/sdb1 /mnt/1 btrfs rw,seclabel,relatime,ssd,space_cache 0 0 # btrfs filesystem show /dev/sdb1 # btrfs filesystem show /dev/sdb2 Label: none uuid: 36eb51a2-2927-4c92-820f-b2f0b5cdae50 Total devices 1 FS bytes used 28.00KB devid 2 size 2.00GB used 1.02GB path /dev/sdb2 Fixed in linux 3.5 by commit: Btrfs: implement ->show_devname https://git.kernel.org/cgit/linux/kernel/git/torvalds/linux.git/commit/?id=9c5085c147989d48dfe74194b48affc23f376650 Bug #723842 - GParted resizes the wrong filesystem (does not pass the devid to btrfs filesystem resize)
2014-02-17 15:39:34 -07:00
}
//Add cache entries for all found devices
std::vector<BlockSpecial> bs_list;
for ( unsigned int i = 0 ; i < path_list.size() ; i ++ )
bs_list.push_back( BlockSpecial( path_list[i] ) );
for ( unsigned int i = 0 ; i < devid_list .size() ; i ++ )
{
BTRFS_Device btrfs_dev ;
btrfs_dev .devid = devid_list[ i ] ;
btrfs_dev.members = bs_list;
btrfs_device_cache[ BlockSpecial( path_list[i] ) ] = btrfs_dev;
}
bd_iter = btrfs_device_cache.find( BlockSpecial( path ) );
if ( bd_iter != btrfs_device_cache .end() )
return bd_iter ->second ;
//If for any reason we fail to parse the information return an "unknown" record
static BTRFS_Device btrfs_dev = { -1, } ;
return btrfs_dev ;
Detect busy status of multi-device btrfs file systems (#723842) Busy detection of file systems works by checking if the device is mounted (appears in the mount_info map). For a multi-device btrfs file system this will only report one of the devices as busy, not all of them. # btrfs filesystem show /dev/sdb1 Label: none uuid: 36eb51a2-2927-4c92-820f-b2f0b5cdae50 Total devices 2 FS bytes used 156.00KB devid 2 size 2.00GB used 512.00MB path /dev/sdb2 devid 1 size 2.00GB used 240.75MB path /dev/sdb1 # mount /dev/sdb1 /mnt/1 # grep btrfs /proc/mounts /dev/sdb1 /mnt/1 btrfs rw,seclabel,relatime,ssd,space_cache 0 0 GParted will only report /dev/sdb1 as busy, but not /dev/sdb2. Add btrfs specific is_busy() method which reports the device as busy if any of the devices in the btrfs file system are mounted. This uses a cache which maps device membership in all btrfs file systems. The cache is cleared on GParted refresh and incrementally populated as each btrfs partition is checked for busy status. WARNING: Removal of the mounting device from a btrfs file system makes it impossible to determine whether the file system is mounted or not for linux <= 3.4. This is because /proc/mounts continues to show the old device which is no longer a member of the file system. # btrfs device delete /dev/sdb1 /mnt/1 # sync # grep btrfs /proc/mounts /dev/sdb1 /mnt/1 btrfs rw,seclabel,relatime,ssd,space_cache 0 0 # btrfs filesystem show /dev/sdb1 # btrfs filesystem show /dev/sdb2 Label: none uuid: 36eb51a2-2927-4c92-820f-b2f0b5cdae50 Total devices 1 FS bytes used 28.00KB devid 2 size 2.00GB used 1.02GB path /dev/sdb2 Fixed in linux 3.5 by commit: Btrfs: implement ->show_devname https://git.kernel.org/cgit/linux/kernel/git/torvalds/linux.git/commit/?id=9c5085c147989d48dfe74194b48affc23f376650 Bug #723842 - GParted resizes the wrong filesystem (does not pass the devid to btrfs filesystem resize)
2014-02-17 15:39:34 -07:00
}
Handle btrfs tools rounding of figures (#499202) The btrfs programs only provide approximations of file system sizes because they display figures using binary prefix multipliers to two decimal places of precision. E.g. 2.00GB. For partition sizes where the contained file system size rounds upwards, GParted will fail to read the file system usage and report a warning because the file system will appear to be larger than the partition. For example, create a 2047 MiB partition containing a btrfs file system and display its size. # btrfs filesystem show Label: none uuid: 92535375-5e76-4a70-896a-8d796a577993 Total devices 1 FS bytes used 28.00KB devid 1 size 2.00GB used 240.62MB path /dev/sda12 The file system size appears to be 2048 MiB, but that is larger than the partition, hence the issue GParted has. (Actually uses the btrfs devid size which is the size of the btrfs file system within the partition in question). This issue is new with the fix for Bug #499202 because it queries the file system sizes for the first time. The same issue could theoretically occur previously, but with the used figure (FS bytes used). This would have been virtually impossible to trigger because btrfs file system would have to have been greater than 99% full, but btrfs has been notorious for early reporting of file system full. The fix is that if a btrfs file system size appears larger than the partition size, but the minimum possible size which could have been rounded to the reported figure is within the partition size use the smaller partition size instead. Apply the method to the used figure too, in case the file system is 100% full. Also if the btrfs file system size appears smaller than the partition size, but the maximum possible size which could have been rounded to the reported figure is within the partition size use the larger partition size instead to avoid reporting, presumably false, unallocated space. Not applied to file system used figure. Bug 499202 - gparted does not see the difference if partition size differs from filesystem size
2012-05-30 06:41:59 -06:00
//Return the value of a btrfs tool formatted size, including reversing
// changes in certain cases caused by using binary prefix multipliers
// and rounding to two decimal places of precision. E.g. "2.00GB".
Byte_Value btrfs::btrfs_size_to_num( Glib::ustring str, Byte_Value ptn_bytes, bool scale_up )
Handle btrfs tools rounding of figures (#499202) The btrfs programs only provide approximations of file system sizes because they display figures using binary prefix multipliers to two decimal places of precision. E.g. 2.00GB. For partition sizes where the contained file system size rounds upwards, GParted will fail to read the file system usage and report a warning because the file system will appear to be larger than the partition. For example, create a 2047 MiB partition containing a btrfs file system and display its size. # btrfs filesystem show Label: none uuid: 92535375-5e76-4a70-896a-8d796a577993 Total devices 1 FS bytes used 28.00KB devid 1 size 2.00GB used 240.62MB path /dev/sda12 The file system size appears to be 2048 MiB, but that is larger than the partition, hence the issue GParted has. (Actually uses the btrfs devid size which is the size of the btrfs file system within the partition in question). This issue is new with the fix for Bug #499202 because it queries the file system sizes for the first time. The same issue could theoretically occur previously, but with the used figure (FS bytes used). This would have been virtually impossible to trigger because btrfs file system would have to have been greater than 99% full, but btrfs has been notorious for early reporting of file system full. The fix is that if a btrfs file system size appears larger than the partition size, but the minimum possible size which could have been rounded to the reported figure is within the partition size use the smaller partition size instead. Apply the method to the used figure too, in case the file system is 100% full. Also if the btrfs file system size appears smaller than the partition size, but the maximum possible size which could have been rounded to the reported figure is within the partition size use the larger partition size instead to avoid reporting, presumably false, unallocated space. Not applied to file system used figure. Bug 499202 - gparted does not see the difference if partition size differs from filesystem size
2012-05-30 06:41:59 -06:00
{
Byte_Value size_bytes = Utils::round( btrfs_size_to_gdouble( str ) ) ;
gdouble delta = btrfs_size_max_delta( str ) ;
Byte_Value upper_size = size_bytes + ceil( delta ) ;
Byte_Value lower_size = size_bytes - floor( delta ) ;
if ( size_bytes > ptn_bytes && lower_size <= ptn_bytes )
{
//Scale value down to partition size:
// The btrfs tool reported size appears larger than the partition
// size, but the minimum possible size which could have been rounded
// to the reported figure is within the partition size so use the
// smaller partition size instead. Applied to FS device size and FS
// wide used bytes.
// ............| ptn_bytes
// [ x ) size_bytes with upper & lower size
// x scaled down size_bytes
// Do this to avoid the FS size or used bytes being larger than the
// partition size and GParted failing to read the file system usage and
// report a warning.
size_bytes = ptn_bytes ;
}
else if ( scale_up && size_bytes < ptn_bytes && upper_size > ptn_bytes )
{
//Scale value up to partition size:
// The btrfs tool reported size appears smaller than the partition
// size, but the maximum possible size which could have been rounded
// to the reported figure is within the partition size so use the
// larger partition size instead. Applied to FS device size only.
// ............| ptn_bytes
// [ x ) size_bytes with upper & lower size
// x scaled up size_bytes
// Make an assumption that the file system actually fills the
// partition, rather than is slightly smaller to avoid false reporting
// of unallocated space.
size_bytes = ptn_bytes ;
}
return size_bytes ;
}
//Return maximum delta for which num +/- delta would be rounded by btrfs
// tools to str. E.g. btrfs_size_max_delta("2.00GB") -> 5368709.12
gdouble btrfs::btrfs_size_max_delta( Glib::ustring str )
Handle btrfs tools rounding of figures (#499202) The btrfs programs only provide approximations of file system sizes because they display figures using binary prefix multipliers to two decimal places of precision. E.g. 2.00GB. For partition sizes where the contained file system size rounds upwards, GParted will fail to read the file system usage and report a warning because the file system will appear to be larger than the partition. For example, create a 2047 MiB partition containing a btrfs file system and display its size. # btrfs filesystem show Label: none uuid: 92535375-5e76-4a70-896a-8d796a577993 Total devices 1 FS bytes used 28.00KB devid 1 size 2.00GB used 240.62MB path /dev/sda12 The file system size appears to be 2048 MiB, but that is larger than the partition, hence the issue GParted has. (Actually uses the btrfs devid size which is the size of the btrfs file system within the partition in question). This issue is new with the fix for Bug #499202 because it queries the file system sizes for the first time. The same issue could theoretically occur previously, but with the used figure (FS bytes used). This would have been virtually impossible to trigger because btrfs file system would have to have been greater than 99% full, but btrfs has been notorious for early reporting of file system full. The fix is that if a btrfs file system size appears larger than the partition size, but the minimum possible size which could have been rounded to the reported figure is within the partition size use the smaller partition size instead. Apply the method to the used figure too, in case the file system is 100% full. Also if the btrfs file system size appears smaller than the partition size, but the maximum possible size which could have been rounded to the reported figure is within the partition size use the larger partition size instead to avoid reporting, presumably false, unallocated space. Not applied to file system used figure. Bug 499202 - gparted does not see the difference if partition size differs from filesystem size
2012-05-30 06:41:59 -06:00
{
Glib::ustring limit_str ;
//Create limit_str. E.g. str = "2.00GB" -> limit_str = "0.005GB"
for ( Glib::ustring::iterator p = str .begin() ; p != str .end() ; p ++ )
{
if ( isdigit( *p ) )
limit_str .append( "0" ) ;
else if ( *p == '.' )
limit_str .append( "." ) ;
else
{
limit_str .append( "5" ) ;
limit_str .append( p, str .end() ) ;
break ;
}
}
gdouble max_delta = btrfs_size_to_gdouble( limit_str ) ;
return max_delta ;
}
//Return the value of a btrfs tool formatted size.
// E.g. btrfs_size_to_gdouble("2.00GB") -> 2147483648.0
gdouble btrfs::btrfs_size_to_gdouble( Glib::ustring str )
{
gchar * suffix ;
gdouble rawN = g_ascii_strtod( str .c_str(), & suffix ) ;
while ( isspace( suffix[0] ) ) //Skip white space before suffix
suffix ++ ;
unsigned long long mult ;
switch ( suffix[0] )
{
case 'K': mult = KIBIBYTE ; break ;
case 'M': mult = MEBIBYTE ; break ;
case 'G': mult = GIBIBYTE ; break ;
case 'T': mult = TEBIBYTE ; break ;
case 'P': mult = PEBIBYTE ; break ;
case 'E': mult = EXBIBYTE ; break ;
default: mult = 1 ; break ;
}
Handle btrfs tools rounding of figures (#499202) The btrfs programs only provide approximations of file system sizes because they display figures using binary prefix multipliers to two decimal places of precision. E.g. 2.00GB. For partition sizes where the contained file system size rounds upwards, GParted will fail to read the file system usage and report a warning because the file system will appear to be larger than the partition. For example, create a 2047 MiB partition containing a btrfs file system and display its size. # btrfs filesystem show Label: none uuid: 92535375-5e76-4a70-896a-8d796a577993 Total devices 1 FS bytes used 28.00KB devid 1 size 2.00GB used 240.62MB path /dev/sda12 The file system size appears to be 2048 MiB, but that is larger than the partition, hence the issue GParted has. (Actually uses the btrfs devid size which is the size of the btrfs file system within the partition in question). This issue is new with the fix for Bug #499202 because it queries the file system sizes for the first time. The same issue could theoretically occur previously, but with the used figure (FS bytes used). This would have been virtually impossible to trigger because btrfs file system would have to have been greater than 99% full, but btrfs has been notorious for early reporting of file system full. The fix is that if a btrfs file system size appears larger than the partition size, but the minimum possible size which could have been rounded to the reported figure is within the partition size use the smaller partition size instead. Apply the method to the used figure too, in case the file system is 100% full. Also if the btrfs file system size appears smaller than the partition size, but the maximum possible size which could have been rounded to the reported figure is within the partition size use the larger partition size instead to avoid reporting, presumably false, unallocated space. Not applied to file system used figure. Bug 499202 - gparted does not see the difference if partition size differs from filesystem size
2012-05-30 06:41:59 -06:00
return rawN * mult ;
}
} //GParted