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
This commit is contained in:
Mike Fleetwood 2015-08-09 14:35:24 +01:00 committed by Curtis Gedak
parent b0bd465098
commit 809a7e0954
2 changed files with 61 additions and 1 deletions

View file

@ -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

View file

@ -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