[gparted] Display progress of XFS file system specific copy operation (#760709)



commit 809a7e095444f881256871d915b460af5cb4bab2
Author: Mike Fleetwood <mike fleetwood googlemail com>
Date:   Sun Aug 9 14:35:24 2015 +0100

    Display progress of XFS file system specific copy operation (#760709)
    
    XFS uses a file system specific method to copy the partition using
    "xfsdump | xfsrestore".  Monitor progress by periodically querying the
    destination file system usage and comparing to the source file system
    usage.  Use 0.5 seconds as the polling interval to match that used by
    the internal block copying algorithm.
    
    NOTE:
    The number of used blocks in the source and destination file system will
    be very close but may not match exactly.  I have seen an XFS copy finish
    with the following progress text:
        1.54 GiB of 1.50 GiB copied (-00:00:02 remaining)
    Allow the progress bar to overrun like this as it is informing the user
    that it actually copied a little more data and took a little longer than
    expected.  Needs these two previous commits to correctly round and
    format the negative time remaining:
        Fix rounding of negative numbers (#760709)
        Fix formatting of negative time values (#760709)
    
    Bug 760709 - Add progress bars to XFS and EXT2/3/4 file system specific
                 copy methods

 include/xfs.h |   10 ++++++++++
 src/xfs.cc    |   52 +++++++++++++++++++++++++++++++++++++++++++++++++++-
 2 files changed, 61 insertions(+), 1 deletions(-)
---
diff --git a/include/xfs.h b/include/xfs.h
index 1bd1f11..6f11cd3 100644
--- a/include/xfs.h
+++ b/include/xfs.h
@@ -20,7 +20,11 @@
 #define GPARTED_XFS_H
 
 #include "../include/FileSystem.h"
+#include "../include/OperationDetail.h"
 #include "../include/Partition.h"
+#include "../include/Utils.h"
+
+#include <glibmm/ustring.h>
 
 namespace GParted
 {
@@ -40,6 +44,12 @@ public:
                   Partition & dest_part,
                   OperationDetail & operationdetail ) ;
        bool check_repair( const Partition & partition, OperationDetail & operationdetail ) ;
+
+private:
+       bool copy_progress( OperationDetail * operationdetail );
+
+       Byte_Value src_used;             // Used bytes in the source FS of an XFS copy operation
+       Glib::ustring dest_mount_point;  // Temporary FS mount point of an XFS copy operation
 };
 
 } //GParted
diff --git a/src/xfs.cc b/src/xfs.cc
index 9ccf675..449859f 100644
--- a/src/xfs.cc
+++ b/src/xfs.cc
@@ -17,7 +17,12 @@
  
  
 #include "../include/xfs.h"
+#include "../include/OperationDetail.h"
 #include "../include/Partition.h"
+#include "../include/ProgressBar.h"
+#include "../include/Utils.h"
+
+#include <glibmm/ustring.h>
 
 namespace GParted
 {
@@ -223,7 +228,7 @@ bool xfs::copy( const Partition & src_part,
        if ( src_mount_point .empty() )
                return false ;
 
-       Glib::ustring dest_mount_point = mk_temp_dir( "dest", operationdetail ) ;
+       dest_mount_point = mk_temp_dir( "dest", operationdetail );
        if ( dest_mount_point .empty() )
        {
                rm_temp_dir( src_mount_point, operationdetail ) ;
@@ -233,6 +238,14 @@ bool xfs::copy( const Partition & src_part,
        success &= ! execute_command( "mount -v -t xfs -o noatime,ro " + src_part.get_path() +
                                      " " + src_mount_point, operationdetail, EXEC_CHECK_STATUS );
 
+       // Get source FS used bytes, needed in progress update calculation
+       Byte_Value fs_size;
+       Byte_Value fs_free;
+       if ( Utils::get_mounted_filesystem_usage( src_mount_point, fs_size, fs_free, error ) == 0 )
+               src_used = fs_size - fs_free;
+       else
+               src_used = -1LL;
+
        if ( success )
        {
                success &= ! execute_command( "mount -v -t xfs " + dest_part.get_path() +
@@ -240,9 +253,23 @@ bool xfs::copy( const Partition & src_part,
 
                if ( success )
                {
+                       ProgressBar & progressbar = operationdetail.get_progressbar();
+                       sigc::connection c;
+                       if ( src_used > 0LL )
+                       {
+                               progressbar.start( (double)src_used, PROGRESSBAR_TEXT_COPY_BYTES );
+                               // Get xfs::copy_progress() called every 500 ms to update progress
+                               c = Glib::signal_timeout().connect(
+                                               sigc::bind<OperationDetail*>( sigc::mem_fun( *this, 
&xfs::copy_progress ),
+                                                                             &operationdetail ),
+                                               500 );
+                       }
                        success &= ! execute_command( "sh -c 'xfsdump -J - " + src_mount_point +
                                                      " | xfsrestore -J - " + dest_mount_point + "'",
                                                      operationdetail, EXEC_CHECK_STATUS|EXEC_CANCEL_SAFE );
+                       c.disconnect();
+                       if ( progressbar.running() )
+                               progressbar.stop();
 
                        success &= ! execute_command( "umount -v " + dest_part.get_path(), operationdetail,
                                                      EXEC_CHECK_STATUS );
@@ -264,4 +291,27 @@ bool xfs::check_repair( const Partition & partition, OperationDetail & operation
                                  EXEC_CHECK_STATUS|EXEC_CANCEL_SAFE );
 }
 
+//Private methods
+
+// Report progress of XFS copy.  Monitor destination FS used bytes and track against
+// recorded source FS used bytes.
+bool xfs::copy_progress( OperationDetail * operationdetail )
+{
+       ProgressBar & progressbar = operationdetail->get_progressbar();
+       Byte_Value fs_size;
+       Byte_Value fs_free;
+       Byte_Value dst_used;
+       if ( Utils::get_mounted_filesystem_usage( dest_mount_point, fs_size, fs_free, error ) != 0 )
+       {
+               if ( progressbar.running() )
+                       progressbar.stop();
+               // Failed to get destination FS used bytes.  Remove this timed callback early.
+               return false;
+       }
+       dst_used = fs_size - fs_free;
+       progressbar.update( (double)dst_used );
+       operationdetail->signal_update.emit( *operationdetail );
+       return true;
+}
+
 } //GParted


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