After an evaluation, GNOME has moved from Bugzilla to GitLab. Learn more about GitLab.
No new issues can be reported in GNOME Bugzilla anymore.
To report an issue in a GNOME project, go to GNOME GitLab.
Do not go to GNOME Gitlab for: Bluefish, Doxygen, GnuCash, GStreamer, java-gnome, LDTP, NetworkManager, Tomboy.
Bug 767842 - File system usage missing when tools report alternate block device names
File system usage missing when tools report alternate block device names
Status: RESOLVED FIXED
Product: gparted
Classification: Other
Component: application
GIT HEAD
Other Linux
: Normal normal
: ---
Assigned To: Mike Fleetwood
gparted maintainers alias
Depends on:
Blocks:
 
 
Reported: 2016-06-19 15:03 UTC by Mike Fleetwood
Modified: 2016-10-19 16:22 UTC
See Also:
GNOME target: ---
GNOME version: ---


Attachments
Block special comparison by major, minor number (Draft 1) (90.96 KB, patch)
2016-07-10 11:39 UTC, Mike Fleetwood
none Details | Review
Block special comparison by major, minor number (v1) (148.08 KB, patch)
2016-07-15 12:54 UTC, Mike Fleetwood
none Details | Review
Block special comparison by major, minor number (v2) (152.84 KB, patch)
2016-08-04 19:06 UTC, Mike Fleetwood
none Details | Review

Description Mike Fleetwood 2016-06-19 15:03:29 UTC
GParted loads a number of caches of information from external files and
output from commands.  For example "lvm pvs" is used to report all the
LVM2 Physical Volumes and "btrfs filesystem show /dev/PTN" is used to
identify all the devices within a multi-device btrfs.  GParted uses
string comparison to determine if names refer to the same block device.
Most of the time this works because tools use the same canonical set of
names for block devices.  However in some cases those tools report
alternate block device names in their output so usage information is not
found.

Two known failure cases are:

1) LVM on top of DMRaid does not show usage
   See bug 715191 comment 17
   "LVM2 PV space usage details not working on fake BIOS RAID"
   https://bugzilla.gnome.org/show_bug.cgi?id=715191#c17

2) Btrfs multi-device details reported incorrectly on top of LUKS
   See bug 760080 comment 1
   "Implement read-only LUKS support"
   https://bugzilla.gnome.org/show_bug.cgi?id=760080#c1
Comment 1 Mike Fleetwood 2016-06-19 15:16:10 UTC
Example of case (1) LVM on top of DMRaid, on Utuntu 12.04 LTS


GParted built with --enable-libparted-dmraid.  LVM2 PV partition created
on a DMRaid array.  The partition is shows with this warning:

    Unable to read the contents of this file system!
    Because of this some operations may be unavailable.
    The cuase might be a missing software package.
    The following list of software packages is required for lvm2 pv
    file system support: lvm2.


GParted is using /dev/mapper/isw_cgahfjhcdb_MyArray0p2 as the partition
block device name.

# ls -l /dev/mapper
total 0
crw------- 1 root root 10,236 Jun 12 11:59 control
lrwxrwxrwx 1 root root      7 Jun 12 12:17 isw_cgahfjhcdb_MyArray0 -> ../dm-0
lrwxrwxrwx 1 root root      7 Jun 12 12:17 isw_cgahfjhcdb_MyArray0p1 -> ../dm-1
lrwxrwxrwx 1 root root      7 Jun 12 12:17 isw_cgahfjhcdb_MyArray0p2 -> ../dm-2


GParted created the LVM2 PV using using this command:

# lvm pvcreate -M 2 /dev/mapper/isw_cgahfjhcdb_MyArray0p2
Physical volume "/dev/mapper/isw_cgahfjhcdb_MyArray0p2" successfully created


However when querying LVM, it reports an alternate block device name.

# lvm pvs
  PV         VG   Fmt  Attr PSize PFree
  /dev/dm-2       lvm2 a-   1.00g 1.00g


/dev/mapper/isw_cgahfjhcdb_MyArray0p2 is a symlink to /dev/dm-2.

lvm pvs command reports a different block device name to that which
GParted is using so it doesn't find the usage information in the cache
of LVM2 information.  LVM2_PV_Info::get_pv_cache_entry_by_name() is only
performing a string compare to match block device names.
Comment 2 Mike Fleetwood 2016-06-19 15:31:25 UTC
Example of case (1) LVM on top of DMRaid, on Ubuntu 14.04 LTS


GParted built with --enable-libparted-dmraid.  LVM2 PV partition created
on a DMRaid array.  Details are as the same as for Ubuntu 12.04 LTS in
comment 1, except for the following differences.


DMRaid array name differs.  GParted is using this as the partition name:

# cd /dev/mapper
# ls -l isw_bacdehijbd_MyArray0p2
brw-rw---- 1 root disk 252,   2 Jun 12 13:16 isw_bacdehihbd_MyArray0p2


This time LVM is reporting a different name again.

# lvm pvs
  PV                                                VG   Fmt  Attr PSize PFree
  /dev/disk/by-id/dm-name-isw_bacdehijbd_MyArray0p2 VG   lvm2 a--  1.00g 1.00g

# cd /dev/disk/by-id
# ls -l dm-name-isw_bacdehijbd_MyArray0p2
lrwxrwxrwx 10 Jun 12 13:16 dm-name-isw_bacdehihbd_MyArray0p2 -> ../../dm-2
# ls -l /dev/dm-2
brw-rw---- 1 root disk 252, 2 Jun 12 13:24 /dev/dm-2


GParted is using this name:
    /dev/mapper/isw_bacdehihbd_MyArray0p2    blk 252, 2

and LVM is reporting:
    /dev/disk/by-id/dm-name-isw_bacdehijbd_MyArray0p2  symlink to ->
    /dev/dm-2                                blk 252, 2

Therefore when comparing block device name for equality, it is not
enough to follow symlinks and see if the resolve to the same name.  Need
to check that they refer to the same block device; that the major, minor
pair match.
Comment 3 Mike Fleetwood 2016-06-19 15:53:08 UTC
Example case (2) multi-btrfs on top of LUKS, on CentOS 6


Multi-btrfs created on LUKS encrypted partitions.

# cryptsetup luksFormat /dev/sdb7
# cryptsetup luksOpen /dev/sdb7 sdb7_crypt
# cryptsetup luksFormat /dev/sdb8
# cryptsetup luksOpen /dev/sdb8 sdb8_crypt

# ls -l /dev/mapper
total 0
crw-rw----. 1 root root 10, 58 Jun  4 20:36 control
lrwxrwxrwx. 1 root root      7 Jun 19 16:40 sdb7_crypt -> ../dm-0
lrwxrwxrwx. 1 root root      7 Jun 19 16:40 sdb8_crypt -> ../dm-1

# mkfs.btrfs -L encrypted-btrfs /dev/mapper/sdb7_crypt /dev/mapper/sdb8_crypt


Btrfs command doesn't even recognise /dev/mapper/sdb7_crypt as
containing any file system.  Instead it only works with dm-* names and
reports them too.

# btrfs filesystem show /dev/mapper/sdb7_crypt
Btrfs Btrfs v0.20-rc1
# btrfs filesystem show /dev/dm-0
Label: 'encrypted-btrfs'  uuid: 88c3f50d-4860-48ae-8a52-0db7a49461a8
	Total devices 2 FS bytes used 28.00KB
	devid    2 size 510.00MB used 0.00 path /dev/dm-1
	devid    1 size 510.00MB used 12.00MB path /dev/dm-0

Btrfs Btrfs v0.20-rc1


GParted is working with /dev/mapper/sdb[78]_crypt canonical Device
Mapper names, but btrfs is only working with and reporting /dev/dm-*
names.
Comment 4 Mike Fleetwood 2016-06-20 17:11:52 UTC
Reviewing GParted code I find these uses of caches which store block
device names and are matched by string compare in one way or another.
There may well be other code in GParted which is also using string
compare to match block devices.


Proc_Partitions_Info
*   Cache loaded from /proc/partitions
*   ::device_paths_cache
    *   std::vector of whole disk block device names.
        E.g. ["/dev/sda", "/dev/sdb", ...]
    *   returned by ::get_device_paths()
*   ::alternate_paths_cache
    *   std::map indexed by block device names.
        E.g. x["/dev/sda1"] -> ["/dev/sda1"]
    *   returned by ::get_alternate_paths()

FS_Info
*   Cache loaded from command "blkid"
*   ::fs_info_cache
    *   Glib::ustring of blkid output
*   ::get_device_entry()
    *   perform string match on block device name

DMRaid
*   Cache loaded from "dmraid -sa -c"
*   ::dmraid_devices
    *   std::vector of whole DMRaid array block device names.
        E.g. ["isw_bbaecedgch_MyArray0"]
    *   Linearly search and string compared
    *   ::get_devices() returns names prefixed with "/dev/mapper"
        E.g. ["/dev/mapper/isw_bbaecedgch_MyArray0"]

LVM2_PV_Info
*   Cache loaded from "lvm pvs ..."
*   ::lvm2_pv_cache
    *   std::vector of struct LVM2_PV, including disk block device names
        E.g. [{"/dev/sda10", ...}, {"/dev/sda11", ...}, ...]
*   ::get_pv_cache_entry_name_name()
    *    linearly search and string compared

btrfs
*   cache incrementally loaded from "btrfs filesystem show /dev/PTN"
*   ::btrfs_device_cache
    *   std::map indexed by block device names.
        E.g. x["/dev/sdb1"] -> {devid=1, members=["/dev/sdd1",
                                              "/dev/sdc1", "/dev/sdb1"]}
    *   ::get_cache_entry()
        *   lookup in std::map using block device name.
    *   ::get_members() list of btrfs member devices, used for display
    *   ::get_mount_device() also linear search and string compares
        members in vector

SWRaid_Info
*   Cache loaded from command "mdadm -Esv" and file "/proc/mdstat"
*   ::swraid_info_cache
    *   std::vector of struct SWRaid_Member
        E.g. [{member="/dev/sda1", array="/dev/md1", ...}, ...]
*   ::get_cache_entry_by_member()
    *   linear search and string compare

LUKS_Info
*   Cache loaded from "dmsetup table --target crypt"
*   ::luks_mapping_cache
    *   std::vector of struct LUKS_Mapping
        E.g. [{name="sdb6_crypt", major=8, minor=22, path="/dev/sdb6", ...}, ...]
*   ::get_cache_entry()
    *   linear search string matching block device name, falling back to
        major, minor match using stat() call when required

GParted_Core::mount_info
*   Cache loaded from files "/proc/mounts" and "/proc/swaps"
*   Also loaded from command "mount" if required
*   ::mount_info
    *   std::map of Glib::ustring to vector of Glib::ustring
    *   Maps block device names to list of mounting points
        E.g. x["/dev/sda1"] -> ["/boot"]
*   Accessed using .find() and loop from .begin() to .end()

GParted_Core::fstab_info
*   Cache loaded from file "/etc/fstab"
*   ::fstab_info
    *   std::map of Glib::ustring to vector of Glib::ustring
    *   Maps fstab configured mounts
        E.g. x["/dev/sda1"] -> ["/boot"]
*   Assessed using .find()
Comment 5 Mike Fleetwood 2016-06-21 14:55:02 UTC
Hi Curtis,


So GParted is written assuming string compare can be used to match block
devices.  It is used in lots of places in the code.  The question is
should GParted continue to use string compare in all these locations to
match devices?


Option (1): Stick with string comparing block device names
  Then there needs to be a way to canonicalise all block devices to
  their preferred names for all names read from files and command output
  when populating the caches.  Then continue to use string compare to
  access the caches.

  Call Utils::canonical_path() as required.


Option (2): Use class with major, minor comparison
  Change to major, minor block device numbers everywhere.  Looking ahead
  it would seem simplest to implement a Block_Device class which
  represents the name and major, minor numbers of block devices.
  Objects of type Block_Device would be used everywhere, replacing path
  names.

  Construct Block_Device("/dev/sda1") or Block_Device(252, 3) as
  required.


Option (3): Stick with block device names, but use major, minor
            comparison
  Half way house of block device names continuing to be used everywhere
  but using major, minor comparison.  This option gets a bit
  complicated.

  Open coded linear searches of caches can easily be replaced with
  Utils::same_block_device() when required.  Just need to make sure it's
  not missed anywhere.

  However those caches which use std::map with the path as the key are
  harder to handle.  The key of a std::map needs to be orderable; that
  is operator<() is implemented [1][2][3].

  There are several options for this:
  3.1) Stop using std::map altogether.  Instead use a vector and linear
       search to find entries using comparison method of choice.
  3.2) Write a class which implements operator<() for block device names
       which takes major, minor number into account and is passed as the
       3rd argument to std::map.
  3.3) Write a Block_Device class which represents name and major, minor
       and implements operator=() and operator<() allowing standard
       comparison and std::map to be use.
       => This is option (2).

[1] std::map
    http://www.cplusplus.com/reference/map/map/
[2] std::map::key_comp
    http://www.cplusplus.com/reference/map/map/key_comp/
[3] create an own comparator for map
http://stackoverflow.com/questions/5733254/create-an-own-comparator-for-map


No matter which option is chosen, there is going to be a lot of block
device comparison, even for option (1) of just canonicalising path
names.  Therefore another cache containing block device names, major &
minor numbers will almost certainly going to be needed.


I am inclined to use option (2) Block_Device class with major, minor
name comparison.
Pluses:
1) It makes a strong statement about intent that a class is used which
   implements custom (block device relevant) comparison using major,
   minor comparison;
2) It encapsulates things;
3) It is very obvious strings containing paths have been converted to
   Block_Device objects;
Minuses:
1) Seems it bit heavyweight;
2) More change.


So I've changed my mind from our earlier email chat after further
investigation.  Thoughts welcome.


thanks,
Mike
Comment 6 Curtis Gedak 2016-06-21 16:04:41 UTC
Hi Mike,

Your investigation appears to have flushed out a few issues.

One permutation that caught me by surprise was your example in comment #2 with three string paths for the same device:

  GParted is using this name:
    /dev/mapper/isw_bacdehihbd_MyArray0p2    blk 252, 2

  and LVM is reporting:
    /dev/disk/by-id/dm-name-isw_bacdehijbd_MyArray0p2  symlink to ->
    /dev/dm-2                                blk 252, 2

Because there are even more string options available
   e.g., /dev/disk/[by-id|by-label|by-path|by-uuid] 
in addition to the /dev/mapper/* and /dev/dm-#, the string comparison option gets quite messy.  Further from comment #3 it appears the btrfs show command gives different results depending on which string name is used -- this might be a separate issue but still makes things messy.

It seems that we need to be sure to use a descriptive string name so that users know which device/partition is being referred to, and further that we also need to use the appropriate string name for commands such as btrfs show.

From reading your comments, the three things that we appear to need are as follows:

  A)  Descriptive device/partition name string for user
  B)  Appropriate device/partition name for commands (e.g., btrfs show)
  C)  Comparison method that works works for many device/partitions

I think the complexity of these issues warrants a separate class to track block devices and to hide the details of the comparison method.

In simpler words, I agree that "option (2): Use class with major, minor comparison" may be the best path forward.

Thanks,
Curtis
Comment 7 Mike Fleetwood 2016-06-21 17:02:46 UTC
Hi Curtis,

Thanks for the feedback.  Agreed, I'll implement option (2): Use class
with major, minor comparison.  I think it's going to take a little
while.


On the needed feature (B) appropriate device name for commands (e.g.
btrfs show) ...

Not yet sure if I want to add this.  The btrfs failure from comment #3
is also a proxy for another subtle issue found on Fedora 23, also
documented in bug 760080 comment 1, in which btrfs show does work with
alternate names.  Btrfs on CentOS 6 is ancient and unsupported.

However from the recent ZFS related partition identification question,
bug 766989, ZFS document recommends using /dev/disk/by-id/ names [1] so
it might become necessary to better support ZFS in the future.

[1] Ubuntu 16.04 Root on ZFS
    zpool create ... /dev/disk/by-id/...
https://github.com/zfsonlinux/zfs/wiki/Ubuntu%2016.04%20Root%20on%20ZFS


Thanks,
Mike
Comment 8 Mike Fleetwood 2016-06-27 19:02:51 UTC
Example case (2) multi-btrfs on top of LUKS, on CentOS 7


Create btrfs on LUKS encrypted partition.

# cryptsetup luksFormat --force-password /dev/sda11
# cryptsetup luksOpen /dev/sda11 sda11_crypt
# ls -l /dev/mapper
total 0
crw-------. 1 root root 10, 236 Jun 27 10:30 control
lrwxrwxrwx. 1 root root       7 Jun 27 11:16 sda11_crypt -> ../dm-0

# mkfs.btrfs -L encrypted-btrfs /dev/mapper/sda11_crypt
# btrfs filesystem show /dev/mapper/sda11_crypt
Label: 'encrypted-btrfs'  uuid: 11cb152f-e6b5-4677-8947-09737a98268a
	Total devices 1 FS bytes used 28.00KiB
	devid    1 size 1022.00MiB used 12.00MiB path /dev/mapper/sda11_crypt

btrfs-progs v3.19.1


Mount the file system

# mount /dev/mapper/sda11_crypt /mnt/1
# fgrep btrfs /proc/mounts
/dev/mapper/sda11_crypt /mnt/1 btrfs rw,seclabel,relatime,ssd,space_cache 0 0


Add second device into the file system

# cryptsetup luksFormat --force-password /dev/sda12
# cryptsetup luksOpen /dev/sda12 sda12_crypt
# ls -l /dev/mapper
total 0
crw-------. 1 root root 10, 236 Jun 27 10:30 control
lrwxrwxrwx. 1 root root       7 Jun 27 11:30 sda11_crypt -> ../dm-0
lrwxrwxrwx. 1 root root       7 Jun 27 11:36 sda12_crypt -> ../dm-1

# btrfs device add /dev/mapper/sda12_crypt /mnt/1
# btrfs filesystem show /dev/mapper/sda12_crypt 
Label: 'encrypted-btrfs'  uuid: 11cb152f-e6b5-4677-8947-09737a98268a
	Total devices 2 FS bytes used 32.00KiB
	devid    1 size 1022.00MiB used 12.00MiB path /dev/mapper/sda11_crypt
	devid    2 size 1022.00MiB used 0.00B path /dev/mapper/sda12_crypt

btrfs-progs v3.19.1


Remove first and mounting device from the file system

# btrfs device delete /dev/mapper/sda11_crypt /mnt/1
# btrfs filesystem show /dev/mapper/sda12_crypt 
Label: 'encrypted-btrfs'  uuid: 11cb152f-e6b5-4677-8947-09737a98268a
	Total devices 1 FS bytes used 96.00KiB
	devid    2 size 1022.00MiB used 144.00MiB path /dev/mapper/sda12_crypt

btrfs-progs v3.19.1


Now the kernel reports the mounting device as /dev/dm-1 rather than the
canonical Device Mapper name of /dev/mapper/sda12_crypt.

# fgrep btrfs /proc/mounts
/dev/dm-1 /mnt/1 btrfs rw,seclabel,relatime,ssd,space_cache 0 0


This causes GParted to no longer be able to detect the file system is
mounted.  This is because GParted reads /proc/mounts to know which file
systems are mounted, but LUKS support in GParted is using the canonical
Device Mapper name /dev/mapper/sda12_crypt.
Comment 9 Mike Fleetwood 2016-07-09 14:44:30 UTC
Hi Curtis,

Can you do some testing / investigation please.  Can you build GParted
with --enable-libparted-dmraid and test it on a partitioned DMRaid
array.  Particularly interested in cases where GParted breaks.

When I tried viewing a partitioned DMRaid array, creating a partition
and then deleting a partition, I find it works:

Distro             View      Create      Delete
------             -----     ------      ------
CentOS 5           Works      Works      Works
Ubuntu 12.04 LTS   Works      Works      Works
Debian 8           Works      Works      Works

I get breakages on Debian 6, but then that is a no longer supported
distribution.

NOTES:
1) I'm actually building GParted from my git HEAD with a stack of
   patches for this bug report.
2) I'm wondering if DMRaid.cc module can be greatly simplified to the
   equivalent of what is used with --enable-libparted-dmraid.  I.e. just
   reporting DMRaid array names without any calls to "dmraid" command to
   stop and start arrays, etc.

Thanks,
Mike
Comment 10 Mike Fleetwood 2016-07-10 11:39:27 UTC
Created attachment 331156 [details] [review]
Block special comparison by major, minor number (Draft 1)

Hi Curtis,

Here is draft 1 of the patchset.  So far it:
1) Removes alternate paths;
2) Add BlockSpecial() objects into all the caches for matching devices
   by major, minor numbers instead of by name;
   except DMRaid ...
I've been trying to understand the DMRaid module enough to work out if
there are cases of device matching which is being performed by string
compare and should be changed to by major, minor number instead.  So far
I haven't been able to work that out. :-(

Help wanted,
Mike
Comment 11 Curtis Gedak 2016-07-11 16:36:29 UTC
Hi Mike,

My preliminary testing of patch D1 in comment #10 has gone well.  So far I have not observed any regressions.  There are some typos and grammatical errors in the commit comments, but I suspect you are not concerned about these at this time.

With respect to the DMRaid module, it should not require any changes as it should not require comparisons by major, minor number.  The module automatically creates and removes partition paths affected by GParted operations using it's own regular expressions on the /dev/mapper entries.  This should continue to work as expected with the caveat mentioned in this bug report, and has done so in my testing on kubuntu 16.04 both with and without --enable-libparted-dmraid.

Since I recently upgraded to a SSD with kubuntu 16.04, I no longer have my old Debian installation.  When I get around to re-installing Debian then I can test this patch set further.

Curtis
Comment 12 Curtis Gedak 2016-07-12 19:56:28 UTC
Hi Mike,

I installed Debian Testing (Stretch 9), installed the *dmraid* package and performed some testing.

On boot-up, the FAKE RAID is set up as */dev/mapper/isw_efjbbijhh_Vol0*.
The first partition has the entry      */dev/mapper/isw_efjbbijhh_Vol01*.
Note the missing "p" between the "0" and the "1".

When using patch D1 from comment #10, and gparted compiled with no configure options, the LVM2 PV and other partition types file system space usages worked correctly on FAKE RAID.

When using patch D1 from comment #10, and gparted compiled with --enable-libparted-dmraid, the LVM2 PV and other partition types file system space usages FAILED to work correctly on FAKE RAID.  This is to be expected because Debian Testing DMRAID does not create partitions with the same naming standard as libparted.

In conclusion, patch set D1 is an improvement for file system usage when used on Debian Testing both with and without FAKE RAID.

Thanks,
Curtis
Comment 13 Mike Fleetwood 2016-07-15 12:54:03 UTC
Created attachment 331583 [details] [review]
Block special comparison by major, minor number (v1)

Hi Curtis,

Here's patchset v1.

It uses BlockSpecial objects in all the caches, except for DMRaid which
you identified as not requiring change, as per comment 11.  I think use
of BlockSpecial objects in the rest of the code, such as in Device and
Partition* objects is not required because they represent a view of
disks and partitions using preferred user disk names.  E.g. sd*, md*,
mapper/*.

It does:
1) Removes alternate paths from Device and Partition objects;
2) Adds BlockSpecial object usage into the various caches.
[This far is the minimum required features]
3) Add another cache, of major, minor numbers looked up via stat() into
   BlockSpecial class to reduce explicit calls to stat().  Also further
   reduces calls to stat() by pre-populating major, minor numbers found
   in the already being read /proc/partitions.
4) Various refactoring / tidyups including:
4.1) Use static class interfaces for remaining caches;
4.2) Move mount_info and fstab_info maps into separate module.

Thanks,
Mike
Comment 14 Curtis Gedak 2016-08-02 16:59:10 UTC
Hi Mike,

From reviewing this latest patch set (v1) I can see that this took
significant effort to develop.  Thank you for your work in this area
to improve GParted, and thank you for your patience.

Following are my preliminary testing results and code review comments.
Please feel free to question any of my statements.


PRELIMINARY TESTING RESULTS
---------------------------

I've discovered a problem on kubuntu 16.04 on my Intel FAKE RAID
whereby the usage information is not found for an LVM2 PV partition.

The problem occurs if gparted is compiled with
--enable-libparted-dmraid.  This seems strange to me because kubuntu
creates DMRAID device names in the same form that libparted uses in
this distro (e.g. isw_efjbbijhh_Vol0p6).

I suspect the problem is related to the fact that the /dev/mapper/isw*
device name is a block special file whereas the /dev/mapper/isw*
partition entries are symbolic links to ../dm-* block special files.


Information from my setup follows:

  - Kubuntu 16.04
  - dmraid package installed
  - mdadm  package not installed
  - LVM2 PV partition 6 on Intel FAKE RAID

$ ls -l /dev/mapper
total 0
crw------- 1 root root  10, 236 Aug  2 10:38 control
brw-rw---- 1 root disk 252,   0 Aug  2 10:38 isw_efjbbijhh_Vol0
lrwxrwxrwx 1 root root        7 Aug  2 10:38 isw_efjbbijhh_Vol0p1 -> ../dm-1
lrwxrwxrwx 1 root root        7 Aug  2 10:38 isw_efjbbijhh_Vol0p5 -> ../dm-2
lrwxrwxrwx 1 root root        7 Aug  2 10:38 isw_efjbbijhh_Vol0p6 -> ../dm-3
$ ls -l /dev/dm-*
brw-rw---- 1 root disk 252, 0 Aug  2 10:38 /dev/dm-0
brw-rw---- 1 root disk 252, 1 Aug  2 10:38 /dev/dm-1
brw-rw---- 1 root disk 252, 2 Aug  2 10:38 /dev/dm-2
brw-rw---- 1 root disk 252, 3 Aug  2 10:38 /dev/dm-3


The problem does not occur if gparted is compiled with no extra
configure options.  This is likely due to the fact that GParted
directly calls dmraid to create the /dev/mapper partition entries and
these would be block special files (not symbolic links).


I can investigate further if required.


CODE REVIEW COMMENTS
--------------------

Following are my comments from reviewing the code in patch set v1 from
comment # 13.


[01/23] Simplify Device object to a single path (#767842)

Confusing sentence.  Suggest change.

FROM:
GParted stored a list of paths for Device and Partition objects.  It
sorted this list [1][2] and treated the first specially as that it what
                                                           ^^^^^^^
get_path() returned and was used almost everywhere; with the file system
specific tools, looked up in various *_Info caches, etc.

TO:
GParted stored a list of paths for Device and Partition objects.  It
sorted this list [1][2] and treated the first specially as what
get_path() returned and was used almost everywhere; with the file system
specific tools, looked up in various *_Info caches, etc.


[02/23] Rename Device::add_path() to set_path() (#767842)
  - no change

[03/23] Simplify Partition object to a single path (#767842)
  - no change

[04/23] Update calibrate_partition() for single partition path (#767842)
  - no change

[05/23] Rename Partition::add_path() to set_path() (#767842)
  - no change

[06/23] Remove now unused Proc_Partitions_Info::get_alternate_paths() (#767842)
  - no change

[07/23] Create BlockSpecial class and use in LVM2_PV_Info (#767842)

Confusing sentence.  Suggest change.

FROM:
Implement class BlockSpecial which encapsulates the name and major,
minor numbers for a block special device.  Also performs comparison as
needed.  For bug 767842 comment 4 and 5 for further investigation and
         ^^^                 ^^^
decision for choosing to implement a class.

TO:
Implement class BlockSpecial which encapsulates the name and major,
minor numbers for a block special device.  Also performs comparison as
needed.  See bug 767842 comments 4 and 5 for further investigation and
decision for choosing to implement a class.


[08/23] Add BlockSpecial into mount_info and fstab_info (#767842)
  - no change

[09/23] Use BlockSpecial objects in btrfs member cache (#767842)

Extremely minor grammatical change.  I'm being way too picky.  :)

FROM:
There are no known errors which effect the remaining caches in GParted.
                                ^^^^^^
TO:
There are no known errors which affect the remaining caches in GParted.


[10/23] Overload is_dev_mounted() function (#767842)
  - no change

[11/23] Use BlockSpecial in LUKS_Info module cache (#767842)
  - no change

[12/23] Use BlockSpecial in SWRaid_Info module cache (#767842)
  - no change

[13/23] Remove use of retired vol_id from FS_Info module (#767842)

We should also remove vol_id from the following files:
  README
  src/hfs.cc
  src/hfsplus.cc


[14/23] Parse FS_Info cache into fields while loading (#767842)
  - no change

[15/23] Use BlockSpecial in FS_Info module cache (#767842)
  - no change

[16/23] Cache looked up major, minor numbers in BlockSpecial class (#767842)

Minor sentence problem.  Suggest change.

FROM:
Creation of every BlockSpecial object use to result in a stat() OS call.
                                      ^^^^
On one of my test VMs debugging with 4 disks and a few partitions on
each, GParted refresh generated 541 calls to stat() in the
BlockSpecial(name) constructor.  However there were only 45 unique
names.  So on average each name was stat()ed approximately 12 time.
                                                              ^^^^^
TO:
Creation of every BlockSpecial object used to result in a stat() OS call.
On one of my test VMs debugging with 4 disks and a few partitions on
each, GParted refresh generated 541 calls to stat() in the
BlockSpecial(name) constructor.  However there were only 45 unique
names.  So on average each name was stat()ed approximately 12 times.


[17/23] Pre-populate BlockSpecial cache while reading /proc/partitions (#767842)

Minor spelling mistake.  Suggest change:

FROM:
For plain disks (sd*) and Linux Software RAID arrays (md*) the kernel
name is the common users pace name too, therefore matches what GParted
                   ^^^^^^^^^^
uses and pre-populating does avoid calling stat() at all for these
names.

TO:
For plain disks (sd*) and Linux Software RAID arrays (md*) the kernel
name is the common userspace name too, therefore matches what GParted
uses and pre-populating does avoid calling stat() at all for these
names.


[18/23] Switch to a static interface for Proc_Partitions_Info
  - no change

[19/23] Simplify whole device matching in load_proc_partitions_Info_cache()
  - no change

[20/23] Switch to static class interface for FS_Info
  - no change

[21/23] Remove unimplemented prototype DMRaid::partition_is_mounted_by_path()
  - no change

[22/23] Split mount_info and fstab_info maps into separate Mount_Info module

Minor spelling mistake.  Suggest change.

FROM:
GParted_Core slighly.
             ^^^^^^^
TO:
GParted_Core slightly.


[23/23] Remove no longer needed includes from GParted_Core.cc
  - no change


Thanks,
Curtis
Comment 15 Mike Fleetwood 2016-08-03 15:35:20 UTC
Hi Curtis,

I've tracked down the issue with LVM2 PV on top of DMRaid on
Ubuntu 16.04 LTS you reported.


My ISW array details:  (Not especially relevant)
# dmraid -r
/dev/sdc: isw, "isw_jjdaidaaj", GROUP, ok, 16777214 sectors, data@ 0
/dev/sdb: isw, "isw_jjdaidaaj", GROUP, ok, 16777214 sectors, data@ 0
# dmraid -n | head -3
/dev/sdc (isw):
0x000 sig: "  Intel Raid ISM Cfg Sig. 1.1.00"
...
0x138 isw_dev[0].volume: "        MyArray0"
...
/dev/sdb (isw):
0x000 sig: "  Intel Raid ISM Cfg Sig. 1.1.00"
...
# ls -l /dev/mapper
total 0
crw------- 1 root root  10, 236 Aug  3 15:21 control
brw-rw---- 1 root disk 252,   0 Aug  3 15:37 isw_jjdaidaaj_MyArray0
lrwxrwxrwx 1 root root        7 Aug  3 15:37 isw_jjdaidaaj_MyArray0p1 -> ../dm-1
lrwxrwxrwx 1 root root        7 Aug  3 15:37 isw_jjdaidaaj_MyArray0p2 -> ../dm-2
lrwxrwxrwx 1 root root        7 Aug  3 15:37 isw_jjdaidaaj_MyArray0p3 -> ../dm-3
# ls -l /dev/dm*
brw-rw---- 1 root disk 252, 0 Aug  3 15:21 /dev/dm-0
brw-rw---- 1 root disk 252, 1 Aug  3 15:37 /dev/dm-1
brw-rw---- 1 root disk 252, 2 Aug  3 15:37 /dev/dm-2
brw-rw---- 1 root disk 252, 3 Aug  3 15:37 /dev/dm-3


Create LVM2 PV on top of an ISW DMRaid array using GParted.
This runs command:
  lvm pvcreate -M 2 /dev/mapper/isw_jjdaidaaj_MyArray0p2

Refresh after applying this command reports the values correctly.


However manually querying the LVM2 PV details reports this:
(The important bit)
# lvm pvs
  PV         VG   Fmt  Attr PSize PFree
  /dev/sdc2       lvm2 ---  1.00g 1.00g
# blkid | fgrep LVM
/dev/sdb2: UUID="voKYhB-Dj81-ZVzc-w3m5-1uTB-Oaxd-O7JUbn" TYPE="LVM2_member" PARTUUID="6147c0f7-02"
/dev/sdc2: UUID="voKYhB-Dj81-ZVzc-w3m5-1uTB-Oaxd-O7JUbn" TYPE="LVM2_member" PARTUUID="6147c0f7-02"
/dev/mapper/isw_jjdaidaaj_MyArray0p2: UUID="voKYhB-Dj81-ZVzc-w3m5-1uTB-Oaxd-O7JUbn" TYPE="LVM2_member" PARTUUID="6147c0f7-02"

  Cause
  -----
  So the OS has block devices for /dev/mapper/isw*p2, /dev/sdb2 and
  /dev/sdc2 which because I am using mirroring all contain the same
  data.  LVM2 has decided that the PV is actually on /dev/sdc2 instead
  of /dev/mapper/isw*p2.

Refreshing GParted now gets a warning message and no usage details
against /dev/mapper/isw*p2 and /dev/sdb2.  And correct usage details
for /dev/sdc2.

  Previous case
  -------------
  This is the same cause as the failure I documented in
  bug 715191 comment 16.  Multiple separate block devices all pointing
  to / containing the same bytes and signatures.


The hard question is what to do about it.  Options are:
1) Nothing.  Having LVM2 on top of fake/BIOS RAID is rare and being
   broken by incorrectly configured distros.
2) Add filters to LVM2 configuration so that disks within fake/BIOS RAID
   arrays aren't examined for signatures.
3) Configure DMRaid some how to make it not create partition block
   devices for on disks within fake/BIOS RAID arrays.  (In this case
   don't create sdb[123] and sdc[123]).  I know that I have seen this
   happen on some distro when I was testing and seen a flag on the
   dmraid command.  But might involve adjusting udev rules.
4) Something else.

So far I am thinking options (1) do nothing.


Mike
Comment 16 Curtis Gedak 2016-08-03 16:04:34 UTC
Thank you Mike for investigating this issue further.

I too think that having LVM2 on top of fake/BIOS RAID is rare and would recommend against this practice.  If there were a simple solution then I'd go with that.  Since I don't see a simple solution I think our efforts are better spent elsewhere.

I agree with your suggestion to proceed with option (1) "do nothing".

Curtis
Comment 17 Mike Fleetwood 2016-08-04 19:06:14 UTC
Created attachment 332748 [details] [review]
Block special comparison by major, minor number (v2)

Hi Curtis,

Here's patchset v2 with your requested corrections, unless noted here as
doing something different.

[01/24] Simplify Device object to a single path (#767842)
"sorted this list [1][2] and treated the first specially as that it what
 [changed to]                                                     *
"sorted this list [1][2] and treated the first specially as that is what

[13/24] Remove use of retired vol_id from FS_Info module (#767842)
  Created additional commit to remove vol_id from README and
  src/hfs*.cc.
  [18/24] Remove remaining use of retired vol_id

[17/24] Pre-populate BlockSpecial cache while reading /proc/partitions (#767842)
  "users pace" -> "user space"

[24/24] Remove no longer needed includes from GParted_Core.cc
  Removed less headers after identified use for these:
  #include <sys/types.h>  keep for size_t
  #include <stdlib.h>     keep for free(), malloc() and possibly others
  #include <unistd.h>     keep for sleep()
  Documented commit removing the need for the still removed headers.

Thanks,
Mike
Comment 18 Curtis Gedak 2016-08-06 16:11:39 UTC
Hi Mike,

Thank you for the detailed description of the recent changes.

Patch set v2 from comment #17 looks good to me.  It worked as expected in all my tests, with the minor exception of the rare situation of LVM2 on top of fake RAID which we already know about and is an issue in the current code base.

I successfully ran brief tests on:

debian    8.0  (Jessie)
fedora   23
kubuntu  16.04
opensuse 13.2

If there are no objections then I will commit patch set v2 to the git master tomorrow.

Curtis
Comment 19 Curtis Gedak 2016-08-07 21:01:08 UTC
Thank you Mike for your work to improve handling of partition
recognition and comparison using major and minor numbers.

Patch set v2 from comment #17 has been committed to the git master
branch for inclusion in the next release of GParted.

The relevant git commits can be viewed at the following links:

Simplify Device object to a single path (#767842)
https://git.gnome.org/browse/gparted/commit/?id=902afaa010489d748927da1d4e779018d932d439

Rename Device::add_path() to set_path() (#767842)
https://git.gnome.org/browse/gparted/commit/?id=1dc8a0c628ecc4585b519bc16a1f110703b77d31

Simplify Partition object to a single path (#767842)
https://git.gnome.org/browse/gparted/commit/?id=214255eda3160bdee2eab985451f9231b75cd783

Update calibrate_partition() for single partition path (#767842)
https://git.gnome.org/browse/gparted/commit/?id=54652b0d4e117ab76c7b4dcc79e57045379d0ce8

Rename Partition::add_path() to set_path() (#767842)
https://git.gnome.org/browse/gparted/commit/?id=40f39bdbe27cb390b86de7ef79c6b9f8aab5623e

Remove now unused Proc_Partitions_Info::get_alternate_paths() (#767842)
https://git.gnome.org/browse/gparted/commit/?id=0f4df8dfd171ccdf076f562c4371fa237525a674

Create BlockSpecial class and use in LVM2_PV_Info (#767842)
https://git.gnome.org/browse/gparted/commit/?id=ab2d4f5ee6a1e139df3f4340e4247954e0f2a6f2

Add BlockSpecial into mount_info and fstab_info (#767842)
https://git.gnome.org/browse/gparted/commit/?id=a800ca8b68d60251101ee27e569dfa2a97b67886

Use BlockSpecial objects in btrfs member cache (#767842)
https://git.gnome.org/browse/gparted/commit/?id=abee66484fb355a1bac5b03f361bab7435df867b

Overload is_dev_mounted() function (#767842)
https://git.gnome.org/browse/gparted/commit/?id=e4a8530b1428bbd991d4e5b626377efc287e12b3

Use BlockSpecial in LUKS_Info module cache (#767842)
https://git.gnome.org/browse/gparted/commit/?id=7cd574cac5f7d076ebd94795f5c6f41b333fdee7

Use BlockSpecial in SWRaid_Info module cache (#767842)
https://git.gnome.org/browse/gparted/commit/?id=2b013e494c1580c139eaa342be659e46d5d24077

Remove use of retired vol_id from FS_Info module (#767842)
https://git.gnome.org/browse/gparted/commit/?id=8aa34f7baaac5a70e8901275619f7587b2ed21b8

Parse FS_Info cache into fields while loading (#767842)
https://git.gnome.org/browse/gparted/commit/?id=23da3ab9a83979ae97aa634f60834930a1c56569

Use BlockSpecial in FS_Info module cache (#767842)
https://git.gnome.org/browse/gparted/commit/?id=ce8fb1dd91c045991d196fde300a419f00356c84

Cache looked up major, minor numbers in BlockSpecial class (#767842)
https://git.gnome.org/browse/gparted/commit/?id=003d6eff943b3ce37e90100f660eaceda8519421

Pre-populate BlockSpecial cache while reading /proc/partitions (#767842)
https://git.gnome.org/browse/gparted/commit/?id=571304d2c662f8c35e9529b71ae48ffe263c038f

Remove remaining use of retired vol_id
https://git.gnome.org/browse/gparted/commit/?id=91e5a0960eb57b9b877d47e070a0578de4a313bf

Switch to a static interface for Proc_Partitions_Info
https://git.gnome.org/browse/gparted/commit/?id=912766c2e11aab2cecd916bdc2027cc14087c4a0

Simplify whole device matching in load_proc_partitions_Info_cache()
https://git.gnome.org/browse/gparted/commit/?id=5055c0b638ca236ea9457eaf151c3bc54a872065

Switch to static class interface for FS_Info
https://git.gnome.org/browse/gparted/commit/?id=a94be2da05c65b36c290d993c89f5580e85042ca

Remove unimplemented prototype DMRaid::partition_is_mounted_by_path()
https://git.gnome.org/browse/gparted/commit/?id=0785c5d7ef044799de2c61000a3bcf0ae5ba72b2

Split mount_info and fstab_info maps into separate Mount_Info module
https://git.gnome.org/browse/gparted/commit/?id=63ec73dfdac70fde8fabb543d0a7dc5808e168d5

Remove no longer needed includes from GParted_Core.cc
https://git.gnome.org/browse/gparted/commit/?id=e6f4b1c30505b0d4f0ce4da7e258b325e2875d27

Curtis
Comment 20 Curtis Gedak 2016-10-19 16:22:20 UTC
This enhancement was included in the GParted 0.27.0 release on October 19, 2016.