diff --git a/README b/README index 3c740f0f..0becc586 100644 --- a/README +++ b/README @@ -112,7 +112,17 @@ b. Building from Source dmraid support use the --enable-libparted-dmraid flag: E.g., ./configure --enable-libparted-dmraid - Please note that more than one configure flags can be used: + If you wish to build this package with online resize support then + the following is required: + a) A version of libparted that includes the online resize patch. + At time of writing (November 2013), this patch was only + included in Debian and derived distros with parted package + version 2.3-14 or higher. + b) Linux kernel version 3.6 or higher. + Enable with the --enable-online-resize flag: + E.g., ./configure --enable-online-resize + + Please note that more than one configure flag can be used: E.g., ./configure --disable-doc --enable-libparted-dmraid The INSTALL file contains further GNU installation instructions. diff --git a/configure.ac b/configure.ac index f415ca66..0b72e743 100644 --- a/configure.ac +++ b/configure.ac @@ -391,6 +391,22 @@ else AC_MSG_RESULT([no]) fi +dnl====================== +dnl check whether to enable online resize support +dnl====================== +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]) + AC_DEFINE([ENABLE_ONLINE_RESIZE], [1], [Define to 1 if --enable-online-resize specified]) +else + AC_MSG_RESULT([no]) +fi AC_CONFIG_FILES([ Makefile @@ -418,6 +434,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 4a7521e1..4845a358 100644 --- a/include/DialogFeatures.h +++ b/include/DialogFeatures.h @@ -51,7 +51,9 @@ private: Gtk::TreeModelColumn filesystem; Gtk::TreeModelColumn< Glib::RefPtr > create ; Gtk::TreeModelColumn< Glib::RefPtr > grow ; + Gtk::TreeModelColumn< Glib::RefPtr > online_grow ; Gtk::TreeModelColumn< Glib::RefPtr > shrink ; + Gtk::TreeModelColumn< Glib::RefPtr > online_shrink ; Gtk::TreeModelColumn< Glib::RefPtr > move ; Gtk::TreeModelColumn< Glib::RefPtr > copy ; Gtk::TreeModelColumn< Glib::RefPtr > check ; @@ -64,7 +66,9 @@ private: add( filesystem ); add( create ) ; add( grow ) ; + add( online_grow ) ; add( shrink ) ; + add( online_shrink ) ; add( move ) ; add( copy ) ; add( check ) ; @@ -76,7 +80,7 @@ private: treeview_filesystems_Columns treeview_filesystems_columns ; - Glib::RefPtr icon_yes, icon_no ; + Glib::RefPtr icon_yes, icon_no, icon_blank ; }; } //GParted diff --git a/include/Utils.h b/include/Utils.h index 750a0d29..b59dd3a9 100644 --- a/include/Utils.h +++ b/include/Utils.h @@ -138,6 +138,8 @@ struct FS Support copy ; Support remove ; Support online_read ; //Can and how to read sector usage while active + Support online_grow ; + Support online_shrink ; Byte_Value MIN ; Byte_Value MAX ; @@ -145,7 +147,8 @@ struct FS FS() { read = read_label = write_label = read_uuid = write_uuid = create = create_with_label = - grow = shrink = move = check = copy = remove = online_read = NONE ; + grow = shrink = move = check = copy = remove = online_read = + online_grow = online_shrink = NONE ; MIN = MAX = 0 ; } } ; diff --git a/src/DialogFeatures.cc b/src/DialogFeatures.cc index 8b13cf3d..f6ee8cbe 100644 --- a/src/DialogFeatures.cc +++ b/src/DialogFeatures.cc @@ -29,13 +29,27 @@ DialogFeatures::DialogFeatures() set_has_separator( false ) ; set_resizable( false ) ; + //initialize icons + icon_yes = render_icon( Gtk::Stock::APPLY, Gtk::ICON_SIZE_LARGE_TOOLBAR ); + icon_no = render_icon( Gtk::Stock::CANCEL, Gtk::ICON_SIZE_LARGE_TOOLBAR ); + icon_blank = Gdk::Pixbuf::create( Gdk::COLORSPACE_RGB, true, 8, + icon_yes ->get_width(), icon_yes ->get_height() ); + icon_blank ->fill( 0xFFFFFF00 ); + //treeview + Gtk::TreeView::Column *col; liststore_filesystems = Gtk::ListStore::create( treeview_filesystems_columns ); treeview_filesystems .set_model( liststore_filesystems ); treeview_filesystems .append_column( _("File System"), treeview_filesystems_columns .filesystem ); 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 ); + col = manage( new Gtk::TreeView::Column( _("Grow") ) ); + col ->pack_start( treeview_filesystems_columns .grow, false ); + col ->pack_start( treeview_filesystems_columns .online_grow, false ); + treeview_filesystems .append_column( *col ); + col = manage( new Gtk::TreeView::Column( _("Shrink") ) ); + col ->pack_start( treeview_filesystems_columns .shrink, false ); + col ->pack_start( treeview_filesystems_columns .online_shrink, false ); + treeview_filesystems .append_column( *col ); 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 ); @@ -72,18 +86,36 @@ DialogFeatures::DialogFeatures() hbox = manage(new Gtk::HBox()); { - Gtk::Image* image(manage(new Gtk::Image(Gtk::Stock::APPLY, Gtk::ICON_SIZE_LARGE_TOOLBAR))); - hbox->pack_start(*image, Gtk::PACK_SHRINK); + Gtk::Image *image_yes( manage( new Gtk::Image( icon_yes ) ) ); + hbox ->pack_start( *image_yes, Gtk::PACK_SHRINK ); + image_yes = manage( new Gtk::Image( icon_yes ) ); + hbox ->pack_start( *image_yes, Gtk::PACK_SHRINK ); hbox->pack_start(*Utils::mk_label( - /* TO TRANSLATORS: Available - * means that this action is valid for this file system. + /* TO TRANSLATORS: Available offline and online + * means that this action is valid for this file system when + * it is both unmounted and mounted. */ - _("Available")), Gtk::PACK_EXPAND_WIDGET ); + _("Available offline and online")), Gtk::PACK_EXPAND_WIDGET ); vbox ->pack_start(*hbox); + hbox = manage(new Gtk::HBox() ); + image_yes = manage( new Gtk::Image( icon_yes ) ); + hbox ->pack_start( *image_yes, Gtk::PACK_SHRINK ); + Gtk::Image *image_blank( manage( new Gtk::Image( icon_blank ) ) ); + hbox ->pack_start( *image_blank, Gtk::PACK_SHRINK ); + hbox ->pack_start( *Utils::mk_label( + /* TO TRANSLATORS: Available offline only + * means that this action is valid for this file system only + * when it is unmounted. + */ + _("Available offline only")), Gtk::PACK_EXPAND_WIDGET ); + vbox ->pack_start( *hbox ); + hbox = manage(new Gtk::HBox()); - image = manage(new Gtk::Image(Gtk::Stock::CANCEL, Gtk::ICON_SIZE_LARGE_TOOLBAR)); - hbox->pack_start(*image, Gtk::PACK_SHRINK); + Gtk::Image *image_no( manage( new Gtk::Image( icon_no ) ) ); + hbox ->pack_start( *image_no, Gtk::PACK_SHRINK ); + image_blank = manage( new Gtk::Image( icon_blank ) ); + hbox ->pack_start( *image_blank, Gtk::PACK_SHRINK ); } hbox->pack_start(*Utils::mk_label( @@ -106,10 +138,6 @@ DialogFeatures::DialogFeatures() expander_legend.add(*hbox2); } - //initialize icons - icon_yes = render_icon( Gtk::Stock::APPLY, Gtk::ICON_SIZE_LARGE_TOOLBAR ) ; - icon_no = render_icon( Gtk::Stock::CANCEL, Gtk::ICON_SIZE_LARGE_TOOLBAR ) ; - /*TO TRANSLATORS: This is a button that will search for the software tools installed and then refresh the screen with the file system actions supported. */ add_button( _("Rescan For Supported Actions"), Gtk::RESPONSE_OK ); add_button( Gtk::Stock::CLOSE, Gtk::RESPONSE_CLOSE ) ->grab_focus() ; @@ -142,7 +170,9 @@ 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 .online_grow ] = fs .online_grow ? icon_yes : icon_blank ; treerow[ treeview_filesystems_columns .shrink ] = fs .shrink ? icon_yes : icon_no ; + treerow[ treeview_filesystems_columns .online_shrink ] = fs .online_shrink ? icon_yes : icon_blank ; 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 0ba677f4..c9e8fd2b 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::vectorset_fixed_start( false ) ; @@ -161,7 +161,9 @@ void Dialog_Partition_Resize_Move::Resize_Move_Normal( const std::vectorset_used( Utils::round( min_resize / ( total_length / 500.00 ) ) ) ; //set MIN - if ( fs .shrink ) + if ( ( fs .shrink && ! selected_partition .busy ) + || ( fs .online_shrink && selected_partition .busy ) + ) { //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/Dialog_Progress.cc b/src/Dialog_Progress.cc index f8fcc7fd..7fcf71a2 100644 --- a/src/Dialog_Progress.cc +++ b/src/Dialog_Progress.cc @@ -360,6 +360,9 @@ void Dialog_Progress::on_save() << "

" << _("GParted") << " " << VERSION #ifdef USE_LIBPARTED_DMRAID << " --enable-libparted-dmraid" +#endif +#ifdef ENABLE_ONLINE_RESIZE + << " --enable-online-resize" #endif << "

" << std::endl << "

" << _("Libparted") << " " << signal_get_libparted_version .emit() << "

" << std::endl ; diff --git a/src/GParted_Core.cc b/src/GParted_Core.cc index a0046dc0..962d8f3f 100644 --- a/src/GParted_Core.cc +++ b/src/GParted_Core.cc @@ -2271,7 +2271,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 ; @@ -2288,7 +2288,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 87307767..5b99d5e5 100644 --- a/src/Win_GParted.cc +++ b/src/Win_GParted.cc @@ -943,7 +943,10 @@ void Win_GParted::set_valid_operations() //no partition selected... if ( ! selected_partition .get_paths() .size() ) return ; - + + //get filesystem capabilities + fs = gparted_core .get_fs( selected_partition .filesystem ) ; + //if there's something, there's some info ;) allow_info( true ) ; @@ -994,7 +997,16 @@ void Win_GParted::set_valid_operations() ) allow_toggle_busy_state( true ) ; - //only unmount/swapoff/VG deactivate/... is allowed if busy +#ifdef ENABLE_ONLINE_RESIZE + //Find out if online resizing is possible + if ( selected_partition .busy ) + { + if ( ( fs .online_grow || fs .online_shrink ) && ! devices[ current_device ] .readonly ) + allow_resize( true ) ; + } +#endif + + //only unmount/swapoff/VG deactivate or online actions allowed if busy if ( selected_partition .busy ) return ; @@ -1073,8 +1085,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 cecb0897..56b39444 100644 --- a/src/btrfs.cc +++ b/src/btrfs.cc @@ -103,6 +103,13 @@ FS btrfs::get_filesystem_support() } fs .online_read = FS::GPARTED ; +#ifdef ENABLE_ONLINE_RESIZE + if ( Utils::kernel_version_at_least( 3, 6, 0 ) ) + { + fs .online_grow = fs .grow ; + fs .online_shrink = fs .shrink ; + } +#endif fs .MIN = 256 * MEBIBYTE ; @@ -174,12 +181,17 @@ bool btrfs::resize( const Partition & partition_new, OperationDetail & operation { bool success = true ; - 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 ; + if ( ! partition_new .busy ) + { + 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 ) ; + } + else + mount_point = partition_new .get_mountpoint() ; if ( success ) { @@ -219,10 +231,12 @@ 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 ) ; + if ( ! partition_new .busy ) + success &= ! execute_command( "umount -v " + mount_point, operationdetail, true ) ; } - rm_temp_dir( mount_point, operationdetail ) ; + if ( ! partition_new .busy ) + rm_temp_dir( mount_point, operationdetail ) ; return success ; } diff --git a/src/ext2.cc b/src/ext2.cc index fe4e6679..6ba96249 100644 --- a/src/ext2.cc +++ b/src/ext2.cc @@ -66,6 +66,10 @@ FS ext2::get_filesystem_support() } fs .online_read = FS::EXTERNAL ; +#ifdef ENABLE_ONLINE_RESIZE + if ( specific_type != FS_EXT2 && Utils::kernel_version_at_least( 3, 6, 0 ) ) + fs .online_grow = fs .grow ; +#endif } return fs ; diff --git a/src/jfs.cc b/src/jfs.cc index a15f5ad9..39950ee1 100644 --- a/src/jfs.cc +++ b/src/jfs.cc @@ -63,6 +63,10 @@ FS jfs::get_filesystem_support() } fs .online_read = FS::GPARTED ; +#ifdef ENABLE_ONLINE_RESIZE + if ( Utils::kernel_version_at_least( 3, 6, 0 ) ) + fs .online_grow = fs .grow ; +#endif fs .MIN = 16 * MEBIBYTE ; @@ -161,22 +165,29 @@ bool jfs::resize( const Partition & partition_new, OperationDetail & operationde { bool success = true ; - 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 ; + if ( ! partition_new .busy ) + { + 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 ) ; + } + else + mount_point = partition_new .get_mountpoint() ; if ( success ) { 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 ) ; + if ( ! partition_new .busy ) + success &= ! execute_command( "umount -v " + mount_point, operationdetail, true ) ; } - rm_temp_dir( mount_point, operationdetail ) ; + if ( ! partition_new .busy ) + rm_temp_dir( mount_point, operationdetail ) ; return success ; } diff --git a/src/lvm2_pv.cc b/src/lvm2_pv.cc index c2304337..2e8d0c2e 100644 --- a/src/lvm2_pv.cc +++ b/src/lvm2_pv.cc @@ -61,6 +61,13 @@ FS lvm2_pv::get_filesystem_support() fs .check = FS::EXTERNAL ; fs .remove = FS::EXTERNAL ; fs .online_read = FS::EXTERNAL ; +#ifdef ENABLE_ONLINE_RESIZE + if ( Utils::kernel_version_at_least( 3, 6, 0 ) ) + { + fs .online_grow = fs .grow ; + fs .online_shrink = fs.shrink ; + } +#endif } return fs ; diff --git a/src/nilfs2.cc b/src/nilfs2.cc index c593efdb..a4758920 100644 --- a/src/nilfs2.cc +++ b/src/nilfs2.cc @@ -57,6 +57,13 @@ FS nilfs2::get_filesystem_support() fs .copy = GParted::FS::GPARTED ; fs .move = GParted::FS::GPARTED ; fs .online_read = FS::GPARTED ; +#ifdef ENABLE_ONLINE_RESIZE + if ( Utils::kernel_version_at_least( 3, 6, 0 ) ) + { + fs .online_grow = fs .grow ; + fs .online_shrink = fs .shrink ; + } +#endif //Minimum FS size is 128M+4K using mkfs.nilfs2 defaults fs .MIN = 128 * MEBIBYTE + 4 * KIBIBYTE ; @@ -160,12 +167,16 @@ bool nilfs2::resize( const Partition & partition_new, OperationDetail & operatio { bool success = true ; - Glib::ustring mount_point = mk_temp_dir( "", operationdetail ) ; - if ( mount_point .empty() ) - return false ; + Glib::ustring mount_point ; + if ( ! partition_new .busy ) + { + mount_point = mk_temp_dir( "", operationdetail ) ; + if ( mount_point .empty() ) + return false ; - success &= ! execute_command( "mount -v -t nilfs2 " + partition_new .get_path() + " " + mount_point, - operationdetail, true ) ; + success &= ! execute_command( "mount -v -t nilfs2 " + partition_new .get_path() + " " + mount_point, + operationdetail, true ) ; + } if ( success ) { @@ -178,10 +189,12 @@ bool nilfs2::resize( const Partition & partition_new, OperationDetail & operatio } success &= ! execute_command( cmd, operationdetail, true ) ; - success &= ! execute_command( "umount -v " + mount_point, operationdetail, true ) ; + if ( ! partition_new. busy ) + success &= ! execute_command( "umount -v " + mount_point, operationdetail, true ) ; } - rm_temp_dir( mount_point, operationdetail ) ; + if ( ! partition_new .busy ) + rm_temp_dir( mount_point, operationdetail ) ; return success ; } diff --git a/src/reiserfs.cc b/src/reiserfs.cc index 2275f14f..8a426004 100644 --- a/src/reiserfs.cc +++ b/src/reiserfs.cc @@ -65,6 +65,10 @@ FS reiserfs::get_filesystem_support() } fs .online_read = FS::GPARTED ; +#ifdef ENABLE_ONLINE_RESIZE + if ( Utils::kernel_version_at_least( 3, 6, 0 ) ) + fs. online_grow = fs. grow ; +#endif //Actual minimum is at least 18 blocks larger than 32 MiB for the journal offset fs .MIN = 34 * MEBIBYTE ; diff --git a/src/xfs.cc b/src/xfs.cc index 0255342c..46f7506c 100644 --- a/src/xfs.cc +++ b/src/xfs.cc @@ -70,6 +70,10 @@ FS xfs::get_filesystem_support() fs .move = GParted::FS::GPARTED ; fs .online_read = FS::GPARTED ; +#ifdef ENABLE_ONLINE_RESIZE + if ( Utils::kernel_version_at_least( 3, 6, 0 ) ) + fs .online_grow = fs .grow ; +#endif fs .MIN = 32 * MEBIBYTE ;//official minsize = 16MB, but the smallest xfs_repair can handle is 32MB... @@ -178,21 +182,28 @@ bool xfs::resize( const Partition & partition_new, OperationDetail & operationde { bool success = true ; - 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 ; + if ( ! partition_new .busy ) + { + 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 ) ; + } + else + mount_point = partition_new .get_mountpoint() ; if ( success ) { success &= ! execute_command( "xfs_growfs " + mount_point, operationdetail, true ) ; - success &= ! execute_command( "umount -v " + mount_point, operationdetail, true ) ; + if ( ! partition_new .busy ) + success &= ! execute_command( "umount -v " + mount_point, operationdetail, true ) ; } - rm_temp_dir( mount_point, operationdetail ) ; + if ( ! partition_new .busy ) + rm_temp_dir( mount_point, operationdetail ) ; return success ; }