So that the new version and configuration information is displayed even
if the gpartedbin executable is run as a non-root user. To help with
diagnosing root authorisation issues with the gparted shell wrapper
script.
Closes!34 - Display more version and configuration information
So that we might get more information from users when helping them.
Starting GParted from the command line now looks like this:
# ./gpartedbin
GParted 0.33.0-git
configuration --enable-online-resize
libparted 3.2
Closes!34 - Display more version and configuration information
Glibmm has implemented a ustring::compose() set of methods [1] since
Glibmm 2.16, circa 2008. So replace String::ucompose(). Note that
GParted already requires glibmm >= 2.32 as set in configure.ac.
This commit just replaces all the method calls. Edit created by:
sed -i 's|String::ucompose *|Glib::ustring::compose|' src/*.cc
[1] Glibmm Reference Manual, Glib::ustring Class, compose() method
https://developer.gnome.org/glibmm/2.32/classGlib_1_1ustring.html#a64ff7ac3d9e9899c2910f1d831f8d500Closes#46 - Drop compose subdir
Now that we are compiling against Gtkmm3 there are missing declarations
of Glibmm identifiers due to changes in Gtkmm internal header structure.
All we have to do is bring back the declarations by including the
appropriate headers where needed.
Add necessary Glibmm header includes.
Closes#7 - Port to Gtk3
Raise the minimum required version of GNU Parted from 1.7.1 to 2.2,
released 2010-02-16 [1][2]. The oldest supported distributions, also
with gtkmm >= 2.24, since commit [3], are:
Debian 8 parted 3.2
RHEL / CentOS 7 parted 3.1
SLES 12 parted 3.1
Ubuntu 14.04 LTS parted 2.3
Raising the minimum required version allows removal of optional code
associated with these definitions:
* USE_LIBPARTED_LARGE_SECTOR_SUPPORT
Fallback code reporting ignored device with logical sector size
other than 512 bytes.
* ENABLE_PT_REREAD_WORKAROUND
Fallback code re-attempting to inform the kernel of partition
changes.
[1] GNU Parted 2.2 release announcement
http://lists.gnu.org/archive/html/info-gnu/2010-02/msg00016.html
[2] NEWS file from GNU Parted 2.2
http://git.savannah.gnu.org/cgit/parted.git/tree/NEWS?h=v2.2
[3] 8b42bab1ee
modern-gtk2: Require Gtkmm version 2.24 (!17)
Closes!22 - Increase minimums to libparted 2.2 and glibmm 2.32
The code inconsistently uses GParted:: scope in front of TYPE_*.
$ fgrep 'GParted::TYPE_' src/*.cc | wc -l
35
$ egrep '[^:]TYPE_' src/*.cc | wc -l
83
GParted:: scope resolution is unnecessary as all the code is inside the
GParted scope, except for main(). So remove it.
Closes!20 - Minor namespace and scope operator tidy-ups
The code inconsistently uses GParted:: scope in front of FS_*.
$ fgrep 'GParted::FS_' src/*.cc | wc -l
41
$ egrep '[^:]FS_' src/*.cc | wc -l
441
GParted:: scope resolution is unnecessary as all the code is inside the
GParted namespace, except for main(). So remove it.
Closes!20 - Minor namespace and scope operator tidy-ups
The code inconsistency uses GParted::FS::* and FS::*.
$ fgrep 'GParted::FS::' src/*.cc | wc -l
97
$ egrep '[^:]FS::' src/*.cc | wc -l
152
GParted:: scope resolution is unnecessary as all the code is inside the
GParted namespace, except for main(). So remove it.
Closes!20 - Minor namespace and scope operator tidy-ups
Create an active Linux Software RAID member which is larger than /dev
virtual file system and GParted will report the usage figure of the /dev
virtual file system for the SWRAID member.
# df -h /dev
Filesystem Size Used Avail Use% Mounted on
devtmpfs 732M 0 732M 0% /dev
# sgdisk -n 1:1M:+1G /dev/sdb
# mdadm --create --verbose /dev/md1 --level=linear --raid-devices=1 --force /dev/sdb1
mdadm: Defaulting to version 1.2 metadata
mdadm: array /dev/md1 started.
GParted reports the usage of /dev/sdb1 as:
Partition Mount Point Size Used Unused Unallocated
/dev/sdb1 /dev/md1 1.00GiB 0.00B 731.04MiB 292.96MiB
However GParted should have reported the usage as "---" for unknown
because it isn't coded to query the size of the SWRAID member within a
partition.
The fault has been bisected to this commit:
Extend un/mounting and usage reporting to unsupported file systems (!13)
95903efb1f
What happens for busy Linux Software RAID array members:
* GParted_Core::is_busy()
has custom code to identify busy members.
* GParted_Core::set_mountpoints()
has custom code to add the array device name as the "mount point" of
the member.
* GParted_Core::set_used_sectors()
falls into the else not a supported file system (because SWRAID
doesn't have a derived FileSystem implementation class).
* GParted_Core::mounted_set_used_sectors()
is called to get the file system usage of mounted, but unsupported
file systems, such as UFS and any others.
* Utils::get_mounted_filesystem_usage()
is called which queries the kernel using statvfs() and gets the file
system usage of the /dev virtual file system because the array
device name will always start /dev.
Fix by ensuring that GParted only asks the kernel for the usage of paths
which it knows are mount points of mounted file systems. (As read from
/proc/mounts and cached in the Mount_Info module). Also rename the
method, by inserting "_fs", to mounted_fs_set_used_sectors() to remind
us that it is for mounted *file systems* only.
Closes#27 - GParted may report incorrect usage for SWRAID partitions
instead of unknown
S
Just add detection of APFS using GParted's internal magic string
detection. It just matches 1 byte of the 2 byte object type and the
4 byte magic field found in the super block [1]. See code comment for
more details.
Blkid has just gained recognition of APFS with util-linux v2.33 released
06-Nov-2018 [2].
This will write enough for GParted's simple internal detection to find
APFS:
# python -c '
import sys
sys.stdout.write("\0"*24 + "\1\0" + "\0"*6 + "NXSB")
' > /dev/sdb1
[1] Apple File System Reference
https://developer.apple.com/support/apple-file-system/Apple-File-System-Reference.pdf
[2] [ANNOUNCE] util-linux v2.33
https://marc.info/?l=linux-fsdevel&m=154150400305928&w=2Closes#23 - GParted doesn't detect APFS (Apple File System)
Set the partition read-only mount flag at the same time as setting the
file system mount points.
Closes#10 - Gparted fails to resize btrfs partition that is mounted
read-only
The function was using std::map::count() [1] to test if the file system
entry existed in the map before looking up the value using
std::map::operator[] to avoid having operator[] inserting elements which
don't exist [2].
Rewrite using std::map::find() [3] so that map is only searched once,
and so that it is more obvious what is happening without having to know
the subtleties of std::map::count() and ::operator[].
[1] std::map::count()
http://www.cplusplus.com/reference/map/map/count/
"Searches the container for elements with a key equivalent to k and
returns the number of matches.
Because all elements in a map container are unique, the function can
only return 1 (if the element is found) or zero (otherwise).
"
[2] std::map::operator[]
http://www.cplusplus.com/reference/map/map/operator[]/
"If k does not match the key of any element in the container, the
function inserts a new element with that key and returns a reference
to its mapped value. Notice that this always increases the
container size by one, even if no mapped value is assigned to the
element (the element is constructed using its default constructor).
"
[3] std::map::find
http://www.cplusplus.com/reference/map/map/find/
"Searches the container for an element with a key equivalent to k
and returns an iterator to it if found, otherwise it returns an
iterator to map::end.
"
There is no prospect of there being ufs-tools on Linux. The was a
project which did release ufs-tools version 0.1 in 2004, but has been
inactive since then.
http://ufs-linux.sourceforge.net/
Copying and moving is now implemented for file systems in the basic
supported category. Also mounting and unmounting of unsupported file
system and reporting their usage while mounted has been added. This is
all the support that GParted has ever implemented for UFS. Therefore
re-assign UFS as a basic supported file system as it looses no
functionality.
Closes!13 - Support copying and moving of unsupported partition content
For unsupported (including basic supported) file systems, also record
the mount point(s) when mounted and from /etc/fstab when not. This
allows mounted unsupported file systems to be unmounted and ones with
/etc/fstab entries to be mounted, just like fully supported file
systems.
Also for unsupported (again including basic supported) mounted file
systems query the kernel for the usage, just like is already done for
supported file systems.
Closes!13 - Support copying and moving of unsupported partition content
Want a single term under which the supported actions for all basic
supported file systems are displayed in the File System Support dialog.
"Unknown" isn't the correct adjective because the group includes
unknown, but also includes: BitLocker, GRUB2 core image, ISO9660, Linux
SWRaid, Linux Suspend, REFS and ZFS. Add "other" file system type just
for displaying in the dialog.
Closes!13 - Support copying and moving of unsupported partition content
Introduce a third category of basic file system support to go along with
the existing full and none. Use the file system's entry in
FILESYSTEM_MAP to determine the level of support. See comment in
GParted_Core::init_filesystems() for details.
Add and remove FILESYSTEM_MAP NULL pointer entries as required, so that
only the file system types intended to have basic support have such
entries.
Closes!13 - Support copying and moving of unsupported partition content
PATCHSET OVERVIEW:
Forum user wanted to be able to move a partition with unknown content:
Topic: Can't move/rezise partition on android device (unknown format)
http://gparted-forum.surf4.info/viewtopic.php?id=17742
While GParted isn't going to be able to run any sort of file system
check on the unknown content there isn't any reason why such a partition
can't be copied or moved so long as the partition stays the same size.
GParted can just use it's existing internal block copy routine it uses
for copying and moving most partition content. This is no different to
a few of the already supported file system types which don't have a
check-repair tool: exfat, f2fs, nilfs2, udf, ufs.
This patchset introduces a third category called basic file system
support to go along with the existing full and unsupported categories.
Basic supported file systems will just use GParted's inbuilt
capabilities to perform actions so they won't need a derived FileSystem
implementation class. Unknown file systems along with all other
recognised, but otherwise unsupported, file systems will be assigned to
this new basic supported category.
THIS PATCH:
FS_UNKNOWN is used when GParted is unable to identify the contents of a
partition. FS_UNKNOWN is also used to generate a file system support
set with no supported actions, in the FileSystem::FS::FS() constructor
and in GParted_Core::get_fs().
As support for operations on partitions with unknown content is being
added, the second usage will be confusing or even wrong.
FS( FS_UNKNOWN ) constructs the no supported actions set, yet GParted
will support some actions for the FS_UNKNOWN file system type.
Therefore add FS_UNSUPPORTED for the second usage.
Closes!13 - Support copying and moving of unsupported partition content
Util-linux package, at least as far back as version 2.23.2 as found on
CentOS 7, provides the mkfs.minix and fsck.minix commands. Also blkid
from the same package, recognises minix file systems.
Create version 3 file systems because MINIX 3 [1] is the only supported
version and that reportedly uses version 3 of the file system [2].
[1] MINIX 3 / History
https://en.wikipedia.org/wiki/MINIX_3#History
[2] Regarding MINIX 3 file system
https://groups.google.com/forum/#!topic/minix3/3-TeHR_23X8
"MINIX 3 uses Minix File System (MFS). More precisely MFS V3."
Closes!12 - Add minix file system support
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.
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
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
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
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
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
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
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
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
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
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
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()
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