OSDN Git Service

e2image: only skip writing zero blocks when writing to a new file
authorTheodore Ts'o <tytso@mit.edu>
Wed, 25 Dec 2013 21:33:52 +0000 (16:33 -0500)
committerTheodore Ts'o <tytso@mit.edu>
Thu, 26 Dec 2013 05:21:08 +0000 (00:21 -0500)
The e2image progam was originally intended to create image files.
However, some people have started using e2image to copy a file system
from one block device to another, since it is more efficient than
using dd because it only copies the blocks which are in use.  If we
are doing this, however, we must not skip writing blocks which are all
zero in the source device, since they may not be zero in the
destination device.

Signed-off-by: "Theodore Ts'o" <tytso@mit.edu>
Cc: Phillip Susi <psusi@ubuntu.com>
lib/ext2fs/e2image.h
misc/e2image.c

index 5537980..53b20cc 100644 (file)
  * %End-Header%
  */
 
-/* Image types */
-#define E2IMAGE_RAW    1
-#define E2IMAGE_QCOW2  2
-
-/* Image flags */
-#define E2IMAGE_INSTALL_FLAG   1
-#define E2IMAGE_SCRAMBLE_FLAG  2
-#define E2IMAGE_IS_QCOW2_FLAG  4
-
 struct ext2_image_hdr {
        __u32   magic_number;   /* This must be EXT2_ET_MAGIC_E2IMAGE */
        char    magic_descriptor[16]; /* "Ext2 Image 1.0", w/ null padding */
index 4d9868c..67dd3e0 100644 (file)
@@ -50,6 +50,15 @@ extern int optind;
 
 #define QCOW_OFLAG_COPIED     (1LL << 63)
 
+/* Image types */
+#define E2IMAGE_RAW    1
+#define E2IMAGE_QCOW2  2
+
+/* Image flags */
+#define E2IMAGE_INSTALL_FLAG   1
+#define E2IMAGE_SCRAMBLE_FLAG  2
+#define E2IMAGE_IS_QCOW2_FLAG  4
+#define E2IMAGE_CHECK_ZERO_FLAG        8
 
 static const char * program_name = "e2image";
 static char * device_name = NULL;
@@ -495,7 +504,7 @@ static void sigint_handler(int unused EXT2FS_ATTR((unused)))
        signal (SIGINT, SIG_DFL);
 }
 
-static void output_meta_data_blocks(ext2_filsys fs, int fd)
+static void output_meta_data_blocks(ext2_filsys fs, int fd, int flags)
 {
        errcode_t       retval;
        blk64_t         blk;
@@ -607,7 +616,8 @@ more_blocks:
                        if (scramble_block_map &&
                            ext2fs_test_block_bitmap2(scramble_block_map, blk))
                                scramble_dir_block(fs, blk, buf);
-                       if ((fd != 1) && check_zero_block(buf, fs->blocksize))
+                       if ((flags & E2IMAGE_CHECK_ZERO_FLAG) &&
+                           check_zero_block(buf, fs->blocksize))
                                goto sparse_write;
                        if (sparse)
                                seek_relative(fd, sparse);
@@ -1291,7 +1301,7 @@ static void write_raw_image_file(ext2_filsys fs, int fd, int type, int flags)
        if (type & E2IMAGE_QCOW2)
                output_qcow2_meta_data_blocks(fs, fd);
        else
-               output_meta_data_blocks(fs, fd);
+               output_meta_data_blocks(fs, fd, flags);
 
        ext2fs_free_mem(&block_buf);
        ext2fs_close_inode_scan(scan);
@@ -1516,6 +1526,8 @@ skip_device:
 
                if (img_type != E2IMAGE_RAW)
                        o_flags |= O_TRUNC;
+               if (access(image_fn, F_OK) != 0)
+                       flags |= E2IMAGE_CHECK_ZERO_FLAG;
                fd = ext2fs_open_file(image_fn, o_flags, 0600);
                if (fd < 0) {
                        com_err(program_name, errno,