X-Git-Url: http://git.ipfire.org/?a=blobdiff_plain;f=restripe.c;h=30849b7680436df147cc5fa3a6d9e6ecc2fd45d0;hb=7c25f4d706ac14165fd8d85b169f491f1f14b7cc;hp=906788c4c94699e6e44594b4f9b07f534770d7ac;hpb=6f38d7ae107de0615232a64a1b16a470fa1f8a4b;p=thirdparty%2Fmdadm.git diff --git a/restripe.c b/restripe.c index 906788c4..30849b76 100644 --- a/restripe.c +++ b/restripe.c @@ -83,7 +83,6 @@ int geo_map(int block, unsigned long long stripe, int raid_disks, case 500 + ALGORITHM_PARITY_0: return block + 1; - case 600 + ALGORITHM_PARITY_N_6: if (block == -2) return raid_disks - 1; @@ -131,7 +130,6 @@ int geo_map(int block, unsigned long long stripe, int raid_disks, return raid_disks - 1; return block + 1; - case 600 + ALGORITHM_PARITY_0: if (block == -1) return 0; @@ -173,7 +171,6 @@ int geo_map(int block, unsigned long long stripe, int raid_disks, if (block == -2) return (pd+1) % raid_disks; return (pd + 2 + block) % raid_disks; - case 600 + ALGORITHM_ROTATING_N_RESTART: /* Same a left_asymmetric, by first stripe is * D D D P Q rather than @@ -210,8 +207,7 @@ static int is_ddf(int layout) } } - -static void xor_blocks(char *target, char **sources, int disks, int size) +void xor_blocks(char *target, char **sources, int disks, int size) { int i, j; /* Amazingly inefficient... */ @@ -243,7 +239,6 @@ void qsyndrome(uint8_t *p, uint8_t *q, uint8_t **sources, int disks, int size) } } - /* * The following was taken from linux/drivers/md/mktables.c, and modified * to create in-memory tables rather than C code @@ -334,6 +329,18 @@ void make_tables(void) } uint8_t *zero; +int zero_size; + +void ensure_zero_has_size(int chunk_size) +{ + if (zero == NULL || chunk_size > zero_size) { + if (zero) + free(zero); + zero = xcalloc(1, chunk_size); + zero_size = chunk_size; + } +} + /* Following was taken from linux/drivers/md/raid6recov.c */ /* Recover two failed data blocks. */ @@ -424,11 +431,9 @@ int raid6_check_disks(int data_disks, int start, int chunk_size, if((Px != 0) && (Qx == 0)) curr_broken_disk = diskP; - if((Px == 0) && (Qx != 0)) curr_broken_disk = diskQ; - if((Px != 0) && (Qx != 0)) { data_id = (raid6_gflog[Qx] - raid6_gflog[Px]); if(data_id < 0) data_id += 255; @@ -466,16 +471,35 @@ int raid6_check_disks(int data_disks, int start, int chunk_size, return curr_broken_disk; } -/* Save data: - * We are given: - * A list of 'fds' of the active disks. Some may be absent. - * A geometry: raid_disks, chunk_size, level, layout - * A list of 'fds' for mirrored targets. They are already seeked to - * right (Write) location - * A start and length which must be stripe-aligned - * 'buf' is large enough to hold one stripe, and is aligned - */ - +/******************************************************************************* + * Function: save_stripes + * Description: + * Function reads data (only data without P and Q) from array and writes + * it to buf and opcjonaly to backup files + * Parameters: + * source : A list of 'fds' of the active disks. + * Some may be absent + * offsets : A list of offsets on disk belonging + * to the array [bytes] + * raid_disks : geometry: number of disks in the array + * chunk_size : geometry: chunk size [bytes] + * level : geometry: RAID level + * layout : geometry: layout + * nwrites : number of backup files + * dest : A list of 'fds' for mirrored targets + * (e.g. backup files). They are already seeked to right + * (write) location. If NULL, data will be wrote + * to the buf only + * start : start address of data to read (must be stripe-aligned) + * [bytes] + * length - : length of data to read (must be stripe-aligned) + * [bytes] + * buf : buffer for data. It is large enough to hold + * one stripe. It is stripe aligned + * Returns: + * 0 : success + * -1 : fail + ******************************************************************************/ int save_stripes(int *source, unsigned long long *offsets, int raid_disks, int chunk_size, int level, int layout, int nwrites, int *dest, @@ -486,16 +510,25 @@ int save_stripes(int *source, unsigned long long *offsets, int data_disks = raid_disks - (level == 0 ? 0 : level <=5 ? 1 : 2); int disk; int i; + unsigned long long length_test; if (!tables_ready) make_tables(); + ensure_zero_has_size(chunk_size); - if (zero == NULL) { - zero = malloc(chunk_size); - memset(zero, 0, chunk_size); + len = data_disks * chunk_size; + length_test = length / len; + length_test *= len; + + if (length != length_test) { + dprintf("Error: save_stripes(): Data are not alligned. EXIT\n"); + dprintf("\tArea for saving stripes (length) = %llu\n", length); + dprintf("\tWork step (len) = %i\n", len); + dprintf("\tExpected save area (length_test) = %llu\n", + length_test); + abort(); } - len = data_disks * chunk_size; while (length > 0) { int failed = 0; int fdisk[3], fblock[3]; @@ -615,11 +648,14 @@ int save_stripes(int *source, unsigned long long *offsets, fdisk[0], fdisk[1], bufs); } } - - for (i=0; i zero_size) { if (zero) - memset(zero, 0, chunk_size); + free(zero); + zero = xcalloc(1, chunk_size); + zero_size = chunk_size; } + 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 0) { unsigned int len = data_disks * chunk_size; unsigned long long offset; int disk, qdisk; int syndrome_disks; - if (length < len) - return -3; - for (i=0; i < data_disks; i++) { + 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 ((unsigned long long)lseek64(source, read_offset, 0) - != read_offset) - return -1; - if (read(source, stripes[disk], - chunk_size) != chunk_size) - return -1; + if (src_buf == NULL) { + /* read from file */ + if (lseek64(source, read_offset, 0) != + (off64_t)read_offset) { + rv = -1; + goto abort; + } + if (read(source, + stripes[disk], + chunk_size) != chunk_size) { + rv = -1; + goto abort; + } + } else { + /* read from input buffer */ + memcpy(stripes[disk], + src_buf + read_offset, + chunk_size); + } read_offset += chunk_size; } /* We have the data, now do the parity */ @@ -720,22 +773,34 @@ int restore_stripes(int *dest, unsigned long long *offsets, syndrome_disks = data_disks; } qsyndrome((uint8_t*)stripes[disk], - (uint8_t*)stripes[qdisk], + (uint8_t*)stripes[qdisk], (uint8_t**)blocks, syndrome_disks, chunk_size); break; } 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 @@ -745,11 +810,11 @@ int test_stripes(int *source, unsigned long long *offsets, unsigned long long start, unsigned long long length) { /* ready the data and p (and q) blocks, and check we got them right */ - char *stripe_buf = malloc(raid_disks * chunk_size); - char **stripes = malloc(raid_disks * sizeof(char*)); - char **blocks = malloc(raid_disks * sizeof(char*)); - char *p = malloc(chunk_size); - char *q = malloc(chunk_size); + char *stripe_buf = xmalloc(raid_disks * chunk_size); + char **stripes = xmalloc(raid_disks * sizeof(char*)); + char **blocks = xmalloc(raid_disks * sizeof(char*)); + char *p = xmalloc(chunk_size); + char *q = xmalloc(chunk_size); int i; int diskP, diskQ; @@ -817,6 +882,7 @@ unsigned long long getnum(char *str, char **err) return rv; } +char const Name[] = "test_restripe"; main(int argc, char *argv[]) { /* save/restore file raid_disks chunk_size level layout start length devices... @@ -833,8 +899,7 @@ main(int argc, char *argv[]) char *err = NULL; if (argc < 10) { - fprintf(stderr, "Usage: test_stripe save/restore file raid_disks" - " chunk_size level layout start length devices...\n"); + fprintf(stderr, "Usage: test_stripe save/restore file raid_disks chunk_size level layout start length devices...\n"); exit(1); } if (strcmp(argv[1], "save")==0) @@ -864,9 +929,8 @@ main(int argc, char *argv[]) raid_disks, argc-9); exit(2); } - fds = malloc(raid_disks * sizeof(*fds)); - offsets = malloc(raid_disks * sizeof(*offsets)); - memset(offsets, 0, raid_disks * sizeof(*offsets)); + fds = xmalloc(raid_disks * sizeof(*fds)); + offsets = xcalloc(raid_disks, sizeof(*offsets)); storefd = open(file, O_RDWR); if (storefd < 0) { @@ -882,7 +946,7 @@ main(int argc, char *argv[]) *p++ = '\0'; offsets[i] = atoll(p) * 512; } - + fds[i] = open(argv[9+i], O_RDWR); if (fds[i] < 0) { perror(argv[9+i]); @@ -891,7 +955,7 @@ main(int argc, char *argv[]) } } - buf = malloc(raid_disks * chunk_size); + buf = xmalloc(raid_disks * chunk_size); if (save == 1) { int rv = save_stripes(fds, offsets, @@ -916,7 +980,7 @@ main(int argc, char *argv[]) int rv = restore_stripes(fds, offsets, raid_disks, chunk_size, level, layout, storefd, 0ULL, - start, length); + start, length, NULL); if (rv != 0) { fprintf(stderr, "test_stripe: restore_stripes returned %d\n",