forked from mirrors/linux
		
	scsi: target: Convert target drivers to use sbitmap
The sbitmap and the percpu_ida perform essentially the same task, allocating tags for commands. The sbitmap outperforms the percpu_ida as documented here: https://lkml.org/lkml/2014/4/22/553 The sbitmap interface is a little harder to use, but being able to remove the percpu_ida code and getting better performance justifies the additional complexity. Signed-off-by: Matthew Wilcox <willy@infradead.org> Acked-by: Felipe Balbi <felipe.balbi@linux.intel.com> # f_tcm Reviewed-by: Jens Axboe <axboe@kernel.dk> Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com>
This commit is contained in:
		
							parent
							
								
									83c2b54b92
								
							
						
					
					
						commit
						10e9cbb6b5
					
				
					 10 changed files with 59 additions and 24 deletions
				
			
		|  | @ -4277,9 +4277,9 @@ static struct qla_tgt_cmd *qlt_get_tag(scsi_qla_host_t *vha, | ||||||
| { | { | ||||||
| 	struct se_session *se_sess = sess->se_sess; | 	struct se_session *se_sess = sess->se_sess; | ||||||
| 	struct qla_tgt_cmd *cmd; | 	struct qla_tgt_cmd *cmd; | ||||||
| 	int tag; | 	int tag, cpu; | ||||||
| 
 | 
 | ||||||
| 	tag = percpu_ida_alloc(&se_sess->sess_tag_pool, TASK_RUNNING); | 	tag = sbitmap_queue_get(&se_sess->sess_tag_pool, &cpu); | ||||||
| 	if (tag < 0) | 	if (tag < 0) | ||||||
| 		return NULL; | 		return NULL; | ||||||
| 
 | 
 | ||||||
|  | @ -4292,6 +4292,7 @@ static struct qla_tgt_cmd *qlt_get_tag(scsi_qla_host_t *vha, | ||||||
| 	qlt_incr_num_pend_cmds(vha); | 	qlt_incr_num_pend_cmds(vha); | ||||||
| 	cmd->vha = vha; | 	cmd->vha = vha; | ||||||
| 	cmd->se_cmd.map_tag = tag; | 	cmd->se_cmd.map_tag = tag; | ||||||
|  | 	cmd->se_cmd.map_cpu = cpu; | ||||||
| 	cmd->sess = sess; | 	cmd->sess = sess; | ||||||
| 	cmd->loop_id = sess->loop_id; | 	cmd->loop_id = sess->loop_id; | ||||||
| 	cmd->conf_compl_supported = sess->conf_compl_supported; | 	cmd->conf_compl_supported = sess->conf_compl_supported; | ||||||
|  | @ -5294,7 +5295,7 @@ qlt_alloc_qfull_cmd(struct scsi_qla_host *vha, | ||||||
| 	struct fc_port *sess; | 	struct fc_port *sess; | ||||||
| 	struct se_session *se_sess; | 	struct se_session *se_sess; | ||||||
| 	struct qla_tgt_cmd *cmd; | 	struct qla_tgt_cmd *cmd; | ||||||
| 	int tag; | 	int tag, cpu; | ||||||
| 	unsigned long flags; | 	unsigned long flags; | ||||||
| 
 | 
 | ||||||
| 	if (unlikely(tgt->tgt_stop)) { | 	if (unlikely(tgt->tgt_stop)) { | ||||||
|  | @ -5326,7 +5327,7 @@ qlt_alloc_qfull_cmd(struct scsi_qla_host *vha, | ||||||
| 
 | 
 | ||||||
| 	se_sess = sess->se_sess; | 	se_sess = sess->se_sess; | ||||||
| 
 | 
 | ||||||
| 	tag = percpu_ida_alloc(&se_sess->sess_tag_pool, TASK_RUNNING); | 	tag = sbitmap_queue_get(&se_sess->sess_tag_pool, &cpu); | ||||||
| 	if (tag < 0) | 	if (tag < 0) | ||||||
| 		return; | 		return; | ||||||
| 
 | 
 | ||||||
|  | @ -5357,6 +5358,7 @@ qlt_alloc_qfull_cmd(struct scsi_qla_host *vha, | ||||||
| 	cmd->reset_count = ha->base_qpair->chip_reset; | 	cmd->reset_count = ha->base_qpair->chip_reset; | ||||||
| 	cmd->q_full = 1; | 	cmd->q_full = 1; | ||||||
| 	cmd->qpair = ha->base_qpair; | 	cmd->qpair = ha->base_qpair; | ||||||
|  | 	cmd->se_cmd.map_cpu = cpu; | ||||||
| 
 | 
 | ||||||
| 	if (qfull) { | 	if (qfull) { | ||||||
| 		cmd->q_full = 1; | 		cmd->q_full = 1; | ||||||
|  |  | ||||||
|  | @ -17,7 +17,7 @@ | ||||||
|  ******************************************************************************/ |  ******************************************************************************/ | ||||||
| 
 | 
 | ||||||
| #include <linux/list.h> | #include <linux/list.h> | ||||||
| #include <linux/percpu_ida.h> | #include <linux/sched/signal.h> | ||||||
| #include <net/ipv6.h>         /* ipv6_addr_equal() */ | #include <net/ipv6.h>         /* ipv6_addr_equal() */ | ||||||
| #include <scsi/scsi_tcq.h> | #include <scsi/scsi_tcq.h> | ||||||
| #include <scsi/iscsi_proto.h> | #include <scsi/iscsi_proto.h> | ||||||
|  | @ -147,6 +147,30 @@ void iscsit_free_r2ts_from_list(struct iscsi_cmd *cmd) | ||||||
| 	spin_unlock_bh(&cmd->r2t_lock); | 	spin_unlock_bh(&cmd->r2t_lock); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | static int iscsit_wait_for_tag(struct se_session *se_sess, int state, int *cpup) | ||||||
|  | { | ||||||
|  | 	int tag = -1; | ||||||
|  | 	DEFINE_WAIT(wait); | ||||||
|  | 	struct sbq_wait_state *ws; | ||||||
|  | 
 | ||||||
|  | 	if (state == TASK_RUNNING) | ||||||
|  | 		return tag; | ||||||
|  | 
 | ||||||
|  | 	ws = &se_sess->sess_tag_pool.ws[0]; | ||||||
|  | 	for (;;) { | ||||||
|  | 		prepare_to_wait_exclusive(&ws->wait, &wait, state); | ||||||
|  | 		if (signal_pending_state(state, current)) | ||||||
|  | 			break; | ||||||
|  | 		tag = sbitmap_queue_get(&se_sess->sess_tag_pool, cpup); | ||||||
|  | 		if (tag >= 0) | ||||||
|  | 			break; | ||||||
|  | 		schedule(); | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	finish_wait(&ws->wait, &wait); | ||||||
|  | 	return tag; | ||||||
|  | } | ||||||
|  | 
 | ||||||
| /*
 | /*
 | ||||||
|  * May be called from software interrupt (timer) context for allocating |  * May be called from software interrupt (timer) context for allocating | ||||||
|  * iSCSI NopINs. |  * iSCSI NopINs. | ||||||
|  | @ -155,9 +179,11 @@ struct iscsi_cmd *iscsit_allocate_cmd(struct iscsi_conn *conn, int state) | ||||||
| { | { | ||||||
| 	struct iscsi_cmd *cmd; | 	struct iscsi_cmd *cmd; | ||||||
| 	struct se_session *se_sess = conn->sess->se_sess; | 	struct se_session *se_sess = conn->sess->se_sess; | ||||||
| 	int size, tag; | 	int size, tag, cpu; | ||||||
| 
 | 
 | ||||||
| 	tag = percpu_ida_alloc(&se_sess->sess_tag_pool, state); | 	tag = sbitmap_queue_get(&se_sess->sess_tag_pool, &cpu); | ||||||
|  | 	if (tag < 0) | ||||||
|  | 		tag = iscsit_wait_for_tag(se_sess, state, &cpu); | ||||||
| 	if (tag < 0) | 	if (tag < 0) | ||||||
| 		return NULL; | 		return NULL; | ||||||
| 
 | 
 | ||||||
|  | @ -166,6 +192,7 @@ struct iscsi_cmd *iscsit_allocate_cmd(struct iscsi_conn *conn, int state) | ||||||
| 	memset(cmd, 0, size); | 	memset(cmd, 0, size); | ||||||
| 
 | 
 | ||||||
| 	cmd->se_cmd.map_tag = tag; | 	cmd->se_cmd.map_tag = tag; | ||||||
|  | 	cmd->se_cmd.map_cpu = cpu; | ||||||
| 	cmd->conn = conn; | 	cmd->conn = conn; | ||||||
| 	cmd->data_direction = DMA_NONE; | 	cmd->data_direction = DMA_NONE; | ||||||
| 	INIT_LIST_HEAD(&cmd->i_conn_node); | 	INIT_LIST_HEAD(&cmd->i_conn_node); | ||||||
|  |  | ||||||
|  | @ -926,15 +926,16 @@ static struct sbp_target_request *sbp_mgt_get_req(struct sbp_session *sess, | ||||||
| { | { | ||||||
| 	struct se_session *se_sess = sess->se_sess; | 	struct se_session *se_sess = sess->se_sess; | ||||||
| 	struct sbp_target_request *req; | 	struct sbp_target_request *req; | ||||||
| 	int tag; | 	int tag, cpu; | ||||||
| 
 | 
 | ||||||
| 	tag = percpu_ida_alloc(&se_sess->sess_tag_pool, TASK_RUNNING); | 	tag = sbitmap_queue_get(&se_sess->sess_tag_pool, &cpu); | ||||||
| 	if (tag < 0) | 	if (tag < 0) | ||||||
| 		return ERR_PTR(-ENOMEM); | 		return ERR_PTR(-ENOMEM); | ||||||
| 
 | 
 | ||||||
| 	req = &((struct sbp_target_request *)se_sess->sess_cmd_map)[tag]; | 	req = &((struct sbp_target_request *)se_sess->sess_cmd_map)[tag]; | ||||||
| 	memset(req, 0, sizeof(*req)); | 	memset(req, 0, sizeof(*req)); | ||||||
| 	req->se_cmd.map_tag = tag; | 	req->se_cmd.map_tag = tag; | ||||||
|  | 	req->se_cmd.map_cpu = cpu; | ||||||
| 	req->se_cmd.tag = next_orb; | 	req->se_cmd.tag = next_orb; | ||||||
| 
 | 
 | ||||||
| 	return req; | 	return req; | ||||||
|  |  | ||||||
|  | @ -260,7 +260,8 @@ int transport_alloc_session_tags(struct se_session *se_sess, | ||||||
| 		} | 		} | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	rc = percpu_ida_init(&se_sess->sess_tag_pool, tag_num); | 	rc = sbitmap_queue_init_node(&se_sess->sess_tag_pool, tag_num, -1, | ||||||
|  | 			false, GFP_KERNEL, NUMA_NO_NODE); | ||||||
| 	if (rc < 0) { | 	if (rc < 0) { | ||||||
| 		pr_err("Unable to init se_sess->sess_tag_pool," | 		pr_err("Unable to init se_sess->sess_tag_pool," | ||||||
| 			" tag_num: %u\n", tag_num); | 			" tag_num: %u\n", tag_num); | ||||||
|  | @ -547,7 +548,7 @@ void transport_free_session(struct se_session *se_sess) | ||||||
| 		target_put_nacl(se_nacl); | 		target_put_nacl(se_nacl); | ||||||
| 	} | 	} | ||||||
| 	if (se_sess->sess_cmd_map) { | 	if (se_sess->sess_cmd_map) { | ||||||
| 		percpu_ida_destroy(&se_sess->sess_tag_pool); | 		sbitmap_queue_free(&se_sess->sess_tag_pool); | ||||||
| 		kvfree(se_sess->sess_cmd_map); | 		kvfree(se_sess->sess_cmd_map); | ||||||
| 	} | 	} | ||||||
| 	kmem_cache_free(se_sess_cache, se_sess); | 	kmem_cache_free(se_sess_cache, se_sess); | ||||||
|  |  | ||||||
|  | @ -28,7 +28,6 @@ | ||||||
| #include <linux/configfs.h> | #include <linux/configfs.h> | ||||||
| #include <linux/ctype.h> | #include <linux/ctype.h> | ||||||
| #include <linux/hash.h> | #include <linux/hash.h> | ||||||
| #include <linux/percpu_ida.h> |  | ||||||
| #include <asm/unaligned.h> | #include <asm/unaligned.h> | ||||||
| #include <scsi/scsi_tcq.h> | #include <scsi/scsi_tcq.h> | ||||||
| #include <scsi/libfc.h> | #include <scsi/libfc.h> | ||||||
|  | @ -448,9 +447,9 @@ static void ft_recv_cmd(struct ft_sess *sess, struct fc_frame *fp) | ||||||
| 	struct ft_cmd *cmd; | 	struct ft_cmd *cmd; | ||||||
| 	struct fc_lport *lport = sess->tport->lport; | 	struct fc_lport *lport = sess->tport->lport; | ||||||
| 	struct se_session *se_sess = sess->se_sess; | 	struct se_session *se_sess = sess->se_sess; | ||||||
| 	int tag; | 	int tag, cpu; | ||||||
| 
 | 
 | ||||||
| 	tag = percpu_ida_alloc(&se_sess->sess_tag_pool, TASK_RUNNING); | 	tag = sbitmap_queue_get(&se_sess->sess_tag_pool, &cpu); | ||||||
| 	if (tag < 0) | 	if (tag < 0) | ||||||
| 		goto busy; | 		goto busy; | ||||||
| 
 | 
 | ||||||
|  | @ -458,6 +457,7 @@ static void ft_recv_cmd(struct ft_sess *sess, struct fc_frame *fp) | ||||||
| 	memset(cmd, 0, sizeof(struct ft_cmd)); | 	memset(cmd, 0, sizeof(struct ft_cmd)); | ||||||
| 
 | 
 | ||||||
| 	cmd->se_cmd.map_tag = tag; | 	cmd->se_cmd.map_tag = tag; | ||||||
|  | 	cmd->se_cmd.map_cpu = cpu; | ||||||
| 	cmd->sess = sess; | 	cmd->sess = sess; | ||||||
| 	cmd->seq = fc_seq_assign(lport, fp); | 	cmd->seq = fc_seq_assign(lport, fp); | ||||||
| 	if (!cmd->seq) { | 	if (!cmd->seq) { | ||||||
|  |  | ||||||
|  | @ -1071,15 +1071,16 @@ static struct usbg_cmd *usbg_get_cmd(struct f_uas *fu, | ||||||
| { | { | ||||||
| 	struct se_session *se_sess = tv_nexus->tvn_se_sess; | 	struct se_session *se_sess = tv_nexus->tvn_se_sess; | ||||||
| 	struct usbg_cmd *cmd; | 	struct usbg_cmd *cmd; | ||||||
| 	int tag; | 	int tag, cpu; | ||||||
| 
 | 
 | ||||||
| 	tag = percpu_ida_alloc(&se_sess->sess_tag_pool, TASK_RUNNING); | 	tag = sbitmap_queue_get(&se_sess->sess_tag_pool, &cpu); | ||||||
| 	if (tag < 0) | 	if (tag < 0) | ||||||
| 		return ERR_PTR(-ENOMEM); | 		return ERR_PTR(-ENOMEM); | ||||||
| 
 | 
 | ||||||
| 	cmd = &((struct usbg_cmd *)se_sess->sess_cmd_map)[tag]; | 	cmd = &((struct usbg_cmd *)se_sess->sess_cmd_map)[tag]; | ||||||
| 	memset(cmd, 0, sizeof(*cmd)); | 	memset(cmd, 0, sizeof(*cmd)); | ||||||
| 	cmd->se_cmd.map_tag = tag; | 	cmd->se_cmd.map_tag = tag; | ||||||
|  | 	cmd->se_cmd.map_cpu = cpu; | ||||||
| 	cmd->se_cmd.tag = cmd->tag = scsi_tag; | 	cmd->se_cmd.tag = cmd->tag = scsi_tag; | ||||||
| 	cmd->fu = fu; | 	cmd->fu = fu; | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -46,7 +46,6 @@ | ||||||
| #include <linux/virtio_scsi.h> | #include <linux/virtio_scsi.h> | ||||||
| #include <linux/llist.h> | #include <linux/llist.h> | ||||||
| #include <linux/bitmap.h> | #include <linux/bitmap.h> | ||||||
| #include <linux/percpu_ida.h> |  | ||||||
| 
 | 
 | ||||||
| #include "vhost.h" | #include "vhost.h" | ||||||
| 
 | 
 | ||||||
|  | @ -567,7 +566,7 @@ vhost_scsi_get_tag(struct vhost_virtqueue *vq, struct vhost_scsi_tpg *tpg, | ||||||
| 	struct se_session *se_sess; | 	struct se_session *se_sess; | ||||||
| 	struct scatterlist *sg, *prot_sg; | 	struct scatterlist *sg, *prot_sg; | ||||||
| 	struct page **pages; | 	struct page **pages; | ||||||
| 	int tag; | 	int tag, cpu; | ||||||
| 
 | 
 | ||||||
| 	tv_nexus = tpg->tpg_nexus; | 	tv_nexus = tpg->tpg_nexus; | ||||||
| 	if (!tv_nexus) { | 	if (!tv_nexus) { | ||||||
|  | @ -576,7 +575,7 @@ vhost_scsi_get_tag(struct vhost_virtqueue *vq, struct vhost_scsi_tpg *tpg, | ||||||
| 	} | 	} | ||||||
| 	se_sess = tv_nexus->tvn_se_sess; | 	se_sess = tv_nexus->tvn_se_sess; | ||||||
| 
 | 
 | ||||||
| 	tag = percpu_ida_alloc(&se_sess->sess_tag_pool, TASK_RUNNING); | 	tag = sbitmap_queue_get(&se_sess->sess_tag_pool, &cpu); | ||||||
| 	if (tag < 0) { | 	if (tag < 0) { | ||||||
| 		pr_err("Unable to obtain tag for vhost_scsi_cmd\n"); | 		pr_err("Unable to obtain tag for vhost_scsi_cmd\n"); | ||||||
| 		return ERR_PTR(-ENOMEM); | 		return ERR_PTR(-ENOMEM); | ||||||
|  | @ -591,6 +590,7 @@ vhost_scsi_get_tag(struct vhost_virtqueue *vq, struct vhost_scsi_tpg *tpg, | ||||||
| 	cmd->tvc_prot_sgl = prot_sg; | 	cmd->tvc_prot_sgl = prot_sg; | ||||||
| 	cmd->tvc_upages = pages; | 	cmd->tvc_upages = pages; | ||||||
| 	cmd->tvc_se_cmd.map_tag = tag; | 	cmd->tvc_se_cmd.map_tag = tag; | ||||||
|  | 	cmd->tvc_se_cmd.map_cpu = cpu; | ||||||
| 	cmd->tvc_tag = scsi_tag; | 	cmd->tvc_tag = scsi_tag; | ||||||
| 	cmd->tvc_lun = lun; | 	cmd->tvc_lun = lun; | ||||||
| 	cmd->tvc_task_attr = task_attr; | 	cmd->tvc_task_attr = task_attr; | ||||||
|  |  | ||||||
|  | @ -654,9 +654,9 @@ static struct vscsibk_pend *scsiback_get_pend_req(struct vscsiif_back_ring *ring | ||||||
| 	struct scsiback_nexus *nexus = tpg->tpg_nexus; | 	struct scsiback_nexus *nexus = tpg->tpg_nexus; | ||||||
| 	struct se_session *se_sess = nexus->tvn_se_sess; | 	struct se_session *se_sess = nexus->tvn_se_sess; | ||||||
| 	struct vscsibk_pend *req; | 	struct vscsibk_pend *req; | ||||||
| 	int tag, i; | 	int tag, cpu, i; | ||||||
| 
 | 
 | ||||||
| 	tag = percpu_ida_alloc(&se_sess->sess_tag_pool, TASK_RUNNING); | 	tag = sbitmap_queue_get(&se_sess->sess_tag_pool, &cpu); | ||||||
| 	if (tag < 0) { | 	if (tag < 0) { | ||||||
| 		pr_err("Unable to obtain tag for vscsiif_request\n"); | 		pr_err("Unable to obtain tag for vscsiif_request\n"); | ||||||
| 		return ERR_PTR(-ENOMEM); | 		return ERR_PTR(-ENOMEM); | ||||||
|  | @ -665,6 +665,7 @@ static struct vscsibk_pend *scsiback_get_pend_req(struct vscsiif_back_ring *ring | ||||||
| 	req = &((struct vscsibk_pend *)se_sess->sess_cmd_map)[tag]; | 	req = &((struct vscsibk_pend *)se_sess->sess_cmd_map)[tag]; | ||||||
| 	memset(req, 0, sizeof(*req)); | 	memset(req, 0, sizeof(*req)); | ||||||
| 	req->se_cmd.map_tag = tag; | 	req->se_cmd.map_tag = tag; | ||||||
|  | 	req->se_cmd.map_cpu = cpu; | ||||||
| 
 | 
 | ||||||
| 	for (i = 0; i < VSCSI_MAX_GRANTS; i++) | 	for (i = 0; i < VSCSI_MAX_GRANTS; i++) | ||||||
| 		req->grant_handles[i] = SCSIBACK_INVALID_HANDLE; | 		req->grant_handles[i] = SCSIBACK_INVALID_HANDLE; | ||||||
|  |  | ||||||
|  | @ -4,6 +4,7 @@ | ||||||
| 
 | 
 | ||||||
| #include <linux/dma-direction.h>     /* enum dma_data_direction */ | #include <linux/dma-direction.h>     /* enum dma_data_direction */ | ||||||
| #include <linux/list.h>              /* struct list_head */ | #include <linux/list.h>              /* struct list_head */ | ||||||
|  | #include <linux/sched.h> | ||||||
| #include <linux/socket.h>            /* struct sockaddr_storage */ | #include <linux/socket.h>            /* struct sockaddr_storage */ | ||||||
| #include <linux/types.h>             /* u8 */ | #include <linux/types.h>             /* u8 */ | ||||||
| #include <scsi/iscsi_proto.h>        /* itt_t */ | #include <scsi/iscsi_proto.h>        /* itt_t */ | ||||||
|  |  | ||||||
|  | @ -4,7 +4,7 @@ | ||||||
| 
 | 
 | ||||||
| #include <linux/configfs.h>      /* struct config_group */ | #include <linux/configfs.h>      /* struct config_group */ | ||||||
| #include <linux/dma-direction.h> /* enum dma_data_direction */ | #include <linux/dma-direction.h> /* enum dma_data_direction */ | ||||||
| #include <linux/percpu_ida.h>    /* struct percpu_ida */ | #include <linux/sbitmap.h> | ||||||
| #include <linux/percpu-refcount.h> | #include <linux/percpu-refcount.h> | ||||||
| #include <linux/semaphore.h>     /* struct semaphore */ | #include <linux/semaphore.h>     /* struct semaphore */ | ||||||
| #include <linux/completion.h> | #include <linux/completion.h> | ||||||
|  | @ -455,6 +455,7 @@ struct se_cmd { | ||||||
| 	int			sam_task_attr; | 	int			sam_task_attr; | ||||||
| 	/* Used for se_sess->sess_tag_pool */ | 	/* Used for se_sess->sess_tag_pool */ | ||||||
| 	unsigned int		map_tag; | 	unsigned int		map_tag; | ||||||
|  | 	int			map_cpu; | ||||||
| 	/* Transport protocol dependent state, see transport_state_table */ | 	/* Transport protocol dependent state, see transport_state_table */ | ||||||
| 	enum transport_state_table t_state; | 	enum transport_state_table t_state; | ||||||
| 	/* See se_cmd_flags_table */ | 	/* See se_cmd_flags_table */ | ||||||
|  | @ -608,7 +609,7 @@ struct se_session { | ||||||
| 	struct list_head	sess_wait_list; | 	struct list_head	sess_wait_list; | ||||||
| 	spinlock_t		sess_cmd_lock; | 	spinlock_t		sess_cmd_lock; | ||||||
| 	void			*sess_cmd_map; | 	void			*sess_cmd_map; | ||||||
| 	struct percpu_ida	sess_tag_pool; | 	struct sbitmap_queue	sess_tag_pool; | ||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
| struct se_device; | struct se_device; | ||||||
|  | @ -936,7 +937,7 @@ static inline void atomic_dec_mb(atomic_t *v) | ||||||
| 
 | 
 | ||||||
| static inline void target_free_tag(struct se_session *sess, struct se_cmd *cmd) | static inline void target_free_tag(struct se_session *sess, struct se_cmd *cmd) | ||||||
| { | { | ||||||
| 	percpu_ida_free(&sess->sess_tag_pool, cmd->map_tag); | 	sbitmap_queue_clear(&sess->sess_tag_pool, cmd->map_tag, cmd->map_cpu); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| #endif /* TARGET_CORE_BASE_H */ | #endif /* TARGET_CORE_BASE_H */ | ||||||
|  |  | ||||||
		Loading…
	
		Reference in a new issue
	
	 Matthew Wilcox
						Matthew Wilcox