diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2012-03-22 23:38:04 +0400 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2012-03-22 23:38:04 +0400 |
commit | 1ab142d499294b844ecc81e8004db4ce029b0b61 (patch) | |
tree | 9db85a456d0cba3de8b9bd6671b1b52fa939770c /drivers/target/target_core_iblock.c | |
parent | 267d7b23dd62f6ec55e0fba777e456495c308fc7 (diff) | |
parent | 187e70a554e0f0717a65998bc9199945cbbd4692 (diff) | |
download | linux-1ab142d499294b844ecc81e8004db4ce029b0b61.tar.xz |
Merge branch 'for-next' of git://git.kernel.org/pub/scm/linux/kernel/git/nab/target-pending
Pull SCSI target updates from Nicholas Bellinger:
"This contains the usual set of updates and bugfixes to target-core +
existing fabric module code, along with a handful of the patches
destined for v3.3 stable.
It also contains the necessary target-core infrastructure pieces
required to run using tcm_qla2xxx.ko WWPNs with the new Qlogic Fibre
Channel fabric module currently queued in target-pending/for-next-merge,
and coming for round 2.
The highlights for this series include:
- Add target_submit_tmr() helper function for fabric task management
(andy)
- Convert tcm_fc to use target_submit_tmr() (andy)
- Replace target core various cmd flags with a transport state (hch)
- Convert loopback to use workqueue submission (hch)
- Convert target core to use array_zalloc for tpg_lun_list (joern)
- Convert target core to use array_zalloc for device_list (joern)
- Add target core support for TMR_ABORT_TASK (nab)
- Add target core se_sess->sess_kref + get/put helpers (nab)
- Add target core se_node_acl->acl_kref for ->acl_free_comp usage
(nab)
- Convert iscsi-target to use target_put_session + sess_kref (nab)
- Fix tcm_fc fc_exch memory leak in ft_send_resp_status (nab)
- Fix ib_srpt srpt_handle_cmd send_ioctx->ioctx_kref leak on
exception (nab)
- Fix target core up handling of short INQUIRY buffers (roland)
- Untangle target-core front-end and back-end meanings of max_sectors
attribute (roland)
- Set loopback residual field for SCSI commands (roland)
- Fix target-core 16-bit target ports for SET TARGET PORT GROUPS
emulation (roland)
Thanks again to Andy, Christoph, Joern, Roland, and everyone who has
contributed this round!"
* 'for-next' of git://git.kernel.org/pub/scm/linux/kernel/git/nab/target-pending: (64 commits)
ib_srpt: Fix srpt_handle_cmd send_ioctx->ioctx_kref leak on exception
loopback: Fix transport_generic_allocate_tasks error handling
iscsi-target: remove improper externs
iscsi-target: Remove unused variables in iscsi_target_parameters.c
target: remove obvious warnings
target: Use array_zalloc for device_list
target: Use array_zalloc for tpg_lun_list
target: Fix sense code for unsupported SERVICE ACTION IN
target: Remove hack to make READ CAPACITY(10) lie if thin provisioning is enabled
target: Bump core version to v4.1.0-rc2-ml + fabric versions
tcm_fc: Fix fc_exch memory leak in ft_send_resp_status
target: Drop unused legacy target_core_fabric_ops API callers
iscsi-target: Convert to use target_put_session + sess_kref
target: Convert se_node_acl->acl_group removal to use ->acl_kref
target: Add se_node_acl->acl_kref for ->acl_free_comp usage
target: Add se_node_acl->acl_free_comp for NodeACL release path
target: Add se_sess->sess_kref + get/put helpers
target: Convert session_lock to irqsave
target: Fix typo in drivers/target
iscsi-target: Fix dynamic -> explict NodeACL pointer reference
...
Diffstat (limited to 'drivers/target/target_core_iblock.c')
-rw-r--r-- | drivers/target/target_core_iblock.c | 78 |
1 files changed, 36 insertions, 42 deletions
diff --git a/drivers/target/target_core_iblock.c b/drivers/target/target_core_iblock.c index 8572eae62da7..2ec299e8a73e 100644 --- a/drivers/target/target_core_iblock.c +++ b/drivers/target/target_core_iblock.c @@ -46,6 +46,9 @@ #include "target_core_iblock.h" +#define IBLOCK_MAX_BIO_PER_TASK 32 /* max # of bios to submit at a time */ +#define IBLOCK_BIO_POOL_SIZE 128 + static struct se_subsystem_api iblock_template; static void iblock_bio_done(struct bio *, int); @@ -56,51 +59,25 @@ static void iblock_bio_done(struct bio *, int); */ static int iblock_attach_hba(struct se_hba *hba, u32 host_id) { - struct iblock_hba *ib_host; - - ib_host = kzalloc(sizeof(struct iblock_hba), GFP_KERNEL); - if (!ib_host) { - pr_err("Unable to allocate memory for" - " struct iblock_hba\n"); - return -ENOMEM; - } - - ib_host->iblock_host_id = host_id; - - hba->hba_ptr = ib_host; - pr_debug("CORE_HBA[%d] - TCM iBlock HBA Driver %s on" " Generic Target Core Stack %s\n", hba->hba_id, IBLOCK_VERSION, TARGET_CORE_MOD_VERSION); - - pr_debug("CORE_HBA[%d] - Attached iBlock HBA: %u to Generic\n", - hba->hba_id, ib_host->iblock_host_id); - return 0; } static void iblock_detach_hba(struct se_hba *hba) { - struct iblock_hba *ib_host = hba->hba_ptr; - - pr_debug("CORE_HBA[%d] - Detached iBlock HBA: %u from Generic" - " Target Core\n", hba->hba_id, ib_host->iblock_host_id); - - kfree(ib_host); - hba->hba_ptr = NULL; } static void *iblock_allocate_virtdevice(struct se_hba *hba, const char *name) { struct iblock_dev *ib_dev = NULL; - struct iblock_hba *ib_host = hba->hba_ptr; ib_dev = kzalloc(sizeof(struct iblock_dev), GFP_KERNEL); if (!ib_dev) { pr_err("Unable to allocate struct iblock_dev\n"); return NULL; } - ib_dev->ibd_host = ib_host; pr_debug( "IBLOCK: Allocated ib_dev for %s\n", name); @@ -126,10 +103,8 @@ static struct se_device *iblock_create_virtdevice( return ERR_PTR(ret); } memset(&dev_limits, 0, sizeof(struct se_dev_limits)); - /* - * These settings need to be made tunable.. - */ - ib_dev->ibd_bio_set = bioset_create(32, 0); + + ib_dev->ibd_bio_set = bioset_create(IBLOCK_BIO_POOL_SIZE, 0); if (!ib_dev->ibd_bio_set) { pr_err("IBLOCK: Unable to create bioset()\n"); return ERR_PTR(-ENOMEM); @@ -155,8 +130,8 @@ static struct se_device *iblock_create_virtdevice( q = bdev_get_queue(bd); limits = &dev_limits.limits; limits->logical_block_size = bdev_logical_block_size(bd); - limits->max_hw_sectors = queue_max_hw_sectors(q); - limits->max_sectors = queue_max_sectors(q); + limits->max_hw_sectors = UINT_MAX; + limits->max_sectors = UINT_MAX; dev_limits.hw_queue_depth = q->nr_requests; dev_limits.queue_depth = q->nr_requests; @@ -230,7 +205,7 @@ iblock_alloc_task(unsigned char *cdb) return NULL; } - atomic_set(&ib_req->ib_bio_cnt, 0); + atomic_set(&ib_req->pending, 1); return &ib_req->ib_task; } @@ -510,24 +485,35 @@ iblock_get_bio(struct se_task *task, sector_t lba, u32 sg_num) bio->bi_destructor = iblock_bio_destructor; bio->bi_end_io = &iblock_bio_done; bio->bi_sector = lba; - atomic_inc(&ib_req->ib_bio_cnt); + atomic_inc(&ib_req->pending); pr_debug("Set bio->bi_sector: %llu\n", (unsigned long long)bio->bi_sector); - pr_debug("Set ib_req->ib_bio_cnt: %d\n", - atomic_read(&ib_req->ib_bio_cnt)); + pr_debug("Set ib_req->pending: %d\n", atomic_read(&ib_req->pending)); return bio; } +static void iblock_submit_bios(struct bio_list *list, int rw) +{ + struct blk_plug plug; + struct bio *bio; + + blk_start_plug(&plug); + while ((bio = bio_list_pop(list))) + submit_bio(rw, bio); + blk_finish_plug(&plug); +} + static int iblock_do_task(struct se_task *task) { struct se_cmd *cmd = task->task_se_cmd; struct se_device *dev = cmd->se_dev; + struct iblock_req *ibr = IBLOCK_REQ(task); struct bio *bio; struct bio_list list; struct scatterlist *sg; u32 i, sg_num = task->task_sg_nents; sector_t block_lba; - struct blk_plug plug; + unsigned bio_cnt; int rw; if (task->task_data_direction == DMA_TO_DEVICE) { @@ -572,6 +558,7 @@ static int iblock_do_task(struct se_task *task) bio_list_init(&list); bio_list_add(&list, bio); + bio_cnt = 1; for_each_sg(task->task_sg, sg, task->task_sg_nents, i) { /* @@ -581,10 +568,16 @@ static int iblock_do_task(struct se_task *task) */ while (bio_add_page(bio, sg_page(sg), sg->length, sg->offset) != sg->length) { + if (bio_cnt >= IBLOCK_MAX_BIO_PER_TASK) { + iblock_submit_bios(&list, rw); + bio_cnt = 0; + } + bio = iblock_get_bio(task, block_lba, sg_num); if (!bio) goto fail; bio_list_add(&list, bio); + bio_cnt++; } /* Always in 512 byte units for Linux/Block */ @@ -592,11 +585,12 @@ static int iblock_do_task(struct se_task *task) sg_num--; } - blk_start_plug(&plug); - while ((bio = bio_list_pop(&list))) - submit_bio(rw, bio); - blk_finish_plug(&plug); + iblock_submit_bios(&list, rw); + if (atomic_dec_and_test(&ibr->pending)) { + transport_complete_task(task, + !atomic_read(&ibr->ib_bio_err_cnt)); + } return 0; fail: @@ -648,7 +642,7 @@ static void iblock_bio_done(struct bio *bio, int err) bio_put(bio); - if (!atomic_dec_and_test(&ibr->ib_bio_cnt)) + if (!atomic_dec_and_test(&ibr->pending)) return; pr_debug("done[%p] bio: %p task_lba: %llu bio_lba: %llu err=%d\n", |