Commit Graph

1006 Commits

Author SHA1 Message Date
Mike Fleetwood 70cc6187d5 Fix double quote error creating XFS file systems (#744108)
Trying to create an XFS file system causes the following error and
the create new xfs file system step to never complete.

    # ./gpartedbin
    ======================
    libparted : 2.4
    ======================

    (gpartedbin:15572): 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 "mylabel" " /dev/sdb8')

Creation of XFS file systems was broken by the extra stray double quote
added to the command before the device name, by commit:

    63aeb150ac
    Rename member variables and methods in Partition class (#741424)

Bug 744108 - Creating an XFS file system never completes
2015-02-07 10:33:12 -07:00
Mike Fleetwood 9294a10fbd Correct dialog title displaying libparted exceptions (#743825)
Encountered this dialog:

    Libparted Bug Found!

    (-) Invalid argument during seek for read on /dev/md1

                          [ Retry ] [ Cancel ] [ Ignore ]

After investigation found that GParted was asking libparted to read from
sector -1.  Libparted was actually reporting an error but GParted was
incorrectly displaying this as a bug.  This was because setting the
dialog title was falling through from the error case to the bug case.
Fix this.

Also provide unique titles for all libparted exception types so that
they can all be distinguished.

 *  List of exceptions from libparted: enum _PedExceptionType
    http://www.gnu.org/software/parted/api/group__PedException.html

Bug 743825 - gparted displaying dialog: libparted bug found!
2015-02-03 09:45:55 -07:00
Curtis Gedak ed9d537227 Add Mike Fleetwood to menu_help_about 2015-02-01 13:14:05 -07:00
Curtis Gedak 44eaabc57c Provide credit for patch by Michael Zimmermann
Provide credit for patch to add support for GPT partition names.
Also indicate significant effort by Sinlu Bes while we tried different
ideas for how GPT partition name support should work.
2015-02-01 11:01:41 -07:00
Michael Zimmermann 1f5841b4ad Add support for GPT partition names (#741424)
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
2015-02-01 10:08:23 -07:00
Mike Fleetwood b278782ef6 Remove redundant second if condition in Display_Info()
Remove second inner if condition performing the same check as the outer
if:
    partition.type != GParted::TYPE_UNALLOCATED
2015-02-01 10:08:23 -07:00
Mike Fleetwood e1dc89cd11 Rename class to Dialog_FileSystem_Label (#741424)
class Dialog_Partition_Label   -> Dialog_FileSystem_Label
file Dialog_Partition_Label.h  -> Dialog_FileSystem_Label.h
file Dialog_Partition_Label.cc -> Dialog_FileSystem_Label.cc

Bug 741424 - Add support for GPT partition names
2015-02-01 10:08:23 -07:00
Mike Fleetwood 04450c577c Rename class to OperationLabelFileSystem (#741424)
class OperationLabelPartition   -> OperationLabelFileSystem
file OperationLabelPartition.h  -> OperationLabelFileSystem.h
file OperationLabelPartition.cc -> OperationLabelFileSystem.cc

Bug 741424 - Add support for GPT partition names
2015-02-01 10:08:23 -07:00
Mike Fleetwood 3630b9c83b Rename methods in GParted_Core and Win_GParted classes (#741424)
class GParted_Core:
    label_partition() -> label_filesystem()

class Win_GParted:
    allow_label_partition()    -> allow_label_filesystem()
    activate_label_partition() -> activate_label_filesystem()

Bug 741424 - Add support for GPT partition names
2015-02-01 10:08:23 -07:00
Mike Fleetwood 63aeb150ac Rename member variables and methods in Partition class (#741424)
class Partition:
    have_label    -> have_filesystem_label
    label         -> filesystem_label
    label_known() -> filesystem_label_known()
    get_label()   -> get_filesystem_label()
    set_label()   -> set_filesystem_label()

Bug 741424 - Add support for GPT partition names
2015-02-01 10:08:23 -07:00
Mike Fleetwood d480800600 Rename enum to OPERATION_LABEL_FILESYSTEM (#741424)
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
2015-02-01 10:08:23 -07:00
Mike Fleetwood 332a2e7a79 Rename Partition Label to File System Label in the GUI (#741424)
Rename the Partition Label concept to File System Label throughout the
GUI.  This is to better reflect that it is the label of the file system
that is being modified and to separate it from the Partition Name
concept about to be added.

Bug 741424 - Add support for GPT partition names
2015-02-01 10:08:23 -07:00
Mike Fleetwood 8b45219a2d Make swap usage match figures reported by swapon -s (#742647)
GParted reports used figure of active swap space from 4 KiB upwards,
actually 1 page, where as 'swapon -s' reports figures from 0 upwards.
This is because GParted is counting the 1 page swap space overhead as
used space.

    # sfdisk -s /dev/sdb1
    262144
    # mkswap /dev/sdb1
    # swapon /dev/sdb1
    # swapon -s
    Filename                Type            Size    Used    Priority
    /dev/sdb1               partition       262140  0       -1

For this case GParted reports used as 4 KiB.
(ptn size - swap size = 262144 - 262140 = 4)

Instead make GParted report used figure without any overhead from 0
upwards, matching what 'swapon -s' reports.

Bug 742647 - Swap usage doesn't match figures reported by swapon -s
2015-01-28 11:38:53 -07:00
Curtis Gedak 570680826d Update copyright year 2015-01-26 09:48:36 -07:00
Phillip Susi 8a952cd4a9 Fix off by one sector error in GParted internal block copy (#742920)
GParted's internal block copy has an off by one sector bug when the
source is before the destination; and the copy is performed backwards
from high block to low block.  It is as though the source and
destination partitions were both one sector earlier on the disk.

In ASCII art it it looks like this:

Initial layout:      x<--SRC--><--DST-->
Actually wrote:               x<--SRC--
Should have written:           <--SRC-->

Affects moving partitions too.

This bug has existed since commit:

    bd9e16f22f
    Thread the internal copy algorithm (#685740)

Effectively the last sector of the partition is missed and one sector
before the start of the partition is corrupted.  Most of the time file
systems don't get around to using the very last sector so didn't notice.

Bug 742920 - GParted internal copy is overstepping partition boundaries
2015-01-16 11:31:14 +00:00
Mike Fleetwood be8cc9c084 Allow creation of reiser4 file systems on Linux 3.x (#742511)
With reiser4progs 1.0.7 and earlier mkfs specifically checks for Linux
kernel 2.5 or 2.6.  On Linux 3.x it fails with the following warning:

    # mkfs.reiser4 --yes --label "" /dev/sdb1
    Warn : Linux 3.13.0-39-generic is detected. Reiser4 does not support
    such a platform. Use -f to force over.
    # echo $?
    8

This is fixed in reiser4progs 1.0.8 and later.  From the reiser4progs
SourceForce README.txt:

    . Do not ask for confirmation to work under Linux-3.X;

Found on Ubuntu 12.04 LTS and Ubuntu 14.04 LTS both with reiser4progs
1.0.7 and a Linux 3.x kernel.

Fix by adding "--force" flag to the mkfs command line.

Bug 742511 - Creation of reiser4 file systems fails with unsupported
             warning
2015-01-07 08:44:26 -07:00
Mike Fleetwood 95ff4fbdc9 Refactor resize() to make it even easier to understand (#741211)
Split the resizing file system and resizing partition calls in
GParted_Core::resize() into separate grow and shrink code paths.

Note that this also changes the degenerative case of calling resize()
when the partition isn't changing size, for non-swap partitions, from a
file system check step to a successful no-op.  This doesn't matter as my
testing never found resize() to be called when the partition isn't
changing size.

Also correct spelling of local variable success.

Bug 741211 - Remove unnecessary duplicate actions when resizing a
             partition
2014-12-13 10:46:35 -07:00
Mike Fleetwood 99f770ddb0 Stop recreating linux-swap twice when shrinking a partition (#741211)
Shrinking swap partition operation performs these steps:

    Shrink /dev/sdb2 from 2.00 GiB to 1.00 GiB
    + calibrate /dev/sdb2
    + check file system on /dev/sdb2 for errors and (if possible) fix them
        checking is not available for this file system
    + shrink file system
      + create new linux-swap file system
        + mkswap -L "test-swap" -U "bd381eba-5df7-42e2-8e0e-411e9701c995" /dev/sdb2
    + shrink partition from 2.00 GiB to 1.00 GiB
      + create new linux-swap file system
        + mkswap -L "test-swap" -U "bd381eba-5df7-42e2-8e0e-411e9701c995" /dev/sdb2

Resizing a linux-swap partition was partially special cased in
GParted_Core::resize().  Make it fully special cased so that it just
does the following steps.  No more skipped file system checks or extra
resizing.

    1)  Resize partition,
    2)  Recreate linux-swap.

This existing call chain recreates the linux-swap:
    GParted_Core::resize_filesystem()
        linux_swap::resize()

A compound move and resize operation still performs unnecessary checks
and recreates of linux-swap, but less than before.

Bug 741211 - Remove unnecessary duplicate actions when resizing a
             partition
2014-12-11 11:10:09 -07:00
Mike Fleetwood b4acb14ff1 Remove second file system check when growing a partition (#741211)
Shrinking a partition performs a single file system check step, but
growing a partition still performs two file system checks.

    Grow /dev/sda8 from 1.00 GiB to 10.00 GiB
    + calibrate /dev/sda8
    + check file system on /dev/sda8 for errors and (if possible) fix them
    + grow partition from 1.00 GiB to 10.00 GiB
    + check file system on /dev/sda8 for errors and (if possible) fix them
    + grow file system to fill the partition

This is a leftover from the early days of GParted when resizing a
partition used cylinder buffering and performed three file system
checks.  See prior to commit:

    d663c3c277
    removed cylindersize buffering during resize from the filesystems.

Remove the second file system check when growing a partition.

Bug 741211 - Remove unnecessary duplicate actions when resizing a
             partition
2014-12-11 11:10:09 -07:00
Mike Fleetwood 6220a35dac Rework population of the create new partition file system list
Simplify how the list of file system types is populated in the Create
New Partition dialog.  Change from copying everything and removing
unwanted items to only copying required items.  Makes the code simpler
and therefore easier to understand.
2014-10-30 09:55:01 -06:00
Mike Fleetwood 3373ef07fa Recognise ReFS file system (#738471)
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
2014-10-30 09:55:01 -06:00
Mike Fleetwood 88f67058e8 Use supported_filesystem() predicate (#738471)
Use GParted_Core::supported_filesystem() to remove the need to
explicitly list the growing number of recognised, but otherwise
unsupported, file system signatures in multiple places.

Bug #738471 - ReFS file system is not recognised
2014-10-30 09:55:01 -06:00
Mike Fleetwood 8b4b73a8f3 Add supported_filesystem() predicate method (#738471)
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
2014-10-30 09:55:01 -06:00
Mike Fleetwood e3a1b93a6d Pass by value to get_filesystem_object()
get_filesystem_object() takes a constant reference to a FILESYSTEM, but
FILESYSTEM is just an enumeration.  So that's a pointer to a constant
int.  Just pass by value instead.
2014-10-30 09:55:01 -06:00
Mike Fleetwood f672f68863 Check for e4fsprogs commands for ext4 support on RHEL/CentOS 5.x (#738706)
RHEL / CentOS 5.6 and later officially support ext4 file system [1].
From RHEL / CentOS 5.3 ext4 file system was included as a technology
preview.  Ext4 file system tools are in a separate package e4fsprogs,
using uniquely named commands.  The standard e2fsprogs commands only
support ext2 and ext3 file systems.

    # mkfs.ext4 /dev/sdb3
    # tune2fs -l /dev/sdb3
    tune2fs 1.39 (29-May-2006)
    tune2fs: Filesystem has unsupported feature(s) while trying to open /dev/sdb3
    Couldn't find valid filesystem superblock.
    # echo $?
    1
    # tune4fs -l /dev/sdb3
    tune4fs 1.41.12 (17-May-2010)
    Filesystem volume name:   <none>
    Last mounted on:          <not available>
    Filesystem UUID:          ba4a9d58-7728-4b47-8a90-80e772615637
    Filesystem magic number:  0xEF53
    Filesystem revision #:    1 (dynamic)
    Filesystem features:      has_journal ext_attr resize_inode dir_index filetype extent flex_bg sparse_super large_file huge_file uninit_bg dir_nlink extra_isize
    ...

For ext4 only, search for the e4fsprogs specific commands first and the
standard e2fsprogs commands second.

[1] RHEL 5.6 Release Notes, 5. Filesystems and Storage
https://access.redhat.com/documentation/en-US/Red_Hat_Enterprise_Linux/5/html/5.6_Release_Notes/ar01s05.html

Bug #738706 - GParted doesn't support ext4 on RHEL/CentOS 5.x
2014-10-27 09:32:36 -06:00
Mike Fleetwood 0fb8cce699 Reduce flashing redraw from automatic partition selection (#696149)
Automatic selection of the largest unallocated partition caused flashing
redraw of the partition graphic and partition list.  Both the partition
graphic and partition list were being drawn blank then redrawn fully
populated.  This only happened on some distributions including:
CentOS 5.10, 6.5, 7.0, Debian 6, Fedora 14, 20, Xubuntu 14.04 LTS.  Did
not happen on: Kubuntu 12.04 LTS.

This is a workaround, not a complete fix.  It moves automatic selection
of the largest unallocated partition to after processing of the GTK
Event loop in Refresh_Visual() which redraws the partition graphic and
partition list.  These visuals are now drawn only once, fully populated,
however this draws them without the selected partition.  The partition
selection is then drawn afterwards which causes the selection to flash
instead.  This is significant improvement to the whole partition graphic
and partition list flashing when redrawn.

Bug #696149 - Double refresh of display introduced with default
              unallocated space
2014-10-07 10:38:27 -06:00
Mike Fleetwood 52ee26f971 Prevent flashing redraw of the devices combobox (#696149)
The device combobox was getting drawn blank, then getting drawn again
with the selected device.  This was happening because at the start of
Win_GParted::refresh_combo_devices() the GTK model behind the combobox,
liststore_devices, was cleared, changing the active item, causing the
combobox to get redrawn empty.  After the GTK model had been repopulated
the active item was reset causing the comboxbox to get redrawn again,
now showing the selected device.  Call flow:

    Win_GParted::refresh_combo_devices()
        liststore_devices->clear()
            //Gtk::Combobox emits signal_change.  Registered callbacks
            //called.
                Win_GParted::combo_devices_changed()
                    Win_GParted::Refresh_Visual()
                        ...
        ...
        combo_devices.set_active(current_device);
            //Gtk::Combobox emits signal_change.  Registered callbacks
            //called.
                Win_GParted::combo_devices_changed()
                    Win_GParted::Refresh_Visual()
                        ...

This has always been the case, since the device combobox was first added
to GParted before version 0.1 by commit:

    3a4b43e0ad
    replaced deprecated OptionMenu with ComboBox ...

Fix by temporarily blocking the devices comboxbox from emitting
signal_changed while the GTK model behind the combobox is recreated.

However, since automatic selection of the largest free space was added
[1] in GParted 0.15.0, a more noticeable flashing redraw issue was
caused in which the partition graphic and partition list were both drawn
blank then redrawn fully populated.  Some distributions were not
affected by this at all, some only experienced a single flash and others
suffered from two or more flashing redraws.  Some affected
distributions: CentOS 5.10, 6.5, 7.0, Debian 6, Fedora 14, 19, 20,
Ubuntu 13.10, Xubuntu 14.04 LTS.  Did not occur on Kubuntu 12.04 LTS.

[1] 5b53c12f6e
    Select largest unallocated partition by default (#667365)

Bug #696149 - Double refresh of display introduced with default
              unallocated space
2014-10-07 10:38:27 -06:00
Mike Fleetwood e8533c39c2 Prevent automake warning about deprecated INCLUDES (#735742)
Automake 1.13 and later generates the following warning when building
GParted from git:

    $ ./autogen.sh
    ...
    checking for automake >= 1.9...
      testing automake-1.13... found 1.13.4
    ...
    Running automake-1.13...
    src/Makefile.am:1: warning: 'INCLUDES' is the old name for 'AM_CPPFLAGS' (or '*_CPPFLAGS')
    ...

INCLUDES name has been depreciated since automake 1.7.  GParted's
autogen.sh and configure.ac require at least automake 1.9.  Therefore
replace automake variable INCLUDES with AM_CPPFLAGS.

Bug #735742 - automake warns INCLUDES is deprecated
2014-08-31 11:19:57 -06:00
Mike Fleetwood 20158f0440 Tidyup Autoconf check for --disable-doc (#734076)
Use AC_ARG_ENABLE() and AS_HELP_STRING() macros to improve handling of
the --disable-doc option.

Change the names, and sence, of the Autoconf and Automake definitions
used to control building of the help documentation.  Reasons are:
(1) Switch from negative to positive statements which are more natural
    to comprehend.
(2) Insert HELP in the names from *_DOC to *_HELP_DOC as they control
    building of the documentation in the help subdirectory, not the
    manual page in the doc directory.

Autoconf: HAVE_DISABLE_DOC -> ENABLE_HELP_DOC
Automake: DISABLE_DOC      -> BUILD_HELP_DOC

Bug #734076 - Autodetect parted online partition resizing capability
2014-08-31 11:04:36 -06:00
Mike Fleetwood 3030118caf Pass link libraries via LIBS variable into Makefiles (#734718)
Currently -lparted is passed to the linker by being hard coded in the
gpartedbin_LDFLAGS variable in src/Makefile.am and -lparted-fs-resize
by conditionally being appended to the gpartedbin_LDFLAGS.

Add an Autoconf AC_CHECK_LIB check for the parted library using it's
default action-if-found to extend LIBS.  Update the existing
AC_CHECK_LIB check for the parted-fs-resize library so that the
overridden action-if-found also extends LIBS with -lparted-fs-resize.
These libraries are then assigned via the LIBS variable in the
generated Makefiles.

This matches how the other libraries, dl and uuid, were found in the
configure script and passed to the Makefiles.

Bug #734718 - Update Autoconf version specific libparted checks and
              defines to feature specific ones
2014-08-18 15:48:34 -06:00
Mike Fleetwood ed4ea6cf03 Rename HAVE_LIBPARTED_2_2_0_PLUS define into feature names (#734718)
Remove HAVE_LIBPARTED_2_2_0_PLUS definition

Rename version specific #define HAVE_LIBPARTED_2_2_0_PLUS into two
separate feature specific names set as required:

    Name                                  Set when?

    ENABLE_PT_REREAD_WORKAROUND           (libparted < 2.2)
    USE_LIBPARTED_LARGE_SECTOR_SUPPORT    (libparted >= 2.2)

Using feature specific #defines is the standard Autoconf way and makes
the resultant conditional code easier to understand.  Still have to
check the version of libparted though.

Bug #734718 - Update Autoconf version specific libparted checks and
              defines to feature specific ones
2014-08-18 15:48:34 -06:00
Mike Fleetwood 288c4dbf2e Remove little used HAVE_LIBPARTED_3_0_0_PLUS definition (#734718)
Remove HAVE_LIBPARTED_3_0_0_PLUS definition

The #define only controls whether fat16 and fat32 file systems are moved
by libparted (for versions <= 2.4) or the GParted internal algorithm
(for libparted versions >= 3.0).  See this commit for more details:
    0fda1d011d
    Enable new fs resize library available with parted-3.1 (#668281)

As nearly all other file system are moved using the GParted internal
algorithm, just always use it to move fat16 and fat32 file systems too.

Bug #734718 - Update Autoconf version specific libparted checks and
              defines to feature specific ones
2014-08-18 15:48:34 -06:00
Mike Fleetwood a4f761e290 Update parsing of btrfs filesystem show for multi-device membership (#733601)
This patch changes the reading of the btrfs multi-device membership to
resolve issue 1/2 by ignoring the exit status from the 'btrfs filesystem
show' command and relying on parsing the required information to
determine success or failure.

Bug #733601 - Btrfs: Warnings and missing label with btrfs-progs 3.12
              and 3.14
2014-07-28 10:06:00 -06:00
Mike Fleetwood 422829ebff Update parsing of btrfs filesystem show for file system usage (#733601)
Patch 3/4 - btrfs::read_label()

This patch changes the btrfs file system usage reading code to resolve
issue 1/2 by ignoring the exit status from the 'btrfs filesystem show'
command and relying on parsing the required information to determine
success or failure.

Bug #733601 - Btrfs: Warnings and missing label with btrfs-progs 3.12
              and 3.14
2014-07-28 10:06:00 -06:00
Mike Fleetwood eca732fb0c Update parsing of btrfs filesystem show for the label (#733601)
Issue 2/2 - GParted doesn't show label for mounted btrfs file systems

'btrfs filesystem show /dev/PTN' command is used to query details of a
btrfs file system including reading the file system label.  When the
file system is mounted the label is no longer enclosed in single quotes,
but only when using btrfs-progs v3.12.  This causes GParted to think the
label is blank when the file system is mounted and therefore no longer
display it.

File system label not enclosed in single quotes when mounted:

    # fgrep sdb1 /proc/mounts
    /dev/sdb1 /mnt/1 btrfs rw,relatime,space_cache 0 0
    # btrfs filesystem show /dev/sdb1
    Label: test1-btrfs  uuid: 1f78fa38-2f85-41d3-9be6-ae0356ae9469
            Total devices 1 FS bytes used 192.00KiB
            devid    1 size 2.00GiB used 240.75MiB path /dev/sdb1

    Btrfs v3.12

File system label enclosed in single quotes when unmounted:

    # umount /dev/sdb1
    # btrfs filesystem show /dev/sdb1
    Label: 'test1-btrfs'  uuid: 1f78fa38-2f85-41d3-9be6-ae0356ae9469
            Total devices 1 FS bytes used 192.00KiB
            devid    1 size 2.00GiB used 240.75MiB path /dev/sdb1

    Btrfs v3.12

Removing the single quotes enclosing the label makes the output
identical to that from the older 'btrfs-show' command.

Fix by using a common parser to extract the label from both the
'btrfs filesystem show' and 'btrfs-show' commands which can read the
label with and without enclosing single quotes.

Patch 2/4 - btrfs::read_label()

This patch changes the btrfs file system label parsing code to resolve
issue 1/2 by ignoring the exit status from the 'btrfs filesystem show'
command and relying on parsing the required information to determine
success or failure.  Issue 2/2 is also resolved as described above.

Bug #733601 - Btrfs: Warnings and missing label with btrfs-progs 3.12
              and 3.14
2014-07-28 10:06:00 -06:00
Mike Fleetwood 82c6265fa5 Update parsing of btrfs filesystem show for the UUID (#733601)
Issue 1/2 - GParted shows warnings for mounted btrfs file systems

'btrfs filesystem show /dev/PTN' command is used to query details of a
btrfs file system.  When the file system is mounted the command reports
failed exit status 1, but only when using btrfs-progs v3.14 and v3.14.1.
This causes GParted to: (1) report warnings from the failed commands for
a mounted btrfs file system, (2) fail to determine file system usage
figures and (3) fail to display the mount point and busy indicator for
non-mounting devices in multi-device btrfs file systems.  The label is
also read using the secondary blkid method via the FS_Info cache.

Failed exit status 1 when the btrfs file system is mounted:

    # fgrep sdb1 /proc/mounts
    /dev/sdb1 /mnt/1 btrfs rw,seclabel,relatime,space_cache 0 0
    # btrfs filesystem show /dev/sdb1
    Label: 'test1-btrfs'  uuid: 033e6b07-ee6a-4620-a585-8580a2b83275
            Total devices 1 FS bytes used 192.00KiB
            devid    1 size 2.00GiB used 240.75MiB path /dev/sdb1

    Btrfs v3.14.1
    # echo $?
    1

Successful exit status 0 when the btrfs file system is unmounted:

    # umount /dev/sdb1
    # btrfs filesystem show /dev/sdb1
    Label: 'test1-btrfs'  uuid: 033e6b07-ee6a-4620-a585-8580a2b83275
            Total devices 1 FS bytes used 192.00KiB
            devid    1 size 2.00GiB used 240.75MiB path /dev/sdb1

    Btrfs v3.14.1
    # echo $?
    0

Fix by ignoring the exit status of the 'btrfs filesystem show' command
and rely on parsing the required information to determine success or
failure.  The output from the older 'btrfs-show' command is almost
identical so the same code will parse it in all cases.

Patch 1/4 - btrfs::read_uuid()

This patch changes the secondary method used to read the btrfs UUID to
resolve issue 1/2 as described above.

Bug #733601 - Btrfs: Warnings and missing label with btrfs-progs 3.12
              and 3.14
2014-07-28 10:06:00 -06:00
Mike Fleetwood 3bea067596 Flush devices when scanning to prevent reading stale signatures (#723842)
While one partition is busy, reformat another partition from the command
line.  Afterwards parted/libparted still detects the original file
system and GParted shows errors from the file system specific tools
reporting the new file system doesn't exist.  Only limitation is that
the new new file system must be recognised by libparted (or by GParted's
fallback file system signature detection).

Case #1, File system reformatting:

    # 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  2149MB  2147MB  primary  ext2
     2      2149MB  4296MB  2147MB  primary  ext2
    # mount | fgrep sdb
    /dev/sdb1 on /mnt/1 type ext2 (rw)

    # mkfs.xfs -f /dev/sdb2
    # blkid /dev/sdb2
    /dev/sdb2: UUID="c31823a2-b81b-46fa-8246-0a59695e4834" TYPE="xfs"
    # 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  2149MB  2147MB  primary  ext2
     2      2149MB  4296MB  2147MB  primary  ext2
    # e2label /dev/sdb2
    e2label: Bad magic number in super-block while trying to open /dev/sdb2
    Couldn't find valid filesystem superblock.
    # dumpe2fs /dev/sdb2
    dumpe2fs 1.41.12 (17-May-2010)
    dumpe2fs: Bad magic number in super-block while trying to open /dev/sdb2
    Couldn't find valid filesystem superblock.

Case #2, Removing device from multi-device btrfs:

    # btrfs filesystem show /dev/sdb1
    Label: none  uuid: a05db434-efd5-4e8c-902f-05f89a88b610
            Total devices 2 FS bytes used 156.00KB
            devid    2 size 2.00GB used 512.00MB path /dev/sdb2
            devid    1 size 2.00GB used 240.75MB path /dev/sdb1

    # mount /dev/sdb1 /mnt/1
    # btrfs device delete /dev/sdb2
    # btrfs filesystem show /dev/sdb1
    Label: none  uuid: a05db434-efd5-4e8c-902f-05f89a88b610
            Total devices 1 FS bytes used 92.00KB
            devid    1 size 2.00GB used 714.25MB path /dev/sdb1
    # btrfs filesystem show /dev/sdb2

and GParted reports this error for partition /dev/sdb2:
    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 btrfs
    file system support:  btrfs-tools.

This is another case of libparted reading from the whole disk device
(/dev/sdb) yet the file system tools use the partition specific block
device (/dev/sdb2), and the Linux buffer cache not providing cache
coherency.  Previous scenario was fixed with:

    797f0b8eeb
    Flush device after wiping a file system (#688882)

This affects libparted 2.0 to 3.1 inclusive and is fixed by:

    http://git.savannah.gnu.org/cgit/parted.git/commit/?id=fb99ba5ebd0dc34204fc9f1014131d5d494805bc
    Revert "linux-commit: do not unnecessarily open partition device nodes"

Fix by calling ped_device_sync() to guarantee cache coherency for each
device during scanning.

Bug #723842 - GParted resizes the wrong filesystem (does not pass the
              devid to btrfs filesystem resize)
2014-07-28 10:03:16 -06:00
Mike Fleetwood 20f52e2866 Display btrfs members in the Partition Information dialog (#723842)
Bug #723842 - GParted resizes the wrong filesystem (does not pass the
              devid to btrfs filesystem resize)
2014-07-28 10:03:16 -06:00
Mike Fleetwood 4b63e46a4e Fallback to reading mount command output instead of /etc/mtab (#723842)
With linux 3.5 and later, the device used to mount a btrfs file system
is updated in /proc/mounts when the previous mounting device is removed
from the file system.  Most recent distributions make /etc/mtab a
symbolic link to /proc/mounts.  However some still have /etc/mtab as a
plain file only updated by mount and umount, thus showing the old device
name which is no longer part of the file system.

On Ubuntu 13.10, which has /etc/mtab as a plain file managed by mount
and umount:

    # mkfs.btrfs /dev/sdb1
    # mount /dev/sdb1 /mnt/1
    # btrfs device add /dev/sdb2 /mnt/1
    # btrfs device delete /dev/sdb1 /mnt/1
    # sync
    # btrfs filesystem show /dev/sdb1
    # btrfs filesystem show /dev/sdb2
    Label: none  uuid: e47775a6-e5ad-4fb4-9ea4-1570aa5b4009
            Total devices 2 FS bytes used 28.00KB
            devid    2 size 2.00GB used 272.00MB path /dev/sdb2

    # fgrep btrfs /proc/mounts
    /dev/sdb2 /mnt/1 btrfs rw,relatime,space_cache 0 0
    # ls -l /etc/mtab
    -rw-r--r-- 1 root root 842 Apr 15 19:41 /etc/mtab
    # fgrep btrfs /etc/mtab
    /dev/sdb1 /mnt/1 btrfs rw 0 0

This causes GParted to report /dev/sdb1 as busy and mounted at /mnt/1
when it is no longer mounted.  This effects recent releases of Ubuntu,
13.04, 13.10 and 14.04.

Either /etc/mtab is a symlink and is identical to /proc/mounts or
/etc/mtab is a plain file with wrong information.  Fix by not reading
mounted file systems from /etc/mtab.

However old distributions only contain 'rootfs' and '/dev/root' device
names for the / (root) file system with '/dev/root' being a block device
rather than a symlink to the true device.  For example from CentOS 5.x:

    # fgrep ' / ' /proc/mounts
    rootfs / rootfs rw 0 0
    /dev/root / ext3 rw,data=ordered 0 0
    # ls -l /dev/root
    brw------- 1 root root 8, 3 Jun  4  2013 /dev/root

This prevents identification, and therefore busy detection, of the
device containing the / (root) file system.  Used to read /etc/mtab to
get the root file system device name.

    # fgrep ' / ' /etc/mtab
    /dev/sda3 / ext3 rw 0 0
    # ls -l /dev/sda3
    brw-r----- 1 root disk 8, 3 Jun  4  2013 /dev/sda3

As per commit:

    409096f739
    improved scanning for root mountpoint (/) ...

but, as discussed above, this contains an out of date device name after
the mounting device has been dynamically removed from a multi-device
btrfs, thus identifying the wrong device as busy.  Instead fall back to
reading mounted file systems from the output of the mount command, but
only when required.

    # mount | fgrep ' / '
    /dev/sda3 on / type ext3 (rw)

Bug #723842 - GParted resizes the wrong filesystem (does not pass the
              devid to btrfs filesystem resize)
2014-07-28 10:03:16 -06:00
Mike Fleetwood d47783eff8 Add fallback busy detection for btrfs file systems (#723842)
In a number of cases there may be no btrfs device cache entry.  Some of
the reasons why this can occur:
1)  Mounting device removed from btrfs on linux <= 3.4 so old mount
    point in /proc/mounts;
2)  btrfs and btrfs-show commands don't exist;
3)  btrfs or btrfs-show command returned non-zero exit status;
4)  get_cache_entry() failed to parse output from btrfs filesystem show
    or btrfs-show.

Without a valid btrfs device cache entry, busy detection for all member
devices fails.  Search the GParted internal mounted partitions map as
the fallback busy detection method.  This can only determine if the
mounting device is mounted or not, not any of the other members of a
multi-device btrfs file system.

Bug #723842 - GParted resizes the wrong filesystem (does not pass the
              devid to btrfs filesystem resize)
2014-07-28 10:03:16 -06:00
Mike Fleetwood 0e980a47a2 Pass devid when resizing btrfs file systems (#723842)
GParted doesn't specify the devid when resizing a btrfs file system, so
the kernel defaults to resizing devid 1.  On a multi-device btrfs this
may not be the same partition which GParted is resizing.  This will
result in file system truncation and corruption.  Shrinking the wrong
partition example:

    1)  Create a btrfs file system spanning 2 partitions:
            # mkfs.btrfs /dev/sdb1 /dev/sdb2
            # btrfs filesystem show /dev/sdb1
            Label: none  uuid: 41654265-9840-45c4-aca1-55989da358d6
                    Total devices 2 FS bytes used 112.00KiB
                    devid    1 size 2.00GiB used 437.50MiB path /dev/sdb1
                    devid    2 size 2.00GiB used 417.50MiB path /dev/sdb2

    2)  Resize /dev/sdb2 down to 1 GiB using GParted.  This command was
        run:
            btrfs filesystem resize 1048576K /tmp/gparted-ddyGRh
        which resized devid 1 (/dev/sdb1) to 1 GiB:
            # btrfs filesystem show /dev/sdb1
            Label: none  uuid: 41654265-9840-45c4-aca1-55989da358d6
                    Total devices 2 FS bytes used 256.00KiB
                    devid    1 size 1.00GiB used 437.50MiB path /dev/sdb1
                    devid    2 size 2.00GiB used 417.50MiB path /dev/sdb2
        but GParted instead resized /dev/sdb2 to 1 GiB:
            # sfdisk -s /dev/sdb1
            2097152
            # sfdisk -s /dev/sdb2
            1048576

Even on a single device btrfs devid 1 may no longer exist if the file
system has had the initial device removed from it.  Example:

    1)  Create a single btrfs file system, add a second device and
        remove the first:
            # mkfs.btrfs /dev/sdb1
            # mount /dev/sdb1 /mnt/1
            # btrfs device add /dev/sdb2 /mnt/1
            # btrfs device remove /dev/sdb1 /mnt/1
            # umount /mnt/1
            # btrfs filesystem show /dev/sdb2
            Label: none  uuid: 2cbf3ac3-1344-472a-a0c7-1476d23bdc9f
                    Total devices 1 FS bytes used 256.00KiB
                    devid    2 size 2.00GiB used 480.00MiB path /dev/sdb2

    2)  Again resize /dev/sdb2 down to 1 GiB using GParted.  This
        command was run:
            btrfs filesystem resize 1048576K /tmp/gparted-ddyGRh
        but it failed with:
            ERROR: unable to resize 'tmp/gparted-lEyGaY' - No such device
        A more informative error message was written to syslog:
            # tail -1 /var/log/messages
            Mar 12 14:15:01 localhost kernel: btrfs: resizer unable to find device 1

This is with Linux kernel 3.13.5 on Fedora 20, circa March 2014.

Fix by specifying the devid when resizing (part of) a btrfs file system.
Example command specifying devid 2:

    btrfs filesystem resize 2:1048576K /tmp/1

This will always work because it is the kernel which interprets the
devid colon size parameter and has always done so since btrfs was first
added to the kernel in version 2.6.32 [1].

Reference:
[1] linux v2.6.32 fs/btrfs/ioctl.c btrfs_ioctl_resize()
    https://git.kernel.org/cgit/linux/kernel/git/torvalds/linux.git/tree/fs/btrfs/ioctl.c?id=v2.6.32#n578

Bug #723842 - GParted resizes the wrong filesystem (does not pass the
              devid to btrfs filesystem resize)
2014-07-28 10:03:16 -06:00
Mike Fleetwood 287526681d Add devid to the cache of btrfs device information (#723842)
Bug #723842 - GParted resizes the wrong filesystem (does not pass the
              devid to btrfs filesystem resize)
2014-07-28 10:03:16 -06:00
Mike Fleetwood 1712809e01 Display usage for multi-device btrfs file systems (#723842)
Currently GParted fails to report the usage of a multi-device btrfs file
system if it is mounted or if the used space is larger than the size of
an individual member device.  When GParted does display usage figures it
also incorrectly reports the file system wide used figure against every
member device.

Mounted case:
    statvfs() provides an FS size which is larger than any individual
    device so is rejected.  See:
        GParted_Core::mounted_set_used_sectors()
            Utils::get_mounted_filesystem_usage()
            partition .set_sector_usage()

Unmounted case, FS used > device size:
    FS used figure is larger than any individual device so free space is
    calculated as a negative number and rejected.  See:
        btrfs::set_used_sectors()

Btrfs has a volume manager layer within the file system which allows it
to provide multiple levels of data redundancy, RAID levels, and use
multiple devices both of which can be changed while the file system is
mounted.  To achieve this btrfs has to allocate space at two different
level: (1) chunks of 256 MiB or more at the volume manager level; and
(2) extents at the file data level.
References:
*   Btrfs: Working with multiple devices
    https://lwn.net/Articles/577961/
*   Btrfs wiki: Glossary
    https://btrfs.wiki.kernel.org/index.php/Glossary

This makes the question of how much disk space is being used in an
individual device a complicated question to answer.  Further, the
current btrfs tools don't provide the required information.

Btrfs filesystem show only provides space usage information at the chunk
level per device.  At the file extent level only a single figure for the
whole file system is provided.  It also reports size of the data and
metadata being stored, not the larger figure of the amount of space
taken after redundancy is applied.  So it is impossible to answer the
question of how much disk space is being used in an individual device.
Example output:

    Label: none  uuid: 36eb51a2-2927-4c92-820f-b2f0b5cdae50
            Total devices 2 FS bytes used 156.00KB
            devid    2 size 2.00GB used 512.00MB path /dev/sdb2
            devid    1 size 2.00GB used 240.75MB path /dev/sdb1

Fix by guesstimating the per device used figure as the fraction of the
file system wide extent usage based on chunk usage per device.
Calculation:
    ptn fs used = total fs used * devid used / sum devid used

Positives:
1) Per device used figure will correctly be between zero and allocated
   chunk size.

Known inaccuracies:
[for single and multi-device btrfs file systems]
1) Btrfs filesystem show reports file system wide file extent usage
   without considering redundancy applied to that data.  (By default
   btrfs stores two copies of metadata and one copy of data).
2) At minimum size when all data has been consolidated there will be a
   few partly filled chunks of 256 MiB or more for data and metadata of
   each storage profile (RAID level).
[for multi-device btrfs file systems only]
3) Data may be far from evenly distributed between the chunks on
   multiple devices.
4) Extents can be and are relocated to other devices within the file
   system when shrinking a device.

Bug #723842 - GParted resizes the wrong filesystem (does not pass the
              devid to btrfs filesystem resize)
2014-07-28 10:03:16 -06:00
Mike Fleetwood a086e115e5 Display mount points for multi-device btrfs file systems (#723842)
Linux can only show a single device name in /proc/mounts and /etc/mtab
for each mounted btrfs, even if it is a multi-device file system.  So
GParted only shows a mount point for one of the devices in the btrfs, no
matter how many devices are part of the file system.

    # mkfs.btrfs /dev/sdb1 /dev/sdb2
    # btrfs filesystem show /dev/sdb1
    Label: none  uuid: 36eb51a2-2927-4c92-820f-b2f0b5cdae50
            Total devices 2 FS bytes used 156.00KB
            devid    2 size 2.00GB used 512.00MB path /dev/sdb2
            devid    1 size 2.00GB used 240.75MB path /dev/sdb1
    # mount /dev/sdb1 /mnt/1
    # grep btrfs /proc/mounts
    /dev/sdb1 /mnt/1 btrfs rw,seclabel,relatime,ssd,space_cache 0 0

GParted only shows the mount point for /dev/sdb1 as /mnt/1, but nothing
for /dev/sdb2.

Make GParted report the same mount point for all devices included in a
multi-device btrfs file system.

Add btrfs specific get_mount_device() method to report the mounting
device, if any, for the btrfs file system in the occupying the device in
question.  Uses the existing cache of btrfs file system device
membership.  Also extract common code from GParted_Core::
set_mountpoints() into set_mountpoints_helper().

Bug #723842 - GParted resizes the wrong filesystem (does not pass the
              devid to btrfs filesystem resize)
2014-07-28 10:03:16 -06:00
Mike Fleetwood 76e64f2905 Detect busy status of multi-device btrfs file systems (#723842)
Busy detection of file systems works by checking if the device is
mounted (appears in the mount_info map).  For a multi-device btrfs file
system this will only report one of the devices as busy, not all of
them.

    # btrfs filesystem show /dev/sdb1
    Label: none  uuid: 36eb51a2-2927-4c92-820f-b2f0b5cdae50
            Total devices 2 FS bytes used 156.00KB
            devid    2 size 2.00GB used 512.00MB path /dev/sdb2
            devid    1 size 2.00GB used 240.75MB path /dev/sdb1
    # mount /dev/sdb1 /mnt/1
    # grep btrfs /proc/mounts
    /dev/sdb1 /mnt/1 btrfs rw,seclabel,relatime,ssd,space_cache 0 0

GParted will only report /dev/sdb1 as busy, but not /dev/sdb2.

Add btrfs specific is_busy() method which reports the device as busy if
any of the devices in the btrfs file system are mounted.  This uses a
cache which maps device membership in all btrfs file systems.  The cache
is cleared on GParted refresh and incrementally populated as each btrfs
partition is checked for busy status.

WARNING:
Removal of the mounting device from a btrfs file system makes it
impossible to determine whether the file system is mounted or not for
linux <= 3.4.  This is because /proc/mounts continues to show the old
device which is no longer a member of the file system.

    # btrfs device delete /dev/sdb1 /mnt/1
    # sync
    # grep btrfs /proc/mounts
    /dev/sdb1 /mnt/1 btrfs rw,seclabel,relatime,ssd,space_cache 0 0
    # btrfs filesystem show /dev/sdb1
    # btrfs filesystem show /dev/sdb2
    Label: none  uuid: 36eb51a2-2927-4c92-820f-b2f0b5cdae50
            Total devices 1 FS bytes used 28.00KB
            devid    2 size 2.00GB used 1.02GB path /dev/sdb2

Fixed in linux 3.5 by commit:
    Btrfs: implement ->show_devname
    https://git.kernel.org/cgit/linux/kernel/git/torvalds/linux.git/commit/?id=9c5085c147989d48dfe74194b48affc23f376650

Bug #723842 - GParted resizes the wrong filesystem (does not pass the
              devid to btrfs filesystem resize)
2014-07-28 10:03:16 -06:00
Mike Fleetwood a0c0533e3e Add is_dev_mounted() to expose core partition is mounted test (#723842)
Add static member function GParted_Core::is_dev_mounted() so that other
modules can determine if a particular partition contains a mounted file
system or not.

Make it a static member function so that it can be called without
needing the gparted_core object.  Extend to make the group of
manipulated variables (mount_info, fstab_info) and manipulating
functions (init_maps(), read_mountpoints_from_file(),
read_mountpoints_from_file_swaps(), get_all_mountpoints()) static too.

Bug #723842 - GParted resizes the wrong filesystem (does not pass the
              devid to btrfs filesystem resize)
2014-07-28 10:03:16 -06:00
Mike Fleetwood 49a2e19462 Restore busy detection of unknown mounted file systems (#723842)
Previous commit:
    Make partition busy detection method selectable per file system
    (#723842)
causes GParted to no longer detect an unknown mounted file system as
busy.

This is needed because there are many less popular file systems which
Linux can mount but GParted doesn't recognise, such as: Acorn ADFS,
AFFS, BeFS, BFS, etc.  Encountering an unrecognised mounted device can
also occur with btrfs on Linux 3.4 and earlier when the mounting device
is deleted from a multi-device btrfs file system.  Happens because
/proc/mounts continues to show the original mounting device even after
that device was deleted from the file system.

    # mkfs.btrfs /dev/sdb1
    # mount /dev/sdb1 /mnt/1
    # btrfs device add /dev/sdb2 /mnt/1
    # btrfs device delete /dev/sdb1 /mnt/1
    # btrfs filesystem sync /mnt/1
    # grep btrfs /proc/mounts
    /dev/sdb1 /mnt/1 btrfs rw,seclabel,relatime,ssd,space_cache 0 0
    # blkid /dev/sdb1
    # btrfs filesystem show /dev/sdb1
    # blkid /dev/sdb2
    /dev/sdb2: UUID="9c75647c-217a-4718-bcc7-f3ccd8cc7dc6" UUID_SUB="b5d43630-80d4-42ac-b406-185e97cd5bbe" TYPE="btrfs"
    # btrfs filesystem show /dev/sdb2
    Label: none  uuid: 9c75647c-217a-4718-bcc7-f3ccd8cc7dc6
            Total devices 1 FS bytes used 28.00KB
            devid    2 size 2.00GB used 1.02GB path /dev/sdb2

Reinstate the search for mounted partitions for busy detection even for
unrecognised file system types.

Bug #723842 - GParted resizes the wrong filesystem (does not pass the
              devid to btrfs filesystem resize)
2014-07-28 10:03:16 -06:00
Mike Fleetwood b1dc9e69e3 Make partition busy detection method selectable per file system (#723842)
GParted's primary inbuilt busy detection method is "is the partition
mounted?".  A custom method is used for LVM2 PV because its not a
mounted file system.

Make busy detection selectable per file system type.

    .fs.busy = FS::NONE  (default)
        No busy detection.

    .fs.busy = FS::GPARTED
        Use internal GParted method which checks if the partition is
        mounted.

    .fs.busy = FS:EXTERNAL
        Call the file system type's member function is_busy().

LVM2 PV busy detection changes from a special case to just electing to
call the lvm2_pv::is_busy() method.  Linux Software RAID remains a
special case because it's only recognised, but not otherwise supported.

Bug #723842 - GParted resizes the wrong filesystem (does not pass the
              devid to btrfs filesystem resize)
2014-07-28 10:03:16 -06:00
Mike Fleetwood 0fcfd18061 Prevent cross thread write after free in _OnReadable() (#731752)
Fragment of debugging and valgrind output:
D: tid=2193 main()
...
D: tid=2202 GParted_Core::set_devices_thread()
...
D: tid=2202 Utils::execute_command(command="dumpe2fs -h /dev/sda1", output, error, use_C_locale=1)
D: tid=2202 this=0x13fef4a0 PipeCapture::PipeCapture()
D: tid=2202 this=0x13fef4f0 PipeCapture::PipeCapture()
D: tid=2202 this=0x13fef4a0 PipeCapture::connect_signal()
D:  sourceid=77
D: tid=2202 this=0x13fef4f0 PipeCapture::connect_signal()
D:  sourceid=78
D: tid=2193 data=0x13fef4a0 PipeCapture::_OnReadable()
D: tid=2193 this=0x13fef4a0 PipeCapture::OnReadable()
D:  signal_update.emit()
D:  return true
D: tid=2193 data=0x13fef4f0 PipeCapture::_OnReadable()
D: tid=2193 this=0x13fef4f0 PipeCapture::OnReadable()
D:  signal_update.emit()
D:  return true
D: tid=2193 data=0x13fef4a0 PipeCapture::_OnReadable()
D: tid=2193 this=0x13fef4a0 PipeCapture::OnReadable()
D:  signal_update.emit()
D:  return true
D: tid=2193 data=0x13fef4f0 PipeCapture::_OnReadable()
D: tid=2193 this=0x13fef4f0 PipeCapture::OnReadable()
D:  signal_eof.emit()
D:  return false
D:  (!rc)  &(pc->sourceid)=0x13fef518
D: tid=2193 data=0x13fef4a0 PipeCapture::_OnReadable()
D: tid=2193 this=0x13fef4a0 PipeCapture::OnReadable()
D:  signal_update.emit()
D:  return true
D: tid=2193 data=0x13fef4a0 PipeCapture::_OnReadable()
D: tid=2193 this=0x13fef4a0 PipeCapture::OnReadable()
D:  signal_update.emit()
D:  return true
D: tid=2193 data=0x13fef4a0 PipeCapture::_OnReadable()
D: tid=2193 this=0x13fef4a0 PipeCapture::OnReadable()
D:  signal_eof.emit()
D: tid=2202 this=0x13fef4f0 PipeCapture::~PipeCapture()
D:  sourceid=0
D: tid=2202 this=0x13fef4a0 PipeCapture::~PipeCapture()
D:  sourceid=77
D:  return false
D:  (!rc)  &(pc->sourceid)=0x13fef4c8
==2193== Thread 1:
==2193== Invalid write of size 4
==2193==    at 0x490580: GParted::PipeCapture::_OnReadable(_GIOChannel*, GIOCondition, void*) (PipeCapture.cc:56)
==2193==    by 0x38662492A5: g_main_context_dispatch (gmain.c:3066)
==2193==    by 0x3866249627: g_main_context_iterate.isra.24 (gmain.c:3713)
==2193==    by 0x3866249A39: g_main_loop_run (gmain.c:3907)
==2193==    by 0x3D7FD45C26: gtk_main (gtkmain.c:1257)
==2193==    by 0x469743: GParted::GParted_Core::set_devices(std::vector<GParted::Device, std::allocator<GParted::Device> >&) (GParted_Core.cc:155)
==2193==    by 0x4A78F1: GParted::Win_GParted::menu_gparted_refresh_devices() (Win_GParted.cc:1259)
==2193==    by 0x4A7886: GParted::Win_GParted::on_show() (Win_GParted.cc:1253)
==2193==    by 0x3D82B2009C: Gtk::Widget_Class::show_callback(_GtkWidget*) (widget.cc:3855)
==2193==    by 0x3867210297: g_closure_invoke (gclosure.c:777)
==2193==    by 0x3867221B86: signal_emit_unlocked_R (gsignal.c:3516)
==2193==    by 0x386722A0F1: g_signal_emit_valist (gsignal.c:3330)
==2193==  Address 0x13fef4c8 is not stack'd, malloc'd or (recently) free'd
==2193==

PipeCapture.cc (with debugging):
    46  gboolean PipeCapture::_OnReadable( GIOChannel *source,
    47                                     GIOCondition condition,
    48                                     gpointer data )
    49  {
    50          std::cout << "D: tid=" << (long int)syscall(SYS_gettid) << " data=" << data << " PipeCapture::_OnReadable()" << std::endl;
    51          PipeCapture *pc = static_cast<PipeCapture *>(data);
    52          gboolean rc = pc->OnReadable( Glib::IOCondition(condition) );
    53          if (!rc)
    54          {
    55                  std::cout << "D:  (!rc)  &(pc->sourceid)=" << &(pc->sourceid) << std::endl;
    56                  pc->sourceid = 0;
    57          }
    58          return rc;
    59  }

The use after free across threads only happens when an external program
is being executed from a thread other than the main() thread.  This is
because by default glib registered callbacks are run by the glib main
loop, which is only called from the main() thread with Gtk::Main::run().

Event sequence:
tid=2193                      tid=2202

main()
...
  GParted_Core::set_devices()
    Glib::Thread::create(... set_devices_thread ...)
    Gtk::Main::run()          GParted_Core::set_devices_thread()
                              ...
                                Utils::execute_command("dumpe2fs ... /dev/sda1" ...)
                                  Glib::spawn_async_with_pipes()
                                  PipeCapture outputcapture(out, output)
                                  outputcapture.connect_signal()
      //Glib main loop runs callback
      PipeCapture::_OnReadable()
        pc->OnReadable()
          //output read
          signal_update.emit()
          return true
      ...
      //Glib main loop runs callback
      PipeCapture::_OnReadable()
        pc->OnReadable()
          //eof reached
[1]       signal_eof.emit()
                                  return status.exit_status
[2]                               PipeCapture::~PipeCapture()
[3]       return false
[4]     pc->sourceid = 0

What is happening is that the PipeCapture destructor [2] is running in
the set_devices_thread() thread and freeing the object's memory as soon
as signal_eof.emit() [1] has been called.  Then signal_eof.emit()
returns back to OnReadable() which then returns false [3] back to the
_OnReadable() callback function which then assigns 0 to sourceid member
variable [4] in the already freed object, detected by valgrind as:
    Invalid write of size 4
       at ... GParted::PipeCapture::_OnReadable(...) (PipeCapture.cc:56)

This is happening because PipeCapture member variable sourceid is being
saved, in a different thread, just so the _OnReadable() callback can be
removed.  However a glib IOChannel callback, type GIOFunc(), returning
false will be automatically removed.

    GLib Reference Manual 2.26 / IO Channels
    https://developer.gnome.org/glib/2.26/glib-IO-Channels.html#GIOFunc

    GIOFunc()

    Returns : the function should return FALSE if the event source
              should be removed

Therefore fix by just not saving the event sourceid at all, and not
calling g_source_remove() to manually remove the callback, but instead
letting glib automatically remove the callback when it returns false.

Bug #731752 - Write after free cross thread race in
              PipeCapture::_OnReadable()
2014-07-06 10:22:40 -06:00
Phillip Susi 947cd02857 Change OperationDetail to not store complex objects in STL containers (#729139)
OperationDetail was storing its children in a std::vector.  This means they
can be moved around in memory arbitrarily, going through indeterminate
lifetimes.  This is generally a bad thing for any non trivial object and
in the case of OperationDetail, it created havoc with the way it maintains
pointers between parent/child objects for signal connections.  It will now
keep only pointers to children in a std::vector instead, so their lifetime
can be controlled, fixing various crashes.

Bug 729139 - Refactor OperationDetail to address random behavior
2014-05-18 10:07:45 -06:00