X-Git-Url: http://git.ipfire.org/?a=blobdiff_plain;f=restripe.c;h=359ae86ed5845d109336639629bc737f3895e39a;hb=83ca7d4527a8abe65a06256ce87e4f2f719449f2;hp=90896c89de0260a4c610d8ebdab7c5ffe3d031f8;hpb=1cc101f3f873fac4110aeece95bfe391fc8680c2;p=thirdparty%2Fmdadm.git diff --git a/restripe.c b/restripe.c index 90896c89..359ae86e 100644 --- a/restripe.c +++ b/restripe.c @@ -58,32 +58,35 @@ int geo_map(int block, unsigned long long stripe, int raid_disks, return block; case 500 + ALGORITHM_LEFT_ASYMMETRIC: pd = (raid_disks-1) - stripe % raid_disks; - if (block == -1) return pd; + if (block == -1) + return pd; if (block >= pd) block++; return block; case 500 + ALGORITHM_RIGHT_ASYMMETRIC: pd = stripe % raid_disks; - if (block == -1) return pd; + if (block == -1) + return pd; if (block >= pd) block++; return block; case 500 + ALGORITHM_LEFT_SYMMETRIC: pd = (raid_disks - 1) - stripe % raid_disks; - if (block == -1) return pd; + if (block == -1) + return pd; return (pd + 1 + block) % raid_disks; case 500 + ALGORITHM_RIGHT_SYMMETRIC: pd = stripe % raid_disks; - if (block == -1) return pd; + if (block == -1) + return pd; return (pd + 1 + block) % raid_disks; case 500 + ALGORITHM_PARITY_0: return block + 1; - case 600 + ALGORITHM_PARITY_N_6: if (block == -2) return raid_disks - 1; @@ -95,7 +98,8 @@ int geo_map(int block, unsigned long long stripe, int raid_disks, return raid_disks - 1; raid_disks--; pd = (raid_disks-1) - stripe % raid_disks; - if (block == -1) return pd; + if (block == -1) + return pd; if (block >= pd) block++; return block; @@ -105,7 +109,8 @@ int geo_map(int block, unsigned long long stripe, int raid_disks, return raid_disks - 1; raid_disks--; pd = stripe % raid_disks; - if (block == -1) return pd; + if (block == -1) + return pd; if (block >= pd) block++; return block; @@ -115,7 +120,8 @@ int geo_map(int block, unsigned long long stripe, int raid_disks, return raid_disks - 1; raid_disks--; pd = (raid_disks - 1) - stripe % raid_disks; - if (block == -1) return pd; + if (block == -1) + return pd; return (pd + 1 + block) % raid_disks; case 600 + ALGORITHM_RIGHT_SYMMETRIC_6: @@ -123,7 +129,8 @@ int geo_map(int block, unsigned long long stripe, int raid_disks, return raid_disks - 1; raid_disks--; pd = stripe % raid_disks; - if (block == -1) return pd; + if (block == -1) + return pd; return (pd + 1 + block) % raid_disks; case 600 + ALGORITHM_PARITY_0_6: @@ -131,7 +138,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; @@ -141,8 +147,10 @@ int geo_map(int block, unsigned long long stripe, int raid_disks, case 600 + ALGORITHM_LEFT_ASYMMETRIC: pd = raid_disks - 1 - (stripe % raid_disks); - if (block == -1) return pd; - if (block == -2) return (pd+1) % raid_disks; + if (block == -1) + return pd; + if (block == -2) + return (pd+1) % raid_disks; if (pd == raid_disks - 1) return block+1; if (block >= pd) @@ -153,8 +161,10 @@ int geo_map(int block, unsigned long long stripe, int raid_disks, /* Different order for calculating Q, otherwize same as ... */ case 600 + ALGORITHM_RIGHT_ASYMMETRIC: pd = stripe % raid_disks; - if (block == -1) return pd; - if (block == -2) return (pd+1) % raid_disks; + if (block == -1) + return pd; + if (block == -2) + return (pd+1) % raid_disks; if (pd == raid_disks - 1) return block+1; if (block >= pd) @@ -163,25 +173,30 @@ int geo_map(int block, unsigned long long stripe, int raid_disks, case 600 + ALGORITHM_LEFT_SYMMETRIC: pd = raid_disks - 1 - (stripe % raid_disks); - if (block == -1) return pd; - if (block == -2) return (pd+1) % raid_disks; + if (block == -1) + return pd; + if (block == -2) + return (pd+1) % raid_disks; return (pd + 2 + block) % raid_disks; case 600 + ALGORITHM_RIGHT_SYMMETRIC: pd = stripe % raid_disks; - if (block == -1) return pd; - if (block == -2) return (pd+1) % raid_disks; + if (block == -1) + return pd; + 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 * Q D D D P */ pd = raid_disks - 1 - ((stripe + 1) % raid_disks); - if (block == -1) return pd; - if (block == -2) return (pd+1) % raid_disks; + if (block == -1) + return pd; + if (block == -2) + return (pd+1) % raid_disks; if (pd == raid_disks - 1) return block+1; if (block >= pd) @@ -191,13 +206,16 @@ int geo_map(int block, unsigned long long stripe, int raid_disks, case 600 + ALGORITHM_ROTATING_N_CONTINUE: /* Same as left_symmetric but Q is before P */ pd = raid_disks - 1 - (stripe % raid_disks); - if (block == -1) return pd; - if (block == -2) return (pd+raid_disks-1) % raid_disks; + if (block == -1) + return pd; + if (block == -2) + return (pd+raid_disks-1) % raid_disks; return (pd + 1 + block) % raid_disks; } return -1; } -static int is_ddf(int layout) + +int is_ddf(int layout) { switch (layout) { @@ -210,7 +228,6 @@ static int is_ddf(int layout) } } - void xor_blocks(char *target, char **sources, int disks, int size) { int i, j; @@ -243,7 +260,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 @@ -349,16 +365,28 @@ void ensure_zero_has_size(int chunk_size) /* Following was taken from linux/drivers/md/raid6recov.c */ /* Recover two failed data blocks. */ + void raid6_2data_recov(int disks, size_t bytes, int faila, int failb, - uint8_t **ptrs) + uint8_t **ptrs, int neg_offset) { uint8_t *p, *q, *dp, *dq; uint8_t px, qx, db; const uint8_t *pbmul; /* P multiplier table for B data */ const uint8_t *qmul; /* Q multiplier table (for both) */ - p = ptrs[disks-2]; - q = ptrs[disks-1]; + if (faila > failb) { + int t = faila; + faila = failb; + failb = t; + } + + if (neg_offset) { + p = ptrs[-1]; + q = ptrs[-2]; + } else { + p = ptrs[disks-2]; + q = ptrs[disks-1]; + } /* Compute syndrome with zero for the missing data pages Use the dead data pages as temporary storage for @@ -389,13 +417,19 @@ void raid6_2data_recov(int disks, size_t bytes, int faila, int failb, } /* Recover failure of one data block plus the P block */ -void raid6_datap_recov(int disks, size_t bytes, int faila, uint8_t **ptrs) +void raid6_datap_recov(int disks, size_t bytes, int faila, uint8_t **ptrs, + int neg_offset) { uint8_t *p, *q, *dq; const uint8_t *qmul; /* Q multiplier table */ - p = ptrs[disks-2]; - q = ptrs[disks-1]; + if (neg_offset) { + p = ptrs[-1]; + q = ptrs[-2]; + } else { + p = ptrs[disks-2]; + q = ptrs[disks-1]; + } /* Compute syndrome with zero for the missing data page Use the dead data page as temporary storage for delta q */ @@ -420,7 +454,7 @@ void raid6_datap_recov(int disks, size_t bytes, int faila, uint8_t **ptrs) /* Try to find out if a specific disk has a problem */ int raid6_check_disks(int data_disks, int start, int chunk_size, int level, int layout, int diskP, int diskQ, - char *p, char *q, char **stripes) + uint8_t *p, uint8_t *q, char **stripes) { int i; int data_id, diskD; @@ -436,11 +470,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; @@ -643,16 +675,11 @@ int save_stripes(int *source, unsigned long long *offsets, if (fblock[1] == data_disks) /* One data failed, and parity failed */ raid6_datap_recov(syndrome_disks+2, chunk_size, - fdisk[0], bufs); + fdisk[0], bufs, 0); else { - if (fdisk[0] > fdisk[1]) { - int t = fdisk[0]; - fdisk[0] = fdisk[1]; - fdisk[1] = t; - } /* Two data blocks failed, P,Q OK */ raid6_2data_recov(syndrome_disks+2, chunk_size, - fdisk[0], fdisk[1], bufs); + fdisk[0], fdisk[1], bufs, 0); } } if (dest) { @@ -780,7 +807,7 @@ 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; @@ -820,8 +847,8 @@ int test_stripes(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*)); - char *p = xmalloc(chunk_size); - char *q = xmalloc(chunk_size); + uint8_t *p = xmalloc(chunk_size); + uint8_t *q = xmalloc(chunk_size); int i; int diskP, diskQ; @@ -889,7 +916,8 @@ unsigned long long getnum(char *str, char **err) return rv; } -main(int argc, char *argv[]) +char const Name[] = "test_restripe"; +int main(int argc, char *argv[]) { /* save/restore file raid_disks chunk_size level layout start length devices... */ @@ -905,8 +933,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) @@ -953,7 +980,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]);