X-Git-Url: http://git.ipfire.org/?a=blobdiff_plain;f=raid6check.c;h=e9a17a7caa037bb60a53594bb3a7aee81bd9cc7e;hb=13f2dd6be5618ff556f9a364903e4b95558115e1;hp=aba8160f6e5c51058bc6a4248d223da5e5ae92a2;hpb=f2e29ad6910041161309ffe9d0d2462b942a7b9f;p=thirdparty%2Fmdadm.git diff --git a/raid6check.c b/raid6check.c index aba8160f..e9a17a7c 100644 --- a/raid6check.c +++ b/raid6check.c @@ -107,6 +107,38 @@ int raid6_stats(int *results, int raid_disks, int chunk_size) return curr_broken_disk; } +int lock_stripe(struct mdinfo *info, unsigned long long start, + int chunk_size, int data_disks, sighandler_t *sig) { + int rv; + if(mlockall(MCL_CURRENT | MCL_FUTURE) != 0) { + return 2; + } + + sig[0] = signal(SIGTERM, SIG_IGN); + sig[1] = signal(SIGINT, SIG_IGN); + sig[2] = signal(SIGQUIT, SIG_IGN); + + rv = sysfs_set_num(info, NULL, "suspend_lo", start * chunk_size * data_disks); + rv |= sysfs_set_num(info, NULL, "suspend_hi", (start + 1) * chunk_size * data_disks); + return rv * 256; +} + +int unlock_all_stripes(struct mdinfo *info, sighandler_t *sig) { + int rv; + rv = sysfs_set_num(info, NULL, "suspend_lo", 0x7FFFFFFFFFFFFFFFULL); + rv |= sysfs_set_num(info, NULL, "suspend_hi", 0); + rv |= sysfs_set_num(info, NULL, "suspend_lo", 0); + + signal(SIGQUIT, sig[2]); + signal(SIGINT, sig[1]); + signal(SIGTERM, sig[0]); + + if(munlockall() != 0) + return 3; + return rv * 256; +} + + int check_stripes(struct mdinfo *info, int *source, unsigned long long *offsets, int raid_disks, int chunk_size, int level, int layout, unsigned long long start, unsigned long long length, char *name[], @@ -116,16 +148,16 @@ int check_stripes(struct mdinfo *info, int *source, unsigned long long *offsets, char *stripe_buf = xmalloc(raid_disks * chunk_size); char **stripes = xmalloc(raid_disks * sizeof(char*)); char **blocks = xmalloc(raid_disks * sizeof(char*)); + int *block_index_for_slot = xmalloc(raid_disks * sizeof(int)); uint8_t *p = xmalloc(chunk_size); uint8_t *q = xmalloc(chunk_size); int *results = xmalloc(chunk_size * sizeof(int)); + sighandler_t *sig = xmalloc(3 * sizeof(sighandler_t)); int i; int diskP, diskQ; int data_disks = raid_disks - 2; int err = 0; - sighandler_t sig[3]; - int rv; extern int tables_ready; @@ -140,38 +172,24 @@ int check_stripes(struct mdinfo *info, int *source, unsigned long long *offsets, printf("pos --> %llu\n", start); - if(mlockall(MCL_CURRENT | MCL_FUTURE) != 0) { - err = 2; + err = lock_stripe(info, start, chunk_size, data_disks, sig); + if(err != 0) { + if (err != 2) + unlock_all_stripes(info, sig); goto exitCheck; } - sig[0] = signal(SIGTERM, SIG_IGN); - sig[1] = signal(SIGINT, SIG_IGN); - sig[2] = signal(SIGQUIT, SIG_IGN); - rv = sysfs_set_num(info, NULL, "suspend_lo", start * chunk_size * data_disks); - rv |= sysfs_set_num(info, NULL, "suspend_hi", (start + 1) * chunk_size * data_disks); for (i = 0 ; i < raid_disks ; i++) { lseek64(source[i], offsets[i] + start * chunk_size, 0); read(source[i], stripes[i], chunk_size); } - rv |= sysfs_set_num(info, NULL, "suspend_lo", 0x7FFFFFFFFFFFFFFFULL); - rv |= sysfs_set_num(info, NULL, "suspend_hi", 0); - rv |= sysfs_set_num(info, NULL, "suspend_lo", 0); - signal(SIGQUIT, sig[2]); - signal(SIGINT, sig[1]); - signal(SIGTERM, sig[0]); - if(munlockall() != 0) { - err = 3; - goto exitCheck; - } - - if(rv != 0) { - err = rv * 256; + err = unlock_all_stripes(info, sig); + if(err != 0) goto exitCheck; - } for (i = 0 ; i < data_disks ; i++) { int disk = geo_map(i, start, raid_disks, level, layout); blocks[i] = stripes[disk]; + block_index_for_slot[disk] = i; printf("%d->%d\n", i, disk); } @@ -179,7 +197,9 @@ int check_stripes(struct mdinfo *info, int *source, unsigned long long *offsets, diskP = geo_map(-1, start, raid_disks, level, layout); diskQ = geo_map(-2, start, raid_disks, level, layout); blocks[data_disks] = stripes[diskP]; + block_index_for_slot[diskP] = data_disks; blocks[data_disks+1] = stripes[diskQ]; + block_index_for_slot[diskQ] = data_disks+1; if (memcmp(p, stripes[diskP], chunk_size) != 0) { printf("P(%d) wrong at %llu\n", diskP, start); @@ -208,23 +228,21 @@ int check_stripes(struct mdinfo *info, int *source, unsigned long long *offsets, if (failed_disk1 == diskQ || failed_disk2 == diskQ) { char *all_but_failed_blocks[data_disks]; - int failed_data; + int failed_data_or_p; int failed_block_index; if (failed_disk1 == diskQ) - failed_data = failed_disk2; + failed_data_or_p = failed_disk2; else - failed_data = failed_disk1; - printf("Repairing D/P(%d) and Q\n", failed_data); - failed_block_index = geo_map( - failed_data, start, raid_disks, - level, layout); + failed_data_or_p = failed_disk1; + printf("Repairing D/P(%d) and Q\n", failed_data_or_p); + failed_block_index = block_index_for_slot[failed_data_or_p]; for (i=0; i < data_disks; i++) if (failed_block_index == i) all_but_failed_blocks[i] = stripes[diskP]; else all_but_failed_blocks[i] = blocks[i]; - xor_blocks(stripes[failed_data], + xor_blocks(stripes[failed_data_or_p], all_but_failed_blocks, data_disks, chunk_size); qsyndrome(p, (uint8_t*)stripes[diskQ], (uint8_t**)blocks, data_disks, chunk_size); } else { @@ -235,13 +253,13 @@ int check_stripes(struct mdinfo *info, int *source, unsigned long long *offsets, failed_data = failed_disk2; else failed_data = failed_disk1; - failed_block_index = geo_map(failed_data, start, raid_disks, level, layout); + failed_block_index = block_index_for_slot[failed_data]; printf("Repairing D(%d) and P\n", failed_data); raid6_datap_recov(raid_disks, chunk_size, failed_block_index, (uint8_t**)blocks); } else { printf("Repairing D and D\n"); - int failed_block_index1 = geo_map(failed_disk1, start, raid_disks, level, layout); - int failed_block_index2 = geo_map(failed_disk2, start, raid_disks, level, layout); + int failed_block_index1 = block_index_for_slot[failed_disk1]; + int failed_block_index2 = block_index_for_slot[failed_disk2]; if (failed_block_index1 > failed_block_index2) { int t = failed_block_index1; failed_block_index1 = failed_block_index2; @@ -250,34 +268,51 @@ int check_stripes(struct mdinfo *info, int *source, unsigned long long *offsets, raid6_2data_recov(raid_disks, chunk_size, failed_block_index1, failed_block_index2, (uint8_t**)blocks); } } - if(mlockall(MCL_CURRENT | MCL_FUTURE) != 0) { - err = 2; + + err = lock_stripe(info, start, chunk_size, data_disks, sig); + if(err != 0) { + if (err != 2) + unlock_all_stripes(info, sig); goto exitCheck; } - sig[0] = signal(SIGTERM, SIG_IGN); - sig[1] = signal(SIGINT, SIG_IGN); - sig[2] = signal(SIGQUIT, SIG_IGN); - rv = sysfs_set_num(info, NULL, "suspend_lo", start * chunk_size * data_disks); - rv |= sysfs_set_num(info, NULL, "suspend_hi", (start + 1) * chunk_size * data_disks); + lseek64(source[failed_disk1], offsets[failed_disk1] + start * chunk_size, 0); write(source[failed_disk1], stripes[failed_disk1], chunk_size); lseek64(source[failed_disk2], offsets[failed_disk2] + start * chunk_size, 0); write(source[failed_disk2], stripes[failed_disk2], chunk_size); - rv |= sysfs_set_num(info, NULL, "suspend_lo", 0x7FFFFFFFFFFFFFFFULL); - rv |= sysfs_set_num(info, NULL, "suspend_hi", 0); - rv |= sysfs_set_num(info, NULL, "suspend_lo", 0); - signal(SIGQUIT, sig[2]); - signal(SIGINT, sig[1]); - signal(SIGTERM, sig[0]); - if(munlockall() != 0) { - err = 3; + + err = unlock_all_stripes(info, sig); + if(err != 0) goto exitCheck; + } else if (disk >= 0 && repair == 2) { + printf("Auto-repairing slot %d (%s)\n", disk, name[disk]); + if (disk == diskQ) { + qsyndrome(p, (uint8_t*)stripes[diskQ], (uint8_t**)blocks, data_disks, chunk_size); + } else { + char *all_but_failed_blocks[data_disks]; + int failed_block_index = block_index_for_slot[disk]; + for (i=0; i < data_disks; i++) + if (failed_block_index == i) + all_but_failed_blocks[i] = stripes[diskP]; + else + all_but_failed_blocks[i] = blocks[i]; + xor_blocks(stripes[disk], + all_but_failed_blocks, data_disks, chunk_size); } - if(rv != 0) { - err = rv * 256; + err = lock_stripe(info, start, chunk_size, data_disks, sig); + if(err != 0) { + if (err != 2) + unlock_all_stripes(info, sig); goto exitCheck; } + + lseek64(source[disk], offsets[disk] + start * chunk_size, 0); + write(source[disk], stripes[disk], chunk_size); + + err = unlock_all_stripes(info, sig); + if(err != 0) + goto exitCheck; } @@ -337,7 +372,7 @@ int main(int argc, char *argv[]) prg++; if (argc < 4) { - fprintf(stderr, "Usage: %s md_device start_stripe length_stripes\n", prg); + fprintf(stderr, "Usage: %s md_device start_stripe length_stripes [autorepair]\n", prg); fprintf(stderr, " or: %s md_device repair stripe failed_slot_1 failed_slot_2\n", prg); exit_err = 1; goto exitHere; @@ -416,12 +451,12 @@ int main(int argc, char *argv[]) failed_disk1 = getnum(argv[4], &err); failed_disk2 = getnum(argv[5], &err); - if(failed_disk1 > info->array.raid_disks) { + if(failed_disk1 >= info->array.raid_disks) { fprintf(stderr, "%s: failed_slot_1 index is higher than number of devices in raid\n", prg); exit_err = 4; goto exitHere; } - if(failed_disk2 > info->array.raid_disks) { + if(failed_disk2 >= info->array.raid_disks) { fprintf(stderr, "%s: failed_slot_2 index is higher than number of devices in raid\n", prg); exit_err = 4; goto exitHere; @@ -435,6 +470,8 @@ int main(int argc, char *argv[]) else { start = getnum(argv[2], &err); length = getnum(argv[3], &err); + if (argc >= 5 && strcmp(argv[4], "autorepair")==0) + repair = 2; } if (err) {