2018-04-04 01:16:55 +08:00
|
|
|
/* SPDX-License-Identifier: GPL-2.0 */
|
2013-01-30 07:40:14 +08:00
|
|
|
/*
|
|
|
|
* Copyright (C) 2012 Fusion-io All rights reserved.
|
|
|
|
* Copyright (C) 2012 Intel Corp. All rights reserved.
|
|
|
|
*/
|
|
|
|
|
2018-04-04 01:16:55 +08:00
|
|
|
#ifndef BTRFS_RAID56_H
|
|
|
|
#define BTRFS_RAID56_H
|
|
|
|
|
2019-05-17 17:43:43 +08:00
|
|
|
static inline int nr_parity_stripes(const struct map_lookup *map)
|
2013-01-30 07:40:14 +08:00
|
|
|
{
|
|
|
|
if (map->type & BTRFS_BLOCK_GROUP_RAID5)
|
|
|
|
return 1;
|
|
|
|
else if (map->type & BTRFS_BLOCK_GROUP_RAID6)
|
|
|
|
return 2;
|
|
|
|
else
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2019-05-17 17:43:43 +08:00
|
|
|
static inline int nr_data_stripes(const struct map_lookup *map)
|
2013-01-30 07:40:14 +08:00
|
|
|
{
|
|
|
|
return map->num_stripes - nr_parity_stripes(map);
|
|
|
|
}
|
|
|
|
#define RAID5_P_STRIPE ((u64)-2)
|
|
|
|
#define RAID6_Q_STRIPE ((u64)-1)
|
|
|
|
|
|
|
|
#define is_parity_stripe(x) (((x) == RAID5_P_STRIPE) || \
|
|
|
|
((x) == RAID6_Q_STRIPE))
|
|
|
|
|
Btrfs, raid56: support parity scrub on raid56
The implementation is:
- Read and check all the data with checksum in the same stripe.
All the data which has checksum is COW data, and we are sure
that it is not changed though we don't lock the stripe. because
the space of that data just can be reclaimed after the current
transction is committed, and then the fs can use it to store the
other data, but when doing scrub, we hold the current transaction,
that is that data can not be recovered, it is safe that read and check
it out of the stripe lock.
- Lock the stripe
- Read out all the data without checksum and parity
The data without checksum and the parity may be changed if we don't
lock the stripe, so we need read it in the stripe lock context.
- Check the parity
- Re-calculate the new parity and write back it if the old parity
is not right
- Unlock the stripe
If we can not read out the data or the data we read is corrupted,
we will try to repair it. If the repair fails. we will mark the
horizontal sub-stripe(pages on the same horizontal) as corrupted
sub-stripe, and we will skip the parity check and repair of that
horizontal sub-stripe.
And in order to skip the horizontal sub-stripe that has no data, we
introduce a bitmap. If there is some data on the horizontal sub-stripe,
we will the relative bit to 1, and when we check and repair the
parity, we will skip those horizontal sub-stripes that the relative
bits is 0.
Signed-off-by: Miao Xie <miaox@cn.fujitsu.com>
2014-11-06 17:20:58 +08:00
|
|
|
struct btrfs_raid_bio;
|
|
|
|
struct btrfs_device;
|
|
|
|
|
2016-06-23 06:54:24 +08:00
|
|
|
int raid56_parity_recover(struct btrfs_fs_info *fs_info, struct bio *bio,
|
2015-01-20 15:11:33 +08:00
|
|
|
struct btrfs_bio *bbio, u64 stripe_len,
|
|
|
|
int mirror_num, int generic_io);
|
2016-06-23 06:54:24 +08:00
|
|
|
int raid56_parity_write(struct btrfs_fs_info *fs_info, struct bio *bio,
|
2015-01-20 15:11:33 +08:00
|
|
|
struct btrfs_bio *bbio, u64 stripe_len);
|
2013-01-30 07:40:14 +08:00
|
|
|
|
2015-06-20 02:52:50 +08:00
|
|
|
void raid56_add_scrub_pages(struct btrfs_raid_bio *rbio, struct page *page,
|
|
|
|
u64 logical);
|
|
|
|
|
Btrfs, raid56: support parity scrub on raid56
The implementation is:
- Read and check all the data with checksum in the same stripe.
All the data which has checksum is COW data, and we are sure
that it is not changed though we don't lock the stripe. because
the space of that data just can be reclaimed after the current
transction is committed, and then the fs can use it to store the
other data, but when doing scrub, we hold the current transaction,
that is that data can not be recovered, it is safe that read and check
it out of the stripe lock.
- Lock the stripe
- Read out all the data without checksum and parity
The data without checksum and the parity may be changed if we don't
lock the stripe, so we need read it in the stripe lock context.
- Check the parity
- Re-calculate the new parity and write back it if the old parity
is not right
- Unlock the stripe
If we can not read out the data or the data we read is corrupted,
we will try to repair it. If the repair fails. we will mark the
horizontal sub-stripe(pages on the same horizontal) as corrupted
sub-stripe, and we will skip the parity check and repair of that
horizontal sub-stripe.
And in order to skip the horizontal sub-stripe that has no data, we
introduce a bitmap. If there is some data on the horizontal sub-stripe,
we will the relative bit to 1, and when we check and repair the
parity, we will skip those horizontal sub-stripes that the relative
bits is 0.
Signed-off-by: Miao Xie <miaox@cn.fujitsu.com>
2014-11-06 17:20:58 +08:00
|
|
|
struct btrfs_raid_bio *
|
2016-06-23 06:54:24 +08:00
|
|
|
raid56_parity_alloc_scrub_rbio(struct btrfs_fs_info *fs_info, struct bio *bio,
|
2015-01-20 15:11:33 +08:00
|
|
|
struct btrfs_bio *bbio, u64 stripe_len,
|
|
|
|
struct btrfs_device *scrub_dev,
|
Btrfs, raid56: support parity scrub on raid56
The implementation is:
- Read and check all the data with checksum in the same stripe.
All the data which has checksum is COW data, and we are sure
that it is not changed though we don't lock the stripe. because
the space of that data just can be reclaimed after the current
transction is committed, and then the fs can use it to store the
other data, but when doing scrub, we hold the current transaction,
that is that data can not be recovered, it is safe that read and check
it out of the stripe lock.
- Lock the stripe
- Read out all the data without checksum and parity
The data without checksum and the parity may be changed if we don't
lock the stripe, so we need read it in the stripe lock context.
- Check the parity
- Re-calculate the new parity and write back it if the old parity
is not right
- Unlock the stripe
If we can not read out the data or the data we read is corrupted,
we will try to repair it. If the repair fails. we will mark the
horizontal sub-stripe(pages on the same horizontal) as corrupted
sub-stripe, and we will skip the parity check and repair of that
horizontal sub-stripe.
And in order to skip the horizontal sub-stripe that has no data, we
introduce a bitmap. If there is some data on the horizontal sub-stripe,
we will the relative bit to 1, and when we check and repair the
parity, we will skip those horizontal sub-stripes that the relative
bits is 0.
Signed-off-by: Miao Xie <miaox@cn.fujitsu.com>
2014-11-06 17:20:58 +08:00
|
|
|
unsigned long *dbitmap, int stripe_nsectors);
|
|
|
|
void raid56_parity_submit_scrub_rbio(struct btrfs_raid_bio *rbio);
|
|
|
|
|
2015-06-20 02:52:50 +08:00
|
|
|
struct btrfs_raid_bio *
|
2016-06-23 06:54:24 +08:00
|
|
|
raid56_alloc_missing_rbio(struct btrfs_fs_info *fs_info, struct bio *bio,
|
2015-06-20 02:52:50 +08:00
|
|
|
struct btrfs_bio *bbio, u64 length);
|
|
|
|
void raid56_submit_missing_rbio(struct btrfs_raid_bio *rbio);
|
|
|
|
|
2013-01-30 07:40:14 +08:00
|
|
|
int btrfs_alloc_stripe_hash_table(struct btrfs_fs_info *info);
|
|
|
|
void btrfs_free_stripe_hash_table(struct btrfs_fs_info *info);
|
2018-04-04 01:16:55 +08:00
|
|
|
|
2013-01-30 07:40:14 +08:00
|
|
|
#endif
|