btrfs-progs: Introduce wrapper to recover raid56 data

Introduce a wrapper to recover raid56 data.

The logical is the same with kernel one, but with different interfaces,
since kernel ones cares the performance while in btrfs we don't care
that much.

And the interface is more caller friendly inside btrfs-progs.

Signed-off-by: Qu Wenruo <quwenruo@cn.fujitsu.com>
Signed-off-by: David Sterba <dsterba@suse.com>
master
Qu Wenruo 2017-05-25 14:21:50 +08:00 committed by David Sterba
parent 008bbd8842
commit 05734124f2
2 changed files with 88 additions and 0 deletions

View File

@ -280,3 +280,80 @@ int raid6_recov_datap(int nr_devs, size_t stripe_len, int dest1, void **data)
}
return 0;
}
/* Original raid56 recovery wrapper */
int raid56_recov(int nr_devs, size_t stripe_len, u64 profile, int dest1,
int dest2, void **data)
{
int min_devs;
int ret;
if (profile & BTRFS_BLOCK_GROUP_RAID5)
min_devs = 2;
else if (profile & BTRFS_BLOCK_GROUP_RAID6)
min_devs = 3;
else
return -EINVAL;
if (nr_devs < min_devs)
return -EINVAL;
/* Nothing to recover */
if (dest1 == -1 && dest2 == -1)
return 0;
/* Reorder dest1/2, so only dest2 can be -1 */
if (dest1 == -1) {
dest1 = dest2;
dest2 = -1;
} else if (dest2 != -1 && dest1 != -1) {
/* Reorder dest1/2, ensure dest2 > dest1 */
if (dest1 > dest2) {
int tmp;
tmp = dest2;
dest2 = dest1;
dest1 = tmp;
}
}
if (profile & BTRFS_BLOCK_GROUP_RAID5) {
if (dest2 != -1)
return 1;
return raid5_gen_result(nr_devs, stripe_len, dest1, data);
}
/* RAID6 one dev corrupted case*/
if (dest2 == -1) {
/* Regenerate P/Q */
if (dest1 == nr_devs - 1 || dest1 == nr_devs - 2) {
raid6_gen_syndrome(nr_devs, stripe_len, data);
return 0;
}
/* Regerneate data from P */
return raid5_gen_result(nr_devs - 1, stripe_len, dest1, data);
}
/* P/Q bot corrupted */
if (dest1 == nr_devs - 2 && dest2 == nr_devs - 1) {
raid6_gen_syndrome(nr_devs, stripe_len, data);
return 0;
}
/* 2 Data corrupted */
if (dest2 < nr_devs - 2)
return raid6_recov_data2(nr_devs, stripe_len, dest1, dest2,
data);
/* Data and P*/
if (dest2 == nr_devs - 1)
return raid6_recov_datap(nr_devs, stripe_len, dest1, data);
/*
* Final case, Data and Q, recover data first then regenerate Q
*/
ret = raid5_gen_result(nr_devs - 1, stripe_len, dest1, data);
if (ret < 0)
return ret;
raid6_gen_syndrome(nr_devs, stripe_len, data);
return 0;
}

View File

@ -44,4 +44,15 @@ int raid6_recov_data2(int nr_devs, size_t stripe_len, int dest1, int dest2,
/* Recover data and P */
int raid6_recov_datap(int nr_devs, size_t stripe_len, int dest1, void **data);
/*
* Recover raid56 data
* @dest1/2 can be -1 to indicate correct data
*
* Return >0 for unrecoverable case.
* Return 0 for recoverable case, And recovered data will be stored into @data
* Return <0 for fatal error
*/
int raid56_recov(int nr_devs, size_t stripe_len, u64 profile, int dest1,
int dest2, void **data);
#endif