From: Greg Kroah-Hartman Date: Tue, 18 Jul 2017 09:12:36 +0000 (+0200) Subject: 4.11-stable patches X-Git-Tag: v4.12.3~25 X-Git-Url: http://git.ipfire.org/gitweb.cgi?a=commitdiff_plain;h=b257c5bad435c4c5ed0e8346dbb545fef574d545;p=thirdparty%2Fkernel%2Fstable-queue.git 4.11-stable patches added patches: block-fix-a-blk_exit_rl-regression.patch --- diff --git a/queue-4.11/block-fix-a-blk_exit_rl-regression.patch b/queue-4.11/block-fix-a-blk_exit_rl-regression.patch new file mode 100644 index 00000000000..e137bf8d021 --- /dev/null +++ b/queue-4.11/block-fix-a-blk_exit_rl-regression.patch @@ -0,0 +1,114 @@ +From dc9edc44de6cd7cc8cc7f5b36c1adb221eda3207 Mon Sep 17 00:00:00 2001 +From: Bart Van Assche +Date: Wed, 14 Jun 2017 13:27:50 -0600 +Subject: block: Fix a blk_exit_rl() regression + +From: Bart Van Assche + +commit dc9edc44de6cd7cc8cc7f5b36c1adb221eda3207 upstream. + +Avoid that the following complaint is reported: + + BUG: sleeping function called from invalid context at kernel/workqueue.c:2790 + in_atomic(): 1, irqs_disabled(): 0, pid: 41, name: rcuop/3 + 1 lock held by rcuop/3/41: + #0: (rcu_callback){......}, at: [] rcu_nocb_kthread+0x282/0x500 + Call Trace: + dump_stack+0x86/0xcf + ___might_sleep+0x174/0x260 + __might_sleep+0x4a/0x80 + flush_work+0x7e/0x2e0 + __cancel_work_timer+0x143/0x1c0 + cancel_work_sync+0x10/0x20 + blk_throtl_exit+0x25/0x60 + blkcg_exit_queue+0x35/0x40 + blk_release_queue+0x42/0x130 + kobject_put+0xa9/0x190 + +This happens since we invoke callbacks that need to block from the +queue release handler. Fix this by pushing the final release to +a workqueue. + +Reported-by: Ross Zwisler +Fixes: commit b425e5049258 ("block: Avoid that blk_exit_rl() triggers a use-after-free") +Signed-off-by: Bart Van Assche +Tested-by: Ross Zwisler +Signed-off-by: Greg Kroah-Hartman +Updated changelog +Signed-off-by: Jens Axboe +Cc: Laura Abbott +Signed-off-by: Greg Kroah-Hartman + + +--- + block/blk-sysfs.c | 34 ++++++++++++++++++++++------------ + include/linux/blkdev.h | 2 ++ + 2 files changed, 24 insertions(+), 12 deletions(-) + +--- a/block/blk-sysfs.c ++++ b/block/blk-sysfs.c +@@ -791,24 +791,25 @@ static void blk_free_queue_rcu(struct rc + } + + /** +- * blk_release_queue: - release a &struct request_queue when it is no longer needed +- * @kobj: the kobj belonging to the request queue to be released ++ * __blk_release_queue - release a request queue when it is no longer needed ++ * @work: pointer to the release_work member of the request queue to be released + * + * Description: +- * blk_release_queue is the pair to blk_init_queue() or +- * blk_queue_make_request(). It should be called when a request queue is +- * being released; typically when a block device is being de-registered. +- * Currently, its primary task it to free all the &struct request +- * structures that were allocated to the queue and the queue itself. ++ * blk_release_queue is the counterpart of blk_init_queue(). It should be ++ * called when a request queue is being released; typically when a block ++ * device is being de-registered. Its primary task it to free the queue ++ * itself. + * +- * Note: ++ * Notes: + * The low level driver must have finished any outstanding requests first + * via blk_cleanup_queue(). +- **/ +-static void blk_release_queue(struct kobject *kobj) ++ * ++ * Although blk_release_queue() may be called with preemption disabled, ++ * __blk_release_queue() may sleep. ++ */ ++static void __blk_release_queue(struct work_struct *work) + { +- struct request_queue *q = +- container_of(kobj, struct request_queue, kobj); ++ struct request_queue *q = container_of(work, typeof(*q), release_work); + + wbt_exit(q); + bdi_put(q->backing_dev_info); +@@ -844,6 +845,15 @@ static void blk_release_queue(struct kob + call_rcu(&q->rcu_head, blk_free_queue_rcu); + } + ++static void blk_release_queue(struct kobject *kobj) ++{ ++ struct request_queue *q = ++ container_of(kobj, struct request_queue, kobj); ++ ++ INIT_WORK(&q->release_work, __blk_release_queue); ++ schedule_work(&q->release_work); ++} ++ + static const struct sysfs_ops queue_sysfs_ops = { + .show = queue_attr_show, + .store = queue_attr_store, +--- a/include/linux/blkdev.h ++++ b/include/linux/blkdev.h +@@ -580,6 +580,8 @@ struct request_queue { + + size_t cmd_size; + void *rq_alloc_data; ++ ++ struct work_struct release_work; + }; + + #define QUEUE_FLAG_QUEUED 1 /* uses generic tag queueing */ diff --git a/queue-4.11/series b/queue-4.11/series index 4ceac0b4c24..f4f7616d9c2 100644 --- a/queue-4.11/series +++ b/queue-4.11/series @@ -32,3 +32,4 @@ adding-asm-prototypes.h-for-genksyms-to-generate-crc.patch sed-regex-in-makefile.build-requires-line-break-between-exported-symbols.patch adding-the-type-of-exported-symbols.patch sparc64-fix-gup_huge_pmd.patch +block-fix-a-blk_exit_rl-regression.patch