]> git.ipfire.org Git - thirdparty/mdadm.git/blobdiff - restripe.c
FIX: Detect error and rollback metadata
[thirdparty/mdadm.git] / restripe.c
index 9c83e2ebbedf0bc1774dd97ea2876873ca0b9258..00e7a822ffb9d2babf6e485991bd4491486a8246 100644 (file)
@@ -687,6 +687,7 @@ int restore_stripes(int *dest, unsigned long long *offsets,
        char **stripes = malloc(raid_disks * sizeof(char*));
        char **blocks = malloc(raid_disks * sizeof(char*));
        int i;
+       int rv;
 
        int data_disks = raid_disks - (level == 0 ? 0 : level <= 5 ? 1 : 2);
 
@@ -704,11 +705,8 @@ int restore_stripes(int *dest, unsigned long long *offsets,
 
        if (stripe_buf == NULL || stripes == NULL || blocks == NULL
            || zero == NULL) {
-               free(stripe_buf);
-               free(stripes);
-               free(blocks);
-               free(zero);
-               return -2;
+               rv = -2;
+               goto abort;
        }
        for (i = 0; i < raid_disks; i++)
                stripes[i] = stripe_buf + i * chunk_size;
@@ -717,20 +715,26 @@ int restore_stripes(int *dest, unsigned long long *offsets,
                unsigned long long offset;
                int disk, qdisk;
                int syndrome_disks;
-               if (length < len)
-                       return -3;
+               if (length < len) {
+                       rv = -3;
+                       goto abort;
+               }
                for (i = 0; i < data_disks; i++) {
                        int disk = geo_map(i, start/chunk_size/data_disks,
                                           raid_disks, level, layout);
                        if (src_buf == NULL) {
                                /* read from file */
-                               if (lseek64(source,
-                                       read_offset, 0) != (off64_t)read_offset)
-                                       return -1;
+                               if (lseek64(source, read_offset, 0) !=
+                                        (off64_t)read_offset) {
+                                       rv = -1;
+                                       goto abort;
+                               }
                                if (read(source,
                                         stripes[disk],
-                                        chunk_size) != chunk_size)
-                                       return -1;
+                                        chunk_size) != chunk_size) {
+                                       rv = -1;
+                                       goto abort;
+                               }
                        } else {
                                /* read from input buffer */
                                memcpy(stripes[disk],
@@ -782,15 +786,27 @@ int restore_stripes(int *dest, unsigned long long *offsets,
                }
                for (i=0; i < raid_disks ; i++)
                        if (dest[i] >= 0) {
-                               if (lseek64(dest[i], offsets[i]+offset, 0) < 0)
-                                       return -1;
-                               if (write(dest[i], stripes[i], chunk_size) != chunk_size)
-                                       return -1;
+                               if (lseek64(dest[i],
+                                        offsets[i]+offset, 0) < 0) {
+                                       rv = -1;
+                                       goto abort;
+                               }
+                               if (write(dest[i], stripes[i],
+                                        chunk_size) != chunk_size) {
+                                       rv = -1;
+                                       goto abort;
+                               }
                        }
                length -= len;
                start += len;
        }
-       return 0;
+       rv = 0;
+
+abort:
+       free(stripe_buf);
+       free(stripes);
+       free(blocks);
+       return rv;
 }
 
 #ifdef MAIN