Merge branch 'raid56-scrub-replace' of git://github.com/miaoxie/linux-btrfs into for-linus
Esse commit está contido em:
@@ -80,13 +80,6 @@ noinline void btrfs_clear_path_blocking(struct btrfs_path *p,
|
||||
{
|
||||
int i;
|
||||
|
||||
#ifdef CONFIG_DEBUG_LOCK_ALLOC
|
||||
/* lockdep really cares that we take all of these spinlocks
|
||||
* in the right order. If any of the locks in the path are not
|
||||
* currently blocking, it is going to complain. So, make really
|
||||
* really sure by forcing the path to blocking before we clear
|
||||
* the path blocking.
|
||||
*/
|
||||
if (held) {
|
||||
btrfs_set_lock_blocking_rw(held, held_rw);
|
||||
if (held_rw == BTRFS_WRITE_LOCK)
|
||||
@@ -95,7 +88,6 @@ noinline void btrfs_clear_path_blocking(struct btrfs_path *p,
|
||||
held_rw = BTRFS_READ_LOCK_BLOCKING;
|
||||
}
|
||||
btrfs_set_path_blocking(p);
|
||||
#endif
|
||||
|
||||
for (i = BTRFS_MAX_LEVEL - 1; i >= 0; i--) {
|
||||
if (p->nodes[i] && p->locks[i]) {
|
||||
@@ -107,10 +99,8 @@ noinline void btrfs_clear_path_blocking(struct btrfs_path *p,
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef CONFIG_DEBUG_LOCK_ALLOC
|
||||
if (held)
|
||||
btrfs_clear_lock_blocking_rw(held, held_rw);
|
||||
#endif
|
||||
}
|
||||
|
||||
/* this also releases the path */
|
||||
@@ -2893,7 +2883,7 @@ cow_done:
|
||||
}
|
||||
p->locks[level] = BTRFS_WRITE_LOCK;
|
||||
} else {
|
||||
err = btrfs_try_tree_read_lock(b);
|
||||
err = btrfs_tree_read_lock_atomic(b);
|
||||
if (!err) {
|
||||
btrfs_set_path_blocking(p);
|
||||
btrfs_tree_read_lock(b);
|
||||
@@ -3025,7 +3015,7 @@ again:
|
||||
}
|
||||
|
||||
level = btrfs_header_level(b);
|
||||
err = btrfs_try_tree_read_lock(b);
|
||||
err = btrfs_tree_read_lock_atomic(b);
|
||||
if (!err) {
|
||||
btrfs_set_path_blocking(p);
|
||||
btrfs_tree_read_lock(b);
|
||||
|
@@ -4167,7 +4167,12 @@ int btrfs_scrub_progress(struct btrfs_root *root, u64 devid,
|
||||
/* dev-replace.c */
|
||||
void btrfs_bio_counter_inc_blocked(struct btrfs_fs_info *fs_info);
|
||||
void btrfs_bio_counter_inc_noblocked(struct btrfs_fs_info *fs_info);
|
||||
void btrfs_bio_counter_dec(struct btrfs_fs_info *fs_info);
|
||||
void btrfs_bio_counter_sub(struct btrfs_fs_info *fs_info, s64 amount);
|
||||
|
||||
static inline void btrfs_bio_counter_dec(struct btrfs_fs_info *fs_info)
|
||||
{
|
||||
btrfs_bio_counter_sub(fs_info, 1);
|
||||
}
|
||||
|
||||
/* reada.c */
|
||||
struct reada_control {
|
||||
|
@@ -316,11 +316,6 @@ int btrfs_dev_replace_start(struct btrfs_root *root,
|
||||
struct btrfs_device *tgt_device = NULL;
|
||||
struct btrfs_device *src_device = NULL;
|
||||
|
||||
if (btrfs_fs_incompat(fs_info, RAID56)) {
|
||||
btrfs_warn(fs_info, "dev_replace cannot yet handle RAID5/RAID6");
|
||||
return -EOPNOTSUPP;
|
||||
}
|
||||
|
||||
switch (args->start.cont_reading_from_srcdev_mode) {
|
||||
case BTRFS_IOCTL_DEV_REPLACE_CONT_READING_FROM_SRCDEV_MODE_ALWAYS:
|
||||
case BTRFS_IOCTL_DEV_REPLACE_CONT_READING_FROM_SRCDEV_MODE_AVOID:
|
||||
@@ -927,9 +922,9 @@ void btrfs_bio_counter_inc_noblocked(struct btrfs_fs_info *fs_info)
|
||||
percpu_counter_inc(&fs_info->bio_counter);
|
||||
}
|
||||
|
||||
void btrfs_bio_counter_dec(struct btrfs_fs_info *fs_info)
|
||||
void btrfs_bio_counter_sub(struct btrfs_fs_info *fs_info, s64 amount)
|
||||
{
|
||||
percpu_counter_dec(&fs_info->bio_counter);
|
||||
percpu_counter_sub(&fs_info->bio_counter, amount);
|
||||
|
||||
if (waitqueue_active(&fs_info->replace_wait))
|
||||
wake_up(&fs_info->replace_wait);
|
||||
|
@@ -127,6 +127,26 @@ again:
|
||||
atomic_inc(&eb->spinning_readers);
|
||||
}
|
||||
|
||||
/*
|
||||
* take a spinning read lock.
|
||||
* returns 1 if we get the read lock and 0 if we don't
|
||||
* this won't wait for blocking writers
|
||||
*/
|
||||
int btrfs_tree_read_lock_atomic(struct extent_buffer *eb)
|
||||
{
|
||||
if (atomic_read(&eb->blocking_writers))
|
||||
return 0;
|
||||
|
||||
read_lock(&eb->lock);
|
||||
if (atomic_read(&eb->blocking_writers)) {
|
||||
read_unlock(&eb->lock);
|
||||
return 0;
|
||||
}
|
||||
atomic_inc(&eb->read_locks);
|
||||
atomic_inc(&eb->spinning_readers);
|
||||
return 1;
|
||||
}
|
||||
|
||||
/*
|
||||
* returns 1 if we get the read lock and 0 if we don't
|
||||
* this won't wait for blocking writers
|
||||
@@ -158,9 +178,7 @@ int btrfs_try_tree_write_lock(struct extent_buffer *eb)
|
||||
atomic_read(&eb->blocking_readers))
|
||||
return 0;
|
||||
|
||||
if (!write_trylock(&eb->lock))
|
||||
return 0;
|
||||
|
||||
write_lock(&eb->lock);
|
||||
if (atomic_read(&eb->blocking_writers) ||
|
||||
atomic_read(&eb->blocking_readers)) {
|
||||
write_unlock(&eb->lock);
|
||||
|
@@ -35,6 +35,8 @@ void btrfs_clear_lock_blocking_rw(struct extent_buffer *eb, int rw);
|
||||
void btrfs_assert_tree_locked(struct extent_buffer *eb);
|
||||
int btrfs_try_tree_read_lock(struct extent_buffer *eb);
|
||||
int btrfs_try_tree_write_lock(struct extent_buffer *eb);
|
||||
int btrfs_tree_read_lock_atomic(struct extent_buffer *eb);
|
||||
|
||||
|
||||
static inline void btrfs_tree_unlock_rw(struct extent_buffer *eb, int rw)
|
||||
{
|
||||
|
Diferenças do arquivo suprimidas por serem muito extensas
Carregar Diff
@@ -39,13 +39,25 @@ static inline int nr_data_stripes(struct map_lookup *map)
|
||||
#define is_parity_stripe(x) (((x) == RAID5_P_STRIPE) || \
|
||||
((x) == RAID6_Q_STRIPE))
|
||||
|
||||
struct btrfs_raid_bio;
|
||||
struct btrfs_device;
|
||||
|
||||
int raid56_parity_recover(struct btrfs_root *root, struct bio *bio,
|
||||
struct btrfs_bio *bbio, u64 *raid_map,
|
||||
u64 stripe_len, int mirror_num);
|
||||
struct btrfs_bio *bbio, u64 *raid_map,
|
||||
u64 stripe_len, int mirror_num, int generic_io);
|
||||
int raid56_parity_write(struct btrfs_root *root, struct bio *bio,
|
||||
struct btrfs_bio *bbio, u64 *raid_map,
|
||||
u64 stripe_len);
|
||||
|
||||
struct btrfs_raid_bio *
|
||||
raid56_parity_alloc_scrub_rbio(struct btrfs_root *root, struct bio *bio,
|
||||
struct btrfs_bio *bbio, u64 *raid_map,
|
||||
u64 stripe_len, struct btrfs_device *scrub_dev,
|
||||
unsigned long *dbitmap, int stripe_nsectors);
|
||||
void raid56_parity_add_scrub_pages(struct btrfs_raid_bio *rbio,
|
||||
struct page *page, u64 logical);
|
||||
void raid56_parity_submit_scrub_rbio(struct btrfs_raid_bio *rbio);
|
||||
|
||||
int btrfs_alloc_stripe_hash_table(struct btrfs_fs_info *info);
|
||||
void btrfs_free_stripe_hash_table(struct btrfs_fs_info *info);
|
||||
#endif
|
||||
|
803
fs/btrfs/scrub.c
803
fs/btrfs/scrub.c
Diferenças do arquivo suprimidas por serem muito extensas
Carregar Diff
@@ -4879,13 +4879,15 @@ static inline int parity_smaller(u64 a, u64 b)
|
||||
static void sort_parity_stripes(struct btrfs_bio *bbio, u64 *raid_map)
|
||||
{
|
||||
struct btrfs_bio_stripe s;
|
||||
int real_stripes = bbio->num_stripes - bbio->num_tgtdevs;
|
||||
int i;
|
||||
u64 l;
|
||||
int again = 1;
|
||||
int m;
|
||||
|
||||
while (again) {
|
||||
again = 0;
|
||||
for (i = 0; i < bbio->num_stripes - 1; i++) {
|
||||
for (i = 0; i < real_stripes - 1; i++) {
|
||||
if (parity_smaller(raid_map[i], raid_map[i+1])) {
|
||||
s = bbio->stripes[i];
|
||||
l = raid_map[i];
|
||||
@@ -4893,6 +4895,14 @@ static void sort_parity_stripes(struct btrfs_bio *bbio, u64 *raid_map)
|
||||
raid_map[i] = raid_map[i+1];
|
||||
bbio->stripes[i+1] = s;
|
||||
raid_map[i+1] = l;
|
||||
|
||||
if (bbio->tgtdev_map) {
|
||||
m = bbio->tgtdev_map[i];
|
||||
bbio->tgtdev_map[i] =
|
||||
bbio->tgtdev_map[i + 1];
|
||||
bbio->tgtdev_map[i + 1] = m;
|
||||
}
|
||||
|
||||
again = 1;
|
||||
}
|
||||
}
|
||||
@@ -4921,6 +4931,7 @@ static int __btrfs_map_block(struct btrfs_fs_info *fs_info, int rw,
|
||||
int ret = 0;
|
||||
int num_stripes;
|
||||
int max_errors = 0;
|
||||
int tgtdev_indexes = 0;
|
||||
struct btrfs_bio *bbio = NULL;
|
||||
struct btrfs_dev_replace *dev_replace = &fs_info->dev_replace;
|
||||
int dev_replace_is_ongoing = 0;
|
||||
@@ -5159,15 +5170,14 @@ static int __btrfs_map_block(struct btrfs_fs_info *fs_info, int rw,
|
||||
BTRFS_BLOCK_GROUP_RAID6)) {
|
||||
u64 tmp;
|
||||
|
||||
if (bbio_ret && ((rw & REQ_WRITE) || mirror_num > 1)
|
||||
&& raid_map_ret) {
|
||||
if (raid_map_ret &&
|
||||
((rw & (REQ_WRITE | REQ_GET_READ_MIRRORS)) ||
|
||||
mirror_num > 1)) {
|
||||
int i, rot;
|
||||
|
||||
/* push stripe_nr back to the start of the full stripe */
|
||||
stripe_nr = raid56_full_stripe_start;
|
||||
do_div(stripe_nr, stripe_len);
|
||||
|
||||
stripe_index = do_div(stripe_nr, nr_data_stripes(map));
|
||||
do_div(stripe_nr, stripe_len * nr_data_stripes(map));
|
||||
|
||||
/* RAID[56] write or recovery. Return all stripes */
|
||||
num_stripes = map->num_stripes;
|
||||
@@ -5233,14 +5243,19 @@ static int __btrfs_map_block(struct btrfs_fs_info *fs_info, int rw,
|
||||
num_alloc_stripes <<= 1;
|
||||
if (rw & REQ_GET_READ_MIRRORS)
|
||||
num_alloc_stripes++;
|
||||
tgtdev_indexes = num_stripes;
|
||||
}
|
||||
bbio = kzalloc(btrfs_bio_size(num_alloc_stripes), GFP_NOFS);
|
||||
|
||||
bbio = kzalloc(btrfs_bio_size(num_alloc_stripes, tgtdev_indexes),
|
||||
GFP_NOFS);
|
||||
if (!bbio) {
|
||||
kfree(raid_map);
|
||||
ret = -ENOMEM;
|
||||
goto out;
|
||||
}
|
||||
atomic_set(&bbio->error, 0);
|
||||
if (dev_replace_is_ongoing)
|
||||
bbio->tgtdev_map = (int *)(bbio->stripes + num_alloc_stripes);
|
||||
|
||||
if (rw & REQ_DISCARD) {
|
||||
int factor = 0;
|
||||
@@ -5325,6 +5340,7 @@ static int __btrfs_map_block(struct btrfs_fs_info *fs_info, int rw,
|
||||
if (rw & (REQ_WRITE | REQ_GET_READ_MIRRORS))
|
||||
max_errors = btrfs_chunk_max_errors(map);
|
||||
|
||||
tgtdev_indexes = 0;
|
||||
if (dev_replace_is_ongoing && (rw & (REQ_WRITE | REQ_DISCARD)) &&
|
||||
dev_replace->tgtdev != NULL) {
|
||||
int index_where_to_add;
|
||||
@@ -5353,8 +5369,10 @@ static int __btrfs_map_block(struct btrfs_fs_info *fs_info, int rw,
|
||||
new->physical = old->physical;
|
||||
new->length = old->length;
|
||||
new->dev = dev_replace->tgtdev;
|
||||
bbio->tgtdev_map[i] = index_where_to_add;
|
||||
index_where_to_add++;
|
||||
max_errors++;
|
||||
tgtdev_indexes++;
|
||||
}
|
||||
}
|
||||
num_stripes = index_where_to_add;
|
||||
@@ -5400,7 +5418,9 @@ static int __btrfs_map_block(struct btrfs_fs_info *fs_info, int rw,
|
||||
tgtdev_stripe->length =
|
||||
bbio->stripes[index_srcdev].length;
|
||||
tgtdev_stripe->dev = dev_replace->tgtdev;
|
||||
bbio->tgtdev_map[index_srcdev] = num_stripes;
|
||||
|
||||
tgtdev_indexes++;
|
||||
num_stripes++;
|
||||
}
|
||||
}
|
||||
@@ -5410,6 +5430,7 @@ static int __btrfs_map_block(struct btrfs_fs_info *fs_info, int rw,
|
||||
bbio->num_stripes = num_stripes;
|
||||
bbio->max_errors = max_errors;
|
||||
bbio->mirror_num = mirror_num;
|
||||
bbio->num_tgtdevs = tgtdev_indexes;
|
||||
|
||||
/*
|
||||
* this is the case that REQ_READ && dev_replace_is_ongoing &&
|
||||
@@ -5441,6 +5462,16 @@ int btrfs_map_block(struct btrfs_fs_info *fs_info, int rw,
|
||||
mirror_num, NULL);
|
||||
}
|
||||
|
||||
/* For Scrub/replace */
|
||||
int btrfs_map_sblock(struct btrfs_fs_info *fs_info, int rw,
|
||||
u64 logical, u64 *length,
|
||||
struct btrfs_bio **bbio_ret, int mirror_num,
|
||||
u64 **raid_map_ret)
|
||||
{
|
||||
return __btrfs_map_block(fs_info, rw, logical, length, bbio_ret,
|
||||
mirror_num, raid_map_ret);
|
||||
}
|
||||
|
||||
int btrfs_rmap_block(struct btrfs_mapping_tree *map_tree,
|
||||
u64 chunk_start, u64 physical, u64 devid,
|
||||
u64 **logical, int *naddrs, int *stripe_len)
|
||||
@@ -5810,12 +5841,9 @@ int btrfs_map_bio(struct btrfs_root *root, int rw, struct bio *bio,
|
||||
} else {
|
||||
ret = raid56_parity_recover(root, bio, bbio,
|
||||
raid_map, map_length,
|
||||
mirror_num);
|
||||
mirror_num, 1);
|
||||
}
|
||||
/*
|
||||
* FIXME, replace dosen't support raid56 yet, please fix
|
||||
* it in the future.
|
||||
*/
|
||||
|
||||
btrfs_bio_counter_dec(root->fs_info);
|
||||
return ret;
|
||||
}
|
||||
|
@@ -292,7 +292,7 @@ struct btrfs_bio_stripe {
|
||||
struct btrfs_bio;
|
||||
typedef void (btrfs_bio_end_io_t) (struct btrfs_bio *bio, int err);
|
||||
|
||||
#define BTRFS_BIO_ORIG_BIO_SUBMITTED 0x1
|
||||
#define BTRFS_BIO_ORIG_BIO_SUBMITTED (1 << 0)
|
||||
|
||||
struct btrfs_bio {
|
||||
atomic_t stripes_pending;
|
||||
@@ -305,6 +305,8 @@ struct btrfs_bio {
|
||||
int max_errors;
|
||||
int num_stripes;
|
||||
int mirror_num;
|
||||
int num_tgtdevs;
|
||||
int *tgtdev_map;
|
||||
struct btrfs_bio_stripe stripes[];
|
||||
};
|
||||
|
||||
@@ -387,12 +389,18 @@ struct btrfs_balance_control {
|
||||
int btrfs_account_dev_extents_size(struct btrfs_device *device, u64 start,
|
||||
u64 end, u64 *length);
|
||||
|
||||
#define btrfs_bio_size(n) (sizeof(struct btrfs_bio) + \
|
||||
(sizeof(struct btrfs_bio_stripe) * (n)))
|
||||
#define btrfs_bio_size(total_stripes, real_stripes) \
|
||||
(sizeof(struct btrfs_bio) + \
|
||||
(sizeof(struct btrfs_bio_stripe) * (total_stripes)) + \
|
||||
(sizeof(int) * (real_stripes)))
|
||||
|
||||
int btrfs_map_block(struct btrfs_fs_info *fs_info, int rw,
|
||||
u64 logical, u64 *length,
|
||||
struct btrfs_bio **bbio_ret, int mirror_num);
|
||||
int btrfs_map_sblock(struct btrfs_fs_info *fs_info, int rw,
|
||||
u64 logical, u64 *length,
|
||||
struct btrfs_bio **bbio_ret, int mirror_num,
|
||||
u64 **raid_map_ret);
|
||||
int btrfs_rmap_block(struct btrfs_mapping_tree *map_tree,
|
||||
u64 chunk_start, u64 physical, u64 devid,
|
||||
u64 **logical, int *naddrs, int *stripe_len);
|
||||
|
Referência em uma nova issue
Block a user