diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2017-06-09 22:24:23 -0700 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2017-06-09 22:24:23 -0700 |
commit | 2833b7e913327855c2c0c842c37ca1d90602139e (patch) | |
tree | 9ff3b4af4a31cde4032e55da3c2ffdbbdfb98e36 /drivers | |
parent | 42211f6cb6d7c3a39fe9b2892a93e4c065149d5f (diff) | |
parent | a415c0f10627913793709ddb75add09d2ea334dc (diff) |
Merge tag 'md/4.12-rc5' of git://git.kernel.org/pub/scm/linux/kernel/git/shli/md
Pull MD bugfix from Shaohua Li:
"One bug fix from Neil Brown for MD. The bug was introduced in this
cycle"
* tag 'md/4.12-rc5' of git://git.kernel.org/pub/scm/linux/kernel/git/shli/md:
md: initialise ->writes_pending in personality modules.
Diffstat (limited to 'drivers')
-rw-r--r-- | drivers/md/md.c | 16 | ||||
-rw-r--r-- | drivers/md/md.h | 1 | ||||
-rw-r--r-- | drivers/md/raid1.c | 2 | ||||
-rw-r--r-- | drivers/md/raid10.c | 3 | ||||
-rw-r--r-- | drivers/md/raid5.c | 3 |
5 files changed, 21 insertions, 4 deletions
diff --git a/drivers/md/md.c b/drivers/md/md.c index 212a6777ff31..87edc342ccb3 100644 --- a/drivers/md/md.c +++ b/drivers/md/md.c @@ -5174,6 +5174,18 @@ static void mddev_delayed_delete(struct work_struct *ws) 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) { /* @@ -5239,10 +5251,6 @@ static int md_alloc(dev_t dev, char *name) blk_queue_make_request(mddev->queue, md_make_request); 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); if (!disk) { blk_cleanup_queue(mddev->queue); diff --git a/drivers/md/md.h b/drivers/md/md.h index 11f15146ce51..0fa1de42c42b 100644 --- a/drivers/md/md.h +++ b/drivers/md/md.h @@ -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_check_recovery(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_inc(struct mddev *mddev, struct bio *bi); extern void md_write_end(struct mddev *mddev); diff --git a/drivers/md/raid1.c b/drivers/md/raid1.c index af5056d56878..e1a7e3d4c5e4 100644 --- a/drivers/md/raid1.c +++ b/drivers/md/raid1.c @@ -3063,6 +3063,8 @@ static int raid1_run(struct mddev *mddev) mdname(mddev)); return -EIO; } + if (mddev_init_writes_pending(mddev) < 0) + return -ENOMEM; /* * copy the already verified devices into our private RAID1 * bookkeeping area. [whatever we allocate in run(), diff --git a/drivers/md/raid10.c b/drivers/md/raid10.c index 4343d7ff9916..797ed60abd5e 100644 --- a/drivers/md/raid10.c +++ b/drivers/md/raid10.c @@ -3611,6 +3611,9 @@ static int raid10_run(struct mddev *mddev) int first = 1; bool discard_supported = false; + if (mddev_init_writes_pending(mddev) < 0) + return -ENOMEM; + if (mddev->private == NULL) { conf = setup_conf(mddev); if (IS_ERR(conf)) diff --git a/drivers/md/raid5.c b/drivers/md/raid5.c index 722064689e82..ec0f951ae19f 100644 --- a/drivers/md/raid5.c +++ b/drivers/md/raid5.c @@ -7118,6 +7118,9 @@ static int raid5_run(struct mddev *mddev) long long min_offset_diff = 0; int first = 1; + if (mddev_init_writes_pending(mddev) < 0) + return -ENOMEM; + if (mddev->recovery_cp != MaxSector) pr_notice("md/raid:%s: not clean -- starting background reconstruction\n", mdname(mddev)); |