From b885e23b951e939cc0c805c34771f97e9db64ef0 Mon Sep 17 00:00:00 2001 From: Changpeng Liu Date: Wed, 21 Apr 2021 17:59:33 +0800 Subject: [PATCH] bdev/iscsi: apply max_unmap and max_unmap_segments to bdev layer The bdev layer can do the unmap split now based on the backend device. For now we only use 1 unmap descriptor, the bdev layer can help us to do the split. Fix issue #1888 Change-Id: Iaf740bafd4f2bb4b108133fee2aafd2f53da9b2b Signed-off-by: Changpeng Liu Reviewed-on: https://review.spdk.io/gerrit/c/spdk/spdk/+/7519 Community-CI: Broadcom CI Community-CI: Mellanox Build Bot Tested-by: SPDK CI Jenkins Reviewed-by: Jim Harris Reviewed-by: Shuhei Matsumoto --- module/bdev/iscsi/bdev_iscsi.c | 51 +++++++++++++++++++++++++++++----- 1 file changed, 44 insertions(+), 7 deletions(-) diff --git a/module/bdev/iscsi/bdev_iscsi.c b/module/bdev/iscsi/bdev_iscsi.c index e12095d7b..c811d65b6 100644 --- a/module/bdev/iscsi/bdev_iscsi.c +++ b/module/bdev/iscsi/bdev_iscsi.c @@ -64,6 +64,13 @@ struct bdev_iscsi_lun; */ #define BDEV_ISCSI_DEFAULT_MAX_UNMAP_LBA_COUNT (32768) +/* MAXIMUM UNMAP BLOCK DESCRIPTOR COUNT: + * indicates the maximum number of UNMAP block descriptors that + * shall be contained in the parameter data transferred to the + * device server for an UNMAP command. + */ +#define BDEV_ISCSI_MAX_UNMAP_BLOCK_DESCS_COUNT (1) + static int bdev_iscsi_initialize(void); static TAILQ_HEAD(, bdev_iscsi_conn_req) g_iscsi_conn_req = TAILQ_HEAD_INITIALIZER( g_iscsi_conn_req); @@ -90,6 +97,7 @@ struct bdev_iscsi_lun { struct spdk_poller *no_main_ch_poller; struct spdk_thread *no_main_ch_poller_td; bool unmap_supported; + uint32_t max_unmap; struct spdk_poller *poller; }; @@ -319,17 +327,41 @@ bdev_iscsi_unmap(struct bdev_iscsi_lun *lun, struct bdev_iscsi_io *iscsi_io, uint64_t lba, uint64_t num_blocks) { struct scsi_task *task; - struct unmap_list list[1]; + struct unmap_list list[BDEV_ISCSI_MAX_UNMAP_BLOCK_DESCS_COUNT] = {}; + struct unmap_list *entry; + uint32_t num_unmap_list; + uint64_t offset, remaining, unmap_blocks; - list[0].lba = lba; - list[0].num = num_blocks; - task = iscsi_unmap_task(lun->context, 0, 0, 0, list, 1, + num_unmap_list = spdk_divide_round_up(num_blocks, lun->max_unmap); + if (num_unmap_list > BDEV_ISCSI_MAX_UNMAP_BLOCK_DESCS_COUNT) { + SPDK_ERRLOG("Too many unmap entries\n"); + goto failed; + } + + remaining = num_blocks; + offset = lba; + num_unmap_list = 0; + entry = &list[0]; + + do { + unmap_blocks = spdk_min(remaining, lun->max_unmap); + entry->lba = offset; + entry->num = unmap_blocks; + num_unmap_list++; + remaining -= unmap_blocks; + offset += unmap_blocks; + entry++; + } while (remaining > 0); + + task = iscsi_unmap_task(lun->context, 0, 0, 0, list, num_unmap_list, bdev_iscsi_command_cb, iscsi_io); - if (task == NULL) { - SPDK_ERRLOG("failed to get unmap_task\n"); - bdev_iscsi_io_complete(iscsi_io, SPDK_BDEV_IO_STATUS_FAILED); + if (task != NULL) { return; } + SPDK_ERRLOG("failed to get unmap_task\n"); + +failed: + bdev_iscsi_io_complete(iscsi_io, SPDK_BDEV_IO_STATUS_FAILED); } static void @@ -655,6 +687,11 @@ create_iscsi_lun(struct bdev_iscsi_conn_req *req, uint64_t num_blocks, lun->bdev.blockcnt = num_blocks; lun->bdev.ctxt = lun; lun->unmap_supported = req->unmap_supported; + if (lun->unmap_supported) { + lun->max_unmap = req->max_unmap; + lun->bdev.max_unmap = req->max_unmap; + lun->bdev.max_unmap_segments = BDEV_ISCSI_MAX_UNMAP_BLOCK_DESCS_COUNT; + } lun->bdev.fn_table = &iscsi_fn_table;