[gparted/psusi/resize] Add online resize support



commit b8cfc75e857ff833a6918e90af5efe5b84fcf381
Author: Phillip Susi <psusi ubuntu com>
Date:   Sun Feb 24 16:38:21 2013 -0500

    Add online resize support
    
    Many filesystems are capable of growing while mounted, and btrfs can even
    shrink.  This support must be explicitly enabled at configure time and
    depends on a patched libparted.

 configure.in                        |   15 +++++++++++++
 include/DialogFeatures.h            |    8 +++++++
 include/Utils.h                     |    8 ++++++-
 src/DialogFeatures.cc               |    8 +++++++
 src/Dialog_Partition_Resize_Move.cc |   10 +++++++-
 src/GParted_Core.cc                 |    4 +-
 src/Win_GParted.cc                  |   13 +++++++++--
 src/btrfs.cc                        |   38 +++++++++++++++++++++++++---------
 src/ext2.cc                         |    3 ++
 src/jfs.cc                          |   37 ++++++++++++++++++++++++---------
 src/reiserfs.cc                     |    4 ++-
 src/xfs.cc                          |   38 ++++++++++++++++++++++++----------
 12 files changed, 146 insertions(+), 40 deletions(-)
---
diff --git a/configure.in b/configure.in
index 0455978..a92f314 100644
--- a/configure.in
+++ b/configure.in
@@ -310,6 +310,20 @@ else
        AC_MSG_RESULT([no])
 fi
 
+AC_ARG_ENABLE([online_resize],
+  [  --enable-online-resize   enable online resize support],,)
+if test "x${enable_online_resize}" = "x" ; then
+       enable_online_resize=no
+fi
+
+AC_MSG_CHECKING([whether online resize support is enabled])
+if test ${enable_online_resize} = yes; then
+       AC_MSG_RESULT([yes])
+       dnl Set   #define USE_LIBPARTED_DMRAID 1   to indicate documentation not wanted
+       AC_DEFINE([ENABLE_ONLINE_RESIZE], [1], [Define to 1 if --enable-online-resize specified])
+else
+       AC_MSG_RESULT([no])
+fi
 
 AC_CONFIG_FILES([
 Makefile
@@ -337,6 +351,7 @@ echo ""
 echo "                           Build documentation?  :  $enable_doc"
 echo ""
 echo "           Use native libparted dmraid support?  :  $enable_libparted_dmraid"
+echo "                    Enable online resize support :  $enable_online_resize"
 echo ""
 echo "       --- Features Based On Libparted Version ---"
 echo "      Need partition table re-read work around?  :  $need_pt_reread_work_around"
diff --git a/include/DialogFeatures.h b/include/DialogFeatures.h
index 6fb256d..4750459 100644
--- a/include/DialogFeatures.h
+++ b/include/DialogFeatures.h
@@ -52,6 +52,10 @@ private:
                Gtk::TreeModelColumn< Glib::RefPtr<Gdk::Pixbuf> > create ;
                Gtk::TreeModelColumn< Glib::RefPtr<Gdk::Pixbuf> > grow ;
                Gtk::TreeModelColumn< Glib::RefPtr<Gdk::Pixbuf> > shrink ;
+#ifdef ENABLE_ONLINE_RESIZE
+               Gtk::TreeModelColumn< Glib::RefPtr<Gdk::Pixbuf> > online_grow;
+               Gtk::TreeModelColumn< Glib::RefPtr<Gdk::Pixbuf> > online_shrink;
+#endif
                Gtk::TreeModelColumn< Glib::RefPtr<Gdk::Pixbuf> > move ;
                Gtk::TreeModelColumn< Glib::RefPtr<Gdk::Pixbuf> > copy ;
                Gtk::TreeModelColumn< Glib::RefPtr<Gdk::Pixbuf> > check ;
@@ -65,6 +69,10 @@ private:
                        add( create ) ;
                        add( grow ) ;
                        add( shrink ) ;
+#ifdef ENABLE_ONLINE_RESIZE
+                       add( online_grow ) ;
+                       add( online_shrink ) ;
+#endif
                        add( move ) ;
                        add( copy ) ;
                        add( check ) ;
diff --git a/include/Utils.h b/include/Utils.h
index 5094890..1c60f50 100644
--- a/include/Utils.h
+++ b/include/Utils.h
@@ -131,7 +131,10 @@ struct FS
        Support copy ;
        Support remove ;
        Support online_read ;  //Can and how to read sector usage while active
-
+#ifdef ENABLE_ONLINE_RESIZE
+       Support online_grow;
+       Support online_shrink;
+#endif
        Byte_Value MIN ; 
        Byte_Value MAX ;
        
@@ -139,6 +142,9 @@ struct FS
        {
                read = read_label = write_label = read_uuid = write_uuid = create = grow = shrink =
                move = check = copy = remove = online_read = NONE ;
+#ifdef ENABLE_ONLINE_RESIZE
+               online_grow = online_shrink = NONE;
+#endif
                MIN = MAX = 0 ;
        } 
 } ;
diff --git a/src/DialogFeatures.cc b/src/DialogFeatures.cc
index cc51f44..5ed3081 100644
--- a/src/DialogFeatures.cc
+++ b/src/DialogFeatures.cc
@@ -36,6 +36,10 @@ DialogFeatures::DialogFeatures()
        treeview_filesystems .append_column( _("Create"), treeview_filesystems_columns .create );
        treeview_filesystems .append_column( _("Grow"), treeview_filesystems_columns .grow );
        treeview_filesystems .append_column( _("Shrink"), treeview_filesystems_columns .shrink );
+#ifdef ENABLE_ONLINE_RESIZE
+       treeview_filesystems .append_column( _("Online Grow"), treeview_filesystems_columns.online_grow );
+       treeview_filesystems .append_column( _("Online Shrink"), treeview_filesystems_columns.online_shrink );
+#endif
        treeview_filesystems .append_column( _("Move"), treeview_filesystems_columns .move );
        treeview_filesystems .append_column( _("Copy"), treeview_filesystems_columns .copy );
        treeview_filesystems .append_column( _("Check"), treeview_filesystems_columns .check );
@@ -141,6 +145,10 @@ void DialogFeatures::show_filesystem( const FS & fs )
        treerow[ treeview_filesystems_columns .create ] = fs .create ? icon_yes : icon_no ; 
        treerow[ treeview_filesystems_columns .grow ] = fs .grow ? icon_yes : icon_no ; 
        treerow[ treeview_filesystems_columns .shrink ] = fs .shrink ? icon_yes : icon_no ; 
+#ifdef ENABLE_ONLINE_RESIZE
+       treerow[ treeview_filesystems_columns .online_grow ] = fs.online_grow ? icon_yes : icon_no;
+       treerow[ treeview_filesystems_columns .online_shrink ] = fs.online_shrink ? icon_yes : icon_no;
+#endif
        treerow[ treeview_filesystems_columns .move ] = fs .move ? icon_yes : icon_no ;  
        treerow[ treeview_filesystems_columns .copy ] = fs .copy ? icon_yes : icon_no ; 
        treerow[ treeview_filesystems_columns .check ] = fs .check ? icon_yes : icon_no ; 
diff --git a/src/Dialog_Partition_Resize_Move.cc b/src/Dialog_Partition_Resize_Move.cc
index 0ba677f..cebd6d9 100644
--- a/src/Dialog_Partition_Resize_Move.cc
+++ b/src/Dialog_Partition_Resize_Move.cc
@@ -78,7 +78,7 @@ void Dialog_Partition_Resize_Move::Resize_Move_Normal( const std::vector<Partiti
        }
 
        //see if we need a fixed_start
-       if ( fs .move )
+       if ( fs .move && !selected_partition.busy)
        {
                set_title( String::ucompose( _("Resize/Move %1"), selected_partition .get_path() ) ) ;
                frame_resizer_base ->set_fixed_start( false ) ;
@@ -158,10 +158,16 @@ void Dialog_Partition_Resize_Move::Resize_Move_Normal( const std::vector<Partiti
        frame_resizer_base ->set_x_end( 
                Utils::round( selected_partition .get_sector_length() / ( total_length / 500.00 ) ) + 
frame_resizer_base ->get_x_start() ) ;
        Sector min_resize = selected_partition .estimated_min_size() ;
+
        frame_resizer_base ->set_used( Utils::round( min_resize / ( total_length / 500.00 ) ) ) ;
 
        //set MIN
-       if ( fs .shrink )
+#ifdef ENABLE_ONLINE_RESIZE
+       if ( (selected_partition.busy && fs.online_shrink != FS::NONE) ||
+            (!selected_partition.busy && fs.shrink ) )
+#else
+       if ( fs. shrink )
+#endif
        {
                //since some file systems have lower limits we need to check for this
                if ( min_resize > (fs .MIN / selected_partition .sector_size) )
diff --git a/src/GParted_Core.cc b/src/GParted_Core.cc
index 41c8926..c57b62c 100644
--- a/src/GParted_Core.cc
+++ b/src/GParted_Core.cc
@@ -2246,7 +2246,7 @@ bool GParted_Core::resize( const Partition & partition_old,
        }
 
        bool succes = false ;
-       if ( check_repair_filesystem( partition_new, operationdetail ) )
+       if ( partition_new.busy || check_repair_filesystem( partition_new, operationdetail ) )
        {
                succes = true ;
 
@@ -2263,7 +2263,7 @@ bool GParted_Core::resize( const Partition & partition_old,
                        && partition_new .get_sector_length() > partition_old .get_sector_length()
                       )
                   )
-                       succes =    check_repair_filesystem( partition_new, operationdetail )
+                       succes = (partition_new.busy || check_repair_filesystem( partition_new, 
operationdetail ))
                                 && maximize_filesystem( partition_new, operationdetail ) ;
 
                return succes ;
diff --git a/src/Win_GParted.cc b/src/Win_GParted.cc
index 92cec19..b575d3d 100644
--- a/src/Win_GParted.cc
+++ b/src/Win_GParted.cc
@@ -937,6 +937,8 @@ void Win_GParted::set_valid_operations()
        //no partition selected...      
        if ( ! selected_partition .get_paths() .size() )
                return ;
+
+       fs = gparted_core.get_fs( selected_partition.filesystem );
        
        //if there's something, there's some info ;)
        allow_info( true ) ;
@@ -989,7 +991,14 @@ void Win_GParted::set_valid_operations()
 
        //only unmount/swapoff/VG deactivate/... is allowed if busy
        if ( selected_partition .busy )
-               return ;
+       {
+#ifdef ENABLE_ONLINE_RESIZE
+               //find out if resizing/moving is possible
+               if ( (fs.online_grow || fs.online_shrink) && ! devices[ current_device ] .readonly )
+                       allow_resize( true );
+#endif
+               return;
+       }
 
        //UNALLOCATED
        if ( selected_partition .type == GParted::TYPE_UNALLOCATED )
@@ -1066,8 +1075,6 @@ void Win_GParted::set_valid_operations()
        //PRIMARY and LOGICAL
        if (  selected_partition .type == GParted::TYPE_PRIMARY || selected_partition .type == 
GParted::TYPE_LOGICAL )
        {
-               fs = gparted_core .get_fs( selected_partition .filesystem ) ;
-               
                allow_delete( true ) ;
                allow_format( true ) ;
                
diff --git a/src/btrfs.cc b/src/btrfs.cc
index c7cf842..a90b04d 100644
--- a/src/btrfs.cc
+++ b/src/btrfs.cc
@@ -99,7 +99,10 @@ FS btrfs::get_filesystem_support()
        }
 
        fs .online_read = FS::GPARTED ;
-
+#ifdef ENABLE_ONLINE_RESIZE
+       fs.online_grow = GParted::FS::EXTERNAL;
+       fs.online_shrink = GParted::FS::EXTERNAL;
+#endif
        fs .MIN = 256 * MEBIBYTE ;
 
        //Linux before version 3.2 fails when resizing btrfs file system
@@ -169,17 +172,27 @@ bool btrfs::write_label( const Partition & partition, OperationDetail & operatio
 bool btrfs::resize( const Partition & partition_new, OperationDetail & operationdetail, bool fill_partition )
 {
        bool success = true ;
+       bool do_unmount = false;
 
-       Glib::ustring mount_point = mk_temp_dir( "", operationdetail ) ;
-       if ( mount_point .empty() )
-               return false ;
-
-       success &= ! execute_command( "mount -v -t btrfs " + partition_new .get_path() + " " + mount_point,
-                                     operationdetail, true ) ;
+       Glib::ustring mount_point;
+#ifdef ENABLE_ONLINE_RESIZE
+       if ( !partition_new.busy )
+#endif
+       {
+               mount_point = mk_temp_dir( "", operationdetail );
+               if ( mount_point .empty() )
+                       return false ;
+               success &= ! execute_command( "mount -v -t btrfs " + partition_new .get_path() + " " + 
mount_point,
+                                             operationdetail, true );
+       }
+#ifdef ENABLE_ONLINE_RESIZE
+       else mount_point = partition_new.get_mountpoint();
+#endif
 
        if ( success )
        {
                Glib::ustring size ;
+               do_unmount = true;
                if ( ! fill_partition )
                        size = Utils::num_to_str( floor( Utils::sector_to_unit(
                                        partition_new .get_sector_length(), partition_new .sector_size, 
UNIT_KIB ) ) ) + "K" ;
@@ -214,11 +227,16 @@ bool btrfs::resize( const Partition & partition_new, OperationDetail & operation
                }
                operationdetail .get_last_child() .set_status( resize_succeeded ? STATUS_SUCCES : 
STATUS_ERROR ) ;
                success &= resize_succeeded ;
-
-               success &= ! execute_command( "umount -v " + mount_point, operationdetail, true ) ;
        }
 
-       rm_temp_dir( mount_point, operationdetail ) ;
+#ifdef ENABLE_ONLINE_RESIZE
+       if ( !partition_new.busy )
+#endif
+       {
+               if ( do_unmount )
+                       success &= ! execute_command( "umount -v " + mount_point, operationdetail, true );
+               rm_temp_dir( mount_point, operationdetail );
+       }
 
        return success ;
 }
diff --git a/src/ext2.cc b/src/ext2.cc
index 9b54010..9cb6ad8 100644
--- a/src/ext2.cc
+++ b/src/ext2.cc
@@ -65,6 +65,9 @@ FS ext2::get_filesystem_support()
                }
 
                fs .online_read = FS::EXTERNAL ;
+#ifdef ENABLE_ONLINE_RESIZE
+               fs.online_grow = FS::EXTERNAL;
+#endif
        }
 
        return fs ;
diff --git a/src/jfs.cc b/src/jfs.cc
index 606da2e..9ac08e6 100644
--- a/src/jfs.cc
+++ b/src/jfs.cc
@@ -62,7 +62,9 @@ FS jfs::get_filesystem_support()
        fs .online_read = FS::GPARTED ;
 
        fs .MIN = 16 * MEBIBYTE ;
-       
+#ifdef ENABLE_ONLINE_RESIZE
+       fs.online_grow = GParted::FS::EXTERNAL;
+#endif
        return fs ;
 }
 
@@ -157,23 +159,38 @@ bool jfs::create( const Partition & new_partition, OperationDetail & operationde
 bool jfs::resize( const Partition & partition_new, OperationDetail & operationdetail, bool fill_partition )
 {
        bool success = true ;
+       bool do_unmount = false;
 
-       Glib::ustring mount_point = mk_temp_dir( "", operationdetail ) ;
-       if ( mount_point .empty() )
-               return false ;
-
-       success &= ! execute_command( "mount -v -t jfs " + partition_new .get_path() + " " + mount_point,
-                                     operationdetail, true ) ;
+       Glib::ustring mount_point;
+#ifdef ENABLE_ONLINE_RESIZE
+       if ( !partition_new.busy )
+#endif
+       {
+               mount_point = mk_temp_dir( "", operationdetail );
+               if ( mount_point.empty() )
+                       return false;
+               success &= ! execute_command( "mount -v -t jfs " + partition_new .get_path() + " " + 
mount_point,
+                                             operationdetail, true );
+       }
+#ifdef ENABLE_ONLINE_RESIZE
+       else mount_point = partition_new.get_mountpoint();
+#endif
 
        if ( success )
        {
+               do_unmount = true;
                success &= ! execute_command( "mount -v -t jfs -o remount,resize " + partition_new 
.get_path() + " " + mount_point,
                                              operationdetail, true ) ;
-
-               success &= ! execute_command( "umount -v " + mount_point, operationdetail, true ) ;
        }
 
-       rm_temp_dir( mount_point, operationdetail ) ;
+#ifdef ENABLE_ONLINE_RESIZE
+       if (!partition_new.busy )
+#endif
+       {
+               if ( do_unmount )
+                       success &= ! execute_command( "umount -v " + mount_point, operationdetail, true ) ;
+               rm_temp_dir( mount_point, operationdetail );
+       }
 
        return success ;
 }
diff --git a/src/reiserfs.cc b/src/reiserfs.cc
index b546646..f51223a 100644
--- a/src/reiserfs.cc
+++ b/src/reiserfs.cc
@@ -65,7 +65,9 @@ FS reiserfs::get_filesystem_support()
 
        //Actual minimum is at least 18 blocks larger than 32 MiB for the journal offset
        fs .MIN = 34 * MEBIBYTE ;
-       
+#ifdef ENABLE_ONLINE_RESIZE
+       fs.online_grow = FS::EXTERNAL;
+#endif
        return fs ;
 }
 
diff --git a/src/xfs.cc b/src/xfs.cc
index 53505c8..d0b2e8b 100644
--- a/src/xfs.cc
+++ b/src/xfs.cc
@@ -69,6 +69,9 @@ FS xfs::get_filesystem_support()
        fs .online_read = FS::GPARTED ;
 
        fs .MIN = 32 * MEBIBYTE ;//official minsize = 16MB, but the smallest xfs_repair can handle is 32MB...
+#ifdef ENABLE_ONLINE_RESIZE
+       fs.online_grow = FS::EXTERNAL;
+#endif
        
        return fs ;
 }
@@ -174,23 +177,36 @@ bool xfs::create( const Partition & new_partition, OperationDetail & operationde
 bool xfs::resize( const Partition & partition_new, OperationDetail & operationdetail, bool fill_partition )
 {
        bool success = true ;
+       bool do_unmount = false;
 
-       Glib::ustring mount_point = mk_temp_dir( "", operationdetail ) ;
-       if ( mount_point .empty() )
-               return false ;
-
-       success &= ! execute_command( "mount -v -t xfs " + partition_new .get_path() + " " + mount_point,
-                                     operationdetail, true ) ;
-
+       Glib::ustring mount_point;
+#ifdef ENABLE_ONLINE_RESIZE
+       if ( !partition_new.busy )
+#endif
+       {
+               mount_point = mk_temp_dir( "", operationdetail );
+               if ( mount_point.empty() )
+                       return false;
+               success &= ! execute_command( "mount -v -t xfs " + partition_new .get_path() + " " + 
mount_point,
+                                             operationdetail, true );
+       }
+#ifdef ENABLE_ONLINE_RESIZE
+       else mount_point = partition_new.get_mountpoint();
+#endif
        if ( success )
        {
+               do_unmount = true;
                success &= ! execute_command( "xfs_growfs " + mount_point, operationdetail, true ) ;
-
-               success &= ! execute_command( "umount -v " + mount_point, operationdetail, true ) ;
        }
 
-       rm_temp_dir( mount_point, operationdetail ) ;
-
+#ifdef ENABLE_ONLINE_RESIZE
+       if ( !partition_new.busy )
+#endif
+       {
+               if ( do_unmount )
+                       success &= ! execute_command( "umount -v " + mount_point, operationdetail, true );
+               rm_temp_dir( mount_point, operationdetail );
+       }
        return success ;
 }
 


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