From: Greg Kroah-Hartman Date: Tue, 29 Jul 2014 00:30:46 +0000 (-0700) Subject: 3.4-stable patches X-Git-Tag: v3.15.8~29 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=7743a1f4a9b876e9179584896d576dd5e9022a3c;p=thirdparty%2Fkernel%2Fstable-queue.git 3.4-stable patches added patches: block-don-t-assume-last-put-of-shared-tags-is-for-the-host.patch --- diff --git a/queue-3.4/block-don-t-assume-last-put-of-shared-tags-is-for-the-host.patch b/queue-3.4/block-don-t-assume-last-put-of-shared-tags-is-for-the-host.patch new file mode 100644 index 00000000000..433a2235f93 --- /dev/null +++ b/queue-3.4/block-don-t-assume-last-put-of-shared-tags-is-for-the-host.patch @@ -0,0 +1,90 @@ +From d45b3279a5a2252cafcd665bbf2db8c9b31ef783 Mon Sep 17 00:00:00 2001 +From: Christoph Hellwig +Date: Tue, 8 Jul 2014 12:25:28 +0200 +Subject: block: don't assume last put of shared tags is for the host + +From: Christoph Hellwig + +commit d45b3279a5a2252cafcd665bbf2db8c9b31ef783 upstream. + +There is no inherent reason why the last put of a tag structure must be +the one for the Scsi_Host, as device model objects can be held for +arbitrary periods. Merge blk_free_tags and __blk_free_tags into a single +funtion that just release a references and get rid of the BUG() when the +host reference wasn't the last. + +Signed-off-by: Christoph Hellwig +Signed-off-by: Jens Axboe +Signed-off-by: Greg Kroah-Hartman + +--- + block/blk-tag.c | 33 +++++++-------------------------- + 1 file changed, 7 insertions(+), 26 deletions(-) + +--- a/block/blk-tag.c ++++ b/block/blk-tag.c +@@ -27,18 +27,15 @@ struct request *blk_queue_find_tag(struc + EXPORT_SYMBOL(blk_queue_find_tag); + + /** +- * __blk_free_tags - release a given set of tag maintenance info ++ * blk_free_tags - release a given set of tag maintenance info + * @bqt: the tag map to free + * +- * Tries to free the specified @bqt. Returns true if it was +- * actually freed and false if there are still references using it ++ * Drop the reference count on @bqt and frees it when the last reference ++ * is dropped. + */ +-static int __blk_free_tags(struct blk_queue_tag *bqt) ++void blk_free_tags(struct blk_queue_tag *bqt) + { +- int retval; +- +- retval = atomic_dec_and_test(&bqt->refcnt); +- if (retval) { ++ if (atomic_dec_and_test(&bqt->refcnt)) { + BUG_ON(find_first_bit(bqt->tag_map, bqt->max_depth) < + bqt->max_depth); + +@@ -50,9 +47,8 @@ static int __blk_free_tags(struct blk_qu + + kfree(bqt); + } +- +- return retval; + } ++EXPORT_SYMBOL(blk_free_tags); + + /** + * __blk_queue_free_tags - release tag maintenance info +@@ -69,28 +65,13 @@ void __blk_queue_free_tags(struct reques + if (!bqt) + return; + +- __blk_free_tags(bqt); ++ blk_free_tags(bqt); + + q->queue_tags = NULL; + queue_flag_clear_unlocked(QUEUE_FLAG_QUEUED, q); + } + + /** +- * blk_free_tags - release a given set of tag maintenance info +- * @bqt: the tag map to free +- * +- * For externally managed @bqt frees the map. Callers of this +- * function must guarantee to have released all the queues that +- * might have been using this tag map. +- */ +-void blk_free_tags(struct blk_queue_tag *bqt) +-{ +- if (unlikely(!__blk_free_tags(bqt))) +- BUG(); +-} +-EXPORT_SYMBOL(blk_free_tags); +- +-/** + * blk_queue_free_tags - release tag maintenance info + * @q: the request queue for the device + *