[gparted] Switch to using lvs to identify active LVM LVs (#160787)



commit 820242635a9e02ce8af67854dd15cb9b32af485f
Author: Mike Fleetwood <mike fleetwood googlemail com>
Date:   Thu Feb 2 13:22:46 2012 +0000

    Switch to using lvs to identify active LVM LVs (#160787)
    
    Previously used "dmsetup info" to directly list device-mapper mapping
    names in the kernel to identify active Logical Volumes.  However GParted
    failed to recognise active LVs if the VGNAME contains any hyphens (-).
    This is because LVM encodes hyphens as double hyphens in the mapping
    name.
    
    To avoid having to duplicate the LVM hyphen encoding in GParted, switch
    to using "lvm lvs" to list LVs.
    
        # dmsetup info --columns --noheadings --separator , -o name
        GParted_VG1-lvol_00
        GParted--VG2-lvol--00
    
        # lvm lvs --noheadings --separator , -o lv_name,vg_name,lv_attr
          lvol_00,GParted_VG1,-wi-a-
          lvol-00,GParted-VG2,-wi-a-
          lvol-01,GParted-VG3,-wi---
                                 .^.
    (-) not active, (a) or any other character considered active.  Reference
    lvs(8).
    
    Bug #160787 - lvm support

 include/LVM2_PV_Info.h |    5 +--
 src/LVM2_PV_Info.cc    |   71 +++++++++++++++++++++++++++++------------------
 2 files changed, 46 insertions(+), 30 deletions(-)
---
diff --git a/include/LVM2_PV_Info.h b/include/LVM2_PV_Info.h
index 7ddb1a6..c6ef2c7 100644
--- a/include/LVM2_PV_Info.h
+++ b/include/LVM2_PV_Info.h
@@ -43,14 +43,13 @@ public:
 	bool has_active_lvs( const Glib::ustring & path ) ;
 private:
 	void initialize_if_required() ;
-	void set_commands_found() ;
+	void set_command_found() ;
 	void load_lvm2_pv_info_cache() ;
 	Glib::ustring get_pv_attr( const Glib::ustring & path, unsigned int entry ) ;
 	static bool lvm2_pv_info_cache_initialized ;
 	static bool lvm_found ;
-	static bool dmsetup_found ;
 	static std::vector<Glib::ustring> lvm2_pv_cache ;
-	static Glib::ustring dmsetup_info_cache ;
+	static std::vector<Glib::ustring> lvm2_lv_cache ;
 };
 
 }//GParted
diff --git a/src/LVM2_PV_Info.cc b/src/LVM2_PV_Info.cc
index dc245f2..adaf6e6 100644
--- a/src/LVM2_PV_Info.cc
+++ b/src/LVM2_PV_Info.cc
@@ -27,11 +27,17 @@ enum PV_ATTRIBUTE
 	PVATTR_PV_FREE = 2
 } ;
 
+enum LV_ATTRIBUTE
+{
+	LVATTR_LV_NAME = 0,
+	LVATTR_VG_NAME = 1,
+	LVATTR_LV_BITS = 2
+} ;
+
 //Data model:
 //  lvm2_pv_info_cache_initialized
 //                      - Has the cache been loaded let?
 //  lvm_found           - Is the "lvm" command available?
-//  dmsetup_found       - Is the "dmsetup" command available?
 //  lvm2_pv_cache       - String vector storing attributes of a PV.
 //                        Attributes are: pv_name,vg_name,pv_free.
 //                        Pv_free is the number of free bytes.
@@ -39,15 +45,18 @@ enum PV_ATTRIBUTE
 //                        ["/dev/sda6,vg_test,4022337536",
 //                         "/dev/sda8,vg_test2,5087690752",
 //                         "/dev/sda10,,2147483648"]
-//  dmsetup_info_cache  - String storing active LVs.  E.g.
-//                        "vg_test-lvol1\nvg_test-lvol0\nvg_test2-lvol0\n"
+//  lvm2_lv_cache       - String vector storing attributes of an LV.
+//                        Attributes are: lv_name,vg_name,lv_attrs.
+//                        See lvs(8) for details of lv_attrs.
+//                        E.g.
+//                        ["lvol0,vg_test,-wi---",
+//                         "lvol0,vg_test2,-wi-a-"]
 
 //Initialize static data elements
 bool LVM2_PV_Info::lvm2_pv_info_cache_initialized = false ;
 bool LVM2_PV_Info::lvm_found = false ;
-bool LVM2_PV_Info::dmsetup_found = false ;
 std::vector<Glib::ustring> LVM2_PV_Info::lvm2_pv_cache ;
-Glib::ustring LVM2_PV_Info::dmsetup_info_cache = "" ;
+std::vector<Glib::ustring> LVM2_PV_Info::lvm2_lv_cache ;
 
 LVM2_PV_Info::LVM2_PV_Info()
 {
@@ -57,7 +66,7 @@ LVM2_PV_Info::LVM2_PV_Info( bool do_refresh )
 {
 	if ( do_refresh )
 	{
-		set_commands_found() ;
+		set_command_found() ;
 		load_lvm2_pv_info_cache() ;
 		lvm2_pv_info_cache_initialized = true ;
 	}
@@ -70,8 +79,8 @@ LVM2_PV_Info::~LVM2_PV_Info()
 bool LVM2_PV_Info::is_lvm2_pv_supported()
 {
 	if ( ! lvm2_pv_info_cache_initialized )
-		set_commands_found() ;
-	return ( lvm_found && dmsetup_found ) ;
+		set_command_found() ;
+	return ( lvm_found ) ;
 }
 
 Glib::ustring LVM2_PV_Info::get_vg_name( const Glib::ustring & path )
@@ -106,9 +115,21 @@ bool LVM2_PV_Info::has_active_lvs( const Glib::ustring & path )
 		//PV not yet included in any VG
 		return false ;
 
-	Glib::ustring regexp = "^(" + vgname + ")-" ;
-	Glib::ustring match = Utils::regexp_label( dmsetup_info_cache, regexp ) ;
-	return ( match == vgname ) ;
+	for ( unsigned int i = 0 ; i < lvm2_lv_cache .size() ; i ++ )
+	{
+		std::vector<Glib::ustring> lv_attrs ;
+		Utils::split( lvm2_lv_cache [i], lv_attrs, "," ) ;
+		if ( vgname == lv_attrs [LVATTR_VG_NAME] )
+		{
+			//5th "bit" is active status.  E.g.
+			//  "-wi---" inactive, "-wi-a-" active, ...
+			//  Treat any non-hyphen character as active.
+			if ( lv_attrs [LVATTR_LV_BITS] [4] != '-' )
+				//LV in VG is active
+				return true ;
+		}
+	}
+	return false ;
 }
 
 //Private methods
@@ -117,49 +138,45 @@ void LVM2_PV_Info::initialize_if_required()
 {
 	if ( ! lvm2_pv_info_cache_initialized )
 	{
-		set_commands_found() ;
+		set_command_found() ;
 		load_lvm2_pv_info_cache() ;
 		lvm2_pv_info_cache_initialized = true ;
 	}
 }
 
-void LVM2_PV_Info::set_commands_found()
+void LVM2_PV_Info::set_command_found()
 {
-	//Set status of commands found
+	//Set status of command found
 	lvm_found = ( ! Glib::find_program_in_path( "lvm" ) .empty() ) ;
-	dmsetup_found = ( ! Glib::find_program_in_path( "dmsetup" ) .empty() ) ;
 }
 
 void LVM2_PV_Info::load_lvm2_pv_info_cache()
 {
 	Glib::ustring output, error ;
 
-	//Load LVM2 PV attribute cache
 	lvm2_pv_cache .clear() ;
+	lvm2_lv_cache .clear() ;
 	if ( lvm_found )
 	{
 		//The OS is expected to fully enable LVM, this scan does
 		//  not do the full job.  It is included incase anything
 		//  is changed not using lvm commands.
 		Utils::execute_command( "lvm vgscan", output, error, true ) ;
-		//Output PV attributes, in PV_ATTRIBUTE order
+
+		//Load LVM2 PV attribute cache.  Output PV attributes in
+		//  PV_ATTRIBUTE order
 		if ( ! Utils::execute_command( "lvm pvs --config \"log{command_names=0}\" --nosuffix --noheadings --separator , --units b -o pv_name,vg_name,pv_free", output, error, true ) )
 		{
 			if ( output != "" )
 				Utils::tokenize( output, lvm2_pv_cache, " \n" ) ;
 		}
-	}
 
-	//Load dmsetup info cache.  This is a list of active LV names as
-	//reported by the kernel's device-mapper driver.
-	dmsetup_info_cache = "" ;
-	if ( dmsetup_found )
-	{
-		if ( ! Utils::execute_command( "dmsetup info --columns --noheadings --separator , -o name", output, error, true ) )
+		//Load LVM2 LV attribute cache.  Output LV attributes in
+		//  LV_ATTRIBUTE order
+		if ( ! Utils::execute_command( "lvm lvs --config \"log{command_names=0}\" --noheadings --separator , -o lv_name,vg_name,lv_attr", output, error, true ) )
 		{
-			Glib::ustring match = Utils::regexp_label( output, "^(No devices found).*" ) ;
-			if ( match != "No devices found" )
-				dmsetup_info_cache = output ;
+			if ( output != "" )
+				Utils::tokenize( output, lvm2_lv_cache, " \n" ) ;
 		}
 	}
 }



[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]