[RFC PATCH 1/1] scsi: sd: associate sd_probe_domain with scsi_disk
From: "wangqiang (AY)" sd_remove() waits for the completion of async threads executing sd_probe_async of disks on unrelated host adapters, rather than just the the async thread associated with the scsi_disk being removed. This patch makes sd_remove() just wait for the the async thread associated with the scsi_disk being removed. And makes the operation of iscsid after received ISCSI_KEVENT_CONN_ERROR be asynchronous by put the __iscsi_destroy_session() in work queue. Signed-off-by: "wangqiang (AY)" Signed-off-by: Ming Lin --- drivers/scsi/scsi_transport_iscsi.c | 14 +- drivers/scsi/sd.c | 5 +++-- drivers/scsi/sd.h | 3 +++ include/scsi/scsi_transport_iscsi.h | 1 + 4 files changed, 20 insertions(+), 3 deletions(-) diff --git a/drivers/scsi/scsi_transport_iscsi.c b/drivers/scsi/scsi_transport_iscsi.c index 0a82e93566dc..7e5782eb527b 100644 --- a/drivers/scsi/scsi_transport_iscsi.c +++ b/drivers/scsi/scsi_transport_iscsi.c @@ -2005,6 +2005,16 @@ void iscsi_block_session(struct iscsi_cls_session *session) } EXPORT_SYMBOL_GPL(iscsi_block_session); +static void __iscsi_destroy_session(struct work_struct *work) +{ + struct iscsi_cls_session *session = + container_of(work, struct iscsi_cls_session, +destroy_work); + struct iscsi_transport *transport = session->transport; + + transport->destroy_session(session); +} + static void __iscsi_unbind_session(struct work_struct *work) { struct iscsi_cls_session *session = @@ -2061,6 +2071,7 @@ iscsi_alloc_session(struct Scsi_Host *shost, struct iscsi_transport *transport, INIT_WORK(&session->block_work, __iscsi_block_session); INIT_WORK(&session->unbind_work, __iscsi_unbind_session); INIT_WORK(&session->scan_work, iscsi_scan_session); + INIT_WORK(&session->destroy_work, __iscsi_destroy_session); spin_lock_init(&session->lock); /* this is released in the dev's release function */ @@ -3536,7 +3547,8 @@ iscsi_if_recv_msg(struct sk_buff *skb, struct nlmsghdr *nlh, uint32_t *group) case ISCSI_UEVENT_DESTROY_SESSION: session = iscsi_session_lookup(ev->u.d_session.sid); if (session) - transport->destroy_session(session); + scsi_queue_work(iscsi_session_to_shost(session), + &session->destroy_work); else err = -EINVAL; break; diff --git a/drivers/scsi/sd.c b/drivers/scsi/sd.c index 2b2bc4b49d78..378f57142183 100644 --- a/drivers/scsi/sd.c +++ b/drivers/scsi/sd.c @@ -3436,7 +3436,8 @@ static int sd_probe(struct device *dev) dev_set_drvdata(dev, sdkp); get_device(&sdkp->dev); /* prevent release before async_schedule */ - async_schedule_domain(sd_probe_async, sdkp, &scsi_sd_probe_domain); + INIT_LIST_HEAD(&sdkp->sd_probe_domain.pending); + async_schedule_domain(sd_probe_async, sdkp, &sdkp->sd_probe_domain); return 0; @@ -3472,7 +3473,7 @@ static int sd_remove(struct device *dev) scsi_autopm_get_device(sdkp->device); async_synchronize_full_domain(&scsi_sd_pm_domain); - async_synchronize_full_domain(&scsi_sd_probe_domain); + async_synchronize_full_domain(&sdkp->sd_probe_domain); device_del(&sdkp->dev); del_gendisk(sdkp->disk); sd_shutdown(dev); diff --git a/drivers/scsi/sd.h b/drivers/scsi/sd.h index 5796ace76225..f46a87ebd759 100644 --- a/drivers/scsi/sd.h +++ b/drivers/scsi/sd.h @@ -2,6 +2,8 @@ #ifndef _SCSI_DISK_H #define _SCSI_DISK_H +#include + /* * More than enough for everybody ;) The huge number of majors * is a leftover from 16bit dev_t days, we don't really need that @@ -73,6 +75,7 @@ struct scsi_disk { struct device dev; struct gendisk *disk; struct opal_dev *opal_dev; + struct async_domain sd_probe_domain; #ifdef CONFIG_BLK_DEV_ZONED u32 nr_zones; u32 zone_blocks; diff --git a/include/scsi/scsi_transport_iscsi.h b/include/scsi/scsi_transport_iscsi.h index b266d2a3bcb1..7830e1596ef3 100644 --- a/include/scsi/scsi_transport_iscsi.h +++ b/include/scsi/scsi_transport_iscsi.h @@ -238,6 +238,7 @@ struct iscsi_cls_session { struct work_struct unblock_work; struct work_struct scan_work; struct work_struct unbind_work; + struct work_struct destroy_work; /* recovery fields */ int recovery_tmo; -- 2.14.4.52.g320db32
[RFC PATCH 0/1] fix bug of iscsid hung
Hi list, I encountered a bug of iscsid hung when testing iscsi login/logout in unstable network. Same as this one reported by Wangqiang@Huawei https://lore.kernel.org/lkml/508a4c72ed914648bb0f1814399310dbbb2...@dggemm506-mbx.china.huawei.com/ Use tc tool to simulate network packet loss. -- test script start - tc qdisc add dev eth0 root netem loss 60 # 2 target, each with 10 LUNs n=1 while [ 1 ] do echo "$(date) test loop $n " iscsiadm -m node -T iqn.2016-06.io.spdk:disk1 --login sleep 5 iscsiadm -m node -T iqn.2016-06.io.spdk:disk1 --logout& iscsiadm -m node -T iqn.2016-06.io.spdk:disk2 --login& sleep 10 iscsiadm -m node -u n=$(($n + 1)) echo "$(date) continue to test loop " done -- test script end - iscsid hung as below, [ 369.909988] INFO: task iscsid:1254 blocked for more than 122 seconds. [ 369.912532] Tainted: GE 5.1.0-rc3+ #12 [ 369.914750] "echo 0 > /proc/sys/kernel/hung_task_timeout_secs" disables this message. [ 369.917396] iscsid D0 1254 1 0x0080 [ 369.917399] Call Trace: [ 369.920958] schedule+0x32/0x70 [ 369.922716] schedule_timeout+0x1d8/0x300 [ 369.926129] wait_for_completion+0x123/0x190 [ 369.929365] __flush_work.isra.34+0x124/0x1b0 ===> flush_work(&session->unbind_work); [ 369.932746] iscsi_remove_session+0xf0/0x1d0 [scsi_transport_iscsi] [ 369.934718] iscsi_session_teardown+0x37/0xf0 [libiscsi] [ 369.936417] iscsi_sw_tcp_session_destroy+0x42/0x60 [iscsi_tcp] [ 369.938312] iscsi_if_recv_msg+0x69b/0x1510 [scsi_transport_iscsi] [ 369.946502] iscsi_if_rx+0xa5/0x1e0 [scsi_transport_iscsi] [ 369.948193] netlink_unicast+0x17f/0x230 [ 369.949734] netlink_sendmsg+0x2d2/0x3d0 [ 369.951277] sock_sendmsg+0x36/0x50 [ 369.952691] ___sys_sendmsg+0x280/0x2a0 [ 369.981533] __sys_sendmsg+0x58/0xa0 [ 369.982444] do_syscall_64+0x5b/0x180 [ 369.983369] entry_SYSCALL_64_after_hwframe+0x44/0xa9 __flush_work() tried to flush session->unbind_work. kworker thread that handles unbind_work blocked as below, [ 615.742259] INFO: task kworker/u4:11:1321 blocked for more than 368 seconds. [ 615.743615] Tainted: GE 5.1.0-rc3+ #12 [ 615.744780] "echo 0 > /proc/sys/kernel/hung_task_timeout_secs" disables this message. [ 615.746274] kworker/u4:11 D0 1321 2 0x8080 [ 615.746281] Workqueue: scsi_wq_2 __iscsi_unbind_session [scsi_transport_iscsi] [ 615.746282] Call Trace: [ 615.749131] schedule+0x32/0x70 [ 615.750065] async_synchronize_cookie_domain+0x8b/0x140 [ 615.752349] sd_remove+0x8f/0x140 [sd_mod] [ 615.753411] device_release_driver_internal+0xeb/0x1c0 [ 615.754605] bus_remove_device+0xe5/0x160 [ 615.755702] device_del+0x15a/0x340 [ 615.759495] __scsi_remove_device+0x9c/0x160 [ 615.760673] scsi_remove_device+0x21/0x30 [ 615.761824] scsi_remove_target+0x172/0x1c0 [ 615.763001] __iscsi_unbind_session+0xd0/0x1a0 [scsi_transport_iscsi] [ 615.764477] process_one_work+0x171/0x380 [ 615.765646] worker_thread+0x49/0x3f0 [ 615.766774] kthread+0xf8/0x130 [ 615.769974] ret_from_fork+0x35/0x40 async_synchronize_cookie_domain() blocked until all entries in "scsi_sd_probe_domain" finished. But some entries never finished because kworker thread that executes sd_probe_async() blocked as below, [ 492.909482] INFO: task kworker/u4:0:7 blocked for more than 122 seconds. [ 492.912321] Tainted: GE 5.1.0-rc3+ #6 [ 492.913519] "echo 0 > /proc/sys/kernel/hung_task_timeout_secs" disables this message. [ 492.915037] kworker/u4:0D0 7 2 0x8000 [ 492.915046] Workqueue: events_unbound async_run_entry_fn [ 492.915047] Call Trace: [ 492.916813] schedule+0x32/0x70 [ 492.917740] io_schedule+0x12/0x40 [ 492.918659] do_read_cache_page+0x43b/0x740 [ 492.921877] read_dev_sector+0x28/0xa0 [ 492.922859] read_lba+0xfe/0x1b0 [ 492.924904] find_valid_gpt+0xfa/0x720 [ 492.927048] efi_partition+0x89/0x430 [ 492.931934] check_partition+0x110/0x200 [ 492.932960] rescan_partitions+0xbb/0x360 [ 492.934000] __blkdev_get+0x372/0x4b0 [ 492.934987] blkdev_get+0x1a7/0x300 [ 492.937892] __device_add_disk+0x45f/0x4c0 [ 492.938942] sd_probe_async+0x13f/0x240 [sd_mod] [ 492.940065] async_run_entry_fn+0x39/0x160 [ 492.941126] process_one_work+0x171/0x380 [ 492.942181] worker_thread+0x49/0x3f0 [ 492.943169] kthread+0xf8/0x130 [ 492.946140] ret_from_fork+0x35/0x40 The iscsi command sent by do_read_cache_page() timedout in my test, but it's never completed/aborted because session->state is ISCSI_STATE_FAILED and iscsi_eh_cmd_timed_out() keep returning BLK_EH_RESET_TIMER. 1947 enum blk_eh_timer_return iscsi_eh_cmd_timed_out(struct scsi_cmnd *sc) 1948 { .. .. 1972 if (session->state != ISCSI_STATE_LOGGED_IN) { 1973 /* 1974 * During shutdown, if session is prematurely disconn
Re: NVMe over Fabrics target implementation
On Tue, Jun 7, 2016 at 2:02 PM, Andy Grover wrote: > On 06/06/2016 11:23 PM, Nicholas A. Bellinger wrote: >> >> Hi HCH & Co, >> >> On Mon, 2016-06-06 at 23:22 +0200, Christoph Hellwig wrote: >>> >>> This patch set adds a generic NVMe over Fabrics target. The >>> implementation conforms to the NVMe 1.2b specification (which >>> includes Fabrics) and provides the NVMe over Fabrics access >>> to Linux block devices. >>> >> >> Thanks for all of the development work by the fabric_linux_driver team >> (HCH, Sagi, Ming, James F., James S., and Dave M.) over the last year. >> >> Very excited to see this code get a public release now that NVMf >> specification is out. Now that it's in the wild, it's a good >> opportunity to discuss some of the more interesting implementation >> details, beyond the new NVMf wire-protocol itself. > > > I'm sorry but I missed it, can you repeat the link to the NVMe spec(s)? http://www.nvmexpress.org/wp-content/uploads/NVM_Express_1_2_1_Gold_20160603.pdf http://www.nvmexpress.org/wp-content/uploads/NVMe_over_Fabrics_1_0_Gold_20160605.pdf -- 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
Re: [PATCH v3 4/5] scsi: rename SCSI_MAX_{SG, SG_CHAIN}_SEGMENTS
On Mon, Apr 11, 2016 at 2:34 PM, Martin K. Petersen wrote: >>>>>> "Ming" == Ming Lin writes: > > Ming> Are we ready to merge it? > > We're still missing an ack from Sagi. Thought we already had a ack from Bart. OK, let's get one more from Sagi. -- 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
Re: [PATCH v3 4/5] scsi: rename SCSI_MAX_{SG, SG_CHAIN}_SEGMENTS
On Tue, Apr 5, 2016 at 7:55 AM, Tejun Heo wrote: > On Mon, Apr 04, 2016 at 02:48:10PM -0700, Ming Lin wrote: >> From: Ming Lin >> >> Rename SCSI_MAX_SG_SEGMENTS to SG_CHUNK_SIZE, which means the amount >> we fit into a single scatterlist chunk. >> >> Rename SCSI_MAX_SG_CHAIN_SEGMENTS to SG_MAX_SEGMENTS. >> >> Will move these 2 generic definitions to scatterlist.h later. >> >> Reviewed-by: Christoph Hellwig >> Acked-by: Bart Van Assche (for ib_srp changes) >> Signed-off-by: Ming Lin > > For libata, > > Acked-by: Tejun Heo Hi James, Are we ready to merge it? Thanks, Ming -- 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
Re: [PATCH RFC 1/2] scatterlist: add mempool based chained SG alloc/free api
On Thu, Apr 7, 2016 at 9:43 AM, Ming Lin wrote: > On Thu, Apr 7, 2016 at 7:56 AM, Bart Van Assche > wrote: >> On 03/15/16 15:39, Ming Lin wrote: >>> >>> +static void sg_mempoll_free(struct scatterlist *sgl, unsigned int nents) >> >> >> Please change mempoll into mempool. > > Good catch. Thanks Bart! Hi Bart, This is actually the previous old RFC patch. The v2 and v3 patch series doesn't have this typo. Thanks. -- 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
Re: [PATCH RFC 1/2] scatterlist: add mempool based chained SG alloc/free api
On Thu, Apr 7, 2016 at 7:56 AM, Bart Van Assche wrote: > On 03/15/16 15:39, Ming Lin wrote: >> >> +static void sg_mempoll_free(struct scatterlist *sgl, unsigned int nents) > > > Please change mempoll into mempool. Good catch. Thanks Bart! -- 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
[PATCH v3 1/5] scsi: replace "scsi_data_buffer" with "sg_table" in SG functions
From: Ming Lin Replace parameter "struct scsi_data_buffer" with "struct sg_table" in SG alloc/free functions to make them generic. Reviewed-by: Christoph Hellwig Signed-off-by: Ming Lin --- drivers/scsi/scsi_lib.c | 41 +++-- 1 file changed, 23 insertions(+), 18 deletions(-) diff --git a/drivers/scsi/scsi_lib.c b/drivers/scsi/scsi_lib.c index 8106515..4229c18 100644 --- a/drivers/scsi/scsi_lib.c +++ b/drivers/scsi/scsi_lib.c @@ -583,14 +583,14 @@ static struct scatterlist *scsi_sg_alloc(unsigned int nents, gfp_t gfp_mask) return mempool_alloc(sgp->pool, gfp_mask); } -static void scsi_free_sgtable(struct scsi_data_buffer *sdb, bool mq) +static void scsi_free_sgtable(struct sg_table *table, bool mq) { - if (mq && sdb->table.orig_nents <= SCSI_MAX_SG_SEGMENTS) + if (mq && table->orig_nents <= SCSI_MAX_SG_SEGMENTS) return; - __sg_free_table(&sdb->table, SCSI_MAX_SG_SEGMENTS, mq, scsi_sg_free); + __sg_free_table(table, SCSI_MAX_SG_SEGMENTS, mq, scsi_sg_free); } -static int scsi_alloc_sgtable(struct scsi_data_buffer *sdb, int nents, bool mq) +static int scsi_alloc_sgtable(struct sg_table *table, int nents, bool mq) { struct scatterlist *first_chunk = NULL; int ret; @@ -599,17 +599,17 @@ static int scsi_alloc_sgtable(struct scsi_data_buffer *sdb, int nents, bool mq) if (mq) { if (nents <= SCSI_MAX_SG_SEGMENTS) { - sdb->table.nents = sdb->table.orig_nents = nents; - sg_init_table(sdb->table.sgl, nents); + table->nents = table->orig_nents = nents; + sg_init_table(table->sgl, nents); return 0; } - first_chunk = sdb->table.sgl; + first_chunk = table->sgl; } - ret = __sg_alloc_table(&sdb->table, nents, SCSI_MAX_SG_SEGMENTS, + ret = __sg_alloc_table(table, nents, SCSI_MAX_SG_SEGMENTS, first_chunk, GFP_ATOMIC, scsi_sg_alloc); if (unlikely(ret)) - scsi_free_sgtable(sdb, mq); + scsi_free_sgtable(table, mq); return ret; } @@ -625,12 +625,17 @@ static void scsi_uninit_cmd(struct scsi_cmnd *cmd) static void scsi_mq_free_sgtables(struct scsi_cmnd *cmd) { + struct scsi_data_buffer *sdb; + if (cmd->sdb.table.nents) - scsi_free_sgtable(&cmd->sdb, true); - if (cmd->request->next_rq && cmd->request->next_rq->special) - scsi_free_sgtable(cmd->request->next_rq->special, true); + scsi_free_sgtable(&cmd->sdb.table, true); + if (cmd->request->next_rq) { + sdb = cmd->request->next_rq->special; + if (sdb) + scsi_free_sgtable(&sdb->table, true); + } if (scsi_prot_sg_count(cmd)) - scsi_free_sgtable(cmd->prot_sdb, true); + scsi_free_sgtable(&cmd->prot_sdb->table, true); } static void scsi_mq_uninit_cmd(struct scsi_cmnd *cmd) @@ -669,19 +674,19 @@ static void scsi_mq_uninit_cmd(struct scsi_cmnd *cmd) static void scsi_release_buffers(struct scsi_cmnd *cmd) { if (cmd->sdb.table.nents) - scsi_free_sgtable(&cmd->sdb, false); + scsi_free_sgtable(&cmd->sdb.table, false); memset(&cmd->sdb, 0, sizeof(cmd->sdb)); if (scsi_prot_sg_count(cmd)) - scsi_free_sgtable(cmd->prot_sdb, false); + scsi_free_sgtable(&cmd->prot_sdb->table, false); } static void scsi_release_bidi_buffers(struct scsi_cmnd *cmd) { struct scsi_data_buffer *bidi_sdb = cmd->request->next_rq->special; - scsi_free_sgtable(bidi_sdb, false); + scsi_free_sgtable(&bidi_sdb->table, false); kmem_cache_free(scsi_sdb_cache, bidi_sdb); cmd->request->next_rq->special = NULL; } @@ -1085,7 +1090,7 @@ static int scsi_init_sgtable(struct request *req, struct scsi_data_buffer *sdb) /* * If sg table allocation fails, requeue request later. */ - if (unlikely(scsi_alloc_sgtable(sdb, req->nr_phys_segments, + if (unlikely(scsi_alloc_sgtable(&sdb->table, req->nr_phys_segments, req->mq_ctx != NULL))) return BLKPREP_DEFER; @@ -1158,7 +1163,7 @@ int scsi_init_io(struct scsi_cmnd *cmd) ivecs = blk_rq_count_integrity_sg(rq->q, rq->bio); - if (scsi_alloc_sgtable(prot_sdb, ivecs, is_mq)) { + if (scsi_alloc_sgtable(&prot_sdb->table, ivecs, is_mq)) { error = BLKPREP_DEFER; goto err_exit; } -- 1.9.1 -- 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
[PATCH v3 4/5] scsi: rename SCSI_MAX_{SG, SG_CHAIN}_SEGMENTS
From: Ming Lin Rename SCSI_MAX_SG_SEGMENTS to SG_CHUNK_SIZE, which means the amount we fit into a single scatterlist chunk. Rename SCSI_MAX_SG_CHAIN_SEGMENTS to SG_MAX_SEGMENTS. Will move these 2 generic definitions to scatterlist.h later. Reviewed-by: Christoph Hellwig Acked-by: Bart Van Assche (for ib_srp changes) Signed-off-by: Ming Lin --- drivers/ata/pata_icside.c | 2 +- drivers/infiniband/ulp/srp/ib_srp.c | 4 ++-- drivers/scsi/arm/cumana_2.c | 2 +- drivers/scsi/arm/eesox.c| 2 +- drivers/scsi/arm/powertec.c | 2 +- drivers/scsi/esas2r/esas2r_main.c | 4 ++-- drivers/scsi/hisi_sas/hisi_sas.h| 2 +- drivers/scsi/mpt3sas/mpt3sas_base.c | 4 ++-- drivers/scsi/mpt3sas/mpt3sas_base.h | 2 +- drivers/scsi/scsi_debug.c | 2 +- drivers/scsi/scsi_lib.c | 34 +- drivers/usb/storage/scsiglue.c | 2 +- include/scsi/scsi.h | 8 include/scsi/scsi_host.h| 2 +- 14 files changed, 36 insertions(+), 36 deletions(-) diff --git a/drivers/ata/pata_icside.c b/drivers/ata/pata_icside.c index d7c7320..188f2f2 100644 --- a/drivers/ata/pata_icside.c +++ b/drivers/ata/pata_icside.c @@ -294,7 +294,7 @@ static int icside_dma_init(struct pata_icside_info *info) static struct scsi_host_template pata_icside_sht = { ATA_BASE_SHT(DRV_NAME), - .sg_tablesize = SCSI_MAX_SG_CHAIN_SEGMENTS, + .sg_tablesize = SG_MAX_SEGMENTS, .dma_boundary = IOMD_DMA_BOUNDARY, }; diff --git a/drivers/infiniband/ulp/srp/ib_srp.c b/drivers/infiniband/ulp/srp/ib_srp.c index ff21597..369a75e 100644 --- a/drivers/infiniband/ulp/srp/ib_srp.c +++ b/drivers/infiniband/ulp/srp/ib_srp.c @@ -81,7 +81,7 @@ MODULE_PARM_DESC(cmd_sg_entries, module_param(indirect_sg_entries, uint, 0444); MODULE_PARM_DESC(indirect_sg_entries, -"Default max number of gather/scatter entries (default is 12, max is " __stringify(SCSI_MAX_SG_CHAIN_SEGMENTS) ")"); +"Default max number of gather/scatter entries (default is 12, max is " __stringify(SG_MAX_SEGMENTS) ")"); module_param(allow_ext_sg, bool, 0444); MODULE_PARM_DESC(allow_ext_sg, @@ -3097,7 +3097,7 @@ static int srp_parse_options(const char *buf, struct srp_target_port *target) case SRP_OPT_SG_TABLESIZE: if (match_int(args, &token) || token < 1 || - token > SCSI_MAX_SG_CHAIN_SEGMENTS) { + token > SG_MAX_SEGMENTS) { pr_warn("bad max sg_tablesize parameter '%s'\n", p); goto out; diff --git a/drivers/scsi/arm/cumana_2.c b/drivers/scsi/arm/cumana_2.c index faa1bee..edce5f3 100644 --- a/drivers/scsi/arm/cumana_2.c +++ b/drivers/scsi/arm/cumana_2.c @@ -365,7 +365,7 @@ static struct scsi_host_template cumanascsi2_template = { .eh_abort_handler = fas216_eh_abort, .can_queue = 1, .this_id= 7, - .sg_tablesize = SCSI_MAX_SG_CHAIN_SEGMENTS, + .sg_tablesize = SG_MAX_SEGMENTS, .dma_boundary = IOMD_DMA_BOUNDARY, .use_clustering = DISABLE_CLUSTERING, .proc_name = "cumanascsi2", diff --git a/drivers/scsi/arm/eesox.c b/drivers/scsi/arm/eesox.c index a8ad688..e93e047 100644 --- a/drivers/scsi/arm/eesox.c +++ b/drivers/scsi/arm/eesox.c @@ -484,7 +484,7 @@ static struct scsi_host_template eesox_template = { .eh_abort_handler = fas216_eh_abort, .can_queue = 1, .this_id= 7, - .sg_tablesize = SCSI_MAX_SG_CHAIN_SEGMENTS, + .sg_tablesize = SG_MAX_SEGMENTS, .dma_boundary = IOMD_DMA_BOUNDARY, .use_clustering = DISABLE_CLUSTERING, .proc_name = "eesox", diff --git a/drivers/scsi/arm/powertec.c b/drivers/scsi/arm/powertec.c index 5e1b73e..79aa889 100644 --- a/drivers/scsi/arm/powertec.c +++ b/drivers/scsi/arm/powertec.c @@ -291,7 +291,7 @@ static struct scsi_host_template powertecscsi_template = { .can_queue = 8, .this_id= 7, - .sg_tablesize = SCSI_MAX_SG_CHAIN_SEGMENTS, + .sg_tablesize = SG_MAX_SEGMENTS, .dma_boundary = IOMD_DMA_BOUNDARY, .cmd_per_lun= 2, .use_clustering = ENABLE_CLUSTERING, diff --git a/drivers/scsi/esas2r/esas2r_main.c b/drivers/scsi/esas2r/esas2r_main.c index 33581ba..2
[PATCH v3 2/5] scsi: replace "mq" with "first_chunk" in SG functions
From: Ming Lin Parameter "bool mq" is block driver specific. Change it to "first_chunk" to make it more generic. Reviewed-by: Christoph Hellwig Signed-off-by: Ming Lin --- drivers/scsi/scsi_lib.c | 20 ++-- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/drivers/scsi/scsi_lib.c b/drivers/scsi/scsi_lib.c index 4229c18..9675353 100644 --- a/drivers/scsi/scsi_lib.c +++ b/drivers/scsi/scsi_lib.c @@ -583,33 +583,32 @@ static struct scatterlist *scsi_sg_alloc(unsigned int nents, gfp_t gfp_mask) return mempool_alloc(sgp->pool, gfp_mask); } -static void scsi_free_sgtable(struct sg_table *table, bool mq) +static void scsi_free_sgtable(struct sg_table *table, bool first_chunk) { - if (mq && table->orig_nents <= SCSI_MAX_SG_SEGMENTS) + if (first_chunk && table->orig_nents <= SCSI_MAX_SG_SEGMENTS) return; - __sg_free_table(table, SCSI_MAX_SG_SEGMENTS, mq, scsi_sg_free); + __sg_free_table(table, SCSI_MAX_SG_SEGMENTS, first_chunk, scsi_sg_free); } -static int scsi_alloc_sgtable(struct sg_table *table, int nents, bool mq) +static int scsi_alloc_sgtable(struct sg_table *table, int nents, + struct scatterlist *first_chunk) { - struct scatterlist *first_chunk = NULL; int ret; BUG_ON(!nents); - if (mq) { + if (first_chunk) { if (nents <= SCSI_MAX_SG_SEGMENTS) { table->nents = table->orig_nents = nents; sg_init_table(table->sgl, nents); return 0; } - first_chunk = table->sgl; } ret = __sg_alloc_table(table, nents, SCSI_MAX_SG_SEGMENTS, first_chunk, GFP_ATOMIC, scsi_sg_alloc); if (unlikely(ret)) - scsi_free_sgtable(table, mq); + scsi_free_sgtable(table, (bool)first_chunk); return ret; } @@ -1091,7 +1090,7 @@ static int scsi_init_sgtable(struct request *req, struct scsi_data_buffer *sdb) * If sg table allocation fails, requeue request later. */ if (unlikely(scsi_alloc_sgtable(&sdb->table, req->nr_phys_segments, - req->mq_ctx != NULL))) + sdb->table.sgl))) return BLKPREP_DEFER; /* @@ -1163,7 +1162,8 @@ int scsi_init_io(struct scsi_cmnd *cmd) ivecs = blk_rq_count_integrity_sg(rq->q, rq->bio); - if (scsi_alloc_sgtable(&prot_sdb->table, ivecs, is_mq)) { + if (scsi_alloc_sgtable(&prot_sdb->table, ivecs, + prot_sdb->table.sgl)) { error = BLKPREP_DEFER; goto err_exit; } -- 1.9.1 -- 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
[PATCH v3 5/5] lib: scatterlist: move SG pool code from SCSI driver to lib/sg_pool.c
From: Ming Lin Now it's ready to move the mempool based SG chained allocator code from SCSI driver to lib/sg_pool.c, which will be compiled only based on a Kconfig symbol CONFIG_SG_POOL. SCSI selects CONFIG_SG_POOL. Reviewed-by: Christoph Hellwig Signed-off-by: Ming Lin --- drivers/scsi/Kconfig| 1 + drivers/scsi/scsi_lib.c | 137 --- include/linux/scatterlist.h | 25 +++ include/scsi/scsi.h | 19 - lib/Kconfig | 7 ++ lib/Makefile| 1 + lib/sg_pool.c | 172 7 files changed, 206 insertions(+), 156 deletions(-) create mode 100644 lib/sg_pool.c diff --git a/drivers/scsi/Kconfig b/drivers/scsi/Kconfig index 0950567..98e5d51 100644 --- a/drivers/scsi/Kconfig +++ b/drivers/scsi/Kconfig @@ -17,6 +17,7 @@ config SCSI tristate "SCSI device support" depends on BLOCK select SCSI_DMA if HAS_DMA + select SG_POOL ---help--- If you want to use a SCSI hard disk, SCSI tape drive, SCSI CD-ROM or any other SCSI device under Linux, say Y and make sure that you know diff --git a/drivers/scsi/scsi_lib.c b/drivers/scsi/scsi_lib.c index 8f776f1..b920c5d 100644 --- a/drivers/scsi/scsi_lib.c +++ b/drivers/scsi/scsi_lib.c @@ -14,8 +14,6 @@ #include #include #include -#include -#include #include #include #include @@ -40,39 +38,6 @@ #include "scsi_logging.h" -#define SG_MEMPOOL_NR ARRAY_SIZE(sg_pools) -#define SG_MEMPOOL_SIZE2 - -struct sg_pool { - size_t size; - char*name; - struct kmem_cache *slab; - mempool_t *pool; -}; - -#define SP(x) { .size = x, "sgpool-" __stringify(x) } -#if (SG_CHUNK_SIZE < 32) -#error SG_CHUNK_SIZE is too small (must be 32 or greater) -#endif -static struct sg_pool sg_pools[] = { - SP(8), - SP(16), -#if (SG_CHUNK_SIZE > 32) - SP(32), -#if (SG_CHUNK_SIZE > 64) - SP(64), -#if (SG_CHUNK_SIZE > 128) - SP(128), -#if (SG_CHUNK_SIZE > 256) -#error SG_CHUNK_SIZE is too large (256 MAX) -#endif -#endif -#endif -#endif - SP(SG_CHUNK_SIZE) -}; -#undef SP - struct kmem_cache *scsi_sdb_cache; /* @@ -553,65 +518,6 @@ void scsi_run_host_queues(struct Scsi_Host *shost) scsi_run_queue(sdev->request_queue); } -static inline unsigned int sg_pool_index(unsigned short nents) -{ - unsigned int index; - - BUG_ON(nents > SG_CHUNK_SIZE); - - if (nents <= 8) - index = 0; - else - index = get_count_order(nents) - 3; - - return index; -} - -static void sg_pool_free(struct scatterlist *sgl, unsigned int nents) -{ - struct sg_pool *sgp; - - sgp = sg_pools + sg_pool_index(nents); - mempool_free(sgl, sgp->pool); -} - -static struct scatterlist *sg_pool_alloc(unsigned int nents, gfp_t gfp_mask) -{ - struct sg_pool *sgp; - - sgp = sg_pools + sg_pool_index(nents); - return mempool_alloc(sgp->pool, gfp_mask); -} - -static void sg_free_table_chained(struct sg_table *table, bool first_chunk) -{ - if (first_chunk && table->orig_nents <= SG_CHUNK_SIZE) - return; - __sg_free_table(table, SG_CHUNK_SIZE, first_chunk, sg_pool_free); -} - -static int sg_alloc_table_chained(struct sg_table *table, int nents, - struct scatterlist *first_chunk) -{ - int ret; - - BUG_ON(!nents); - - if (first_chunk) { - if (nents <= SG_CHUNK_SIZE) { - table->nents = table->orig_nents = nents; - sg_init_table(table->sgl, nents); - return 0; - } - } - - ret = __sg_alloc_table(table, nents, SG_CHUNK_SIZE, - first_chunk, GFP_ATOMIC, sg_pool_alloc); - if (unlikely(ret)) - sg_free_table_chained(table, (bool)first_chunk); - return ret; -} - static void scsi_uninit_cmd(struct scsi_cmnd *cmd) { if (cmd->request->cmd_type == REQ_TYPE_FS) { @@ -2269,8 +2175,6 @@ EXPORT_SYMBOL(scsi_unblock_requests); int __init scsi_init_queue(void) { - int i; - scsi_sdb_cache = kmem_cache_create("scsi_data_buffer", sizeof(struct scsi_data_buffer), 0, 0, NULL); @@ -2279,53 +2183,12 @@ int __init scsi_init_queue(void) return -ENOMEM; } - for (i = 0; i < SG_MEMPOOL_NR; i++) { - struct sg_pool *sgp = sg_pools + i; - int size = sgp->size * sizeof(struct scatterlist); - - sgp->slab = kmem_cache_create(sgp->name, size, 0, - SLAB_HWCACHE_ALIGN, NULL); - if (!sgp->slab) {
[PATCH v3 3/5] scsi: rename SG related struct and functions
From: Ming Lin Rename SCSI specific struct and functions to more genenic names. Reviewed-by: Christoph Hellwig Signed-off-by: Ming Lin --- drivers/scsi/scsi_lib.c | 52 - 1 file changed, 26 insertions(+), 26 deletions(-) diff --git a/drivers/scsi/scsi_lib.c b/drivers/scsi/scsi_lib.c index 9675353..08134f6 100644 --- a/drivers/scsi/scsi_lib.c +++ b/drivers/scsi/scsi_lib.c @@ -40,10 +40,10 @@ #include "scsi_logging.h" -#define SG_MEMPOOL_NR ARRAY_SIZE(scsi_sg_pools) +#define SG_MEMPOOL_NR ARRAY_SIZE(sg_pools) #define SG_MEMPOOL_SIZE2 -struct scsi_host_sg_pool { +struct sg_pool { size_t size; char*name; struct kmem_cache *slab; @@ -54,7 +54,7 @@ struct scsi_host_sg_pool { #if (SCSI_MAX_SG_SEGMENTS < 32) #error SCSI_MAX_SG_SEGMENTS is too small (must be 32 or greater) #endif -static struct scsi_host_sg_pool scsi_sg_pools[] = { +static struct sg_pool sg_pools[] = { SP(8), SP(16), #if (SCSI_MAX_SG_SEGMENTS > 32) @@ -553,7 +553,7 @@ void scsi_run_host_queues(struct Scsi_Host *shost) scsi_run_queue(sdev->request_queue); } -static inline unsigned int scsi_sgtable_index(unsigned short nents) +static inline unsigned int sg_pool_index(unsigned short nents) { unsigned int index; @@ -567,30 +567,30 @@ static inline unsigned int scsi_sgtable_index(unsigned short nents) return index; } -static void scsi_sg_free(struct scatterlist *sgl, unsigned int nents) +static void sg_pool_free(struct scatterlist *sgl, unsigned int nents) { - struct scsi_host_sg_pool *sgp; + struct sg_pool *sgp; - sgp = scsi_sg_pools + scsi_sgtable_index(nents); + sgp = sg_pools + sg_pool_index(nents); mempool_free(sgl, sgp->pool); } -static struct scatterlist *scsi_sg_alloc(unsigned int nents, gfp_t gfp_mask) +static struct scatterlist *sg_pool_alloc(unsigned int nents, gfp_t gfp_mask) { - struct scsi_host_sg_pool *sgp; + struct sg_pool *sgp; - sgp = scsi_sg_pools + scsi_sgtable_index(nents); + sgp = sg_pools + sg_pool_index(nents); return mempool_alloc(sgp->pool, gfp_mask); } -static void scsi_free_sgtable(struct sg_table *table, bool first_chunk) +static void sg_free_table_chained(struct sg_table *table, bool first_chunk) { if (first_chunk && table->orig_nents <= SCSI_MAX_SG_SEGMENTS) return; - __sg_free_table(table, SCSI_MAX_SG_SEGMENTS, first_chunk, scsi_sg_free); + __sg_free_table(table, SCSI_MAX_SG_SEGMENTS, first_chunk, sg_pool_free); } -static int scsi_alloc_sgtable(struct sg_table *table, int nents, +static int sg_alloc_table_chained(struct sg_table *table, int nents, struct scatterlist *first_chunk) { int ret; @@ -606,9 +606,9 @@ static int scsi_alloc_sgtable(struct sg_table *table, int nents, } ret = __sg_alloc_table(table, nents, SCSI_MAX_SG_SEGMENTS, - first_chunk, GFP_ATOMIC, scsi_sg_alloc); + first_chunk, GFP_ATOMIC, sg_pool_alloc); if (unlikely(ret)) - scsi_free_sgtable(table, (bool)first_chunk); + sg_free_table_chained(table, (bool)first_chunk); return ret; } @@ -627,14 +627,14 @@ static void scsi_mq_free_sgtables(struct scsi_cmnd *cmd) struct scsi_data_buffer *sdb; if (cmd->sdb.table.nents) - scsi_free_sgtable(&cmd->sdb.table, true); + sg_free_table_chained(&cmd->sdb.table, true); if (cmd->request->next_rq) { sdb = cmd->request->next_rq->special; if (sdb) - scsi_free_sgtable(&sdb->table, true); + sg_free_table_chained(&sdb->table, true); } if (scsi_prot_sg_count(cmd)) - scsi_free_sgtable(&cmd->prot_sdb->table, true); + sg_free_table_chained(&cmd->prot_sdb->table, true); } static void scsi_mq_uninit_cmd(struct scsi_cmnd *cmd) @@ -673,19 +673,19 @@ static void scsi_mq_uninit_cmd(struct scsi_cmnd *cmd) static void scsi_release_buffers(struct scsi_cmnd *cmd) { if (cmd->sdb.table.nents) - scsi_free_sgtable(&cmd->sdb.table, false); + sg_free_table_chained(&cmd->sdb.table, false); memset(&cmd->sdb, 0, sizeof(cmd->sdb)); if (scsi_prot_sg_count(cmd)) - scsi_free_sgtable(&cmd->prot_sdb->table, false); + sg_free_table_chained(&cmd->prot_sdb->table, false); } static void scsi_release_bidi_buffers(struct scsi_cmnd *cmd) { struct scsi_data_buffer *bidi_sdb = cmd->request->next_rq->special; - scsi_free_sgtable(&bidi_sdb->table, false);
[PATCH v3 0/5] mempool based chained scatterlist alloc/free api
From: Ming Lin The fist 4 patches make the SG related definitions/structs/functions in SCSI code generic and the last patch move it to lib/sg_pool.c. v3: - Resend for Tejun to review. No code change since v2. - Add review/ack tags v2: - do modification in scsi code first then move to lib/sg_pool.c - address Christoph's comments Ming Lin (5): scsi: replace "scsi_data_buffer" with "sg_table" in SG functions scsi: replace "mq" with "first_chunk" in SG functions scsi: rename SG related struct and functions scsi: rename SCSI_MAX_{SG, SG_CHAIN}_SEGMENTS lib: scatterlist: move SG pool code from SCSI driver to lib/sg_pool.c drivers/ata/pata_icside.c | 2 +- drivers/infiniband/ulp/srp/ib_srp.c | 4 +- drivers/scsi/Kconfig| 1 + drivers/scsi/arm/cumana_2.c | 2 +- drivers/scsi/arm/eesox.c| 2 +- drivers/scsi/arm/powertec.c | 2 +- drivers/scsi/esas2r/esas2r_main.c | 4 +- drivers/scsi/hisi_sas/hisi_sas.h| 2 +- drivers/scsi/mpt3sas/mpt3sas_base.c | 4 +- drivers/scsi/mpt3sas/mpt3sas_base.h | 2 +- drivers/scsi/scsi_debug.c | 2 +- drivers/scsi/scsi_lib.c | 172 +--- drivers/usb/storage/scsiglue.c | 2 +- include/linux/scatterlist.h | 25 ++ include/scsi/scsi.h | 19 include/scsi/scsi_host.h| 2 +- lib/Kconfig | 7 ++ lib/Makefile| 1 + lib/sg_pool.c | 172 19 files changed, 241 insertions(+), 186 deletions(-) create mode 100644 lib/sg_pool.c -- 1.9.1 -- 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
Re: [PATCH v2 5/5] lib: scatterlist: move SG pool code from SCSI driver to lib/sg_pool.c
On Mon, Apr 4, 2016 at 1:17 PM, Christoph Hellwig wrote: > On Mon, Apr 04, 2016 at 01:15:45PM -0700, Ming Lin wrote: >> cleanup_sdb: >> for (i = 0; i < SG_MEMPOOL_NR; i++) { >> struct sg_pool *sgp = sg_pools + i; >> if (sgp->pool) >> mempool_destroy(sgp->pool); >> if (sgp->slab) >> kmem_cache_destroy(sgp->slab); >> } >> >> I'll keep the NULL check if no objection. > > I don't necessarily, but given that this is a code move I'd prefer > to keep the code as similar as possible in the actual move patch.. So I'll just keep it. And I can send a cleanup patch after this series applied. -- 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
Re: [PATCH v2 4/5] scsi: rename SCSI_MAX_{SG, SG_CHAIN}_SEGMENTS
On Tue, Mar 22, 2016 at 3:03 PM, Ming Lin wrote: > From: Ming Lin > > Rename SCSI_MAX_SG_SEGMENTS to SG_CHUNK_SIZE, which means the amount > we fit into a single scatterlist chunk. > > Rename SCSI_MAX_SG_CHAIN_SEGMENTS to SG_MAX_SEGMENTS. > > Will move these 2 generic definitions to scatterlist.h later. > > Signed-off-by: Ming Lin > --- > drivers/ata/pata_icside.c | 2 +- > drivers/infiniband/ulp/srp/ib_srp.c | 4 ++-- > drivers/scsi/arm/cumana_2.c | 2 +- > drivers/scsi/arm/eesox.c| 2 +- > drivers/scsi/arm/powertec.c | 2 +- > drivers/scsi/esas2r/esas2r_main.c | 4 ++-- > drivers/scsi/hisi_sas/hisi_sas.h| 2 +- > drivers/scsi/mpt3sas/mpt3sas_base.c | 4 ++-- > drivers/scsi/mpt3sas/mpt3sas_base.h | 2 +- > drivers/scsi/scsi_debug.c | 2 +- > drivers/scsi/scsi_lib.c | 34 +- > drivers/usb/storage/scsiglue.c | 2 +- > include/scsi/scsi.h | 8 > include/scsi/scsi_host.h| 2 +- > 14 files changed, 36 insertions(+), 36 deletions(-) > > diff --git a/drivers/ata/pata_icside.c b/drivers/ata/pata_icside.c > index d7c7320..188f2f2 100644 > --- a/drivers/ata/pata_icside.c > +++ b/drivers/ata/pata_icside.c > @@ -294,7 +294,7 @@ static int icside_dma_init(struct pata_icside_info *info) > > static struct scsi_host_template pata_icside_sht = { > ATA_BASE_SHT(DRV_NAME), > - .sg_tablesize = SCSI_MAX_SG_CHAIN_SEGMENTS, > + .sg_tablesize = SG_MAX_SEGMENTS, > .dma_boundary = IOMD_DMA_BOUNDARY, > }; Hi Tejun, Could you help to review/ack this ATA part? Thanks. > diff --git a/include/scsi/scsi.h b/include/scsi/scsi.h > index e0a3398..74dafa7 100644 > --- a/include/scsi/scsi.h > +++ b/include/scsi/scsi.h > @@ -24,16 +24,16 @@ enum scsi_timeouts { > * to SG_MAX_SINGLE_ALLOC to pack correctly at the highest order. The > * minimum value is 32 > */ > -#define SCSI_MAX_SG_SEGMENTS 128 > +#define SG_CHUNK_SIZE 128 > > /* > - * Like SCSI_MAX_SG_SEGMENTS, but for archs that have sg chaining. This limit > + * Like SG_CHUNK_SIZE, but for archs that have sg chaining. This limit > * is totally arbitrary, a setting of 2048 will get you at least 8mb ios. > */ > #ifdef CONFIG_ARCH_HAS_SG_CHAIN > -#define SCSI_MAX_SG_CHAIN_SEGMENTS 2048 > +#define SG_MAX_SEGMENTS2048 > #else > -#define SCSI_MAX_SG_CHAIN_SEGMENTS SCSI_MAX_SG_SEGMENTS > +#define SG_MAX_SEGMENTSSG_CHUNK_SIZE > #endif > > /* > diff --git a/include/scsi/scsi_host.h b/include/scsi/scsi_host.h > index fcfa3d7..76e9d27 100644 > --- a/include/scsi/scsi_host.h > +++ b/include/scsi/scsi_host.h > @@ -37,7 +37,7 @@ struct blk_queue_tags; > * used in one scatter-gather request. > */ > #define SG_NONE 0 > -#define SG_ALL SCSI_MAX_SG_SEGMENTS > +#define SG_ALL SG_CHUNK_SIZE > > #define MODE_UNKNOWN 0x00 > #define MODE_INITIATOR 0x01 > -- > 1.9.1 -- 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
Re: [PATCH v2 5/5] lib: scatterlist: move SG pool code from SCSI driver to lib/sg_pool.c
On Tue, Mar 22, 2016 at 7:38 PM, kbuild test robot wrote: > Hi Ming, > > [auto build test WARNING on scsi/for-next] > [also build test WARNING on v4.5 next-20160322] > [if your patch is applied to the wrong git tree, please drop us a note to > help improving the system] > > url: > https://github.com/0day-ci/linux/commits/Ming-Lin/mempool-based-chained-scatterlist-alloc-free-api/20160323-060710 > base: https://git.kernel.org/pub/scm/linux/kernel/git/jejb/scsi.git for-next > > > coccinelle warnings: (new ones prefixed by >>) > >>> lib/sg_pool.c:152:3-18: WARNING: NULL check before freeing functions like >>> kfree, debugfs_remove, debugfs_remove_recursive or usb_free_urb is not >>> needed. Maybe consider reorganizing relevant code to avoid passing NULL >>> values. >lib/sg_pool.c:154:3-21: WARNING: NULL check before freeing functions like > kfree, debugfs_remove, debugfs_remove_recursive or usb_free_urb is not > needed. Maybe consider reorganizing relevant code to avoid passing NULL > values. mempool_destroy()/kmem_cache_destroy() is OK to accept NULL pointer. But the logic is more readable that we do NULL check when cleanup due to error. cleanup_sdb: for (i = 0; i < SG_MEMPOOL_NR; i++) { struct sg_pool *sgp = sg_pools + i; if (sgp->pool) mempool_destroy(sgp->pool); if (sgp->slab) kmem_cache_destroy(sgp->slab); } I'll keep the NULL check if no objection. Thanks. -- 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
Re: [PATCH v2 0/5] mempool based chained scatterlist alloc/free api
On Mon, Mar 28, 2016 at 7:48 AM, Ming Lin wrote: > On Thu, Mar 24, 2016 at 8:46 AM, James Bottomley > wrote: >> On Thu, 2016-03-24 at 08:09 -0700, Ming Lin wrote: >>> On Wed, Mar 23, 2016 at 12:40 AM, Christoph Hellwig >>> wrote: >>> > On Tue, Mar 22, 2016 at 03:03:11PM -0700, Ming Lin wrote: >>> > > From: Ming Lin >>> > > >>> > > The fist 4 patches make the SG related >>> > > definitions/structs/functions >>> > > in SCSI code generic and the last patch move it to lib/sg_pool.c. >>> > > >>> > > I still keep the macro "SG_MEMPOOL_NR" since it's used in 3 >>> > > places. >>> > >>> > I don't ѕee the point, but I'm not going to block the series over >>> > it either. >>> > >>> > The new series looks really nice to me! >>> > >>> > Reviewed-by: Christoph Hellwig >>> >>> Hi James, >>> >>> This series touches several sub-systems. >>> What's the best way to merge it? >> >> It has a minor intrusion into >> >> drivers/ata/pata_icside.c | 2 +- >> drivers/infiniband/ulp/srp/ib_srp.c | 4 +- >> drivers/usb/storage/scsiglue.c | 2 +- >> >> Apart from that, it's all SCSI, so the SCSI tree would seem to be the >> best one. > > Are you OK to merge it? Hi James, Ping ... Are you OK to apply this series? Or any changes needed? Thanks. > > Thanks. -- 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
Re: [PATCH v2 0/5] mempool based chained scatterlist alloc/free api
On Thu, Mar 24, 2016 at 8:46 AM, James Bottomley wrote: > On Thu, 2016-03-24 at 08:09 -0700, Ming Lin wrote: >> On Wed, Mar 23, 2016 at 12:40 AM, Christoph Hellwig >> wrote: >> > On Tue, Mar 22, 2016 at 03:03:11PM -0700, Ming Lin wrote: >> > > From: Ming Lin >> > > >> > > The fist 4 patches make the SG related >> > > definitions/structs/functions >> > > in SCSI code generic and the last patch move it to lib/sg_pool.c. >> > > >> > > I still keep the macro "SG_MEMPOOL_NR" since it's used in 3 >> > > places. >> > >> > I don't ѕee the point, but I'm not going to block the series over >> > it either. >> > >> > The new series looks really nice to me! >> > >> > Reviewed-by: Christoph Hellwig >> >> Hi James, >> >> This series touches several sub-systems. >> What's the best way to merge it? > > It has a minor intrusion into > > drivers/ata/pata_icside.c | 2 +- > drivers/infiniband/ulp/srp/ib_srp.c | 4 +- > drivers/usb/storage/scsiglue.c | 2 +- > > Apart from that, it's all SCSI, so the SCSI tree would seem to be the > best one. Are you OK to merge it? Thanks. -- 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
Re: [PATCH v2 0/5] mempool based chained scatterlist alloc/free api
On Wed, Mar 23, 2016 at 12:40 AM, Christoph Hellwig wrote: > On Tue, Mar 22, 2016 at 03:03:11PM -0700, Ming Lin wrote: >> From: Ming Lin >> >> The fist 4 patches make the SG related definitions/structs/functions >> in SCSI code generic and the last patch move it to lib/sg_pool.c. >> >> I still keep the macro "SG_MEMPOOL_NR" since it's used in 3 places. > > I don't ѕee the point, but I'm not going to block the series over > it either. > > The new series looks really nice to me! > > Reviewed-by: Christoph Hellwig Hi James, This series touches several sub-systems. What's the best way to merge it? Thanks. -- 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
[PATCH v2 2/5] scsi: replace "mq" with "first_chunk" in SG functions
From: Ming Lin Parameter "bool mq" is block driver specific. Change it to "first_chunk" to make it more generic. Signed-off-by: Ming Lin --- drivers/scsi/scsi_lib.c | 20 ++-- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/drivers/scsi/scsi_lib.c b/drivers/scsi/scsi_lib.c index 5eaddc7..ab3dd09 100644 --- a/drivers/scsi/scsi_lib.c +++ b/drivers/scsi/scsi_lib.c @@ -583,33 +583,32 @@ static struct scatterlist *scsi_sg_alloc(unsigned int nents, gfp_t gfp_mask) return mempool_alloc(sgp->pool, gfp_mask); } -static void scsi_free_sgtable(struct sg_table *table, bool mq) +static void scsi_free_sgtable(struct sg_table *table, bool first_chunk) { - if (mq && table->orig_nents <= SCSI_MAX_SG_SEGMENTS) + if (first_chunk && table->orig_nents <= SCSI_MAX_SG_SEGMENTS) return; - __sg_free_table(table, SCSI_MAX_SG_SEGMENTS, mq, scsi_sg_free); + __sg_free_table(table, SCSI_MAX_SG_SEGMENTS, first_chunk, scsi_sg_free); } -static int scsi_alloc_sgtable(struct sg_table *table, int nents, bool mq) +static int scsi_alloc_sgtable(struct sg_table *table, int nents, + struct scatterlist *first_chunk) { - struct scatterlist *first_chunk = NULL; int ret; BUG_ON(!nents); - if (mq) { + if (first_chunk) { if (nents <= SCSI_MAX_SG_SEGMENTS) { table->nents = table->orig_nents = nents; sg_init_table(table->sgl, nents); return 0; } - first_chunk = table->sgl; } ret = __sg_alloc_table(table, nents, SCSI_MAX_SG_SEGMENTS, first_chunk, GFP_ATOMIC, scsi_sg_alloc); if (unlikely(ret)) - scsi_free_sgtable(table, mq); + scsi_free_sgtable(table, (bool)first_chunk); return ret; } @@ -1091,7 +1090,7 @@ static int scsi_init_sgtable(struct request *req, struct scsi_data_buffer *sdb) * If sg table allocation fails, requeue request later. */ if (unlikely(scsi_alloc_sgtable(&sdb->table, req->nr_phys_segments, - req->mq_ctx != NULL))) + sdb->table.sgl))) return BLKPREP_DEFER; /* @@ -1163,7 +1162,8 @@ int scsi_init_io(struct scsi_cmnd *cmd) ivecs = blk_rq_count_integrity_sg(rq->q, rq->bio); - if (scsi_alloc_sgtable(&prot_sdb->table, ivecs, is_mq)) { + if (scsi_alloc_sgtable(&prot_sdb->table, ivecs, + prot_sdb->table.sgl)) { error = BLKPREP_DEFER; goto err_exit; } -- 1.9.1 -- 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
[PATCH v2 0/5] mempool based chained scatterlist alloc/free api
From: Ming Lin The fist 4 patches make the SG related definitions/structs/functions in SCSI code generic and the last patch move it to lib/sg_pool.c. I still keep the macro "SG_MEMPOOL_NR" since it's used in 3 places. v2: - do modification in scsi code first then move to lib/sg_pool.c - address Christoph's comments Ming Lin (5): scsi: replace "scsi_data_buffer" with "sg_table" in SG functions scsi: replace "mq" with "first_chunk" in SG functions scsi: rename SG related struct and functions scsi: rename SCSI_MAX_{SG, SG_CHAIN}_SEGMENTS lib: scatterlist: move SG pool code from SCSI driver to lib/sg_pool.c drivers/ata/pata_icside.c | 2 +- drivers/infiniband/ulp/srp/ib_srp.c | 4 +- drivers/scsi/Kconfig| 1 + drivers/scsi/arm/cumana_2.c | 2 +- drivers/scsi/arm/eesox.c| 2 +- drivers/scsi/arm/powertec.c | 2 +- drivers/scsi/esas2r/esas2r_main.c | 4 +- drivers/scsi/hisi_sas/hisi_sas.h| 2 +- drivers/scsi/mpt3sas/mpt3sas_base.c | 4 +- drivers/scsi/mpt3sas/mpt3sas_base.h | 2 +- drivers/scsi/scsi_debug.c | 2 +- drivers/scsi/scsi_lib.c | 172 +--- drivers/usb/storage/scsiglue.c | 2 +- include/linux/scatterlist.h | 25 ++ include/scsi/scsi.h | 19 include/scsi/scsi_host.h| 2 +- lib/Kconfig | 7 ++ lib/Makefile| 1 + lib/sg_pool.c | 172 19 files changed, 241 insertions(+), 186 deletions(-) create mode 100644 lib/sg_pool.c -- 1.9.1 -- 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
[PATCH v2 1/5] scsi: replace "scsi_data_buffer" with "sg_table" in SG functions
From: Ming Lin Replace parameter "struct scsi_data_buffer" with "struct sg_table" in SG alloc/free functions to make them generic. Signed-off-by: Ming Lin --- drivers/scsi/scsi_lib.c | 41 +++-- 1 file changed, 23 insertions(+), 18 deletions(-) diff --git a/drivers/scsi/scsi_lib.c b/drivers/scsi/scsi_lib.c index 8c6e318..5eaddc7 100644 --- a/drivers/scsi/scsi_lib.c +++ b/drivers/scsi/scsi_lib.c @@ -583,14 +583,14 @@ static struct scatterlist *scsi_sg_alloc(unsigned int nents, gfp_t gfp_mask) return mempool_alloc(sgp->pool, gfp_mask); } -static void scsi_free_sgtable(struct scsi_data_buffer *sdb, bool mq) +static void scsi_free_sgtable(struct sg_table *table, bool mq) { - if (mq && sdb->table.orig_nents <= SCSI_MAX_SG_SEGMENTS) + if (mq && table->orig_nents <= SCSI_MAX_SG_SEGMENTS) return; - __sg_free_table(&sdb->table, SCSI_MAX_SG_SEGMENTS, mq, scsi_sg_free); + __sg_free_table(table, SCSI_MAX_SG_SEGMENTS, mq, scsi_sg_free); } -static int scsi_alloc_sgtable(struct scsi_data_buffer *sdb, int nents, bool mq) +static int scsi_alloc_sgtable(struct sg_table *table, int nents, bool mq) { struct scatterlist *first_chunk = NULL; int ret; @@ -599,17 +599,17 @@ static int scsi_alloc_sgtable(struct scsi_data_buffer *sdb, int nents, bool mq) if (mq) { if (nents <= SCSI_MAX_SG_SEGMENTS) { - sdb->table.nents = sdb->table.orig_nents = nents; - sg_init_table(sdb->table.sgl, nents); + table->nents = table->orig_nents = nents; + sg_init_table(table->sgl, nents); return 0; } - first_chunk = sdb->table.sgl; + first_chunk = table->sgl; } - ret = __sg_alloc_table(&sdb->table, nents, SCSI_MAX_SG_SEGMENTS, + ret = __sg_alloc_table(table, nents, SCSI_MAX_SG_SEGMENTS, first_chunk, GFP_ATOMIC, scsi_sg_alloc); if (unlikely(ret)) - scsi_free_sgtable(sdb, mq); + scsi_free_sgtable(table, mq); return ret; } @@ -625,12 +625,17 @@ static void scsi_uninit_cmd(struct scsi_cmnd *cmd) static void scsi_mq_free_sgtables(struct scsi_cmnd *cmd) { + struct scsi_data_buffer *sdb; + if (cmd->sdb.table.nents) - scsi_free_sgtable(&cmd->sdb, true); - if (cmd->request->next_rq && cmd->request->next_rq->special) - scsi_free_sgtable(cmd->request->next_rq->special, true); + scsi_free_sgtable(&cmd->sdb.table, true); + if (cmd->request->next_rq) { + sdb = cmd->request->next_rq->special; + if (sdb) + scsi_free_sgtable(&sdb->table, true); + } if (scsi_prot_sg_count(cmd)) - scsi_free_sgtable(cmd->prot_sdb, true); + scsi_free_sgtable(&cmd->prot_sdb->table, true); } static void scsi_mq_uninit_cmd(struct scsi_cmnd *cmd) @@ -669,19 +674,19 @@ static void scsi_mq_uninit_cmd(struct scsi_cmnd *cmd) static void scsi_release_buffers(struct scsi_cmnd *cmd) { if (cmd->sdb.table.nents) - scsi_free_sgtable(&cmd->sdb, false); + scsi_free_sgtable(&cmd->sdb.table, false); memset(&cmd->sdb, 0, sizeof(cmd->sdb)); if (scsi_prot_sg_count(cmd)) - scsi_free_sgtable(cmd->prot_sdb, false); + scsi_free_sgtable(&cmd->prot_sdb->table, false); } static void scsi_release_bidi_buffers(struct scsi_cmnd *cmd) { struct scsi_data_buffer *bidi_sdb = cmd->request->next_rq->special; - scsi_free_sgtable(bidi_sdb, false); + scsi_free_sgtable(&bidi_sdb->table, false); kmem_cache_free(scsi_sdb_cache, bidi_sdb); cmd->request->next_rq->special = NULL; } @@ -1085,7 +1090,7 @@ static int scsi_init_sgtable(struct request *req, struct scsi_data_buffer *sdb) /* * If sg table allocation fails, requeue request later. */ - if (unlikely(scsi_alloc_sgtable(sdb, req->nr_phys_segments, + if (unlikely(scsi_alloc_sgtable(&sdb->table, req->nr_phys_segments, req->mq_ctx != NULL))) return BLKPREP_DEFER; @@ -1158,7 +1163,7 @@ int scsi_init_io(struct scsi_cmnd *cmd) ivecs = blk_rq_count_integrity_sg(rq->q, rq->bio); - if (scsi_alloc_sgtable(prot_sdb, ivecs, is_mq)) { + if (scsi_alloc_sgtable(&prot_sdb->table, ivecs, is_mq)) { error = BLKPREP_DEFER; goto err_exit; } -- 1.9.1 -- 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
[PATCH v2 4/5] scsi: rename SCSI_MAX_{SG, SG_CHAIN}_SEGMENTS
From: Ming Lin Rename SCSI_MAX_SG_SEGMENTS to SG_CHUNK_SIZE, which means the amount we fit into a single scatterlist chunk. Rename SCSI_MAX_SG_CHAIN_SEGMENTS to SG_MAX_SEGMENTS. Will move these 2 generic definitions to scatterlist.h later. Signed-off-by: Ming Lin --- drivers/ata/pata_icside.c | 2 +- drivers/infiniband/ulp/srp/ib_srp.c | 4 ++-- drivers/scsi/arm/cumana_2.c | 2 +- drivers/scsi/arm/eesox.c| 2 +- drivers/scsi/arm/powertec.c | 2 +- drivers/scsi/esas2r/esas2r_main.c | 4 ++-- drivers/scsi/hisi_sas/hisi_sas.h| 2 +- drivers/scsi/mpt3sas/mpt3sas_base.c | 4 ++-- drivers/scsi/mpt3sas/mpt3sas_base.h | 2 +- drivers/scsi/scsi_debug.c | 2 +- drivers/scsi/scsi_lib.c | 34 +- drivers/usb/storage/scsiglue.c | 2 +- include/scsi/scsi.h | 8 include/scsi/scsi_host.h| 2 +- 14 files changed, 36 insertions(+), 36 deletions(-) diff --git a/drivers/ata/pata_icside.c b/drivers/ata/pata_icside.c index d7c7320..188f2f2 100644 --- a/drivers/ata/pata_icside.c +++ b/drivers/ata/pata_icside.c @@ -294,7 +294,7 @@ static int icside_dma_init(struct pata_icside_info *info) static struct scsi_host_template pata_icside_sht = { ATA_BASE_SHT(DRV_NAME), - .sg_tablesize = SCSI_MAX_SG_CHAIN_SEGMENTS, + .sg_tablesize = SG_MAX_SEGMENTS, .dma_boundary = IOMD_DMA_BOUNDARY, }; diff --git a/drivers/infiniband/ulp/srp/ib_srp.c b/drivers/infiniband/ulp/srp/ib_srp.c index 60b169a..b428b48 100644 --- a/drivers/infiniband/ulp/srp/ib_srp.c +++ b/drivers/infiniband/ulp/srp/ib_srp.c @@ -81,7 +81,7 @@ MODULE_PARM_DESC(cmd_sg_entries, module_param(indirect_sg_entries, uint, 0444); MODULE_PARM_DESC(indirect_sg_entries, -"Default max number of gather/scatter entries (default is 12, max is " __stringify(SCSI_MAX_SG_CHAIN_SEGMENTS) ")"); +"Default max number of gather/scatter entries (default is 12, max is " __stringify(SG_MAX_SEGMENTS) ")"); module_param(allow_ext_sg, bool, 0444); MODULE_PARM_DESC(allow_ext_sg, @@ -3129,7 +3129,7 @@ static int srp_parse_options(const char *buf, struct srp_target_port *target) case SRP_OPT_SG_TABLESIZE: if (match_int(args, &token) || token < 1 || - token > SCSI_MAX_SG_CHAIN_SEGMENTS) { + token > SG_MAX_SEGMENTS) { pr_warn("bad max sg_tablesize parameter '%s'\n", p); goto out; diff --git a/drivers/scsi/arm/cumana_2.c b/drivers/scsi/arm/cumana_2.c index faa1bee..edce5f3 100644 --- a/drivers/scsi/arm/cumana_2.c +++ b/drivers/scsi/arm/cumana_2.c @@ -365,7 +365,7 @@ static struct scsi_host_template cumanascsi2_template = { .eh_abort_handler = fas216_eh_abort, .can_queue = 1, .this_id= 7, - .sg_tablesize = SCSI_MAX_SG_CHAIN_SEGMENTS, + .sg_tablesize = SG_MAX_SEGMENTS, .dma_boundary = IOMD_DMA_BOUNDARY, .use_clustering = DISABLE_CLUSTERING, .proc_name = "cumanascsi2", diff --git a/drivers/scsi/arm/eesox.c b/drivers/scsi/arm/eesox.c index a8ad688..e93e047 100644 --- a/drivers/scsi/arm/eesox.c +++ b/drivers/scsi/arm/eesox.c @@ -484,7 +484,7 @@ static struct scsi_host_template eesox_template = { .eh_abort_handler = fas216_eh_abort, .can_queue = 1, .this_id= 7, - .sg_tablesize = SCSI_MAX_SG_CHAIN_SEGMENTS, + .sg_tablesize = SG_MAX_SEGMENTS, .dma_boundary = IOMD_DMA_BOUNDARY, .use_clustering = DISABLE_CLUSTERING, .proc_name = "eesox", diff --git a/drivers/scsi/arm/powertec.c b/drivers/scsi/arm/powertec.c index 5e1b73e..79aa889 100644 --- a/drivers/scsi/arm/powertec.c +++ b/drivers/scsi/arm/powertec.c @@ -291,7 +291,7 @@ static struct scsi_host_template powertecscsi_template = { .can_queue = 8, .this_id= 7, - .sg_tablesize = SCSI_MAX_SG_CHAIN_SEGMENTS, + .sg_tablesize = SG_MAX_SEGMENTS, .dma_boundary = IOMD_DMA_BOUNDARY, .cmd_per_lun= 2, .use_clustering = ENABLE_CLUSTERING, diff --git a/drivers/scsi/esas2r/esas2r_main.c b/drivers/scsi/esas2r/esas2r_main.c index 33581ba..2aca4d1 100644 --- a/drivers/scsi/esas2r/esas2r_main.c +++ b/drivers/s
[PATCH v2 3/5] scsi: rename SG related struct and functions
From: Ming Lin Rename SCSI specific struct and functions to more genenic names. Signed-off-by: Ming Lin --- drivers/scsi/scsi_lib.c | 52 - 1 file changed, 26 insertions(+), 26 deletions(-) diff --git a/drivers/scsi/scsi_lib.c b/drivers/scsi/scsi_lib.c index ab3dd09..5fd9dd7 100644 --- a/drivers/scsi/scsi_lib.c +++ b/drivers/scsi/scsi_lib.c @@ -40,10 +40,10 @@ #include "scsi_logging.h" -#define SG_MEMPOOL_NR ARRAY_SIZE(scsi_sg_pools) +#define SG_MEMPOOL_NR ARRAY_SIZE(sg_pools) #define SG_MEMPOOL_SIZE2 -struct scsi_host_sg_pool { +struct sg_pool { size_t size; char*name; struct kmem_cache *slab; @@ -54,7 +54,7 @@ struct scsi_host_sg_pool { #if (SCSI_MAX_SG_SEGMENTS < 32) #error SCSI_MAX_SG_SEGMENTS is too small (must be 32 or greater) #endif -static struct scsi_host_sg_pool scsi_sg_pools[] = { +static struct sg_pool sg_pools[] = { SP(8), SP(16), #if (SCSI_MAX_SG_SEGMENTS > 32) @@ -553,7 +553,7 @@ void scsi_run_host_queues(struct Scsi_Host *shost) scsi_run_queue(sdev->request_queue); } -static inline unsigned int scsi_sgtable_index(unsigned short nents) +static inline unsigned int sg_pool_index(unsigned short nents) { unsigned int index; @@ -567,30 +567,30 @@ static inline unsigned int scsi_sgtable_index(unsigned short nents) return index; } -static void scsi_sg_free(struct scatterlist *sgl, unsigned int nents) +static void sg_pool_free(struct scatterlist *sgl, unsigned int nents) { - struct scsi_host_sg_pool *sgp; + struct sg_pool *sgp; - sgp = scsi_sg_pools + scsi_sgtable_index(nents); + sgp = sg_pools + sg_pool_index(nents); mempool_free(sgl, sgp->pool); } -static struct scatterlist *scsi_sg_alloc(unsigned int nents, gfp_t gfp_mask) +static struct scatterlist *sg_pool_alloc(unsigned int nents, gfp_t gfp_mask) { - struct scsi_host_sg_pool *sgp; + struct sg_pool *sgp; - sgp = scsi_sg_pools + scsi_sgtable_index(nents); + sgp = sg_pools + sg_pool_index(nents); return mempool_alloc(sgp->pool, gfp_mask); } -static void scsi_free_sgtable(struct sg_table *table, bool first_chunk) +static void sg_free_table_chained(struct sg_table *table, bool first_chunk) { if (first_chunk && table->orig_nents <= SCSI_MAX_SG_SEGMENTS) return; - __sg_free_table(table, SCSI_MAX_SG_SEGMENTS, first_chunk, scsi_sg_free); + __sg_free_table(table, SCSI_MAX_SG_SEGMENTS, first_chunk, sg_pool_free); } -static int scsi_alloc_sgtable(struct sg_table *table, int nents, +static int sg_alloc_table_chained(struct sg_table *table, int nents, struct scatterlist *first_chunk) { int ret; @@ -606,9 +606,9 @@ static int scsi_alloc_sgtable(struct sg_table *table, int nents, } ret = __sg_alloc_table(table, nents, SCSI_MAX_SG_SEGMENTS, - first_chunk, GFP_ATOMIC, scsi_sg_alloc); + first_chunk, GFP_ATOMIC, sg_pool_alloc); if (unlikely(ret)) - scsi_free_sgtable(table, (bool)first_chunk); + sg_free_table_chained(table, (bool)first_chunk); return ret; } @@ -627,14 +627,14 @@ static void scsi_mq_free_sgtables(struct scsi_cmnd *cmd) struct scsi_data_buffer *sdb; if (cmd->sdb.table.nents) - scsi_free_sgtable(&cmd->sdb.table, true); + sg_free_table_chained(&cmd->sdb.table, true); if (cmd->request->next_rq) { sdb = cmd->request->next_rq->special; if (sdb) - scsi_free_sgtable(&sdb->table, true); + sg_free_table_chained(&sdb->table, true); } if (scsi_prot_sg_count(cmd)) - scsi_free_sgtable(&cmd->prot_sdb->table, true); + sg_free_table_chained(&cmd->prot_sdb->table, true); } static void scsi_mq_uninit_cmd(struct scsi_cmnd *cmd) @@ -673,19 +673,19 @@ static void scsi_mq_uninit_cmd(struct scsi_cmnd *cmd) static void scsi_release_buffers(struct scsi_cmnd *cmd) { if (cmd->sdb.table.nents) - scsi_free_sgtable(&cmd->sdb.table, false); + sg_free_table_chained(&cmd->sdb.table, false); memset(&cmd->sdb, 0, sizeof(cmd->sdb)); if (scsi_prot_sg_count(cmd)) - scsi_free_sgtable(&cmd->prot_sdb->table, false); + sg_free_table_chained(&cmd->prot_sdb->table, false); } static void scsi_release_bidi_buffers(struct scsi_cmnd *cmd) { struct scsi_data_buffer *bidi_sdb = cmd->request->next_rq->special; - scsi_free_sgtable(&bidi_sdb->table, false); + sg_free_table
[PATCH v2 5/5] lib: scatterlist: move SG pool code from SCSI driver to lib/sg_pool.c
From: Ming Lin Now it's ready to move the mempool based SG chained allocator code from SCSI driver to lib/sg_pool.c, which will be compiled only based on a Kconfig symbol CONFIG_SG_POOL. SCSI selects CONFIG_SG_POOL. Signed-off-by: Ming Lin --- drivers/scsi/Kconfig| 1 + drivers/scsi/scsi_lib.c | 137 --- include/linux/scatterlist.h | 25 +++ include/scsi/scsi.h | 19 - lib/Kconfig | 7 ++ lib/Makefile| 1 + lib/sg_pool.c | 172 7 files changed, 206 insertions(+), 156 deletions(-) create mode 100644 lib/sg_pool.c diff --git a/drivers/scsi/Kconfig b/drivers/scsi/Kconfig index e2f31c9..ee9cf41 100644 --- a/drivers/scsi/Kconfig +++ b/drivers/scsi/Kconfig @@ -17,6 +17,7 @@ config SCSI tristate "SCSI device support" depends on BLOCK select SCSI_DMA if HAS_DMA + select SG_POOL ---help--- If you want to use a SCSI hard disk, SCSI tape drive, SCSI CD-ROM or any other SCSI device under Linux, say Y and make sure that you know diff --git a/drivers/scsi/scsi_lib.c b/drivers/scsi/scsi_lib.c index 478b0e8..6d818e8 100644 --- a/drivers/scsi/scsi_lib.c +++ b/drivers/scsi/scsi_lib.c @@ -14,8 +14,6 @@ #include #include #include -#include -#include #include #include #include @@ -40,39 +38,6 @@ #include "scsi_logging.h" -#define SG_MEMPOOL_NR ARRAY_SIZE(sg_pools) -#define SG_MEMPOOL_SIZE2 - -struct sg_pool { - size_t size; - char*name; - struct kmem_cache *slab; - mempool_t *pool; -}; - -#define SP(x) { .size = x, "sgpool-" __stringify(x) } -#if (SG_CHUNK_SIZE < 32) -#error SG_CHUNK_SIZE is too small (must be 32 or greater) -#endif -static struct sg_pool sg_pools[] = { - SP(8), - SP(16), -#if (SG_CHUNK_SIZE > 32) - SP(32), -#if (SG_CHUNK_SIZE > 64) - SP(64), -#if (SG_CHUNK_SIZE > 128) - SP(128), -#if (SG_CHUNK_SIZE > 256) -#error SG_CHUNK_SIZE is too large (256 MAX) -#endif -#endif -#endif -#endif - SP(SG_CHUNK_SIZE) -}; -#undef SP - struct kmem_cache *scsi_sdb_cache; /* @@ -553,65 +518,6 @@ void scsi_run_host_queues(struct Scsi_Host *shost) scsi_run_queue(sdev->request_queue); } -static inline unsigned int sg_pool_index(unsigned short nents) -{ - unsigned int index; - - BUG_ON(nents > SG_CHUNK_SIZE); - - if (nents <= 8) - index = 0; - else - index = get_count_order(nents) - 3; - - return index; -} - -static void sg_pool_free(struct scatterlist *sgl, unsigned int nents) -{ - struct sg_pool *sgp; - - sgp = sg_pools + sg_pool_index(nents); - mempool_free(sgl, sgp->pool); -} - -static struct scatterlist *sg_pool_alloc(unsigned int nents, gfp_t gfp_mask) -{ - struct sg_pool *sgp; - - sgp = sg_pools + sg_pool_index(nents); - return mempool_alloc(sgp->pool, gfp_mask); -} - -static void sg_free_table_chained(struct sg_table *table, bool first_chunk) -{ - if (first_chunk && table->orig_nents <= SG_CHUNK_SIZE) - return; - __sg_free_table(table, SG_CHUNK_SIZE, first_chunk, sg_pool_free); -} - -static int sg_alloc_table_chained(struct sg_table *table, int nents, - struct scatterlist *first_chunk) -{ - int ret; - - BUG_ON(!nents); - - if (first_chunk) { - if (nents <= SG_CHUNK_SIZE) { - table->nents = table->orig_nents = nents; - sg_init_table(table->sgl, nents); - return 0; - } - } - - ret = __sg_alloc_table(table, nents, SG_CHUNK_SIZE, - first_chunk, GFP_ATOMIC, sg_pool_alloc); - if (unlikely(ret)) - sg_free_table_chained(table, (bool)first_chunk); - return ret; -} - static void scsi_uninit_cmd(struct scsi_cmnd *cmd) { if (cmd->request->cmd_type == REQ_TYPE_FS) { @@ -2269,8 +2175,6 @@ EXPORT_SYMBOL(scsi_unblock_requests); int __init scsi_init_queue(void) { - int i; - scsi_sdb_cache = kmem_cache_create("scsi_data_buffer", sizeof(struct scsi_data_buffer), 0, 0, NULL); @@ -2279,53 +2183,12 @@ int __init scsi_init_queue(void) return -ENOMEM; } - for (i = 0; i < SG_MEMPOOL_NR; i++) { - struct sg_pool *sgp = sg_pools + i; - int size = sgp->size * sizeof(struct scatterlist); - - sgp->slab = kmem_cache_create(sgp->name, size, 0, - SLAB_HWCACHE_ALIGN, NULL); - if (!sgp->slab) { - printk(
Re: [PATCH RFC 1/2] scatterlist: add mempool based chained SG alloc/free api
On Wed, 2016-03-16 at 09:23 +0100, Christoph Hellwig wrote: > > > We can defintively kill this one. We want to support different size of pools. How can we kill this one? Or did you mean we just create a single pool with size SG_CHUNK_SIZE? > > > +static __init int sg_mempool_init(void) > > +{ > > + int i; > > + > > + for (i = 0; i < SG_MEMPOOL_NR; i++) { > > + struct sg_mempool *sgp = sg_pools + i; > > + int size = sgp->size * sizeof(struct scatterlist); > > + > > + sgp->slab = kmem_cache_create(sgp->name, size, 0, > > + SLAB_HWCACHE_ALIGN, NULL); > > Having these mempoools around in every kernel will make some embedded > developers rather unhappy. We could either not create them at > runtime, which would require either a check in the fast path, or > an init call in every driver, or just move the functions you > added into a separe file, which will be compiled only based on a > Kconfig > symbol, and could even be potentially modular. I think that > second option might be easier. I created lib/sg_pool.c with CONFIG_SG_POOL. -- 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
Re: [PATCH RFC 0/2] mempool based chained scatterlist alloc/free api api
On Tue, 2016-03-15 at 16:12 -0700, James Bottomley wrote: > On Tue, 2016-03-15 at 15:39 -0700, Ming Lin wrote: > > From: Ming Lin > > > > Hi list, > > > > This moves the mempool based chained scatterlist alloc/free code > > from > > scsi_lib.c to lib/scatterlist.c. > > > > So other drivers(for example, the under development NVMe over > > fabric > > drivers) can also use it. > > > > Ming Lin (2): > > scatterlist: add mempool based chained SG alloc/free api > > scsi: use the new chained SG api > > > > drivers/scsi/scsi_lib.c | 129 ++ > > -- > > include/linux/scatterlist.h | 12 > > lib/scatterlist.c | 156 > > > > 3 files changed, 175 insertions(+), 122 deletions(-) > > I'd really rather this were a single patch so git can tell us the > code > motion. If you add in one patch and remove in another the code > motion > trackers don't see it. > > Secondly, you said "This copied code from scsi_lib.c to scatterlist.c > and modified it a bit" could you move in one patch and modify in > another, so we can see exactly what you're changing. The modification is mostly about structure names and function names changes. I can do it in a single patch. > > Thirdly, are you sure the pool structure for NVMe should be the same > as > for SCSI? We don't do buddy pools for 1,2 or 4 entry transactions in > SCSI just basically because of heuristics, but the packetised io > characteristics of NVMe make single entry lists more likely for it, > don't they? Not sure about this, but the nvme-pci driver may not use this api, because it also has a PRP lists except for the SG lists. But nvme-over-rdma/nvme-over-fiber-channel driver is good to use this api. > > James > > -- 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
[PATCH RFC 1/2] scatterlist: add mempool based chained SG alloc/free api
From: Ming Lin This copied code from scsi_lib.c to scatterlist.c and modified it a bit. Signed-off-by: Ming Lin --- include/linux/scatterlist.h | 12 lib/scatterlist.c | 156 2 files changed, 168 insertions(+) diff --git a/include/linux/scatterlist.h b/include/linux/scatterlist.h index 556ec1e..888f2c3 100644 --- a/include/linux/scatterlist.h +++ b/include/linux/scatterlist.h @@ -266,6 +266,10 @@ int sg_alloc_table_from_pages(struct sg_table *sgt, unsigned long offset, unsigned long size, gfp_t gfp_mask); +void sg_free_chained(struct sg_table *table, bool first_chunk); +int sg_alloc_chained(struct sg_table *table, int nents, + struct scatterlist *first_chunk, gfp_t gfp); + size_t sg_copy_buffer(struct scatterlist *sgl, unsigned int nents, void *buf, size_t buflen, off_t skip, bool to_buffer); @@ -286,6 +290,14 @@ size_t sg_pcopy_to_buffer(struct scatterlist *sgl, unsigned int nents, #define SG_MAX_SINGLE_ALLOC(PAGE_SIZE / sizeof(struct scatterlist)) /* + * The maximum number of SG segments that we will put inside a + * scatterlist. + * + * XXX: what's the best number? + */ +#define SG_MAX_SEGMENTS128 + +/* * sg page iterator * * Iterates over sg entries page-by-page. On each successful iteration, diff --git a/lib/scatterlist.c b/lib/scatterlist.c index 004fc70..f97831e 100644 --- a/lib/scatterlist.c +++ b/lib/scatterlist.c @@ -11,6 +11,7 @@ #include #include #include +#include /** * sg_next - return the next scatterlist entry in a list @@ -755,3 +756,158 @@ size_t sg_pcopy_to_buffer(struct scatterlist *sgl, unsigned int nents, return sg_copy_buffer(sgl, nents, buf, buflen, skip, true); } EXPORT_SYMBOL(sg_pcopy_to_buffer); + +#define SG_MEMPOOL_NR ARRAY_SIZE(sg_pools) +#define SG_MEMPOOL_SIZE2 + +struct sg_mempool { + size_t size; + char*name; + struct kmem_cache *slab; + mempool_t *pool; +}; + +#define SP(x) { .size = x, "sgpool-" __stringify(x) } +#if (SG_MAX_SEGMENTS < 32) +#error SG_MAX_SEGMENTS is too small (must be 32 or greater) +#endif +static struct sg_mempool sg_pools[] = { + SP(8), + SP(16), +#if (SG_MAX_SEGMENTS > 32) + SP(32), +#if (SG_MAX_SEGMENTS > 64) + SP(64), +#if (SG_MAX_SEGMENTS > 128) + SP(128), +#if (SG_MAX_SEGMENTS > 256) +#error SG_MAX_SEGMENTS is too large (256 MAX) +#endif +#endif +#endif +#endif + SP(SG_MAX_SEGMENTS) +}; +#undef SP + +static inline unsigned int sg_pool_index(unsigned short nents) +{ + unsigned int index; + + BUG_ON(nents > SG_MAX_SEGMENTS); + + if (nents <= 8) + index = 0; + else + index = get_count_order(nents) - 3; + + return index; +} + +static void sg_mempoll_free(struct scatterlist *sgl, unsigned int nents) +{ + struct sg_mempool *sgp; + + sgp = sg_pools + sg_pool_index(nents); + mempool_free(sgl, sgp->pool); +} + +static struct scatterlist *sg_mempool_alloc(unsigned int nents, gfp_t gfp) +{ + struct sg_mempool *sgp; + + sgp = sg_pools + sg_pool_index(nents); + return mempool_alloc(sgp->pool, gfp); +} + +/** + * sg_free_chained - Free a previously mapped sg table + * @table: The sg table header to use + * @first_chunk: was first_chunk not NULL in sg_alloc_chained? + * + * Description: + *Free an sg table previously allocated and setup with + *sg_alloc_chained(). + * + **/ +void sg_free_chained(struct sg_table *table, bool first_chunk) +{ + if (first_chunk && table->orig_nents <= SG_MAX_SEGMENTS) + return; + __sg_free_table(table, SG_MAX_SEGMENTS, 1, sg_mempoll_free); +} +EXPORT_SYMBOL_GPL(sg_free_chained); + +/** + * sg_alloc_chained - Allocate and chain SGLs in an sg table + * @table: The sg table header to use + * @nents: Number of entries in sg list + * @first_chunk: first SGL + * @gfp: GFP allocation mask + * + * Description: + *Allocate and chain SGLs in an sg table. If @nents@ is larger than + *SG_MAX_SEGMENTS a chained sg table will be setup. + * + **/ +int sg_alloc_chained(struct sg_table *table, int nents, + struct scatterlist *first_chunk, gfp_t gfp) +{ + int ret; + + BUG_ON(!nents); + + if (first_chunk && nents <= SG_MAX_SEGMENTS) { + table->nents = table->orig_nents = nents; + sg_init_table(first_chunk, nents); + return 0; + } + + ret = __sg_alloc_table(table, nents, SG_MAX_SEGMENTS, + first_chunk, gfp, sg_mempool_alloc); + if (unlikely(ret)) + sg_free_chained(table, (bool)first_chunk); + + return ret; +} +EXPORT_SYMBOL_GPL(sg_alloc_chained); + +static __init int sg_mempoo
[PATCH RFC 0/2] mempool based chained scatterlist alloc/free api api
From: Ming Lin Hi list, This moves the mempool based chained scatterlist alloc/free code from scsi_lib.c to lib/scatterlist.c. So other drivers(for example, the under development NVMe over fabric drivers) can also use it. Ming Lin (2): scatterlist: add mempool based chained SG alloc/free api scsi: use the new chained SG api drivers/scsi/scsi_lib.c | 129 ++-- include/linux/scatterlist.h | 12 lib/scatterlist.c | 156 3 files changed, 175 insertions(+), 122 deletions(-) -- 1.9.1 -- 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
[PATCH RFC 2/2] scsi: use the new chained SG api
From: Ming Lin This removes the old code and uses the new chained SG alloc/free api. Signed-off-by: Ming Lin --- drivers/scsi/scsi_lib.c | 129 +++- 1 file changed, 7 insertions(+), 122 deletions(-) diff --git a/drivers/scsi/scsi_lib.c b/drivers/scsi/scsi_lib.c index 8c6e318..97e283c 100644 --- a/drivers/scsi/scsi_lib.c +++ b/drivers/scsi/scsi_lib.c @@ -39,40 +39,6 @@ #include "scsi_priv.h" #include "scsi_logging.h" - -#define SG_MEMPOOL_NR ARRAY_SIZE(scsi_sg_pools) -#define SG_MEMPOOL_SIZE2 - -struct scsi_host_sg_pool { - size_t size; - char*name; - struct kmem_cache *slab; - mempool_t *pool; -}; - -#define SP(x) { .size = x, "sgpool-" __stringify(x) } -#if (SCSI_MAX_SG_SEGMENTS < 32) -#error SCSI_MAX_SG_SEGMENTS is too small (must be 32 or greater) -#endif -static struct scsi_host_sg_pool scsi_sg_pools[] = { - SP(8), - SP(16), -#if (SCSI_MAX_SG_SEGMENTS > 32) - SP(32), -#if (SCSI_MAX_SG_SEGMENTS > 64) - SP(64), -#if (SCSI_MAX_SG_SEGMENTS > 128) - SP(128), -#if (SCSI_MAX_SG_SEGMENTS > 256) -#error SCSI_MAX_SG_SEGMENTS is too large (256 MAX) -#endif -#endif -#endif -#endif - SP(SCSI_MAX_SG_SEGMENTS) -}; -#undef SP - struct kmem_cache *scsi_sdb_cache; /* @@ -553,61 +519,23 @@ void scsi_run_host_queues(struct Scsi_Host *shost) scsi_run_queue(sdev->request_queue); } -static inline unsigned int scsi_sgtable_index(unsigned short nents) -{ - unsigned int index; - - BUG_ON(nents > SCSI_MAX_SG_SEGMENTS); - - if (nents <= 8) - index = 0; - else - index = get_count_order(nents) - 3; - - return index; -} - -static void scsi_sg_free(struct scatterlist *sgl, unsigned int nents) -{ - struct scsi_host_sg_pool *sgp; - - sgp = scsi_sg_pools + scsi_sgtable_index(nents); - mempool_free(sgl, sgp->pool); -} - -static struct scatterlist *scsi_sg_alloc(unsigned int nents, gfp_t gfp_mask) -{ - struct scsi_host_sg_pool *sgp; - - sgp = scsi_sg_pools + scsi_sgtable_index(nents); - return mempool_alloc(sgp->pool, gfp_mask); -} - static void scsi_free_sgtable(struct scsi_data_buffer *sdb, bool mq) { - if (mq && sdb->table.orig_nents <= SCSI_MAX_SG_SEGMENTS) - return; - __sg_free_table(&sdb->table, SCSI_MAX_SG_SEGMENTS, mq, scsi_sg_free); + sg_free_chained(&sdb->table, mq); } static int scsi_alloc_sgtable(struct scsi_data_buffer *sdb, int nents, bool mq) { - struct scatterlist *first_chunk = NULL; + struct scatterlist *first_chunk; int ret; - BUG_ON(!nents); - - if (mq) { - if (nents <= SCSI_MAX_SG_SEGMENTS) { - sdb->table.nents = sdb->table.orig_nents = nents; - sg_init_table(sdb->table.sgl, nents); - return 0; - } + if (mq) first_chunk = sdb->table.sgl; - } + else + first_chunk = NULL; + + ret = sg_alloc_chained(&sdb->table, nents, first_chunk, GFP_ATOMIC); - ret = __sg_alloc_table(&sdb->table, nents, SCSI_MAX_SG_SEGMENTS, - first_chunk, GFP_ATOMIC, scsi_sg_alloc); if (unlikely(ret)) scsi_free_sgtable(sdb, mq); return ret; @@ -2264,8 +2192,6 @@ EXPORT_SYMBOL(scsi_unblock_requests); int __init scsi_init_queue(void) { - int i; - scsi_sdb_cache = kmem_cache_create("scsi_data_buffer", sizeof(struct scsi_data_buffer), 0, 0, NULL); @@ -2274,53 +2200,12 @@ int __init scsi_init_queue(void) return -ENOMEM; } - for (i = 0; i < SG_MEMPOOL_NR; i++) { - struct scsi_host_sg_pool *sgp = scsi_sg_pools + i; - int size = sgp->size * sizeof(struct scatterlist); - - sgp->slab = kmem_cache_create(sgp->name, size, 0, - SLAB_HWCACHE_ALIGN, NULL); - if (!sgp->slab) { - printk(KERN_ERR "SCSI: can't init sg slab %s\n", - sgp->name); - goto cleanup_sdb; - } - - sgp->pool = mempool_create_slab_pool(SG_MEMPOOL_SIZE, -sgp->slab); - if (!sgp->pool) { - printk(KERN_ERR "SCSI: can't init sg mempool %s\n", - sgp->name); - goto cleanup_sdb; - } - } - return 0; - -cleanup_sdb: - for (i = 0; i < SG_MEMPOOL_