Enhancements
authorChristophe Varoqui <christophe.varoqui@opensvc.com>
Tue, 1 Jun 2010 21:46:33 +0000 (23:46 +0200)
committerChristophe Varoqui <christophe.varoqui@opensvc.com>
Tue, 1 Jun 2010 21:46:33 +0000 (23:46 +0200)
o remove trailing whitespaces
o add -C/--showchunks (split -v into -v -C)
o convert all read/write to 'do {} while' loops
o add chunk checksums display to -C
o remove unused vars
o allocate a private buffer for exception chunks

dds.c

diff --git a/dds.c b/dds.c
index e78e5b7..89f123c 100644 (file)
--- a/dds.c
+++ b/dds.c
  *                                                    `- size of exception struct
  */
 
-/* 
- * Magic for persistent snapshots: "SnAp" - Feeble isn't it. 
- */ 
-#define SNAP_MAGIC 0x70416e53 
+/*
+ * Magic for persistent snapshots: "SnAp" - Feeble isn't it.
+ */
+#define SNAP_MAGIC 0x70416e53
 
-/* 
- * The on-disk version of the metadata. 
- */ 
-#define SNAPSHOT_DISK_VERSION 1 
+/*
+ * The on-disk version of the metadata.
+ */
+#define SNAPSHOT_DISK_VERSION 1
 
-struct disk_header { 
+struct disk_header {
        uint32_t magic;
 
-       /* 
-        * Is this snapshot valid. There is no way of recovering 
-        * an invalid snapshot. 
-        */ 
+       /*
+        * Is this snapshot valid. There is no way of recovering
+        * an invalid snapshot.
+        */
        uint32_t valid;
 
-       /* 
-        * Simple, incrementing version. no backward 
-        * compatibility. 
-        */ 
+       /*
+        * Simple, incrementing version. no backward
+        * compatibility.
+        */
        uint32_t version;
 
-       /* In sectors */ 
+       /* In sectors */
        uint32_t chunk_size;
 };
 
-struct disk_exception { 
+struct disk_exception {
        uint64_t old_chunk;
        uint64_t new_chunk;
 };
@@ -93,7 +93,7 @@ struct disk_exception {
 size_t chunk_size_bytes;
 int fdin, fdout, fdcow;
 char * buf;
-int verbose, extract, merge;
+int showchunks, verbose, extract, merge;
 
 static int init_buffer () {
        buf = malloc(MAX_SNAP_CHUNK_SIZE);
@@ -124,11 +124,13 @@ static void print_disk_header (struct disk_header * h) {
 }
 
 static int read_disk_header() {
-       int len;
+       size_t len = 0;
        struct disk_header * h;
 
-       /* minimum aligned read */
-       len = read(fdcow, buf, SECTOR_SIZE);
+       /* read disk header sector */
+        do {
+               len += read(fdcow, buf, SECTOR_SIZE - len);
+        } while (len > 0 && len != SECTOR_SIZE);
        h = (struct disk_header *)buf;
        if (!len && !errno && fdcow == STDIN_FILENO) {
                fprintf(stderr, "stdin is empty\n");
@@ -136,6 +138,7 @@ static int read_disk_header() {
        }
        if (len != SECTOR_SIZE) {
                perror("read cow header");
+                fprintf(stderr, "len = %i\n", len);
                return 1;
        }
        if (h->magic != SNAP_MAGIC) {
@@ -150,7 +153,7 @@ static int read_disk_header() {
                fprintf(stderr, "snapshot is invalid\n");
                return 1;
        }
-       if (h->chunk_size & (h->chunk_size - 1) != 0 ) {
+       if ((h->chunk_size & (h->chunk_size - 1)) != 0 ) {
                fprintf(stderr, "snapshot chunk size is not a power of 2\n");
                return 1;
        }
@@ -159,8 +162,15 @@ static int read_disk_header() {
        if (verbose)
                print_disk_header(h);
 
-       /* consume the rest of the chunk for non-seekable fdcow */
-       len = read(fdcow, buf, chunk_size_bytes - SECTOR_SIZE);
+       /*
+        * consume the rest of the chunk for non-seekable fdcow
+        * now that we know chunk_size_bytes
+        */
+       len = 0;
+       do {
+               len += read(fdcow, buf, chunk_size_bytes - SECTOR_SIZE);
+       } while (len > 0 && len != chunk_size_bytes - SECTOR_SIZE);
+
        if (!len && !errno && fdcow == STDIN_FILENO) {
                fprintf(stderr, "stdin is empty\n");
                return 1;
@@ -183,12 +193,19 @@ int write_disk_header () {
                perror("seek cow to header chunk");
                return 1;
        }
-       len = read(fdcow, buf, chunk_size_bytes);
+        len = 0;
+       do {
+               len += read(fdcow, buf, chunk_size_bytes - len);
+       } while (len > 0 && len != chunk_size_bytes);
        if (len != chunk_size_bytes) {
                perror("read cow header");
+                fprintf(stderr, "len = %i\n", len);
                return 1;
        }
-       len = write(fdout, buf, chunk_size_bytes);
+        len = 0;
+       do {
+               len += write(fdout, buf, chunk_size_bytes - len);
+       } while (len > 0 && len != chunk_size_bytes);
        if (len != chunk_size_bytes) {
                perror("write cow header");
                return 1;
@@ -203,18 +220,27 @@ static int write_exception (struct disk_exception * e) {
                perror("seek source to data chunk");
                return 1;
        }
-       len = read(fdin, buf, chunk_size_bytes);
+        len = 0;
+       do {
+               len += read(fdin, buf, chunk_size_bytes - len);
+       } while (len > 0 && len != chunk_size_bytes);
        if (len != chunk_size_bytes) {
-               perror("read cow header");
+               perror("read chunk from source");
+                fprintf(stderr, "len = %i\n", len);
                return 1;
        }
-       len = write(fdout, buf, chunk_size_bytes);
+        len = 0;
+       do {
+               len += write(fdout, buf, chunk_size_bytes - len);
+       } while (len > 0 && len != chunk_size_bytes);
        if (len != chunk_size_bytes) {
-               perror("write cow header");
+               perror("write chunk to extract dest");
                return 1;
        }
-       if (verbose)
-               printf("  %-16llu  %-16llu\n", e->old_chunk, e->new_chunk);
+       if (showchunks)
+               printf("  %-16llu  %-16llu %-32llu\n",
+                       e->old_chunk, e->new_chunk,
+                       checksum(buf, chunk_size_bytes));
        return 0;
 }
 
@@ -234,7 +260,10 @@ static int seek_to_exception_table (const int n) {
 static int load_exception (struct disk_exception * e) {
        size_t len;
 
-       len = read(fdcow, buf, chunk_size_bytes);
+       len = 0;
+       do {
+               len += read(fdcow, buf, chunk_size_bytes - len);
+       } while (len > 0 && len != chunk_size_bytes);
        if (len != chunk_size_bytes) {
                perror("read cow data chunk to load");
                return 1;
@@ -243,13 +272,18 @@ static int load_exception (struct disk_exception * e) {
                perror("seek dest to load data chunk");
                return 1;
        }
-       len = write(fdout, buf, chunk_size_bytes);
+       len = 0;
+       do {
+               len += write(fdout, buf, chunk_size_bytes - len);
+       } while (len > 0 && len != chunk_size_bytes);
        if (len != chunk_size_bytes) {
                perror("write cow exceptions");
                return 1;
        }
-       if (verbose)
-               printf("  %-16llu  %-16llu\n", e->old_chunk, e->new_chunk);
+       if (showchunks)
+               printf("  %-16llu  %-16llu %-32llu\n",
+                       e->old_chunk, e->new_chunk,
+                       checksum(buf, chunk_size_bytes));
        return 0;
 }
 
@@ -268,16 +302,17 @@ static void report (uint64_t exception_chunk_count, uint64_t exception_count) {
 }
 
 int load_exceptions () {
-       struct disk_exception * e, * pe;
-       int i, len;
+       struct disk_exception * e;
+       int i;
        int err = 0;
        uint64_t exception_chunk_count = 0;
-       uint64_t n, exception_count = 0;
+       uint64_t exception_count = 0;
        char * exception_chunk_buf;
+       size_t len;
 
-       if (verbose) {
+       if (showchunks) {
                printf("Exception table:\n");
-               printf("  chunk number      chunk number\n");
+               printf("  chunk number      chunk number      checksum\n");
                printf("  on source         on dest\n");
        }
 
@@ -291,16 +326,17 @@ int load_exceptions () {
                exception_chunk_count++;
 
                /* read it all */
-               len = read(fdcow, buf, chunk_size_bytes);
+               len = 0;
+               do {
+                       len += read(fdcow, exception_chunk_buf, chunk_size_bytes - len);
+               } while (len > 0 && len != chunk_size_bytes);
+
                if (len != chunk_size_bytes) {
                        perror("read cow exceptions");
                        err = 1;
                        goto out;
                }
 
-               /* buf will be used for other reads, use a copy */
-               memcpy(exception_chunk_buf, buf, chunk_size_bytes);
-
                for (i=0; i<len ; i+=sizeof(struct disk_exception)) {
                        e = (struct disk_exception *)&exception_chunk_buf[i];
 
@@ -318,16 +354,17 @@ out:
 }
 
 int write_exceptions () {
-       struct disk_exception * e, * pe;
-       int i, len;
+       struct disk_exception * e;
+       int i;
        int err = 0;
        uint64_t exception_chunk_count = 0;
        uint64_t n, exception_count = 0;
        char * exception_chunk_buf;
+       size_t len;
 
-       if (verbose) {
+       if (showchunks) {
                printf("Exception table:\n");
-               printf("  chunk number      chunk number\n");
+               printf("  chunk number      chunk number      checksum\n");
                printf("  on source         on dest\n");
        }
 
@@ -343,7 +380,10 @@ int write_exceptions () {
                        return 1;
 
                /* read it all */
-               len = read(fdcow, buf, chunk_size_bytes);
+               len = 0;
+               do {
+                       len += read(fdcow, exception_chunk_buf, chunk_size_bytes - len);
+               } while (len > 0 && len != chunk_size_bytes);
                if (len != chunk_size_bytes) {
                        perror("read cow exceptions");
                        err = 1;
@@ -353,7 +393,7 @@ int write_exceptions () {
                /* serialize the exception new chunk number. start at 2 */
                n = exception_count;
                for (i=0; i<len ; i+=sizeof(struct disk_exception)) {
-                       e = (struct disk_exception *)&buf[i];
+                       e = (struct disk_exception *)&exception_chunk_buf[i];
 
                        /* detect end-of-exceptions */
                        if (e->new_chunk == 0)
@@ -364,15 +404,15 @@ int write_exceptions () {
                }
 
                /* write it to dest */
-               len = write(fdout, buf, chunk_size_bytes);
+               len = 0;
+               do {
+                       len += write(fdout, exception_chunk_buf, chunk_size_bytes - len);
+               } while (len > 0 && len != chunk_size_bytes);
                if (len != chunk_size_bytes) {
                        perror("write cow exceptions");
                        return 1;
                }
 
-               /* buf will be used for other reads, use a copy */
-               memcpy(exception_chunk_buf, buf, chunk_size_bytes);
-
                for (i=0; i<len ; i+=sizeof(struct disk_exception)) {
                        e = (struct disk_exception *)&exception_chunk_buf[i];
 
@@ -423,6 +463,7 @@ void usage (char * prog) {
        printf(" -d, --dest       file to copy the data to (default stdout)\n");
        printf(" -h, --help       this message\n");
        printf(" -v, --verbose    display more information\n");
+       printf(" -C, --showchunks display chunk remappings\n");
        return;
 }
 
@@ -481,6 +522,7 @@ int main (int argc, char * const * argv) {
        char * cow = NULL;
 
        verbose = 0;
+       showchunks = 0;
        extract = 0;
        merge = 0;
 
@@ -494,9 +536,10 @@ int main (int argc, char * const * argv) {
                        {"help", 0, 0, 'h'},
                        {"source", 1, 0, 's'},
                        {"verbose", 0, 0, 'v'},
+                       {"showchunks", 0, 0, 'C'},
                        {0, 0, 0, 0},
                };
-               c = getopt_long(argc, argv, "c:d:hms:vx",
+               c = getopt_long(argc, argv, "c:Cd:hms:vx",
                                long_options, &option_index);
                if (c == -1)
                        break;
@@ -505,6 +548,9 @@ int main (int argc, char * const * argv) {
                case 'c':
                        cow = strdup(optarg);
                        break;
+               case 'C':
+                       showchunks = 1;
+                       break;
                case 'd':
                        dest = strdup(optarg);
                        break;
@@ -533,8 +579,8 @@ int main (int argc, char * const * argv) {
        /*
         * sanity checks
         */
-       if (extract && verbose && !dest) {
-               fprintf(stderr, "extract verbose mode needs --dest "
+       if (extract && (verbose || showchunks) && !dest) {
+               fprintf(stderr, "extract verbose and showchunks modes needs --dest "
                                "(stdout usage conflict)\n");
                return 1;
        }
@@ -600,7 +646,7 @@ int main (int argc, char * const * argv) {
 
        if (merge && do_merge())
                return 1;
-               
+
        return 0;
 }