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 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;
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;
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:
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:
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)
/* 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)
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:
* 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)
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;
/* 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
}
/* 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 */
/* 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;
}
if((Px == 0) && (Qx == 0))
- curr_broken_disk = curr_broken_disk;
+ curr_broken_disk = prev_broken_disk;
if(curr_broken_disk >= data_disks + 2)
broken_status = 2;
raid_disks, level, layout);
if (dnum < 0) abort();
if (source[dnum] < 0 ||
- lseek64(source[dnum], offsets[dnum]+offset, 0) < 0 ||
- read(source[dnum], buf+disk * chunk_size, chunk_size)
- != chunk_size)
+ lseek64(source[dnum],
+ offsets[dnum] + offset, 0) < 0 ||
+ read(source[dnum], buf+disk * chunk_size,
+ chunk_size) != chunk_size) {
if (failed <= 2) {
fdisk[failed] = dnum;
fblock[failed] = disk;
failed++;
}
+ }
}
if (failed == 0 || fblock[0] >= data_disks)
/* all data disks are good */
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) {
zero_size = chunk_size;
}
- if (stripe_buf == NULL || stripes == NULL || blocks == NULL
- || zero == NULL) {
+ if (stripe_buf == NULL || stripes == NULL || blocks == NULL ||
+ zero == NULL) {
rv = -2;
goto abort;
}
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;