[RFC PATCH 1/1] scsi: sd: associate sd_probe_domain with scsi_disk

2019-04-04 Thread Ming Lin
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

2019-04-04 Thread Ming Lin
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

2016-06-07 Thread Ming Lin
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

2016-04-11 Thread Ming Lin
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

2016-04-10 Thread Ming Lin
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

2016-04-07 Thread Ming Lin
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

2016-04-07 Thread Ming Lin
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

2016-04-04 Thread Ming Lin
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

2016-04-04 Thread Ming Lin
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

2016-04-04 Thread Ming Lin
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

2016-04-04 Thread Ming Lin
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

2016-04-04 Thread Ming Lin
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

2016-04-04 Thread Ming Lin
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

2016-04-04 Thread Ming Lin
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

2016-04-04 Thread Ming Lin
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

2016-04-04 Thread Ming Lin
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

2016-04-03 Thread Ming Lin
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

2016-03-28 Thread Ming Lin
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

2016-03-24 Thread Ming Lin
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

2016-03-22 Thread Ming Lin
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

2016-03-22 Thread Ming Lin
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

2016-03-22 Thread Ming Lin
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

2016-03-22 Thread Ming Lin
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

2016-03-22 Thread Ming Lin
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

2016-03-22 Thread Ming Lin
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

2016-03-20 Thread Ming Lin
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

2016-03-15 Thread Ming Lin
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

2016-03-15 Thread Ming Lin
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

2016-03-15 Thread Ming Lin
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

2016-03-15 Thread Ming Lin
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_