Commit a415c0f1 authored by NeilBrown's avatar NeilBrown Committed by Shaohua Li

md: initialise ->writes_pending in personality modules.

The new per-cpu counter for writes_pending is initialised in
md_alloc(), which is not called by dm-raid.
So dm-raid fails when md_write_start() is called.

Move the initialization to the personality modules
that need it.  This way it is always initialised when needed,
but isn't unnecessarily initialized (requiring memory allocation)
when the personality doesn't use writes_pending.
Reported-by: default avatarHeinz Mauelshagen <heinzm@redhat.com>
Fixes: 4ad23a97 ("MD: use per-cpu counter for writes_pending")
Signed-off-by: default avatarNeilBrown <neilb@suse.com>
Signed-off-by: default avatarShaohua Li <shli@fb.com>
parent 3c2993b8
...@@ -5174,6 +5174,18 @@ static void mddev_delayed_delete(struct work_struct *ws) ...@@ -5174,6 +5174,18 @@ static void mddev_delayed_delete(struct work_struct *ws)
static void no_op(struct percpu_ref *r) {} static void no_op(struct percpu_ref *r) {}
int mddev_init_writes_pending(struct mddev *mddev)
{
if (mddev->writes_pending.percpu_count_ptr)
return 0;
if (percpu_ref_init(&mddev->writes_pending, no_op, 0, GFP_KERNEL) < 0)
return -ENOMEM;
/* We want to start with the refcount at zero */
percpu_ref_put(&mddev->writes_pending);
return 0;
}
EXPORT_SYMBOL_GPL(mddev_init_writes_pending);
static int md_alloc(dev_t dev, char *name) static int md_alloc(dev_t dev, char *name)
{ {
/* /*
...@@ -5239,10 +5251,6 @@ static int md_alloc(dev_t dev, char *name) ...@@ -5239,10 +5251,6 @@ static int md_alloc(dev_t dev, char *name)
blk_queue_make_request(mddev->queue, md_make_request); blk_queue_make_request(mddev->queue, md_make_request);
blk_set_stacking_limits(&mddev->queue->limits); blk_set_stacking_limits(&mddev->queue->limits);
if (percpu_ref_init(&mddev->writes_pending, no_op, 0, GFP_KERNEL) < 0)
goto abort;
/* We want to start with the refcount at zero */
percpu_ref_put(&mddev->writes_pending);
disk = alloc_disk(1 << shift); disk = alloc_disk(1 << shift);
if (!disk) { if (!disk) {
blk_cleanup_queue(mddev->queue); blk_cleanup_queue(mddev->queue);
......
...@@ -648,6 +648,7 @@ extern void md_unregister_thread(struct md_thread **threadp); ...@@ -648,6 +648,7 @@ extern void md_unregister_thread(struct md_thread **threadp);
extern void md_wakeup_thread(struct md_thread *thread); extern void md_wakeup_thread(struct md_thread *thread);
extern void md_check_recovery(struct mddev *mddev); extern void md_check_recovery(struct mddev *mddev);
extern void md_reap_sync_thread(struct mddev *mddev); extern void md_reap_sync_thread(struct mddev *mddev);
extern int mddev_init_writes_pending(struct mddev *mddev);
extern void md_write_start(struct mddev *mddev, struct bio *bi); extern void md_write_start(struct mddev *mddev, struct bio *bi);
extern void md_write_inc(struct mddev *mddev, struct bio *bi); extern void md_write_inc(struct mddev *mddev, struct bio *bi);
extern void md_write_end(struct mddev *mddev); extern void md_write_end(struct mddev *mddev);
......
...@@ -3063,6 +3063,8 @@ static int raid1_run(struct mddev *mddev) ...@@ -3063,6 +3063,8 @@ static int raid1_run(struct mddev *mddev)
mdname(mddev)); mdname(mddev));
return -EIO; return -EIO;
} }
if (mddev_init_writes_pending(mddev) < 0)
return -ENOMEM;
/* /*
* copy the already verified devices into our private RAID1 * copy the already verified devices into our private RAID1
* bookkeeping area. [whatever we allocate in run(), * bookkeeping area. [whatever we allocate in run(),
......
...@@ -3611,6 +3611,9 @@ static int raid10_run(struct mddev *mddev) ...@@ -3611,6 +3611,9 @@ static int raid10_run(struct mddev *mddev)
int first = 1; int first = 1;
bool discard_supported = false; bool discard_supported = false;
if (mddev_init_writes_pending(mddev) < 0)
return -ENOMEM;
if (mddev->private == NULL) { if (mddev->private == NULL) {
conf = setup_conf(mddev); conf = setup_conf(mddev);
if (IS_ERR(conf)) if (IS_ERR(conf))
......
...@@ -7118,6 +7118,9 @@ static int raid5_run(struct mddev *mddev) ...@@ -7118,6 +7118,9 @@ static int raid5_run(struct mddev *mddev)
long long min_offset_diff = 0; long long min_offset_diff = 0;
int first = 1; int first = 1;
if (mddev_init_writes_pending(mddev) < 0)
return -ENOMEM;
if (mddev->recovery_cp != MaxSector) if (mddev->recovery_cp != MaxSector)
pr_notice("md/raid:%s: not clean -- starting background reconstruction\n", pr_notice("md/raid:%s: not clean -- starting background reconstruction\n",
mdname(mddev)); mdname(mddev));
......
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