If an EXT2/3/4 file system needs checking, then resize2fs will report an
error, rather than report the minimum file system size.
# mkfs.ext4 /dev/sdb11
# resize2fs -P /dev/sdb11
resize2fs 1.42.9 (28-Dec-2013)
Estimated minimum size of the filesystem: 17012
# debugfs -w -R "ssv state 0" /dev/sdb11
# resize2fs -P /dev/sdb11
resize2fs 1.42.9 (28-Dec-2013)
Please run 'e2fsck -f /dev/sdb11' first.
# echo $?
1
This will prevent GParted reading the file system usage and in turn
GParted won't allow the file system to be shrunk. Re-add the previous
method of reading the free space from dumpe2fs output as a fallback.
With this change, the worst case scenario is that GParted allows the
user to attempt to shrink an unclean EXT4 file system, smaller that that
which resize2fs allows and gets an error telling them so. As part of
the failed shrink operation GParted will have checked the file system so
on refresh GParted will get the correct minimum size next time.
This scenario only seems to apply to unclean EXT4 file systems because
resize2fs has a larger minimum size that the free blocks would suggest
because of extra space requirements when resizing EXT4 file systems [1].
[1] e2fsprogs 1.44.3, resize/resize2fs.c:calculate_minimum_resize_size()
https://git.kernel.org/pub/scm/fs/ext2/e2fsprogs.git/tree/resize/resize2fs.c?h=v1.44.3#n2946
/*
* For ext4 we need to allow for up to a flex_bg worth of
* inode tables of slack space so the resize operation can be
* guaranteed to finish.
*/
/*
* We need to reserve a few extra blocks if extents are
* enabled, in case we need to grow the extent tree. The more
* we shrink the file system, the more space we need.
*
* The absolute worst case is every single data block is in
* the part of the file system that needs to be evacuated,
* with each data block needs to be in its own extent, and
* with each inode needing at least one extent block.
*/
Closes#8 - Shrinking an EXT4 partition does not respect resize2fs
limits
A user reported GParted failed to shrink an EXT4 file system because
GParted tried to shrink it smaller than resize2fs reported minimum size.
Operation details were:
Shrink /dev/sdc1 from 931.51 GiB to 605.00 GiB (ERROR)
calibrate /dev/sdc1 (SUCCESS)
path: /dev/sdc1 (partition)
start: 63
end: 1953520064
size: 1953520002 (931.51 GiB)
check file system on /dev/sdc1 for errors and (if poss...(SUCCESS)
e2fsck -f -y -v -C 0 '/dev/sdc1' (SUCCESS)
...
158165624 blocks are used (64.77% of 244190000)
...
shrink file system (ERROR)
resize2fs -p '/dev/sdc1' 634389176K (ERROR)
resize2fs 1.44.2 (14-May-2018)
resize2fs: New size smaller than minimum (171882113)
The GParted figures:
* Partition size = 1953520064 (512b sectors) = 976760032 KiB
* FS size = 244190000 (4K blocks) = 976760000 KiB
* Used FS size = 158165624 (4K blocks) = 632662496 KiB
* Requested FS size = 634389176 KiB
The resize2fs figure:
* Minimum FS size = 171882113 (4K blocks) = 687528452 KiB
GParted uses the number of free blocks in the file system to determine
the minimum size it can shrink a file system to. However resize2fs uses
it's own internally calculated minimum size and won't shrink a file
system below that size, as seen in the above details. Resize2fs does
have a force flag, (-f) which overrides some safety checks which are
normally enforced, to allow it to try to shrink a file system smaller
than it's calculated minimum. GParted currently doesn't use the force
flag and it seems unwise for it to start to do so.
So for unmounted EXT2/3/4 file systems, change GParted to use
'resize2fs -P' to get the minimum file system size, rather than using
the number of free blocks direct from the super block, as reported by
'dumpe2fs -h'.
Mounted file systems still use statvfs() to provide file system usage.
As mounted EXT2/3/4 file systems can't be shrunk the fact that statvfs()
produces different, possibly smaller than minimum, figures than those
from 'resize2fs -P' doesn't matter.
Closes#8 - Shrinking an EXT4 partition does not respect resize2fs
limits
No functional change. Just work in FS block sized units until as late
as possible in ext2::set_used_sectors(), before converting to device
sector size units. This is to make the following change simpler and
easier to understand.
Closes#8 - Shrinking an EXT4 partition does not respect resize2fs
limits
This is functionally identical, but is just to follow established coding
pattern [1] of specifying the FSType when constructing struct FS, rather
and setting it afterwards. luks.cc was added after the aforementioned
commit, but was being developed in parallel so was created [2] following
the old coding pattern.
[1] 1a4cefb960
Initialise all struct FS members
[2] 070d734e57
Add busy detection of LUKS mapping (#760080)
Shrinking an LVM2 Physical Volume on CentOS 7 with the latest
lvm2 2.02.177 fails like this:
Shrink /dev/sda9 from 1.00 GiB to 768.00 MiB
* calibrate /dev/sda9
* check file system on /dev/sda9 for errors and (if possib...(SUCCESS)
* shrink file system (ERROR)
* lvm pvresize -v --setphysicalvolumesize 786432K '/dev/...(ERROR)
0 physical volume(s) resized / 1 physical volume(s) not resized
Wiping internal VG cache
Wiping cache of LVM-capable devices
/dev/sda9: Requested size 712.00 MiB is less than real size 1.00 GiB. Proceed? [y/n]:[n]
Physical Volume /dev/sda9 not resized.
This upstream change to lvm2 [1] makes pvresize prompt for confirmation
whenever the --setphysicalvolumesize option is used. (The change was
included in lvm2 2.02.171 and later, which is used in recent
distributions. The reporter found the issue on Ubuntu 18.04 LTS and I
reproduced the issue on RHEL/CentOS 7.5). The set size option has to be
used when shrinking the PV before shrinking the partition therefore fix
this issue by adding lvm common option --yes when using the set size
option.
[1] https://sourceware.org/git/?p=lvm2.git;a=commitdiff;h=cbc69f8c693edf0d1307c9447e2e66d07a04bfe9
pvresize: Prompt when non-default size supplied.
Closes#1 - Can't shrink LVM partition due to pvresize prompt
After a failed LUKS unlock attempt the password entry dialog shows the
error "Failed to open LUKS encryption". Improve the user experience by
clearing that error message at the start of the next attempt to avoid
contradictory information with the main windows status of "Opening
encryption on $PARTITION" whilst performing the next unlock attempt.
Bug 795617 - Implement opening and closing of LUKS mappings
When the wrong LUKS password is entered and the [Unlock] button clicked,
the wrong password is left in the entry box and focus remains on the
[Unlocked] button. Improve the user experience by selecting
(highlighting) the whole of the wrong password ready for deletion or
retyping and ensuring that the entry box always has focus.
Just for completeness also programmatically make the password entry box
have focus when the dialog box is created and first displayed, even
though it gets this by default.
Bug 795617 - Implement opening and closing of LUKS mappings
We previously migrated our web site from http://gparted.org to
https://gparted.org under:
bug 786707 - gparted.org does not use HTTPS
and updated URLs in the GParted Manual to match in commit:
a8172ecb04
Convert Manual links to HTTPS where possible and update version
Now update the URLs displayed in the GParted application too.
Bug 796411 - Enhancements request - URL links
The Change_UUID_Warning vectors were fat16 and ntfs class member
variables, but are only ever accessed in the get_custom_text() method.
Make them local variables in get_custom_text() instead. Static so that
references to them can be returned.
I completely missed that when reading XFS file system size and usage it
was using the '-r' read-only flag to xfs_db because it was at the end of
the string on the following line of code. Move it to the start of the
xfs_db command line, like it is when reading the file system label.
Same case as for FileSystem Label dialog before; the Partition Name
dialog only has a single line of just 2 widgets. Therefore switch to a
simpler horizontal box widget to lay them out.
The FileSystem Label dialog only has a single line of just 2 widgets; a
text label and entry box widget. There is no need to use a multi-line
capable table to hold this. Switch to a simpler horizontal box widget.
Note that this change is not related to porting to Gtk 3 and stopping
using deprecated APIs because both HBox [1] and Table [2] are deprecated
in Gtk 3.2 and Gtk 3.4 and replaced by Box with horizontal orientation
and Grid respectively.
[1] NEWS file from gtkmm 3.2, actually first released in gtkmm 3.1.6
(unstable):
https://git.gnome.org/browse/gtkmm/tree/NEWS?h=3.2.0#n91
"Gtk:
* All H* or V* specialized classes have been deprecated, to
match the deprecations in the GTK+ C API. You should now
set the orientation instead.
This includes HBox, VBox, HButtonBox, VButtonBox, HPaned,
VPaned, HScale, VScale, HSeparator, VSeparator, HScrollbar
and VScrollbar."
[2] NEWS file from gtkmm 3.4, actually first released in gtkmm 3.3.2
(unstable):
https://git.gnome.org/browse/gtkmm/tree/NEWS?h=3.4.0#n162
"* Deprecate Gtk::Table in favour of Gtk::Grid."
Replace return by value of const strings from
FileSystem::get_custom_text() and get_generic_text() because that
implies duplication of those strings. Return a reference to constant
strings instead.
Compiling (with new enough g++) produces this warning:
PasswordRAMStore.cc: In member function 'void GParted::PWStore::erase_all()':
PasswordRAMStore.cc:177:2: warning: this 'if' clause does not guard... [-Wmisleading-indentation]
if ( protected_mem != NULL );
^~
PasswordRAMStore.cc:193:3: note: ...this statement, but the latter is misleadingly indented as if it were guarded by the 'if'
memset( protected_mem, '\0', ProtectedMemSize );
^~~~~~
Looks like a stray semicolon...
Bug 796293 - Fix null pointer check accidentally disabled
Replace the insert() method (which reports an error when inserting a
password with a key which already exists) with the store() method which
replaces or inserts the password depending on whether the key already
exists or not respectively. There is also an optimisation that nothing
is changed if the password to be replaced is the same as the one already
stored. The code in Win_GParted::open_encrypted_partition() is
simplified now it doesn't have to implement this pattern of behaviour
itself.
Bug 795617 - Implement opening and closing of LUKS mappings
Reports generic GParted error "Failed to open LUKS encryption" on any
failure unlocking the partition. Choosing not to display cryptsetup
reported errors because those messages and their translations are not
under GParted control.
Bug 795617 - Implement opening and closing of LUKS mappings
The underlying C coded Gtk Entry widget is careful to zero memory after
use, allowing the widget to be safely used for password entry [1].
However the C++ method Gtk::Entry::get_text() just takes the underlying
C string from the Gtk Entry widget and copies it when constructing a
Glib::ustring for the return value [2].
So directly use the Gtk/C API to get the C string instead.
[1] https://git.gnome.org/browse/gtk+/tree/gtk/gtkentrybuffer.c?h=3.22.28#n92
See function trash_area() which zeros memory and its use in
gtk_entry_buffer_normal_insert_text(),
gtk_entry_buffer_normal_delete_text() and
gtk_entry_buffer_finalize().
[2] https://git.gnome.org/browse/gtkmm/tree/gtk/src/entry.hg?h=3.22.2#n104
_WRAP_METHOD(Glib::ustring get_text() const, gtk_entry_get_text)
https://git.gnome.org/browse/glibmm/tree/docs/internal/using_gmmproc.txt?h=2.46.1#n53
_WRAP_METHOD(Glib::ustring METHOD const, FUNC) is processed to:
Glib::ustring METHOD() const
{
return Glib::convert_const_gchar_ptr_to_ustring(
FUNC(const_cast<GtkEntry*>(gobj())));
}
https://git.gnome.org/browse/glibmm/tree/glib/glibmm/utility.h?h=2.46.1#n82
Glib::ustring convert_const_gchar_ptr_to_ustring(const char* str)
{
return (str) ? Glib::ustring(str) : Glib::ustring();
}
So Gtk::Entry::get_text() calls Glib::ustring() constructor which
copies the C string to create the Glib::ustring object returned.
Bug 795617 - Implement opening and closing of LUKS mappings
To keep password dialog open, just keep running it in a loop performing
LUKS mapping unlock attempts with the entered passphrase until it
succeeds or the dialog is cancelled or closed. This is the same model
that is already used for the File Support System dialog and how the
[Rescan For Supported Actions] button is implemented.
Also any error from attempting to open the LUKS mapping is no longer
displayed in a separate error dialog or at all. Will add some sort of
error reporting into the password entry dialog in a following commit.
Creates new method Win_GParted::open_encrypted_partition() which handles
the non UI parts of attempting to open an encrypted partition. Running
"cryptsetup luksOpen" and updating the stored passphrase as needed.
Bug 795617 - Implement opening and closing of LUKS mappings
Initial addition of a password entry dialog. Looks like:
+------------------------------------------------+
| LUKS Passphrase /dev/sdb1 |
+------------------------------------------------+
| Enter LUKS passphrase to open /dev/sdb1 |
| Passphrase: [ ] |
| |
| [ Cancel ] [ Unlock ] |
+------------------------------------------------+
A standard Gtk Dialog is used to accept the password once, with any
errors displayed in a separate error dialog afterwards. This is poor UI
design. A password dialog should remain open for all authentication
attempts and only close when successful or the dialog is cancelled or
closed. This UI design issue will be improved in following commits.
Bug 795617 - Implement opening and closing of LUKS mappings
Implement Close Encryption partition menu item.
The Open Encryption action is not yet implemented and instead reports an
error detailing the open encryption command. A dialog needs to be
written to accept the password entry and pass it to the open encryption
command.
Bug 795617 - Implement opening and closing of LUKS mappings
Add new item to the partition menu to allow the user to open and close
the LUKS mapping. However for now the menu item is always disabled and
there is no implementation behind it to actually open or close the LUKS
mapping. Fragment of the partition menu is now:
...
Format to >
-----------------
Open Encryption <- New menu item
Mount
-----------------
Name Partition
...
Has to be two separate menu items to clearly represent to the user that
LUKS mappings and file system mounting are two separate busy states.
And also in the case of an open but unmounted file system to offer both
actions; close encryption and mount file system.
The text of the menu item automatically changes similarly to how it does
for the Mount/Unmount, Swapon/Swapoff, Activate/Deactivate item
depending on the state of the LUKS mapping. For open LUKS mappings it
will show "Close Encryption" and for all other cases (closed LUKS
mapping or partition is not encrypted) "Open Encryption". Again similar
to how the default of "Mount" is shown for unallocated and unknown
partitions.
Bug 795617 - Implement opening and closing of LUKS mappings
In preparation for adding the ability to toggle the encryption busy
state (open/close the encryption volume), rename existing members to
reflect that they are related to changing the file system state. (Swap
and LVM2 Physical Volumes are handled as file systems by GParted).
class Win_GParted renaming:
MENU_TOGGLE_BUSY -> MENU_TOGGLE_FS_BUSY
allow_toggle_busy_state() -> allow_toggle_fs_busy_state()
toggle_busy_state() -> toggle_fs_busy_state()
check_toggle_busy_allowed() -> check_toggle_fs_busy_allowed()
Bug 795617 - Implement opening and closing of LUKS mappings
Replace echoing "dm" into jfs_debugfs via a shell command to directly
writing "dm" to the input of the jfs_debug command. One less use of the
shell.
Bug 795617 - Implement opening and closing of LUKS mappings
As discussed in "LUKS password handling, threats and preventative
measures" [1] GParted must be able to pass LUKS passphrases to
cryptsetup via standard input to avoid having to write passwords to the
file system and deal with additional security requirements. Therefore
add a way to write input into created child processes. For small
amounts of input, writing up to the pipe buffer capacity won't block
[2]. This is 64K on versions of Linux in any currently supported
distributions.
[1] LUKS password handling, threats and preventative measures
https://bugzilla.gnome.org/show_bug.cgi?id=627701#c56
GParted must not become a password manage so it must never save
LUKS passwords to disk across separate invocations of GParted.
...
GParted should avoid writing a temporary file containing the LUKS
password as it introduces extra complexity with trying to safely
handle and erase file content. Instead GParted must
programmatically pass the LUKS password via standard input to the
cryptsetup command.
[2] pipe(7) manual page:
Pipe capacity
A pipe has a limited capacity. If the pipe is full, then a
write(2) will block or fail, depending on whether the O_NONBLOCK
flag is set (see below). ...
In Linux versions before 2.6.11, the capacity of a pipe was the
same as the system page size (e.g., 4096 bytes on i386). Since
Linux 2.6.11, the pipe capacity is 65536 bytes.
Bug 795617 - Implement opening and closing of LUKS mappings
Use private access into the PasswordRAMStore class to directly obtain
the address of the locked memory, rather than inferring it from the
address of the first stored password. This simplifies
PasswordRAMStoreTest::SetUpTestCase() and avoids encoding most of the
implementation knowledge that the first password will be stored at the
start of the protected memory.
Bug 795617 - Implement opening and closing of LUKS mappings
Test that all passwords are zeroed by PasswordRAMStore::erase_all(), the
same method as used in the PasswordRAMStore destructor.
Bug 795617 - Implement opening and closing of LUKS mappings
Move zeroing of the locked memory into separate PWStore::erase_all()
private method. Then use this in the PWStore destructor. This is so
that zeroing of all passwords can be unit tested independently of
destructing the singleton PWStore object.
Bug 795617 - Implement opening and closing of LUKS mappings
Application level requirements for secure password management were set
out in "LUKS password handling, threats and preventative measures" [1].
The requirements are:
1) Passwords are stored in RAM and are not allowed to be paged to swap.
(However hibernating with GParted still running will write all of RAM
to swap).
2) Passwords are wiped from RAM when no longer needed. When each
password is no longer needed and when GParted closes.
3) Passwords are referenced by unique key. Recommend using LUKS UUIDs
as the unique key.
(Each LUKS password should only ever need to be entered once for each
execution of GParted. Therefore the passwords can't be stored in any
of the existing data structures such as Partitions or LUKS_Info cache
because all of these are cleared and reloaded on each device
refresh).
There seems to be two possible implementation methods: use an existing
library to provide secure memory handling, or write our own.
Libgcrypt [2] and libsodium [3] cryptographic libraries both provide
secure memory handling. (Secure memory is quite simple really, some
virtual memory locked into RAM which is zeroed when no longer needed).
Linking to an encryption library just to provide secure memory seems
like using a sledge hammer to crack a nut. Also because of requirement
(3) above a module is needed to "own" the pointers to the passwords in
the secure memory. Managing the secure memory ourselves is probably no
more code that that needed to interface to libgcrypt. Therefore handle
the secure memory ourselves.
So far the module is only compiled. It is not used anywhere in GParted.
[1] LUKS password handling, threats and preventative measures
https://bugzilla.gnome.org/show_bug.cgi?id=627701#c56
[2] libgcrypt general purpose cryptographic library, as used in GNU
Privacy Guard
https://gnupg.org/related_software/libgcrypt/
[3] libsodium crypto library
https://download.libsodium.org/doc/
Bug 795617 - Implement opening and closing of LUKS mappings
Increase the minimum required version of gtkmm to 2.16.0, thus allowing
removal of HAVE_GTK_SHOW_URI autoconf definition and associated fallback
code.
Bug 794253 - Desupport RHEL / CentOS 5 and raise minimum required
versions to glibmm 2.14.0 and gtkmm 2.16.0
Increase the minimum required version of gtkmm to 2.11.1, thus allowing
removal of:
* HAVE_SET_DEFAULT_ICON_NAME autoconf definition and associated
optional code.
* INSTALL_PIXMAPS_DIR automake conditional and associated make
instructions.
This is reversing these 3 commits, except for the higher minimum gtkmm
version:
1) a042107883
Only use Gtk::Window::set_default_icon_name method when available (#695279)
2) b09d6035cd
Add fallback method for specifying GParted icon (#695279)
3) d6baac2546
Only install fallback icon when required (#695279)
Bug 794253 - Desupport RHEL / CentOS 5 and raise minimum required
versions to glibmm 2.14.0 and gtkmm 2.16.0
Increase the minimum required version of glibmm to 2.14.0, thus allowing
removal of the HAVE_GLIB_REGEX autoconf definition and associated
conditional code. This is reversing commit, except for the new glibmm
minimum check:
456932846b
Implement fallback if Glib::Regex class is missing (#695279)
Bug 794253 - Desupport RHEL / CentOS 5 and raise minimum required
versions to glibmm 2.14.0 and gtkmm 2.16.0
E2fsprogs 1.41.0 (from 10 July 2008) first included ext4 support [1].
As RHEL / CentOS 6 is now the oldest supported distribution, and that
includes e2fsprogs 1.41.12 (from 22 August 2009) [2] all the e2fs
programs support ext4 so it is no longer necessary to also depend on
finding mkfs.ext4 before enabling each supported capability for ext4.
This makes the ext2::get_filesystem_support() look like all the others
in which each supported capability only depends on the presence of the
relevant file system specific command.
[1] Release notes for the e2fsprogs package / E2fsprogs 1.41.0
http://e2fsprogs.sourceforge.net/e2fsprogs-release.html#1.41.0
[2] pkgs.org > CentOS 6 > CentOS x86_64 > e2fsprogs
https://centos.pkgs.org/6/centos-x86_64/e2fsprogs-1.41.12-23.el6.x86_64.rpm.html
Bug 794253 - Desupport RHEL / CentOS 5 and raise minimum required
versions to glibmm 2.14.0 and gtkmm 2.16.0
PATCHSET OVERVIEW:
As of 31 March 2017 RHEL / CentOS 5 reached the end of their support
[1][2]. Therefore remove code which supports them. This makes RHEL /
CentOS 6 the oldest supported distribution. So the minimum required
versions of glibmm and gtkmm can be increased dropping some autoconf
checks and conditional code supporting older versions of these
libraries. This will undo the bulk of these these previous bug fixes:
* GParted 0.21.0
Bug 738706 - Add support for ext4 on RHEL/CentOS 5.x
* GParted 0.16.1
Bug 695279 - Fix GParted doesn't compile on RHEL / CentOS 5.9
[1] Red Hat Enterprise Linux Life Cycle
https://access.redhat.com/support/policy/updates/errata#Life_Cycle_Dates
[2] Subject: CentOS Linux 5 EOL
https://lists.centos.org/pipermail/centos-announce/2017-April/022350.html
THIS PATCH:
Remove checks for e4fsprogs commands, removing support for ext4 on
RHEL / CentOS 5.x. This is reverting earlier commit:
f672f68863
Check for e4fsprogs commands for ext4 support on RHEL/CentOS 5.x (#738706)
Mkfs_cmd member variable is being kept as a convenience so that it is
created once rather than on each use. Also note that as it is a
Glib::ustring type object, it's constructor will be called which will
initialise it to the empty string so it doesn't need initialising to the
empty string in the initialiser list of the ext2() constructor itself.
Bug 794253 - Desupport RHEL / CentOS 5 and raise minimum required
versions to glibmm 2.14.0 and gtkmm 2.16.0
Struct FS and struct FS_Limits are strongly related to the FileSystem
class, both being return values from members and associated with storing
file system attributes. Move their definitions from Utils.h into
FileSystem.h.
There are too many different types of things named "filesystem" in the
GParted code with the potential to cause confusion. Namely:
std::vector<FS> FILESYSTEMS
Vector of file system capabilities.
class FileSystem Base class interfacing to file system
specific executables for querying and
modification.
enum FILESYSTEM Symbolic constants representing each file
system type.
Many recent written or re-written functions already used a variable
named fstype. Rename enum FILESYSTEM to enum FSType to clearly
distinguish it from the other things with very similar names. Only
changing the name of the enumeration, not the name of variables of that
type too because that is a lot more lines of code and those can be
changed when the relevant code is re-written.
Try to format an existing partition with a file system which doesn't
fit. The error dialog reporting the partition as too small or too large
always claimed the file system was encrypted, whether it was or not.
For example trying to format a 128 MiB partition as btrfs produces this
error dialog:
(-) Cannot format this file system to [Encrypted] btrfs
A [Encrypted] btrfs file system requires
a partition of at least 256.00 MiB.
[ OK ]
This commit:
88136c96d7
Extend functions generating encrypted file system string (#774818)
just completely missed handling the case for non-encrypted file systems
in Utils::get_filesystem_string(). Add the missed code.
There are multiple repetitions of the same code getting a FileSystem
object, checking for NULL and then calling the file system specific
get_filesystem_limits(). Extract that into a common function.
GParted_Core::get_filesystem_limits() can't use the file system from the
passed Partition object because that is the current file system which
will be different from the intended file system for new and format
operations. So would look up the wrong derived FileSystem specific
object and call the wrong get_filesystem_limits(). Hence still needing
fstype as a separate parameter to pass the intended file system.
Bug 787204 - Minimum and maximum size of the UDF partition/disk
UDF file system minimum and maximum size limits are defined in terms of
numbers of file system blocks. So when resizing an existing file system
compute the byte size limits from the existing UDF file system's block
size. Alternatively when creating a new UDF file system use the
device's sector size as the multiplier instead.
Bug 787204 - Minimum and maximum size of the UDF partition/disk
As described in the previous commit, this is so that file system
specific implementations can dynamically determine size limits based on
Partition object attributes: such as the device sector size and the file
system block size. (Assuming set_used_sectors() sets
partition.fs_block_size for the type of file system in question).
Bug 787204 - Minimum and maximum size of the UDF partition/disk
Background information about UDF is that when creating a file system
it's block size must match the underlying device's sector size. For
optical media like CDs and DVDs that is 2K. For hard drives that is
usually 512 bytes or 4K. However if a UDF file system has been copied
from a device with a different sector size the UDF block size won't
match the sector size. Linux will happily mount such UDF file system.
Therefore the derived udf::get_filesystem_limits() will need access to
the file system block size when determining the size limits of an
existing UDF file system being resized and use the device sector size
when a new UDF file system is being created. All this can be queried
from an appropriate Partition object passed to get_filesystem_limits().
All the calls to get_filesystem_limits() have an appropriate Partition
object available already, except in Win_GParted::activate_reformat()
when composing a format operation. Or more correctly
activate_reformat() constructs temp_ptn, a suitable Partition object,
including with fs_block_size member defaulting to -1 indicating not a
resize, but not until after the file system size limits had been checked
and get_filesystem_limits() called.
Therefore reorder the code in activate_paste() so that the file system
size limits are checked after the wanted Partition object has been
created. No functional change with this commit.
Bug 787204 - Minimum and maximum size of the UDF partition/disk
All the code has been switched to call get_filesystem_limits() and use
struct FS_Limits. Remove struct FS members .MIN & .MAX.
Bug 787204 - Minimum and maximum size of the UDF partition/disk
Change Dialog_Partition_New to use a fs_limits rather than struct FS
and .MIN and .MAX. No passing of struct FS_Limits required. Just use
the FILESYSTEMS vector of struct FS to provide the file system type and
look up it's size limits each time the selection changes.
Bug 787204 - Minimum and maximum size of the UDF partition/disk
Refactor Win_GParted::activate_resize() to query the file system size
limits using the new get_filesystem_limits() method and pass those
limits into the dialog class as struct FS_Limits.
Bug 787204 - Minimum and maximum size of the UDF partition/disk
Changes the internal code in Dialog_Partition_Resize_Move to use
fs_limits instead of fs.MIN and fs.MAX. The limits are still passed
into the constructor via struct FS and it's members .MIN and .MAX but
immediately used to assign to fs_limits.
Bug 787204 - Minimum and maximum size of the UDF partition/disk
Refactor Win_GParted::activate_paste() to query the file system size
limits using the new get_filesystem_limits() method and pass those
limits into the the dialog class as struct FS_Limits.
Bug 787204 - Minimum and maximum size of the UDF partition/disk
Adds working copy fs_limits member into common Dialog_Base_Partition
class. Changes the internal code in Dialog_Partition_Copy class to use
fs_limits instead of fs.MIN and fs.MAX. The limits are still passed
into the constructor via object of struct FS and it's members .MIN and
.MAX but immediately used to assign to the fs_limits member.
Bug 787204 - Minimum and maximum size of the UDF partition/disk
Duplicate the assignment of file system size limits into
struct FS_Limits, matching the fixed values currently assigned to
struct FS members .MIN and .MAX.
Bug 787204 - Minimum and maximum size of the UDF partition/disk
Those external tools were introduced in version 2.0 of udftools package
and can show or change UDF label, UDF uuid and can provide information
needed for counting total/free sectors.
Bug 792052 - Add support for changing UDF label/uuid and show disk usage
Attempt to grow a partition to more than twice it's size. If committing
that change to the partition fails in such a way that the new larger
partition boundaries are not written to the disk drive then rolling back
will fail with libparted error:
Can't have overlapping partitions.
Example operation details:
Grow /dev/sdb8 from 1.00 GiB to 2.20 GiB
* calibrate /dev/sdb8 (SUCCESS)
* check file system on /dev/sdb8 for errors and (if poss...(SUCCESS)
* grow partition from 1.00 GiB to 2.20 GiB (ERROR)
* attempt to rollback failed change to the partition (ERROR)
original start: 7350272
original end: 9447423
original size: 2097152 (1.00 GiB)
* libparted messages (ERROR)
Can't have overlapping partitions.
What happened is that resize_move_partition() passed the new Partition
object to resize_move_partition_implement() as the source partition for
the rollback, and than called ped_disk_partition_by_sector() with a
sector in the middle to identify the partition to be changed. However
the new partition was never written to the drive so in the middle was
outside the old smaller partition. Therefore libparted identified empty
space after the partition, rather than the partition itself, as the
intended target so when ped_disk_set_partition_geom() was called it
reported error "Can't have overlapping partitions" because it thought
another partition was being created with the same boundaries as the old
partition, rather than the boundaries of the old partition being
updated.
The same error also occurs when rolling back a failed partition change
as part of a move operation when the middle of the new partition falls
outside of the boundaries of the old partition.
Fix by making a temporary Partition object from the intersection of the
old and new partition boundaries just to be used to identify the
partition being changed to libparted. As this is only rolling back a
single step adjusting the partition boundaries as part of a resize
and/or move operation, the old and new partition boundaries must
intersect (and in fact that intersection contains the file system data).
Bug 791875 - Rollback specific failed partition change steps
The general rule is that:
1) For a partition change step BEFORE a file system change step,
rollback on failure;
2) For a partition change step AFTER a file system change step, don't
rollback on failure.
Examining every case where resize_move_partition() is called and whether
rollback on failure is wanted or not:
* In resize_move()
Resize / move extended partition. No associated file system change.
NO ROLLBACK
Just to keep possibly applied operation.
* #1 in move()
Making all encompassing partition before moving file system.
ROLLBACK
To restore partition boundaries back to those of the file system.
* #2 in move()
Recreating original partition boundaries after file system move
failed or was cancelled and has been rolled back.
NO ROLLBACK
To keep updated partition boundaries to match restored file system
data.
* #3 in move()
Replacing all encompassing partition with final partition after
successful file system move.
NO ROLLBACK
Keep new partition boundaries to match moved file system.
* #1 in resize_encryption()
Making the partition larger before growing closed LUKS encrypted
data.
ROLLBACK
Restore partition boundaries back to those of the closed LUKS
encrypted data.
* #2 in resize_encryption()
Shrinking the partition after open LUKS mapping has been shrunk, but
before swap is re-created (smaller).
NO ROLLBACK
Difficult case because the partition shrink is in the middle of a
LUKS shrink and a swap shrink (re-create). If swap was actually
shrunk like other types of file system, rather than re-created, then
the operation sequence would be (1) shrink swap, (2) shrink LUKS
encryption, (3) shrink partition. In this hypothetical case and the
actual case no rollback is preferred to try to keep the new
partition boundaries match the shrunk open LUKS encryption mapping.
* #3 in resize_encryption()
Grow the partition before growing open LUKS mapping and re-creating
swap larger.
ROLLBACK
Restore partition boundaries back to those of the smaller open LUKS
encryption mapping.
* #4 in resize_encryption()
Shrink the partition after shrinking the file system and open LUKS
encryption mapping.
NO ROLLBACK
Keep new smaller partition boundaries to match shrunk encrypted file
system.
* #5 in resize_encryption()
Grow the partition before growing the open LUKS encryption mapping
and file system.
ROLLBACK
Restore partition boundaries back to those of the not yet grown
encrypted file system.
* #1 in resize_plain()
Resize partition before re-creating swap a different size.
ROLLBACK
Restore partition boundaries back to those of the not yet resized
(re-created) swap space.
* #2 in resize_plain()
Shrink partition after shrinking the file system.
NO ROLLBACK
Keep new smaller partition boundaries to match shrunk file system.
* #3 in resize_plain()
Grow partition before growing the file system.
ROLLBACK
Restore partition boundaries back to those of the not yet grown
file system.
Removes the default value from the rollback_on_fail parameter so
rollback or not has to be explicitly specified for every call of
resize_move_partition().
Bug 791875 - Rollback specific failed partition change steps
Even after implementing a fix for bug 790418 "Unable to inform the
kernel of the change message may lead to corrupted partition table"
GParted/libparted can still encounter errors informing the kernel of the
new partition layout. This has been seen with GParted on CentOS 7 with
libparted 3.1.
In such a case the partition has been successfully written to the disk
but just informing the kernel failed. This is a problem because when a
partition is being moved in advance of a file system move step, failure
to inform the kernel leaves the partition boundaries not matching the on
disk limits of the file system. For a move to the left this leaves the
partition reported as unknown, apparently losing the user's data.
For example start with a 512 MiB partition containing an XFS file
system. This is recognised by blkid and parted, hence also by GParted.
# blkid /dev/sdb1
/dev/sdb1: UUID=... TYPE="xfs" PARTUUID="37965980-01"
# parted /dev/sdb unit s print
Model: ATA VBOX HARDDISK (scsi)
Disk /dev/sdb: 16777216s
Sector size (logical/physical): 512B/512B
Partition Table: msdos
Disk Flags:
Number Start End Size Type File system Flags
1 1048576s 2097151s 1048576s primary xfs
Now move the partition 100 MiB to the left and have it fail to inform
the kernel after the first partition change step. Operation details:
Move /dev/sdb1 to the left (ERROR)
* calibrate /dev/sdb1 (SUCCESS)
* check file system on /dev/sdb1 for errors and (if poss...(SUCCESS)
* grow partition from 512.00 MiB to 612.00 MiB (ERROR)
old start: 1048576
old end: 2097151
old size: 1048576 (512.00 MiB)
requested start: 843776
requested end: 2097151
requested size: 1253376 (612.00 MiB)
* libparted messages (ERROR)
Error informing the kernel about modifications to partition
/dev/sdb1 -- Device or resource busy. This means Linux won't
know about any changes you made to /dev/sdb1 until you reboot
-- so you shouldn't mount it or use it in any way before
rebooting. Failed to add partition 1 (resource temporarily
unavailable)
Now because the start of the partition is 100 MiB before the start of
the file system, the file system is no longer recognised, and apparently
the user's data has been lost.
# blkid /dev/sdb1
/dev/sdb1: PARTUUID="37965980-01"
# parted /dev/sdb unit s print
...
Number Start End Size Type File system Flags
1 843776s 2097151s 1253376s primary
It doesn't matter why updating the partition failed, even if it was
because of an error writing to the disk. Rollback of the change to the
partition should be attempted. The worst case scenario is that rollback
of the change fails, which is the equivalent to how the code worked
before this patch set.
However in other cases where the partition boundaries are being updated
after a file system move or shrink step then the partition should be
updated to match the new location of the file system itself. And no
rollback is wanted. If the failure was only informing the kernel then
in fact the partition has actually been updated on disk after all.
So each partition resize/move step needs examining on a case by case
basis to decide if rolling back the change to the partition is wanted or
not.
This patch only adds partition change rollback into
resize_move_partition(). Rollback remains disabled until all cases are
examined in the following patch.
Bug 791875 - Rollback specific failed partition change steps
Extract common code which updates a DMRaid device mapper entry into a
sub-function. This will also be needed when adding rollback of a
partition change on failure.
Bug 791875 - Rollback specific failed partition change steps
Extract the code which actually implements the partition change into a
sub-function ready for adding rollback of the change on failure.
Bug 791875 - Rollback specific failed partition change steps
This is not required, but it is more logical to have an OperationDetail
object created and it's final status set in the same function rather
than split between caller and callee. So move creation of
"copy %1 using a block size of %2" OperationDetail objects into
GParted_Core::copy().
Also introduces a couple of variables to remove some recomputation:
benchmark_od & remaining_length.
Bug 790842 - Report libparted messages into operation details at the
point at which they occur
Performing a copy or move operation which uses GParted's internal copy
routine triggered the new GParted bug message. Example operation
details:
Copy /dev/sdb8 to /dev/sdb (start at 4.51 GiB) (SUCESSS)
* calibrate /dev/sdb8 (SUCCESS)
* check file system on /dev/sdb8 for errors and (if possib...(SUCCESS)
* create empty partition (SUCCESS)
* set partition type on /dev/sdb9 (SUCCESS)
* copy file system from /dev/sdb8 to /dev/sdb9 (SUCCESS)
using internal algorithm
copy 1.00 GiB
* finding optimal block size
* copy 16.00 MiB using a block size of 1.00 MiB (SUCCESS)
16.00 MiB of 16.00 MiB copied
GParted Bug: Adding more information to the result...(WARNING)
0.797269 seconds
* copy 16.00 MiB using a block size of 2.00 MiB (SUCCESS)
* copy 16.00 MiB using a block size of 4.00 MiB (SUCCESS)
* copy 16.00 MiB using a block size of 8.00 MiB (SUCCESS)
* copy 16.00 MiB using a block size of 16.00 MiB (SUCCESS)
optimal block size is 1.00 MiB
* copy 944.00 MiB using a block size of 1.00 MiB (SUCCESS)
This is because when performing the initial benchmarking copies the time
taken by each copy is added to the operation detail results in the
calling GParted_Core::copy_blocks() after the final status was set in
CopyBlocks::copy() with set_success_and_capture_errors(). Fix by
setting the final status in the parent function after adding the time to
the benchmark copies.
Bug 790842 - Report libparted messages into operation details at the
point at which they occur
To be consistent with all previous bug messages being translatable.
Also only mark the bug as a warning instead of an error because the bug
doesn't cause any disk drive operations to fail.
Bug 790842 - Report libparted messages into operation details at the
point at which they occur
There is still another subtle issue. When GParted_Core::commit() closes
the device, the kernel initiates a second set of events which removes
and re-adds the partitions again. Need to wait for these to complete
to prevent any following step failing with missing partition device
nodes.
Bug 790418 - "Unable to inform the kernel of the change" message may
lead to corrupted partition table
Operations involving modifications to a partition are sometimes failing
with a libparted error informing the kernel about modifications to
partitions. For example I encountered these errors when just creating a
fourth partition on CentOS 7 in a VirtualBox VM. Operation results:
Create Primary Partition #1 (ext4, 4.73 GiB) on /dev/sdb (ERROR)
* create empty partition (ERROR)
* libparted messages (ERROR)
* Error informing the kernel about modification to partition
/dev/sdb1 -- Device or resource busy. This means Linux won't
know about any changes you made to /dev/sdb1 until you reboot
-- so you shouldn't mount it or use it in any way before
rebooting.
* Failed to add partition 1 (Resource temporarily unavailable)
Those two libparted messages were presented in "Libparted Error" dialogs
and [Cancel] was selected both times.
Libparted Error
(-) Error informing the kernel about modifications to partition
/dev/sdb1 -- Device or resource busy. This means Linux won't
know about any changes you made to /dev/sdb1 until you reboot --
so you shouldn't mount it or use it in any way before rebooting.
[ Cancel ] [ Ignore ]
Libparted Error
(-) Failed to add partition 1 (Resource temporarily unavailable)
[ Retry ] [ Cancel ]
This is the edited output showing GParted print debugging, stracing of
GParted and monitoring of udev events for this case.
# ./gpartedbin /dev/sdb
======================
libparted : 3.1
======================
...
24.541604 +23.923435 create_partition() start (new_partition, optdet, min_size=0) new_partition.device_path="/dev/sdb"
24.556101 +0.014497 create_partition() type=PED_PARTITION_NORMAL
24.556354 +0.000253 commit() start (lp_disk) lp_disk->dev->path="/dev/sdb"
D: strace pid 18054. Press [Return] to continue.
^Z
[1]+ Stopped ./gpartedbin /dev/sdb
# udevadm monitor &
[2] 18124
monitor will print the received events for:
UDEV - the event which udev sends out after rule processing
KERNEL - the kernel uevent
# strace -p 18054 -e open,ioctl,write,close &
[3] 18129
strace: Process 18054 attached
# fg %1
./gpartedbin /dev/sdb
128.175811 +103.619457 commit() calling ped_disk_commit_to_dev(lp_disk) ...
open("/dev/sdb", O_RDWR) = 6
ioctl(6, BLKFLSBUF) = 0
write(6, "\372\270\0\20\216\320\274\0\260\270\0\0\216\330\216\300\373\276\0|\277\0\6\271\0\2\363\244\352!\6\0"..., 512) = 512
ioctl(6, BLKFLSBUF) = 0
close(6)
128.181352 +0.005542 commit() ped_disk_commit_to_dev(lp_disk) returned true
128.181475 +0.000122 commit_to_os() start (lp_disk, timeout=10) lp_disk->dev->path="/dev/sdb"
128.181527 +0.000052 commit_to_os() calling ped_disk_commit_to_os(lp_disk) ...
open("/dev/sdb", O_RDWR) = 6
ioctl(6, BLKFLSBUF) = 0
open("/sys/block/sdb/ext_range", O_RDONLY) = 7
close(7) = 0
KERNEL[1158935.380543] remove /devices/pci0000:00/0000:00:0d.0/ata4/host3/target3:0:0/3:0:0:0/block/sdb/sdb1 (block)
KERNEL[1158935.380565] remove /devices/pci0000:00/0000:00:0d.0/ata4/host3/target3:0:0/3:0:0:0/block/sdb/sdb2 (block)
KERNEL[1158935.380578] remove /devices/pci0000:00/0000:00:0d.0/ata4/host3/target3:0:0/3:0:0:0/block/sdb/sdb3 (block)
ioctl(6, BLKPG, {BLKPG_DEL_PARTITION, flags=0, datalen=152, data={start=0, length=0, pno=1, devname="", volname=""}}) = -1 ENXIO (No such device or address)
ioctl(6, BLKPG, {BLKPG_DEL_PARTITION, flags=0, datalen=152, data={start=0, length=0, pno=2, devname="", volname=""}}) = -1 ENXIO (No such device or address)
ioctl(6, BLKPG, {BLKPG_DEL_PARTITION, flags=0, datalen=152, data={start=0, length=0, pno=3, devname="", volname=""}}) = -1 ENXIO (No such device or address)
...
KERNEL[1158935.380977] change /devices/pci0000:00/0000:00:0d.0/ata4/host3/target3:0:0/3:0:0:0/block/sdb (block)
KERNEL[1158935.381296] add /devices/pci0000:00/0000:00:0d.0/ata4/host3/target3:0:0/3:0:0:0/block/sdb/sdb1 (block)
KERNEL[1158935.381367] add /devices/pci0000:00/0000:00:0d.0/ata4/host3/target3:0:0/3:0:0:0/block/sdb/sdb2 (block)
KERNEL[1158935.381432] add /devices/pci0000:00/0000:00:0d.0/ata4/host3/target3:0:0/3:0:0:0/block/sdb/sdb3 (block)
KERNEL[1158935.382992] add /devices/pci0000:00/0000:00:0d.0/ata4/host3/target3:0:0/3:0:0:0/block/sdb/sdb4 (block)
ioctl(6, BLKPG, {BLKPG_DEL_PARTITION, flags=0, datalen=152, data={start=0, length=0, pno=62, devname="", volname=""}}) = -1 ENXIO (No such device or address)
ioctl(6, BLKPG, {BLKPG_DEL_PARTITION, flags=0, datalen=152, data={start=0, length=0, pno=63, devname="", volname=""}}) = -1 ENXIO (No such device or address)
ioctl(6, BLKPG, {BLKPG_DEL_PARTITION, flags=0, datalen=152, data={start=0, length=0, pno=64, devname="", volname=""}}) = -1 ENXIO (No such device or address)
ioctl(6, BLKPG, {BLKPG_ADD_PARTITION, flags=0, datalen=152, data={start=1048576, length=1073741824, pno=1, devname="/dev/sdb1", volname=""}}) = -1 EBUSY (Device or resource busy)
write(2, "Error informing the kernel about"..., 251) = 251
Error informing the kernel about modifications to partition
/dev/sdb1 -- Device or resource busy. This means Linux won't know
about any changes you made to /dev/sdb1 until you reboot -- so you
shouldn't mount it or use it in any way before rebooting.
UDEV [1158935.384641] remove /devices/pci0000:00/0000:00:0d.0/ata4/host3/target3:0:0/3:0:0:0/block/sdb/sdb2 (block)
UDEV [1158935.390203] remove /devices/pci0000:00/0000:00:0d.0/ata4/host3/target3:0:0/3:0:0:0/block/sdb/sdb1 (block)
UDEV [1158935.390243] remove /devices/pci0000:00/0000:00:0d.0/ata4/host3/target3:0:0/3:0:0:0/block/sdb/sdb3 (block)
UDEV [1158935.462866] add /devices/pci0000:00/0000:00:0d.0/ata4/host3/target3:0:0/3:0:0:0/block/sdb/sdb4 (block)
UDEV [1158935.469207] add /devices/pci0000:00/0000:00:0d.0/ata4/host3/target3:0:0/3:0:0:0/block/sdb/sdb3 (block)
UDEV [1158935.471512] add /devices/pci0000:00/0000:00:0d.0/ata4/host3/target3:0:0/3:0:0:0/block/sdb/sdb2 (block)
UDEV [1158935.492173] add /devices/pci0000:00/0000:00:0d.0/ata4/host3/target3:0:0/3:0:0:0/block/sdb/sdb1 (block)
write(2, "Failed to add partition 1 (Resou"..., 60) = 60
Failed to add partition 1 (Resource temporarily unavailable)
close(6)
KERNEL[1158955.730960] remove /devices/pci0000:00/0000:00:0d.0/ata4/host3/target3:0:0/3:0:0:0/block/sdb/sdb1 (block)
KERNEL[1158955.731095] remove /devices/pci0000:00/0000:00:0d.0/ata4/host3/target3:0:0/3:0:0:0/block/sdb/sdb2 (block)
KERNEL[1158955.731314] remove /devices/pci0000:00/0000:00:0d.0/ata4/host3/target3:0:0/3:0:0:0/block/sdb/sdb3 (block)
KERNEL[1158955.731397] remove /devices/pci0000:00/0000:00:0d.0/ata4/host3/target3:0:0/3:0:0:0/block/sdb/sdb4 (block)
KERNEL[1158955.731817] change /devices/pci0000:00/0000:00:0d.0/ata4/host3/target3:0:0/3:0:0:0/block/sdb (block)
KERNEL[1158955.731981] add /devices/pci0000:00/0000:00:0d.0/ata4/host3/target3:0:0/3:0:0:0/block/sdb/sdb1 (block)
KERNEL[1158955.732166] add /devices/pci0000:00/0000:00:0d.0/ata4/host3/target3:0:0/3:0:0:0/block/sdb/sdb2 (block)
KERNEL[1158955.732232] add /devices/pci0000:00/0000:00:0d.0/ata4/host3/target3:0:0/3:0:0:0/block/sdb/sdb3 (block)
KERNEL[1158955.733955] add /devices/pci0000:00/0000:00:0d.0/ata4/host3/target3:0:0/3:0:0:0/block/sdb/sdb4 (block)
148.533154 +20.351627 commit_to_os() ped_disk_commit_to_os(lp_disk) returned false
UDEV [1158955.738262] remove /devices/pci0000:00/0000:00:0d.0/ata4/host3/target3:0:0/3:0:0:0/block/sdb/sdb1 (block)
UDEV [1158955.738460] remove /devices/pci0000:00/0000:00:0d.0/ata4/host3/target3:0:0/3:0:0:0/block/sdb/sdb3 (block)
UDEV [1158955.738525] remove /devices/pci0000:00/0000:00:0d.0/ata4/host3/target3:0:0/3:0:0:0/block/sdb/sdb2 (block)
148.537648 +0.004494 execute_command() udevadm settle --timeout=10
UDEV [1158955.740864] remove /devices/pci0000:00/0000:00:0d.0/ata4/host3/target3:0:0/3:0:0:0/block/sdb/sdb4 (block)
UDEV [1158955.760192] change /devices/pci0000:00/0000:00:0d.0/ata4/host3/target3:0:0/3:0:0:0/block/sdb (block)
UDEV [1158955.801211] add /devices/pci0000:00/0000:00:0d.0/ata4/host3/target3:0:0/3:0:0:0/block/sdb/sdb4 (block)
UDEV [1158955.815262] add /devices/pci0000:00/0000:00:0d.0/ata4/host3/target3:0:0/3:0:0:0/block/sdb/sdb3 (block)
UDEV [1158955.815314] add /devices/pci0000:00/0000:00:0d.0/ata4/host3/target3:0:0/3:0:0:0/block/sdb/sdb2 (block)
UDEV [1158955.828134] add /devices/pci0000:00/0000:00:0d.0/ata4/host3/target3:0:0/3:0:0:0/block/sdb/sdb1 (block)
148.630797 +0.093149 execute_command() exit status 0
148.630882 +0.000085 commit_to_os() return false
D: stop strace pid 18054. Press [Return] to continue.
^Z
[1]+ Stopped ./gpartedbin /dev/sdb
# kill %3
strace: Process 18054 detached
[3]- Done strace -p 18054 -e open,ioctl,write,close
# kill %2
[2] Done udevadm monitor
# fg %1
./gpartedbin /dev/sdb
173.700143 +25.069261 commit() return false
173.700470 +0.000327 create_partition() return false
What happens is that GParted calls ped_disk_commit_to_dev() which opens
the device, writes the updated partition table and closes the device.
When the device closes the kernel initiates asynchronous uevents and
user space udev rules which remove and re-add all the partitions. In
the mean time GParted calls ped_disk_commit_to_os() to inform the kernel
of the changes to the partition table. This involves opening the
device, using ioctl() to remove all possible partitions [1] and re-add
needed partitions. It finds partitions 1 to 3 already removed and
accepts this along with all other non-existent partitions up to 64.
When it tries to re-add partition 1 the ioctl() BLKPG_ADD_PARTITION call
returns EBUSY. Presumably because the partition is in use by udev which
is in the process of running the user space rules associated with
removing and re-adding it. Then ped_disk_commit_to_os() closes the
device which initiates a second round of asynchronous uevents and user
space udev rules removing and re-adding all the partitions again.
So in summary the kernel and udev are removing and re-adding the
partitions exactly when libparted is trying to do exactly the same
thing!
[1] The algorithm in libparted 3.1 is to try to remove all possible
partitions, 64 for this kernel, followed by re-adding the needed
partitions.
parted/libparted/arch/linux.c:_disk_sync_part_table()
http://git.savannah.gnu.org/cgit/parted.git/tree/libparted/arch/linux.c?h=v3.1#n2541
Partprobe has had exactly the same issue with failing to inform the
kernel about modifications to the partition table [2]. This was fixed
in libparted post v3.2 release by this commit [3].
[2] rhbz#1339705 - ceph-disk prepare: Error: partprobe /dev/vdb failed :
Error: Error informing the kernel about modifications to partition
/dev/vdb1 -- Device or resource busy.
https://bugzilla.redhat.com/show_bug.cgi?id=1339705
[3] partprobe: Open the device once for probing
Previously there were 3 open/close pairs for the device, which may
result in triggering extra udev actions. Instead, open it once at
the start of process_dev and close it at the end.
http://git.savannah.gnu.org/cgit/parted.git/commit/?id=cfafa4394998a11f871a0f8d172b13314f9062c2
Implement the same fix as implemented for partprobe. Hold a file handle
open which libparted can use internally to avoid having to open() and
close() the device itself twice, once for each of the calls
ped_disk_commit_to_dev() and ped_disk_commit_to_os(). This avoids the
first close() initiating the kernel and udev to remove and re-add the
partitions exactly when ped_disk_commit_to_os() is trying to do the same
thing.
Bug 790418 - "Unable to inform the kernel of the change" message may
lead to corrupted partition table
The includes were missed being removed by this earlier refactoring
commit which reduced direct access to the single ProgressBar object:
b1313281bd
Simplify use of the progress bar via OperationDetail (#760709)
All libparted messages were reported as informational, even for a step
which failed. Instead identify libparted messages as either
informational or errors depending on whether this step was successful
or not respectively.
Bug 790842 - Report libparted messages into operation details at the
point at which they occur
Resizing any unmounted file system which has to be mounted to be resized
triggered the new GParted bug message. However the operation did
complete successfully. Example operation details:
Grow /dev/sdb8 from 1.00 GiB to 1.50 GiB (SUCCESS)
* calibrate /dev/sdb
* check file system on /dev/sdb8 for errors and (if possib...(SUCCESS)
* grow partition from 1.00 GiB to 1.50 GiB (SUCCESS)
* grow file system to fill the partition (SUCCESS)
* mkdir -v /tmp/gparted-wvH0Ez (SUCCESS)
* GParted Bug: Adding another child after no_more_chil...(ERROR)
* Created directory /tmp/gparted-wvH0Ez
* mount -v -t btrfs '/dev/sdb8' '/tmp/gparted-wvH0Ez' (SUCCESS)
* btrfs filesystem resize 1:max '/tmp/gparted-wvH0Ez' (SUCCESS)
* umount -v '/tmp/gparted-wvH0Ez' (SUCCESS)
* rmdir -v /tmp/gparted-wvH0Ez (SUCCESS)
* GParted Bug: Adding another child after no_more_chil...(ERROR)
* Removed directory /tmp/gparted-wvH0Ez
This is because set_success_and_capture_errors() was called first and
the child details added after. Reverse this ordering to fix.
Bug 790842 - Report libparted messages into operation details at the
point at which they occur
Transition all remaining code, DMRaid and file system code, to use the
new method of reporting success of a step and automatic error
collection. None of this code calls libparted so can't generate any
libparted exceptions. This is just for consistency so all code follows
the same pattern using set_success_and_capture_errors().
Bug 790842 - Report libparted messages into operation details at the
point at which they occur
Refactor nested if-then-else into a sequence of if fail return early.
Makes the code simpler to understand and converts separate
OperationDetail::set_status() calls for success or error into a single
call using ternary conditional matching how it is or was done everywhere
else. This is also ready for status and error capture refactoring.
Bug 790842 - Report libparted messages into operation details at the
point at which they occur
Transition GParted block copying code and partition manipulation code,
which uses libparted API, to the new method of reporting success of a
step and automatic error collection. Libparted exceptions are now
reported with the step at which they occurred.
Bug 790842 - Report libparted messages into operation details at the
point at which they occur
Just copies the callback into each newly added child detail. As there
are no more uses of set_success_and_capture_errors() yet, libparted
errors are still only captured once at the top-level of each operation.
Bug 790842 - Report libparted messages into operation details at the
point at which they occur
Replace the explicit adding of libparted exception messages with a
callback to do it instead, and fire the callback just once per operation
by only changing the very top-level OperationDetail to use the new
set_success_and_capture_errors(). Therefore this still produces exactly
the same operation details with libparted messages at the end of each
operation.
Bug 790842 - Report libparted messages into operation details at the
point at which they occur
All code implementing a step of an operation follows this pattern:
od.add_child(OperationDetail("Step heading"));
od.get_last_child().add_child(OperationDetail("More details"));
// Do step
success = ...
od.get_last_child().set_status(success ? STATUS_SUCCESS
: STATUS_ERROR);
At this point any libparted messages reported via exceptions need to be
added into the OperationDetail tree. Also adding further children into
the tree after collecting those errors needs to be prohibited (as much
as the previous patch prohibited it).
Add a new method which will replace the final set_status() call above
like this which set the status, captures the errors and flags that
further children shouldn't be added:
...
od.get_last_child().set_success_and_capture_errors(status);
It emits a callback to capture the errors to provide flexibility and so
that the OperationDetail class doesn't have to get into the details of
how GParted_Core saves libparted exception messages.
Bug 790842 - Report libparted messages into operation details at the
point at which they occur
Want functionality to prevent further child details being added to an
OperationDetail. This is so that the captured libparted error messages
are always the last child in the list, and more details (at that point
in the tree) can't be added.
For example we want GParted to report like this:
Move /dev/sdb3 to the right and shrink it from 1.14 GiB to...(SUCCESS)
...
* shrink partition from 1.14 GiB to 1.00 GiB (SUCCESS)
* old start: 4464640
old end: 6856703
old size: 2392064 (1.14 GiB)
* new start: 4464640
new end: 6561791
new size: 2097152 (1.00 GiB)
* libparted messages (INFO)
* DEBUG: GParted generated synthetic libparted excepti...
and not like this:
Move /dev/sdb3 to the right and shrink it from 1.14 GiB to...(SUCCESS)
...
* shrink partition from 1.14 GiB to 1.00 GiB (SUCCESS)
* old start: 4464640
old end: 6856703
old size: 2392064 (1.14 GiB)
* libparted messages (INFO)
* DEBUG: GParted generated synthetic libparted excepti...
* new start: 4464640
new end: 6561791
new size: 2097152 (1.00 GiB)
So actually preventing the addition of more child details would stop
users seeing information they should see. So instead just report a bug
message into the operation details. This doesn't stop anything, but the
bug message will be seen and allow us to fix GParted.
So far nothing is enforced. This patch just adds the mechanism to
report a bug when a new child detail is added when prohibited.
Bug 790842 - Report libparted messages into operation details at the
point at which they occur
PATCH SET SUMMARY:
Libparted exception messages are reported into the operation details at
the end of each separate operation. For operations which involve
multiple steps of partition manipulation there is no way to identify
which exceptions occurred with which steps.
Example resize/move operation in which multiple libparted exceptions
were raised:
Move /dev/sdb to the right and shrink it from 1.15 GiB to ...(ERROR)
* calibrate /dev/sdb3 (SUCCESS)
* check file system on /dev/sdb3 for errors and (if possib...(SUCCESS)
* e2fsck -f -y -v -C 0 '/dev/sdb3' (SUCCESS)
* shrink file system (SUCCESS)
* resize2fs -p 'dev/sdb3' 1048576K (SUCCESS)
* shrink partition from 1.14 GiB to 1.00 GiB (SUCCESS)
* check file system on /dev/sdb3 for errors and (if possib...(SUCCESS)
* e2fsck -f -y -v -C 0 '/dev/sdb3' (SUCCESS)
* grow partition from 1.00 GiB to 1.12 GiB (SUCCESS)
* move file system to the right (SUCCESS)
* e2image -ra -p -O 134217728 '/dev/sdb3' (SUCCESS)
* shrink partition from 1.12 GiB to 1.00 GiB (ERROR)
* libparted messages (INFO)
* DEBUG: GParted generated synthetic libparted exception...
* Error informing the kernel about modifications to part...
* Error informing the kernel about modifications to part...
* DEBUG: GParted generated synthetic libparted exception...
* DEBUG: GParted generated synthetic libparted exception...
But there is no way to know which of the libparted steps: 1 calibrate or
3 partition resize steps encountered which exceptions.
Fix this by reporting the libparted messages into the operation details
at the point at which they occur. Then the above example would become:
Move /dev/sdb to the right and shrink it from 1.15 GiB to ...(ERROR)
* calibrate /dev/sdb3 (SUCCESS)
* check file system on /dev/sdb3 for errors and (if possib...(SUCCESS)
* e2fsck -f -y -v -C 0 '/dev/sdb3' (SUCCESS)
* shrink file system (SUCCESS)
* resize2fs -p 'dev/sdb3' 1048576K (SUCCESS)
* shrink partition from 1.14 GiB to 1.00 GiB (SUCCESS)
* libparted messages (INFO)
* DEBUG: GParted generated synthetic libparted excepti...
* check file system on /dev/sdb3 for errors and (if possib...(SUCCESS)
* e2fsck -f -y -v -C 0 '/dev/sdb3' (SUCCESS)
* grow partition from 1.00 GiB to 1.12 GiB (SUCCESS)
* libparted messages (INFO)
* Error informing the kernel about modifications to pa...
* Error informing the kernel about modifications to pa...
* DEBUG: GParted generated synthetic libparted excepti...
* move file system to the right (SUCCESS)
* e2image -ra -p -O 134217728 '/dev/sdb3' (SUCCESS)
* shrink partition from 1.12 GiB to 1.00 GiB (ERROR)
* libparted messages (ERROR)
* DEBUG: GParted generated synthetic libparted excepti...
THIS PATCH:
Small change so that setting the status of an OperationDetail to N/A,
warning, also stops the execution timer if it was running. Matching
what happens when the status is set to either success or error.
This is to avoid having to set status twice, first time just to stop the
timer, and second time to set it to the desired status when reporting a
warning.
Bug 790842 - Report libparted messages into operation details at the
point at which they occur
Fix up following switch from whole_device flag to TYPE_UNPARTITIONED.
Also calibrate the type for whole disk device partitions.
Bug 788308 - Remove whole_device partition flag
So they display as previously; as all grey in the graphic and with only
the correct attributes shown.
Fix up following switch from whole_device flag to TYPE_UNPARTITIONED.
Bug 788308 - Remove whole_device partition flag
Fix up following switch from whole_device flag to TYPE_UNPARTITIONED.
Again use FS_UNALLOCATED to determine if a partition represents
unallocated space and creation of a new partition should be allowed.
This is so that trying to create a new partition on a whole disk device
shows the "No partition table found on device /dev/DEV" warning again.
Bug 788308 - Remove whole_device partition flag
After the change from whole_device flag to TYPE_UNPARTITIONED,
unallocated whole disk devices are no longer automatically selected
because the partition type is no longer TYPE_UNALLOCATED. Fix by
checking for file system type FS_UNALLOCATED when identifying the
largest unallocated space.
Bug 788308 - Remove whole_device partition flag
Following the switch from whole_device flag to TYPE_UNPARTITIONED,
unallocated space can be found in two partition types:
TYPE_UNALLOCATED
TYPE_UNPARTITIONED (only when filesystem == FS_UNALLOCATED)
As the file system in both cases is FS_UNALLOCATED check for that when
determining whether a partition is unallocated or not.
Bug 788308 - Remove whole_device partition flag
Remove whole_device flag and replace with new partition type
TYPE_UNPARTITIONED. Minimally adapt the remaining code to compile and
run.
Bug 788308 - Remove whole_device partition flag
Update the partition can be named and partition flags can be managed
checks from being disallowed on unallocated partition types, to being
allowed on primary, logical and extended partition types. This is in
preparation for the introduction of new unallocated partition type.
Bug 788308 - Remove whole_device partition flag
Now when refreshing the devices, GParted_Core::read_label() calls
GParted_Core::get_fs() with parameter FS_EXTENDED.
Before this change, get_fs() would fail to find file system capabilities
set for FS_EXTENDED and construct a not supported capabilities set and
return that.
Afterwards, find_supported_filesystems() creates a not supported
capabilities set from the NULL pointer for FS_EXTENDED and adds this
entry into the FILESYSTEMS vector. Then get_fs() finds that not
supported capabilities set for FS_EXTENDED in the FILESYSTEMS vector and
returns that.
This makes no functional difference. It just seems right as other
unsupported but used file system types have entries in FILESYSTEM_MAP.
See this earlier commit doing the same thing:
7870a92b80
Add FILESYSTEM_MAP[FS_UNALLOCATED] entry
For example GParted_Core::read_label() is already called for empty
partitions where .filesystem = FS_UNKNOWN. In that case get_fs()
returns an unsupported capability set with all capabilities set to
FS::NONE. The same would be true extended partitions where .filesystem
= FS_EXTENDED too; get_fs() would return an unsupported capability set
with all capabilities set to FS::NONE.
Therefore the if not extended partition condition around the switch
statements is not necessary in GParted_Core::read_label(), read_uuid(),
label_filesystem() and change_uuid(). Remove.
This also achieves removal of some uses of partition type enumerations
in advance of the introduction of new partition type TYPE_UNPARTITIONED.
Bug 788308 - Remove whole_device partition flag
PATCHSET OVERVIEW:
When unpartitioned drive read-write support was added this commit added
a whole_device flag:
5098744f9a
Add whole_device flag to the partition object (#743181)
Using a whole_device flags now seems not the correct way to model
unpartitioned drives. GParted models an uninitialised drive as:
.path = _("uninitialized")
.type = TYPE_UNALLOCATED
.whole_device = true
.filesystem = FS_UNALLOCATED
and a whole drive file system, using ext4 for example, as:
.path = "/dev/sdb"
.type = TYPE_PRIMARY
.whole_device = true
.filesystem = FS_EXT4
No partitioning changed yet the type of the partition in the model
changed between TYPE_UNALLOCATED and TYPE_PRIMARY depending on whether
the whole drive contains a recognised file system or not.
The partition object describing a file system within a LUKS encryption
mapping is another case of the model not matching reality.
.path = /dev/mapper/crypt_sdb1_crypt
.type = TYPE_PRIMARY
.whole_device = true
.filesystem = FS_EXT4
There is no partition table within the encryption mapping, the file
system fills it, but GParted records it as a primary partition.
Make TYPE_UNALLOCATED and TYPE_PRIMARY be reserved for representing
unallocated space and primary partitions within a partitioned disk drive
and introduce new TYPE_UNPARTITIONED for all cases of an unpartitioned
whole disk drive.
The GParted UI does differentiate between an unallocated whole disk
device and anything else by requiring a partition table to be created
first, even if that is just the loop partition table. That
determination can simply look for the partition object containing file
system type FS_UNALLOCATED instead.
THIS PATCH:
Create set_unpartitioned() helper method to set a partition object to
represent a whole disk drive and use everywhere such an object is
modelled. This matches what existing methods Set_Unallocated() and
indeed Set() do for unallocated space and any type of partition
respectively.
For now the partition type is still set to either TYPE_UNALLOCATED or
TYPE_PRIMARY so the rest of the code base remains the same.
TYPE_UNPARTITIONED will be introduced later.
Bug 788308 - Remove whole_device partition flag
There were a few cases of creating a local string variable from a
literal and then passing the variable to execute_command() like this:
Glib::ustring cmd = "whatever";
Utils::execute_command( cmd, ... );
This creates an unnecessary local variable. Instead pass the string
literal directly to Utils::execute_command() like this:
Utils::execute_command( "whatever", ... );
This also make the code a little bit more grep friendly.
No other commands run by GParted are niced, so stop nicing commands run
from the DMRaid module.
I think nicing of possibly long running file system modification
commands would have made virtually no difference because "nice -n 19"
lowered the CPU priority, but such command would be I/O bound.
History:
Nicing of file system modification commands was added by this commit
from 2006-08-21:
82e6f6b132
added nice -n 19, so that all extensive filesystem operations will be
Nicing of DMRaid operations was copied into the DMRaid module when it
was added here in 2009-03-14:
5865c92dc0
Added new class for dmraid support
Nicing was removed from file system modification commands with this
commit from 2013-02-22:
52a2a9b00a
Reduce threading (#685740)
Bug 788007 - Remove minor bits of legacy from DMRaid module
The -P option was first added to dmraid-1.0.0.rc15 released 2006-09-17
[1]. dmraid-1.0.0.rc16 (a later release) was included in Debian 6 and
Ubunbu 12.04 LTS. dmraid-1.0.0.rc13 was included in RedHat/CentOS 5
however the -P option was back ported into RedHat/CentOS 5.1.
All of these distributions are so old as to be no longer supported and
yet they provided the dmraid -P option. Therefore backward
compatibility for dmraid without the -P option is no longer required.
So remove it.
[1] old dmraid source code releases
http://people.redhat.com/heinzm/sw/dmraid/src/old/
Bug 788007 - Remove minor bits of legacy from DMRaid module
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()
Shell fragments must be properly quoted and escaped to prevent execution
of unintended commands derived from user controllable data. For
example:
$ printf '#!/bin/sh\necho test > out\n' > script.sh
$ chmod +x script.sh
$ truncate -s 20M 'jfs;script.sh'
$ mkfs.jfs -q 'jfs;script.sh'
$ ls -l out
ls: cannot access out: No such file or directory
$ sudo PATH=$PWD:$PATH /usr/local/bin/gparted 'jfs;script.sh'
$ sudo PATH=$PWD:$PATH /usr/local/bin/gparted 'jfs;script.sh'
$ ls -l out
-rw-r--r-- 1 root root 5 Sep 12 23:11 out
$ cat out
test
What is happening is that jfs::set_used_sectors() is using the device
name 'jfs;script.sh' without quoting it and passing it to the shell to
execute like this:
sh -c 'echo dm | jfs_debugfs jfs;script.sh'
which the shell duly executes as these two commands:
echo dm | jfs_debugfs jfs
script.sh
This could be a security related issue as "sh -c" is able to execute
arbitrary shell commands from the argument if if contains shell special
characters. Use Glib::shell_quote() [1] to quote and escape file names
and whole commands passed to the shell.
[1] Glib::shell_quote(const std::string & unquoted_string)
https://developer.gnome.org/glibmm/stable/group__ShellUtils.html
"Quotes a string so that the shell (/bin/sh) will interpret the
quoted string to mean unquoted_string.
If you pass a filename to the shell, for example, you should first
quote it with this function."
Bug 787203 - Correctly quote and escape arguments of external programs
passed to execute_command()
Naming a file system image file on the command line is shown by GParted
as unknown.
$ truncate -s 100M /tmp/fat.img
$ mkfs.vfat /tmp/fat.img
$ sudo ./gpartedbin /tmp/fat.img
Currently the FS_Info cache is loaded for all devices reported by
blkid (plus all whole disk devices identified from /proc/partitions even
if blkid reports nothing). However file system images named on the
command line are not queried so GParted can't identify them.
Fix by ensuring that the FS_Info blkid cache is loaded for all named
devices, including named file system image files.
Note that Mount_Info::load_cache() depends on the contents of the
FS_Info cache to lookup UUID= and LABEL= device names from /etc/fstab.
However only file systems in block devices can be mounted like this, and
never file system image files, so the fact that the cache may be
extended afterwards by FS_Info::load_cache_for_paths() does not matter.
History
Prior to version 0.22.0, when unpartitioned drive support was added,
GParted could recognise some file system image files using loop
partition handling in libparted. However libparted before version 3.2
reported the loop partition name as the whole disk device name appended
with "1" so all the query commands were provided a non-existent name to
use. Therefore no file system usage or the label was displayed.
Bug 787181 - Fix detection of file system images
Add double quote (") to the list of prohibited FAT label characters,
previously missed [1][2].
Also add single quote (') because mlabel encoded it in a way that both
Windows and blkid don't understand, although mlabel can correctly decode
it itself.
# export MTOOLS_SKIP_CHECK=1
# mlabel ::"MIKE'S" -i /dev/sdf1
# mlabel -s :: -i /dev/sdf1
Volume label is MIKE'S (abbr=MIKE_S~1???)
# blkid -o value -s LABEL /dev/sdf1
MIKE_S~1???
(8-bit characters in the above output have been replaced with
question marks (?) just to keep this commit message as 7-bit ASCII).
Finally exclude ASCII control characters below SPACE (0x00 to 0x1F) as
they also cause mlabel to ask a question and wait for input in the same
way that prohibited characters do. As discussed in the previous commit
[1] the only way to stop GParted waiting forever is to manually kill
mlabel with signal 9 (KILL).
# mlabel ::"^A" -i /dev/sdf1
Long file name "^A" contains illegal character(s).
a)utorename A)utorename-all r)ename R)ename-all
s)kip S)kip-all q)uit (aArRsSq):
[1] 584137b32b
Remove prohibited characters from FAT16/32 labels (#755608)
[2] Microsoft TechNet: Label
https://technet.microsoft.com/en-us/library/bb490925.aspx
Bug 787202 - Update list of prohibited fat label characters
So far GParted is still loading the default non-reversible encoded
labels from blkid in the initial loading of the FS_Info module cache.
This encoded label is used to match LABEL=<label> when reading
/etc/fstab, via the get_path_by_label() call, so works for ASCII only
labels. This prevents GParted enabling the "mount on >" partition menu
item when non-ASCII labels are used.
To fix this:
1) Stop reading the labels the wrong way.
Via the blkid command used to initially load the FS_Info module cache
and is subject to default non-reversible encoding of non-printable
ASCII bytes.
2) Read all the labels the right way, but only when needed.
Only when /etc/fstab file contains LABEL=<label> and
get_path_by_label() is called, read all the labels from blkid without
encoding them via run_blkid_update_cache_one_label().
3) Return label from the cache.
get_label() returns the cached label, loading it into the cache first
if needed with run_blkid_update_cache_one_label().
In the worst case scenario of having a LABEL=<label> in /etc/fstab blkid
will be run for every partition containing a recognised file system to
read the label. On my desktop with 5 hard drives, 4 SWRaid arrays and
31 recognised file systems running 'blkid -o value -s LABEL ...' 31
times took 0.074 seconds of a total scan time of 9.072 seconds. Less
that 1% of the total scanning time. When LABEL=<label> is not used in
/etc/fstab individual blkid executions are only used to read labels for
file systems where there is no file system specific tool available
reducing the impact further. Blkid itself caches the data in it's
blkid.tab cache file rather than reading all file systems on each
invocation. Also the Linux file system cache will already contain the
blkid executable file, needed libraries files and the blkid.tab cache
file itself. Hence why repeated execution of blkid is so fast.
Further to the updated comment in set_partition_label_and_uuid().
Matching LABEL=<label> from /etc/fstab uses the label obtained from
blkid run in the C locale so this kind of assumes it returns the label
correctly and it does for my limited testing on Unicode enabled
desktops. Just not sure if it would be true for all cases in all
locales compared to the FS specific command run in the users default
locale.
Bug 786502 - Support reading Unicode labels when file system specific
tools aren't available
Move the code which reads the Unicode label from FS_Info::get_label()
into new function run_blkid_update_cache_one_label() which also replaces
the non-reversibly encoded copy loaded during the initial cache load.
This is mainly a bit of code refactoring ready for the following change.
It deliberately keeps the initial loaded labels so that reading
/etc/fstab and decoding LABEL=<label> to block special device names via
FS_Info::get_path_by_label() continues to works, at least for ASCII only
labels.
Bug 786502 - Support reading Unicode labels when file system specific
tools aren't available
For file systems which don't provide a specific tool to read labels
(exfat, f2fs, hfs, hfsplus, udf and ufs) or when the tools aren't
installed for any other file system, reading labels falls back to using
the blkid command. Blkid encodes non-ASCII bytes in it's output [1].
For example blkid reports a short Unicode label like this:
# blkid /dev/sdb12
/dev/sdb12: LABEL="M-PM-^ZM-PM->M-QM-^HM-PM-:M-PM-0" TYPE="hfsplus"
This shows encoding using 'M-' for bytes above 127 and caret '^' for
control characters. Unfortunately neither 'M-' or '^' are encoded by
blkid so it is impossible to distinguish between the original label
containing either of these sequences or encoded non-printable bytes.
See this Bugzilla's bug 786502 entry for more details. Unfortunately
this makes the default output format from blkid unsuitable for reading
Unicode character labels.
Instead instruct blkid to print values without encoding them using the
'-o value' option. This just produces a list of new line separated
values without being able to identify which TYPE, UUID or LABEL belongs
to which device. So query just the label for each block device one at
a time. This method has the advantage of also working with all versions
of blkid, from version 1.0.0 (12-Feb-2003) in CentOS 5 to the latest
version 2.30.1 (20-Jul-2017) in Fedora 26.
# blkid -o value -s LABEL /dev/sdb12 | hexdump -C
00000000 d0 9a d0 be d1 88 d0 ba d0 b0 0a |...........|
0000000b
(Using hexdump -C just so that this commit message only contains ASCII
characters).
Therefore this commit changes FS_Info::get_label() to query blkid as
shown above. Note that GParted_Core::set_partition_label_and_uuid()
only calls get_label() when there is no file system specific tool
available (or the tool failed).
The FS_Info cache still contains copies of the labels subject to blkid
encoding, and that will be addressed in following commits.
[1] blkid.c v2.30.1 safe_print()
https://git.kernel.org/pub/scm/utils/util-linux/util-linux.git/tree/misc-utils/blkid.c?h=v2.30.1#n111
Bug 786502 - Support reading Unicode labels when file system specific
tools aren't available
When udftools are not installed and the mkudffs program isn't found
GParted would report this error during startup:
# ./gpartedbin
======================
libparted : 3.1
======================
Failed to execute child process "mkudffs" (No such file or directory)
Only run mkudffs to check for an old version when the program is found.
Bug 786050 - GParted reports failed to execute child process "mkudffs"
when it is not installed
Make especially the Volume Identifier length limit code simpler to
understand and therefore easier to maintain.
Bug 784533 - Add support for UDF file system
UDF label is stored in the Logical Volume Identifier which has space for
either 126 Latin1 or 63 UCS-2 characters. For compatibility reasons
with older versions of blkid, the possibly truncated UDF label is also
stored in the Volume Identifier which only has space for 30 Latin1 or 15
UCS-2 characters.
Because versions of mkudffs prior to 1.1 damage the label if it contains
non-ASCII characters, make sure GParted does not call such versions of
mkudffs with a non-ASCII character label.
Bug 784533 - Add support for UDF file system
Add support for detecting UDF file systems and formatting hard disks
with revision 2.01 UDF file systems using udftools. Formatting optical
disks or any other media types is not supported yet. Changing label or
UUID after formatting is not supported as the tools do not yet exist.
Bug 784533 - Add support for UDF file system
Btrfstune changed it's command line help output from being written on
stderr to being written on stdout in the following commit first included
in btrfs-progs 4.7.2 released 05-Sep-2016. This breaks GParted
detection of the change UUID capability. Found on the very latest
distributions: up to date Arch Linux and Fedora 26 Beta. Fix this.
https://git.kernel.org/pub/scm/linux/kernel/git/kdave/btrfs-progs.git/commit/?id=57d1cbd867311d99a2ae5e3cdcffd04
btrfs-progs: print help test to stdout
Bug 784467 - No longer detecting btrfs change UUID capability
Internal file system detection is broken for detection of LVM2 PVs
because it reports finding LVM2 PV even when only the first magic is
found. Prepare a partition like this:
# lvm pvcreate /dev/sdb1
# hexdump -C /dev/sdb1 > hexdump-1.txt
Clear the second magic:
# python
f = open("/dev/sdb1","w")
f.seek(0x218)
f.write("\x00"*4)
f.close()
quit()
# hexdump -C /dev/sdb1 > hexdump-2.txt
# diff -u hexdump-[12].txt
00000200 4c 41 42 45 4c 4f 4e 45 01 00 00 00 00 00 00 00 |LABELONE........|
-00000210 58 69 83 e1 20 00 00 00 4c 56 4d 32 20 30 30 31 |Xi.. ...LVM2 001|
+00000210 58 69 83 e1 20 00 00 00 00 00 00 00 20 30 30 31 |Xi.. ....... 001|
^^ ^^ ^^ ^^ ^^^^
00000220 52 4b 31 73 50 77 49 66 6a 72 55 4c 6a 4d 30 58 |RK1sPwIfjrULjM0X|
GParted still detects this as an LVM2 PV even though lvm and blkid do
not.
Correct logic error and only perform memcmp() with the second magic when
the second signature is non-NULL.
Bug 783997 - GParted detecting LVM2 PV regardless whether second magic
matches or not
For large output a lot of time is used copying capturebuf to callerbuf
to provide a Glib::ustring copy of the buffer for the update callback.
However update callbacks are only used when commands are run to apply
operations by FileSystem::execute_command() and their output is
incrementally displayed in the UI. Whereas update callbacks are never
used when commands are used to query information via
Utils::execute_command().
Stop performing interim copying of capturebuf to callerbuf when there
are no update callbacks registered as it is unnecessary.
Time to read portions of the recorded fsck.fat output via
fat16::set_used_sectors() and intermediate copies aren't required:
1 MiB 10 MiB 122 MiB
old code : 0.074 sec 1.41 sec 210 sec [3:30]
new code : 0.063 sec 0.56 sec 6.57 sec
Bug 777973 - Segmentation fault on bad disk
For large output PipeCapture spends all it's time copying the capturebuf
to callerbuf to provide a consistent view for any registered update
callbacks. This overhead is dependant of the size of the ever growing
captured output and the number of times OnReadable() is called.
Therefore increase the maximum read size to exponentially reduce this
overhead.
Time taken to read varying amounts of fsck.fat output with various
read buffer sizes:
1 MiB 10 MiB 122 MiB
512b : 0.60 sec 65 sec [1:05] 17262 sec [4:47:42]
4096b : 0.19 sec 13 sec 2157 sec [ 35:57]
64K : 0.07 sec 1.4 sec 210 sec [ 3:30]
Note that this is only increasing the maximum size that can be read from
the output of the external command. If the command produces it's output
slowly, such as the with progress reporting commands like mkfs.ext4,
then only the available number of bytes is read reporting the next
progress increment. However if the command produces it's output
quickly, such as when testing this bug using a modified fsck.fat
concatenating the 122 MiB of pre-recorded output, then full buffer reads
are performed.
To ensure that a single call to OnReadable() couldn't block the UI too
long, the time taken for OnReadable() to process a full buffer of
various sizes was recorded as:
512b : 0.031 milliseconds
4096b : 0.188 milliseconds
64K : 3.576 milliseconds
Adding this amount of processing time in the UI under normal
circumstances is not a problem.
As the captured output increases, the time taken by OnReadable() becomes
dominated by the time taken to copy the ever increasing capture buffer
to handle it's expansion and to copy it to the caller buffer for the
update callback. At the end of the 122M captured fsck.fat output
OnReadable() takes 350 milliseconds per call. This is not a problem
because this is an extreme case in which GParted is already hung and
increasing the buffer size is reducing the overall hang time from over
4 hours to a few minutes.
Bug 777973 - Segmentation fault on bad disk
If PipeCapture reads a NUL byte in the middle of what is expected to be
a multi-byte UTF-8 character then PipeCapture either returns the
captured characters to the previous update or loops forever depending on
whether the end of the stream is encountered before the read buffer is
full or not. This is equivalent to saying whether the NUL byte occurs
within the last 512 bytes of the output or not.
This is caused by a bug in g_utf8_get_char_validated() reporting that a
partial UTF-8 character has been found when the NUL byte is encountered
in the middle of a multi-byte character even though more bytes are
available in the length specified buffer. g_utf8_get_char_validated()
is always stopping at the NUL byte assuming it is working with a NUL
terminated string.
Workaround this by checking for g_utf8_get_char_validated() claiming a
partial UTF-8 character has been found when in fact there are at least
enough bytes in the read buffer to instead determine that it is really
an invalid UTF-8 character.
Reference:
Bug 780095 - g_utf8_get_char_validated() stopping at nul byte even
for length specified buffers
https://bugzilla.gnome.org/show_bug.cgi?id=780095
Bug 777973 - Segmentation fault on bad disk
If PipeCapture reads a NUL character, a valid UTF-8 character, it causes
GParted to allocate all available memory and crash. The while loop in
PipeCapture::OnReadable() loops forever reading the same NUL character
from readbuf because g_utf8_find_next_char() doesn't advance past it.
Hence an infinite number of NUL characters are added to the current
line, linevec.
Workaround this by checking for this failure case of
g_utf8_find_next_char() and increment past the NUL character.
This is actually a bug recently fixed in glib 2.49.3 released
2016-07-17. References:
* Bug 547200 - g_utf8_find_next_char() issues
https://bugzilla.gnome.org/show_bug.cgi?id=547200
* https://git.gnome.org/browse/glib/commit/?id=e0e652e4032a181d4f0b0a12aeddf0678b7a3c04
Fix a corner-case in g_utf8_find_next_char
In the case that *p is '\0', we should return p + 1, not p.
This change allows to simplify g_utf8_find_next_char a bit.
Bug 777973 - Segmentation fault on bad disk
A user had a very corrupted FAT file system such that fsck.fat produced
122 MiB of output. GParted has to read this output to get the file
system usage information. However GParted takes more than 48 hours to
read the 122 MiB of output, while using 100% CPU time and is
unresponsive for the duration.
Modified fsck.fat to output just the first 1 MiB of output and used perf
to capture performance data from GParted reading that output:
# perf -g -F 1999 -- ./gpartedbin
# perf report --stdio
67.84% Glib::ustring::replace [4.23s]
17.67% g_utf8_pointer_to_offset [1.10s]
8.48% g_utf8_offset_to_pointer [0.53s]
[ 6.01% (everything else) ] [0.38s]
[100.00% TOTAL ] [6.24s]
And to read the first 10 MiB of output the performance figures are:
92.95% Glib::ustring::replace [257.44s]
4.35% g_utf8_pointer_to_offset [ 12.05s]
2.13% g_utf8_offset_to_pointer [ 5.90s]
[ 0.58% (everything else) ] [ 1.61s]
[100.00% TOTAL ] [277.00s]
See how the total time is increasing non-linearly, 44 times longer for
only 10 times as much data. This is because of the exponential increase
in time spent in Glib::ustring::replace.
After a lot of experimentation I came to the conclusion that
Glib::ustrings are not appropriate for storing and editing large buffers
of data, sizes megabytes and above. The issues are that iterators are
invalid after the content changes and replacing UTF-8 characters by
index gets exponentially slower as the size of the string increases.
Hence the > 48 hours of 100% CPU time to read and apply the line
discipline to the 122 MiB of fsck.fat output. See code comment for a
more detailed description of the issues found.
Rewrote OnReadable() to use Glib::ustrings as little as possible.
Instead using buffers and vectors of fixed width data types allowing for
fast access using pointers and indexes (converted to pointers by the
compiler with simple arithmetic). Again see code comment for a more
detailed description of the implementation.
Repeating the performance capture with the new code for the first 1 MiB
of fsck.fat output:
63.34% memcpy [0.35s]
[ 36.66% (everything else) ] [0.21s]
[100.00% TOTAL ] [0.56s]
And for the first 10 MiB of fsck.fat output:
96.66% memcpy [63.60s]
[ 3.34% (everything else) ] [ 2.20s]
[100.00% TOTAL ] [65.80s]
Simple timings taken to read portions of the fsck.fat output (when not
using perf):
1 MiB 10 MiB 122 MiB
old code : 6.2 sec 277 sec > 48 hours
(4:37)
new code : 0.6 sec 66 sec 17262 sec
(1:06) (4:47:42)
Performance of the code is still non-linear because of the assignment
of the ever growing capturebuf to callerbuf for every block of input
read. This is required to generate a consistent Glib::ustring copy of
the input for the update callback. However this is much faster than
before, and I have a plan for further improvements.
Bug 777973 - Segmentation fault on bad disk
Seems more logical to initially clear the output capture buffer in a
single location in the PipeCapture class which reads the command output
into said buffer, rather than each calling site before the PipeCapture
objects are constructed.
Bug 777973 - Segmentation fault on bad disk
A user had a very corrupted FAT file system and when GParted was reading
the file system usage it would core dump. The tip of the stack trace
was:
#0 Glib::ustring_Iterator<__gnu_cxx::__normal_iterator<char*, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > > >::operator++()
at /usr/include/glibmm-2.4/glibmm/ustring.h line 957
#1 Glib::ustring_Iterator<__gnu_cxx::__normal_iterator<char*, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > > >::operator++(int)
at /usr/include/glibmm-2.4/glibmm/ustring.h line 965
#2 GParted::PipeCapture::OnReadable(Glib::IOCondition)
at PipeCapture.cc line 63
#3 GParted::PipeCapture::_OnReadable(_GIOChannel*, GIOCondition, void*)
at PipeCapture.cc line 45
GParted uses 'fsck.fat -n -v /dev/PTN' to get the file system usage.
However because the file system was so corrupted it was reporting every
file name as being damaged, including the file names being reported as
binary data. PipeCapture::OnReadable() reads up to 512 bytes at a time
and then uses a Glib::ustring iterator to loop over the UTF-8
characters, but a Glib::ustring iterator is explicitly not capable of
reading binary data [1]. With invalid UTF-8 bytes the code continued to
read beyond the end of the string until GParted crashed with a
segmentation violation.
Fix by accessing the read string by index instead of by iterator.
[1] Quote from the Glib::ustring_Iterator<T> Class Template Reference:
https://developer.gnome.org/glibmm/stable/classGlib_1_1ustring__Iterator.html
"The Glib::ustring iterated over must contain only valid UTF-8 data.
If it does not, operator++(), operator--() and operator*() may make
accesses outside the bounds of the string."
Bug 777973 - Segmentation fault on bad disk
As the source code is managed in GIT and there is a .gitignore file in
the top level directory specifying file names to exclude from version
control, then the old per-directory .cvsignore files for CVS are
redundant.
Add the only missing and applicable entry from src/.cvsignore of '.libs'
to .gitignore and remove all the .cvsignore files.
Attempting to grow an already mounted xfs where the mount point
contained spaces failed like this:
Grow /dev/sdb4 from 1.00 GiB to 1.50 GiB
+ calibrate /dev/sdb4
+ grow partition from 1.00 GiB to 1.50 GiB
+ grow file system to fill the partition
+ xfs_growfs /tmp/File System Label
Usage: xfs_growfs [options] mountpoint
...
Apply the rule and quote all uses of mount points within command lines.
This is also applied to copying xfs file systems even though it was safe
because it only ever used GParted generated mount points.
Also for the xfs copy operation switch unmounting of partitions to
specify mount points instead of partitions. This is just to be
consistent with how it is done in all the online file system resizing
code.
Bug 782681 - btrfs partitions mounted with whitespace cannot be resized
The current nilfs2 resizing code is safe because it never passes a user
influenced mount point into a command line. Regardless, apply the same
simple rule to always quote mount points when used in command lines.
WARNING:
Nilfs-resize is broken and can't actually resize a file system mounted
with spaces in the mount point anyway!
# mkdir "/tmp/File System Label"
# mount -v -t nilfs2 /dev/sdb3 "/tmp/File System Label"
mount.nilfs2: started nilfs_cleanerd
# nilfs-resize -v -y /dev/sdb3
Error: cannot open NILFS on /dev/sdb3.
# echo $?
1
# strace nilfs-resize -v -y /dev/sdb3
...
stat("/dev/sdb3", {st_mode=S_IFBLK|0660, st_rdev=makedev(8, 19), ...}) = 0
open("/dev/sdb3", O_RDONLY) = 3
...
open("/proc/mounts", O_RDONLY) = 4
read(4, "sysfs /sys sysfs rw,seclabel,nos"..., 1024) = 1024
...
close(4) = 0
open("/tmp/File\\040System\\040Label", O_RDONLY) = -1 ENOENT (No such file or directory)
...
# fgrep /dev/sd /proc/mounts
/dev/sda3 / ext4 rw,seclabel,relatime,data=ordered 0 0
/dev/sda1 /boot ext4 rw,seclabel,relatime,data=ordered 0 0
/dev/sdb3 /tmp/File\040System\040Label nilfs2 rw,relatime 0 0
So it looks like nilfs-resize (or a library it uses) can't decode the
octal characters '\040' used to encode spaces in the mount point as
reported in /proc/mounts.
Bug 782681 - btrfs partitions mounted with whitespace cannot be resized
Attempting to grow an already mounted jfs where the mount point
contained spaces failed like this:
Grow /dev/sdb2 from 1.00 GiB to 1.50 GiB
+ calibrate /dev/sdb2
+ grow partition from 1.00 GiB to 1.50 GiB
+ grow file system to fill the partition
+ mount -v -t jfs -o remount,resize /dev/sdb2 /tmp/File System Label
Usage:
mount [-lhV]
mount -a [options]
mount [options] [--source[ <source> | [--target] <directory>
mount [options] <source> <directory>
mount <operation> <mountpoint> [<target>]
...
Apply the rule to always enclose mount points within double quotes
within command lines.
Bug 782681 - btrfs partitions mounted with whitespace cannot be resized
A user had a btrfs file system mounted by automounter on a mount point
like "/mount/$USER/File System Label" which included white space
characters. Resizing the file system while online failed like this:
Grow /dev/sdb1 from 1.00 GiB to 1.50 GiB
+ calibrate /dev/sdb1
+ grow partition from 1.00 GiB to 1.50 GiB
+ grow file system to fill the partition
+ btrfs filesystem resize 1:max /mount/USER/File System Label
btrfs filesystem resize: too many arguments
usage: btrfs filesystem resize [devid:][+/-]<newsize>[kKmMgGtTpPeE]|[devid:]max <path>
So mount points not created by GParted should be considered under user
control and need quoting when used as parameters in command lines.
Strictly speaking, mount points created by GParted itself, by
FileSystem::mk_temp_dir(), are safe and don't need quoting. However it
is simpler and safer just to quote all uses of mount points in command
lines, rather than risk missing some.
Bug 782681 - btrfs partitions mounted with whitespace cannot be resized
Using the default MiB alignment, creating an MSDOS logical partition
between two other existing logical partitions fails with this error
dialog:
(-) <b>An error occurred while applying the operations</b>
See the details for more information.
<b>IMPORTANT</b>
If you want support, you need to provide the saved details!
See http://gparted.org/save-details.htm for more information.
[ OK ]
and these operation details:
+ libparted messages
- Unable to satisfy all constraints on the partition.
This bug was introduced by this commit included in GParted 0.23.0:
90e3ed68fc
Shallow copy Device object into Operation object (#750168)
The commit message claimed that the deep copied Partition objects inside
the Device inside the Operation object are never accessed. This turned
out not to be true. Win_GParted::Add_Operation() uses them as part of
snap_to_alignment() which updates requested partition boundaries to
account for alignment requirements and the space needed for EBR
(Extended Boot Record) preceding logical partitions.
In this case the new logical partition was trying to be created over the
top of the EBR for the following logical partition because
snap_to_alignment() wasn't aware of its existence.
Fix by making Add_Operation() and snap_to_alignment() refer to the
current device, as displayed in the UI, rather than the shallow copy
included in the Operation object. Hopefully now it is true that the
not copied vector of Partition objects in the Device object in each
Operation object are never accessed.
Bug 779339 - enforce at least 1 MiB "free space following"
A regression which prevented growing a primary partition that had
unallocated space between it and the following extended partition was
introduced with the following commit:
Create and use general find_extended_partition() function
aa98107706
To fix the regression, restore the logic that checked for a logical
partition before seeking the index of the extended partition.
Bug 778700 - Unable to grow partition even though unallocated space is
adjacent
Increase the size of the Name Partition dialog, matching the change made
to the Label File System dialog in the previous commit. The code for
the Name Partition dialog was basically copied from the Label File
System dialog.
Bug 778003 - The "Label File System" dialog is too small
On Arch Linux with XFCE 4.12 and Fedora 24 with GNOME 3.20 and later;
the Label File System dialog is too small. The problem is that the
label entry box clips the Cancel and OK buttons.
Stop specifying the dialog height, instead letting it fit the combined
height of all the widgets automatically.
Also make the dialog wider and the label entry box wider so that longer
device names can be shown in the title before they are truncated.
Bug 778003 - The "Label File System" dialog is too small
Change the error message after it raised a question with the translators
and to better align with the operation only being described as a check
in the GParted Manual and in the application UI.
Bug 774818 - Implement LUKS read-write actions NOT requiring a
passphrase
The Operation class already provided find_index_extended() method and
was used in the Operation and derived classes where required. It
returns the index to the extended partition in the PartitionVector
object, or -1 when no extended partition exists.
There were several cases of the same functionality being open coded in
GParted_Core and Win_GParted. Therefore move the implementation to
find_extended_partition() in PartitionVector compilation unit and use
this implementation everywhere.
The clear_mountpoints parameter has never been used since
add_mountpoint*() were first added [1][2]. clear_mountpoints() method
[3] is available to provide this functionality and used. Therefore
removed unused parameter and code.
[1] add_mountpoints() added 2006-03-15
9532c3cad1
Made Partition::mountpoints private
[2] add_mountpoint() added 2011-12-16
208083f11d84dbd4f186271a3cdbf5170db259f8b8
Display LVM2 VGNAME as the PV's mount point (#160787)
[3] clear_mountpoint() added 2006-03-19
ad9f2126e7
fixed issues with copying (see also #335004) cleanups + added FIXME added
Shrinking LUKS encryption is only possible while the mapping is open and
active. Therefore the File System Support dialog shows Cross + Tick for
this operation. Add this new combination to the legend.
Bug 774818 - Implement LUKS read-write actions NOT requiring a
passphrase
Switch the remaining create and delete operation description generation
to use the virtual Partition get_filesystem_string() method.
Bug 774818 - Implement LUKS read-write actions NOT requiring a
passphrase
Now that resizing of encrypted file systems is implemented add growing
of the open LUKS mapping as part of the check repair operation.
Resizing an encrypted file system requires the LUKS mapping to be open
to access the file system within; therefore it also requires libparted
and kernel support for online partition resizing. This limits resizing
to the latest distributions with libparted >= 3.2 and kernel >= 3.6.
However growing an open LUKS mapping as part of a check repair operation
doesn't require resizing the partition. Therefore route via offline
grow of LUKS to avoid those extra, unnecessary requirement. This does
mean that offline LUKS grow artificially requires cryptsetup, but that is
not really significant as even opening LUKS requires cryptsetup.
So now checking an encrypted file system on even the oldest
distributions does:
1) runs FSCK on the encrypted file system;
2) grows the encryption volume to fill the partition;
3) grows the file system to fill the encryption mapping.
Bug 774818 - Implement LUKS read-write actions NOT requiring a
passphrase
While a device-mapper encryption mapping can only be resized while
active, a LUKS volume can inherently be grown while offline because it
doesn't store a size and when started fills the partition. This doesn't
even need the cryptsetup command to do the resizing (just to open the
LUKS volume afterwards which GParted doesn't yet support). Implement
offline growing of LUKS volumes.
Bug 774818 - Implement LUKS read-write actions NOT requiring a
passphrase
Ensure pre-conditions of always or never being passed a Partition object
containing an open LUKS encryption are met for resizing file system and
LUKS encryption methods.
Bug 774818 - Implement LUKS read-write actions NOT requiring a
passphrase
Moving of closed LUKS is simply enabled by luks .move capability being
set and requires no further coding.
Resizing of encrypted file systems requires both the LUKS mapping and
encrypted file system within to be resized in the right order for both
shrinking and growing. To keep the code simple split resizing of plain
and encrypted into separate functions.
Bug 774818 - Implement LUKS read-write actions NOT requiring a
passphrase
Changing the Resize/Move dialog code to also handle PartitionLUKS
objects was considered too complicated. Instead create an unencrypted
equivalent using clone_as_plain(), pass that to the Resize/Move dialog
and finally apply the change back using Partition*::resize().
Bug 774818 - Implement LUKS read-write actions NOT requiring a
passphrase
Add a resize() method to both Partition and PartitionLUKS classes. They
take a reference Partition object, and update the position, size and
file system usage of *this Partition to match. This is ready for taking
a partition returned from Resize/Move dialog and applying the change.
Bug 774818 - Implement LUKS read-write actions NOT requiring a
passphrase
Implement a specialist PartitionLUKS clone method. Creates a new
Partition object which has the same space usage as the source encrypted
file system, but is a plain file system. Namely, the overhead of the
LUKS header has been added to the file system usage. This is ready for
feeding this representation of the partition to the Resize/Move dialog.
Bug 774818 - Implement LUKS read-write actions NOT requiring a
passphrase
A partition containing LUKS encryption can only be moved when closed and
the Device Mapper encryption mapping only exists to be resized when
open. As GParted can't yet open or close LUKS encryption these
restrictions have to be adhered to when composing operations. Also as
encrypted partitions are only being resized when open, additionally
libparted and the kernel have to both be capable of resizing a partition
while in use.
Bug 774818 - Implement LUKS read-write actions NOT requiring a
passphrase
Ensure pre-condition of never being passed a Partition object containing
an open LUKS encryption mapping is met for copy operation related
methods.
Bug 774818 - Implement LUKS read-write actions NOT requiring a
passphrase
Users will expect to see that copying of LUKS is available in the File
System Support dialog, even if technically what is implemented is
copying of the file system within an open encryption mapping. There is
no other reason to do this change as these two previous commits have
fully enabled copying of encrypted content:
Implement copy operation of encrypted file systems (#774814)
Preview copy operation of encrypted file systems (#774818)
Set LUKS .copy capability so that the dialog shows copying availability,
but then disallow copying of closed LUKS. (Checking for the capability
and performing copying the content of an open LUKS encryption mapping is
inherent in Win_GParted::set_valid_operations() and GParted_Core::copy()
in the way that they access the block device containing the file system,
whether encrypted or not).
Bug 774818 - Implement LUKS read-write actions NOT requiring a
passphrase
Implement the copy operation by making the copy code work with the
Partition object directly containing the file system, instead of the
enclosing PartitionLUKS object containing the LUKS encryption mapping.
Bug 774818 - Implement LUKS read-write actions NOT requiring a
passphrase
Implement composing of the copy paste operation for encrypted file
systems.
Copying a closed LUKS partition would duplicate the LUKS header
containing the UUID, passphrase and master encryption key. From a
security point of view having additional copies of encrypted data with
the same master key is an extra risk, but it all depends on what is
going to happen with that copy. The Cryptsetup FAQ [1] talks about how
to make a backup at the file system level and block level, preferring
file system level with separate encryption if needed. It strongly
recommends separate encryption if the copy is removable or going
off-site [2]. Also in the case of cloning the data, cloning the LUKS
container is strongly discouraged [3].
Therefore copying of encrypted file systems will be implemented by
copying the file system inside an open LUKS encryption mapping and not
by copying a closed LUKS partition.
Also, while creating new LUKS encryption is not yet supported, copying
an encrypted file system into a new partition will not be permitted as
that will always decrypt the data. An encrypted file system will be
allowed to be copied into an existing plain partition, decrypting the
data, or into an existing open encrypted partition, keeping it
encrypted. Pasting over the top of a closed encrypted partition will
remove the LUKS encryption. (This is planned to be removed when
creating and removing LUKS encryption is implemented as part of full
LUKS read-write support).
Remember that when pasting into an existing partition the file system
must fit within the available space and that encryption has overhead
from the LUKS header. Therefore copying from a plain partition into a
partition of the same size with open an encryption mapping will not fit
for space reasons.
[1] The Cryptsetup FAQ, Backup and data Recovery section
https://gitlab.com/cryptsetup/cryptsetup/wikis/FrequentlyAskedQuestions
[2] 6.7 Does a backup compromise security?
"If you do network-backup or tape-backup, I strongly recommend to go the
filesystem backup path with independent encryption, as you typically
cannot reliably delete data in these scenarios, especially in a cloud
setting."
[3] 6.15 Can I clone a LUKS container?
"You can, but it breaks security, because the cloned container has the
same header and hence the same master key. You cannot change the master
key on a LUKS container, even if you change the passphrase(s), the
master key stays the same. That means whoever has access to one of the
clones can decrypt them all, completely bypassing the passphrases.
The right way to do this is to first luksFormat the target container,
then to clone the contents of the source container, with both containers
mapped, i.e. decrypted. You can clone the decrypted contents of a LUKS
container in binary mode, although you may run into secondary issues
with GUIDs in filesystems, partition tables, RAID-components and the
like. These are just the normal problems binary cloning causes.
Note that if you need to ship (e.g.) cloned LUKS containers with a
default passphrase, that is fine as long as each container was
individually created (and hence has its own master key). In this case,
changing the default passphrase will make it secure again."
Bug 774818 - Implement LUKS read-write actions NOT requiring a
passphrase
Ensure pre-condition of never being passed a Partition object containing
an open LUKS encryption mapping is met for format operation related
methods.
Bug 774818 - Implement LUKS read-write actions NOT requiring a
passphrase
Formatting an existing encrypted partition will format the file system
within the encrypted mapping. Formatting over the top of a closed
encrypted partition will remove the encryption. (The latter is planned
to be prevented when creating and removing LUKS encryption is
implemented as part of full LUKS read-write support).
Composing the format operation inside an open LUKS encryption mapping
also has to account for the size of that mapping and construct a
PartitionLUKS object containing the new file system. Implementing the
operation itself is as simple as passing the Partition object directly
containing the file system, instead of the outer PartitionLUKS object.
Bug 774818 - Implement LUKS read-write actions NOT requiring a
passphrase
Already have:
Utils::get_filesystem_string(FS_EXT2) -> "ext2"
virtual Partition::get_filesystem_string() -> "ext2"
virtual PartitionLUKS::get_filesystem_string() -> "[Encrypted] ext2"
Add these:
Utils::get_encrypted_string() -> "[Encrypted]"
Utils::get_filesystem_string(false, FS_EXT2) -> "ext2"
Utils::get_filesystem_string(true, FS_EXT2) -> "[Encrypted] ext2"
This is ready for use of Utils::get_filesystem_string(true, FS_EXT2)
when composing the preview of a format of an encrypted file system by
Win_GParted::activate_format().
Bug 774818 - Implement LUKS read-write actions NOT requiring a
passphrase
Adapts the swapon/swapoff, activate/deactivate Volume Group and mount/
unmount file system code to work with the Partition object directly
containing the file system.
Bug 774818 - Implement LUKS read-write actions NOT requiring a
passphrase
Ensure pre-condition of never being passed a Partition object containing
an open LUKS encryption mapping is met for check operation related
methods.
Bug 774818 - Implement LUKS read-write actions NOT requiring a
passphrase
Just update the code describing and implementing the check operation.
No need to update the code composing the operation in
Win_GParted::activate_check() as that is incredibly simple, just cloning
the Partition object and doesn't need changing.
Note that for encrypted file systems this does:
1) runs FSCK on the encrypted file system;
2) grows the file system to fill the encrypted mapping.
At this time it does not grow the encryption mapping to fill the
partition. That will be added after resize/move has been implemented.
Bug 774818 - Implement LUKS read-write actions NOT requiring a
passphrase
Ensure pre-condition of never being passed a Partition object containing
an open LUKS encryption mapping is met for label file system operation
related methods.
Bug 774818 - Implement LUKS read-write actions NOT requiring a
passphrase
Again, just need to change the code when composing, describing and
implementing the operation to query and set the Partition object
directly containing the file system, instead of the enclosing encryption
mapping to make it work.
Bug 774818 - Implement LUKS read-write actions NOT requiring a
passphrase
Ensure pre-condition of never being passed a Partition object containing
an open LUKS encryption mapping is met for change UUID operation related
methods.
Bug 774818 - Implement LUKS read-write actions NOT requiring a
passphrase
When composing, describing and implementing the operation just need the
code to query and set the Partition object directly containing the file
system, instead of the enclosing encryption mapping to make it work.
The operation details for setting a new UUID on an encrypted ext4 file
system become:
Set a new random UUID on [Encrypted] ext4 file system on /dev/sdb4
+ calibrate /dev/sdb4
+ Set UUID on /dev/mapper/sdb4_crypt to a new, random value
+ tune2fs -U random /dev/mapper/sdb4_crypt
tune2fs 1.41.12 (17-May-2010)
Also note the now documented rule in apply_operation_to_disk() which
says each operation must leave the status of the encryption mapping and
file system as it found it.
Bug 774818 - Implement LUKS read-write actions NOT requiring a
passphrase
Provide and use a single interface for getting the file system string
for display, regardless of whether the partition is encrypted or the
encryption mapping is active or not.
Example return values for get_filesystem_string() for different types
and states of Partition objects:
1) Plain ext4 file system: -> "ext4"
2) Closed encrypted: -> "[Encrypted]"
3) Open encrypted ext4 file system: -> "[Encrypted] ext4"
This simplifies the code in TreeView_Detail::create_row() which sets the
file system type displayed in the main window. The same method will
then also be used when setting the operation description as each
operation is updated to handle encrypted file systems.
Bug 774818 - Implement LUKS read-write actions NOT requiring a
passphrase
The previous commit changed how the code behind the main window
retrieved the file system label for display. This is the relevant
changes in TreeView_Detail::create_row():
+ const Partition & filesystem_ptn = partition.get_filesystem_partition();
...
- Glib::ustring temp_filesystem_label = partition.get_filesystem_label();
+ Glib::ustring temp_filesystem_label = filesystem_ptn.get_filesystem_label();
treerow[treeview_detail_columns.label] = temp_filesystem_label;
In the case of an encrypted file system get_filesystem_label() is now
called on the Partition object directly rather than on the outer
Partition object containing the LUKS encryption.
The code behind the Information dialog always obtained and used the
Partition object directly containing the file system to call
get_filesystem_label() since read-only LUKS support was added.
Therefore the virtualised PartitionLUKS::get_filesystem_label() is no
longer needed, so remove it.
Bug 774818 - Implement LUKS read-write actions NOT requiring a
passphrase
There are multiple cases of code wanting to work with the Partition
object directly containing the file system, regardless of whether it is
within a PartitionLUKS object or not. The code had to do something
similar to this to access it:
const Partition * filesystem_ptn = &partition;
if ( partition.filesystem == FS_LUKS && partition.busy )
filesystem_ptn = &dynamic_cast<const PartitionLUKS *>( &partition )->get_encrypted();
...
// Access Partition object directly containing the file system
filesystem_ptn-> ...
Implement and use virtual accessor get_filesystem_partition() which
allows the code to be simplified like this:
const Partition & filesystem_ptn = partition.get_filesystem_partition();
...
// Access Partition object directly containing the file system
filesystem_ptn. ...
Bug 774818 - Implement LUKS read-write actions NOT requiring a
passphrase
In the main window, display the busy status of the file system only
according to whether it is mounted or not, ignoring the status of the
encryption mapping.
Bug 774818 - Implement LUKS read-write actions NOT requiring a
passphrase
More recent versions of blkid don't report an ISO9660 file system on the
whole disk device if partitions can be reports for embedded partitions.
However when querying the whole disk device directly then the expected
ISO9660 file system is reported. For example on CentOS 7 with the
previous ISO images:
# wget http://git.kernel.org/cgit/utils/util-linux/util-linux.git/plain/tests/ts/isosize/sample.iso.gz
# dd if=/dev/zero bs=1M of=/dev/sdc
# zcat sample.iso.gz | dd of=/dev/sdc
# blkid -v
blkid from util-linux 2.23.2 (libblkid 2.23.0, 25-Apr-2013)
# blkid | fgrep /dev/sdc
/dev/sdc1: UUID="2013-01-04-22-05-45-00" LABEL="ARCH_201301" TYPE="iso9660" PTTYPE="dos"
# blkid /dev/sdc
/dev/sdc: UUID="2013-01-04-22-05-45-00" LABEL="ARCH_201301" TYPE="iso9660" PTTYPE="dos"
# wget http://cdimage.debian.org/debian-cd/8.6.0/amd64/iso-cd/debian-8.6.0-amd64-netinst.iso
# dd if=/dev/zero bs=1M of=/dev/sdc
# dd if=debian-8.6.0-amd64-netinst.iso bs=1M of=/dev/sdc
# blkid | fgrep /dev/sdc
/dev/sdc1: UUID="2016-09-17-14-23-48-00" LABEL="Debian 8.6.0 amd64 1" TYPE="iso9660" PTTYPE="dos"
/dev/sdc2: SEC_TYPE="msdos" UUID="17F3-1162" TYPE="vfat"
# blkid /dev/sdc
/dev/sdc: UUID="2016-09-17-14-23-48-00" LABEL="Debian 8.6.0 amd64 1" TYPE="iso9660" PTTYPE="dos"
This behavioural difference with blkid is probably as a result of newer
versions of udev informing the kernel of the partitions embedded within
the ISO9660 image, and not directly as a result of a change in blkid
itself. Older distributions don't have partition entries for the above
ISO images, but CentOS 7 (with udev 219) and later distributions do have
partition entries:
# fgrep sdc /proc/partitions
8 16 8388608 sdc
8 17 252928 sdc1
8 18 416 sdc2
Fix by ensuring that the blkid FS_Info cache has entries for whole disk
devices, even if each entry has all empty attributes because there is a
partition table and not a recognised file system.
Calling blkid on whole disk devices containing partition tables produces
output like this, with newer versions of blkid:
# blkid /dev/sda
/dev/sda: PTTYPE="dos"
# blkid /dev/sdb
/dev/sdb: PTTYPE="gpt"
This will be loaded into the FS_Info cache as a blank entry for the
device by run_blkid_load_cache(). There will be a path name but all the
other attributes will be blank because there are no TYPE, SEC_TYPE, UUID
or LABEL name value pairs. With older versions of blkid no output is
produced at all. In that case load_fs_info_cache_extra_for_path() will
create the same blank entry with just the path name defined.
Bug 771244 - gparted does not recognize the iso9660 file system in
cloned Ubuntu USB boot drives
ISO9660 images can contain embedded partitions which when encountered on
whole disk drives causes libparted to report various warnings and
errors. For example on CentOS 6 with upgraded libparted 2.4 the
following errors and warnings are encountered with various ISO images.
(Deliberately using an older distribution with older blkid to avoid
another issue with blkid addressed in the following patch).
Libparted error message 1:
# wget http://git.kernel.org/cgit/utils/util-linux/util-linux.git/plain/tests/ts/isosize/sample.iso.gz
# dd if=/dev/zero bs=1M of=/dev/sdc
# zcat sample.iso.gz | dd of=/dev/sdc
# blkid -v
blkid from util-linux-ng 2.17.2 (libblkid 2.17.0, 22-Mar-2010)
# blkid | fgrep /dev/sdc
/dev/sdc: LABEL="ARCH_201301" TYPE="iso9660"
# ./gpartedbin /dev/sdc
======================
libparted : 2.4
======================
Invalid partition table - recursive partition on /dev/sdc.
Libparted Error
(-) Invalid partition table - recursive partition on /dev/sdc.
[ Cancel ] [ Ignore ]
Libparted error message 2:
# wget http://cdimage.debian.org/debian-cd/8.6.0/amd64/iso-cd/debian-8.6.0-amd64-netinst.iso
# dd if=/dev/zero bs=1M of=/dev/sdc
# dd if=debian-8.6.0-amd64-netinst.iso bs=1M of=/dev/sdc
# blkid | fgrep /dev/sdc
/dev/sdc: LABEL="Debian 8.6.0 amd64 1" TYPE="iso9660"
# ./gpartedbin /dev/sdc
======================
libparted : 2.4
======================
/dev/sdc contains GPT signatures, indicating that it has a GPT
table. However, it does not have a valid fake msdos partition
table, as it should. Perhaps it was corrupted -- possibly by a
program that doesn't understand GPT partition tables. Or perhaps
you deleted the GPT table, and are now using an msdos partition
table. Is this a GPT partition table?
Libparted Warning
/!\ /dev/sdc contains GPT signatures, indicating that it has a GPT
table. However, it does not have a valid fake msdos partition
table, as it should. Perhaps it was corrupted -- possibly by a
program that doesn't understand GPT partition tables. Or
perhaps you deleted the GPT table, and are now using an msdos
partition table. Is this a GPT partition table?
[ Yes ] [ No ]
These messages are because GParted is calling ped_disk_new() to attempt
to read the partition table even before it has tried to recognise the
ISO9660 file system on the whole disk drive. Full call chain is:
set_devices_thread()
set_device_from_disk()
get_device_and_disk()
get_disk()
ped_disk_new()
Fix this by delaying the call to ped_disk_new() until after whole disk
drive recognition has been performed. Replace combined
get_device_and_disk() with separate get_device() and only call
get_disk() after no whole disk drive file system has been recognised.
This is similar to how calibrate_partition() and
erase_filesystem_signatures() are structured to also handle whole disk
drive file systems.
Bug 771244 - gparted does not recognize the iso9660 file system in
cloned Ubuntu USB boot drives
Move code from GParted_Core::set_devices_thread() performing top level
population of each Device object during the scan of the drives into new
set_device_from_disk() method.
Bug 771244 - gparted does not recognize the iso9660 file system in
cloned Ubuntu USB boot drives
Requires blkid.
Note that FS_LUKS was also moved to more closely match the order in
include/Utils.h
Bug 771244 - gparted does not recognize the iso9660 file system in
cloned Ubuntu USB boot drives
Glibc 2.25 is deprecating <sys/types.h> including <sys/sysmacros.h>.
https://sourceware.org/git/?p=glibc.git;a=commitdiff;h=dbab6577c6684c62bd2521c1c29dc25c3cac966f
Deprecate inclusion of <sys/sysmacros.h> by <sys/types.h>
Building on Fedora Rawhide with Glibc 2.24.90 produces these warnings:
BlockSpecial.cc:64:13: warning: In the GNU C Library, "major" is defined
by <sys/sysmacros.h>. For historical compatibility, it is
currently defined by <sys/types.h> as well, but we plan to
remove this soon. To use "major", include <sys/sysmacros.h>
directly. If you did not intend to use a system-defined macro
"major", you should undefine it after including <sys/types.h>.
m_major = major( sb.st_rdev );
^~~~~~~~~~~~~~~~~~~~
BlockSpecial.cc:65:13: warning: In the GNU C Library, "minor" is defined
by <sys/sysmacros.h>. For historical compatibility, it is
currently defined by <sys/types.h> as well, but we plan to
remove this soon. To use "minor", include <sys/sysmacros.h>
directly. If you did not intend to use a system-defined macro
"minor", you should undefine it after including <sys/types.h>.
m_minor = minor( sb.st_rdev );
^~~~~~~~~~~~~~~~~~~~
Code needing major and minor macros should include <sys/sysmacros.h>
directly. As both Glibc and musl-libc have always provided this header
and GParted is a Linux only application, just always include the header
and don't bother with an autoconf check for its existence.
Bug 776173 - Missing sys/sysmacros.h #include, needed for experimental
glibc versions
The details for a file system shrink operation look like this with the
"shrink file system" message being missing:
Shrink /dev/sdb1 from 128.00 MiB to 100.00 MiB
+ calibrate /dev/sdb1
+ check file system on /dev/sdb1 for errors and (if possible) fix them
+ e2fsck -f -y -v -C 0 /dev/sdb1
+ resize2fs -p /dev/sdb1 102400K
+ shrink partition from 128.00 MiB to 100.00 MiB
This earlier commit [1] in the series dropped the message while moving
code from resize_filesystem() to shrink_filesystem(). Re-add the
message back.
[1] a0158abbeb
Refactor resizing file system apply methods (#775932)
Bug 775932 - Refactor mostly applying of operations
Explain when and why shrinking file systems is disallowed.
Unnecessary history. Check added in 2004-12-15:
d100935b55
:Set_Valid_Operations()
Comment later added in 2006-07-30:
677a21f50a
improved errorhandling a bit. At the initialscan we store errors/warnings
It made the code look a little messy, is easily resolved in the build
system and made the dependencies more complicated than needed. Each
GParted header was tracked via multiple different names (different
numbers of "../include/" prefixes). For example just looking at how
DialogFeatures.o depends on Utils.h:
$ cd src
$ make DialogFeatures.o
$ egrep ' [^ ]*Utils.h' .deps/DialogFeatures.Po
../include/DialogFeatures.h ../include/../include/Utils.h \
../include/../include/../include/../include/../include/../include/Utils.h \
../include/../include/../include/Utils.h \
After removing "../include/" from the GParted header #includes, just
need to add "-I../include" to the compile command via the AM_CPPFLAGS in
src/Makefile.am. Now the dependencies on GParted header files are
tracked under a single name (with a single "../include/" prefix). Now
DialogFeatures.o only depends on a single name to Utils.h:
$ make DialogFeatures.o
$ egrep ' [^ ]*Utils.h' .deps/DialogFeatures.Po
../include/DialogFeatures.h ../include/Utils.h ../include/i18n.h \
Simplify conditions checking whether activate/deactivate of an LVM2 PV
is possible. Excluding extended partition type was unnecessary as it
only matters that the file system type is LVM2 PV or not.
Also remove activate/deactivate from the comment above as that check
only determines if the busy state of file systems and swap space can be
toggled.
Linux-swap is recreated as part of copy, resize and move operations and
the code was special cased to implement that by calling the linux-swap
specific resize method. However the displayed text always said "growing
file system" and then proceeded to recreate linux swap. Example
operation:
Copy /dev/sdb1 to /dev/sdb2
...
+ copy file system from /dev/sdb1 to /dev/sdb2
Partition copy action skipped because linux-swap file system does not contain data
+ grow file system to fill the partition
+ create new linux-swap file system
+ mkswap -L"" -U "77d939ef-54d6-427a-a2bf-a053da7eed4c" /dev/sdb2
Setting up swapspace version 1, size = 262140 KiB
LABEL=, UUID=77d939ef-54d6-427a-a2bf-a053da7eed4c
Fix by writing recreate_linux_swap_filesystem() method with better
messaging and use everywhere maximise_filesystem() was previously used
to recreate linux-swap. Also as this is a create step, erase the
partition first to prevent the possibility of any other file system
signatures being found afterwards. Now the operation steps are more
reflective of what is actually being performed.
Copy /dev/sdb1 to /dev/sdb2
...
+ copy file system from /dev/sdb1 to /dev/sdb2
Partition copy action skipped because linux-swap file system does not contain data
+ clear old file system signatures in /dev/sdb2
+ create new linux-swap file system
+ mkswap -L"" -U "77d939ef-54d6-427a-a2bf-a053da7eed4c" /dev/sdb2
Setting up swapspace version 1, size = 262140 KiB
LABEL=, UUID=77d939ef-54d6-427a-a2bf-a053da7eed4c
Bug 775932 - Refactor mostly applying of operations
Resizing a file system only checked the .grow and .shrink support
capabilities of the file system, even when perform online resizing.
This wasn't a issue because .online_grow and .online_shrink were always
set from the offline .grow and .shrink capabilities respectively, but
only when online resizing was possible.
However the Device Mapper encryption mapping used for LUKS can only be
resized when online, and not when offline. Therefore the correct
.online_grow and .online_shrink capabilities needs to be checked to
prevent a LUKS resize step failing as not implemented.
Bug 775932 - Refactor mostly applying of operations
resize_filesystem() was meeting two different needs:
1) when called with fill_partition = false it generated operation
details;
2) when called from maximize_filesystem() with fill_partition = true it
skipped generating any operation details;
then ran the switch statement to select the resize implementation. So
extract the common switch statement into new method
resize_filesystem_implement().
Then observe that the only time resize_filesystem() was called to grow
the file system was when re-creating linux-swap. Therefore change that
call to use maximize_filesystem() and rename to shrink_filesystem() and
modify the operation detail messages to match.
Bug 775932 - Refactor mostly applying of operations
Attempting to copy or move linux-swap partition was possible when the
mkswap command was unavailable. However as linux-swap is re-created as
part of these operations the mkswap command is a mandatory requirement.
Example copy operation results:
Copy /dev/sdb1 to /dev/sdb2
+ calibrate /dev/sdb1
+ check file system on /dev/sdb1 for errors and (if possible) fix them
+ create empty partition
+ set partition type on /dev/sdb2
+ copy file system from /dev/sdb1 to /dev/sdb2 [SUCCESS]
Partition copy action skipped because linux-swap file system does not contain data
+ grow file system to fill the partition [WARNING]
growing is not available for this file system
Because mkswap was not available the grow action didn't re-create
the linux-swap so the newly copied partition is left without any content
and therefore reported as an unknown partition.
Fix by making copying and moving linux-swap depend on mkswap being
available.
Bug 775932 - Refactor mostly applying of operations
Make the methods called below apply_operation_to_disk() follow a
standard naming convention:
* Contains "_partition"
Uses libparted to query or change the partition in the disk label
(partition table).
E.g.:
calibrate_partition()
create_partition()
delete_partition()
name_partition()
resize_move_partition()
set_partition_type()
* Contains "_filesystem"
Manipulates the file system within the partition, mostly using the
FileSystem and derived class methods.
E.g.:
create_filesystem()
remove_filesystem()
label_filesystem()
copy_filesystem()
erase_filesystem_signatures()
check_repair_filesystem()
resize_filesystem()
maximize_filesystem()
* Other
Compound method calling multiple partition and file system related
apply methods.
E.g.:
create()
format()
copy()
resize_move()
resize()
move()
Rename:
Delete() -> delete_partition()
change_uuid() -> change_filesystem_uuid()
Bug 775932 - Refactor mostly applying of operations
The initial check in each of GParted_Core::resize() and move() check for
impossible conditions. (See resize_move() where both functions are
called for confirmation). The old messages could have suggested the
user somehow composed the operation incorrectly if they had ever been
seen.
Make it clear these failures are programming bugs, thus expecting the
user to raise a bug report should they ever be seen. While for now the
checks are obviously impossible they document preconditions for the
functions. More precondition checks are expected to be added later.
Bug 775932 - Refactor mostly applying of operations
Simplify the move() function. Change it into an if-operation-fails-
return-false style and re-write the final overly complicated conditional
check repair and maximise file system.
The final condition said if the file system was linux-swap or the new
partition was larger, perform a check repair and maximize file system.
However this is a move only step with a check at the top of the move()
function ensuring the Partition objects are the same size. So that
simplifies to only checking for linux-swap. As the context is a move
and linux-swap is recreated, performing a check repair first is
unnecessary, so remove that too.
Bug 775932 - Refactor mostly applying of operations
Make the logic at the resize_move_partition() call sites a little
simpler by not having to avoid calling it for whole disk device
partitions. Make it a successful non-operation in that case.
Bug 775932 - Refactor mostly applying of operations
Make the logic at the check_repair_filesystem() call sites a little
easier by not having to avoid calling it for online file systems. The
function handles that itself as a silent non-operation.
Bug 775932 - Refactor mostly applying of operations
Make the logic at the set_partition_type() call sites a little simpler
by not having to avoid calling it for whole disk device Partition
objects. Make set_partition_type() handle those itself as a silent
non-operation.
This is similar to how calibrate_partition() could be called on an
UNALLOCATED Partition object, and update_bootsector() is called on
non-NTFS file system Partition objects. Both are successful and silent
non-operations.
Bug 775932 - Refactor mostly applying of operations
Until now an encryption mapping has been modelled as a Partition object
similar to a partition like this:
.encrypted.device_path = "/dev/sdb1"
.encrypted.path = "/dev/mapper/sdb1_crypt"
.encrypted.whole_device = false
.encrypted.sector_start = // start of the mapping in the partition
.encrypted.sector_end = // end of the mapping in the partition
However accessing device_path in the start to end sector range is not
equivalent to accessing the partition path as it doesn't provide access
to the encrypted data. Therefore existing functions which read and
write partition data (GParted file system copying and signature erasure)
via libparted using the device_path won't work and will in fact destroy
the encrypted data. This could be coded around with an extra case in
the device opening code, however it is not necessary.
An encrypted block special device /dev/mapper/CRYPTNAME looks just like
a whole disk device because it doesn't contain a partition and the file
system it contains starts at sector 0 and goes to the end. Therefore
model an encryption mapping in the same way a whole disk device is
modelled as a Partition object like this:
.encrypted.device_path = "/dev/mapper/sdb1_crypt"
.encrypted.path = "/dev/mapper/sdb1_crypt"
.encrypted.whole_device = true
.encrypted.sector_start = 0
.encrypted.sector_end = // size of the encryption mapping - 1
Now GParted file system copy and erasure will just work without any
change. Just need to additionally store the LUKS header size, which was
previous stored in the sector_start, for use in the
get_sectors_{used,unused,unallocated}() calculations.
Bug 775932 - Refactor mostly applying of operations
Split out the switch statement selecting the copy implementation and
associated copy file system operation detail message into a separate
copy_filesystem() method, matching how a number of other operations are
coded. This is why the previous copy_filesystem() methods needed
renaming.
Re-write the remaining copy() into if-operation-fails-return-false style
to simplify it. Re-write final complicated conditional check repair and
maximise file system into separate positive if conditions for swap and
larger partition to make it understandable.
The min_size parameter to copy() was queried from the partition_src
parameter also passed to copy(). Drop the parameter and query inside
copy() instead.
Bug 775932 - Refactor mostly applying of operations
Rename GParted_Core methods:
copy_filesystem(4 params) -> copy_filesystem_internal()
copy_filesystem(5 params) -> copy_filesystem_internal()
copy_filesystem(10 params) -> copy_blocks()
See the following commit for the desire to do this.
Bug 775932 - Refactor mostly applying of operations
Files were named Block_Copy and the class was named block_copy. Change
to the primary naming convention of CamelCase class name and matching
file names.
Also make CopyBlocks::copy_block() a private method as it is only used
internally within the class.
Bug 775932 - Refactor mostly applying of operations
These two methods had a lot of repeated and common code. Both determine
if the partition has any pending operations, notify the user that
changing the busy status can not be performed, and report any errors
when changing the status.
Extract the common code into sub-functions check_toggle_busy_allowed()
and show_toggle_failure_dialog() to handle showing the message dialogs.
Also refactor toggle_busy_state() to make it clear that it handles 5
cases of swapon, swapoff, activate VG, deactivate VG and unmount file
system.
Also remove out of date comment near the top of toggle_busy_state()
stating there can only be pending operations for inactive partitions is
out of date. Some file systems can be resized while online and
partition naming is allowed whatever the busy status of the file system.
Bug 775932 - Refactor mostly applying of operations
The primary reason to refactor unmount_partition() is to pass the
Partition object to be unmounted, rather than use member variable
selected_partition_ptr so that it doesn't have to handle the differences
between encrypted and non-encrypted Partition objects. The calling
function can deal with that instead. Then there were lots of small
reasons to change almost every other line too:
* Return success or failure rather than updating a passed pointer with
the result. Leftover from when the function used to be a separate
thread:
commit 52a2a9b00a
Reduce threading (#685740)
* Pass updated error string by reference rather than by pointer. Likely
another leftover.
* Stop borrowing the updated error string as a local variable for the
error output from the umount command. Use new umount_error local
variable instead. Was bad practice making the code harder to
understand.
* Rename failed_mountpoints to skipped_mountpoints to better reflect
that it contains the mount points not attempted to be unmounted
because two or more file systems are mounted at that point.
* Rename errors to umount_errors to better reflect it contains the
errors from each failed umount command.
* Document the reason for mount points being skipped.
* Update the skipped mount points message to state definitely why they
could not be unmounted rather than stating most likely.
* Simplify logic processing the error cases and return value.
* Made static because it no longer accesses any class members.
* Remove out dated "//threads.." comment from the header. Another
leftover from when the function use to be a separate thread.
Bug 775932 - Refactor mostly applying of operations
Reorder the parameters into the same order in which they occur in the
row, i.e. Name first, then Mount Point and finally Label. Rename local
variables in load_partitions(1 param) and parameters of
load_partitions(5 params) prefixing with "show_" to make it clearer the
variables track if that column will be displayed or not.
create_row() populates the values for each row to be displayed in the UI
from the relevant Partition object. However load_partitions(5 params)
independently decided if the Name, Mount Point and Label columns were
empty and should be displayed.
Getting the mount point value is more complex for encrypted file systems
because it has to call get_mountpoints() on the inner encrypted
Partition object. load_partitions(5 params) didn't account for this.
Fix by making create_row() both copy the values into each row and at the
same time check if they are empty to decide if they should be displayed
or not.
Bug 775475 - Mount Point column displayed for encrypted file systems
even when empty
Running Device > Attempt Data Rescue... hangs the GParted UI for as long
as gpart takes to scan the whole disk device looking for file system
signatures.
Originally when gpart support was added by commit [1] a separate thread
was created to run gpart. Then most threading was removed by commit [2]
which left gpart running in the main thread blocking the UI.
[1] ef37bdb7de
Added support to lost data recovery using gpart
[2] 52a2a9b00a
Reduce threading (#685740)
guess_partition_table() hand codes using Glib to run the gpart command
asynchronously reading standard output, but it just doesn't run the Gtk
main loop to process events, hence the UI hangs. Instead just use
Utils::execute_command() which handles everything already. It runs the
commands asynchronously, reading output and if being run in the main
thread also calls the Gtk main loop to keep the UI responsive.
Bug 772123 - GParted is unresponsive while gpart is running
If the GParted main window is closed before the initial device load
completed gpartedbin never exits. The main window closes but the
process sits there idle forever. Subsequently running GParted reports
this error:
# gparted
The process gpartedbin is already running.
Only one gpartedbin process is permitted.
If the user is running GParted from a desktop menu they will never see
this error so they will never know why GParted won't start any more.
More technically, it is if the main window is closed before the
Win_GParted::on_show() callback completes.
I assume the Gtk main loop doesn't setup the normal quit handling until
the on_show() callback finishes drawing the main window for the first
time. Following this hint [1], move the initial device load from the
on_show() callback to immediately after it completes by using a run once
idle callback setup in on_show().
This looks exactly the same to the user except now gpartedbin exits when
the main window is closed during the initial device load. Note that
GParted finished the device load before exiting. This is exactly the
same as happens when exiting during subsequent device refreshes.
[1] How to know when a Gtk Window is fully shown?
http://stackoverflow.com/questions/14663212/how-to-know-when-a-gtk-window-is-fully-shown
"If you want to know when your main window appears the first time,
it is far easier (and saner) add a g_idle_add after your show_all
call."
Bug 771816 - GParted never exits if the main window is closed before the
initial device load completes
Again this is to handle a long list of mount points for a single
partition. To prevent the file system status value of "Mounted on [list
of 20 mount points]" causing the dialog to become wider than the screen,
line wrap the text. This instead makes the dialog taller, which already
automatically scrolls vertically as needed.
Bug 771693 - Mount Point column is wider than the screen on openSUSE
using btrfs root with lots of mounted subvolumes
openSUSE 42.1 with default btrfs root installation is heavily using
subvolumes. (Think of btrfs as a storage pool and subvolumes as
individual file systems within the pool for a rough approximation).
Thus the root partition is mounted on many mount points:
# df -k
Filesystem 1K-blocks Used Available Use% Mounted on
...
/dev/sda2 19445760 5820080 13157104 31% /
/dev/sda2 19445760 5820080 13157104 31% /var/lib/libvirt/images
/dev/sda2 19445760 5820080 13157104 31% /var/lib/mysql
/dev/sda2 19445760 5820080 13157104 31% /.snapshots
/dev/sda2 19445760 5820080 13157104 31% /home
/dev/sda2 19445760 5820080 13157104 31% /var/opt
/dev/sda2 19445760 5820080 13157104 31% /usr/local
/dev/sda2 19445760 5820080 13157104 31% /var/tmp
/dev/sda2 19445760 5820080 13157104 31% /var/lib/named
/dev/sda2 19445760 5820080 13157104 31% /var/lib/mariadb
/dev/sda2 19445760 5820080 13157104 31% /var/spool
/dev/sda2 19445760 5820080 13157104 31% /var/lib/pgsql
/dev/sda2 19445760 5820080 13157104 31% /var/lib/mailman
/dev/sda2 19445760 5820080 13157104 31% /srv
/dev/sda2 19445760 5820080 13157104 31% /opt
/dev/sda2 19445760 5820080 13157104 31% /var/crash
/dev/sda2 19445760 5820080 13157104 31% /tmp
/dev/sda2 19445760 5820080 13157104 31% /boot/grub2/i386-pc
/dev/sda2 19445760 5820080 13157104 31% /var/log
/dev/sda2 19445760 5820080 13157104 31% /boot/grub2/x86_64-efi
As the Mount Point column contains all 20 mount points it makes the
column wider than the screen, requiring lots of horizontal scrolling to
see the following columns. (Truncated to just 7 mounts in this
example here).
Partition | File System | Mount Point
/dev/sda1 * | # swap |
/dev/sda2 * | # btrfs | /, /.snapshots, /boot/grub2/i386-pc, /boot/grub2/x86_64-efi, /home, /opt, /srv
Fix by making the Mount Point column resizable and display truncated
text with ellipsis. The column now takes the initial and minimum width
from the width of the "Mount Point" column header text.
Partition | File System | Mount Point | Size
/dev/sda1 * | # swap | | 1.45 GiB
/dev/sda2 * | # btrfs | /, /.snapsho... | 18.54 GiB
Bug 771693 - Mount Point column is wider than the screen on openSUSE
using btrfs root with lots of mounted subvolumes
This commit stopped setting the text colours in the Partition, File
System and Mount Point columns to avoid hard coding text colours making
them impossible to read when using GNOME's High Contrast Inverse theme:
ff2a6c00dd
Changes post gparted-0.3.6 - code recreation from Source Forge
* src/TreeView_Detail.cc: Removed text_color hard coding
- Removed hard coding of Partition and Filesystem text_color
which was based on if partition was TYPE_UNALLOCATED.
- Removed hard coding of Mount text_color which was based
on if partition was busy. Lock symbol provides this indicator.
- Closes GParted bug #413810 - Don't hardcode text colour in
partition list
Now remove the remaining vestiges left behind. Remove the unused color
text and mount_text_color columns from the tree model. Also remove
setting of the column attributes which set the colour of the text in the
tree view from those unused columns in the tree model.
Unnecessary history. Added by:
b179990dc9
show greyed-out mountpoint of unmounted partitions in the treeview
as an improved way to identify partitions
Bug #333027 - Displaying unmounted partitions' default mount points
in grey
and by commit only in CVS history:
Bart Hakvoort <...> 2004-08-22 15:06:45
Made text in Partition column darkgrey for unallocated. this offers
more visual difference between partitions and unallocated space
Trying to create a new partition table on a device with active
partitions reports the number of active partitions in the error dialog.
However when there is a busy logical partition the number of reported
busy partitions will be one less than the number of partitions in the
main UI showing the busy symbol.
GParted considers extended partitions as busy when any of the logical
partitions it contains as busy. Display in the main UI reflects this.
Fix Win_GParted::active_partitions_on_device_count() to not exclude
extended partitions from the count.
Found that in some cases usage of active encrypted swap was not working,
but only for the first encrypted swap partition. This only failed on
the first Device Mapper device, dm-0:
# ls -l /dev/mapper/ /dev/dm-*
brw-rw---- 1 root disk 254, 0 Oct 4 20:58 /dev/dm-0
brw-rw---- 1 root disk 254, 1 Oct 4 20:58 /dev/dm-1
/dev/mapper/:
total 0
crw------- 1 root root 10,236 Oct 4 19:48 control
lrwxrwxrwx 1 root root 7 Oct 4 20:58 sdb1_crypt -> ../dm-0
lrwxrwxrwx 1 root root 7 Oct 4 20:58 sdb2_crypt -> ../dm-1
# cat /proc/swaps
Filename Type Size Used Priority
/dev/sda1 partition 1524732 92356 -1
/dev/dm-0 partition 1046524 0 -2
/dev/dm-1 partition 1046524 0 -3
Was failing because the minor number of dm-0 was 0, causing BlockSpecial
operator==() to fall back to name comparison rather than major, minor
number, and GParted name /dev/mapper/sdb1_crypt doesn't match /dev/dm-0.
Found on openSUSE and Ubuntu which don't use LVM by default and don't
already have dm-0 used as an LVM Logical Volume which GParted doesn't
support.
The LINUX ALLOCATED DEVICES document [1] says block special device 0, 0
(major, minor) is not used "reserved as null device number". (Not to
be confused with 1, 3 /dev/null the Null device). All other
non-negative pairs are valid block special device numbers. Therefore
update BlockSpecial operator==() accordingly; compare by major, minor
number when either is greater than 0 falling back to string compare
otherwise. This still fits in with the BlockSpecial() constructor using
major, minor numbers 0, 0 to represent plain files.
[1] LINUX ALLOCATED DEVICES
https://www.kernel.org/doc/Documentation/devices.txt
Bug 771670 - Usage of active encrypted swap is not shown
GParted does not show the usage of active encrypted swap partitions,
instead showing partition warning "Unable to read the contents of this
file system! ...". OS setup:
# ls -l /dev/mapper/sdb4_crypt /dev/dm-3
brw-rw----. 1 root disk 253, 3 Sep 14 07:26 /dev/dm-3
lrwxrwxrwx. 1 root root 7 Sep 14 07:26 /dev/mapper/sdb4_crypt -> ../dm-3
# mkswap -L encrypted_swap /dev/mapper/sdb4_crypt
# swapon /dev/mapper/sdb4_crypt
# cat /proc/swaps
Filename Type Size Used Priority
/dev/sda2 partition 2097148 237632 -1
/dev/dm-3 partition 1046524 0 -2
This is because the code was performing a string compare between the
canonical /dev/mapper/sdb4_crypt name GParted is using and the /dev/dm-3
name reported by the kernel via /proc/swaps. Fix by creating
BlockSpecial objects from the names and compare those so that comparison
is done correctly using major, minor numbers.
Bug 771670 - Usage of active encrypted swap is not shown
The comment became completely unnecessary with the transfer of
mount_info and fstab_info into separate Mount_Info module by commit:
63ec73dfda
Split mount_info and fstab_info maps into separate Mount_Info module
It was never necessary to clear one of the mappings at the end of the
device refresh because it was reloaded at the start of the next device
refresh anyway and it is only a small amount of memory.
Have an unmounted file system within an open encrypted mapping and an
entry in /etc/fstab for the file system like this:
# lsblk
NAME MAJ:MIN RM SIZE RO TYPE MOUNTPOINT
...
sdb 8:16 0 8G 0 disk
+-sdb1 8:17 0 1G 0 part
+-sdb1_crypt 253:0 0 1022M 0 crypt
# blkid | grep sdb1
/dev/sdb1: TYPE="crypto_LUKS" ...
/dev/mapper/sdb1_crypt: TYPE="ext4" ...
# ls -l /dev/mapper/sdb1_crypt /dev/dm-0
brw-rw----. 1 root disk 253, 0 Sep 12 19:09 /dev/dm-0
lrwxrwxrwx. 1 root root 7 Sep 12 19:09 /dev/mapper/sdb1_crypt -> ../dm-0
# grep sdb1 /etc/fstab
/dev/mapper/sdb1_crypt /mnt/1 ext4 defaults 0 0
The mount point will be shown twice for the partition:
/mnt/1, /mnt/1
This is because add_node_and_mountpoint() adds two entries for both the
symbolic and real block special names:
map["/dev/mapper/sdb1_crypt"] = ["/mnt/1"]
map["/dev/dm-0"] = ["/mnt/1"]
This was needed for the old code which used string compare to match
block devices so that the mount point could be looked up by either name.
However since bug 767842 introduced major, minor number comparison it
became unnecessary. As both names refer to the same device the mount
point gets added twice to the same entry. Hence display of the double
mount.
map[BlockSpecial{"/dev/mapper/sdb1_crypt", 253, 0}] =
["/mnt/1", "/mnt/1"]
It is always going to be the case that the symbolic link and real block
special names have the same major, minor numbers. That was the
requirement of the BlockSpecial class and the reason for using stat() to
lookup the numbers. Therefore adding entries for both names will always
add duplicate entries. Fix by stop using realpath() to lookup the real
name and adding the duplicate entry.
Introduced by:
a800ca8b68
Add BlockSpecial into mount_info and fstab_info (#767842)
Bug 771323 - GParted is showing duplicate mount points for unmounted
encrypted file systems
The GParted_Core::mount_info and GParted_Core::fstab_info maps and the
methods that manipulate them are self-contained. Therefore move them to
a separate Mount_Info module and reduce the size of the monster
GParted_Core slightly.
The FS_Info module has a pseudo multi-object interface and used the
constructor to load the cache. However all the data in the class is
static. An FS_Info object doesn't contain any member variables, yet was
needed just to call the member functions.
Make all the member functions static removing the need to use any
FS_Info objects and provide an explicit load_cache() method.
Following earlier commit "Pre-populate BlockSpecial cache while reading
/proc/partitions (#767842)" load_proc_partitions_info_cache() has
extracted just the name field from each line of /proc/partitions.
Therefore simplify the regular expressions matching each type of whole
disk device to just matching in the name field rather than matching in
the whole line.
The Proc_Partitions_Info has a pseudo multi-object interface and uses
the constructor to load the cache. However all the data in the class is
static. A Proc_Partitions_Info object doesn't contain any member
variables, yet was needed just to call the member functions.
Make all the member functions static removing the need to use any
Proc_Partitions_Info objects and provide and explicit load_cache()
method.
Vol_id has been retired and removed from all supported distributions.
See earlier commit "Remove use of retired vol_id from FS_Info module
(#767842)" for more details. Therefore remove it's use from GParted
entirely.
GParted is already reading /proc/partitions to get whole disk device
names. The file also contains the major, minor device number of every
partition. Use this information to pre-populate the cache in the
BlockSpecial class.
# cat /proc/partitions
major minor #blocks name
8 0 20971520 sda
8 1 512000 sda1
8 2 20458496 sda2
...
9 3 1047552 md3
259 2 262144 md3p1
259 3 262144 md3p2
...
253 0 18317312 dm-0
253 1 2097152 dm-1
253 2 8383872 dm-2
253 3 1048576 dm-3
Note that for Device-Mapper names (dm-*) the kernel is not using the
canonical user space names (mapper/*). There is no harm in
pre-populating the cache with these names and will help if tools report
them too. It is just that for DMRaid, LVM and LUKS, GParted uses the
canonical /dev/mapper/* names so will still have to call stat() once for
each such name.
For plain disks (sd*) and Linux Software RAID arrays (md*) the kernel
name is the common user space name too, therefore matches what GParted
uses and pre-populating does avoid calling stat() at all for these
names.
Bug 767842 - File system usage missing when tools report alternate block
device names
Creation of every BlockSpecial object used to result in a stat() OS
call. On one of my test VMs debugging with 4 disks and a few partitions
on each, GParted refresh generated 541 calls to stat() in the
BlockSpecial(name) constructor. However there were only 45 unique
names. So on average each name was stat()ed approximately 12 times.
Cache the major, minor number associated with each name after starting
with a cleared cache for each GParted refresh. This reduces these
direct calls to stat() to just the 45 unique names.
Bug 767842 - File system usage missing when tools report alternate block
device names
The FS_Info cache is loaded from "blkid" output and compares block
special names. Therefore switch to using BlockSpecial objects so that
comparisons are performed by the major, minor device number instead.
Bug 767842 - File system usage missing when tools report alternate block
device names
FS_Info module caches the output from blkid as a single string and uses
regular expressions to find the line matching the requested block
special file name. This is not compatible with using BlockSpecial
objects to represent block special files, and perform matching by major,
minor device number. Therefore parse the blkid output into a vector of
structures containing the needed fields, ready for switching to
BlockSpecial objects in the following patch.
Interface to the module remains unchanged.
Bug 767842 - File system usage missing when tools report alternate block
device names
Vol_id was removed from udev 142, released 2009-05-13, and udev switched
to using blkid instead [1]. All currently supported distributions use
later versions of udev (or systemd after the udev merge), except for
RedHat / CentOS 5 with udev 095. However RedHat / CentOS 5 does provide
blkid and vol_id is found in udev specific /lib/udev directory not on
the PATH. Therefore effectively vol_id is not available on any
supported distribution and blkid is always available. Therefore remove
use of vol_id from the FS_Info module. Less code to refactor and test
in following changes.
[1] delete vol_id and require util-linux-ng's blkid
http://git.kernel.org/cgit/linux/hotplug/udev.git/commit/?id=f07996885dab45102492d7f16e7e2997e264c725
Bug 767842 - File system usage missing when tools report alternate block
device names
The SWRaid_Info cache is loaded from "mdadm" command output and
/proc/mdstat file. It contains the member name which is used to access
the cache, therefore switch to using BlockSpecial objects so that
comparison is performed using the major, minor device number.
Bug 767842 - File system usage missing when tools report alternate block
device names
The LUKS_Info module cache is loaded from "dmsetup" command and compares
block special files, therefore switch to using BlockSpecial objects so
that comparisons are performed by major, minor device number.
Bug 767842 - File system usage missing when tools report alternate block
device names
Small optimisation which avoids constructing an extra BlockSpecial
object when determining if a btrfs member is mounted. Rather than
extracting the name from the BlockSpecial object in
btrfs::get_mount_device() and re-constructing another BlockSpecial
object from that name in GParted_Core::is_dev_mounted(), pass the
BlockSpecial object directly.
Bug 767842 - File system usage missing when tools report alternate block
device names
There are no known errors which affect the remaining caches in GParted.
However those caches which compare block special devices will be changed
to use BlockSpecial objects so comparison is by major, minor device
number rather than by name.
Change btrfs member cache loaded from "btrfs filesystem show" output to
use BlockSpecial objects.
Bug 767842 - File system usage missing when tools report alternate block
device names
On some distributions having btrfs on top of LUKS encrypted partitions,
adding a second device and removing the first device used to mount the
file system causes GParted to no longer be able to report the file
system as busy or the mount points themselves.
For example, on CentOS 7, create a single btrfs file system and mount
it. The provided /dev/mapper/sdb1_crypt name is reported, via
/proc/mounts, as the mounting device:
# cryptsetup luksFormat --force-password /dev/sdb1
# cryptsetup luksOpen /dev/sdb1 sdb1_crypt
# mkfs.btrfs -L encrypted-btrfs /dev/mapper/sdb1_crypt
# mount /dev/mapper/sdb1_crypt /mnt/1
# ls -l /dev/mapper
total 0
lrwxrwxrwx. 1 root root 7 Jul 2 14:15 centos-root -> ../dm-1
lrwxrwxrwx. 1 root root 7 Jul 2 14:15 centos-swap -> ../dm-0
crw-------. 1 root root 10, 236 Jul 2 14:15 control
lrwxrwxrwx. 1 root root 7 Jul 2 15:14 sdb1_crypt -> ../dm-2
# fgrep btrfs /proc/mounts
/dev/mapper/sdb1_crypt /mnt/1 btrfs rw,seclabel,relatime,space_cache 0 0
Add a second device to the btrfs file system:
# cryptsetup luksFormat --force-password /dev/sdb2
# cryptsetup luksOpen /dev/sdb2 sdb2_crypt
# btrfs device add /dev/mapper/sdb2_crypt /mnt/1
# ls -l /dev/mapper
...
lrwxrwxrwx. 1 root root 7 Jul 2 15:12 sdb2_crypt -> ../dm-3
# btrfs filesystem show /dev/mapper/sdb1_crypt
Label: 'encrypted-btrfs' uuid: 45d7b1ef-820c-4ef8-8abd-c70d928afb49
Total devices 2 FS bytes used 32.00KiB
devid 1 size 1022.00MiB used 12.00MiB path /dev/mapper/sdb1_crypt
devid 2 size 1022.00MiB used 0.00B path /dev/mapper/sdb2_crypt
Remove the first mounting device from the btrfs file system. Now the
non-canonical name /dev/dm-3 is reported, via /proc/mounts, as the
mounting device:
# btrfs device delete /dev/mapper/sdb1_crypt /mnt/1
# btrfs filesystem show /dev/mapper/sdb2_crypt
Label: 'encrypted-btrfs' uuid: 45d7b1ef-820c-4ef8-8abd-c70d928afb49
Total devices 1 FS bytes used 96.00KiB
devid 2 size 1022.00MiB used 144.00MiB path /dev/mapper/sdb2_crypt
# fgrep btrfs /proc/mounts
/dev/dm-3 /mnt/1 btrfs rw,seclabel,relatime,space_cache 0 0
# ls -l /dev/dm-3
brw-rw----. 1 root disk 253, 3 Jul 2 15:12 /dev/dm-3
GParted loads the mount_info mapping from /proc/mounts and with it the
/dev/dm-3 name. When GParted is determining if the encrypted btrfs file
system is mounted or getting the mount points it is using the
/dev/mapper/sdb2_crypt name. Therefore no information is found and the
file system is incorrectly reported as unmounted.
Fix by changing mount_info and fstab_info to use BlockSpecial objects
instead of strings so that matching is performed by major, minor device
numbers rather than by string compare. Note that as BlockSpecial
objects are used as the key of std::map [1] mappings operator<() [2]
needs to be provided to order the key values.
[1] std::map
http://www.cplusplus.com/reference/map/map/
[2] std::map::key_comp
http://www.cplusplus.com/reference/map/map/key_comp/
Bug 767842 - File system usage missing when tools report alternate block
device names
In some cases creating an LVM2 Physical Volume on top of a DMRaid array
reports no usage information and this partition warning:
Unable to read the contents of this file system!
Because of this some operations may be unavailable.
The cause might be a missing software package.
The following list of software packages is required for lvm2
pv file system support: lvm2.
For example on Ubuntu 14.04 LTS (with GParted built with
--enable-libparted-dmraid) create an LVM2 PV in a DMRaid array
partition. GParted uses this command:
# lvm pvcreate -M 2 /dev/mapper/isw_bacdehijbd_MyArray0p2
But LVM reports the PV having a different name:
# lvm pvs
PV VG Fmt Attr PSize PFree
/dev/disk/by-id/dm-name-isw_bacdehijbd_MyArray0p2 lvm2 a-- 1.00g 1.00g
This alternate name is loaded into the LVM2_PV_Info module cache. Hence
when GParted queries partition /dev/mapper/isw_bacdehijbd_MyArray0p2 it
has no PV information against that name and reports unknown usage.
However they are actually the same block special device; major 252,
minor 2:
# ls -l /dev/mapper/isw_bacdehijbd_MyArray0p2
brw-rw---- 1 root disk 252, 2 Jul 2 11:09 /dev/mapper/isw_bacdehijbd_MyArray0p2
# ls -l /dev/disk/by-id/dm-name-isw_bacdehijbd_MyArray0p2
lrwxrwxrwx 1 root root 10 Jul 2 11:09 /dev/disk/by-id/dm-name-isw_bacdehijbd_MyArray0p2 -> ../../dm-2
# ls -l /dev/dm-2
brw-rw---- 1 root disk 252, 2 Jul 2 11:09 /dev/dm-2
To determine if two names refer to the same block special device their
major, minor numbers need to be compared, instead of string comparing
their names.
Implement class BlockSpecial which encapsulates the name and major,
minor numbers for a block special device. Also performs comparison as
needed. See bug 767842 comments 4 and 5 for further investigation and
decision for choosing to implement a class.
Replace name strings in the LVM2_PV_Info module with BlockSpecial
objects performing correct block special device comparison.
Bug 767842 - File system usage missing when tools report alternate block
device names
Now Device and Partition objects only have a single path,
get_alternate_paths() is never called. Remove the method and population
of the private alternate_paths_cache member that went with it.
Bug 767842 - File system usage missing when tools report alternate block
device names
To reflect that there is now only a single path in the Partition object
now. Also get rid of the now unneeded optional clear_paths parameter
which was only relevant when there was a vector of paths.
Bug 767842 - File system usage missing when tools report alternate block
device names
Now that Partition objects only have a single path, rather than a list
of paths, stop performing unnecessary actions in calibrate_partitions()
which added alternate paths reported from libparted. Just left with
setting the partition path name correctly, when the path name doesn't
exist. Happens when the path is set to "Copy of /dev/SRC" when the
partition was newly created by a copy-paste into unallocated space
earlier in the sequence of operations now being applied.
Bug 767842 - File system usage missing when tools report alternate block
device names
Change from a vector of paths to a single path member in the Partition
object. Remove add_paths() and get_paths() methods. Keep add_path()
and get_path().
Bug 767842 - File system usage missing when tools report alternate block
device names
To reflect that there is only a single path in the Device object now.
Also get rid of the now unneeded optional parameter which was only
relevant when there was a vector of paths.
Bug 767842 - File system usage missing when tools report alternate block
device names
Background
GParted stored a list of paths for Device and Partition objects. It
sorted this list [1][2] and treated the first specially as that is what
get_path() returned and was used almost everywhere; with the file system
specific tools, looked up in various *_Info caches, etc.
[1] Device::add_path(), ::add_paths()
[2] Partition::add_path(), ::add_paths()
Mount point display [3] was the only bit of GParted which really worked
with the path list. Busy file system detection [4] just used the path
provided by libparted, or for LUKS /dev/mapper/* names. It checked that
single path against the mounted file systems found from /proc/mounts,
expanded with additional block device names when symlinks were
encountered.
[3] GParted_Core::set_mountpoints() -> set_mountpoints_helper()
[4] GParted_Core::set_device_partitions() -> is_busy()
GParted_Core::set_device_one_partition() -> is_busy()
GParted_Core::set_luks_partition() -> is_busy()
Having the first path, by sort order, treated specially by being used
everywhere and virtually ignoring the others was wrong, complicated to
remember and difficult code with. As all the additional paths were
virtually unused and made no difference, remove them. The "improved
detection of mountpoins, free space, etc.." benefit from commit [5]
doesn't seem to exist. Therefore simplify to a single path for Device
and Partition objects.
[5] commit 6d8b169e73
changed the way devices and partitions store their device paths.
Instead of holding a 'realpath' and a symbolic path we store paths
in a list. This allows for improved detection of mountpoins, free
space, etc..
This patch
Simplify the Device object from a vector of paths to a single path.
Remove add_paths() and get_paths() methods. Keep add_path() and
get_path() for now.
Bug 767842 - File system usage missing when tools report alternate block
device names
Recognise GRUB2 core.img boot code written to a partition without a file
system. Such setups are possible/likely with GPT partitioned disks as
there is a specific partition type reserved for it [1][2]:
21686148-6449-6E6F-744E-656564454649 (BIOS Boot partition)
[1] GUID Partition Table, Partition types
https://en.wikipedia.org/wiki/GUID_Partition_Table#Partition_type_GUIDs
[2] BIOS boot partition
https://en.wikipedia.org/wiki/BIOS_boot_partition
Bug 766989 - zfsonline support - need file system name support for ZFS
type codes
Composing these operations caused GParted to abort on an assert failure:
(1) Delete an existing partition,
(2) Create a new partition,
(3) Delete new partition.
This is the equivalent issue as fixed in the previous commit, except with
the delete operation rather than the check operation:
Prevent assert failure from OperationCheck::get_partition_new() (#767233)
# ./gpartedbin
======================
libparted : 2.4
======================
**
ERROR:OperationDelete.cc:41:virtual GParted::Partition& GParted::OperationDelete::get_partition_new(): assertion failed: (false)
Aborted (core dumped)
# gdb ./gpartedbin core.19232 --batch --quiet --ex backtrace -ex quit
[New Thread 19232]
[New Thread 19234]
[Thread debugging using libthread_db enabled]
Core was generated by `./gpartedbin'.
Program terminated with signal 6, Aborted.
#0 0x000000361f2325e5 in raise (sig=6) at ../nptl/sysdeps/unix/sysv/linux/raise.c:64
64 return INLINE_SYSCALL (tgkill, 3, pid, selftid, sig);
#0 0x000000361f2325e5 in raise (sig=6) at ../nptl/sysdeps/unix/sysv/linux/raise.c:64
#1 0x000000361f233dc5 in abort () at abort.c:92
#2 0x0000003620a67324 in g_assertion_message (domain=<value optimized out>, file=<value optimized out>, line=<value optimized out>, func=0x50fcc0 "virtual GParted::Partition& GParted::OperationDelete::get_partition_new()", message=0x1b55f60 "assertion failed: (false)") at gtestutils.c:1358
#3 0x0000003620a678f0 in g_assertion_message_expr (domain=0x0, file=0x50fa68 "OperationDelete.cc", line=41, func=0x50fcc0 "virtual GParted::Partition& GParted::OperationDelete::get_partition_new()", expr=<value optimized out>) at gtestutils.c:1369
#4 0x000000000049aa0d in GParted::OperationDelete::get_partition_new (this=0x1b321b0) at OperationDelete.cc:41
#5 0x00000000004c6700 in GParted::Win_GParted::activate_delete (this=0x7ffc91403670) at Win_GParted.cc:2068
...
As before the crash is happened in Win_GParted::activate_delete() as it
was going through the list of operations removing those which applied to
the never created partition. It came across the delete operation of an
existing partition and called get_partition_new(). As partition_new was
not set or used by the delete operation this asserted false and crashed
GParted.
Unlike the check operation case, the delete operation doesn't have a
partition afterwards. (As GParted represents unallocated space with
partition objects then the delete operation could be populated with a
new partition by constructing the correctly merged unallocated space
partition object, but that is what OperationDelete::apply_to_visual()
does and having a place holder doesn't seem like the right thing to do).
Instead exclude delete operations, on existing partitions, when looking
for operations applying to this not yet created partition as they are
mutually exclusive.
Bug 767233 - GParted core dump on assert failure in
OperationDelete::get_partition_new()
Composing these operations caused GParted to abort on an assert failure:
(1) Check an existing partition,
(2) Create a new partition,
(3) Delete new partition.
# ./gpartedbin
======================
libparted : 2.4
======================
**
ERROR:OperationCheck.cc:40:virtual GParted::Partition& GParted::OperationCheck::get_partition_new(): assertion failed: (false)
Aborted (core dumped)
# gdb ./gpartedbin core.8876 --batch --quiet --ex backtrace -ex quit
[New Thread 8876]
[New Thread 8879]
[Thread debugging using libthread_db enabled]
Core was generated by `./gpartedbin'.
Program terminated with signal 6, Aborted.
#0 0x000000361f2325e5 in raise (sig=6) at ../nptl/sysdeps/unix/sysv/linux/raise.c:64
64 return INLINE_SYSCALL (tgkill, 3, pid, selftid, sig);
#0 0x000000361f2325e5 in raise (sig=6) at ../nptl/sysdeps/unix/sysv/linux/raise.c:64
#1 0x000000361f233dc5 in abort () at abort.c:92
#2 0x0000003620a67324 in g_assertion_message (domain=<value optimized out>, file=<value optimized out>, line=<value optimized out>, func=0x50f400 "virtual GParted::Partition& GParted::OperationCheck::get_partition_new()", message=0x1d37a00 "assertion failed: (false)") at gtestutils.c:1358
#3 0x0000003620a678f0 in g_assertion_message_expr (domain=0x0, file=0x50f1a8 "OperationCheck.cc", line=40, func=0x50f400 "virtual GParted::Partition& GParted::OperationCheck::get_partition_new()", expr=<value optimized out>) at gtestutils.c:1369
#4 0x0000000000498e21 in GParted::OperationCheck::get_partition_new (this=0x1d1bb30) at OperationCheck.cc:40
#5 0x00000000004c66ec in GParted::Win_GParted::activate_delete (this=0x7fff031c3e30) at Win_GParted.cc:2068
...
When Win_GParted::activate_delete() was stepping through the operation
list removing operations (2 & 3 in the above recreation steps) which
related to the new partition never to be created it called
get_partition_new() on all operations in the list. This included
calling get_partition_new() on the check operation (1 in the above
recreation steps). As partition_new was not set or used by the check
operation get_partition_new() asserted false and crashed GParted.
Fix by populating the partition_new member in OperationCheck objects,
thus allowing get_partition_new() to be called on the object. As a
check operation doesn't change any partition boundaries or file system
attributes, just duplicate the new partition from the original
partition.
Bug 767233 - GParted core dump on assert failure in
OperationDelete::get_partition_new()
E2fsprogs 1.42 adds ext4 64bit feature [1] allowing volume sizes larger
than 16 TiB. However only enable large volumes from e2fsprogs 1.42.9
when a large number of 64bit bugs were fixed [2]. (Also RHEL / CentOS 7
use e2fsprogs 1.42.9 and always enable 64bit feature by default).
[1] Release notes, E2fsprogs 1.42 (November 29, 2011)
http://e2fsprogs.sourceforge.net/e2fsprogs-release.html#1.42
"This release of e2fsprogs has support for file systems > 16TB.
Online resize requires kernel support which will hopefully be in
Linux version 3.2. Offline support is not yet available for > 16TB
file systems, but will be coming".
[2] Release notes, E2fsprogs 1.42.9 (December 28, 2013)
http://e2fsprogs.sourceforge.net/e2fsprogs-release.html#1.42.9
"Fixed a large number of bugs in resize2fs, e2fsck, debugfs, and
libext2fs to correctly handle bigalloc and 64-bit file systems.
There were many corner cases that had not been noticed in previous
uses of these file systems, since they are not as common. Some of
the bugs could cause file system corruption or data loss, so users
of 64-bit or bigalloc file systems are strongly urged to upgrade to
e2fsprogs 1.42.9".
Bug 766910 - Multiple boot loaders don't work on 64bit EXT4 file systems
Calling libparted ped_geometry_new() creates a new PedGeometry object
from malloced memory, however the corresponding ped_geometry_destroy()
is never called to destroy the object and free the memory.
Perform a resize of a FAT file system when running GParted under
valgrind identifies several memory blocks leaked via ped_geometry_new()
from resize_move_filesystem_using_libparted(). One such example:
# valgrind --track-origins=yes --leak-check=full ./gpartedbin
...
==32069== 32 bytes in 1 blocks are definitely lost in loss record 5,419 of 11,542
==32069== at 0x4C29BFD: malloc (in /usr/lib64/valgrind/vgpreload_memcheck-amd64-linux.so)
==32069== by 0x8ECD8C5: ped_malloc (libparted.c:231)
==32069== by 0x8ED23C1: ped_geometry_new (geom.c:79)
==32069== by 0x4764F3: GParted::GParted_Core::resize_move_filesystem_using_libparted(GParted::Partition const&, GParted::Partition const&, GParted::OperationDetail&) (GParted_Core.cc:2666)
==32069== by 0x478007: GParted::GParted_Core::resize_filesystem(GParted::Partition const&, GParted::Partition const&, GParted::OperationDetail&, bool) (GParted_Core.cc:2990)
==32069== by 0x478440: GParted::GParted_Core::maximize_filesystem(GParted::Partition const&, GParted::OperationDetail&) (GParted_Core.cc:3037)
==32069== by 0x4769A0: GParted::GParted_Core::resize(GParted::Partition const&, GParted::Partition const&, GParted::OperationDetail&) (GParted_Core.cc:2746)
==32069== by 0x47582B: GParted::GParted_Core::resize_move(GParted::Partition const&, GParted::Partition&, GParted::OperationDetail&) (GParted_Core.cc:2457)
==32069== by 0x46DDB2: GParted::GParted_Core::apply_operation_to_disk(GParted::Operation*) (GParted_Core.cc:767)
...
There is also a leak of a PedGeometry object from
resize_move_partition(). Fix by calling ped_geometry_destroy() to
delete all the allocated PedGeometry objects and free the memory.
Bug 767009 - PedGeometry objects are memory leaked
When replacing the list of paths for the other partition object involved
in either a Resize/Move or Format operation in apply_operation_to_disk()
should replace the whole list of partitions not just replace with the
first path. Copy the whole path list is the correct action. It makes
no material difference because secondary partition paths are only used
to discover mount points during refresh phase and not at the apply
phase, where only the primary path is used.
Bug 766349 - Resolve code ugliness with partition path getting set to
"copy of /dev/SRC"
Quoting the relevant comments from GParted_Core::calibrate_partition():
Re-add the real partition path from libparted.
When creating a copy operation by pasting into unallocated space the
list of paths for the partition object was set to
["Copy of /dev/SRC"] because the partition didn't yet exist before
the operations were applied. Additional operations on that new
partition also got the list of paths set to ["Copy of /dev/SRC"].
This re-adds the real path to the start of the list making it
["/dev/NEW", "Copy of /dev/SRC"]. This provides the real path for
file system specific tools used during those additional operations
such mkfs for the format operation or fsck and others for the
resize/move operation.
FIXME: Having this work just because "/dev/NEW" happens to sort
before "Copy of /dev/SRC" is ugly! Probably have a separate display
path which can be changed at will without affecting the list of real
paths for the partition.
Having a separate display path is overly complicated and unnecessary.
Just replace the list of paths with the real one reported by libparted
if it contained "Copy of /dev/SRC", determined by checking if the file
exists. Otherwise continue to add the libparted name as an alternate
path. Whole disk devices can never be named "Copy of /dev/SRC" because
they are not partitioned so never created or deleted by GParted, only
ever written to, hence don't need the extra exists test logic.
Bug 766349 - Resolve code ugliness with partition path getting set to
"copy of /dev/SRC"
When composing a copy operation it always named the destination
partition as "copy of /dev/SRC". For the case of pasting into
unallocated space creating a new partition this was the right thing to
do as the partition doesn't yet exist so the path is not yet known.
However for the case of pasting into an existing partition the path is
known and replacing it with "copy of /dev/SRC" is wrong. No other
operation when operating on an existing partition changes it path.
Given a set of existing partitions, sdb1 to sdb4, compose a set of copy
operations as: copy sdb1 to sdb2, copy sdb2 to sdb3 and copy sdb3 to
sdb4. The displayed partitions before being applied become:
/dev/sdb1
copy of /dev/sdb1
copy of copy of /dev/sdb1
copy of copy of copy of /dev/sdb1
And the pending operations are named:
Copy /dev/sdb1 to /dev/sdb2
Copy copy of /dev/sdb1 to /dev/sdb3
Copy copy of copy of /dev/sdb1 to /sev/sdb4
This is perverse. In the case of pasting into an existing partition
keep the real path name. This keeps the partitions being displayed as:
/dev/sdb1
/dev/sdb2
/dev/sdb3
/dev/sdb4
And the pending operations named as:
Copy /dev/sdb1 to /dev/sdb2
Copy /dev/sdb2 to /dev/sdb3
Copy /dev/sdb3 to /dev/sdb4
Much more understandable.
Also switch to an upper case "C" in "Copy of /dev/SRC" as the temporary
path name when pasting into unallocated space. Finally update the
comment in calibrate_partition() to describe the remaining cases when
re-adding the path is still required.
Bug 766349 - Resolve code ugliness with partition path getting set to
"copy of /dev/SRC"
Make the code a little more self documenting by adding the symbolic
constants:
SETTLE_DEVICE_APPLY_MAX_WAIT_SECONDS
SETTLE_DEVICE_PROBE_MAX_WAIT_SECONDS
which highlight that settle_device() is called in two different
contexts, device probe and apply operations, with two different timeout
values.
File system specific commands sometimes fail reporting that the
partition specific /dev entry doesn't exist. Example failing check
operation details:
Check and repair file system (ext4) on dev/sdb4
calibrate /dev/sdb4
path: /dev/sdb4 (partition)
start: 4196352
end: 6293503
size: 2097152 (1.00 GiB)
check file system on /dev/sdb4 for errors and (if possible) fix them
e2fsck -f -y -bv -C 0 /dev/sdb4
e2fsck 1.42.9 (28-Dec-2013)
e2fsck: No such file or directory while trying to open /dev/sdb4
Possibly non-existent device?
This has been reproduced on CentOS 7. Debugging shows that the
libparted calls used to re-read the partition details in
GParted_Core::calibrate_partition() leads to udev removing and re-adding
all the partition /dev entries for the disk.
# udevadm monitor &
# gpartedbin
...
16.480662 +12.618659 calibrate_partition() calling get_device("/dev/sdb", lp_device) ...
16.483644 +0.002982 calibrate_partition() get_device() returned
16.483678 +0.000034 calibrate_partition() calling get_disk(lp_device, lp_disk) ...
16.618113 +0.134435 calibrate_partition() get_disk() returned
KERNEL[19275.707968] remove /devices/pci0000:00/0000:00:0d.0/ata4/host3/target3:0:0/3:0:0:0/block/sdb/sdb1 (block)
16.618561 +0.000448 destroy_device_and_disk() calling ped_disk_destroy(lp_disk) ...
16.618584 +0.000023 destroy_device_and_disk() ped_disk_destroy() returned
16.618591 +0.000007 destroy_device_and_disk() calling ped_device_destroy(lp_disk) ...
16.618602 +0.000011 destroy_device_and_disk() ped_device_destroy() returned
16.618687 +0.000085 calibrate_partition() return true
16.618851 +0.000164 execute_command() e2fsck -f -y -v -C 0 /dev/sdb4
KERNEL[19275.708389] remove /devices/pci0000:00/0000:00:0d.0/ata4/host3/target3:0:0/3:0:0:0/block/sdb/sdb2 (block)
KERNEL[19275.708500] remove /devices/pci0000:00/0000:00:0d.0/ata4/host3/target3:0:0/3:0:0:0/block/sdb/sdb3 (block)
KERNEL[19275.708643] remove /devices/pci0000:00/0000:00:0d.0/ata4/host3/target3:0:0/3:0:0:0/block/sdb/sdb4 (block)
KERNEL[19275.768278] change /devices/pci0000:00/0000:00:0d.0/ata4/host3/target3:0:0/3:0:0:0/block/sdb (block)
KERNEL[19275.771171] add /devices/pci0000:00/0000:00:0d.0/ata4/host3/target3:0:0/3:0:0:0/block/sdb/sdb1 (block)
KERNEL[19275.771360] add /devices/pci0000:00/0000:00:0d.0/ata4/host3/target3:0:0/3:0:0:0/block/sdb/sdb2 (block)
KERNEL[19275.771542] add /devices/pci0000:00/0000:00:0d.0/ata4/host3/target3:0:0/3:0:0:0/block/sdb/sdb3 (block)
KERNEL[19275.775858] add /devices/pci0000:00/0000:00:0d.0/ata4/host3/target3:0:0/3:0:0:0/block/sdb/sdb4 (block)
UDEV [19275.820153] remove /devices/pci0000:00/0000:00:0d.0/ata4/host3/target3:0:0/3:0:0:0/block/sdb/sdb3 (block)
UDEV [19275.823152] remove /devices/pci0000:00/0000:00:0d.0/ata4/host3/target3:0:0/3:0:0:0/block/sdb/sdb4 (block)
UDEV [19275.828275] remove /devices/pci0000:00/0000:00:0d.0/ata4/host3/target3:0:0/3:0:0:0/block/sdb/sdb1 (block)
16.742735 +0.123884 execute_command() exit status 8
UDEV [19275.841425] remove /devices/pci0000:00/0000:00:0d.0/ata4/host3/target3:0:0/3:0:0:0/block/sdb/sdb2 (block)
UDEV [19275.905478] change /devices/pci0000:00/0000:00:0d.0/ata4/host3/target3:0:0/3:0:0:0/block/sdb (block)
UDEV [19276.013580] add /devices/pci0000:00/0000:00:0d.0/ata4/host3/target3:0:0/3:0:0:0/block/sdb/sdb3 (block)
UDEV [19276.034728] add /devices/pci0000:00/0000:00:0d.0/ata4/host3/target3:0:0/3:0:0:0/block/sdb/sdb4 (block)
UDEV [19276.174840] add /devices/pci0000:00/0000:00:0d.0/ata4/host3/target3:0:0/3:0:0:0/block/sdb/sdb1 (block)
UDEV [19276.237105] add /devices/pci0000:00/0000:00:0d.0/ata4/host3/target3:0:0/3:0:0:0/block/sdb/sdb2 (block)
So exactly when GParted is running the external e2fsck command, udev is
in the middle of removing and re-adding all the /dev partition entries
for the disk. Hence the above failure reporting that /dev/sdb4 didn't
exist. This error depends on the timing between GParted running the
external file system specific command and udev removing and re-adding
the entries, so sometimes it works and sometimes it fails.
Further debugging showed that simply opening and closing the whole disk
device read-write triggers the same removing and re-adding of all the
partition /dev entries with udev >= 219. Opening the whole disk device
read-write is what libparted has always done until this post
libparted 3.2 patch to make it open read-only when probing:
http://git.savannah.gnu.org/cgit/parted.git/commit/?id=44d5ae0115c4ecfe3158748309e9912c5aede92d
libparted: Use read only when probing devices on linux (#1245144)
To fix this simply wait for udev devices to settle in
calibrate_partitions(). The longest I have seen udev take to do this is
0.80 seconds in a VM. Wait up to 10 seconds as is done in commit() ->
commit_to_os(), also called when applying operations.
On configurations which don't have this issue execution of udevadm
settle, which will return immediately, adds at most 0.1 seconds to the
time taken for the calibrate step. This won't be noticed in the time
taken of the operation details so there is no point in trying to avoid
executing udevadm settle when not needed.
Bug 762941 - Operations sometimes failing with: No such file or
directory
Minor issues:
1) In the while loop reading from /proc/partitions into variable line,
just after the sscanf() call the variable was re-purposed to hold the
device name making the code unnecessarily hard to follow.
2) Variable c_str was a fixed sized buffer holding the device name read
from /proc/partitions.
3) Variable c_str name provides no meaning as to what data it holds.
4) Return value from all the Utils::regexp_label() calls is converted
from Glib::ustring to std::string to be stored in device variable.
Resolve by using Utils::regexp_label() to extract the device name from
each line in /proc/partitions and store in the variable device, already
used for this purpose and now changed to type Glib::ustring.
realpath(3) manual page says:
BUGS
The POSIX.1-2001 standard version of this function is broken by
design, since it is impossible to determine a suitable size for
the output buffer, resolved_path. According to POSIX.1-2001 a
buffer of size PATH_MAX suffices, but PATH_MAX need not be a
defined constant, and may have to be obtained using pathconf(3).
And asking pathconf(3) does not really help, since, on the one
hand POSIX warns that the result of pathconf(3) may be huge and
unsuitable for mallocing memory, and on the other hand
pathconf(3) may return -1 to signify that PATH_MAX is not
bounded. The resolved_path == NULL feature, not standardized in
POSIX.1-2001, but standardized in POSIX.1-2008, allows this
design problem to be avoided.
The resolved_path == NULL feature of realpath() has existed as a Glibc
extension since realpath() was first added to Glibc 1.90, released in
June 1996. Therefore it can be used unconditionally.
https://sourceware.org/git/?p=glibc.git;a=commitdiff;h=fa0bc87c32d02cd81ec4d0ae00e0d943c683e6e1
Bug 764369 - Use realpath() safely
The previous commit (Fix crash reading NTFS usage when there is no
/dev/PTN entry) identified that the FileSystem member variable "index"
is too small on 64-bit machines. Also this member variable stores no
FileSystem class information and was being used as a local variable.
Replace with local variables of the of the correct type, wide enough to
store the npos not found value.
Bug 764658 - GParted crashes when reading NTFS usage when there is no
/dev/PTN entry
On a 64-bit distribution, with an NTFS file system in a partition
without a /dev entry then GParted will crash when attempting to read
the file system usage. Not having a /dev entry for the partition is
rare and only known to occur for the disk devices used within Fake RAID
(dmraid) arrays, and then only on Ubuntu 12.04 LTS. Other/newer
distributions do create /dev entries for partitions found on disk
devices within Fake RAID arrays.
Create mirror Fake RAID array:
# dmraid -f isw -C MyArray --type 1 --disk /dev/sdc,/dev/sdd
# dmraid -ay
Create NTFS partition on the Fake RAID array. On refresh GParted
crashes:
# ./gpartedbin
(gpartedbin:590): glibmm-ERROR **:
unhandled exception (type std::exception) in signal handler:
what: basic_string::assign
Without a /dev/sdc1 device entry the ntfsresize command reports this:
# ntfsresize --info --force --no-progress-bar /dev/sdc1
ntfsresize v2015.3.14 (libntfs-3g)
ERROR(2): Failed to check '/dev/sdc1' mount state: No such file or directory
Probably /etc/mtab is missing. It's too risky to continue. You might try
an another Linux distro.
The problem code in ntfs::set_used_sectors():
145 index = output.find( "Cluster size" );
146 if ( index == output.npos ||
147 sscanf( output.substr( index ).c_str(), "Cluster size : %Ld", &S ) != 1 )
As "Cluster size" did not exist in the output find() returned the not
found token of string::npos [1], which in a 64-bit environment is
represented by 2^64-1 [2]. However it was saved in the variable index
of type unsigned integer, which is only a 32-bit integer, thus
truncating it to 2^32-1. Therefore the comparison failed and sscanf()
tried to parse the output starting at offset 2^32-1 which resulted in
the crash.
Introduced by commit:
324d99a172
Record file system block size where known (#760709)
Fix by following the same pattern of the other comparisons in
ntfs::set_used_sectors() which checks if index is less than the output
length.
References:
[1] std::string::find
http://www.cplusplus.com/reference/string/string/find/
[2] std::string::npos
http://www.cplusplus.com/reference/string/string/npos/
(Note that Glib::ustring is derived from std::string in the Standard C++
library and provides a compatible interface).
Bug 764658 - GParted crashes when reading NTFS usage when there is no
/dev/PTN entry
GParted is allowing creation of a FAT32 formatted partition of any size.
However with a 512 byte sector size the maximum volume size of a FAT32
file system is reported to be 2 TiB.
* Wikipedia: File Allocation Table / FAT32
https://en.wikipedia.org/wiki/File_Allocation_Table#FAT32
"The boot sector uses a 32-bit field for the sector count, limiting
the FAT32 volume size to 2 TB for a sector size of 512 bytes and 16 TB
for a sector size of 4,096 bytes."
* Microsoft: Default cluster size for NTFS, FAT, and exFAT / Default
cluster sizes for FAT32
https://support.microsoft.com/en-us/kb/140365
Trying to create a FAT32 file system in a partition larger than 2 TiB
results in unallocated space being left after the file system.
Nuances:
[1] Larger sector sizes allow larger maximum volume sizes up to 16 TiB
with 4096 byte sectors.
[2] mkdosfs/mkfs.fat has an -S SECTOR_SIZE option which allows changing
the "logical" sector size of the file system allowing the maximum
volume to be proportionally increased.
[3] mkfs.fat appears to have an signed overflow bug when the size of the
partition is larger than maximum signed 32-bit integer of logical(?)
sectors. (2 TiB for a sector size of 512 bytes). It reports the
partition size as minus size and creates a 1 TiB file system.
GParted wants a single maximum file system size and the code is not
ready for a differing maximum file system size for different sector
sizes.
In fat16::create() could specify larger "logical" sector sizes to
mkfs.fat when the partition is larger than 2 TiB to allow maximum volume
size to be increased further. However that will take a lot of cross
platform testing to ensure that all sorts of devices support "logical"
sector sizes other than 512 bytes on devices with a hardware sector size
of 512 bytes. This is too much effort.
Therefore implement a single FAT32 maximum volume size of 2 TiB.
Bug 763896 - GParted not restricting creation of FAT32 volume to maximum
size of 2 TiB
As part of the internal block copy operation 5 initial ranges of blocks
are copied using different block sizes to determine the fastest. Then
the remainder is copied using the fastest block size. Each of these
copies reports progress independently, so during the benchmarking phase
the progress bar flashes 5 times as it goes from 0 to 100% in a fraction
of a second, before showing the progress of the remainder.
This looks bad, so report a single progress bar for all the ranges of
blocks copied in a single copy operation.
Already have variables done and length which track progress within each
copied range; and total_done which records amount copied in previous
ranges. Just add total_length to allow overall progress to be reported.
Bug 762367 - Use a single progress bar for the whole of the internal
copy operation
Previously total_done was updated in copy_thread() after copying of the
blocks, but importantly before the last call to set_progress_info() to
update the progress bar. Having total_done varying during the copy of a
single range of blocks, single call to copy_blocks::copy(), is an
impediment to being able to report a single progress bar across the
whole internal copy operation.
Move updating of total_done to copy() immediately after copy_thread()
completes.
Bug 762367 - Use a single progress bar for the whole of the internal
copy operation
Copying of ntfs is performed using ntfsclone, which writes progress
indication to standard output like this:
# ntfsclone -f /dev/sdb2 /dev/sdb1 2> /dev/null
NTFS volume version: 3.1
Cluster size : 4096 bytes
Current volume size: 21474832384 bytes (21475 MB)
Current device size: 21474836480 bytes (21475 MB)
Scanning volume ...
100.00 percent completed
Accounting clusters ...
Space in use : 1832 MB (8.5%)
Cloning NTFS ...
100.00 percent completed
Syncing ...
Add ntfsclone progress tracker for ntfsclone command. Deliberately
doesn't stop the progress bar. See comment in ntfs::clone_progress()
for the explanation.
Bug 762366 - Add progress bar to NTFS file system specific copy method
Mostly the code is explicit and calls the emit() method when emitting a
signal [1], like this:
signal_name.emit();
However there are a few cases which use the function call operator on
the signal object [2], like this:
signal_name();
The behaviour is identical [3] but it is preferred to be explicit that a
signal callback is being initiated, and it also makes them much easier
to search for too.
[1] List explicit emit() signal calls
fgrep '.emit(' src/*.cc
[2] List function call operator emitted signals
egrep "`sed -n '/sigc::signal/s/.*sigc::signal.*> *\([a-zA-Z_]*\).*/\1/p' include/*.h | tr '\n' '|' | sed 's/\(.*\).$/[^a-zA-Z_](\1)\\\(/'`" src/*.cc
[3] Quote from the libsigc++ Reference Manual, class sigc::signal
https://developer.gnome.org/libsigc++/stable/classsigc_1_1signal7.html#ab37db0ecc788824d0baa3c301efc8dcd
result_type sigc::signal<...>::operator()(...)
Triggers the emission of the signal (see emit())
For non-progress tracked external commands the command being executed is
displayed in the Apply pending operations dialog, just below the top
pulsing progress bar. However for progress tracked external commands
the description of the parent operation detail is displayed instead.
Example 1: non-progress tracked xfs check repair:
TreePath
Check and repair file system (xfs) on /dev/sdc1 0
+ calibrate /dev/sdc1 0:0
+ check file system on /dev/sdc1 for errors and (if po... 0:1
+ xfs_repair -v /dev/sdc1 0:1:0
+ [empty stdout] 0:1:0:0
+ [stderr]Phase 1 - find and verify superblock... 0:1:0:1
"xfs_repair -v /dev/sdc1" (TreePath 0:1:0) is shown because it is the
latest updated operation detail which is timed (set to status
executing).
Example 2: progress tracked ext4 copy using e2image:
TreePath
Copy /dev/sdc2 to /dev/sdc3 0
+ calibrate /dev/sdc2 0:0
+ check file system on /dev/sdc2 for errors and (if po... 0:1
+ set partition type on /dev/sdc3 0:2
+ copy file system of /dev/sdc2 to /dev/sdc3 0:3
+ e2image -ra -p /dev/sdc2 /dev/sdc3 0:3:0
+ [stdout]Scanning inodes... 0:3:0:0
+ [stderr]e2image 1.42.9 (28-Dec-2013)... 0:3:0:1
"copy file system of /dev/sdc2 to /dev/sdc3" (TreePath 0:3) is shown
because that operation detail is also timed and it is being constantly
updated by the progress bar updates via it.
Change execute_command() to update the progress bar via the operation
detail it creates to hold the command being executed, instead of the
parent operation detail, to resolve the above. Also replaces calling
operationdetail.get_last_child() throughout the method.
Bug 760709 - Add progress bars to XFS and EXT2/3/4 file system specific
copy methods
Remove starting and stopping the progress bar in xfs::copy(). The
progress bar will be automatically started in xfs::copy_progress()
callback when run_progressbar() is called; and automatically stopped in
FileSystem::execute_command() when it calls stop_progress() at the end.
Note that this will now not initialise the progress bar from zero
immediately that the XFS copy is started, but instead 0.5 seconds into
the copy when xfs::copy_progress() timed callback is called for the
first time.
Bug 760709 - Add progress bars to XFS and EXT2/3/4 file system specific
copy methods
The timed progress tracking callback for execution of xfs copy follows
this pattern:
sigc::connection c;
...
c = Glib::signal_timeout().connect( ... sigc::mem_fun( *this, &xfs::copy_progress ) ..., 500 /*ms*/ );
... execute_command( ... );
c.disconnect();
As with output progress tracking callbacks for ext2/3/4 and ntfs file
system specific commands, pass the callback slot and a flag into
execute_command() and connect the timed callback inside. This
simplified the pattern to:
... execute_command( ...|EXEC_PROGRESS_TIMED,
static_cast<TimedSlot>( sigc::mem_fun( *this, &xfs::copy_progress ) ) );
NOTE:
The type of sigc::mem_fun() doesn't allow the compiler to choose between
the two overloaded variants of execute_command() with the fourth
parameter of either (full types without typedefs of StreamSlot and
TimedSlot respectively):
sigc::slot<void, OperationDetail *> stream_progress_slot
sigc::slot<bool, OperationDetail *> timed_progress_slot
Therefore have to cast the result of all callback slots to the relevant
type. Hence:
static_cast<StreamSlot>( sigc::mem_fun( *this, &{CLASS}::{NAME}_progress ) )
static_cast<TimedSlot>( sigc::mem_fun( *this, &xfs::copy_progress ) )
References:
* [sigc] Functor not resolving between overloaded methods with
different slot types
https://mail.gnome.org/archives/libsigc-list/2016-February/msg00000.html
* Bug 306705 - Can't overload methods based on different slot<>
parameters.
https://bugzilla.gnome.org/show_bug.cgi?id=306705
Bug 760709 - Add progress bars to XFS and EXT2/3/4 file system specific
copy methods
For the relevant stream from a file system specific command being
tracked, there were 2 callbacks attached: update_command_output() and
update_command_progress(). When called, update_command_progress() just
emitted signal_progress to call the file system specific progress
tracker callback. Like this:
signal_update.emit() -> update_command_output()
-> update_command_progress()
signal_progress.emit() -> {CLASS}::{NAME}_progress()
Instead just connect the file system specific progress tracker callback
directly to signal_update and bypass the unnecessary
update_command_progress() method and the signal_progress signal. Like
this:
signal_update.emit() -> update_command_output()
-> {CLASS}::{NAME}_progress()
Bug 760709 - Add progress bars to XFS and EXT2/3/4 file system specific
copy methods
All the output progress tracking callbacks for execution of ext2/3/4 and
ntfs file system specific commands followed this pattern:
sigc::connection c = signal_progress.connect( sigc::mem_fun( *this, &ext2::..._progress ) );
bool success = ! execute_command( ... );
c.disconnect();
return success;
Instead, pass the callback slot and a flag into execute_command() and
connect the callback inside. This simplifies the pattern to:
return ! execute_command( ...|EXEC_PROGRESS_STDOUT,
sigc::mem_fun( *this, &ext2::..._progress ) );
Note that as the progress tracking callbacks are only registered against
updates to the relevant stream from the tracked commands they won't be
called when the other stream is updated any more.
Also note that signal_progress is a member of the FileSystem class and
derived objects so lives as long as GParted is running, therefore the
progress tracking callbacks need explicitly disconnecting at the end of
execute_command(). However signal_update is a member of the PipeCapture
class of which the output and error local variables in execute_command()
are types. Therefore there is no need to explicitly disconnect the
signal_update callbacks as they will be destructed along with the
callback slots when they go out of scope at the end of the
execute_command() method.
Bug 760709 - Add progress bars to XFS and EXT2/3/4 file system specific
copy methods
Remove unused members: fraction and progress_text from the
OperationDetail class now that the ProgressBar class has superseded
their use. This also allows removal of timer_global member from the
copy_blocks class. Timer_global was only used to track the elapsed time
copying blocks and allow the remaining time to be estimated and written
into progress_text. The ProgressBar class also does this itself
internally.
Bug 760709 - Add progress bars to XFS and EXT2/3/4 file system specific
copy methods
Most of the file system specific command progress trackers followed this
pattern:
void {CLASS}::{NAME}_progress( OperationDetail *operationdetail )
{
ProgressBar & progressbar = operationdetail->get_progressbar();
// parse output for progress and target values
if ( // have progress and target values )
{
if ( ! progressbar.running() )
progressbar.start( target );
progressbar.update( progress );
operationdetail->signal_update( *operationdetail );
}
else if ( // found progress finished )
{
if ( progressbar.running() )
progressbar.stop();
operationdetail->signal_update( *operationdetail );
}
}
That is a lot of repetition handling progress bar updates and
OperationDetail object update signalling. Remove the need for direct
access to the single ProgressBar object and provide these two
OperationDetail methods instead:
// Start and update in one
run_progressbar( progress, target, optional text_mode );
stop_progressbar();
Now the file system specific command progress trackers can become:
void {CLASS}::{NAME}_progress( OperationDetail *operationdetail )
{
// parse output for progress and target values
if ( // have progress and target values )
{
operationdetail->run_progressbar( progress, target );
}
else if ( // found progress finished )
{
operationdetail->stop_progressbar();
}
}
Make ProgressBar::get_progressbar() a private method to enforce use of
the new way to access the progress bar via the run_progress() and
stop_progressbar() methods. Then make the Dialog_Progress a friend
class to OperationDetail so that the Apply pending operations dialog can
still access the single ProgressBar object for its querying needs.
Bug 760709 - Add progress bars to XFS and EXT2/3/4 file system specific
copy methods
Using e2image to copy a file system looks like this. (Intermediate
progress lines which are constantly overwritten are indicated with ">").
# e2image -ra -p /dev/sdb4 /dev/sdb5
e2image 1.42.13 (17-May-2015)
Scanning inodes...
> Copying 0 / 276510 blocks (0%)
> Copying 8845 / 276510 blocks (3%)
> Copying 48433 / 276510 blocks (18%)
> Copying 77135 / 276510 blocks (28%)
> Copying 111311 / 276510 blocks (40%)
> Copying 137039 / 276510 blocks (50%)
> Copying 166189 / 276510 blocks (60%) 00:00:03 remaining at 108.20 MB/s
> Copying 190285 / 276510 blocks (69%) 00:00:03 remaining at 106.19 MB/s
> Copying 209675 / 276510 blocks (76%) 00:00:02 remaining at 102.38 MB/s
> Copying 238219 / 276510 blocks (86%) 00:00:01 remaining at 103.39 MB/s
> Copying 256692 / 276510 blocks (93%) 00:00:00 remaining at 100.27 MB/s
Copied 276510 / 276510 blocks (100%) in 00:00:10 at 108.01 MB/s
Note that the copying figures are reported in file system block size
units and the progress information is written to stderr, hence needing
these two previous commits:
Record file system block size where known (#760709)
Call any FS specific progress trackers for stderr updates too (#760709)
Add progress tracking function for e2image command. Also tracks when
the text progress indicator has passed in the output so that the
progress bar can be stopped as well as started when needed.
Bug 760709 - Add progress bars to XFS and EXT2/3/4 file system specific
copy methods
So far the signal_progress callback slot was only emitted when standard
output from the file system specific command was updated. This was okay
as all the commands until now wrote their progress information to
stdout. However e2image writes its progress information to stderr,
therefore also emit signal_progress when stderr is updated too.
This does mean that the file system specific *_progress() tracking
callbacks will be called when either of the OperationDetail objects
containing stdout or stderr are updated. Therefore the trackers may be
called when there is no update to the stream from which it is parsing
the progress information. This is not a problem as the tracker will
just update the progress bar with the same information it already has.
Also it won't happen much as only e2image is known to write to both
streams, and then only one line to stdout and the updated progress
information to stderr. This is just an observation and not an issue
which needs coding around.
Bug 760709 - Add progress bars to XFS and EXT2/3/4 file system specific
copy methods
Record the file system block size in the Partition object. Only
implemented for file systems when set_used_sectors() method has already
parsed the value or can easily parse the value from the existing
executed command(s).
Needed for ext2/3/4 copies and moves performed using e2image so that
they can be tracked in bytes by the ProgressBar class as e2image reports
progress in file system block size units.
Bug 760709 - Add progress bars to XFS and EXT2/3/4 file system specific
copy methods
XFS uses a file system specific method to copy the partition using
"xfsdump | xfsrestore". Monitor progress by periodically querying the
destination file system usage and comparing to the source file system
usage. Use 0.5 seconds as the polling interval to match that used by
the internal block copying algorithm.
NOTE:
The number of used blocks in the source and destination file system will
be very close but may not match exactly. I have seen an XFS copy finish
with the following progress text:
1.54 GiB of 1.50 GiB copied (-00:00:02 remaining)
Allow the progress bar to overrun like this as it is informing the user
that it actually copied a little more data and took a little longer than
expected. Needs these two previous commits to correctly round and
format the negative time remaining:
Fix rounding of negative numbers (#760709)
Fix formatting of negative time values (#760709)
Bug 760709 - Add progress bars to XFS and EXT2/3/4 file system specific
copy methods
... to display a negative sign before the hours, minutes and seconds.
Before:
Utils::format_time(-1) = "00:00:0-1"
Utils::format_time(-119) = "00:0-1:0-59"
After:
Utils::format_time(-1) = "-00:00:01"
Utils::format_time(-119) = "-00:01:59"
Bug 760709 - Add progress bars to XFS and EXT2/3/4 file system specific
copy methods
Utils::round() was doing +0.5 then truncate. Correct for positive
values. Wrong for negative values.
E.G.
Utils::round(-1.4)
= trunc(-1.4 + 0.5)
= trunc(-0.9)
= 0
Round of -1.4 is definitely not 0. Fix this for negative values by
subtracting 0.5 then truncating.
Reference:
How can I convert a floating-point value to an integer in C?
https://www.cs.tut.fi/~jkorpela/round.html
Bug 760709 - Add progress bars to XFS and EXT2/3/4 file system specific
copy methods
When the ntfs resize operation had almost completed, percentage complete
was >= 99.9%, the progress tracker was passing 0.04 (4%) to the progress
bar. After reading the next chunk of output from the ntfsresize command
the last line contained this text:
" 4) set the bootable flag for the partit"
End of the ntfsresize command output for context:
Relocating needed data ...
100.00 percent completed
Updating $BadClust file ...
Updating $Bitmap file ...
Updating Boot record ...
Syncing device ...
Successfully resized NTFS on device '/dev/sdd4'.
You can go on to shrink the device for example with Linux fdisk.
IMPORTANT: When recreating the partition, make sure that you
1) create it at the same disk sector (use sector as the unit!)
2) create it with the same partition type (usually 7, HPFS/NTFS)
3) do not make it smaller than the new NTFS filesystem size
4) set the bootable flag for the partition if it existed before
Otherwise you won't be able to access NTFS or can't boot from the disk!
If you make a mistake and don't have a partition table backup then you
can recover the partition table by TestDisk or Parted's rescue mode.
This was occurring because *scanf() can't actually report failure to
match fixed text after conversion of the last variable. See code
comment in ntfs::resize_progress() for more details. Fix by using
.find() instead to match the required "percent completed" explicit text
of the progress information when it appears on the last line.
Bug 760709 - Add progress bars to XFS and EXT2/3/4 file system specific
copy methods
Adapt the ntfs resize progress tracker to use the new ProgressBar class.
Also make it track when the text progress indicator has passed in the
output so that the progress bar can be stopped as well as started when
needed.
Bug 760709 - Add progress bars to XFS and EXT2/3/4 file system specific
copy methods
Adapt the ext2 fsck progress tracker to use the new ProgressBar class.
Also make it track when the text progress bar has completely passed in
the output so that the progress bar can be stopped as well as started
when needed.
Bug 760709 - Add progress bars to XFS and EXT2/3/4 file system specific
copy methods
Adapt the ext2 create file system progress tracker to used the new
ProgressBar class. Also make it track when the text progress indicator
completes so that the progress bar can be stopped as well as started
when needed.
Bug 760709 - Add progress bars to XFS and EXT2/3/4 file system specific
copy methods
Adapt the ext2 resize progress tracker to the new ProgressBar class.
Also update the progress function to track when text progress bars have
completely passed in the output so that the progress bar can be stopped
as well as started when needed.
Bug 760709 - Add progress bars to XFS and EXT2/3/4 file system specific
copy methods
Change the Applying pending operations dialog so that it takes it source
of progress from the single ProgressBar object, rather than the fraction
value in every OperationDetail object. Also remove ProgressBar
debugging now that it is being used to drive the UI.
NOTE:
This temporarily causes the existing file system specific progress bars
to not be shown because they still update via the fraction member in
each OperationDetail object, rather than the new ProgressBar. This will
be corrected in following commits.
Bug 760709 - Add progress bars to XFS and EXT2/3/4 file system specific
copy methods
1) Multiple progress bars
The OperationDetail class contains member fraction which is used to feed
data to the current operation progress bar shown in the Applying pending
operations dialog. Dialog_Progress::on_signal_update() gets called for
every updated OperationDetail object and depending on whether fraction
is > 0.0 or not, switches between showing a growing or pulsing progress
bar. This leads to the conclusion that every OperationDetail object
currently being updated is effectively driving the single on screen
progress bar with different data.
The Copy_Blocks code is careful to update text and faction in a single
OperationDetail object and everything is good. The on screen progress
bar is switched into growing mode and then grows to 100%.
Since external command output is updated in real time [1] there are two
OperationDetail objects, one for stdout and one for stderr, which are
updated whenever data is read from the relevant stream. Also now that
progress is interpreted from some external command output [2][3][4] a
separate OperationDetail object is getting updated with the progress
fraction. (Actually the grandparent OperationDetail of the ones
receiving stdout and stderr updates as used by the file system specific
*_progress() methods). In the normal case of an external command
which is reporting it's progress two OperationDetails are constantly
being updated together, the OperationDetail object tracking stdout and
it's grandparent receiving progress fraction updates. This causes the
the code in Dialog_Progress::on_signal_update() to constantly switch
between growing and pulsing progress bar mode. The only reason this
doesn't flash the progress bar is because the stdout OperationDetail
object is updated first and before the 100 ms timeout fires to pulse the
bar, it's grandparent is updated with the new fraction to keep growing
the bar instead.
2) Common code
The Copy_Blocks code currently tracks the progress of blocks copied
against target amount, which it has to do anyway. That information is
then used to generate the text and fraction to update into the
OperationDetail object and drive the on screen progress bar. This same
level of tracking is wanted for the XFS and ext2/3/4 file system
specific copy methods.
Conclusion and solution
Having multiple sources of progress bar data is a problem and makes it
clear that there must be only one source of progress data. Also some
code can be shared for tracking the amount of blocks copied and
generating the display.
Therefore have a single ProgressBar object which is used everywhere.
This commit
It just creates a single ProgressBar object which is available via all
OperationDetail objects and Copy_Blocks is updated accordingly. Note
that the ProgressBar still contains debugging and that the GUI progress
bar of the current operation is still driven via the fraction member in
any OperationDetail object.
Referenced commits:
[1] 52a2a9b00a
Reduce threading (#685740)
[2] ae434579e1
Display progress for e2fsck (#467925)
[3] baea186138
Display progress for mke2fs (#467925)
[4] 57b028bb8e
Display progress during resize (#467925)
Bug 760709 - Add progress bars to XFS and EXT2/3/4 file system specific
copy methods
Write a generic progress bar class. Has the following features:
* Has separate progress and target numbers, rather than a single
completion fraction, to enable the the next feature.
* Optionally generates text reporting the amount of data copied using
the progress and target numbers like this:
"1.00 MiB of 16.00 MiB copied"
* After running for 5 seconds, also add estimated remaining time.
(Waits to allow the data copying rate to settle down a little before
estimating the remaining time). Looks like this:
"1.00 MiB of 16.00 MiB copied (00:01:59) remaining)"
The ProgressBar class is not driving the visual progress bar yet. It
has just been added into the internal block copy algorithm and generates
debug messages showing the progress bar is operating correctly.
Debugging looks like this:
DEBUG: ProgressBar::start(target=2.0636e+09, text_mode=PROGRESSBAR_TEXT_COPY_BYTES)
DEBUG: ProgressBar::update(progress=1.30023e+08) m_fraction=0.0630081 m_text="124.00 MiB of 1.92 GiB copied"
DEBUG: ProgressBar::update(progress=2.67387e+08) m_fraction=0.129573 m_text="255.00 MiB of 1.92 GiB copied"
DEBUG: ProgressBar::update(progress=4.0475e+08) m_fraction=0.196138 m_text="386.00 MiB of 1.92 GiB copied"
...
DEBUG: ProgressBar::update(progress=1.13351e+09) m_fraction=0.549289 m_text="1.06 GiB of 1.92 GiB copied (00:00:04 remaining)"
DEBUG: ProgressBar::update(progress=1.26249e+09) m_fraction=0.611789 m_text="1.18 GiB of 1.92 GiB copied (00:00:04 remaining)"
DEBUG: ProgressBar::update(progress=1.39041e+09) m_fraction=0.67378 m_text="1.29 GiB of 1.92 GiB copied (00:00:03 remaining)"
...
DEBUG: ProgressBar::update(progress=1.97552e+09) m_fraction=0.957317 m_text="1.84 GiB of 1.92 GiB copied (00:00:00 remaining)"
DEBUG: ProgressBar::update(progress=2.0636e+09) m_fraction=1 m_text="1.92 GiB of 1.92 GiB copied"
DEBUG: ProgressBar::stop()
Bug 760709 - Add progress bars to XFS and EXT2/3/4 file system specific
copy methods
Simplify code in Dialog_Partition_Info::Dialog_Info() which was open
coding concatenating together a vector of strings with a new line
between each. Replace with Glib::build_path(), as used elsewhere in
this method and other code.
Create and open a LUKS mapping but don't create any file system within.
# cryptsetup luksFormat /dev/sdb5
# cryptsetup luksOpen /dev/sdb5 sdb5_crypt
GParted was incorrectly reporting this warning:
Unable to read the contents of this file system!
Because of this some operations may be unavailable.
The cause might be a missing software package.
The following list of software packages is required for luks file
system support: dmsetup.
This is even though the usage figures for the on disk LUKS encryption
are fully known. See luks::set_used_sectors().
This was occurring because derived PartitionLUKS::set_usage_known()
was checking usage figures for the outer LUKS and the inner encrypted
file system, unknown in this case. Correct when displaying figures in
the UI, but not correct in GParted_Core::set_used_sectors() when only
checking the outer LUKS usage figures were set correctly. Fix this.
Bug 760080 - Implement read-only LUKS support
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
For LUKS formatted partitions add an encryption section into the
Information dialog and display the type of encryption, path, UUID and
status of the encryption.
The file system section continues to display appropriate file system
details, including the partition graphic with the file system specific
border colour and correct usage. The details will either be of a plain
file system, an encrypted file system, or nothing when there is no open
dm-crypt mapping, leaving the encrypted file system inaccessible.
Should there be LUKS encryption directly within LUKS encryption then the
details of the inner encryption will be displayed in the file system
section. However this configuration will not be further supported by
GParted.
Bug 760080 - Implement read-only LUKS support
There is already the set of methods in the Partition class to report the
file system usage. Virtualise them and provide PartitionLUKS specific
implementations to calculate the usage of a file system wrapped in LUKS
encryption.
See the ascii art and comment in PartitionLUKS.cc for the details of
those calculations.
Bug 760080 - Implement read-only LUKS support
LUKS headers don't provide any concept of label. Also there is already
the method Partition::get_filesystem_label() for getting the *file
system* label, so virtualise it and provide an appropriate
implementation to get the label of an encrypted file system represented
within a derived PartitionLUKS object. This causes the label to be
displayed correctly in the main window.
It also happens to display the encrypted file system label in the
Information dialog for a LUKS formatted partition. However the whole
Information dialog will be addressed differently in a following commit.
Bug 760080 - Implement read-only LUKS support
In the main window disk graphic, when there is an open dm-crypt mapping,
display the colour of the encrypted file system.
Bug 760080 - Implement read-only LUKS support
In the File System column in the GUI, when there is an open dm-crypt
mapping, display the colour square for the encrypted file system within
and the text as "[Encrypted] FSTYPE". For closed mappings nothing can
be known about the encrypted file system within so continue to display a
purple square and the text "[Encrypted]".
Looks like:
Partition | File System
...
/dev/sdb3 # ext4
v /dev/sdb4 * # extended
/dev/sdb5 # [Encrypted]
/dev/sdb6 * # [Encrypted] unknown
/dev/sdb7 * # [Encrypted] ext4
Bug 760080 - Implement read-only LUKS support
Partition object represents a region of a disk and the file system
within. GParted always displays the colour base of the type of the file
system. Therefore remove the color member and always look it up from
the type of the file system as needed.
This makes one less member that will need virtual accessor methods with
different handling in the derived PartitionLUKS class.
Bug 760080 - Implement read-only LUKS support
When there exists an open dm-crypt mapping, populate the encrypted
Partition object representing the encrypted file system.
Bug 760080 - Implement read-only LUKS support
Absolute minimum implementation of a PartitionLUKS class which can be
constructed, polymorphically copied and destroyed. Contains an
"encrypted" member of type Partition to represent the encrypted file
system within the LUKS format.
Create PartitionLUKS objects instead of base Partition objects when a
LUKS formatted partition is found. Only the base Partition object
member values have been populated, and the "encrypted" member remains
blank at this point.
Bug 760080 - Implement read-only LUKS support
This is the equivalent change as made to set_mountpoints() in an earlier
commit. Change GParted_Core::set_used_sectors() from being called with
a vector of partitions and processing them all to being called per
partition. This is in preparation for calling set_used_sectors() on a
single Partition object inside a PartitionLUKS object.
Bug 760080 - Implement read-only LUKS support
Populate the canonical device name, /dev/mapper/NAME, used to access the
encrypted file system into the mount points of the Partition object.
This is the equivalent of what is already done for the Volume Group name
and SWRaid Array device.
This does get displayed in the Mount Point column in the main window,
which isn't wanted. However the data will be needed when displaying
details of the encryption mapping in the Information dialog. Both will
be dealt with in following commits.
Bug 760080 - Implement read-only LUKS support
Previously GParted_Core::set_mountpoints() was called with a vector of
partitions and processed them all. Now make set_mountpoints() process a
single partition and push the calls to it down one level from
set_devices_thread() into set_device_partitions() and
set_device_one_partition(). This is in preparation for having an
encrypted file system represented as a Partition object inside a
PartitionLUKS object and needing to call set_mountpoints() for the inner
single Partition object.
Bug 760080 - Implement read-only LUKS support
Only load the LUKS_Info cache of active dm-crypt mappings when the first
LUKS partition is encountered. Not needed from a performance point of
view as the longest that I have ever seen "dmsetup table --target crypt"
take to run is 0.05 seconds. Just means that the dmsetup command is
only run when there are LUKS partitions and the information is needed.
Bug 760080 - Implement read-only LUKS support
Populate the used, unused and unallocated figures in the Partition
object for a LUKS formatted partition. See comment in
luks::set_used_sectors() for the rational of what is used, unused and
unallocated.
As that rational mentions, a LUKS header does not store the size of the
encrypted data and is assumed to extend to the end of the partition by
the tools which start the mapping.
An underlying block device of 128 MiB (131072 KiB).
# sfdisk -s /dev/sde
131072
An active LUKS mapping at offset 2 MiB (4096 512-byte sectors) and
length 126 MiB (129024 KiB, 258048 512-byte sectors).
# sfdisk -s /dev/mapper/sde_crypt
129024
# cryptsetup status sde_crypt
/dev/mapper/sde_crypt is active.
type: LUKS1
cipher: aes-cbc-essiv:sha256
keysize: 256 bits
device: /dev/sde
offset: 4096 sectors
size: 258048 sectors
mode: read/write
No size/length reported when dumping the LUKS header, just (payload)
offset.
# cryptsetup luksDump /dev/sde
LUKS header information for /dev/sde
Version: 1
Cipher name: aes
Cipher mode: cbc-essiv:sha256
Hash spec: sha1
Payload offset: 4096
MK bits: 256
MK digest: 7f fb ba 40 7e ba e4 3b 2f c6 d0 93 7b f7 05 49 7b 72 d4 ad
MK salt: 4a 5b 54 f9 7b 67 af 6e ef 16 31 0a fe d9 7e 5f
c3 66 dc 8a ed e0 07 f4 45 c3 7c 1a 8d 7d ac f4
MK iterations: 37750
UUID: 0a337705-434a-4994-a842-5b4351cb3778
...
Shrink the LUKS mapping to 64 MiB (65536 KiB, 131072 512-byte sectors).
# cryptsetup resize --size 131072 sde_crypt
# sfdisk -s /dev/mapper/sde_crypt
65536
# cryptsetup status sde_crypt
/dev/mapper/sde_crypt is active.
type: LUKS1
cipher: aes-cbc-essiv:sha256
keysize: 256 bits
device: /dev/sde
offset: 4096 sectors
size: 131072 sectors
mode: read/write
Stop and start the LUKS mapping.
# cryptsetup luksClose sde_crypt
# cryptsetup luksOpen /dev/sde sde_crypt
The size of the LUKS mapping is back to 126 MiB (129024 KiB, 258048
512-byte sectors), extending to the end of the partition.
# sfdisk -s /dev/mapper/sde_crypt
129024
# cryptsetup status sde_crypt
/dev/mapper/sde_crypt is active.
type: LUKS1
cipher: aes-cbc-essiv:sha256
keysize: 256 bits
device: /dev/sde
offset: 4096 sectors
size: 258048 sectors
mode: read/write
Bug 760080 - Implement read-only LUKS support
Also load the starting offset and length of the active dm-crypt mapping
into the LUKS_Info module from the dmsetup output. This provides the
location and size of the encrypted data within the underlying block
device.
Note that dmsetup reports in units of 512 bytes sectors [1], the GParted
LUKS_Info module uses bytes and GParted Partition objects work in device
sector size units. However the actual sector size of a dm-crypt mapping
[2] is the same as that of the underlying block device [3].
# modprobe scsi_debug dev_size_mb=128 sector_size=4096
# fgrep scsi_debug /sys/block/*/device/model
/sys/block/sdd/device/model:scsi_debug
# parted /dev/sde print
Error: /dev/sde: unrecognised disk label
Model: Linux scsi_debug (scsi)
Disk /dev/sde: 134MB
[3] Sector size (logical/physical): 4096B/4096B
Partition Table: unknown
# cryptsetup luksFormat /dev/sde
# cryptsetup luksOpen /dev/sde sde_crypt
# parted /dev/mapper/sde_crypt print
Error: /dev/mapper/sde_crypt: unrecognised disk label
Model: Linux device-mapper (crypt) (dm)
Disk /dev/mapper/sde_crypt: 132MB
[2] Sector size (logical/physical): 4096B/4096B
Partition Table: unknown
# cryptsetup status sde_crypt
/dev/mapper/sde_crypt is active.
type: LUKS1
cipher: aes-cbc-essiv:sha256
keysize: 256 bits
device: /dev/sde
offset: 4096 sectors
size: 258048 sectors
mode: read/write
# dmsetup table --target crypt
...
sde_crypt: 0 258048 crypt aes-cbc-essiv:sha256 0000000000000000000000000000000000000000000000000000000000000000 0 8:64 4096
[1] Both cryptsetup and dmsetup report the offset as 4096 and the size/
length as 258048. 128 MiB / (4096+258048) = 512 byte units, even on a
4096 byte sector size device.
Update debugging of LUKS to this:
# ./gpartedbin
======================
libparted : 2.4
======================
DEBUG: /dev/sdb5: LUKS closed
DEBUG: /dev/sdb6: LUKS open mapping /dev/mapper/sdb6_crypt, offset=2097152, length=534773760
/dev/sde: unrecognised disk label
DEBUG: /dev/sde: LUKS open mapping /dev/mapper/sde_crypt, offset=2097152, length=132120576
Bug 760080 - Implement read-only LUKS support
The code currently allows attempting to mount and unmount a LUKS
partition. It is nonsense to directly try to mount and unmount a LUKS
partition and obviously doesn't work. For read-only LUKS support there
is no need to attempt to apply this to the encrypted file system within.
Therefore prevent these operations for LUKS partitions.
Bug 760080 - Implement read-only LUKS support
This patchset is adding read-only LUKS support. Creation of LUKS is
planned to be a tick box adding encryption in the Create New Partition
dialog. Therefore remove the greyed out crypt-luks entry in the Create
New Partition dialog and the Format menu.
Bug 760080 - Implement read-only LUKS support
Provide a minimal implementation of a luks file system class which only
does busy detection.
NOTE:
For now, read-only LUKS support, a LUKS partition will be busy when a
dm-crypt mapping exists. Later when read-write LUKS support is added
GParted will need to look at the busy status of the encrypted file
system within the open LUKS partition and map LUKS partition busy status
to encryption being open or closed.
Bug 760080 - Implement read-only LUKS support
Load basic details of active Device-mapper encryption mappings from the
kernel. Use dmsetup active targets.
# cryptsetup luksFormat /dev/sdb5
# cryptsetup luksFormat /dev/sdb6
# cryptsetup luksOpen /dev/sdb6 sdb6_crypt
# ls -l /dev/mapper/sdb6_crypt /dev/dm-0
lrwxrwxrwx. 1 root root 7 Nov 15 09:03 /dev/mapper/sdb6_crypt -> ../dm-0
brw-rw----. 1 root disk 253, 0 Nov 15 09:03 /dev/dm-0
# ls -l /dev/sdb6
brw-rw----. 1 root disk 8, 22 Nov 15 09:02 /dev/sdb6
# dmsetup table --target crypt
sdb6_crypt: 0 1044480 crypt aes-cbc-essiv:sha256 0000000000000000000000000000000000000000000000000000000000000000 0 8:22 4096
So far just load the mapping name and underlying block device reference
(path or major, minor pair).
Note that all supported kernels appear to report the underlying block
device as major, minor pair in the dmsetup output. Underlying block
device paths are added to the cache when found during a search to avoid
stat(2) call on subsequent searches for the same path.
Prints debugging to show results, like this:
# ./gpartedbin
======================
libparted : 2.4
======================
DEBUG: /dev/sdb5: LUKS closed
DEBUG: /dev/sdb6: LUKS open mapping /dev/mapper/sdb6_crypt
Bug 760080 - Implement read-only LUKS support
Renamed from DEV_MAP_PATH to DEV_MAPPER_PATH. Moved so that the
constant is logically intended for use outside of the DMRaid class.
Also specifically make the string constant have external linkage, rather
than the default internal (static) linkage for constants, so that there
is only one copy of the variable in the program, rather than one copy in
each compilation unit which included DMRaid.h. Namely DMRaid.cc and
GParted_Core.cc.
References:
[1] Proper way to do const std::string in a header file?
http://stackoverflow.com/questions/10201880/proper-way-to-do-const-stdstring-in-a-header-file
[2] What is external linkage and internal linkage in C++
http://stackoverflow.com/questions/1358400/what-is-external-linkage-and-internal-linkage-in-c/1358796#1358796
Bug 760080 - Implement read-only LUKS support
History:
1) The constructor was added by commit:
6d8b169e73
2006-03-14 21:37:47
changed the way devices and partitions store their devicepaths. Instead of
2) Removed from most of the file system specific ::Copy() methods by
commit:
ad9f2126e7
2006-03-19 15:30:20
fixed issues with copying (see also #335004) cleanups + added FIXME added
3) Removed from GParted_Core::copy() method by commit:
7bb7e8a84f
2006-05-23 22:17:34
Use ped_device_read and ped_device_write instead of 'dd' to copy
4) Finally removed from the last place in xfs::Copy() method by commit:
e414b71b73
2012-01-11 19:49:13
Update xfs resize and copy to use new helper functions
The Partition(path) constructor is no longer used. Remove.
The sector_size parameter is unnecessary as the value can be retrieved
from the sector size of the selected Partition object on which the
create new, copy & paste or resize/move operation is being performed.
For the create new and resize/move operations it is trivial as the
existing unallocated or in use Partition object on which the operation
is being perform already contains the correct sector size. For the copy
& paste operation, which can copy across disk devices of different
sector sizes, we merely have to use the sector size of the existing
selected (destination) Partition object rather than copied (source)
Partition object. Hence these relevant lines in the new code:
Dialog_Partition_Copy::set_data(selected_partition, copied_partition)
new_partition = copied_partition.clone();
...
new_partition->sector_size = selected_partition.sector_size;
The expressions used in the call to Set() were comparing
lp_partition->type to 0 for the type parameter and passing it as a bool
for the inside_extended parameter. Libparted lp_partition->type is
actually an enumeration. The code was only working because of the
specific values assigned to the symbolic names, PED_PARTITION_NORMAL = 0
and PED_PARTITION_EXTENDED is non-zero (true).
Make the code use the symbolic names and not depend on the actual
enumeration values, which should be considered changeable and private to
libparted.
When displaying an unallocated partition
Win_GParted::set_valid_operations() calls GParted_Core::get_fs() with
parameter FS_UNALLOCATED.
Before this change, get_fs() would fail to find file system capabilities
set for FS_UNALLOCATED and construct a not supported capabilities set
and return that.
Afterwards, find_supported_filesystems() creates a not supported
capabilities set from the NULL pointer for FS_UNALLOCATED and adds this
entry into the FILESYSTEMS vector. Then get_fs() finds that not
supported capabilities set for FS_UNALLOCATED in the FILESYSTEMS vector
and returns that.
This makes no functional difference. It just seems right as other
unsupported but used file system types have entries in FILESYSTEM_MAP.
The struct FS constructor initialised every member *except* filesystem
and busy. Then in *most* cases after declaring struct FS, assignments
followed like this:
FS fs;
fs.filesystem = FS_BTRFS;
fs.busy = FS::GPARTED;
But member busy wasn't always initialised.
Add initialisation of members filesystem and busy to the struct FS
constructor. Specify optional parameter to the constructor to set the
filesystem member, or when left off filesystem is initialised to
FS_UNKNOWN.
get_fs() used to work by (1) returning the supported capabilities of the
requested file system found in the FILESYSTEMS vector; (2) if not found
return the supported capabilities for file system FS_UNKNOWN; and (3)
if that wasn't found either, create a not supported capabilities set for
FS_UNKNOWN and return that.
This is more complicated that required. Also the not supported
capabilities set, as created by struct FS() constructor, is the same as
that created in file_supported_filesystems() local variable fs_notsupp.
Simplify get_fs() just using a single not found code path returning a
not supported capabilities set.
Final step for full polymorphic handling of Partition objects is to
implement a virtual copy constructor. C++ doesn't directly support
virtual copy constructors, so instead use the virtual copy constructor
idiom [1]. (Just a virtual method called clone() which is implemented
in every polymorphic class and creates a clone of the current object and
returns a pointer to it).
Then replace all calls to the (monomorphic) Partition object copy
constructor throughout the code, except in the clone() implementation
itself, with calls to the new virtual clone() method "virtual copy
constructor".
Also have to make the Partition destructor virtual too [2][3] so that
the derived class destructor is called when deleting using a base class
pointer. C++ supports this directly.
[1] Wikibooks: More C++ Idioms / Virtual Constructor
https://en.wikibooks.org/wiki/More_C%2B%2B_Idioms/Virtual_Constructor
[2] When to use virtual destructors?
http://stackoverflow.com/questions/461203/when-to-use-virtual-destructors
[3] Virtuality
Guideline #4: A base class destructor should be either public and
virtual, or protected and nonvirtual
http://www.gotw.ca/publications/mill18.htm
Bug 759726 - Implement Partition object polymorphism
SQUASH: When first using pointers to Partition and calling delete
Copy assignment of Partition objects is now only performed in a few
places in the Operation and OperationResizeMove classes when updating
the displayed PartitionVector. (From Refresh_Visual() when each
operation is visually applied to the display_partitions vector; the
new_partition from the operation is copy assigned over the top of the
relevant existing partition in the display_partitions vector).
In general polymorphic copy assignment is complicated [1], and is now
unnecessary given the above limited use. All that is needed is a way to
polymorphically replace one Partition object with another in a
PartitionVector.
First, prevent further use of Partition object copy assignment by
providing a private declaration and no implementation, so the compiler
enforces this. Second implement and use PartitionVector method
replace_at() which replaces a pointer to one Partition object with
another at the specified index in the PartitionVector.
[1] The Assignment Operator Revisited
[Section:] Virtual assignment
http://icu-project.org/docs/papers/cpp_report/the_assignment_operator_revisited.html
Bug 759726 - Implement Partition object polymorphism
Now use a pointer to the Partition object in Dialog_Base_Partition class
and derived classes, Dialog_Partition_{Copy,New,Resize_Move}. This is
equivalent to how the Partition objects are managed in the Operation and
derived classes.
The Partition object is allocated and copy constructed in each derived
classes' set_data() method, called from each constructor and deallocated
in the destructors. Considering the remaining Big 3, these classes are
never copy constructed or copy assigned so provide private definitions
and no implementations so the compiler enforces this.
Bug 759726 - Implement Partition object polymorphism
The code in on_view_clicked() copy constructed a Partition object and
then in the following 3 lines only read a couple of public member
variables from the new copy.
Making a copy of the partition is unnecessary. Change to just creating
a constant reference to the Partition instead.
(It would also be an impediment to polymorphically using Partition
objects, except for the fact that gpart doesn't recognise LUKS
signatures so will never have to create a PartitionLUKS object).
Bug 759726 - Implement Partition object polymorphism
A number of methods in GParted_Core and Win_GParted were using local
Partition objects. Change them into pointers so that Partition object
polymorphism can be implemented.
Bug 759726 - Implement Partition object polymorphism
Change Win_GParted::copied_partition from Partition object which is
copied by value into a pointer to a Partition object object which is
allocated, copy constructed and deleted. Required as part of the
polymorphic implementation of Partitions.
As before when managing the lifetime of pointers to objects in a class
the Big 3 of destructor, copy constructor and copy assignment operator
need to be considered. A destructor is added to finally delete
copied_partition. A single Win_GParted object is only ever created and
destroyed in main(). The class is never copy constructed or copy
assigned. Make the compiler enforce this with private declarations and
no implementations.
Bug 759726 - Implement Partition object polymorphism
Operation classes now internally use pointers to Partition objects and
take on management of their lifetimes. As before, with the
PartitionVector class, when storing pointers in a class the Big 3 of
destructor, copy constructor and copy assignment operator also have to
be considered.
First, all the Partition objects are allocated in the derived Operation*
class parameterised constructors and freed in the associated
destructors. However the Operation classes are never copy constructed
or copy assigned; they are only ever created and destroyed. Only
pointers to the derived Operations are copied into the vector of pending
operations. Therefore the copy construtor and copy assignment operator
aren't needed. To enforce this provide inaccessible private
declarations without any implementation so that the compiler will
enforce this [1][2].
This example code fragment:
1 OperationCheck o1( device, partition );
2 OperationCheck o2 = o1;
3 o2 = o1;
Does these OperationCheck calls:
1 Implemented parameterised construtor,
2 Disallowed copy constructor,
3 Disallowed copy assignment
Trying to compile the above code would fail with errors like these:
../include/OperationCheck.h: In member function 'void GParted::Win_GParted::activate_check()':
../include/OperationCheck.h:36:2: error: 'GParted::OperationCheck::OperationCheck(const GParted::OperationCheck&)' is private
OperationCheck( const OperationCheck & src ); // Not implemented copy constructor
^
test.cc:2:21: error: within this context
OperationCheck o2 = o1;
^
../include/OperationCheck.h:37:19: error: 'GParted::OperationCheck& GParted::OperationCheck::operator=(const GParted::OperationCheck&)' is private
OperationCheck & operator=( const OperationCheck & rhs ); // Not implemented copy assignment operator
^
test.cc:3:4: error: within this context
o2 = o1;
^
[1] Disable copy constructor
http://stackoverflow.com/questions/6077143/disable-copy-constructor
[2] Disable compiler-generated copy-assignment operator [duplicate]
http://stackoverflow.com/questions/7823845/disable-compiler-generated-copy-assignment-operator
Bug 759726 - Implement Partition object polymorphism
The Operation classes contain partition objects which are copied by
value. Need to replace these with pointers to Partition objects instead
and manage their lifetimes so that they can be used polymorphically.
First step is to protect the partition members partition_new,
partition_original, and for OperationCopy class only, partition_copied
within the Operation classes and provide accessor methods.
get_partition_new() and get_partition_original() accessors are
implemented in the Operation base class so all derived classes get an
implementation. get_partition_new() is also virtual so that
OperationCheck and OperationDelete can override the implementation and
assert that they don't use partition_new. get_partition_copied() is
provided for the OperationCopy class only so can only be accessed via an
OperationCopy type variable.
Bug 759726 - Implement Partition object polymorphism
Remove PartitionVector push_back() and insert() methods which copy
construct Partitions objects into the vector. All the code has already
been changed to dynamically allocate Partition objects and use the
adoption variants of these methods named, push_back_adopt() and
insert_adopt(). Remove the no longer used methods.
Bug 759726 - Implement Partition object polymorphism
Replace all the current code which uses push_back() and insert() of a
local Partition object and gets it copy constructed into a
PartitionVector. Instead allocate a Partition object on the heap and
adopt a pointer into the PartitionVector using push_back_adopt() and
insert_adopt().
Bug 759726 - Implement Partition object polymorphism
GParted_Core and Operation classes both have an insert_unallocated()
method which do the same thing with very nearly identical code. Both
methods insert unallocated partitions into the vector of partitions
within the specified range of sectors to fill in any gaps larger than
1 MiB. The only difference was how the two methods got the device path;
the GParted_Core class method got it via a parameter and the Operation
class method got it by calling get_path() on its device member variable.
The GParted_Core insert_unallocated() method gets called during device
scanning and the Operation one gets called when constructing the visual
for a pending operation.
Consolidate down to a single insert_unallocated() implementation by
making the Operation class method call the GParted_Core class method.
Make the GParted_Core class method static and public so that it can be
called using the class name from outside the class.
Bug 759726 - Implement Partition object polymorphism
The current code uses push_back() and insert() to copy Partition objects
into the vector of pointers. This has a few issues:
1) Unnecessary copying of Partition objects;
2) Hides the nature of the PartitionVector class as a manager of
pointers to Partition objects by providing copy semantics to add
items. It is generally better to be explicit;
3) C++ doesn't provide polymorphic copy construction directly, but this
is easily worked around by following the Virtual Constructor idiom
[1], which would allow PartitionLUKS derived class objects to be
copied into the vector.
Add push_back_adopt() and insert_adopt() methods which add a pointer to
a Partition object into the PartitionVector adopting ownership.
[1] Wikibooks: More C++ Idioms / Virtual Constructor
https://en.wikibooks.org/wiki/More_C%2B%2B_Idioms/Virtual_Constructor
Bug 759726 - Implement Partition object polymorphism
The PartitionVector class is now internally using pointers to Partition
objects and taking on management of their lifetimes. It therefore has
to implement the Big 3: destructor, copy constructor and copy assignment
operator [1][2]. This is because the implicitly-defined copy
constructor and assignment operator perform memberwise "shallow copying"
and the destructor does nothing. This not correct for classes which
contain non-class types such as raw pointers.
The semantics of the interface still copies each Partition object into
the PartitionVector when they are added with push_back() and insert().
Note that a PartitionVector object is explicitly copy assigned in
Win_GParted::Refresh_Visual(). They are also implicitly copied when
(1) the implementing vector is resized larger to allow it to hold more
pointers to Partition objects than it previously had capacity for; and
(2) a Partition object is copied including the logicals PartitionVector
member.
[1] The rule of three/five/zero
http://en.cppreference.com/w/cpp/language/rule_of_three
[2] Rule of Three
https://en.wikipedia.org/wiki/Rule_of_three_%28C%2B%2B_programming%29
Bug 759726 - Implement Partition object polymorphism
Lots of files which use the Partition class relied on the declaration
being included via other header files. This is bad practice.
Add #include "Partition.h" into every file which uses the Partition
class which doesn't already include it. Header file #include guards are
specifically to allow this.
get_partitions() method was returning a vector of partitions. However
the calling code only needed to know whether any partitions were found
or not. Replace with found_partitions() method reporting the needed
boolean.
Now use of std::vector<Partition> partitions is hidden within the
Dialog_Rescue_Data class implementation.
Bug 759726 - Implement Partition object polymorphism
GParted was also displaying the GPT partition names as the file system
labels for some type of file systems.
Create 2 empty partitions on a GPT partitioned disk and name them like
this. Then create a hfsplus file system with an empty label. (Actually
single space character but blkid treats it as empty. Can't use GParted
for this because when no label is specified mkfs.hfsplus sets the label
to "untitled").
# sgdisk -p /dev/sdb
/dev/sdb: 4194304 sectors, 2.0 GiB
Logical sector size: 512 bytes
...
Number Start (sector) End (sector) Size Code Name
1 2048 526335 256.0 MiB 8300 empty partition
2 526336 1050623 256.0 MiB 8300 hfsplus partition
# mkfs.hfsplus -v " " /dev/sdb2
Even though only the GPT partition names are set to "SOMETHING
partition", GParted will display them as the file system labels too.
Also in the Information dialog for the empty partition a file system
UUID is displayed as well even though none exists.
Blkid output looks like this:
# blkid -V
blkid from util-linux 2.27.1 (libblkid 2.27.0, 02-Nov-2015)
# blkid | grep /dev/sdb
/dev/sdb1: PARTLABEL="empty partition" PARTUUID="bf3d2085-65b7-4ae6-97da-5ff968ad7d2c"
/dev/sdb2: UUID="2c893037-ff76-38f2-9158-2352ef5dc8de" TYPE="hfsplus" PARTLABEL="hfsplus partition" PARTUUID="457e9c2b-e4f2-4235-833b-28208592aaac"
With blkid from util-linux >= 2.22, released September 2012, it is
including additional PARTLABEL and PARTUUID name and value pairs for
GPT partitions [1]. The FS_Info module regular expressions used to
match the file system LABEL and UUID names also happen to match these
new PARTLABEL and PARTUUID names too. Hence this bug when GParted has
to fall back to using the FS_Info module to read the file system label,
when there is no working file system specific method. Effects: exfat,
f2fs, hfs, hfsplus, ufs, unknown.
Fix by requiring all the regular expressions used to search the blkid
output to also match the space character in front of the name.
[1] Util-linux 2.22 Release Notes
https://git.kernel.org/cgit/utils/util-linux/util-linux.git/tree/Documentation/releases/v2.22-ReleaseNotes?h=v2.22
Bug 759972 - GParted displays partition names also as file system labels
with new blkid for some file systems
In the UI new partitions were being named "unallocated" instead of
"New Partition #1", etc. Also deleting a new partition not yet created
deletes all new partitions from the operation list because it matches
by name only and they were all named "unallocated". Broken by this
recent commit:
762cd1094a
Return class member from Dialog_Partition_New::Get_New_Partition() (#757671)
Prior to this commit in the create new partition dialog code did these
relevant steps:
Dialog_Partition_New::Get_New_Partition()
Partition part_temp;
...
part_temp.Set(..., "New Partition #%1", ...);
Create local Partition object using default constructor which calls
Partition::Reset() and clears the paths vector. It then calls Set()
which appends the new name making the vector:
paths = ["New Partition #%1"]
After the above commit the code did these steps:
Dialog_Partition_New::Dialog_Partition_New(..., selected_partition, ...)
set_data(..., selected_partition, ...);
new_partition = selected_partition;
Dialog_Partition_New::Get_New_Partition(...)
new_partition.Set(..., "New Partition #%1", ...);
New_partition is copied from the selected unallocated partition in which
the new partition will be created. So new_partition is now named
"unallocated". Then the Set() call appends the new name making the
vector:
paths = ["unallocated", "New Partition #%1"]
As get_path() returns the first name in the paths vector the path name
changed from "New Partition #%1" to "unallocated" causing this bug.
Fix by resetting the new_partition object to clear all vestiges of it
being a copy of the selected unallocated partition, Reset() call, before
then calling Set(). This then appends the new name to an empty vector
making it contain just the required new name:
paths = ["New Partition #%1"]
Bug 759488 - Pending create partitions are all getting named
"unallocated"
Capture and parse the progress reports of ntfsresize and resize2fs and
update the dialog progress bar.
Bug 467925 - gparted: add progress bar during operation
Return newly constructed partition object by reference rather than by
copy from the Copy, Resize/Move and New dialog classes. This is another
case of stopping copying partition objects in preparation for using
polymorphic Partition objects. In C++ polymorphism has to use pass by
pointer and reference and not pass by value, copying, to avoid object
slicing.
The returned reference to the partition is only valid until the dialog
object containing the new_partition member is destroyed. This is okay
because in all three cases the returned referenced partition is copied
into a context with new lifetime expectations before the dialog object
is destroyed.
Case 1: GParted_Core::activate_paste()
Referenced new_partition is copied in the OperationCopy constructor
before the dialog object goes out of scope.
Operation * operation = new OperationCopy( ...,
dialog.Get_New_Partition( ... ),
... );
Case 2: GParted_Core::activate_new()
Referenced new_partition is copied in the OperationCreate
constructor before the dialog object goes out of scope.
Operation * operation = new OperationCreate( ...,
dialog.Get_New_Partition( ... ) );
Case 3: GParted_Core::activate_resize()
Temporary partition object is copied from the referenced
new_partition before the dialog object goes out of scope.
Partition part_temp = dialog.Get_New_Partition( ... );
Bug 757671 - Rework Dialog_Partition_New::Get_New_Partition() a bit
Replace the use of local Partition variable with class member in
preparation for Dialog_Partition_New::Get_New_Partition() being changed
to return the new partition object by reference instead of by value.
part_temp -> new_partition
Bug 757671 - Rework Dialog_Partition_New::Get_New_Partition() a bit
When creating a new extended partition, the unallocated space within it
was being created before adjusting the partition boundaries for
alignment reasons. This must be wrong. Move creation of the
unallocated space to after adjusting the partition boundaries for
alignment reasons. First introduced by this commit:
a30f991ca5
Fix size reduced by 1 MiB when created after cylinder aligned partition
Also added a big FIXME comment explaining how further adjustments are
still made by snap_to_alignment() to the partition boundaries including
a test case where this too late adjustment causes overlapping boundaries
and apply to fail.
Bug 757671 - Rework Dialog_Partition_New::Get_New_Partition() a bit
This is just to make the parameter name in the Dialog_Partition_New
constructor and set_data() method match the name of the equivalent
parameter in the Dialog_Partition_Copy and Dialog_Partition_Resize_Move
classes. (All three classes inherit from Dialog_Base_Partition and have
similar interfaces).
Bug 757671 - Rework Dialog_Partition_New::Get_New_Partition() a bit
Blkid recognises many more file system types and RAID member signatures
than libparted. GParted already uses blkid detection instead of or
before libparted for whole disk devices [1] and for ext4 detection [2]
(only required with libparted < 1.9.0). Also GParted could only use
blkid detection on non-512 byte sector devices [3] before libparted was
fixed in version 3.2 [4]. Blkid was documented as a mandatory
requirement from GParted 0.24.0 [5].
Util-linux package, of which blkid command is a part, is a core piece of
Linux software which is very actively maintained and used by lots of
other packages. Parted package is much less active and has added
detection of fewer file systems and doesn't recognise any RAID members.
In cases of multiple signatures within a partition blkid and libparted
can report different results leading to confusion and issues for
GParted. This was the primary reason for bug 688882 "Improve clearing
of file system signatures" and a number of other changes to GParted.
Also as the mount command links with libblkid it uses it's detection
when telling the kernel the type of a file system to be mounted.
There aren't any current issues with GParted's file system detection but
given the above argument, switch to using blkid before libparted for
file system detection. Only falling back to libparted when blkid
doesn't report a result, notably for extended partitions. Order of
information sources for detection is now:
1) mdadm (for SWRaid members)
2) blkid
3) libparted
4) GParted internal code
References:
[1] f8faee6377
Avoid whole disk FAT being detected as MSDOS partition table (#743181)
[2] 533eb1bc03
Added support for ext4 file systems
[3] 9e5e9f5627
Enhance file system detection to use FS_Info method - blkid
[4] http://git.savannah.gnu.org/cgit/parted.git/commit/?id=80678bdd957cf49a9ccfc8b88ba3fb8b4c63fc12
Fix filesystem detection on non 512 byte sectors
[5] 749a249571
Document blkid command as a mandatory requirement (#753436)
Bug 757781 - Always use blkid file system detection before libparted
The GParted_Core code only interacts with derived Operation* objects
through the Operation base class interface and in one case the
OperationCopy class. Therefore include Operation.h and OperationCopy.h
headers and no others.
ZFS labels were not cleared by GParted when clearing old file system
signatures.
# wget https://git.kernel.org/cgit/utils/util-linux/util-linux.git/plain/tests/ts/blkid/images-fs/zfs.img.bz2
# bzip2 -dc zfs.img.bz2 > /dev/sdb1
[In GParted format to cleared /dev/sdb1]
# blkid /dev/sdb1
/dev/sdb1: LABEL="tank" UUID="1782036546311300980" UUID_SUB="13179280127379850514" TYPE="zfs_member"
Update to also zero all 4 ZFS labels.
NOTE:
GParted now writes a little over 1 MiB when clearing old file system
signatures. As this is performed in the main thread the UI is not able
to respond during this action. Testing this on a range of USB flash
keys and hard drives found the slowest normal time to write this was
0.25 seconds, with an occasional outlier up to 2.8 seconds from a USB
flash key. This is considered acceptable.
Following the previous commit "Add erasing of SWRaid metadata 0.90 and
1.0 super blocks (#756829)" signature zeroing specified to write 4 KiB
of zeros at position end - 64 KiB, aligned to 64 KiB. Example operation
details from formatting a 1 GiB partition to cleared:
Format /dev/sdb8 as cleared
+ calibrate /dev/sdb8
+ clear old file system signatures in /dev/sdb8
+ write 68.00 KiB of zeros as byte offset 0
+ wite 4.00 KiB of zeros at byte offset 67108864
+ wite 64.00 KiB of zeros at byte offset 1073676288
+ write 8.00 KiB of zeros at byte offset 1073733632
+ flush operating system cache of /dev/sdb
However it actually wrote 64 KiB. This is because the rounding /
alignment was also applied to the zeroing length. Before this commit
rounding / alignment was always less than or equal to the length so this
wasn't seen before. Instead just apply device sector size rounding up
to the length.
Bug 756829 - SWRaid member detection enhancements
The super blocks for Linux Software RAID arrays using metadata types
0.90 and 1.0 are stored at the end of the partition and not currently
cleared by GParted.
Create a SWRaid array, stop it and format it to cleared using GParted.
The signature remains.
# mdadm --create /dev/md1 --level=linear --raid-devices=1 --force --metadata=1.0 /dev/sdb1
# mdadm --stop /dev/md1
[In GParted format to cleared /dev/sdb1]
# blkid /dev/sdb1
/dev/sdb1: UUID="8ac947a7-063f-2266-5f2a-e5d178198139" UUID_SUB="49bd51d4-4c54-fb16-a45e-bd795f783f59" LABEL="rockover:1" TYPE="linux_raid_member"
As fixed in other cases before [1][2] it is necessary to clear all
signatures before formatting as a new file system to prevent recognition
issues. For example now format the partition as a FAT32 file system.
Now there are two signatures and libparted reports one type and blkid
reports another.
# mkdosfs -F 32 /dev/sdb1
# blkid /dev/sdb1
/dev/sdb1: UUID="8ac947a7-063f-2266-5f2a-e5d178198139" UUID_SUB="49bd51d4-4c54-fb16-a45e-bd795f783f59" LABEL="rockover:1" TYPE="linux_raid_member"
# parted /dev/sdb print
Model: ATA SAMSUNG SSD UM41 (scsi)
Disk /dev/sdb: 8012MB
Sector size (logical/physical): 512B/512B
Partition Table: msdos
Number Start End Size Type File system Flags
1 1049kB 538MB 537MB primary fat32
(Deliberately avoided btrfs, ext2/3/4 and xfs as recent versions of
their mkfs tools clear other signatures first for the same reason).
[1] Bug 688882 - Improve clearing of file system signatures
[2] 3c75f3f5b1
Use wipefs to clear old signatures before creating new file systems (#688882)
Update erase_filesystem_signatures() to also zero the necessary sectors
to clear SWRaid metadata 0.90 and 1.0 super blocks.
Bug 756829 - SWRaid member detection enhancements
If the installation is unusual / broken such that the mdadm command is
not found but there are active SWRaid arrays, provide a fallback with
some of the information. In this case populate the cache with details
only available from /proc/mdstat. Information will be limited to active
arrays only and their members. No UUIDs or labels. There will be no
information about inactive arrays and GParted will use it's normal
libparted and blkid identification for those devices and partitions.
As mdadm has gained the capability to manage Fake/BIOS RAID arrays they
also appear in /proc/mdstat when mdadm is used to start them. Enhance
the parser of /proc/mdstat to only extract information for SWRaid arrays
with recognised metadata versions.
Bug 756829 - SWRaid member detection enhancements
Automatically load the cache of SWRaid information for the first time if
any of the querying methods are called before the first explicit
load_cache() call. Means we can't accidentally use the class and
incorrectly find no SWRaid members when they do exist.
Bug 756829 - SWRaid member detection enhancements
Busy file systems are accessed via a mount point, LVM Physical Volumes
are activated via the Volume Group name and busy SWRaid members are
accessed via the array device, /dev entry. Therefore choose to show the
array device in the mount point field for busy SWRaid members.
The kernel device name for an SWRaid array (without leading "/dev/") is
the same as used in /proc/mdstat and /proc/partitions. Therefore the
array device (with leading "/dev/") displayed in GParted will match
between the mount point for busy SWRaid members and the array itself as
used in the device combo box.
# cat /proc/mdstat
Personalities : [raid1]
md1 : active raid1 sda1[2] sdb1[3]
524224 blocks super 1.0 [2/2] [UU]
...
# cat /proc/partitions
major minor #blocks name
8 0 33554432 sda
8 1 524288 sda1
...
8 16 33554432 sdb
8 17 524288 sdb1
...
9 1 524224 md1
...
Bug 756829 - SWRaid member detection enhancements
In cases where blkid wrongly reports a file system instead of an SWRaid
member (sometimes confused by metadata 0.90/1.0 mirror array or old
version not recognising SWRaid members), the UUID and label are
obviously wrong too. Therefore have to use the UUID and label returned
by the mdadm query command and never anything reported by blkid or any
file system specific command.
Example of blkid reporting the wrong type, UUID and label for /dev/sda1
and the correct values for /dev/sdb1:
# blkid | egrep 'sd[ab]1'
/dev/sda1: UUID="10ab5f7d-7d8a-4171-8b6a-5e973b402501" TYPE="ext4" LABEL="chimney-boot"
/dev/sdb1: UUID="15224a42-c25b-bcd9-15db-60004e5fe53a" UUID_SUB="0a095e45-9360-1b17-0ad1-1fe369e22b98" LABEL="chimney:1" TYPE="linux_raid_member"
# mdadm -E -s -v
ARRAY /dev/md/1 level=raid1 metadata=1.0 num-devices=2 UUID=15224a42:c25bbcd9:15db6000:4e5fe53a name=chimney:1
devices=/dev/sda1,/dev/sdb1
...
ARRAY /dev/md127 level=raid1 num-devices=2 UUID=8dc7483c:d74ee0a8:b6a8dc3c:a57e43f8
devices=/dev/sdb6,/dev/sda6
...
NOTES:
* In mdadm terminology the label is called the array name, hence name=
parameter for array md/1 in the above output.
* Metadata 0.90 arrays don't support naming, hence the missing name=
parameter for array md127 in the above output.
Bug 756829 - SWRaid member detection enhancements
Add active attribute to the cache of SWRaid members. Move parsing of
/proc/mdstat to discover busy SWRaid members into the cache loading
code. New parsing code is a little different because it is finding all
members of active arrays rather than determining if a specific member is
active.
Bug 756829 - SWRaid member detection enhancements
Detection of Linux SWRaid members currently fails in a number of cases:
1) Arrays which use metadata type 0.90 or 1.0 store the super block at
the end of the partition. So file system signatures in at least
linear and mirrored arrays occur at the same offsets in the
underlying partitions. As libparted only recognises file systems
this is what is detected, rather than an SWRaid member.
# mdadm -E -s -v
ARRAY /dev/md/1 level=raid1 metadata=1.0 num-devices=2 UUID=15224a42:c25bbcd9:15db6000:4e5fe53a name=chimney:1
devices=/dev/sda1,/dev/sdb1
...
# wipefs /dev/sda1
offset type
----------------------------------------------------------------
0x438 ext4 [filesystem]
LABEL: chimney-boot
UUID: 10ab5f7d-7d8a-4171-8b6a-5e973b402501
0x1fffe000 linux_raid_member [raid]
LABEL: chimney:1
UUID: 15224a42-c25b-bcd9-15db-60004e5fe53a
# parted /dev/sda print
Model: ATA VBOX HARDDISK (scsi)
Disk /dev/sda: 34.4GB
Sector size (logical/physical): 512B/512B
Partition Table: msdos
Number Start End Size Type File system Flags
1 1049kB 538MB 537MB primary ext4 boot, raid
...
2) Again with metadata type 0.90 or 1.0 arrays blkid may report the
contained file system instead of an SWRaid member. Have a single
example of this configuration with a mirrored array containing the
/boot file system. Blkid reports one member as ext4 and the other as
SWRaid!
# blkid | egrep 'sd[ab]1'
/dev/sda1: UUID="10ab5f7d-7d8a-4171-8b6a-5e973b402501" TYPE="ext4" LABEL="chimney-boot"
/dev/sdb1: UUID="15224a42-c25b-bcd9-15db-60004e5fe53a" UUID_SUB="0a095e45-9360-1b17-0ad1-1fe369e22b98" LABEL="chimney:1" TYPE="linux_raid_member"
Bypassing the blkid cache gets the correct result.
# blkid -c /dev/null /dev/sda1
/dev/sda1: UUID="15224a42-c25b-bcd9-15db-60004e5fe53a" UUID_SUB="d0460f90-d11a-e80a-ee1c-3d104dae7e5d" LABEL="chimney:1" TYPE="linux_raid_member"
However this can't be used because if a user has a floppy configured
in the BIOS but no floppy attached, GParted will wait for minutes as
the kernel tries to access non-existent hardware on behalf of the
blkid query. See commit:
18f863151c
Fix long scan problem when BIOS floppy setting incorrect
3) Old versions of blkid don't recognise SWRaid members at all so always
report the file system when found. Occurs with blkid v1.0 on
RedHat / CentOS 5.
The only way I can see how to fix all these cases is to use the mdadm
command to query the configured arrays. Then use this information for
first choice when detecting partition content, making the order: SWRaid
members, libparted, blkid and internal.
GParted shell wrapper already creates temporary blank udev rules to
prevent Linux Software RAID arrays being automatically started when
GParted refreshes its device information[1]. However an administrator
could manually stop or start arrays or change their configuration
between refreshes so GParted must load this information every refresh.
On my desktop with 4 internal hard drives and 3 testing Linux Software
RAID arrays, running mdadm adds between 0.20 and 0.30 seconds to the
device refresh time.
[1] a255abf343
Prevent GParted starting stopped Linux Software RAID arrays (#709640)
Bug 756829 - SWRaid member detection enhancements
When multiple devices are named on the command line and (after sorting
and removing duplicates) the device following a non-existent or invalid
one is not checked for usability [1]. In most situations this isn't
noticed as the device gets skipped at the "Searching ... partitions"
step instead. However as seen in bug 755495 and commit [2]
checking usability matters.
For example (on CentOS 6.5) a large sector disk device can be edited
when it follows a non-existent or invalid device named on the command
line:
# modprobe scsi_debug dev_size_mb=128 sector_size=4096
# fgrep scsi_debug /sys/block/*/device/model
/sys/block/sdd/device/model:scsi_debug
# ./gpartedbin /dev/does-not-exist /dev/sdd
======================
libparted : 2.1
======================
Could not stat device /dev/does-not-exist - No such file or directory.
Device /dev/sdd has a logical sector size of 4096. Not all parts of GNU Parted support this at the moment, and the working code is HIGHLY EXPERIMENTAL.
/dev/sdd: unrecognised disk label
When erasing a device don't skip confirming the following device is
usable.
[1] Usable device as implemented by useable_device()
Must not have a large sector size when GParted is built with an old
version of libparted which doesn't support large sector sizes and
must be able to read the first sector.
[2] 362b2db331
Check disks named on the command line are safe to use too (#755495)
Bug 756434 - GParted dumps core when passing non-existent or invalid
device on the command line
A non-existent or invalid disk device named on the command line caused
two libparted dialogs to be displayed repeatedly on every refresh. This
was because the device was only removed from the 'device_paths' vector
when it wasn't usable [1]; not when it didn't exist or was invalid, when
the libparted ped_device_get() call failed. Fix this.
[1] Usable device as implemented by useable_device()
Must not have a large sector size when GParted is built with an old
version of libparted which doesn't support large sector sizes and
must be able to read the first sector.
Bug 756434 - GParted dumps core when passing non-existent or invalid
device on the command line
Naming a non-existent or invalid disk device on the command line causes
GParted to dump core. Non-existent device looks like this:
# ./gpartedbin /dev/does-not-exist
======================
libparted : 2.4
======================
Could not stat device /dev/does-not-exist - No such file or directory.
Could not stat device /dev/does-not-exist - No such file or directory.
Backtrace has 10 calls on stack:
10: /lib64/libparted.so.0(ped_assert+0x31) [0x7fcfd10b3e61]
9: /lib64/libparted.so.0(+0x3fdfc12a0c) [0x7fcfd10b4a0c]
8: /home/mike/bin/gpartedbin-0.23.0-master-63-g23b5ba4() [0x455028]
7: /home/mike/bin/gpartedbin-0.23.0-master-63-g23b5ba4() [0x455090]
6: /home/mike/bin/gpartedbin-0.23.0-master-63-g23b5ba4() [0x4550d5]
5: /home/mike/bin/gpartedbin-0.23.0-master-63-g23b5ba4() [0x46723f]
4: /usr/lib64/libglibmm-2.4.so.1() [0x3ff5834a8d]
3: /lib64/libglib-2.0.so.0() [0x3fe086a374]
2: /lib64/libpthread.so.0() [0x3fdf407a51]
1: /lib64/libc.so.6(clone+0x6d) [0x3fdf0e893d]
Assertion (dev != NULL) at device.c:227 in function ped_device_open() failed.
Aborted (core dumped)
And with an invalid device the output looks like this:
# ./gpartedbin /dev/zero
======================
libparted : 2.4
======================
The device /dev/zero is so small that it cannot possibly store a file system or partition table. Perhaps you selected the wrong device?
Error fsyncing/closing /dev/zero: Invalid argument
The device /dev/zero is so small that it cannot possibly store a file system or partition table. Perhaps you selected the wrong device?
Error fsyncing/closing /dev/zero: Invalid argument
Backtrace has 10 calls on stack:
...
[Same as above]
Bisected the cause to this commit from 2015-03-09 in GParted 0.22.0. It
claimed to make no functional change. That turned out not to be true.
51ac4d5648
Split get_device_and_disk() into two (#743181)
Fix by simply adding the missed if condition in get_device().
Bug 756434 - GParted dumps core when passing non-existent or invalid
device on the command line
For probed DMRaid devices (when not using libparted DMRaid support)
GParted waits up to 1 second for udev to have processed all events and
created the /dev entries after starting each DMRaid array. This was
added by this commit from 2009-09-02:
e7352a5000
Ensure /dev file system device entries created before adding device
Do the same for devices named on the command line too.
Order named disk devices so that they appear in the combo box in the
same order which they would when probed. Also remove duplicates so that
the same disk devices aren't scanned multiple times and appear
duplicated in the UI.
Try this; it used to take ages to load and looked weird:
# gparted /dev/sda /dev/sdb /dev/sda /dev/sdb /dev/sda /dev/sdb
Bug 755495 - GParted allowing partitioning of large sector devices
specified on the command line, when built with old
libparted which doesn't support it
When probing for disk devices GParted ensures that libparted is capable
of handling the sector size safely and that it is a real disk before it
is shown in the UI. However when disk devices are named on the command
line none of these checks are performed.
Libparted versions before v2.2 can only safely handle a sector size of
512 bytes. Therefore on old distributions with libparted < v2.2 GParted
allows unsafe editing of disk devices with larger sector sizes when they
are named on the command line. Known to affect these distributions:
RedHat/CentOS 5 (parted 1.8.1)
RedHat/CentOS 6 (parted 2.1)
For example (on CentOS 6.5) large sector disk device is ignored when
probing:
# modprobe scsi_debug dev_size_mb=128 sector_size=4096
# fgrep scsi_debug /sys/block/*/device/model
/sys/block/sdd/device/model:scsi_debug
# gparted
======================
libparted : 2.1
======================
Device /dev/sdd has a logical sector size of 4096. Not all parts of
GNU Parted support this at the moment, and the working code is
HIGHLY EXPERIMENTAL.
Ignoring device /dev/sdd with logical sector size of 4096 bytes.
GParted requires libparted version 2.2 or higher to support devices
with sector sizes larger than 512 bytes.
However when the device is named it is not ignored and can be edited:
# gparted /dev/sdd
======================
libparted : 2.1
======================
Device /dev/sdd has a logical sector size of 4096. Not all parts of
GNU Parted support this at the moment, and the working code is
HIGHLY EXPERIMENTAL.
/dev/sdd: unrecognised disk label
Apply the same validity checks to disk devices named on the command line
as to probed ones.
Bug 755495 - GParted allowing partitioning of large sector devices
specified on the command line, when built with old
libparted which doesn't support it
Abstract code checking sector size and ensuring the first sector of a
candidate disk device can be read into new
GParted_Core::useable_device() method.
Bug 755495 - GParted allowing partitioning of large sector devices
specified on the command line, when built with old
libparted which doesn't support it
I missed another case of 'index' may be used uninitialised warning in
OperationDelete::apply_to_visual(). Indent a code block within an if
clause so that the compiler can confirm that the 'index' local variable
isn't used uninitialised. Prevent this compiler warning:
OperationDelete.cc: In member function 'virtual void GParted::OperationDelete::apply_to_visual(std::vector<GParted::Partition, std::allocator<GParted::Partition> >&)':
OperationDelete.cc:34: warning: 'index' may be used uninitialized in this function
Bug 755214 - Refactor operation merging
GParted waits forever when attempting to set a FAT16/32 file system
label which contains prohibited characters [1][2]. This is because
mlabel asks a question and is waiting for input. Force cancelling the
operation doesn't work either as GParted sends signal 2 (interrupt i.e.
[Ctrl-C]) but mtools commands specifically ignores this and a number of
other signals. Have to kill mlabel with signal 9 (kill) to regain
control of GParted.
Mlabel command with prohibited characters in the label:
# export MTOOLS_SKIP_CHECK=1
# mlabel ::"MYLABEL/ " -i /dev/sdb10
Long file name "MYLABEL/ " contains illegal character(s).
a)utorename A)utorename-all r)ename R)ename-all
s)kip S)kip-all q)uit (aArRsSq):
Remove prohibited characters from FAT16/32 file systems labels when
creating and labelling them. Also upper case the label to meet label
requirements [1][2]. This silently corrects the label and the actual
label applied will be displayed when GParted refreshes after applying
the operation.
[1] Microsoft TechNet: Label
https://technet.microsoft.com/en-us/library/bb490925.aspx
[2] Replicated in Wikikedia: label (command)
https://en.wikipedia.org/wiki/Label_%28command%29
Bug 755608 - Labeling fat16/fat32 partitions hangs if certain characters
included in label
These member variables store no Operation class information and were
being used as local variables. Replace with local variables.
Also indent a code block within an if clause so that the compiler can
confirm that the new local variable isn't used uninitialised. Prevents
this compiler warning:
OperationResizeMove.cc: In member function 'void GParted::OperationResizeMove::apply_normal_to_visual(std::vector<GParted::Partition, std::allocator<GParted::Partition> >&)':
OperationResizeMove.cc:125: warning: 'index' may be used uninitialized in this function
Bug 755214 - Refactor operation merging
Since this commit earlier in the patchset the second optional parameter
of method Win_GParted::Add_Operation() is no longer used. Remove it.
Replace open coded merge of resize/move into create operation
(#755214)
Bug 755214 - Refactor operation merging
This is the equivalent case fixed in the earlier commit, but now using
copy/paste to create the second new partition rather than plain new.
Fix visually re-apply create operation in create-create-grow-first
sequence (#755214)
Start with an existing partition as a copy source. Then this sequence
of operations will cause the copy partition to disappear from the disk
graphic:
1) create new #1,
2) copy existing / paste into unallocated leaving space preceding,
3) resize new #1 larger.
There are two different types of copy operation. The first is copy into
unallocated space creating a new partition which needs treating the same
as create new operation. The second is copy into existing partition
which needs treating the same as the other operations which don't change
the boundaries of the partition. Fix apply_to_visual() accordingly.
Bug 755214 - Refactor operation merging
Move the code from OperationCreate::apply_to_visual() into new method
Operation::insert_new() in the parent class. This is in preparation for
the following commit.
Bug 755214 - Refactor operation merging
The apply_to_visual() method for the change UUID, format, label file
system and name partition operations duplicated identical code. This
code was just substituting the partition in the disk graphic vector with
the new partition recorded in the operation, as none of these operations
change the partition boundaries. Move this duplicate code into the
parent class in new method Operation::substitute_new().
Bug 755214 - Refactor operation merging
After previous commit "Replace open coded merge of resize/move into
create operation (#755214)" the second created partition would disappear
from the disk graphic in the following sequence: create new #1, create
new #2 leaving space preceding, resize #1 larger. The create new #2
operation still existed and was shown in the operation list. It was
just that it disappeared from the disk graphic.
Remember that when each operation is created it records the partition,
or the unallocated space, to which the operation is applied at the time
the operation is created in the partition_original member variable. In
the above sequence the resize #1 larger operation was merged back into
the create new #1 operation. When visually re-applying the create
new #1 operation to the disk graphic, it left a smaller unallocated
partition following it. This was smaller than the unallocated partition
recorded in the create new #2 operation, hence it failed to visually
re-apply to the disk graphic.
The insight to fix this is that it doesn't matter what size the
unallocated space was when the create new operation was constructed. It
only matters that the new partition to be created fits in the available
unallocated space currently in the disk graphic.
Bug 755214 - Refactor operation merging
This information is already documented in the existing comments
associated with the calls to merge_operations() and assignments to the
mergetype variables. The table just summaries the rules together in one
place.
Bug 755214 - Refactor operation merging
For the case of resizing/moving a new, not yet created partition,
activate_resize() open coded the merge operation. Again this code has
existed in GParted since before version 0.0.5 and the current code
history in Git.
Replace the necessary code so that an explicit merge_operations() call
is used instead; along with the other case of resizing/moving an
existing partition.
NOTES:
This commit changes the merge direction. The old coded merged forward
by removing the old create operation and adding a new create operation
with the new size. This was bad because with multiple pending create
operations, each merged resize operation reordered those create
operations. Then when the operations were applied the partitions were
created and therefore numbered in a different order to that shown in
disk graphic.
The new code merges backwards by updating the initial create operation
with the new size. This maintains the create operation order so that
when applied the partitions are numbered in the same order as shown in
the disk graphic.
Bug 755214 - Refactor operation merging
For the case of formatting a new, not yet created partition,
activate_format() open coded the merge operation. This code has existed
in GParted since before version 0.0.5 and the current code history in
Git.
Replace the necessary code so that an explicit merge_operations() call
is used instead; along with the other case of formatting an existing
partition.
Bug 755214 - Refactor operation merging
Creation of the various operations involved various implicit rules about
how the different types of operations were merged in different cases.
This was open coded in each ::activate_*() method. Abstract this into
new merge_operations() method and make the merging rules explicitly
specified.
NOTE:
The removal of operation type checking in the MERGE_LAST_WITH_ANY cases
is not a problem because all the Operation*::merge_operations() methods
ensure the operation types match as part of the merge attempt.
Bug 755214 - Refactor operation merging
Rename Win_GParted::Merge_Operations() to merge_two_operations(). To
reflect what it does and in preparation for further refactoring of the
code.
Be more strict on the validation of the first and second indexes. The
first operation must also be before the second operation in the
operation[] vector. (It is actually a programming bug if first and
second fail validation. However so far g_assert() is only being used to
validate pointers, which if wrong would likely cause the program to
eventually crash when dereferenced later. In this case a bug would
merely cause the incorrectly specified pair of operations to not be
merged).
Move validate_display_partition_ptr() declaration in the header file to
be in the same ordering as it's definition in the source file.
Bug 755214 - Refactor operation merging
Win_GParted::Merge_Operations() method was modifying the internals of
Operation* objects; in particular the partition_new member variable.
This is breaking data hiding and encapsulation tenant of object oriented
programming.
Implement exactly the same operation merge semantics, but hide the
manipulation of the internals of the Operation* objects within the
Operation* classes themselves.
Bug 755214 - Refactor operation merging
... before refactoring the code.
See the commit message from 2011-10-05 for details of what operations,
available at that time, on the same partition can be merged and in what
cases:
b10349ae37
Merge overlapping operations (#438573)
Bug 755214 - Refactor operation merging
As previous commit, display_partitions is now a Win_GParted member
variable so checking for the existence of an extended partition can be
localised where it is used.
Remove index_extended member variable and localise the same checking in
activate_new().
Now that display_partitions is a Win_GParted member variable and
therefore available throughout the class, since commit [1], calculation
of primary_count can be localised in max_amount_prim_reached() where it
is used.
Implements a FIXME and removes primary_count as a member variable.
[1] 545b75d957
Move vector of partition objects to a Win_GParted class member (#750168)
Perform a copy, reformat source and paste sequence in GParted. When the
source is a primary partition everything works as expected, with the
newly pasted partition reflecting the reformatted source. However when
the source is a logical partition GParted thinks it is pasting the
original source, rather than the reformatted source. The same is also
true for other file system manipulation operations: resize, file system
label and new UUID. It is just that reformatting the source to a
different file system type is the most obvious in the UI and causes the
most significantly wrong actions to be performed.
For example start with an ext4 logical partition, select it for copy,
format it to xfs and paste into a new partition. GParted thinks the
second operation will create a copy of an ext4 file system instead of
the xfs file system. When applied the operation details are:
Format /dev/sdd5 as xfs
+ calibrate /dev/sdd5
+ clear old file system signatures in /dev/sdd5
+ set partition type on /dev/sdd5
+ create new xfs file system
+ mkfs.xfs -f -L "" /dev/sdd5
Copy /dev/sdd5 to /dev/sdd (start at 131.00 MiB)
+ calibrate /dev/sdd5
+ check file system on /dev/sdd5 for errors and (if possible) fix them
+ e2fsck -f -y -v -C 0 /dev/sdd5
e2fsck: Subperblock invalid, trying backup blocks...
Resize inode not valid. Recreate? yes
...
/dev/sdd5: ***** FILE SYSTEM WAS MODIFIED *****
+ create empty partition
+ set partition type on /dev/sdd6
new partition type: ext4
+ copy file system of /dev/sdd5 to /dev/sdd6
using internal algorithm
...
GParted formatted sdd5 to xfs, but then the copy step ran e2fsck and
managed to resurrect the ext4 file system and then performed a block
copy of it to partition sdd6. The copy step should have ran xfs_repair
and used xfsdump | xfsrestore to copy the xfs file system. Afterwards
sdd5 contains both xfs and ext4 signatures.
# wipefs /dev/sdd5
offset type
----------------------------------------------------------------
0x438 ext4 [filesystem]
UUID: f0ed4247-76db-4d93-b3bc-c7da4a70f95e
0x0 xfs [filesystem]
UUID: 1ac8e7c3-0311-4c64-8e4a-b715a23ea0bd
This has been broken at least as far back as GParted 0.1.0.
Fix by simply refreshing the copy source partition object when it is a
logical partition too, as well as when it is a primary partition.
Bug 754827 - Copy, reformat source and paste a logical partition thinks
it's pasting the original file system
Command exit status is a 1 byte value between 0 and 255. [1][2] However
at the Unix API level the value is encoded as documented in the
waitpid(2) manual page. This is true for the Glib API too. [3] This is
why, for example, the comment in ext2::check_repair() reported receiving
undocumented exit status 256. It was actually receiving exit status 1
encoded as per the waitpid(2) method.
Add shell style exit status decoding [2] to execution of all external
commands. Return value from Utils::execute_command() and
FileSystem::execute_command() functions are now:
0 - 125 - Exit status from the command
126 - Error executing the command
127 - Command not found
128+N - Command terminated by signal N
255 - Unexpected waitpid(2) condition
Also adjust checking of the returned statuses as necessary.
[1] Advanced Bash-Scripting Guide: Appendix D. Exit Codes With Special
Meanings
http://www.linuxtopia.org/online_books/advanced_bash_scripting_guide/exitcodes.html
[2] Quote from the bash(1) manual page:
EXIT STATUS
... Exit statuses fall between 0 and 255, though as
explained below, the shell may use values above 125
specially. ...
... When a command terminates on a fatal signal N, bash uses
the value of 128+N as the exit status.
If a command is not found, the child process created to
execute it returns a status of 127. If a command is found
but is not executable, the return status is 126.
[3] Quote from the Glib Reference Manual, Spawning Processes section,
for function g_spawn_check_exit_status():
https://developer.gnome.org/glib/stable/glib-Spawning-Processes.html#g-spawn-check-exit-status
The g_spawn_sync() and g_child_watch_add() family of APIs return
an exit status for subprocesses encoded in a platform-specific
way. On Unix, this is guaranteed to be in the same format
waitpid() returns, ...
Bug 754684 - Updates to FileSystem:: and Utils::execute_command()
functions
Replace open coding of the creation of the operation details for the
mlabel command used to set the label and UUID with calls to
FileSystem::execute_command() which will do it all. This also results
in the commands getting a time and check mark displayed in the operation
details.
Bug 754684 - Updates to FileSystem:: and Utils::execute_command()
functions
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] 52a2a9b00a
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] 86111fe12a
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
Change the two optional boolean parameters into a single optional flags
parameter which uses symbolically defined names. Makes reading the
execute_command() calls much easier to understand. (Implemented as bit
field using the same technique as used for Glib::SpawnFlags [1]).
This changes the calls thus:
execute_command(cmd, od) -> (cmd, od)
execute_command(cmd, od, false) -> (cmd, od, EXEC_NONE) // [2]
execute_command(cmd, od, true ) -> (cmd, od, EXEC_CHECK_STATUS)
execute_command(cmd, od, false, true) -> (cmd, od, EXEC_CANCEL_SAFE)
execute_command(cmd, od, true , true) ->
(cmd, od, EXEC_CHECK_STATUS|EXEC_CANCEL_SAFE)
[1] SpawnFlags bitwise operators in
/usr/include/glibmm-2.4/glibmm/spawn.h.
[2] False and EXEC_NONE are the default values for the optional third
parameter before and after this change respectively and both mean
the same. This is being used in btrfs::resize() and being kept for
now despite it being the default.
Bug 754684 - Updates to FileSystem:: and Utils::execute_command()
functions
Add a pattern to recognise Non-Volatile Memory Express devices as valid
devices to work with. Devices are named by the Linux kernel device
driver like /dev/nvme0n1 [1] with partitions named like /dev/nvme0n1p1
[2].
[1] linux 3.3 drivers/block/nvme.c nvme_alloc_ns()
https://git.kernel.org/cgit/linux/kernel/git/torvalds/linux.git/tree/drivers/block/nvme.c?id=v3.3#n1351
[2] Contents of /proc/partitions for a partitioned NVME device
$ grep nvme /proc/partitions
259 0 390711384 nvme0n1
259 1 977 nvme0n1p1
259 2 31250000 nvme0n1p2
259 3 328209496 nvme0n1p3
259 4 31249408 nvme0n1p4
Bug 755022 - gparted doesn't recognize nvme devices
The ntfs-3g package previously provided the FUSE based NTFS driver to
mount the file system and ntfsprogs provided the user space tools. In
April 2011 the packages have merged [1] forming ntfs-3g_ntfsprogs. Arch
Linux / Debian / Slackware / Ubuntu now just have an ntfs-3g package
with everything; where as CentOS / Fedora / openSUSE are sticking with
the original two package names. Reverse the order of the needed
packages to:
ntfs-3g / ntfsprogs
[1] Release: NTFS-3G + NTFSPROGS 2011.4.12
http://www.tuxera.com/release-ntfs-3g-ntfsprogs-2011-4-12/
For reiserfs the upstream package is named reiserfsprogs. Arch Linux /
Debian / Slackware / Ubuntu use this name; but CentOS / Fedora name it
reiserfs-utils and openSUSE names it just reiserfs. Update the README
file with all 3 package names.
reiserfsprogs / reiserfs-utils / reiserfs
In the File System Support dialog just use the first 2 package names as
we don't want to make the dialog too wide with all 3 names and hopefully
on openSUSE it is more obvious that the reiserfs package is needed to
support the reiserfs file system.
NOTE:
Again this slightly increases the width of the File System Support
dialog on my CentOS 6 desktop with default fonts, now from 676 to 707
pixels. Again still well within the 800 wide target and still narrower
than the main window.
Bug 753436 - Update documentation of GParted software dependencies
In Fedora bug report:
Bug 1176108 - Warning shown on BTRFS partition because of missing btrfs-tools package
https://bugzilla.redhat.com/show_bug.cgi?id=1176108#c0
The user said:
However there is no btrfs-tools package in the standard Fedora repo.
There is a btrfs-progs package, which is already installed. It's
unclear whether this is a real error or simply a mismatched package
name.
The upstream software is named btrfs-progs. Arch Linux / CentOS /
Fedora / Slackware use the upstream name. Debian / Ubuntu name it
btrfs-tools and openSUSE calls it btrfsprogs (no dash).
Rename the needed software to:
btrfs-progs / btrfs-tools
Upstream name first separated by slash from alternative names
distributions use.
NOTE:
This slightly increases the width of the File System Support dialog on
my CentOS 6 desktop with default fonts, from 655 to 676 pixels. Still
well within the 800 wide target and still narrower that the main window.
Bug 753436 - Update documentation of GParted software dependencies
This message would be displayed as part of the details for an operation
to create or format a partition as LVM2 PV on a disk using partition
table types dvh or pc98, which don't have an lvm flag.
v Format /dev/sdb1 as lvm2 pv
> calibrate /dev/sdb1
> clear old file system signatures in /dev/sdb1
> set partition type on /dev/sdb1
Skip setting unsupported partition flag: lvm
> create new lvm2 pv file system
Translators found this message difficult to translate, as reported in
bug 752901 - Add translator comment or fix string. It is also only
standard practice to set the lvm flag on partitions containing LVM2 PVs,
and not required. In hindsight reporting that an operation was skipped,
when the operation is not a necessity, is probably bad practice as it
could lead to uncertainty on behalf of the user and questions as to why
the flag isn't supported. Just remove the message.
Correct the colour name comment for NILFS2.
Colour for LVM2 PV was a Medium Brown. This is close to Face Skin Dark
from the GNOME colour palette. Use this instead.
Make colour for ReFS a bit darker so it is more distinct from the colour
for NTFS.
Add translation comments to improve the clarity of some translatable
text strings regarding setting partition flags.
Bug 752901 - Add translator comment or fix string
Opening the Resize/Move dialog on a logical partition causes GParted to
crash. This crash affects current GParted GIT HEAD, but does not affect
GParted 0.22.0. Git bisect identifies that it was broken with the
following commit:
Remove Set_Data() from the copy, resize/move and new dialog class APIs
7a4a375ed6
The problem was trying to treat the reference display_partitions_ref
like a pointer, and in particular on line 1732 trying to make it refer
to the a different vector of partitions, .logicals sub-vector.
1721 void Win_GParted::activate_resize()
1722 {
...
1726 std::vector<Partition> & display_partitions_ref = display_partitions;
1727 if ( selected_partition_ptr->type == TYPE_LOGICAL )
1728 {
1729 unsigned int ext = 0 ;
1730 while ( ext < display_partitions.size() && display_partitions[ext].type != TYPE_EXTENDED )
1731 ext++;
* 1732 display_partitions_ref = display_partitions[ext].logicals;
1733 }
1734
1735 Dialog_Partition_Resize_Move dialog( gparted_core.get_fs( selected_partition_ptr->filesystem ),
1736 *selected_partition_ptr,
1737 display_partitions_ref );
What was actually happening was that the .logicals sub-vector was being
copied, replacing the display_partitions vector and freeing the original
sub-vector. This left selected_partition_ptr pointing to the original
memory where the selected partition use to exist in the .logicals
sub-vector. At some point in the Dialog_Partition_Resize_Move class
*selected_partition_ptr was referenced, accessing the freed memory.
Crash soon followed.
Fix by using a pointer instead of a reference, which can be assigned to
point to a different object.
Bug 752587 - GParted crashing when opening Resize/Move dialog on
logical partition
Since GParted commit 52a2a9b "Reduce threading (#685740)", released in
GParted 0.15.0, application of operations occurs in the main thread
running the UI, therefore long running libparted actions such as
resizing a FAT16 or FAT32 file system hang the UI for as long as it take
to complete the operation.
https://git.gnome.org/browse/gparted/commit/?id=52a2a9b00a32996921ace055e71d0e09fb33c5fe
Though this problem exists for all libparted actions, it is particularly
noticeable when performing a large resize of fat16/fat32/hfs/hfs+ file
systems.
To address this significant cause of an unresponsive GUI, this
enhancement adds threading to the libparted ped_file_system_resize
function call.
Bug 737022 - UI hangs while running libparted operations such as
FAT16/FAT32 resizing
GParted was also searching the PATH for the availability of the udevadm
and udevsettle commands for every device with a busy partition during a
refresh and for every applied operation effecting a partition table. As
with hdparm previously this was wasteful.
Again, remember the result of searching the PATH at startup and refresh
when clicking on the [Rescan For Supported Actions] button in the File
System Support dialog.
Previously on every refresh for every device, GParted was searching the
PATH to discover if the hdparm command existed. Stracing GParted showed
that calling Glib::find_program_in_path("hdparm") made the following OS
calls:
access("/usr/lib64/qt-3.3/bin/hdparm", X_OK) = -1 ENOENT (No such file or directory)
access("/usr/local/sbin/hdparm", X_OK) = -1 ENOENT (No such file or directory)
access("/usr/local/bin/hdparm", X_OK) = -1 ENOENT (No such file or directory)
access("/sbin/hdparm", X_OK) = 0
getuid() = 0
stat("/sbin/hdparm", {st_mode=S_IFREG|0755, st_size=137, ...}) = 0
stat("/sbin/hdparm", {st_mode=S_IFREG|0755, st_size=137, ...}) = 0
The Linux VFS is very fast but repeatedly doing this is wasteful.
Remember the result of searching the PATH for the hdparm command at
startup and refresh this when the [Rescan For Supported Actions] button
is pressed in the File System Support dialog. This is the same as
GParted already does for file system specific commands and their
capabilities.
Bug 751251 - Show serial number in device information
With a Kobo Touch eReader connected via USB, GParted would hang when
scanning the device with this error written to the terminal:
$ sudo src/gpartedbin
======================
libparted : 2.3
======================
(gpartedbin:10261): glibmm-CRITICAL **:
unhandled exception (type Glib::Error) in signal handler:
domain: g_convert_error
code : 1
what : Invalid byte sequence in conversion input
The hdparm command was printing binary data as the serial number.
Fragment of the 'hdparm -I /dev/sdf' output:
# hdparm -I /dev/sdf
/dev/sdf:
SG_IO: bad/missing sense data, sb[]: 70 00 05 00 00 00 00 0a 00 00 00 00 24 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
ATAPI Optical card reader/writer, with non-removable media
Model Number: {BINARY_DATA}
Serial Number: {BINARY_DATA}
Firmware Revision: {BINARY_DATA}
GParted reads command output using the Glib::IOChannel class. However
by default an IOChannel performs character set conversion on the data it
reads, so when it came across an invalid byte sequence in the binary
data the above exception was raised and the IOChannel::read() method
never returned. Hence GParted became stuck reportedly scanning the
same device forever. Code fragment:
src/PipeCapture.cc
49 bool PipeCapture::OnReadable( Glib::IOCondition condition )
50 {
...
58 Glib::ustring str;
>> 59 Glib::IOStatus status = channel->read( str, 512 );
60 if (status == Glib::IO_STATUS_NORMAL)
61 {
62 for( Glib::ustring::iterator s = str.begin(); s != str.end(); s++ )
Quote from the IOChannel class reference:
https://developer.gnome.org/glibmm/stable/classGlib_1_1IOChannel.html
Note that IOChannels implement an automatic implicit character set
conversion to the data stream, and usually will not pass by default
binary data unchanged. To set the encoding of the channel, use
e.g. set_encoding("ISO-8859-15"). To set the channel to no encoding,
use set_encoding() without any arguments.
Fix by disabling the automatic character set conversion in the IOChannel
used to read output from executed commands.
Bug 751251 - Show serial number in device information
Run "hdparm -I /dev/DISK" to get the hard drive serial number of
every device which has one and display it in the Device Information.
The displayed value can either be the actual serial number, "none" or
blank. "none" means the device doesn't have a hard drive serial number,
such as for Linux software RAID arrays, BIOS fake RAID arrays or USB
flash drives. Blank means something went wrong getting the serial
number. Either it couldn't be found in the hdparm output or the hdparm
command wasn't installed.
Example real hard drive:
# hdparm -I /dev/sda
...
ATA device, with non-removable media
Model Number: SAMSUNG HM500JI
Serial Number: S1WFJDSZ123732
...
Example Linux software RAID array:
# hdparm -I /dev/md127
/dev/md127:
HDIO_DRIVE_CMD(identify) failed: Inappropriate ioctl for device
On my desktop with 4 internal hard drives 2 Linux software RAID arrays
on those hard drives, 2 USB flash drives and 1 USB hard drive attached,
running hdparm 9 times added 0.07 seconds to the device refresh time.
Bug 751251 - Show serial number in device information
Btrfs-progs 4.1, released June 2015, includes support for changing the
UUID of a btrfs file system using the btrfstune command. Check for
availability by looking for the -u option in the btrfstune help output.
Use btrfstune like this:
# umount /dev/sdb1
# btrfstune -f -u /dev/sdb1
Current fsid: e7ad5dba-d721-4f99-990b-1ba2901c8ad2
New fsid: 231563d9-e173-410d-b1da-d34c4319a423
Set superblock flag CHANGING_FSID
Change fsid in extents
Change fsid on devices
Clear superblock flag CHANGING_FSID
Fsid change finished
# echo $?
0
Bug 751337 - btrfstune in btrfs-progs 4.1 supports changing the file
system UUID
Explain why the implementation uses a clear_cache() call, rather than a
straight load_cache() call. This commit from 2014-02-17 implemented
incremental loading of the btrfs device cache:
76e64f2905
Detect busy status of multi-device btrfs file systems (#723842)
The lvm query commands were always run and the cache loaded even if
GParted, actually blkid, didn't identify any LVM2 PVs. (GParted uses
libparted and blkid to identify partition content and the lvm commands
to provide the needed configuration details).
Now implement complete lazy initialization of the cache. Never force
loading of the cache. The cache is only loaded when the first value is
accessed from it. When there are no LVM2 PVs, the cache is never
queried, so never loaded. All the needed infrastructure for delayed
loading was previously added by this commit from 2011-12-11:
ff8ad04120
Lazy initialize the cache from querying LVM2 PVs (#160787)
Every public member function which access values from the cache already
calls initialize_if_required(). Just need to replace force loading of
the cache with a function which just clears the cache.
On my desktop, only when there are no LVM2 PVs, not loading the cache
and therefore not executing these external commands in
load_lvm2_pv_info_cache() saves 1.0 seconds of the 3.7 seconds it takes
to perform the a refresh in GParted:
lvm vgscan
lvm pvs ... -o pv_name,...
lvm pvs ... -o vg_name,...
Bug 750582 - Refactor the LVM2_PV_Info module object interface and
internal cache representation
GParted used to cache the results of the "lvm pvs" commands used to query
the state of the Logical Volume Manager as a series of lines of text.
Then every time a particular value was queried GParted would split all
the lines of text into fields until the required value was found.
Stop this repeat splitting of cached lines of text. Instead parse the
lines of text into separate fields and store in structures of values of
the correct type in the cache.
Bug 750582 - Refactor the LVM2_PV_Info module object interface and
internal cache representation
The LVM2_PV_Info cache had a pretend multi-object interface, yet all the
data is static. An LVM2_PV_Info object doesn't contain any member
variables, yet was needed just to call the member functions.
Make all the member functions static removing the need to use any
LVM2_PV_Info objects.
Bug 750582 - Refactor the LVM2_PV_Info module object interface and
internal cache representation
An LVM2_PV_Info object contains no member variables as all the data is
static (exists once in the program and accessed by all objects). The
constructor did nothing, except when passed true to load the cache.
Provide a separate load_cache() member function and remove the
constructors and destructor which do nothing. The C++ compiler will
provide a default constructor and destructor, which don't do anything as
there are no member variables to initialise and finalise.
This makes the interface a little easier to understand. Mostly a step
along the way of refactoring how the LVM2_PV_Info cache module works.
Bug 750582 - Refactor the LVM2_PV_Info module object interface and
internal cache representation
The copy, resize/move and new dialog classes (Dialog_Partition_Copy,
Dialog_Partition_Resize_Move and Dialog_Partition_New respectively) had
to be used like this:
construct dialog object passing some parameters
call Set_Data() to pass more parameters
run() dialog
call Get_New_Partition()
There is nothing in the classes which forces Set_Data() to be called,
but it must be called for the dialogs to work and prevent GParted from
crashing.
Make these class APIs safer by making it impossible to program
incorrectly in this regard. Move all the additional parameters from
each Set_Data() method to each constructor. The constructors just call
the now private set_data() methods.
The member variable was named selected_partition. It is assigned from
Win_GParted::selected_partition_ptr (which is a pointer to a const
partition object so is never updated). This gives connotations that it
won't be modified.
However it is updated freely as the new resultant partition object is
prepared before being returned from the dialog, most notable in the
Get_New_Partition() methods.
Therefore rename from selected_partition to new_partition.
The code goes like this:
Dialog_Partition_Copy::Get_New_Partition()
call Dialog_Base_Partition::Get_New_Partition()
Update this->selected_partition with results from running
the dialog.
return this->selected_partition by value.
Save value back to this->selected_partition.
Update this->selected_partition some more.
return this->selected_partition by value.
So there is an unnecessary copy of the partition object returned from
the base class Get_New_Partition() function back to the same variable in
the derived copy class Get_New_Partition() function.
Need to keep the base class Get_New_Partition() function as derived
class Dialog_Partition_Resize_Move uses that implementation as it
doesn't override it, and it's part of the interface.
Avoid this unnecessary copy by moving base class Get_New_Partition()
code into a new private function, called prepare_new_partition(), which
doesn't return anything. Then have Get_New_Partition() in both classes
just return the required partition object. Like this:
Dialog_Base_Partition::Get_New_Partition()
call prepare_new_partition()
return this->selected_partition by value.
Dialog_Partition_Copy::Get_New_Partition()
call Dialog_Base_Partition::prepare_new_partition()
Update this->selected_partition some more.
return this->selected_partition by value.
Bug 750168 - Reduce the amount of copying of partition objects
When Operation objects are created they take a copy of the Device object
to which the operation is to be applied. The Device object includes a
vector of all the contained Partition objects currently on the device,
so these get copied too.
These additional deep copied Partition objects in the Operation object
are never accessed. Therefore don't copy the contained Partition
objects when copying the Device object into the Operation object.
Bug 750168 - Reduce the amount of copying of partition objects
When opening the Manage Flags dialog, creation of the dialog object was
creating a copy of the selected partition object. If this was an
extended partition it also included recursively constructing the
contained logical partitions too.
Instead, replace the partition object in the DialogManageFlags class
with a reference to it.
Bug 750168 - Reduce the amount of copying of partition objects
When opening the Partition Information dialog, creation of the dialog
object was creating a copy of the partition object to be displayed. If
this was an extended partition it also included recursively constructing
the contained logical partitions too.
Instead, replace the partition object in the Dialog_Partition_Info class
with a reference to it.
NOTE:
In C++ a reference is really just a pointer under the hood. As such,
dereferences of a pointer to an object in the context of needing a
reference to the object doesn't copy the object. It merely initialises
the reference from the pointer.
Specifically, with this prototype:
Dialog_Partition_Info( const Partition & partition );
and the dialog object being constructed in Win_GParted::activate_info():
Dialog_Partition_Info dialog( *selected_partition_ptr );
the partition object is not copy constructed. A reference (pointer) to
it is merely passed to the dialog constructor.
Bug 750168 - Reduce the amount of copying of partition objects
The first actions of Win_GParted::activate_resize() were to create a
copy of the vector of partitions for the currently displayed device and
visually apply any pending operations. Exactly this has already been
done in Win_GParted::Refresh_Visual() with the result now available in
the member variable display_partitions. Stop this unnecessary partition
object copying and processing by just using display_partitions member
variable instead.
Bug 750168 - Reduce the amount of copying of partition objects
Document how GParted displays partitions in the GUI and manages the
lifetime and ownership of that data.
Bug 750168 - Reduce the amount of copying of partition objects
Further ensure that a bug doesn't get introduced with the use of
selected_partition_ptr, by asserting that it points to a current
partition object in the vector of display partitions.
After deliberately breaking the code so that selected_partition_ptr
points to some other partition object, trying to display the Information
dialog causes this crash:
======================
libparted : 2.4
======================
**
ERROR:Win_GParted.cc:989:void GParted::Win_GParted::set_valid_operations(): assertion failed: (valid_display_partition_ptr( selected_partition_ptr ))
Aborted (core dumped)
At this point in the code:
973 void Win_GParted::set_valid_operations()
974 {
...
986 // No partition selected ...
987 if ( ! selected_partition_ptr )
988 return ;
>> 989 g_assert( valid_display_partition_ptr( selected_partition_ptr ) ); // Bug: Not pointing at a valid display partition object
Bug 750168 - Reduce the amount of copying of partition objects
Add Glib g_assert() to ensure that a bug doesn't get introduced which
allows a partition callback to be called without a partition being
selected first.
After deliberately breaking the code so that selected_partition_ptr is
not set, trying to display the Information dialog causes this crash:
# ./gpartedbin
======================
libparted : 2.4
======================
ERROR:Win_GParted.cc:1978:void GParted::Win_GParted::activate_info(): assertion failed: (selected_partition_ptr != NULL)
Aborted (core dumped)
At this point in the code:
1976 void Win_GParted::activate_info()
1977 {
>> 1978 g_assert( selected_partition_ptr != NULL ); // Bug: Partition callback without a selected partition
1979
Bug 750168 - Reduce the amount of copying of partition objects
Now that TreeView_Details and DrawingAreaVisualDisk classes store and
pass pointers to partition objects in the Gtk signal callbacks, change
the selected partition into a pointer too.
Bug 750168 - Reduce the amount of copying of partition objects
This stops copying of each displayed partition object into the
DrawingAreaVisualDisk class.
Bug 750168 - Reduce the amount of copying of partition objects
This stops copying of each displayed partition object into the
TreeView_Details class.
It also stops copy constructing lots of partition objects when just
clicking on a partition in the disk graphic. The disk graphic needs to
inform the main GUI and then the partition list which partition has been
selected. The call sequence goes like:
DrawingAreaVisualDisk::on_button_press_event(event)
Win_GParted::on_partition_selected(partition_ptr, src_is_treeview)
TreeView_Detail::set_selected(partition_ptr)
TreeView_Detail::set_selected(rows, partition_ptr,
inside_extended)
Relevant source and highlighted comparison line:
140 bool TreeView_Detail::set_selected( Gtk::TreeModel::Children rows,
141 const Partition * partition_ptr, bool inside_extended )
142 {
143 for ( unsigned int t = 0 ; t < rows .size() ; t++ )
144 {
>> 145 if ( static_cast<Partition>( rows[t][treeview_detail_columns.partition] ) == *partition_ptr )
146 {
147 if ( inside_extended )
148 expand_all() ;
149
150 set_cursor( static_cast<Gtk::TreePath>( rows[ t ] ) ) ;
151 return true ;
152 }
153
154 if ( set_selected( rows[t].children(), partition_ptr, true ) )
155 return true ;
156 }
157
158 return false ;
159 }
Then in this function the partition selected in the disk graphic
(partition_ptr parameter) is compared in turn with each partition object
stored in the Gtk::TreeView model to find the matching one to mark it as
selected. This mere act of accessing the partition object stored in a
row of the Gtk::TreeView model causes it to be copy constructed. So
clicking on the 5th partition in the disk graphic will copy construct
the first 5 partition objects just to do a compare to find the matching
one.
This is because it is not possible to get a reference from a
Gtk:TreeViewProxy in gtkmm. Merely accessing a value in a Gtk::TreeView
model takes a copy of that value.
Subject: get a reference from a Gtk::TreeValueProxy
http://comments.gmane.org/gmane.comp.gnome.gtkmm/2217http://marc.info/?t=104400417500001&r=1&w=4
Bug 750168 - Reduce the amount of copying of partition objects
Change from passing a reference to the selected partition, to passing a
pointer to the selected partition in the signal_partition_selected
callbacks between the disk graphic, partition list and core GUI modules.
This is an enabler for the following patches.
Bug 750168 - Reduce the amount of copying of partition objects
Win_GParted::Refresh_Visual() used a local variable containing a copy of
the vector of partitions in the current device to be displayed. After
visually applying pending operations it loaded copies of each partition
object into the GUI widgets to display the disk graphic and partition
list, DrawingAreaVisualDisk and TreeView_Details classes respectively.
When a partition is selected in the UI, again a partition object is
copied. Also several of the partition dialogs, including the
information dialog, take a copy of the partition object. All these are
copies of the same set of partition objects, those currently being
displayed in the UI.
Move the vector of displayed partitions from a local variable in
Refresh_Visual() to a Win_GParted member variable. This will allow for
the above cases to be changed to used pointers and references to the
same set of partition objects.
The valid lifetime of pointers to elements in this partition object
vector is from one refresh to the next, when the vector is cleared and
repopulated with a new set of partition objects. This is exactly what
is needed as the GUI widgets are reloaded on each refresh, the selected
partition is reset and none of the partition dialog objects exist.
Dialog objects being created and destroyed on each use.
On the other hand some copies of partition objects currently being
displayed, still need to be made because they have lifetimes which need
to last longer than the next call to Refresh_Visual(). Specifically the
source of the copy partition and the partition objects copied into the
in the list of pending operations.
Bug 750168 - Reduce the amount of copying of partition objects
BUF in the copy dialog class, Dialog_Partition_Copy, is use to adjust
limits in 2 cases:
1) Minimum size when copying an XFS file system
Minimum size was set to the used space + 2 * cylinder size (typically
plus ~16 MiB). This commit from 2004-12-20 added it:
a54b52ea33
xfs copy now uses xfsdump and xfsrestore. icw some hacks in the other 2
Issues:
* This is increasing the minimum XFS file system size when copying it,
which doesn't happen in the resize case for other file systems.
* It allows an XFS file system to be created which is smaller than the
minimum size allowed by GParted. Copying an empty XFS file system can
create a new file system as small as 26 MiB. This is smaller than the
minimum GParted allows of 32 MiB because that is the minimum
xfs_repair can handle.
Remove this addition when copying an XFS file system and enforce minimum
file system size.
2) Maximum size when copying a file system into empty space larger than
it's maximum size
Maximum size was set to maximum file system size - cylinder size
(typically minus ~8 MiB). Only applied to FAT16 which has a maximum
file system size set in and can be grown. Added by this commit from
2004-12-15:
10e8f3338d
:get_fs now returns a const reference. in copy and resizedialog
...
* in copy and resizedialog filesystems with MAX set now have a max size of MAX - one cylinder .
Issue:
* This is applying a lower maximum resize when copying the file system
compared to that when creating the file system.
NOTE:
GParted currently allows all file systems to be resize to any size,
regardless of the maximum file system size. This is probably an
oversight, but it does allow libparted to convert FAT16 to FAT32 file
system when resizing.
Remove this lower maximum file system size when copying and resizing,
compared to creating.
Bug 749867 - Some limits are adjusted by arcane cylinder size amount
when copying and resizing in a single operation
This commit from 2010-05-20 removed use of cylinder size increase in the
minimum, and cylinder size decrease in the maximum file system sizes
from the resize/move dialog.
e62a23b5b5
Add partition alignment option to align to MiB (#617409)
This cylinder size limit adjustments were being performed using the
Dialog_Base_Partition::BUF member variable. Now in the
Dialog_Partition_Resize_Move class it is never accessed, and only
unnecessarily set. Move BUF from the common base class into the
Dialog_Partition_Copy class where it is still used.
Bug 749867 - Some limits are adjusted by arcane cylinder size amount
when copying and resizing in a single operation
Avoid long lines, long statements and repeated calls to
gparted_core.get_filesystem_object( selected_partition.filesystem ) by
storing the returned pointer in a local variable.
Needs the previous commit so that the the local variable can be a
pointer to a const FileSystem object instead of a pointer to a
(modifiable) FileSystem object.
The function never modifies any member variables so make it a const
member function.
(FileSystem::get_custom_text() is a virtual function so can't be made
static).
Rename a couple of GParted_Core methods for consistency and to better
distinguish get_filesystem() from get_filesystems() which do completely
unrelated things.
get_filesystem() -> detect_filesystem()
recognise_filesystem_signature() -> detect_filesystem_internal()
Also make detect_filesystem() a static member method as it doesn't use
any member variables. Requirement cascades to get_partition_path().
These member functions are only used within the GParted_Core class and
only operate on the static member variable FILESYSTEM_MAP.
Make both functions private and also make init_filesystems() static.
The FileSystem objects stored in the FILESYSTEM_MAP are allocated once
using new in init_filesystems() but never deleted.
Valgrind output fragment:
# valgrind --leak-check=full ./gparted
==29314== 353 (72 direct, 281 indirect) bytes in 1 blocks are definitely lost in loss record 6,287 of 6,905
==29314== at 0x4A075FC: operator new(unsigned long) (vg_replace_malloc.c:298)
>> ==29314== by 0x46EDA5: GParted::GParted_Core::init_filesystems() (GParted_Core.cc:106)
==29314== by 0x46EC5F: GParted::GParted_Core::GParted_Core() (GParted_Core.cc:96)
==29314== by 0x4A74F4: GParted::Win_GParted::Win_GParted(std::vector<Glib::ustring, std::allocator<Glib::ustring> > const&) (Win_GParted.cc:51)
==29314== by 0x4D600A: main (main.cc:56)
...
==29314== 161 (72 direct, 89 indirect) bytes in 1 blocks are definitely lost in loss record 6,119 of 6,905
==29314== at 0x4A075FC: operator new(unsigned long) (vg_replace_malloc.c:298)
>> ==29314== by 0x46F50C: GParted::GParted_Core::init_filesystems() (GParted_Core.cc:124)
==29314== by 0x46EC5F: GParted::GParted_Core::GParted_Core() (GParted_Core.cc:96)
==29314== by 0x4A74F4: GParted::Win_GParted::Win_GParted(std::vector<Glib::ustring, std::allocator<Glib::ustring> > const&) (Win_GParted.cc:51)
==29314== by 0x4D600A: main (main.cc:56)
GParted_Core.cc source:
102 void GParted_Core::init_filesystems()
103 {
104 FILESYSTEM_MAP[ FS_UNKNOWN ] = NULL ;
105 FILESYSTEM_MAP[ FS_CLEARED ] = NULL ;
>> 106 FILESYSTEM_MAP[ FS_BTRFS ] = new btrfs() ;
...
>> 124 FILESYSTEM_MAP[ FS_XFS ] = new xfs() ;
125 FILESYSTEM_MAP[ FS_BITLOCKER ] = NULL ;
Fix by deleting all FILESYSTEM_MAP pointers. Note that delete on a NULL
pointer is defined by C++ as a safe do nothing operation.
C++ FAQ / Do I need to check for null before delete p?
https://isocpp.org/wiki/faq/freestore-mgmt#delete-handles-null
Fixing this reduces the valgrind reported definitely lost memory blocks
count from 25 down to 6. 19 FileSystem objects deleted and 19 memory
blocks no longer lost.
Bug 749036 - FileSystem objects are memory leaked in init_filesystems()
Background:
GParted_Core::calibrate_partition() reloads the partition path name and
boundary to ensure they are correct before the operation is performed.
(See comments in calibrate_partition() for the reasons why this is
necessary). This also displays details of the partition being modified
in the operation details to inform the user.
The operation object contains these relevant member objects:
* partition_original
Partition before the operation is applied.
* partition_new
Partition as it is intended to be after the operation has been
applied.
* partition_copied (for the copy operation only)
Source partition being copied.
Issues:
GParted_Core::apply_operation_to_disk() was always calibrating partition
object partition_original, but for about half the operations
partition_original was not used and partition_new is used, so should be
calibrated instead.
Copy into an existing partition calibrated three partitions, the source,
destination before and destination after the operation was applied.
This doesn't really make sense in the operation details to the user.
They would expect to only see the source and destination partitions and
don't care about the distinction between the before and after
representation of the destination.
Minor issues:
The previous fix had to copy the correct partition path from the
calibrated partition_original object to the used partition_new object
for the format, label file system, name partition and change uuid
operations.
Calibrate was called for the create operation too, even though the
partition didn't yet exist. It was a no-operation.
Fix:
Stop always calibrating the partition_original object and instead
calibrate the correct partition object in each operation case. For the
copy into existing partition operation only calibrate the right two
partition objects as the user would expect.
Bug 746559 - Various operations fail when following paste into existing
partition
Format, label file system and new UUID operations would fail when
applied in a sequence to the destination partition following a previous
copy-paste operation.
Giving the copy of a file system a new label and a new UUID are the sort
of actions which should be performed when the disk containing the copy
remains attached to the same computer. This really should work.
Fragment of the failing operation details for a copy and label operation
sequence:
+ Copy /dev/sdb1 to /dev/sdb2
+ calibrate /dev/sdb2
+ calibrate copy of /dev/sdb1
+ calibrate /dev/sdb1
+ check the file system on /dev/sdb1 for errors and (if possible fix them
+ copy file system of /dev/sdb1 to /dev/sdb2
+ Set file system label "small-dst" on copy of /dev/sdb1
+ calibrate copy of /dev/sdb1
path: /dev/sdb2 (partition)
...
+ set file system label to "small-dst" on copy of /dev/sdb1
+ e2label copy of /dev/sdb1 "small-dst"
Usage: e2label device [newlabel]
This is failing because the file system specific command is passed
"copy of /dev/sdb1" as the device name. Code sequence:
1) OperationCopy::OperationCopy() sets the real path name of the
partition_new object to "copy of /dev/SRC" for display purposes.
2) GParted_Core::apply_operation_to_disk() calls calibrate_partition()
on partition_original object, restoring the real path name for
object partition_original.
3) apply_operation_to_disk() calls format(), label_filesystem() or
change_uuid() on the partition_new object, which still has the real
path name set to "copy of /dev/SRC". File system specific commands
fail with this as a path name.
Fix by copying the real path name from object partition_original to
partition_new, as is already done for the resize/move operation. Also
apply this fix to the name partition operation, because it uses the
partition_new object and so that it displays the real path name in the
operation details.
Bug 746559 - Various operations fail when following paste into existing
partition
When the partition is named in the Create New Partition dialog, set the
partition name as part of the create partition operation. Currently
this is only supported for GPTs. See
Utils::get_max_partition_name_length() for details.
Bug 746214 - Partition naming enhancements
Add a partition name entry box to the Create New Partition dialog. The
entry box is greyed out (not sensitive) for partition table types which
don't support partition naming. Currently only supported for GPTs. See
Utils::get_max_partition_name_length() for details.
There was a slightly wider gap between the file system combobox row and
the label entry row when there were only three widgets on the right hand
side of the dialog. This has been removed now that there are four
widgets so that they are all evenly spaced and they line up with the
four widgets on the left hand side.
So far the partition name can be entered and previewed, but isn't yet
applied to the disk.
Bug 746214 - Partition naming enhancements
Adding a partition name entry to the Create New Partition dialog will
need access to these two Device methods: partition_naming_supported()
and get_max_partition_length(). The Set_Data() function already takes
two parameters, only_unformatted and disktype, taken from Device member
variables.
Rather than add two more parameters to the Set_Data() function pass the
Device object instead, replacing the current only_unformatted and
disktype parameters.
Bug 746214 - Partition name enhancements
This is a small tidy-up to remove Gtk::Entry method calls on the file
system label entry box in the Create New Partition dialog which serve no
purpose.
filesystem_label_entry.set_activates_default( true );
It trying to make the Create New Partition dialog automatically
close when Enter is pressed with focus in the label entry box.
However this doesn't work, presumably because the default widget for
the dialog is not the Add button. Remove.
filesystem_label_entry.set_text( partition.get_filesystem_label() );
Initialises the text in the entry box with the file system label
from the passed partition object. The label is blank and the entry
box defaults to blank. Achieves nothing. Remove.
filesystem_label_entry.select_region( 0, filesystem_label_entry.get_text_length() );
Highlights the empty text in the entry box. Achieves nothing.
Remove.
NOTE:
The same set of Gtk::Entry method calls in Dialog_FileSystem_Label() and
Dialog_Partition_Name, which are editing the existing file system label
and partition name respectively, do work and have a useful effect so
shouldn't be removed.
Rename Gtk::Entry object entry -> filesystem_label_entry in the
Dialog_Partition_New class. This is in preparation for the introduction
of the partition name entry box in the Create New Partition dialog.
Bug 746214 - Partition name enhancements
Preview of the format operation cleared the partition name, yet when
applied, the partition name reappeared. Fix the preview to reflect
reality.
Bug 746214 - Partition naming enhancements
Previously partition naming had only been implemented for gpt. Make the
code ready to support naming of the other partition table types for
which libparted supports naming. Specifically: amiga, dvh, mac and
pc98 in addition to gpt. Document issues found with some of these
partition table types, which can relatively easily been worked around.
Leave support of naming for partition table types other than gpt
disabled, mostly just to reduce ongoing testing effort, at least until
there is any user demand for it.
Bug 746214 - Partition naming enhancements
Allow partition names to be changed whether or not the partition is
busy, rather than only when not busy, because it doesn't effect the busy
file system or change the partition boundaries in any way.
Bug 746214 - Partition naming enhancements
Attempting to create a new partition on a pc98 partition table fails
with the following libparted error:
The flag 'lvm' is not available for pc98 disk labels.
This has been broken since LVM2 Physical Volume read-write support was
first added in this commit:
c3ab62591b
Add creation of LVM2 PVs (#670171)
Fix by only clearing and setting the lvm partition flag when the type of
the partition table supports it. When creating a partition to contain
an LVM2 PV and the lvm flag is not support add the following message to
the operation results to explain that setting the lvm partition flag was
skipped and why:
Skip setting unsupported partition flag: lvm
Bug 746204 - Creating partitions on pc98 table fails with lvm flag not
available
Refactor GParted_Core::set_partition_type().
1) Set lp_partition variable earlier and use a single if lp_partition
set condition, rather than in both if conditions for the normal file
system case and the LVM2 Physical Volume case.
2) Stop calling Utils::get_filesystem_string() multiple times, instead
save the result in a local variable.
Tidies the code a little and reorders it in preparation for the
following fix to only set the lvm partition flag when support, making
that code change simpler.
Bug 746204 - Creating partitions on pc98 table fails with lvm flag not
available
resize_move() and move() stopped using the device parameter in this
commit from 2006-07-23:
d663c3c277
removed cylindersize buffering during resize from the filesystems. It is
create() stopped using the device parameter in this commit from 2006-03-19:
ad9f2126e7
fixed issues with copying (see also #335004) cleanups + added FIXME added
For reference most other operation methods had the device parameter
removed in this earlier commit from 2005-12-07:
642f0a145b
from now on each partition has a reference to it's device. make use of new
When the following conditions were met GParted would fail to recognise a
newly created whole disk device file system, and instead show an unknown
file system filling the disk:
1) Disk was previously partitioned and contained at least one partition.
2) Using libparted version 2.0 to 3.0 inclusive.
Initial status:
# blkid | fgrep sdc
# fgrep sdc /proc/partitions
8 32 976762584 sdc
8 33 104857600 sdc1
# parted /dev/sdc
GNU Parted 2.4
Using /dev/sdc
Welcome to GNU Parted! Type 'help' to view a list of commands.
(parted) print
Model: ATA ST1000LM024 HN-M (scsi)
Disk /dev/sdc: 1000GB
Sector size (logical/physical): 512B/4096B
Partition Table: msdos
Number Start End Size Type File system Flags
1 1049kB 107GB 107GB primary
When creating the loop partition table libparted would not inform the
kernel to delete the old partitions. /proc/partitions still contained
the details of the old partitions.
(parted) mktable loop
Warning: The existing disk label on /dev/sdc will be destroyed and
all data on this disk will be lost. Do you want to continue?
Yes/No? Yes
(parted) print
Model: ATA ST1000LM024 HN-M (scsi)
Disk /dev/sdc: 1000GB
Sector size (logical/physical): 512B/4096B
Partition Table: loop
Number Start End Size File system Flags
(parted) quit
# fgrep sdc /proc/partitions
8 32 976762584 sdc
8 33 104857600 sdc1
Creation of the whole disk device file system goes unnoticed by blkid
because the kernel and therefore blkid's cache have stale partition
information.
# mkfs.xfs -f /dev/sdc
# blkid | fgrep sdc
NOTE:
On a Linux Software RAID array, as opposed to a hard disk, blkid does
notice creation of the whole disk device file system. However the
kernel still has old partition details.
This was fixed in libparted 3.1 by commit:
http://git.savannah.gnu.org/cgit/parted.git/commit/?id=f5c909c0cd50ed52a48dae6d35907dc08b137e88
libparted: remove has_partitions check to allow loopback partitions
Fix by deleting old partitions before creating the loop table when
compiled with a broken version of libparted. The GParted UI provides
no feedback while a new partition table is created, and with some
versions of GTK the UI become unresponsive too, so it is important to be
as fast as possible. Evaluated three different methods, deleting 15 and
22 MSDOS partitions on a physical 5400 RPM hard drive using libparted
2.4:
M1) Delete and commit one partition at a time.
Takes up to 24 seconds to delete 15 partitions. With 22 partitions
libparted always reports finding some of the partitions busy and
unable to inform the kernel about the modifications.
Too slow and doesn't work.
M2) Delete all partitions in one go and commit once.
Takes up to 1.4 seconds to delete either 15 or 22 partitions. Never
removes partitions 17 and higher from the kernel.
Doesn't work.
M3) Write GPT table (letting libparted delete any old partitions).
Takes up to 0.8 seconds to delete either 15 or 22 partitions.
Fast and works.
Use method 3 - write a GPT table thus using libparted code to inform the
kernel of the old partition deletions.
Bug 743181 - Add unpartitioned drive read-write support
Older versions of blkid don't correctly distinguish between FAT16 and
FAT32 file systems when overwriting one with the other. This effects
GParted too with these file systems on whole disk devices where only
blkid is used to recognise the contents. See previous fix for why only
blkid is used in this case:
Avoid whole disk FAT being detected as MSDOS partition table
(#743181)
Example:
# blkid -v
blkid from util-linux 2.20.1 (liblkid 2.20.0, 19-Oct-2011)
# mkdosfs -F16 -I /dev/md1
# blkid | fgrep md1
/dev/md1: SEC_TYPE="msdos" UUID="7C23-95D9" TYPE="vfat"
# mkdosfs -F32 -I /dev/md1
# blkid | fgrep md1
/dev/md1: SEC_TYPE="msdos" UUID="7F93-98F4" TYPE="vfat"
So blkid recognised the UUID changed but didn't remove the SEC_TYPE for
the FAT32 file system. See FS_Info::get_fs_type() as it uses this to
distinguish between FAT16 and FAT32. This is a caching update bug in
blkid, because telling blkid not to use the cache gets the right
results:
# blkid -c /dev/null | fgrep md1
/dev/md1: UUID="7F93-98F4" TYPE="vfat"
With testing determined that blkid from util-linux 2.23 and later are
not affected and earlier versions are affected. Mostly recently known
affected distribution is Ubuntu 14.04 LTS with util-linux 2.20.1.
The straight forward fix would be to instruct blkid to not use its cache
with 'blkid -c /dev/null'. But using blkid's cache is needed to prevent
blkid hanging for minutes when trying to access a non-existent floppy
drive when the BIOS is set incorrectly. See commit:
18f863151c
Fix long scan problem when BIOS floppy setting incorrect
Instead, when using an older affected version of blkid and when blkid
cache reports a vfat file system, run blkid again bypassing the cache.
The device is known to exist and contain a vfat file system, just not
whether it is a FAT16 or FAT32 file system, so can't be a non-existent
floppy device and won't hang.
Bug 743181 - Add unpartitioned drive read-write support
Libparted 1.9.0 to 2.3 inclusive, recognises whole disk device FAT file
systems as MSDOS partition tables. This causes GParted to do the same.
# dd if=/dev/zero bs=1M of=/dev/md4
# mkdosfs -F32 -v -I /dev/md4
# blkid /dev/md4
/dev/md4: UUID="53FE-31F2" TYPE="vfat"
# parted /dev/md4
GNU Parted 2.1
Using /dev/md4
Welcome to GNU Parted! Type 'help' to view a list of commands.
(parted) print
Model: Unknown (unknown)
Disk /dev/md4: 536MB
Sector size (logical/physical): 512B/512B
Partition Table: msdos
Number Start End Size Type File system Flags
(parted) quit
# /tmp/parted24/bin/parted /dev/md4
GNU Parted 2.4
Welcome to GNU Parted! Type 'help' to view a list of commands.
(parted) print
Model: Linux Software RAID Array (md)
Disk /dev/md4: 536MB
Sector size (logical/physical): 512B/512B
Partition Table: loop
Number Start End Size File system Flags
1 0.00B 536MB 536MB fat32
(parted) quit
This was fixed in libparted 2.4 by commit:
http://git.savannah.gnu.org/cgit/parted.git/commit/?id=616a2a1659d89ff90f9834016a451da8722df509
libparted: avoid regression when processing a whole-disk FAT partition
Make GParted immune to this bug by moving blkid performed whole disk
device file system detection before libparted partition detection. Also
have to always erase old file system signatures on whole disk devices
when creating new partition tables to ensure that blkid doesn't detect
those old signatures before libparted has a chance to detect the new
partition table.
Bug 743181 - Add unpartitioned drive read-write support
When writing "loop" partition table over the top of some whole disk
device file system types GParted continued to show those whole disk
device file systems rather than the virtual unknown partition from the
"loop" partition table.
This affected btrfs, jfs, reiser4 and reiserfs. It occurred because of
several factors:
1) Libparted only zeroed the first and last 9.5 KiB (assuming 512 byte
sectors) of the device before writing a new partition table. See
ped_disk_clobber().
2) These file systems have their super blocks and therefore signatures
after the first 9.5 KiB.
3) Whole disk device file system detection is performed using blkid
before checking for a libparted "loop" partition table. See
GParted_Core::set_devices_thread().
Ref:
libparted 3.2: disk.c:ped_disk_clobber()
http://git.savannah.gnu.org/cgit/parted.git/tree/libparted/disk.c?id=v3.2#n302
Fix by always erasing any possible file system signatures on the device
before creating a new "loop" partition table.
NOTE:
This is typically taking up to 0.5 seconds in my testing on a 5400 RPM
hard drive, during which time the GParted UI is hung and the create
partition table dialog shows the apply button pressed but no other
progress indication.
Bug 743181 - Add unpartitioned drive read-write support
Creating a new partition table was getting libparted to read any
existing partition table before creating a new partition table on the
device. This is an unnecessary step, and if the device didn't already
contain a partition table also printed this error from libparted:
/dev/sdb: unrecognised disk label
Since get_device_and_disk() has been split into two, just call
get_device() instead to just populate the PedDevice object representing
the disk device. Removes a small unnecessary step.
Bug 743181 - Add unpartitioned drive read-write support
The preview of clearing a whole disk device file system was previewing
the same as formatting to all other file system types; as a cleared file
system spanning the whole disk device. However when implemented this
removes all signatures on the disk so it actually becomes an unallocated
and unpartitioned device. Make the preview match what happens in when
implemented.
GParted previously used mydevice.max_prims = -1 to represent an
unpartitioned device. It is now represented as:
mydevice.max_prims = 1
mydevice.disktype = _("unrecognized")
mydevice.partitions[0].type = TYPE_UNALLOCATED
mydevice.partitions[0].whole_device = true
mydevice.partitions[0].filesystem = FS_UNALLOCATED
and the check for an unpartitioned device in Win_GParted.cc becomes:
partitions[0].type == TYPE_UNALLOCATED && partitions[0].whole_device
Bug 743181 - Add unpartitioned drive read-write support
Previously GParted displayed a device containing the parted "loop"
partition table signature "GNU Parted Loopback 0" and nothing else, as
an unrecognised device.
Now make GParted display this as a virtual whole disk device partition
with unknown contents, complete with the unable to detect a file system
warning. This change then allows a whole disk device file system to be
created with the following two steps:
1) Create "loop" partition table on a device;
2) Format to required file system.
GParted represents a whole disk device file system as:
mydevice.max_prims = 1
mydevice.disktype = "none"
mydevice.partitions[0].type = TYPE_PRIMARY
mydevice.partitions[0].whole_device = true
mydevice.partitions[0].filesystem = FS_EXT4 (example)
Now represents just Parted's "loop" signature as:
mydevice.max_prims = 1
mydevice.disktype = "loop"
mydevice.partitions[0].type = TYPE_PRIMARY
mydevice.partitions[0].whole_device = true
mydevice.partitions[0].filesystem = FS_UNKNOWN
And as before, an unpartitioned device as:
mydevice.max_prims = -1
mydevice.disktype = _("unrecognized")
mydevice.partitions[0].type = TYPE_UNALLOCATED
mydevice.partitions[0].whole_device = true
mydevice.partitions[0].filesystem = FS_UNALLOCATED
Bug 743181 - Add unpartitioned drive read-write support
Only allow resizing, not moving of a whole disk device file system.
There is no actual partition to move and moving a file system away from
the start of a disk only makes it unrecognisable.
Also don't perform the partition resize step as there's no actual
partition to be resized. Only the file system is being resized.
(Libparted actually allows the virtual partition spanning a whole disk
device to be resized, implementing it as a no-operation, but only for
recognised file systems. For unrecognised file systems it fails with
"unrecognised disk label").
Note that the existing resize dialog was designed for resizing partition
boundaries, and their contained file systems, not for resizing file
systems within a fixed boundary. The difference is noticeable when
there is unallocated space because the file system doesn't fill the
whole disk device. The dialog starts resizing a virtual partition the
size of the whole disk device, not the actual size of the file system.
Leave addressing this for a possible future update.
Bug 743181 - Add unpartitioned drive read-write support
First, copying into a whole disk device fails on the set partition type
step. Fails with either libparted error "The flag 'lvm' is not
available for loop disk labels" or "unrecognised disk label" depending
whether libparted recognised the content and created a virtual partition
or not. (This is with libparted 2.4).
Fix by just skipping setting the partition type on whole disk devices.
Second, if any file system specific tools are used during the copy, they
will fail because they are passed the device name as "copy of /dev/SRC"
instead of "/dev/DST". Occurs when either the destination whole disk
device is not an identical size to the source so the file system check
and grow steps are added, or when file system specific tools are used to
copy the file system as with XFS or recent EXT2/3/4 tools.
Fix by re-adding the real partition path from libparted for whole disk
devices, as is already done for partitioned device names in
GParted_Core::calibrate_partition().
Bug 743181 - Add unpartitioned drive read-write support
Creation of reiserfs file system fails in GParted with the this error.
# mkreiserfs -f --label "" /dev/sdb < /dev/null
mkreiserfs 3.6.24
/dev/sdb is entire device, not just one partition!
Continue (y/n):
# echo $?
1
Add second force flag, -f, to the mkreiserfs command to make it work.
Bug 743181 - Add unpartitioned drive read-write support
Creation of ext2/3/4 and ntfs file systems fails in GParted on whole
disk devices with these errors.
# mkfs.ext4 -L "" /dev/sdb < /dev/null
mke2fs 1.42.9 (4-Feb-2014)
/dev/sdb is entire device, not just one partition!
Proceed anyway? (y,n)
# echo $?
1
# mkntfs -Q -v -L "" /dev/sdc
/dev/sdc is entire device, not just one partition.
Refusing to make a filesystem here!
# echo $?
1
Add force flag, -F, to both mkfs commands to make them work.
Bug 683643 - Doesn't properly support partitionless drives.
Formatting a whole disk device fails on the set partition type step with
libparted error "unrecognised disk label". This is because the previous
step just cleared the old file system signatures leaving libparted with
nothing to recognise. Therefore libparted doesn't present a virtual
"loop" partition table.
As there is no partition table, there's no partition and no partition
type. Just skip setting the partition type on whole disk devices.
Bug 743181 - Add unpartitioned drive read-write support
This enables Format to Cleared operation to succeed on whole disk device
file systems even when libparted doesn't recognise the file system.
(Turns out that making calibrate work in the previous commit happened to
make Format to Cleared operation succeed, but only if libparted
recognised the file system on the whole disk device).
Bug 743181 - Add unpartitioned drive read-write support
In the operational results of the calibrate step include the type of the
path GParted is working with, either partition or whole disk device. Do
the same for the create empty partition step too for consistency, even
though it only ever creates partitions. Looks like:
create empty partition
path: /dev/sdb3 (partition)
start: 2099200
end: 4196351
size: 2097152 (1.00 GiB)
calibrate /dev/sdc
path: /dev/sdc (device)
start: 0
end: 1953525167
size: 1953525168 (931.51 GiB)
Makes it explicit to the users what GParted has detected. Helps the
developers when looking at saved results to understand what decisions
were made and why specific steps were performed or not.
Bug 743181 - Add unpartitioned drive read-write support
This enables the Check, Label and New UUID operations to succeed on
whole disk device file systems even when libparted doesn't recognise the
file system.
This benefits reiser4 and lvm2 pv file systems with all versions of
libparted, current version is 3.2, and for nilfs2 with libparted < 2.4.
Bug 743181 - Add unpartitioned drive read-write support
get_device_and_disk() basically calls libparted to get a PedDevice
object representing a disk device and a PedDisk object representing a
partition table. Re-implement get_device_and_disk() using two separate
functions, get_device() and get_disk(), to get one of these objects
each.
No functionality changes with this commit. It enables future commits to
incrementally add support for whole disk devices into GParted without
needing libparted to recognise the contents and create a virtual "loop"
partition table.
Bug 743181 - Add unpartitioned drive read-write support
Enable operations on whole disk devices containing any recognised file
system.
The new partition operation on an empty whole disk device continues to
display the "No partition table found on device /dev/DEVICE" information
dialog.
Specifically unsupported operations:
* Delete -
Deletion of a partition only involves removal of the entry in the
partition table leaving the file system intact on the disk. However
this doesn't work for a whole disk device file system. Instead the
file system signatures would have to be erased which is much more
destructive and virtually impossible to undo. Therefore don't
implement whole disk device file system deletion. Alternatives are
to format the file system to cleared or create a partition table on
the device. Both of these imply overwriting the existing data and
set the expectation that undo is not possible.
* Manage flags -
There's no partition table, so there's no partition, so there's no
flags.
Resize/Move operation is being supported so that a whole disk device
file system can be resized to handle devices which can be resize, such
as those from SANs or Linux Software RAID arrays. The start of the file
system must remain fixed so move won't be allowed.
So far only simple operations work if they don't need libparted support
at all [1], or only need libparted support for the calibrate step AND
the file system on the whole disk device is recognised by libparted [2].
(Needs libparted to provide a "loop" partition, hence the recognition
requirement, so that the calibrate step can successfully read the
virtual "loop" partition table. Doesn't matter whether it's an old
version of libparted and it gets the name of the device wrong as GParted
is already using the whole disk device name anyway).
[1] Operations not needing any libparted support:
Mount on, Unmount, Swapon, Swapoff, Activate and Deactivate
[2] Operations only needing libparted support for the calibrate step:
Check, Label, New UUID
Bug 743181 - Add unpartitioned drive read-write support
Need to be able to take different actions in the GParted_Core partition
manipulation methods and in Win_GParted UI methods to deal with
libparted supported partitions or whole disk devices without a partition
table. Add boolean whole_device to the partition object and set
appropriately to allow for this.
Bug 743181 - Add unpartitioned drive read-write support
As was done with a failed mount operation, include the failed activate/
deactivate command in the error dialog. Two example error dialogs now
look like this:
(-) Could not deactivate swap
# swapoff -v /dev/sdb7
swapoff: /dev/sdb7: swapoff failed: Invalid argument
[ OK ]
(-) Could not unmount /dev/sdb6
# umount -v "/mnt/6"
umount: /mnt/6: not mounted
[ OK ]
On RHEL/CentOS 6, GParted fails to mount nilfs2 file system like this:
# mkfs.nilfs2 /dev/sdb1
# mount /dev/sdb1 /mnt/1
mount: you must specify the filesystem type
This fails because mount internally uses libblkid to determine the file
system type when it is not specified on the command line. However on
RHEL/CentOS 6 libblkid is too old to recognise nilfs2.
GParted used libparted recognition first and blkid second. Mount only
uses libblkid. When there are multiple signatures on a partition
GParted may report a different result to blkid alone. Therefore fix by
first trying to mount the file system without specifying the type, as is
already done, and if that fails, trying specifying the file system type.
This allows GParted to mount nilfs2 file systems.
# mount -t nilfs2 /dev/sdb1 /mnt/1
# mount | fgrep sdb1
/dev/sdb1 on /mnt/1 type nilfs2 (rw,gcpid=30946)
And for unsupported file systems the error dialog from the failed mount
command shows both commands like this:
(-) Could not mount /dev/sdb3 on /mnt/3
# mount -v /dev/sdb3 "/mnt/3"
mount: unknown filesystem type 'reiser4'
# mount -v -t reiser4 /dev/sdb3 "/mnt/3"
mount: unknown filesystem type 'reiser4'
[ OK ]
Bug 742741 - Nilfs2 file system is unusable on RHEL/CentOS 6
Function Utils::get_filesystem_kernel_name() returns the name of the
file system as needed for use in the mount command:
mount -t TYPE DEVICE DIR
Needed because the kernel / mount name is 'hfsplus' where as libparted /
GParted, as reported by Utils::get_filesystem_string(), calls it 'hfs+'.
So far just added debugging when mounting a file system to test the
function works.
# ./gartedbin
======================
libparted : 2.1
======================
DEBUG: (hfsplus) # mount -v /dev/sdb5 "/mnt/5"
DEBUG: (nilfs2) # mount -v /dev/sdb1 "/mnt/1"
Bug 742741 - Nilfs2 file system is unusable on RHEL/CentOS 6
On RHEL/CentOS 6 GParted fails to mount nilfs2 file system. Include the
failing file system mount command in the error dialog so the user knows
what command failed. The error dialog now looks like:
(-) Could not mount /dev/sdc1 on /mnt/1
# mount -v /dev/sdc1 "/mnt/1"
mount: you must specify the filesystem type
[ OK ]
Also stop telling the dialog that the secondary text contains pango
markup as the command line and error message certainly isn't pango
markup text.
Bug 742741 - Nilfs2 file system is unusable on RHEL/CentOS 6
GParted can create a nilfs2 file system on RHEL/CentOS 6, yet both
libparted and blkid are too old to recognise it when created. Add
GParted internal detection of nilfs2 file systems.
Easy way to get the required signature needed to recognise nilfs2 is
using wipefs to report the signature bytes it erases, using a more up to
date distribution. So using CentOS 7:
# mkfs.nilfs2 /dev/sdb1
# wipefs -a /dev/sdb1
/dev/sdb1: 2 bytes were erased at offset 0x00000406 (nilfs2): 34 34
Also from util-linux source libblkid/src/superblocks/nilfs2.c
#define NILFS_SB_MAGIC 0x3434
Bug 742741 - Nilfs2 file system is unusable on RHEL/CentOS 6
For libparted recognised file systems covering the whole disk device,
libparted reports the partition table as "loop". With libparted 3.1 and
earlier, the partition device was reported wrongly as /dev/sdb1, instead
of /dev/sdb, by the ped_partition_get_path() call. This causes GParted
to fail to report file system usage, label and UUID, and busy status.
Also multiple file system tool command errors from using the wrong
device are displayed.
# mkfs.ext4 -L whole-ext4 /dev/sdb
# ./gpartedbin
Example partition errors:
e2label: No such file or directory while trying to open /dev/sdb1
Couldn't find valid filesystem superblock.
tune2fs 1.42.8 (20-Jun-2013)
tune2fs: No such file or directory while trying to open /dev/sdb1
Couldn't find valid filesystem superblock.
dumpe2fs 1.42.8 (20-Jun-2013)
dumpe2fs: No such file or directory while trying to open /dev/sdb1
Couldn't find valid filesystem superblock.
Unable to read the contents of this file system!
Because of this some operations may be unavailable.
This cause might be a missing software package.
The following list of software packages is required for ext4 file
system support: e2fsprogs v1.41+.
This also breaks most of the manipulation operations, again because it
is using the wrong device name.
Fix by ignoring libparted's "loop" partition table and just let it get
displayed via the "none" partition table mechanism.
Doing this renders the direction taken in bug 683643 to make GParted
work with libparted "loop" partition tables mute, as GParted no longer
works with such partition tables. Instead they are replaced by "none"
partition tables within GParted.
Bug 683643 - Doesn't properly support partitionless drives
https://bugzilla.gnome.org/show_bug.cgi?id=683643
Bug 741430 - GParted cannot recognise LVM signature on unpartitioned
drive