[gparted] Enhance copy methods for sector sizes > 512 bytes



commit 8fb40d843d9e135b965cee8232bb7f2bbebf6661
Author: Curtis Gedak <gedakc gmail com>
Date:   Wed Apr 7 11:33:21 2010 -0600

    Enhance copy methods for sector sizes > 512 bytes

 include/GParted_Core.h |   24 ++--
 src/GParted_Core.cc    |  260 +++++++++++++++++++++++++++++-------------------
 2 files changed, 169 insertions(+), 115 deletions(-)
---
diff --git a/include/GParted_Core.h b/include/GParted_Core.h
index 2838507..7d111e8 100644
--- a/include/GParted_Core.h
+++ b/include/GParted_Core.h
@@ -1,5 +1,5 @@
 /* Copyright (C) 2004 Bart
- * Copyright (C) 2008, 2009 Curtis Gedak
+ * Copyright (C) 2008, 2009, 2010 Curtis Gedak
  *
  *  This program is free software; you can redistribute it and/or modify
  *  it under the terms of the GNU General Public License as published by
@@ -116,7 +116,7 @@ private:
 				
 	bool copy( const Partition & partition_src,
 		   Partition & partition_dst,
-		   Sector min_size,
+		   Byte_Value min_size,
 		   OperationDetail & operationdetail ) ; 
 	bool copy_filesystem_simulation( const Partition & partition_src,
 			      		 const Partition & partition_dst,
@@ -128,19 +128,19 @@ private:
 	bool copy_filesystem( const Partition & partition_src,
 			      const Partition & partition_dst,
 			      OperationDetail & operationdetail,
-			      Sector & total_done ) ;
+			      Byte_Value & total_done ) ;
 	bool copy_filesystem( const Glib::ustring & src_device,
 			      const Glib::ustring & dst_device,
 			      Sector src_start,
 			      Sector dst_start,
-			      Sector length,
+			      Byte_Value src_length,
 			      OperationDetail & operationdetail,
 			      bool readonly,
-			      Sector & total_done ) ;
+			      Byte_Value & total_done ) ;
 	void rollback_transaction( const Partition & partition_src,
-			      	   const Partition & partition_dst,
-			      	   OperationDetail & operationdetail,
-			      	   Sector total_done ) ;
+				   const Partition & partition_dst,
+				   OperationDetail & operationdetail,
+				   Byte_Value total_done ) ;
 
 	bool check_repair_filesystem( const Partition & partition, OperationDetail & operationdetail ) ;
 
@@ -152,17 +152,17 @@ private:
 			  const Glib::ustring & dst_device,
 			  Sector src_start,
 			  Sector dst_start,
-			  Sector length,
-			  Sector blocksize,
+			  Byte_Value length,
+			  Byte_Value blocksize,
 			  OperationDetail & operationdetail,
 			  bool readonly,
-			  Sector & total_done ) ;
+			  Byte_Value & total_done ) ;
 
 	bool copy_block( PedDevice * lp_device_src,
 			 PedDevice * lp_device_dst,
 			 Sector offset_src,
 			 Sector offset_dst,
-			 Sector blocksize,
+			 Byte_Value blocksize,
 			 Glib::ustring & error_message,
 			 bool readonly ) ; 
 	bool calibrate_partition( Partition & partition, OperationDetail & operationdetail ) ;
diff --git a/src/GParted_Core.cc b/src/GParted_Core.cc
index 70ab305..0acd82c 100644
--- a/src/GParted_Core.cc
+++ b/src/GParted_Core.cc
@@ -479,7 +479,7 @@ bool GParted_Core::apply_operation_to_disk( Operation * operation )
 
 					 copy( static_cast<OperationCopy*>( operation ) ->partition_copied,
 					       operation ->partition_new,
-					       static_cast<OperationCopy*>( operation ) ->partition_copied .get_length(),
+					       static_cast<OperationCopy*>( operation ) ->partition_copied .get_length() * DEFAULT_SECTOR_SIZE,
 					       operation ->operation_detail ) ;
 				break ;
 			case OPERATION_LABEL_PARTITION:
@@ -2004,7 +2004,7 @@ bool GParted_Core::maximize_filesystem( const Partition & partition, OperationDe
 
 bool GParted_Core::copy( const Partition & partition_src,
 			 Partition & partition_dst,
-			 Sector min_size,
+			 Byte_Value min_size,
 			 OperationDetail & operationdetail ) 
 {
 	if ( partition_dst .get_length() < partition_src .get_length() )
@@ -2019,7 +2019,10 @@ bool GParted_Core::copy( const Partition & partition_src,
 	{
 		bool succes = true ;
 		if ( partition_dst .status == GParted::STAT_COPY )
-			succes = create_partition( partition_dst, operationdetail, min_size ) ;
+		{
+			/* Handle situation where src sector size is smaller than dst sector size and an additional partial dst sector is required. */
+			succes = create_partition( partition_dst, operationdetail, ( (min_size + (DEFAULT_SECTOR_SIZE - 1)) / DEFAULT_SECTOR_SIZE ) ) ;
+		}
 
 		if ( succes && set_partition_type( partition_dst, operationdetail ) )
 		{
@@ -2054,8 +2057,8 @@ bool GParted_Core::copy( const Partition & partition_src,
 
 			operationdetail .get_last_child() .set_status( succes ? STATUS_SUCCES : STATUS_ERROR ) ;
 
-			return succes &&	
-	       		       update_bootsector( partition_dst, operationdetail ) &&
+			return succes &&
+			       update_bootsector( partition_dst, operationdetail ) &&
 			       check_repair_filesystem( partition_dst, operationdetail ) &&
 			       maximize_filesystem( partition_dst, operationdetail ) ;
 		}
@@ -2086,72 +2089,81 @@ bool GParted_Core::copy_filesystem( const Partition & partition_src,
 				partition_dst .device_path,
 				partition_src .sector_start,
 				partition_dst .sector_start,
-				partition_src .get_length(),
+				partition_src .get_length() * DEFAULT_SECTOR_SIZE,
 				operationdetail,
 				readonly,
 				dummy ) ;
 }
 
 bool GParted_Core::copy_filesystem( const Partition & partition_src,
-			      	    const Partition & partition_dst,
-			      	    OperationDetail & operationdetail,
-			      	    Sector & total_done ) 
+				    const Partition & partition_dst,
+				    OperationDetail & operationdetail,
+				    Byte_Value & total_done ) 
 {
 	return copy_filesystem( partition_src .device_path,
 				partition_dst .device_path,
 				partition_src .sector_start,
 				partition_dst .sector_start,
-				partition_src .get_length(),
+				partition_src .get_length() * DEFAULT_SECTOR_SIZE,
 				operationdetail,
 				false,
 				total_done ) ;
 }
 	
 bool GParted_Core::copy_filesystem( const Glib::ustring & src_device,
-			      	    const Glib::ustring & dst_device,
-			      	    Sector src_start,
-			      	    Sector dst_start,
-			      	    Sector length,
-			      	    OperationDetail & operationdetail,
-			      	    bool readonly,
-				    Sector & total_done ) 
+				    const Glib::ustring & dst_device,
+				    Sector src_start,
+				    Sector dst_start,
+				    Byte_Value src_length,
+				    OperationDetail & operationdetail,
+				    bool readonly,
+				    Byte_Value & total_done ) 
 {
 	operationdetail .add_child( OperationDetail( _("using internal algorithm"), STATUS_NONE ) ) ;
 	operationdetail .add_child( OperationDetail( 
-		String::ucompose( readonly ? _("read %1 sectors") : _("copy %1 sectors"), length ), STATUS_NONE ) ) ;
-
-	operationdetail .add_child( OperationDetail( _("finding optimal blocksize"), STATUS_NONE ) ) ;
-
-	Sector benchmark_blocksize = readonly ? 128 : 64, N = 32768 ;
-	Sector optimal_blocksize = benchmark_blocksize ;
-	Sector offset_read = src_start,
-	       offset_write = dst_start ;
-
+		String::ucompose( readonly ?
+				/*TO TRANSLATORS: looks like  read 1.00 MiB */
+				_("read %1") :
+				/*TO TRANSLATORS: looks like  copy 1.00 MiB */
+				_("copy %1"),
+				Utils::format_size( src_length, 1 ) ),
+				STATUS_NONE ) ) ;
+
+	operationdetail .add_child( OperationDetail( _("finding optimal block size"), STATUS_NONE ) ) ;
+
+	Byte_Value benchmark_blocksize = readonly ? (2 * MEBI_FACTOR) : (1 * MEBI_FACTOR), N = (16 * MEBI_FACTOR) ;
+	Byte_Value optimal_blocksize = benchmark_blocksize ;
+	Sector offset_read = src_start ;
+	Sector offset_write = dst_start ;
+
+	//Handle situation where we need to perform the copy beginning
+	//  with the end of the partition and finishing with the start.
 	if ( dst_start > src_start )
 	{
-		offset_read += (length -N) ;
-		offset_write += (length -N) ;
+		offset_read  += (src_length/DEFAULT_SECTOR_SIZE) - (N/DEFAULT_SECTOR_SIZE) ;
+		/* Handle situation where src sector size is smaller than dst sector size and an additional partial dst sector is required. */
+		offset_write += ((src_length + (DEFAULT_SECTOR_SIZE - 1))/DEFAULT_SECTOR_SIZE) - (N/DEFAULT_SECTOR_SIZE) ;
 	}
 
 	total_done = 0 ;
-	Sector done = 0 ;
+	Byte_Value done = 0 ;
 	Glib::Timer timer ;
 	double smallest_time = 1000000 ;
 	bool succes = true ;
 
 	//Benchmark copy times using different block sizes to determine optimal size
 	while ( succes &&
-		llabs( done ) + N <= length && 
+		llabs( done ) + N <= src_length && 
 		benchmark_blocksize <= N )
 	{
 		timer .reset() ;
 		succes = copy_blocks( src_device, 
-	  		     	      dst_device,
-			     	      offset_read + done, 
-			     	      offset_write + done,
-			     	      N, 
-			     	      benchmark_blocksize,
-			     	      operationdetail .get_last_child(),
+				      dst_device,
+				      offset_read  + (done / DEFAULT_SECTOR_SIZE),
+				      offset_write + (done / DEFAULT_SECTOR_SIZE),
+				      N,
+				      benchmark_blocksize,
+				      operationdetail .get_last_child(),
 				      readonly,
 				      total_done ) ;
 		timer.stop() ;
@@ -2173,31 +2185,38 @@ bool GParted_Core::copy_filesystem( const Glib::ustring & src_device,
 	}
 	
 	if ( succes )
-		operationdetail .get_last_child() .add_child( OperationDetail( String::ucompose( _("optimal blocksize is %1 sectors (%2)"),
-												optimal_blocksize,
-												Utils::format_size( optimal_blocksize, DEFAULT_SECTOR_SIZE ) ),
-												STATUS_NONE ) ) ;
+		operationdetail .get_last_child() .add_child( OperationDetail( String::ucompose( 
+				/*TO TRANSLATORS: looks like  optimal block size is 1.00 MiB */
+				_("optimal block size is %1"),
+				Utils::format_size( optimal_blocksize, 1 ) ),
+				STATUS_NONE ) ) ;
 
-	if ( succes ) 
-	      succes = copy_blocks( src_device, 
-		      	    	    dst_device,
-		      	    	    src_start + ( dst_start > src_start ? 0 : done ),
-		      	    	    dst_start + ( dst_start > src_start ? 0 : done ),
-		      	    	    length - llabs( done ), 
-		      	    	    optimal_blocksize,
-		      	    	    operationdetail,
-			    	    readonly,
-			    	    total_done ) ;
+	if ( succes )
+		succes = copy_blocks( src_device, 
+				    dst_device,
+				    src_start + ( dst_start > src_start ? 0 : (done / DEFAULT_SECTOR_SIZE) ),
+				    dst_start + ( dst_start > src_start ? 0 : (done / DEFAULT_SECTOR_SIZE) ),
+				    src_length - llabs( done ),
+				    optimal_blocksize,
+				    operationdetail,
+				    readonly,
+				    total_done ) ;
 
 	operationdetail .add_child( OperationDetail( 
-		String::ucompose( readonly ? _("%1 sectors read") : _("%1 sectors copied"), total_done ), STATUS_NONE ) ) ;
+		String::ucompose( readonly ?
+				/*TO TRANSLATORS: looks like  1.00 MiB (1048576 B) read */
+				_("%1 (%2 B) read") :
+				/*TO TRANSLATORS: looks like  1.00 MiB (1048576 B) copied */
+				_("%1 (%2 B) copied"),
+				Utils::format_size( total_done, 1 ), total_done ),
+				STATUS_NONE ) ) ;
 	return succes ;
 }
 
 void GParted_Core::rollback_transaction( const Partition & partition_src,
-			      	   	 const Partition & partition_dst,
-			      	   	 OperationDetail & operationdetail,
-			      	   	 Sector total_done ) 
+					 const Partition & partition_dst,
+					 OperationDetail & operationdetail,
+					 Byte_Value total_done )
 {
 	if ( total_done > 0 )
 	{
@@ -2209,22 +2228,22 @@ void GParted_Core::rollback_transaction( const Partition & partition_src,
 
 		if ( partition_dst .sector_start > partition_src .sector_start )
 		{
-			temp_src .sector_start = temp_src .sector_end - (total_done-1) ;
-			temp_dst .sector_start = temp_dst .sector_end - (total_done-1) ;
+			temp_src .sector_start = temp_src .sector_end - ( (total_done / DEFAULT_SECTOR_SIZE) - 1 ) ;
+			temp_dst .sector_start = temp_dst .sector_end - ( (total_done / DEFAULT_SECTOR_SIZE) - 1 ) ;
 		}
 		else
 		{
-			temp_src .sector_end = temp_src .sector_start + (total_done -1) ;
-			temp_dst .sector_end = temp_dst .sector_start + (total_done -1) ;
+			temp_src .sector_end = temp_src .sector_start + ( (total_done / DEFAULT_SECTOR_SIZE) - 1 ) ;
+			temp_dst .sector_end = temp_dst .sector_start + ( (total_done / DEFAULT_SECTOR_SIZE) - 1 ) ;
 		}
-		
+
 		//and copy it back (NOTE the reversed dst and src)
 		bool succes = copy_filesystem( temp_dst, temp_src, operationdetail .get_last_child() ) ;
 
 		operationdetail .get_last_child() .set_status( succes ? STATUS_SUCCES : STATUS_ERROR ) ;
 	}
 }
-	
+
 bool GParted_Core::check_repair_filesystem( const Partition & partition, OperationDetail & operationdetail ) 
 {
 	operationdetail .add_child( OperationDetail( 
@@ -2308,8 +2327,8 @@ bool GParted_Core::set_partition_type( const Partition & partition, OperationDet
 	return return_value ;
 }
 	
-void GParted_Core::set_progress_info( Sector total,
-				      Sector done,
+void GParted_Core::set_progress_info( Byte_Value total,
+				      Byte_Value done,
 				      const Glib::Timer & timer,
 				      OperationDetail & operationdetail,
 				      bool readonly ) 
@@ -2319,43 +2338,60 @@ void GParted_Core::set_progress_info( Sector total,
 	std::time_t time_remaining = Utils::round( (total - done) / ( done / timer .elapsed() ) ) ;
 
 	operationdetail .progress_text = 
-		String::ucompose( readonly ? _("%1 of %2 read (%3 remaining)") : _("%1 of %2 copied (%3 remaining)"),
-				  Utils::format_size( done, DEFAULT_SECTOR_SIZE ),
-				  Utils::format_size( total, DEFAULT_SECTOR_SIZE ),
+		String::ucompose( readonly ?
+				/*TO TRANSLATORS: looks like  1.00 MiB of 16.00 MiB read (00:01:59 remaining) */
+				_("%1 of %2 read (%3 remaining)") :
+				/*TO TRANSLATORS: looks like  1.00 MiB of 16.00 MiB copied (00:01:59 remaining) */
+				_("%1 of %2 copied (%3 remaining)"),
+				  Utils::format_size( done, 1 ),
+				  Utils::format_size( total,1 ),
 				  Utils::format_time( time_remaining) ) ; 
 			
 	operationdetail .set_description( 
-		String::ucompose( readonly ? _("%1 of %2 read") : _("%1 of %2 copied"), done, total ), FONT_ITALIC ) ;
+		String::ucompose( readonly ?
+				/*TO TRANSLATORS: looks like  1.00 MiB of 16.00 MiB read */
+				_("%1 of %2 read") :
+				/*TO TRANSLATORS: looks like  1.00 MiB of 16.00 MiB copied */
+				_("%1 of %2 copied"),
+				Utils::format_size( done, 1 ), Utils::format_size( total, 1 ) ),
+				FONT_ITALIC ) ;
 }
 	
 bool GParted_Core::copy_blocks( const Glib::ustring & src_device,
-			  	const Glib::ustring & dst_device,
-			  	Sector src_start,
-			  	Sector dst_start,
-				Sector length,
-			  	Sector blocksize,
-			  	OperationDetail & operationdetail,
+				const Glib::ustring & dst_device,
+				Sector src_start,
+				Sector dst_start,
+				Byte_Value length,
+				Byte_Value blocksize,
+				OperationDetail & operationdetail,
 				bool readonly,
-				Sector & total_done ) 
+				Byte_Value & total_done ) 
 {
 	if ( blocksize > length )
 		blocksize = length ;
 
 	if ( readonly )
 		operationdetail .add_child( OperationDetail( 
-			String::ucompose( _("read %1 sectors using a blocksize of %2 sectors"), length, blocksize ) ) ) ;
+				/*TO TRANSLATORS: looks like  read 16.00 MiB using a block size of 1.00 MiB */
+				String::ucompose( _("read %1 using a block size of %2"), Utils::format_size( length, 1 ),
+					Utils::format_size( blocksize, 1 ) ) ) ) ;
 	else
 		operationdetail .add_child( OperationDetail( 
-			String::ucompose( _("copy %1 sectors using a blocksize of %2 sectors"), length, blocksize ) ) ) ;
-	
-	Sector done = length % blocksize ; 
+				/*TO TRANSLATORS: looks like  copy 16.00 MiB using a block size of 1.00 MiB */
+				String::ucompose( _("copy %1 using a block size of %2"), Utils::format_size( length, 1 ),
+					Utils::format_size( blocksize, 1 ) ) ) ) ;
+
+	Byte_Value done = length % blocksize ; 
 
+	//Handle situation where we need to perform the copy beginning
+	//  with the end of the partition and finishing with the start.
 	if ( dst_start > src_start )
 	{
 		blocksize -= 2*blocksize ;
 		done -= 2*done ;
-		src_start += (length -1) ;
-		dst_start += (length -1) ;
+		src_start += ( (length / DEFAULT_SECTOR_SIZE) - 1 ) ;
+		/* Handle situation where src sector size is smaller than dst sector size and an additional partial dst sector is required. */
+		dst_start += ( ((length + (DEFAULT_SECTOR_SIZE - 1))/ DEFAULT_SECTOR_SIZE) - 1 ) ;
 	}
 
 	bool succes = false ;
@@ -2365,33 +2401,33 @@ bool GParted_Core::copy_blocks( const Glib::ustring & src_device,
 	if ( lp_device_src && lp_device_dst && ped_device_open( lp_device_src ) && ped_device_open( lp_device_dst ) )
 	{
 		Glib::ustring error_message ;
-		buf = static_cast<char *>( malloc( llabs( blocksize ) * 512 ) ) ;
+		buf = static_cast<char *>( malloc( llabs( blocksize ) ) ) ;
 		if ( buf )
 		{
 			ped_device_sync( lp_device_dst ) ;
 
 			succes = true ;
-        		if ( done != 0 )
-        		    succes = copy_block( lp_device_src,
-				        	 lp_device_dst,
-				        	 src_start,
-				        	 dst_start, 
-				        	 done,
-				        	 error_message,
-						 readonly ) ;
+			if ( done != 0 )
+				succes = copy_block( lp_device_src,
+						lp_device_dst,
+						src_start,
+						dst_start, 
+						done,
+						error_message,
+						readonly ) ;
 			if ( ! succes )
 				done = 0 ;
 
 			//add an empty sub which we will constantly update in the loop
 			operationdetail .get_last_child() .add_child( OperationDetail( "", STATUS_NONE ) ) ;
-			
+
 			Glib::Timer timer_progress_timeout, timer_total ;
 			while( succes && llabs( done ) < length )
 			{
 				succes = copy_block( lp_device_src,
 						     lp_device_dst,
-						     src_start +done,
-						     dst_start +done, 
+						     src_start + (done / DEFAULT_SECTOR_SIZE),
+						     dst_start + (done / DEFAULT_SECTOR_SIZE),
 						     blocksize,
 						     error_message,
 						     readonly ) ; 
@@ -2420,7 +2456,14 @@ bool GParted_Core::copy_blocks( const Glib::ustring & src_device,
 
 		//final description
 		operationdetail .get_last_child() .get_last_child() .set_description( 
-			String::ucompose( readonly ? _("%1 of %2 read") : _("%1 of %2 copied"), llabs( done ), length ), FONT_ITALIC ) ;
+			String::ucompose( readonly ?
+					/*TO TRANSLATORS: looks like  1.00 MiB of 16.00 MiB read */
+					_("%1 of %2 read") :
+					/*TO TRANSLATORS: looks like  1.00 MiB of 16.00 MiB copied */
+					_("%1 of %2 copied"),
+					Utils::format_size( llabs( done ), 1 ),
+					Utils::format_size( length, 1 ) ),
+					FONT_ITALIC ) ;
 		
 		if ( ! succes && ! error_message .empty() )
 			operationdetail .get_last_child() .add_child( 
@@ -2447,23 +2490,34 @@ bool GParted_Core::copy_block( PedDevice * lp_device_src,
 			       PedDevice * lp_device_dst,
 			       Sector offset_src,
 			       Sector offset_dst,
-			       Sector blocksize,
+			       Byte_Value block_length,
 			       Glib::ustring & error_message,
 			       bool readonly ) 
 {
-	if ( blocksize < 0 )
+	Byte_Value sector_size_src = lp_device_src ->sector_size ;
+	Byte_Value sector_size_dst = lp_device_dst ->sector_size ;
+
+	//Handle case where src and dst sector sizes are different.
+	//    E.g.,  5 sectors x 512 bytes/sector = ??? 2048 byte sectors
+	Sector num_blocks_src = (llabs(block_length) + (sector_size_src - 1) ) / sector_size_src ;
+	Sector num_blocks_dst = (llabs(block_length) + (sector_size_dst - 1) ) / sector_size_dst ;
+
+	//Handle situation where we are performing copy operation beginning
+	//  with the end of the partition and finishing with the start.
+	if ( block_length < 0 )
 	{
-		blocksize = llabs( blocksize ) ;
-		offset_src -= ( blocksize -1 ) ;
-		offset_dst -= ( blocksize -1 ) ;
+		block_length = llabs( block_length ) ;
+		offset_src -= ( (block_length / sector_size_src) - 1 ) ;
+		/* Handle situation where src sector size is smaller than dst sector size and an additional partial dst sector is required. */
+		offset_dst -= ( ( (block_length + (sector_size_dst - 1)) / sector_size_dst) - 1 ) ;
 	}
 
-	if ( blocksize != 0 )
+	if ( block_length != 0 )
 	{
-		if ( ped_device_read( lp_device_src, buf, offset_src, blocksize ) )
+		if ( ped_device_read( lp_device_src, buf, offset_src, num_blocks_src ) )
 		{
-			if ( readonly || ped_device_write( lp_device_dst, buf, offset_dst, blocksize ) )
-				return true ;	
+			if ( readonly || ped_device_write( lp_device_dst, buf, offset_dst, num_blocks_dst ) )
+				return true ;
 			else
 				error_message = String::ucompose( _("Error while writing block at sector %1"), offset_dst ) ;
 		}
@@ -2473,7 +2527,7 @@ bool GParted_Core::copy_block( PedDevice * lp_device_src,
 
 	return false ;
 }
-	
+
 bool GParted_Core::calibrate_partition( Partition & partition, OperationDetail & operationdetail ) 
 {
 	if ( partition .type == TYPE_PRIMARY || partition .type == TYPE_LOGICAL || partition .type == TYPE_EXTENDED )



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