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)
This commit is contained in:
Mike Fleetwood 2014-03-25 23:03:30 +00:00 committed by Curtis Gedak
parent 76e64f2905
commit a086e115e5
4 changed files with 40 additions and 21 deletions

View File

@ -88,6 +88,7 @@ private:
Byte_Value sector_size,
bool inside_extended ) ;
void set_mountpoints( std::vector<Partition> & partitions ) ;
bool set_mountpoints_helper( Partition & partitions, const Glib::ustring & path ) ;
bool is_busy( FILESYSTEM fstype, const Glib::ustring & path ) ;
void set_used_sectors( std::vector<Partition> & partitions, PedDisk* lp_disk ) ;
void mounted_set_used_sectors( Partition & partition ) ;

View File

@ -37,6 +37,7 @@ public:
bool check_repair( const Partition & partition, OperationDetail & operationdetail ) ;
static void clear_cache() ;
static Glib::ustring get_mount_device( const Glib::ustring & path ) ;
private:
static const std::vector<Glib::ustring> get_cache_entry( const Glib::ustring & path ) ;

View File

@ -1515,7 +1515,6 @@ void GParted_Core::set_mountpoints( std::vector<Partition> & partitions )
partitions[ t ] .filesystem != FS_LINUX_SWSUSPEND
)
{
std::map< Glib::ustring, std::vector<Glib::ustring> >::iterator iter_mp ;
if ( partitions[ t ] .busy )
{
#ifndef USE_LIBPARTED_DMRAID
@ -1526,19 +1525,14 @@ void GParted_Core::set_mountpoints( std::vector<Partition> & partitions )
if ( dmraid .is_dmraid_device( partitions[ t ] .device_path ) )
{
//Try device_name + partition_number
iter_mp = mount_info .find( partitions[ t ] .device_path + Utils::num_to_str( partitions[ t ] .partition_number ) ) ;
if ( iter_mp != mount_info .end() )
{
partitions[ t ] .add_mountpoints( iter_mp ->second ) ;
Glib::ustring dmraid_path = partitions[ t ] .device_path + Utils::num_to_str( partitions[t ] .partition_number ) ;
if ( set_mountpoints_helper( partitions[ t ], dmraid_path ) )
break ;
}
//Try device_name + p + partition_number
iter_mp = mount_info .find( partitions[ t ] .device_path + "p" + Utils::num_to_str( partitions[ t ] .partition_number ) ) ;
if ( iter_mp != mount_info .end() )
{
partitions[ t ] .add_mountpoints( iter_mp ->second ) ;
dmraid_path = partitions[ t ] .device_path + "p" + Utils::num_to_str( partitions[ t ] .partition_number ) ;
if ( set_mountpoints_helper( partitions[ t ], dmraid_path ) )
break ;
}
}
else
{
@ -1546,12 +1540,9 @@ void GParted_Core::set_mountpoints( std::vector<Partition> & partitions )
//Normal device, not DMRaid device
for ( unsigned int i = 0 ; i < partitions[ t ] .get_paths() .size() ; i++ )
{
iter_mp = mount_info .find( partitions[ t ] .get_paths()[ i ] ) ;
if ( iter_mp != mount_info .end() )
{
partitions[ t ] .add_mountpoints( iter_mp ->second ) ;
Glib::ustring path = partitions[ t ] .get_paths()[ i ] ;
if ( set_mountpoints_helper( partitions[ t ], path ) )
break ;
}
}
#ifndef USE_LIBPARTED_DMRAID
}
@ -1562,6 +1553,7 @@ void GParted_Core::set_mountpoints( std::vector<Partition> & partitions )
}
else
{
std::map< Glib::ustring, std::vector<Glib::ustring> >::iterator iter_mp ;
iter_mp = fstab_info .find( partitions[ t ] .get_path() );
if ( iter_mp != fstab_info .end() )
partitions[ t ] .add_mountpoints( iter_mp ->second ) ;
@ -1578,6 +1570,24 @@ void GParted_Core::set_mountpoints( std::vector<Partition> & partitions )
}
}
bool GParted_Core::set_mountpoints_helper( Partition & partition, const Glib::ustring & path )
{
Glib::ustring search_path ;
if ( partition .filesystem == FS_BTRFS )
search_path = btrfs::get_mount_device( path ) ;
else
search_path = path ;
std::map< Glib::ustring, std::vector<Glib::ustring> >::iterator iter_mp = mount_info .find( search_path ) ;
if ( iter_mp != mount_info .end() )
{
partition .add_mountpoints( iter_mp ->second ) ;
return true ;
}
return false;
}
//Report whether the partition is busy (mounted/active)
bool GParted_Core::is_busy( FILESYSTEM fstype, const Glib::ustring & path )
{

View File

@ -141,11 +141,7 @@ bool btrfs::is_busy( const Glib::ustring & path )
// member of the file system. 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
std::vector<Glib::ustring> entry = get_cache_entry( path ) ;
for ( unsigned int i = 0 ; i < entry .size() ; i ++ )
if ( GParted_Core::is_dev_mounted( entry[ i ] ) )
return true ;
return false ;
return ! get_mount_device( path ) .empty() ;
}
bool btrfs::create( const Partition & new_partition, OperationDetail & operationdetail )
@ -343,6 +339,17 @@ void btrfs::clear_cache()
btrfs_device_cache .clear() ;
}
//Return the device which is mounting the btrfs in this partition.
// Return empty string if not found (not mounted).
Glib::ustring btrfs::get_mount_device( const Glib::ustring & path )
{
std::vector<Glib::ustring> entry = get_cache_entry( path ) ;
for ( unsigned int i = 0 ; i < entry .size() ; i ++ )
if ( GParted_Core::is_dev_mounted( entry[ i ] ) )
return entry[ i ] ;
return "" ;
}
//Private methods
//Return btrfs device cache entry, incrementally loading cache as required