stable.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
From: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
To: linux-kernel@vger.kernel.org
Cc: Greg Kroah-Hartman <gregkh@linuxfoundation.org>,
	stable@vger.kernel.org, Jianpeng Ma <majianpeng@gmail.com>,
	Jens Axboe <axboe@kernel.dk>,
	Jonghwan Choi <jhbird.choi@samsung.com>
Subject: [ 08/45] elevator: Fix a race in elevator switching
Date: Sun, 18 Aug 2013 13:35:57 -0700	[thread overview]
Message-ID: <20130818203621.572412448@linuxfoundation.org> (raw)
In-Reply-To: <20130818203620.996166594@linuxfoundation.org>

3.10-stable review patch.  If anyone has any objections, please let me know.

------------------

From: Jianpeng Ma <majianpeng@gmail.com>

commit d50235b7bc3ee0a0427984d763ea7534149531b4 upstream.

There's a race between elevator switching and normal io operation.
    Because the allocation of struct elevator_queue and struct elevator_data
    don't in a atomic operation.So there are have chance to use NULL
    ->elevator_data.
    For example:
        Thread A:                               Thread B
        blk_queu_bio                            elevator_switch
        spin_lock_irq(q->queue_block)           elevator_alloc
        elv_merge                               elevator_init_fn

    Because call elevator_alloc, it can't hold queue_lock and the
    ->elevator_data is NULL.So at the same time, threadA call elv_merge and
    nedd some info of elevator_data.So the crash happened.

    Move the elevator_alloc into func elevator_init_fn, it make the
    operations in a atomic operation.

    Using the follow method can easy reproduce this bug
    1:dd if=/dev/sdb of=/dev/null
    2:while true;do echo noop > scheduler;echo deadline > scheduler;done

    The test method also use this method.

Signed-off-by: Jianpeng Ma <majianpeng@gmail.com>
Signed-off-by: Jens Axboe <axboe@kernel.dk>
Cc: Jonghwan Choi <jhbird.choi@samsung.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>

---
 block/cfq-iosched.c      |   17 ++++++++++++++---
 block/deadline-iosched.c |   16 +++++++++++++---
 block/elevator.c         |   25 +++++--------------------
 block/noop-iosched.c     |   17 ++++++++++++++---
 include/linux/elevator.h |    6 +++++-
 5 files changed, 51 insertions(+), 30 deletions(-)

--- a/block/cfq-iosched.c
+++ b/block/cfq-iosched.c
@@ -4347,18 +4347,28 @@ static void cfq_exit_queue(struct elevat
 	kfree(cfqd);
 }
 
-static int cfq_init_queue(struct request_queue *q)
+static int cfq_init_queue(struct request_queue *q, struct elevator_type *e)
 {
 	struct cfq_data *cfqd;
 	struct blkcg_gq *blkg __maybe_unused;
 	int i, ret;
+	struct elevator_queue *eq;
+
+	eq = elevator_alloc(q, e);
+	if (!eq)
+		return -ENOMEM;
 
 	cfqd = kmalloc_node(sizeof(*cfqd), GFP_KERNEL | __GFP_ZERO, q->node);
-	if (!cfqd)
+	if (!cfqd) {
+		kobject_put(&eq->kobj);
 		return -ENOMEM;
+	}
+	eq->elevator_data = cfqd;
 
 	cfqd->queue = q;
-	q->elevator->elevator_data = cfqd;
+	spin_lock_irq(q->queue_lock);
+	q->elevator = eq;
+	spin_unlock_irq(q->queue_lock);
 
 	/* Init root service tree */
 	cfqd->grp_service_tree = CFQ_RB_ROOT;
@@ -4433,6 +4443,7 @@ static int cfq_init_queue(struct request
 
 out_free:
 	kfree(cfqd);
+	kobject_put(&eq->kobj);
 	return ret;
 }
 
--- a/block/deadline-iosched.c
+++ b/block/deadline-iosched.c
@@ -337,13 +337,21 @@ static void deadline_exit_queue(struct e
 /*
  * initialize elevator private data (deadline_data).
  */
-static int deadline_init_queue(struct request_queue *q)
+static int deadline_init_queue(struct request_queue *q, struct elevator_type *e)
 {
 	struct deadline_data *dd;
+	struct elevator_queue *eq;
+
+	eq = elevator_alloc(q, e);
+	if (!eq)
+		return -ENOMEM;
 
 	dd = kmalloc_node(sizeof(*dd), GFP_KERNEL | __GFP_ZERO, q->node);
-	if (!dd)
+	if (!dd) {
+		kobject_put(&eq->kobj);
 		return -ENOMEM;
+	}
+	eq->elevator_data = dd;
 
 	INIT_LIST_HEAD(&dd->fifo_list[READ]);
 	INIT_LIST_HEAD(&dd->fifo_list[WRITE]);
@@ -355,7 +363,9 @@ static int deadline_init_queue(struct re
 	dd->front_merges = 1;
 	dd->fifo_batch = fifo_batch;
 
-	q->elevator->elevator_data = dd;
+	spin_lock_irq(q->queue_lock);
+	q->elevator = eq;
+	spin_unlock_irq(q->queue_lock);
 	return 0;
 }
 
--- a/block/elevator.c
+++ b/block/elevator.c
@@ -150,7 +150,7 @@ void __init load_default_elevator_module
 
 static struct kobj_type elv_ktype;
 
-static struct elevator_queue *elevator_alloc(struct request_queue *q,
+struct elevator_queue *elevator_alloc(struct request_queue *q,
 				  struct elevator_type *e)
 {
 	struct elevator_queue *eq;
@@ -170,6 +170,7 @@ err:
 	elevator_put(e);
 	return NULL;
 }
+EXPORT_SYMBOL(elevator_alloc);
 
 static void elevator_release(struct kobject *kobj)
 {
@@ -221,16 +222,7 @@ int elevator_init(struct request_queue *
 		}
 	}
 
-	q->elevator = elevator_alloc(q, e);
-	if (!q->elevator)
-		return -ENOMEM;
-
-	err = e->ops.elevator_init_fn(q);
-	if (err) {
-		kobject_put(&q->elevator->kobj);
-		return err;
-	}
-
+	err = e->ops.elevator_init_fn(q, e);
 	return 0;
 }
 EXPORT_SYMBOL(elevator_init);
@@ -935,17 +927,10 @@ static int elevator_switch(struct reques
 	spin_unlock_irq(q->queue_lock);
 
 	/* allocate, init and register new elevator */
-	err = -ENOMEM;
-	q->elevator = elevator_alloc(q, new_e);
-	if (!q->elevator)
+	err = new_e->ops.elevator_init_fn(q, new_e);
+	if (err)
 		goto fail_init;
 
-	err = new_e->ops.elevator_init_fn(q);
-	if (err) {
-		kobject_put(&q->elevator->kobj);
-		goto fail_init;
-	}
-
 	if (registered) {
 		err = elv_register_queue(q);
 		if (err)
--- a/block/noop-iosched.c
+++ b/block/noop-iosched.c
@@ -59,16 +59,27 @@ noop_latter_request(struct request_queue
 	return list_entry(rq->queuelist.next, struct request, queuelist);
 }
 
-static int noop_init_queue(struct request_queue *q)
+static int noop_init_queue(struct request_queue *q, struct elevator_type *e)
 {
 	struct noop_data *nd;
+	struct elevator_queue *eq;
+
+	eq = elevator_alloc(q, e);
+	if (!eq)
+		return -ENOMEM;
 
 	nd = kmalloc_node(sizeof(*nd), GFP_KERNEL, q->node);
-	if (!nd)
+	if (!nd) {
+		kobject_put(&eq->kobj);
 		return -ENOMEM;
+	}
+	eq->elevator_data = nd;
 
 	INIT_LIST_HEAD(&nd->queue);
-	q->elevator->elevator_data = nd;
+
+	spin_lock_irq(q->queue_lock);
+	q->elevator = eq;
+	spin_unlock_irq(q->queue_lock);
 	return 0;
 }
 
--- a/include/linux/elevator.h
+++ b/include/linux/elevator.h
@@ -7,6 +7,7 @@
 #ifdef CONFIG_BLOCK
 
 struct io_cq;
+struct elevator_type;
 
 typedef int (elevator_merge_fn) (struct request_queue *, struct request **,
 				 struct bio *);
@@ -35,7 +36,8 @@ typedef void (elevator_put_req_fn) (stru
 typedef void (elevator_activate_req_fn) (struct request_queue *, struct request *);
 typedef void (elevator_deactivate_req_fn) (struct request_queue *, struct request *);
 
-typedef int (elevator_init_fn) (struct request_queue *);
+typedef int (elevator_init_fn) (struct request_queue *,
+				struct elevator_type *e);
 typedef void (elevator_exit_fn) (struct elevator_queue *);
 
 struct elevator_ops
@@ -155,6 +157,8 @@ extern int elevator_init(struct request_
 extern void elevator_exit(struct elevator_queue *);
 extern int elevator_change(struct request_queue *, const char *);
 extern bool elv_rq_merge_ok(struct request *, struct bio *);
+extern struct elevator_queue *elevator_alloc(struct request_queue *,
+					struct elevator_type *);
 
 /*
  * Helper functions.



  parent reply	other threads:[~2013-08-18 20:35 UTC|newest]

Thread overview: 55+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2013-08-18 20:35 [ 00/45] 3.10.8-stable review Greg Kroah-Hartman
2013-08-18 20:35 ` [ 01/45] perf/x86: Fix intel QPI uncore event definitions Greg Kroah-Hartman
2013-08-18 20:35 ` [ 02/45] perf/arm: Fix armpmu_map_hw_event() Greg Kroah-Hartman
2013-08-18 20:35 ` [ 03/45] memcg: dont initialize kmem-cache destroying work for root caches Greg Kroah-Hartman
2013-08-18 20:35 ` [ 04/45] microblaze: fix clone syscall Greg Kroah-Hartman
2013-08-18 20:35 ` [ 05/45] x86 get_unmapped_area(): use proper mmap base for bottom-up direction Greg Kroah-Hartman
2013-08-18 20:35 ` [ 06/45] fs/proc/task_mmu.c: fix buffer overflow in add_page_map() Greg Kroah-Hartman
2013-08-18 20:35 ` [ 07/45] sched: Ensure update_cfs_shares() is called for parents of continuously-running tasks Greg Kroah-Hartman
2013-08-18 20:35 ` Greg Kroah-Hartman [this message]
2013-08-18 20:35 ` [ 09/45] ARM: KVM: perform save/restore of PAR Greg Kroah-Hartman
2013-08-18 20:35 ` [ 10/45] ARM: KVM: add missing dsb before invalidating Stage-2 TLBs Greg Kroah-Hartman
2013-08-18 20:36 ` [ 11/45] ARM: KVM: clear exclusive monitor on all exception returns Greg Kroah-Hartman
2013-08-18 20:36 ` [ 12/45] iwl4965: set power mode early Greg Kroah-Hartman
2013-08-18 20:36 ` [ 13/45] iwl4965: reset firmware after rfkill off Greg Kroah-Hartman
2013-08-18 20:36 ` [ 14/45] mac80211: ignore HT primary channel while connected Greg Kroah-Hartman
2013-08-18 20:36 ` [ 15/45] mac80211: fix infinite loop in ieee80211_determine_chantype Greg Kroah-Hartman
2013-08-18 20:36 ` [ 16/45] mac80211: continue using disabled channels while connected Greg Kroah-Hartman
2013-08-18 20:36 ` [ 17/45] can: pcan_usb: fix wrong memcpy() bytes length Greg Kroah-Hartman
2013-08-18 20:36 ` [ 18/45] genetlink: fix family dump race Greg Kroah-Hartman
2013-08-18 20:36 ` [ 19/45] cfg80211: fix P2P GO interface teardown Greg Kroah-Hartman
2013-08-18 20:36 ` [ 20/45] ASoC: dapm: Fix empty list check in dapm_new_mux() Greg Kroah-Hartman
2013-08-18 20:36 ` [ 21/45] ASoC: cs42l52: Reorder Min/Max and update to SX_TLV for Beep Volume Greg Kroah-Hartman
2013-08-18 20:36 ` [ 22/45] ASoC: tegra: fix Tegra30 I2S capture parameter setup Greg Kroah-Hartman
2013-08-18 20:36 ` [ 23/45] ALSA: usb-audio: Fix invalid volume resolution for Logitech HD Webcam C525 Greg Kroah-Hartman
2013-08-18 20:36 ` [ 24/45] ALSA: 6fire: make buffers DMA-able (pcm) Greg Kroah-Hartman
2013-08-18 20:36 ` [ 25/45] ALSA: 6fire: make buffers DMA-able (midi) Greg Kroah-Hartman
2013-08-18 20:36 ` [ 26/45] ALSA: hda - Fix missing mute controls for CX5051 Greg Kroah-Hartman
2013-08-18 20:36 ` [ 27/45] ALSA: hda - Add pinfix for LG LW25 laptop Greg Kroah-Hartman
2013-08-18 20:36 ` [ 28/45] ALSA: hda - Add a fixup for Gateway LT27 Greg Kroah-Hartman
2013-08-19 17:42   ` Nathanael D. Noblet
2013-08-19 17:48     ` Greg Kroah-Hartman
2013-08-19 18:10       ` Takashi Iwai
2013-08-18 20:36 ` [ 29/45] nl80211: fix another nl80211_fam.attrbuf race Greg Kroah-Hartman
2013-08-18 20:36 ` [ 30/45] usb: add two quirky touchscreen Greg Kroah-Hartman
2013-08-18 20:36 ` [ 31/45] USB: ti_usb_3410_5052: fix big-endian firmware handling Greg Kroah-Hartman
2013-08-18 20:36 ` [ 32/45] USB: mos7840: fix big-endian probe Greg Kroah-Hartman
2013-08-18 20:36 ` [ 33/45] USB: mos7720: fix broken control requests Greg Kroah-Hartman
2013-08-18 20:36 ` [ 34/45] USB: keyspan: fix null-deref at disconnect and release Greg Kroah-Hartman
2013-08-18 20:36 ` [ 35/45] USB: EHCI: accept very late isochronous URBs Greg Kroah-Hartman
2013-08-18 20:36 ` [ 36/45] USB-Serial: Fix error handling of usb_wwan Greg Kroah-Hartman
2013-08-18 20:36 ` [ 37/45] PM / QoS: Fix workqueue deadlock when using pm_qos_update_request_timeout() Greg Kroah-Hartman
2013-08-18 20:36 ` [ 38/45] wusbcore: fix kernel panic when disconnecting a wireless USB->serial device Greg Kroah-Hartman
2013-08-18 20:36 ` [ 39/45] Fix TLB gather virtual address range invalidation corner cases Greg Kroah-Hartman
2013-08-18 20:36 ` [ 40/45] ARM: 7809/1: perf: fix event validation for software group leaders Greg Kroah-Hartman
2013-08-18 20:36 ` [ 41/45] m68k: Truncate base in do_div() Greg Kroah-Hartman
2013-08-18 20:39   ` Geert Uytterhoeven
2013-08-18 20:50     ` Greg Kroah-Hartman
2013-08-18 20:36 ` [ 42/45] m68k/atari: ARAnyM - Fix NatFeat module support Greg Kroah-Hartman
2013-08-18 20:36 ` [ 43/45] s390: Fix broken build Greg Kroah-Hartman
2013-08-18 20:36 ` [ 44/45] jbd2: Fix use after free after error in jbd2_journal_dirty_metadata() Greg Kroah-Hartman
2013-08-18 20:36 ` [ 45/45] cpuset: fix the return value of cpuset_write_u64() Greg Kroah-Hartman
2013-08-19  1:43 ` [ 00/45] 3.10.8-stable review Guenter Roeck
2013-08-19  3:30   ` Greg Kroah-Hartman
2013-08-19 22:48 ` Shuah Khan
2013-08-19 23:11   ` Greg Kroah-Hartman

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20130818203621.572412448@linuxfoundation.org \
    --to=gregkh@linuxfoundation.org \
    --cc=axboe@kernel.dk \
    --cc=jhbird.choi@samsung.com \
    --cc=linux-kernel@vger.kernel.org \
    --cc=majianpeng@gmail.com \
    --cc=stable@vger.kernel.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).