Hi,

On 07/03/2014 08:01 AM, Christoph Hellwig wrote:
> Hi Hans,
> 
> please test the path below:

Note, I did a similar patch a while back, but then it was decided to
try and fix the tear-down ordering instead (which seems to have not
completely fixed the issue).

I've just tested this patch and it indeed fixes this. Note if we go
with this fix for 3.16, it should get a CC: stable for 3.15, as
3.15 is affected too.

Thanks,

Hans


> 
> ---
> From: Christoph Hellwig <h...@lst.de>
> Subject: 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: Christoph Hellwig <h...@lst.de>
> 
> diff --git a/block/blk-tag.c b/block/blk-tag.c
> index 3f33d86..a185b86 100644
> --- a/block/blk-tag.c
> +++ b/block/blk-tag.c
> @@ -27,18 +27,15 @@ struct request *blk_queue_find_tag(struct request_queue 
> *q, int 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
>   *
> - * 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_queue_tag *bqt)
>  
>               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 request_queue *q)
>       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
>   *
> 
--
To unsubscribe from this list: send the line "unsubscribe linux-scsi" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

Reply via email to