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
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
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
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
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
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
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().
GParted_Core methods:
flush_device()
get_device()
get_disk()
get_device_and_disk()
destroy_device_and_disk()
commit()
commit_to_os()
settle_device()
This group of methods only call libparted API functions and run external
executables. None of them access any GParted_Core member variables.
Make them all static member functions.
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()
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
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
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
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
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
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
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
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
For file systems which libparted recognises, when found on the whole
disk device, it reports with partition table "loop" and a partition
covering the whole disk. GParted duly displays this to the user.
For file systems which libparted doesn't recognise it reports
"unrecognised disk label". As of the latest libparted 3.2, these file
system aren't recognised and can't currently be shown when on the whole
disk device:
BitLocker, Crypt LUKS, exFAT, F2FS, LVM2 Physical Volume,
Linux Software RAID, ReFS, Reiser 4
So only when libparted doesn't recognise a file system on the whole disk
device and GParted does, either via blkid or it's internal code, display
this with partition table "none".
Bug 741430 - GParted cannot recognise LVM signature on unpartitioned
drive
Move code which queries the file system label and UUID of a partition
into a separate helper function.
Bug 741430 - GParted cannot recognise LVM signature on unpartitioned
drive
Refactor GParted internal file system signature detection to remove code
duplication. There were 5 separate copies of code to: allocate a
buffer, open, read and close the device, free the buffer and compare the
signature.
Bug 741430 - GParted cannot recognise LVM signature on unpartitioned
drive
Embedded devices (Android) use GPT partition names to identify
partitions, instead of file system labels. Add support for viewing and
changing them.
As partition names are used to provide unique identification they are
never copied when copying the contents of one partition to another.
Note that GNU/Linux uses file system labels, UUIDs or device names for
identification during the boot process and afterwards so while partition
names can be used, they are optional and purely for user information.
Bug 741424 - Add support for GPT partition names
This and the following few commits rename variables, methods, classes,
etc from *label_partition* to *label_filesystem* so that the code also
reflects that it is the label of the file system that is being modified
and to separate it from the name partition operation about to be added.
enum OPERATION_LABEL_PARTITION -> OPERATION_LABEL_FILESYSTEM
Bug 741424 - Add support for GPT partition names
Only recognises ReFS file system. No other actions are supported.
Requires blkid from util-linux >= 2.24.
Bug #738471 - ReFS file system is not recognised
Helper to check whether a recognised file system type is supported by
GParted or not. Supported means there is an implementation class and
will appear in the File System Support dialog.
Make supported_filesystem() a static member function so that it can be
called without a class object so that GParted_Core::GParted_Core()
initialiser isn't called multiple times. This requires FILESYSTEM_MAP
to become a static member variable too.
Bug #738471 - ReFS file system is not recognised