Commit 9c6694bd authored by Jens Axboe's avatar Jens Axboe

Merge branch 'md-next' of...

Merge branch 'md-next' of https://git.kernel.org/pub/scm/linux/kernel/git/song/md into for-5.5/drivers

Pull MD changes from Song.

* 'md-next' of https://git.kernel.org/pub/scm/linux/kernel/git/song/md:
  md: no longer compare spare disk superblock events in super_load
  md: improve handling of bio with REQ_PREFLUSH in md_flush_request()
  md/bitmap: avoid race window between md_bitmap_resize and bitmap_file_clear_bit
  md/raid0: Fix an error message in raid0_make_request()
parents dd85b492 6a5cb53a
...@@ -2139,6 +2139,7 @@ int md_bitmap_resize(struct bitmap *bitmap, sector_t blocks, ...@@ -2139,6 +2139,7 @@ int md_bitmap_resize(struct bitmap *bitmap, sector_t blocks,
memcpy(page_address(store.sb_page), memcpy(page_address(store.sb_page),
page_address(bitmap->storage.sb_page), page_address(bitmap->storage.sb_page),
sizeof(bitmap_super_t)); sizeof(bitmap_super_t));
spin_lock_irq(&bitmap->counts.lock);
md_bitmap_file_unmap(&bitmap->storage); md_bitmap_file_unmap(&bitmap->storage);
bitmap->storage = store; bitmap->storage = store;
...@@ -2154,7 +2155,6 @@ int md_bitmap_resize(struct bitmap *bitmap, sector_t blocks, ...@@ -2154,7 +2155,6 @@ int md_bitmap_resize(struct bitmap *bitmap, sector_t blocks,
blocks = min(old_counts.chunks << old_counts.chunkshift, blocks = min(old_counts.chunks << old_counts.chunkshift,
chunks << chunkshift); chunks << chunkshift);
spin_lock_irq(&bitmap->counts.lock);
/* For cluster raid, need to pre-allocate bitmap */ /* For cluster raid, need to pre-allocate bitmap */
if (mddev_is_clustered(bitmap->mddev)) { if (mddev_is_clustered(bitmap->mddev)) {
unsigned long page; unsigned long page;
......
...@@ -244,10 +244,9 @@ static bool linear_make_request(struct mddev *mddev, struct bio *bio) ...@@ -244,10 +244,9 @@ static bool linear_make_request(struct mddev *mddev, struct bio *bio)
sector_t start_sector, end_sector, data_offset; sector_t start_sector, end_sector, data_offset;
sector_t bio_sector = bio->bi_iter.bi_sector; sector_t bio_sector = bio->bi_iter.bi_sector;
if (unlikely(bio->bi_opf & REQ_PREFLUSH)) { if (unlikely(bio->bi_opf & REQ_PREFLUSH)
md_flush_request(mddev, bio); && md_flush_request(mddev, bio))
return true; return true;
}
tmp_dev = which_dev(mddev, bio_sector); tmp_dev = which_dev(mddev, bio_sector);
start_sector = tmp_dev->end_sector - tmp_dev->rdev->sectors; start_sector = tmp_dev->end_sector - tmp_dev->rdev->sectors;
......
...@@ -104,10 +104,9 @@ static bool multipath_make_request(struct mddev *mddev, struct bio * bio) ...@@ -104,10 +104,9 @@ static bool multipath_make_request(struct mddev *mddev, struct bio * bio)
struct multipath_bh * mp_bh; struct multipath_bh * mp_bh;
struct multipath_info *multipath; struct multipath_info *multipath;
if (unlikely(bio->bi_opf & REQ_PREFLUSH)) { if (unlikely(bio->bi_opf & REQ_PREFLUSH)
md_flush_request(mddev, bio); && md_flush_request(mddev, bio))
return true; return true;
}
mp_bh = mempool_alloc(&conf->pool, GFP_NOIO); mp_bh = mempool_alloc(&conf->pool, GFP_NOIO);
......
...@@ -550,7 +550,13 @@ static void md_submit_flush_data(struct work_struct *ws) ...@@ -550,7 +550,13 @@ static void md_submit_flush_data(struct work_struct *ws)
} }
} }
void md_flush_request(struct mddev *mddev, struct bio *bio) /*
* Manages consolidation of flushes and submitting any flushes needed for
* a bio with REQ_PREFLUSH. Returns true if the bio is finished or is
* being finished in another context. Returns false if the flushing is
* complete but still needs the I/O portion of the bio to be processed.
*/
bool md_flush_request(struct mddev *mddev, struct bio *bio)
{ {
ktime_t start = ktime_get_boottime(); ktime_t start = ktime_get_boottime();
spin_lock_irq(&mddev->lock); spin_lock_irq(&mddev->lock);
...@@ -575,9 +581,10 @@ void md_flush_request(struct mddev *mddev, struct bio *bio) ...@@ -575,9 +581,10 @@ void md_flush_request(struct mddev *mddev, struct bio *bio)
bio_endio(bio); bio_endio(bio);
else { else {
bio->bi_opf &= ~REQ_PREFLUSH; bio->bi_opf &= ~REQ_PREFLUSH;
mddev->pers->make_request(mddev, bio); return false;
} }
} }
return true;
} }
EXPORT_SYMBOL(md_flush_request); EXPORT_SYMBOL(md_flush_request);
...@@ -1149,7 +1156,15 @@ static int super_90_load(struct md_rdev *rdev, struct md_rdev *refdev, int minor ...@@ -1149,7 +1156,15 @@ static int super_90_load(struct md_rdev *rdev, struct md_rdev *refdev, int minor
rdev->desc_nr = sb->this_disk.number; rdev->desc_nr = sb->this_disk.number;
if (!refdev) { if (!refdev) {
ret = 1; /*
* Insist on good event counter while assembling, except
* for spares (which don't need an event count)
*/
if (sb->disks[rdev->desc_nr].state & (
(1<<MD_DISK_SYNC) | (1 << MD_DISK_ACTIVE)))
ret = 1;
else
ret = 0;
} else { } else {
__u64 ev1, ev2; __u64 ev1, ev2;
mdp_super_t *refsb = page_address(refdev->sb_page); mdp_super_t *refsb = page_address(refdev->sb_page);
...@@ -1165,7 +1180,14 @@ static int super_90_load(struct md_rdev *rdev, struct md_rdev *refdev, int minor ...@@ -1165,7 +1180,14 @@ static int super_90_load(struct md_rdev *rdev, struct md_rdev *refdev, int minor
} }
ev1 = md_event(sb); ev1 = md_event(sb);
ev2 = md_event(refsb); ev2 = md_event(refsb);
if (ev1 > ev2)
/*
* Insist on good event counter while assembling, except
* for spares (which don't need an event count)
*/
if (sb->disks[rdev->desc_nr].state & (
(1<<MD_DISK_SYNC) | (1 << MD_DISK_ACTIVE)) &&
(ev1 > ev2))
ret = 1; ret = 1;
else else
ret = 0; ret = 0;
...@@ -1525,6 +1547,7 @@ static int super_1_load(struct md_rdev *rdev, struct md_rdev *refdev, int minor_ ...@@ -1525,6 +1547,7 @@ static int super_1_load(struct md_rdev *rdev, struct md_rdev *refdev, int minor_
sector_t sectors; sector_t sectors;
char b[BDEVNAME_SIZE], b2[BDEVNAME_SIZE]; char b[BDEVNAME_SIZE], b2[BDEVNAME_SIZE];
int bmask; int bmask;
__u64 role;
/* /*
* Calculate the position of the superblock in 512byte sectors. * Calculate the position of the superblock in 512byte sectors.
...@@ -1658,8 +1681,20 @@ static int super_1_load(struct md_rdev *rdev, struct md_rdev *refdev, int minor_ ...@@ -1658,8 +1681,20 @@ static int super_1_load(struct md_rdev *rdev, struct md_rdev *refdev, int minor_
sb->level != 0) sb->level != 0)
return -EINVAL; return -EINVAL;
role = le16_to_cpu(sb->dev_roles[rdev->desc_nr]);
if (!refdev) { if (!refdev) {
ret = 1; /*
* Insist of good event counter while assembling, except for
* spares (which don't need an event count)
*/
if (rdev->desc_nr >= 0 &&
rdev->desc_nr < le32_to_cpu(sb->max_dev) &&
(role < MD_DISK_ROLE_MAX ||
role == MD_DISK_ROLE_JOURNAL))
ret = 1;
else
ret = 0;
} else { } else {
__u64 ev1, ev2; __u64 ev1, ev2;
struct mdp_superblock_1 *refsb = page_address(refdev->sb_page); struct mdp_superblock_1 *refsb = page_address(refdev->sb_page);
...@@ -1676,7 +1711,14 @@ static int super_1_load(struct md_rdev *rdev, struct md_rdev *refdev, int minor_ ...@@ -1676,7 +1711,14 @@ static int super_1_load(struct md_rdev *rdev, struct md_rdev *refdev, int minor_
ev1 = le64_to_cpu(sb->events); ev1 = le64_to_cpu(sb->events);
ev2 = le64_to_cpu(refsb->events); ev2 = le64_to_cpu(refsb->events);
if (ev1 > ev2) /*
* Insist of good event counter while assembling, except for
* spares (which don't need an event count)
*/
if (rdev->desc_nr >= 0 &&
rdev->desc_nr < le32_to_cpu(sb->max_dev) &&
(role < MD_DISK_ROLE_MAX ||
role == MD_DISK_ROLE_JOURNAL) && ev1 > ev2)
ret = 1; ret = 1;
else else
ret = 0; ret = 0;
...@@ -3597,7 +3639,7 @@ static struct md_rdev *md_import_device(dev_t newdev, int super_format, int supe ...@@ -3597,7 +3639,7 @@ static struct md_rdev *md_import_device(dev_t newdev, int super_format, int supe
* Check a full RAID array for plausibility * Check a full RAID array for plausibility
*/ */
static void analyze_sbs(struct mddev *mddev) static int analyze_sbs(struct mddev *mddev)
{ {
int i; int i;
struct md_rdev *rdev, *freshest, *tmp; struct md_rdev *rdev, *freshest, *tmp;
...@@ -3618,6 +3660,12 @@ static void analyze_sbs(struct mddev *mddev) ...@@ -3618,6 +3660,12 @@ static void analyze_sbs(struct mddev *mddev)
md_kick_rdev_from_array(rdev); md_kick_rdev_from_array(rdev);
} }
/* Cannot find a valid fresh disk */
if (!freshest) {
pr_warn("md: cannot find a valid disk\n");
return -EINVAL;
}
super_types[mddev->major_version]. super_types[mddev->major_version].
validate_super(mddev, freshest); validate_super(mddev, freshest);
...@@ -3652,6 +3700,8 @@ static void analyze_sbs(struct mddev *mddev) ...@@ -3652,6 +3700,8 @@ static void analyze_sbs(struct mddev *mddev)
clear_bit(In_sync, &rdev->flags); clear_bit(In_sync, &rdev->flags);
} }
} }
return 0;
} }
/* Read a fixed-point number. /* Read a fixed-point number.
...@@ -5570,7 +5620,9 @@ int md_run(struct mddev *mddev) ...@@ -5570,7 +5620,9 @@ int md_run(struct mddev *mddev)
if (!mddev->raid_disks) { if (!mddev->raid_disks) {
if (!mddev->persistent) if (!mddev->persistent)
return -EINVAL; return -EINVAL;
analyze_sbs(mddev); err = analyze_sbs(mddev);
if (err)
return -EINVAL;
} }
if (mddev->level != LEVEL_NONE) if (mddev->level != LEVEL_NONE)
......
...@@ -550,7 +550,7 @@ struct md_personality ...@@ -550,7 +550,7 @@ struct md_personality
int level; int level;
struct list_head list; struct list_head list;
struct module *owner; struct module *owner;
bool (*make_request)(struct mddev *mddev, struct bio *bio); bool __must_check (*make_request)(struct mddev *mddev, struct bio *bio);
/* /*
* start up works that do NOT require md_thread. tasks that * start up works that do NOT require md_thread. tasks that
* requires md_thread should go into start() * requires md_thread should go into start()
...@@ -703,7 +703,7 @@ extern void md_error(struct mddev *mddev, struct md_rdev *rdev); ...@@ -703,7 +703,7 @@ extern void md_error(struct mddev *mddev, struct md_rdev *rdev);
extern void md_finish_reshape(struct mddev *mddev); extern void md_finish_reshape(struct mddev *mddev);
extern int mddev_congested(struct mddev *mddev, int bits); extern int mddev_congested(struct mddev *mddev, int bits);
extern void md_flush_request(struct mddev *mddev, struct bio *bio); extern bool __must_check md_flush_request(struct mddev *mddev, struct bio *bio);
extern void md_super_write(struct mddev *mddev, struct md_rdev *rdev, extern void md_super_write(struct mddev *mddev, struct md_rdev *rdev,
sector_t sector, int size, struct page *page); sector_t sector, int size, struct page *page);
extern int md_super_wait(struct mddev *mddev); extern int md_super_wait(struct mddev *mddev);
......
...@@ -575,10 +575,9 @@ static bool raid0_make_request(struct mddev *mddev, struct bio *bio) ...@@ -575,10 +575,9 @@ static bool raid0_make_request(struct mddev *mddev, struct bio *bio)
unsigned chunk_sects; unsigned chunk_sects;
unsigned sectors; unsigned sectors;
if (unlikely(bio->bi_opf & REQ_PREFLUSH)) { if (unlikely(bio->bi_opf & REQ_PREFLUSH)
md_flush_request(mddev, bio); && md_flush_request(mddev, bio))
return true; return true;
}
if (unlikely((bio_op(bio) == REQ_OP_DISCARD))) { if (unlikely((bio_op(bio) == REQ_OP_DISCARD))) {
raid0_handle_discard(mddev, bio); raid0_handle_discard(mddev, bio);
...@@ -615,7 +614,7 @@ static bool raid0_make_request(struct mddev *mddev, struct bio *bio) ...@@ -615,7 +614,7 @@ static bool raid0_make_request(struct mddev *mddev, struct bio *bio)
tmp_dev = map_sector(mddev, zone, sector, &sector); tmp_dev = map_sector(mddev, zone, sector, &sector);
break; break;
default: default:
WARN("md/raid0:%s: Invalid layout\n", mdname(mddev)); WARN(1, "md/raid0:%s: Invalid layout\n", mdname(mddev));
bio_io_error(bio); bio_io_error(bio);
return true; return true;
} }
......
...@@ -1567,10 +1567,9 @@ static bool raid1_make_request(struct mddev *mddev, struct bio *bio) ...@@ -1567,10 +1567,9 @@ static bool raid1_make_request(struct mddev *mddev, struct bio *bio)
{ {
sector_t sectors; sector_t sectors;
if (unlikely(bio->bi_opf & REQ_PREFLUSH)) { if (unlikely(bio->bi_opf & REQ_PREFLUSH)
md_flush_request(mddev, bio); && md_flush_request(mddev, bio))
return true; return true;
}
/* /*
* There is a limit to the maximum size, but * There is a limit to the maximum size, but
......
...@@ -1525,10 +1525,9 @@ static bool raid10_make_request(struct mddev *mddev, struct bio *bio) ...@@ -1525,10 +1525,9 @@ static bool raid10_make_request(struct mddev *mddev, struct bio *bio)
int chunk_sects = chunk_mask + 1; int chunk_sects = chunk_mask + 1;
int sectors = bio_sectors(bio); int sectors = bio_sectors(bio);
if (unlikely(bio->bi_opf & REQ_PREFLUSH)) { if (unlikely(bio->bi_opf & REQ_PREFLUSH)
md_flush_request(mddev, bio); && md_flush_request(mddev, bio))
return true; return true;
}
if (!md_write_start(mddev, bio)) if (!md_write_start(mddev, bio))
return false; return false;
......
...@@ -5592,8 +5592,8 @@ static bool raid5_make_request(struct mddev *mddev, struct bio * bi) ...@@ -5592,8 +5592,8 @@ static bool raid5_make_request(struct mddev *mddev, struct bio * bi)
if (ret == 0) if (ret == 0)
return true; return true;
if (ret == -ENODEV) { if (ret == -ENODEV) {
md_flush_request(mddev, bi); if (md_flush_request(mddev, bi))
return true; return true;
} }
/* ret == -EAGAIN, fallback */ /* ret == -EAGAIN, fallback */
/* /*
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment