X-Git-Url: http://git.ipfire.org/?a=blobdiff_plain;f=raid6check.c;h=d4b60859fcc91346772fcbc2b1b68bbebbccc1ac;hb=572d7091f74e28fd2c15de210a57b060dd247dae;hp=97e3f1c8e482230e95f4673f8405f836b6b6c67b;hpb=51d9a2ce33a6a60a75751a46bb93bf052a2dfc7a;p=thirdparty%2Fmdadm.git diff --git a/raid6check.c b/raid6check.c index 97e3f1c8..d4b60859 100644 --- a/raid6check.c +++ b/raid6check.c @@ -24,6 +24,8 @@ #include "mdadm.h" #include +#include +#include int geo_map(int block, unsigned long long stripe, int raid_disks, int level, int layout); @@ -99,7 +101,7 @@ int raid6_stats(int *results, int raid_disks, int chunk_size) return curr_broken_disk; } -int check_stripes(int *source, unsigned long long *offsets, +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[]) { @@ -114,9 +116,22 @@ int check_stripes(int *source, unsigned long long *offsets, int i; int diskP, diskQ; int data_disks = raid_disks - 2; + int err = 0; + sighandler_t sig[3]; + int rv; extern int tables_ready; + if((stripe_buf == NULL) || + (stripes == NULL) || + (blocks == NULL) || + (p == NULL) || + (q == NULL) || + (results == NULL)) { + err = 1; + goto exitCheck; + } + if (!tables_ready) make_tables(); @@ -126,49 +141,72 @@ int check_stripes(int *source, unsigned long long *offsets, while (length > 0) { int disk; + printf("pos --> %llu\n", start); + + if(mlockall(MCL_CURRENT | MCL_FUTURE) != 0) { + err = 2; + 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, 0); + 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; + goto exitCheck; + } + for (i = 0 ; i < data_disks ; i++) { - int disk = geo_map(i, start/chunk_size, raid_disks, - level, layout); + int disk = geo_map(i, start, raid_disks, level, layout); blocks[i] = stripes[disk]; printf("%d->%d\n", i, disk); } qsyndrome(p, q, (uint8_t**)blocks, data_disks, chunk_size); - diskP = geo_map(-1, start/chunk_size, raid_disks, - level, layout); + diskP = geo_map(-1, start, raid_disks, level, layout); if (memcmp(p, stripes[diskP], chunk_size) != 0) { - printf("P(%d) wrong at %llu\n", diskP, - start / chunk_size); + printf("P(%d) wrong at %llu\n", diskP, start); } - diskQ = geo_map(-2, start/chunk_size, raid_disks, - level, layout); + diskQ = geo_map(-2, start, raid_disks, level, layout); if (memcmp(q, stripes[diskQ], chunk_size) != 0) { - printf("Q(%d) wrong at %llu\n", diskQ, - start / chunk_size); + printf("Q(%d) wrong at %llu\n", diskQ, start); } - raid6_collect(chunk_size, p, q, - stripes[diskP], stripes[diskQ], results); + raid6_collect(chunk_size, p, q, stripes[diskP], stripes[diskQ], results); disk = raid6_stats(results, raid_disks, chunk_size); if(disk >= -2) { - disk = geo_map(disk, start/chunk_size, raid_disks, - level, layout); + disk = geo_map(disk, start, raid_disks, level, layout); } if(disk >= 0) { - printf("Possible failed disk: %d --> %s\n", disk, name[disk]); + printf("Error detected at %llu: possible failed disk slot: %d --> %s\n", + start, disk, name[disk]); } if(disk == -65535) { - printf("Failure detected, but disk unknown\n"); + printf("Error detected at %llu: disk slot unknown\n", start); } - length -= chunk_size; - start += chunk_size; + length--; + start++; } +exitCheck: + free(stripe_buf); free(stripes); free(blocks); @@ -176,7 +214,7 @@ int check_stripes(int *source, unsigned long long *offsets, free(q); free(results); - return 0; + return err; } unsigned long long getnum(char *str, char **err) @@ -192,71 +230,174 @@ unsigned long long getnum(char *str, char **err) int main(int argc, char *argv[]) { - /* raid_disks chunk_size layout start length devices... - */ - int *fds; - char *buf; - unsigned long long *offsets; - int raid_disks, chunk_size, layout; + /* md_device start length */ + int *fds = NULL; + char *buf = NULL; + char **disk_name = NULL; + unsigned long long *offsets = NULL; + int raid_disks = 0; + int active_disks; + int chunk_size = 0; + int layout = -1; int level = 6; unsigned long long start, length; int i; - + int mdfd; + struct mdinfo *info = NULL, *comp = NULL; char *err = NULL; - if (argc < 8) { - fprintf(stderr, "Usage: raid6check raid_disks" - " chunk_size layout start length devices...\n"); - exit(1); + int exit_err = 0; + int close_flag = 0; + char *prg = strrchr(argv[0], '/'); + + if (prg == NULL) + prg = argv[0]; + else + prg++; + + if (argc < 4) { + fprintf(stderr, "Usage: %s md_device start_stripe length_stripes\n", prg); + exit_err = 1; + goto exitHere; } - raid_disks = getnum(argv[1], &err); - chunk_size = getnum(argv[2], &err); - layout = getnum(argv[3], &err); - start = getnum(argv[4], &err); - length = getnum(argv[5], &err); + mdfd = open(argv[1], O_RDONLY); + if(mdfd < 0) { + perror(argv[1]); + fprintf(stderr,"%s: cannot open %s\n", prg, argv[1]); + exit_err = 2; + goto exitHere; + } + + info = sysfs_read(mdfd, -1, + GET_LEVEL| + GET_LAYOUT| + GET_DISKS| + GET_DEGRADED | + GET_COMPONENT| + GET_CHUNK| + GET_DEVS| + GET_OFFSET| + GET_SIZE); + + if(info == NULL) { + fprintf(stderr, "%s: Error reading sysfs information of %s\n", prg, argv[1]); + exit_err = 9; + goto exitHere; + } + + if(info->array.level != level) { + fprintf(stderr, "%s: %s not a RAID-6\n", prg, argv[1]); + exit_err = 3; + goto exitHere; + } + + if(info->array.failed_disks > 0) { + fprintf(stderr, "%s: %s degraded array\n", prg, argv[1]); + exit_err = 8; + goto exitHere; + } + + printf("layout: %d\n", info->array.layout); + printf("disks: %d\n", info->array.raid_disks); + printf("component size: %llu\n", info->component_size * 512); + printf("total stripes: %llu\n", (info->component_size * 512) / info->array.chunk_size); + printf("chunk size: %d\n", info->array.chunk_size); + printf("\n"); + + comp = info->devs; + for(i = 0, active_disks = 0; active_disks < info->array.raid_disks; i++) { + printf("disk: %d - offset: %llu - size: %llu - name: %s - slot: %d\n", + i, comp->data_offset * 512, comp->component_size * 512, + map_dev(comp->disk.major, comp->disk.minor, 0), + comp->disk.raid_disk); + if(comp->disk.raid_disk >= 0) + active_disks++; + comp = comp->next; + } + printf("\n"); + + close(mdfd); + + raid_disks = info->array.raid_disks; + chunk_size = info->array.chunk_size; + layout = info->array.layout; + start = getnum(argv[2], &err); + length = getnum(argv[3], &err); + if (err) { - fprintf(stderr, "test_stripe: Bad number: %s\n", err); - exit(2); + fprintf(stderr, "%s: Bad number: %s\n", prg, err); + exit_err = 4; + goto exitHere; } - if (argc != raid_disks + 6) { - fprintf(stderr, "test_stripe: wrong number of devices: want %d found %d\n", - raid_disks, argc-6); - exit(2); + + if(start > ((info->component_size * 512) / chunk_size)) { + start = (info->component_size * 512) / chunk_size; + fprintf(stderr, "%s: start beyond disks size\n", prg); } + + if((length == 0) || + ((length + start) > ((info->component_size * 512) / chunk_size))) { + length = (info->component_size * 512) / chunk_size - start; + } + + disk_name = malloc(raid_disks * sizeof(*disk_name)); fds = malloc(raid_disks * sizeof(*fds)); offsets = malloc(raid_disks * sizeof(*offsets)); - memset(offsets, 0, raid_disks * sizeof(*offsets)); + buf = malloc(raid_disks * chunk_size); - for (i=0; idevs; + for (i=0, active_disks=0; active_disksdisk.raid_disk; + if(disk_slot >= 0) { + disk_name[disk_slot] = map_dev(comp->disk.major, comp->disk.minor, 0); + offsets[disk_slot] = comp->data_offset * 512; + fds[disk_slot] = open(disk_name[disk_slot], O_RDWR); + if (fds[disk_slot] < 0) { + perror(disk_name[disk_slot]); + fprintf(stderr,"%s: cannot open %s\n", prg, disk_name[disk_slot]); + exit_err = 6; + goto exitHere; + } + active_disks++; } + comp = comp->next; } - buf = malloc(raid_disks * chunk_size); - - int rv = check_stripes(fds, offsets, + int rv = check_stripes(info, fds, offsets, raid_disks, chunk_size, level, layout, - start, length, &argv[6]); + start, length, disk_name); if (rv != 0) { fprintf(stderr, - "test_stripe: test_stripes returned %d\n", rv); - exit(1); + "%s: check_stripes returned %d\n", prg, rv); + exit_err = 7; + goto exitHere; } +exitHere: + + if (close_flag) + for(i = 0; i < raid_disks; i++) + close(fds[i]); + + free(disk_name); free(fds); free(offsets); free(buf); - exit(0); + exit(exit_err); }