History

[SCSI] block: add support for shared tag maps

The current block queue implementation already contains most of the machinery for shared tag maps. The only remaining pieces are a way to allocate and destroy a tag map independently of the queues (so that the maps can be managed on the life cycle of the overseeing entity)

James Bottomley committed 20 years ago

Commit 492dfb41 parent f19eaa72 files · +90 −21Browse files

Unified · Split

2 files
  1. block/ll_rw_blk.c +88 −21
  2. include/linux/blkdev.h +2 −0
block/ll_rw_blk.c+88−21
@@ -848,21 +848,18 @@ struct request *blk_queue_find_tag(request_queue_t *q, int tag) · 847 unmodified lines
848EXPORT_SYMBOL(blk_queue_find_tag);848EXPORT_SYMBOL(blk_queue_find_tag);
849 849
850/**850/**
851 * __blk_queue_free_tags - release tag maintenance info851 * __blk_free_tags - release a given set of tag maintenance info
852 * @q: the request queue for the device852 * @bqt: the tag map to free
853 *853 *
854 * Notes:854 * Tries to free the specified @bqt@. Returns true if it was
855 * blk_cleanup_queue() will take care of calling this function, if tagging855 * actually freed and false if there are still references using it
856 * has been used. So there's no need to call this directly.856 */
857 **/857static int __blk_free_tags(struct blk_queue_tag *bqt)
858static void __blk_queue_free_tags(request_queue_t *q)
859{858{
860 struct blk_queue_tag *bqt = q->queue_tags;859 int retval;
861
862 if (!bqt)
863 return;
864 860
865 if (atomic_dec_and_test(&bqt->refcnt)) {861 retval = atomic_dec_and_test(&bqt->refcnt);
862 if (retval) {
866 BUG_ON(bqt->busy);863 BUG_ON(bqt->busy);
867 BUG_ON(!list_empty(&bqt->busy_list));864 BUG_ON(!list_empty(&bqt->busy_list));
868 865
@@ -873,12 +870,49 @@ static void __blk_queue_free_tags(request_queue_t *q) · 4 unmodified lines
873 bqt->tag_map = NULL;870 bqt->tag_map = NULL;
874 871
875 kfree(bqt);872 kfree(bqt);
873
876 }874 }
877 875
876 return retval;
877}
878
879/**
880 * __blk_queue_free_tags - release tag maintenance info
881 * @q: the request queue for the device
882 *
883 * Notes:
884 * blk_cleanup_queue() will take care of calling this function, if tagging
885 * has been used. So there's no need to call this directly.
886 **/
887static void __blk_queue_free_tags(request_queue_t *q)
888{
889 struct blk_queue_tag *bqt = q->queue_tags;
890
891 if (!bqt)
892 return;
893
894 __blk_free_tags(bqt);
895
878 q->queue_tags = NULL;896 q->queue_tags = NULL;
879 q->queue_flags &= ~(1 << QUEUE_FLAG_QUEUED);897 q->queue_flags &= ~(1 << QUEUE_FLAG_QUEUED);
880}898}
881 899
900
901/**
902 * blk_free_tags - release a given set of tag maintenance info
903 * @bqt: the tag map to free
904 *
905 * For externally managed @bqt@ frees the map. Callers of this
906 * function must guarantee to have released all the queues that
907 * might have been using this tag map.
908 */
909void blk_free_tags(struct blk_queue_tag *bqt)
910{
911 if (unlikely(!__blk_free_tags(bqt)))
912 BUG();
913}
914EXPORT_SYMBOL(blk_free_tags);
915
882/**916/**
883 * blk_queue_free_tags - release tag maintenance info917 * blk_queue_free_tags - release tag maintenance info
884 * @q: the request queue for the device918 * @q: the request queue for the device
@@ -901,7 +935,7 @@ init_tag_map(request_queue_t *q, struct blk_queue_tag *tags, int depth) · 16 unmodified lines
901 unsigned long *tag_map;935 unsigned long *tag_map;
902 int nr_ulongs;936 int nr_ulongs;
903 937
904 if (depth > q->nr_requests * 2) {938 if (q && depth > q->nr_requests * 2) {
905 depth = q->nr_requests * 2;939 depth = q->nr_requests * 2;
906 printk(KERN_ERR "%s: adjusted depth to %d\n",940 printk(KERN_ERR "%s: adjusted depth to %d\n",
907 __FUNCTION__, depth);941 __FUNCTION__, depth);
@@ -927,6 +961,38 @@ fail: · 19 unmodified lines
927 return -ENOMEM;961 return -ENOMEM;
928}962}
929 963
964static struct blk_queue_tag *__blk_queue_init_tags(struct request_queue *q,
965 int depth)
966{
967 struct blk_queue_tag *tags;
968
969 tags = kmalloc(sizeof(struct blk_queue_tag), GFP_ATOMIC);
970 if (!tags)
971 goto fail;
972
973 if (init_tag_map(q, tags, depth))
974 goto fail;
975
976 INIT_LIST_HEAD(&tags->busy_list);
977 tags->busy = 0;
978 atomic_set(&tags->refcnt, 1);
979 return tags;
980fail:
981 kfree(tags);
982 return NULL;
983}
984
985/**
986 * blk_init_tags - initialize the tag info for an external tag map
987 * @depth: the maximum queue depth supported
988 * @tags: the tag to use
989 **/
990struct blk_queue_tag *blk_init_tags(int depth)
991{
992 return __blk_queue_init_tags(NULL, depth);
993}
994EXPORT_SYMBOL(blk_init_tags);
995
930/**996/**
931 * blk_queue_init_tags - initialize the queue tag info997 * blk_queue_init_tags - initialize the queue tag info
932 * @q: the request queue for the device998 * @q: the request queue for the device
@@ -941,16 +1007,10 @@ int blk_queue_init_tags(request_queue_t *q, int depth, · 8 unmodified lines
941 BUG_ON(tags && q->queue_tags && tags != q->queue_tags);1007 BUG_ON(tags && q->queue_tags && tags != q->queue_tags);
942 1008
943 if (!tags && !q->queue_tags) {1009 if (!tags && !q->queue_tags) {
944 tags = kmalloc(sizeof(struct blk_queue_tag), GFP_ATOMIC);1010 tags = __blk_queue_init_tags(q, depth);
945 if (!tags)
946 goto fail;
947 1011
948 if (init_tag_map(q, tags, depth))1012 if (!tags)
949 goto fail;1013 goto fail;
950
951 INIT_LIST_HEAD(&tags->busy_list);
952 tags->busy = 0;
953 atomic_set(&tags->refcnt, 1);
954 } else if (q->queue_tags) {1014 } else if (q->queue_tags) {
955 if ((rc = blk_queue_resize_tags(q, depth)))1015 if ((rc = blk_queue_resize_tags(q, depth)))
956 return rc;1016 return rc;
@@ -1001,6 +1061,13 @@ int blk_queue_resize_tags(request_queue_t *q, int new_depth) · 44 unmodified lines
1001 return 0;1061 return 0;
1002 }1062 }
1003 1063
1064 /*
1065 * Currently cannot replace a shared tag map with a new
1066 * one, so error out if this is the case
1067 */
1068 if (atomic_read(&bqt->refcnt) != 1)
1069 return -EBUSY;
1070
1004 /*1071 /*
1005 * save the old state info, so we can copy it back1072 * save the old state info, so we can copy it back
1006 */1073 */
include/linux/blkdev.h+2−0
@@ -746,6 +746,8 @@ extern void blk_queue_free_tags(request_queue_t *); · 745 unmodified lines
746extern int blk_queue_resize_tags(request_queue_t *, int);746extern int blk_queue_resize_tags(request_queue_t *, int);
747extern void blk_queue_invalidate_tags(request_queue_t *);747extern void blk_queue_invalidate_tags(request_queue_t *);
748extern long blk_congestion_wait(int rw, long timeout);748extern long blk_congestion_wait(int rw, long timeout);
749extern struct blk_queue_tag *blk_init_tags(int);
750extern void blk_free_tags(struct blk_queue_tag *);
749 751
750extern void blk_rq_bio_prep(request_queue_t *, struct request *, struct bio *);752extern void blk_rq_bio_prep(request_queue_t *, struct request *, struct bio *);
751extern int blkdev_issue_flush(struct block_device *, sector_t *);753extern int blkdev_issue_flush(struct block_device *, sector_t *);