Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit d45b3279 authored by Christoph Hellwig's avatar Christoph Hellwig Committed by Jens Axboe
Browse files

block: don't assume last put of shared tags is for the host



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: default avatarChristoph Hellwig <hch@lst.de>
Cc: stable@kernel.org
Signed-off-by: default avatarJens Axboe <axboe@fb.com>
parent 448bfad8
Loading
Loading
Loading
Loading
+7 −26
Original line number Original line Diff line number Diff line
@@ -27,18 +27,15 @@ struct request *blk_queue_find_tag(struct request_queue *q, int tag)
EXPORT_SYMBOL(blk_queue_find_tag);
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
 * @bqt:	the tag map to free
 *
 *
 * Tries to free the specified @bqt.  Returns true if it was
 * Drop the reference count on @bqt and frees it when the last reference
 * actually freed and false if there are still references using it
 * is dropped.
 */
 */
static int __blk_free_tags(struct blk_queue_tag *bqt)
void blk_free_tags(struct blk_queue_tag *bqt)
{
{
	int retval;
	if (atomic_dec_and_test(&bqt->refcnt)) {

	retval = atomic_dec_and_test(&bqt->refcnt);
	if (retval) {
		BUG_ON(find_first_bit(bqt->tag_map, bqt->max_depth) <
		BUG_ON(find_first_bit(bqt->tag_map, bqt->max_depth) <
							bqt->max_depth);
							bqt->max_depth);


@@ -50,9 +47,8 @@ static int __blk_free_tags(struct blk_queue_tag *bqt)


		kfree(bqt);
		kfree(bqt);
	}
	}

	return retval;
}
}
EXPORT_SYMBOL(blk_free_tags);


/**
/**
 * __blk_queue_free_tags - release tag maintenance info
 * __blk_queue_free_tags - release tag maintenance info
@@ -69,27 +65,12 @@ void __blk_queue_free_tags(struct request_queue *q)
	if (!bqt)
	if (!bqt)
		return;
		return;


	__blk_free_tags(bqt);
	blk_free_tags(bqt);


	q->queue_tags = NULL;
	q->queue_tags = NULL;
	queue_flag_clear_unlocked(QUEUE_FLAG_QUEUED, q);
	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
 * blk_queue_free_tags - release tag maintenance info
 * @q:  the request queue for the device
 * @q:  the request queue for the device