Re: [PATCH 0/9] block/scsi: Implement SMR drive support

2016-04-09 Thread Hannes Reinecke

On 04/08/2016 08:35 PM, Shaun Tancheff wrote:

On Mon, Apr 4, 2016 at 5:00 PM, Hannes Reinecke  wrote:

Hi all,

here's a patchset implementing SMR (shingled magnetic recording)
device support for the block and SCSI layer.

There are two main parts to it:
- mapping the 'RESET WRITE POINTER' command to the 'discard' functionality.
   The 'RESET WRITE POINTER' operation is pretty close to the existing
   'discard' functionality with the 'discard_zeroes_blocks' bit set.
   So I've added a new 'reset_wp' provisioning mode for this.


Completely agree with the REQ_OP_DISCARD -> Reset WP translation
seems like a good idea. I have tried something similar and ended up
essentially adding a 'reset wp' flag instead.
Now I am optimistic to see if I can use you patch to get the
discard -> reset wp working in my device mapper.

It works quite well here with my setup, although I've tripped across two 
caveats:


- We currently don't handle conventional zones.
  It would make sense to fallback to normal block zeroing here.
- Issuing 'RESET WP' is dead slow (at least on the prototypes I've had)
  Short-circuiting it for empty zones is a _major_ performance win here;
  the time for issuing discards for an entire drive is reduced by
  several orders of magnitude. So you absolutely need an in-kernel
  zone tree for this.


- Adding a 'zone' pointer to the request queue. This pointer holds an
   RB-tree with the zone information, which can be used by other layers
   to access the write pointer.


Here is where I have some concerns. Having a common in-kernel
shadow of the drive's zone state seems problematic to me.


Well, this is the general SMR programming model, is it not?
And as already pointed out above you really want this tree to be present 
to avoid unnecessary RESET WP calls.
You also need it to format READ calls correctly for host-managed drives; 
from my understanding of the programming model any READ call crossing 
the write pointer will be aborted.
Which you could easily circumvent by splitting the READ call in two 
parts, one up to the read pointer and another beyond it. For which again 
you need the zone tree.



Also if I am understanding the direction here it is to hold the zone
information in an rbtree. Since that comes to just under 30,000
entries I think it would be better to shift to an array of
write pointer offsets.

The thing is that using an rbtree might actually be faster than an 
array; the rbtree entries easily fit into the processor cache, whereas 
the array doesn't. So you might end up having a slower access when using 
arrays despite being easier to code.



At the moment my translation layer keeps track of activity and state
of all the zones on the drive so that is how I have been handling
the zone data up to this point.

As outlined above: Any driver/filesystem need access to the zone states 
as it might need to align its internal structures to the zones.
But you also need to keep track of the zones in the SCSI layer so as to 
format the RESET WP correctly. Which means you basically need a common tree.


As you might've seen I've also programmed my own zoned device-mapper 
device, caching individual zones. We should discuss if those two 
approached can't be merged, to end up with a common device-mapper target.


Cheers,

Hannes
--
Dr. Hannes Reinecke   zSeries & Storage
h...@suse.de  +49 911 74053 688
SUSE LINUX Products GmbH, Maxfeldstr. 5, 90409 Nürnberg
GF: J. Hawn, J. Guild, F. Imendörffer, HRB 16746 (AG Nürnberg)
--
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: [RFC 14/34] iscsi-target: export symbols

2016-04-09 Thread Varun Prakash
On Fri, Apr 08, 2016 at 12:16:43AM -0700, Nicholas A. Bellinger wrote:
> On Sun, 2016-03-13 at 17:43 +0530, Varun Prakash wrote:
> > On Fri, Mar 11, 2016 at 10:28:33PM -0800, Nicholas A. Bellinger wrote:
> > > Hi Varun & Co,
> > > 
> > > On Mon, 2016-03-07 at 15:22 -0800, Nicholas A. Bellinger wrote:
> > > 
> > > 
> > > 
> > > The drivers/net/ethernet/chelsio/cxgb4/ prerequisites for supporting
> > > iscsi segment offload (ISO) + page pod manager (PPM) are in
> > > target-pending/for-next-merge, and patches #13+ have been dropped
> > > for initial v4.6-rc1 merge.
> > > 
> > > Also, there haven't been any further linux-next subsystem merge failures
> > > beyond the initial t4fw_api.h conflict as reported by SFR.
> > > 
> > > https://lkml.org/lkml/2016/2/29/34
> > > 
> > > So please go ahead and post stand-alone cxgb4 driver changes for
> > > initial ISO + PPM to net-dev + target-devel, and Hariprasad should
> > > review + ack these ASAP.
> > 
> > Yes, I will post cxgb4 patch series, thanks.
> 
> Great.  Just curious how -v2 is coming along..?
> 
> I've got a few cycles over the weekend, and plan to start reviewing as
> the series hits the list.
>
 
I will post v2 series today, thanks.

> Btw, I asked Sagi to help out with review as well.
>
--
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 02/16] iscsi-target: add int (*iscsit_xmit_pdu)()

2016-04-09 Thread Varun Prakash
Add int (*iscsit_xmit_pdu)() to
struct iscsit_transport, iscsi-target
uses this callback to transmit an
iSCSI PDU.

Signed-off-by: Varun Prakash 
---
 drivers/target/iscsi/iscsi_target.c| 391 +
 include/target/iscsi/iscsi_transport.h |   2 +
 2 files changed, 102 insertions(+), 291 deletions(-)

diff --git a/drivers/target/iscsi/iscsi_target.c 
b/drivers/target/iscsi/iscsi_target.c
index fdb33ba..0e7a481 100644
--- a/drivers/target/iscsi/iscsi_target.c
+++ b/drivers/target/iscsi/iscsi_target.c
@@ -504,6 +504,79 @@ static void *iscsit_alloc_pdu(struct iscsi_conn *conn, 
struct iscsi_cmd *cmd)
return cmd->pdu;
 }
 
+static void iscsit_do_crypto_hash_buf(struct ahash_request *, const void *,
+ u32, u32, u8 *, u8 *);
+static void iscsit_tx_thread_wait_for_tcp(struct iscsi_conn *);
+
+static int iscsit_xmit_pdu(struct iscsi_conn *conn, struct iscsi_cmd *cmd,
+  const void *data_buf, u32 data_buf_len)
+{
+   struct iscsi_hdr *hdr = (struct iscsi_hdr *)cmd->pdu;
+   struct kvec *iov;
+   u32 niov = 0, tx_size = ISCSI_HDR_LEN;
+   int ret;
+
+   iov = &cmd->iov_misc[0];
+   iov[niov].iov_base  = cmd->pdu;
+   iov[niov++].iov_len = ISCSI_HDR_LEN;
+
+   if (conn->conn_ops->HeaderDigest) {
+   u32 *header_digest = (u32 *)&cmd->pdu[ISCSI_HDR_LEN];
+
+   iscsit_do_crypto_hash_buf(conn->conn_tx_hash, hdr,
+ ISCSI_HDR_LEN, 0, NULL,
+ (u8 *)header_digest);
+
+   iov[0].iov_len += ISCSI_CRC_LEN;
+   tx_size += ISCSI_CRC_LEN;
+   pr_debug("Attaching CRC32C HeaderDigest"
+" to opcode 0x%x 0x%08x\n",
+hdr->opcode, *header_digest);
+   }
+
+   if (data_buf_len) {
+   u32 padding = ((-data_buf_len) & 3);
+
+   iov[niov].iov_base  = (void *)data_buf;
+   iov[niov++].iov_len = data_buf_len;
+   tx_size += data_buf_len;
+
+   if (padding != 0) {
+   iov[niov].iov_base = &cmd->pad_bytes;
+   iov[niov++].iov_len = padding;
+   tx_size += padding;
+   pr_debug("Attaching %u additional"
+" padding bytes.\n", padding);
+   }
+
+   if (conn->conn_ops->DataDigest) {
+   iscsit_do_crypto_hash_buf(conn->conn_tx_hash,
+ data_buf, data_buf_len,
+ padding,
+ (u8 *)&cmd->pad_bytes,
+ (u8 *)&cmd->data_crc);
+
+   iov[niov].iov_base = &cmd->data_crc;
+   iov[niov++].iov_len = ISCSI_CRC_LEN;
+   tx_size += ISCSI_CRC_LEN;
+   pr_debug("Attached DataDigest for %u"
+" bytes opcode 0x%x, CRC 0x%08x\n",
+data_buf_len, hdr->opcode, cmd->data_crc);
+   }
+   }
+
+   cmd->iov_misc_count = niov;
+   cmd->tx_size = tx_size;
+
+   ret = iscsit_send_tx_data(cmd, conn, 1);
+   if (ret < 0) {
+   iscsit_tx_thread_wait_for_tcp(conn);
+   return ret;
+   }
+
+   return 0;
+}
+
 static enum target_prot_op iscsit_get_sup_prot_ops(struct iscsi_conn *conn)
 {
return TARGET_PROT_NORMAL;
@@ -525,6 +598,7 @@ static struct iscsit_transport iscsi_target_transport = {
.iscsit_queue_status= iscsit_queue_rsp,
.iscsit_aborted_task= iscsit_aborted_task,
.iscsit_alloc_pdu   = iscsit_alloc_pdu,
+   .iscsit_xmit_pdu= iscsit_xmit_pdu,
.iscsit_get_sup_prot_ops = iscsit_get_sup_prot_ops,
 };
 
@@ -2540,7 +2614,6 @@ static int iscsit_send_conn_drop_async_message(
 {
struct iscsi_async *hdr;
 
-   cmd->tx_size = ISCSI_HDR_LEN;
cmd->iscsi_opcode = ISCSI_OP_ASYNC_EVENT;
 
hdr = conn->conn_transport->iscsit_alloc_pdu(conn, cmd);
@@ -2561,25 +2634,11 @@ static int iscsit_send_conn_drop_async_message(
hdr->param2 = 
cpu_to_be16(conn->sess->sess_ops->DefaultTime2Wait);
hdr->param3 = 
cpu_to_be16(conn->sess->sess_ops->DefaultTime2Retain);
 
-   if (conn->conn_ops->HeaderDigest) {
-   u32 *header_digest = (u32 *)&cmd->pdu[ISCSI_HDR_LEN];
-
-   iscsit_do_crypto_hash_buf(conn->conn_tx_hash, hdr,
-   ISCSI_HDR_LEN, 0, NULL, (u8 *)header_digest);
-
-   cmd->tx_size += ISCSI_CRC_LEN;
-   pr_debug("Attaching CRC32C HeaderDigest to"
-   " Async Message 0x%08x\n", *header_digest);
-   }
-
-   cmd->iov_misc[0].iov_base 

[PATCH v2 00/16] Chelsio iSCSI target offload driver

2016-04-09 Thread Varun Prakash
This is v2 patch series for Chelsio iSCSI target offload
driver(cxgbit.ko).

cxgbit.ko registers with iSCSI target transport and
offloads multiple CPU intensive tasks to
Chelsio T5 adapters.

T5 adapters has following offload features for
iSCSI
-TCP/IP offload
-iSCSI PDU recovery by reassembling TCP segments.
-Header and Data Digest offload.
-iSCSI segmentation offload(ISO).
-Direct Data Placement(DDP).

-v2
 - added hw offload transport type (Nicholas).
 - added PDU alloc, free, xmit callbacks (Nicholas).
 - created single patch for all cxgbit.ko files (Nicholas).
 - merged definition and usage of int (*iscsit_validate_params)()
   in a single patch (Christoph).
 - merged definition and usage of void (*iscsit_release_cmd)()
   in a single patch (Christoph).
 - renamed void (*iscsit_rx_pdu)() to void (*iscsit_get_rx_pdu)() (Sagi).  
 - added dependency on INET in Kconfig (Arnd).
 - added check for NULL sg in cxgbit_set_one_ppod() (Dan Carpenter). 

Please review.

Thanks

Varun Prakash (16):
  iscsi-target: add callback to alloc and free PDU
  iscsi-target: add int (*iscsit_xmit_pdu)()
  iscsi-target: add int (*iscsit_xmit_datain_pdu)()
  iscsi-target: add void (*iscsit_release_cmd)()
  iscsi-target: add void (*iscsit_get_rx_pdu)()
  iscsi-target: split iscsi_target_rx_thread()
  iscsi-target: add int (*iscsit_validate_params)()
  iscsi-target: add void (*iscsit_get_r2t_ttt)()
  iscsi-target: move iscsit_thread_check_cpumask()
  iscsi-target: use conn->network_transport in text rsp
  iscsi-target: add new offload transport type
  iscsi-target: clear tx_thread_active
  iscsi-target: call complete on conn_logout_comp
  iscsi-target: export symbols
  iscsi-target: fix seq_end_offset calculation
  cxgbit: add files for cxgbit.ko

 drivers/infiniband/ulp/isert/ib_isert.c   |   10 +
 drivers/target/iscsi/Kconfig  |2 +
 drivers/target/iscsi/Makefile |1 +
 drivers/target/iscsi/cxgbit/Kconfig   |7 +
 drivers/target/iscsi/cxgbit/Makefile  |6 +
 drivers/target/iscsi/cxgbit/cxgbit.h  |  358 
 drivers/target/iscsi/cxgbit/cxgbit_cm.c   | 2086 +
 drivers/target/iscsi/cxgbit/cxgbit_ddp.c  |  325 
 drivers/target/iscsi/cxgbit/cxgbit_lro.h  |   72 +
 drivers/target/iscsi/cxgbit/cxgbit_main.c |  703 +++
 drivers/target/iscsi/cxgbit/cxgbit_target.c   | 1601 
 drivers/target/iscsi/iscsi_target.c   |  740 +++-
 drivers/target/iscsi/iscsi_target_configfs.c  |   76 +
 drivers/target/iscsi/iscsi_target_datain_values.c |1 +
 drivers/target/iscsi/iscsi_target_erl0.c  |6 +-
 drivers/target/iscsi/iscsi_target_login.c |   13 +-
 drivers/target/iscsi/iscsi_target_nego.c  |1 +
 drivers/target/iscsi/iscsi_target_parameters.c|1 +
 drivers/target/iscsi/iscsi_target_util.c  |5 +
 include/target/iscsi/iscsi_target_core.h  |   27 +
 include/target/iscsi/iscsi_transport.h|   45 +
 21 files changed, 5648 insertions(+), 438 deletions(-)
 create mode 100644 drivers/target/iscsi/cxgbit/Kconfig
 create mode 100644 drivers/target/iscsi/cxgbit/Makefile
 create mode 100644 drivers/target/iscsi/cxgbit/cxgbit.h
 create mode 100644 drivers/target/iscsi/cxgbit/cxgbit_cm.c
 create mode 100644 drivers/target/iscsi/cxgbit/cxgbit_ddp.c
 create mode 100644 drivers/target/iscsi/cxgbit/cxgbit_lro.h
 create mode 100644 drivers/target/iscsi/cxgbit/cxgbit_main.c
 create mode 100644 drivers/target/iscsi/cxgbit/cxgbit_target.c

-- 
2.0.2

--
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 01/16] iscsi-target: add callback to alloc and free PDU

2016-04-09 Thread Varun Prakash
Add two callbacks to struct iscsit_transport -

1. void *(*iscsit_alloc_pdu)()
   iscsi-target uses this callback for
   iSCSI PDU allocation.

2. void (*iscsit_free_pdu)
   iscsi-target uses this callback
   to free an iSCSI PDU which was
   allocated by iscsit_alloc_pdu().

Signed-off-by: Varun Prakash 
---
 drivers/target/iscsi/iscsi_target.c| 76 --
 include/target/iscsi/iscsi_transport.h |  2 +
 2 files changed, 65 insertions(+), 13 deletions(-)

diff --git a/drivers/target/iscsi/iscsi_target.c 
b/drivers/target/iscsi/iscsi_target.c
index 961202f..fdb33ba 100644
--- a/drivers/target/iscsi/iscsi_target.c
+++ b/drivers/target/iscsi/iscsi_target.c
@@ -499,6 +499,11 @@ static void iscsit_aborted_task(struct iscsi_conn *conn, 
struct iscsi_cmd *cmd)
__iscsit_free_cmd(cmd, scsi_cmd, true);
 }
 
+static void *iscsit_alloc_pdu(struct iscsi_conn *conn, struct iscsi_cmd *cmd)
+{
+   return cmd->pdu;
+}
+
 static enum target_prot_op iscsit_get_sup_prot_ops(struct iscsi_conn *conn)
 {
return TARGET_PROT_NORMAL;
@@ -519,6 +524,7 @@ static struct iscsit_transport iscsi_target_transport = {
.iscsit_queue_data_in   = iscsit_queue_rsp,
.iscsit_queue_status= iscsit_queue_rsp,
.iscsit_aborted_task= iscsit_aborted_task,
+   .iscsit_alloc_pdu   = iscsit_alloc_pdu,
.iscsit_get_sup_prot_ops = iscsit_get_sup_prot_ops,
 };
 
@@ -2537,7 +2543,10 @@ static int iscsit_send_conn_drop_async_message(
cmd->tx_size = ISCSI_HDR_LEN;
cmd->iscsi_opcode = ISCSI_OP_ASYNC_EVENT;
 
-   hdr = (struct iscsi_async *) cmd->pdu;
+   hdr = conn->conn_transport->iscsit_alloc_pdu(conn, cmd);
+   if (unlikely(!hdr))
+   return -ENOMEM;
+
hdr->opcode = ISCSI_OP_ASYNC_EVENT;
hdr->flags  = ISCSI_FLAG_CMD_FINAL;
cmd->init_task_tag  = RESERVED_ITT;
@@ -2630,7 +2639,7 @@ iscsit_build_datain_pdu(struct iscsi_cmd *cmd, struct 
iscsi_conn *conn,
 
 static int iscsit_send_datain(struct iscsi_cmd *cmd, struct iscsi_conn *conn)
 {
-   struct iscsi_data_rsp *hdr = (struct iscsi_data_rsp *)&cmd->pdu[0];
+   struct iscsi_data_rsp *hdr;
struct iscsi_datain datain;
struct iscsi_datain_req *dr;
struct kvec *iov;
@@ -2675,6 +2684,10 @@ static int iscsit_send_datain(struct iscsi_cmd *cmd, 
struct iscsi_conn *conn)
set_statsn = true;
}
 
+   hdr = conn->conn_transport->iscsit_alloc_pdu(conn, cmd);
+   if (unlikely(!hdr))
+   return -ENOMEM;
+
iscsit_build_datain_pdu(cmd, conn, &datain, hdr, set_statsn);
 
iov = &cmd->iov_data[0];
@@ -2843,13 +2856,20 @@ EXPORT_SYMBOL(iscsit_build_logout_rsp);
 static int
 iscsit_send_logout(struct iscsi_cmd *cmd, struct iscsi_conn *conn)
 {
+   struct iscsi_logout_rsp *hdr;
struct kvec *iov;
int niov = 0, tx_size, rc;
 
-   rc = iscsit_build_logout_rsp(cmd, conn,
-   (struct iscsi_logout_rsp *)&cmd->pdu[0]);
-   if (rc < 0)
+   hdr = conn->conn_transport->iscsit_alloc_pdu(conn, cmd);
+   if (unlikely(!hdr))
+   return -ENOMEM;
+
+   rc = iscsit_build_logout_rsp(cmd, conn, hdr);
+   if (rc < 0) {
+   if (conn->conn_transport->iscsit_free_pdu)
+   conn->conn_transport->iscsit_free_pdu(conn, cmd);
return rc;
+   }
 
tx_size = ISCSI_HDR_LEN;
iov = &cmd->iov_misc[0];
@@ -2909,9 +2929,13 @@ static int iscsit_send_unsolicited_nopin(
struct iscsi_conn *conn,
int want_response)
 {
-   struct iscsi_nopin *hdr = (struct iscsi_nopin *)&cmd->pdu[0];
+   struct iscsi_nopin *hdr;
int tx_size = ISCSI_HDR_LEN, ret;
 
+   hdr = conn->conn_transport->iscsit_alloc_pdu(conn, cmd);
+   if (unlikely(!hdr))
+   return -ENOMEM;
+
iscsit_build_nopin_rsp(cmd, conn, hdr, false);
 
if (conn->conn_ops->HeaderDigest) {
@@ -2950,11 +2974,15 @@ static int iscsit_send_unsolicited_nopin(
 static int
 iscsit_send_nopin(struct iscsi_cmd *cmd, struct iscsi_conn *conn)
 {
-   struct iscsi_nopin *hdr = (struct iscsi_nopin *)&cmd->pdu[0];
+   struct iscsi_nopin *hdr;
struct kvec *iov;
u32 padding = 0;
int niov = 0, tx_size;
 
+   hdr = conn->conn_transport->iscsit_alloc_pdu(conn, cmd);
+   if (unlikely(!hdr))
+   return -ENOMEM;
+
iscsit_build_nopin_rsp(cmd, conn, hdr, true);
 
tx_size = ISCSI_HDR_LEN;
@@ -3028,7 +3056,10 @@ static int iscsit_send_r2t(
if (!r2t)
return -1;
 
-   hdr = (struct iscsi_r2t_rsp *) cmd->pdu;
+   hdr = conn->conn_transport->iscsit_alloc_pdu(conn, cmd);
+   if (unlikely(!hdr))
+   return -ENOMEM;
+
memset(hdr, 0, ISCSI_HDR_LEN);
hdr->opcode = ISCSI_OP_R2T;
hdr->flag

[PATCH v2 05/16] iscsi-target: add void (*iscsit_get_rx_pdu)()

2016-04-09 Thread Varun Prakash
Add void (*iscsit_get_rx_pdu)() to
struct iscsit_transport, iscsi-target
uses this callback to receive and
process Rx iSCSI PDUs.

Signed-off-by: Varun Prakash 
---
 drivers/infiniband/ulp/isert/ib_isert.c | 10 ++
 drivers/target/iscsi/iscsi_target.c | 10 ++
 include/target/iscsi/iscsi_transport.h  |  1 +
 3 files changed, 13 insertions(+), 8 deletions(-)

diff --git a/drivers/infiniband/ulp/isert/ib_isert.c 
b/drivers/infiniband/ulp/isert/ib_isert.c
index 411e446..9118d7c 100644
--- a/drivers/infiniband/ulp/isert/ib_isert.c
+++ b/drivers/infiniband/ulp/isert/ib_isert.c
@@ -3273,6 +3273,15 @@ static void isert_free_conn(struct iscsi_conn *conn)
isert_put_conn(isert_conn);
 }
 
+static void isert_get_rx_pdu(struct iscsi_conn *conn)
+{
+   struct completion comp;
+
+   init_completion(&comp);
+
+   wait_for_completion_interruptible(&comp);
+}
+
 static struct iscsit_transport iser_target_transport = {
.name   = "IB/iSER",
.transport_type = ISCSI_INFINIBAND,
@@ -3291,6 +3300,7 @@ static struct iscsit_transport iser_target_transport = {
.iscsit_queue_data_in   = isert_put_datain,
.iscsit_queue_status= isert_put_response,
.iscsit_aborted_task= isert_aborted_task,
+   .iscsit_get_rx_pdu  = isert_get_rx_pdu,
.iscsit_get_sup_prot_ops = isert_get_sup_prot_ops,
 };
 
diff --git a/drivers/target/iscsi/iscsi_target.c 
b/drivers/target/iscsi/iscsi_target.c
index 9e65e5d..4311636 100644
--- a/drivers/target/iscsi/iscsi_target.c
+++ b/drivers/target/iscsi/iscsi_target.c
@@ -3989,14 +3989,8 @@ int iscsi_target_rx_thread(void *arg)
if (rc < 0 || iscsi_target_check_conn_state(conn))
return 0;
 
-   if (conn->conn_transport->transport_type == ISCSI_INFINIBAND) {
-   struct completion comp;
-
-   init_completion(&comp);
-   rc = wait_for_completion_interruptible(&comp);
-   if (rc < 0)
-   goto transport_err;
-
+   if (conn->conn_transport->iscsit_get_rx_pdu) {
+   conn->conn_transport->iscsit_get_rx_pdu(conn);
goto transport_err;
}
 
diff --git a/include/target/iscsi/iscsi_transport.h 
b/include/target/iscsi/iscsi_transport.h
index 19cef94..1f63d8c 100644
--- a/include/target/iscsi/iscsi_transport.h
+++ b/include/target/iscsi/iscsi_transport.h
@@ -30,6 +30,7 @@ struct iscsit_transport {
  struct iscsi_datain_req *,
  struct iscsi_datain *);
void (*iscsit_release_cmd)(struct iscsi_conn *, struct iscsi_cmd *);
+   void (*iscsit_get_rx_pdu)(struct iscsi_conn *);
enum target_prot_op (*iscsit_get_sup_prot_ops)(struct iscsi_conn *);
 };
 
-- 
2.0.2

--
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 06/16] iscsi-target: split iscsi_target_rx_thread()

2016-04-09 Thread Varun Prakash
split iscsi_target_rx_thread() into two parts,
1. iscsi_target_rx_thread() is common to all
   transport drivers, it will call Rx function
   registered by transport driver.

2. iscsit_get_rx_pdu() is Rx function for
   ISCSI_TCP transport.

Signed-off-by: Varun Prakash 
---
 drivers/target/iscsi/iscsi_target.c | 59 +
 1 file changed, 33 insertions(+), 26 deletions(-)

diff --git a/drivers/target/iscsi/iscsi_target.c 
b/drivers/target/iscsi/iscsi_target.c
index 4311636..98d96d4 100644
--- a/drivers/target/iscsi/iscsi_target.c
+++ b/drivers/target/iscsi/iscsi_target.c
@@ -480,6 +480,7 @@ int iscsit_del_np(struct iscsi_np *np)
 
 static int iscsit_immediate_queue(struct iscsi_conn *, struct iscsi_cmd *, 
int);
 static int iscsit_response_queue(struct iscsi_conn *, struct iscsi_cmd *, int);
+static void iscsit_get_rx_pdu(struct iscsi_conn *);
 
 static int iscsit_queue_rsp(struct iscsi_conn *conn, struct iscsi_cmd *cmd)
 {
@@ -678,6 +679,7 @@ static struct iscsit_transport iscsi_target_transport = {
.iscsit_alloc_pdu   = iscsit_alloc_pdu,
.iscsit_xmit_pdu= iscsit_xmit_pdu,
.iscsit_xmit_datain_pdu = iscsit_xmit_datain_pdu,
+   .iscsit_get_rx_pdu  = iscsit_get_rx_pdu,
.iscsit_get_sup_prot_ops = iscsit_get_sup_prot_ops,
 };
 
@@ -3969,30 +3971,12 @@ static bool iscsi_target_check_conn_state(struct 
iscsi_conn *conn)
return ret;
 }
 
-int iscsi_target_rx_thread(void *arg)
+static void iscsit_get_rx_pdu(struct iscsi_conn *conn)
 {
-   int ret, rc;
+   int ret;
u8 buffer[ISCSI_HDR_LEN], opcode;
u32 checksum = 0, digest = 0;
-   struct iscsi_conn *conn = arg;
struct kvec iov;
-   /*
-* Allow ourselves to be interrupted by SIGINT so that a
-* connection recovery / failure event can be triggered externally.
-*/
-   allow_signal(SIGINT);
-   /*
-* Wait for iscsi_post_login_handler() to complete before allowing
-* incoming iscsi/tcp socket I/O, and/or failing the connection.
-*/
-   rc = wait_for_completion_interruptible(&conn->rx_login_comp);
-   if (rc < 0 || iscsi_target_check_conn_state(conn))
-   return 0;
-
-   if (conn->conn_transport->iscsit_get_rx_pdu) {
-   conn->conn_transport->iscsit_get_rx_pdu(conn);
-   goto transport_err;
-   }
 
while (!kthread_should_stop()) {
/*
@@ -4010,7 +3994,7 @@ int iscsi_target_rx_thread(void *arg)
ret = rx_data(conn, &iov, 1, ISCSI_HDR_LEN);
if (ret != ISCSI_HDR_LEN) {
iscsit_rx_thread_wait_for_tcp(conn);
-   goto transport_err;
+   return;
}
 
if (conn->conn_ops->HeaderDigest) {
@@ -4020,7 +4004,7 @@ int iscsi_target_rx_thread(void *arg)
ret = rx_data(conn, &iov, 1, ISCSI_CRC_LEN);
if (ret != ISCSI_CRC_LEN) {
iscsit_rx_thread_wait_for_tcp(conn);
-   goto transport_err;
+   return;
}
 
iscsit_do_crypto_hash_buf(conn->conn_rx_hash,
@@ -4044,7 +4028,7 @@ int iscsi_target_rx_thread(void *arg)
}
 
if (conn->conn_state == TARG_CONN_STATE_IN_LOGOUT)
-   goto transport_err;
+   return;
 
opcode = buffer[0] & ISCSI_OPCODE_MASK;
 
@@ -4055,15 +4039,38 @@ int iscsi_target_rx_thread(void *arg)
" while in Discovery Session, rejecting.\n", opcode);
iscsit_add_reject(conn, ISCSI_REASON_PROTOCOL_ERROR,
  buffer);
-   goto transport_err;
+   return;
}
 
ret = iscsi_target_rx_opcode(conn, buffer);
if (ret < 0)
-   goto transport_err;
+   return;
}
+}
+
+int iscsi_target_rx_thread(void *arg)
+{
+   int rc;
+   struct iscsi_conn *conn = arg;
+
+   /*
+* Allow ourselves to be interrupted by SIGINT so that a
+* connection recovery / failure event can be triggered externally.
+*/
+   allow_signal(SIGINT);
+   /*
+* Wait for iscsi_post_login_handler() to complete before allowing
+* incoming iscsi/tcp socket I/O, and/or failing the connection.
+*/
+   rc = wait_for_completion_interruptible(&conn->rx_login_comp);
+   if (rc < 0 || iscsi_target_check_conn_state(conn))
+   return 0;
+
+   if (!conn->conn_transport->iscsit_get_rx_pdu)
+   return 0;
+
+   conn->conn_transport->iscsit_get_rx_pdu(conn);
 
-transport_err:
if (!signal_pending(current))
atomic_set(&conn->transport_failed, 1);
iscsit_

[PATCH v2 12/16] iscsi-target: clear tx_thread_active

2016-04-09 Thread Varun Prakash
clear tx_thread_active for ISCSI_HW_OFFLOAD
transport in logout_post_handler functions.

Signed-off-by: Varun Prakash 
---
 drivers/target/iscsi/iscsi_target.c | 6 --
 1 file changed, 4 insertions(+), 2 deletions(-)

diff --git a/drivers/target/iscsi/iscsi_target.c 
b/drivers/target/iscsi/iscsi_target.c
index e61249d..959644f 100644
--- a/drivers/target/iscsi/iscsi_target.c
+++ b/drivers/target/iscsi/iscsi_target.c
@@ -4417,7 +4417,8 @@ static void iscsit_logout_post_handler_closesession(
 * always sleep waiting for RX/TX thread shutdown to complete
 * within iscsit_close_connection().
 */
-   if (conn->conn_transport->transport_type == ISCSI_TCP)
+   if ((conn->conn_transport->transport_type == ISCSI_TCP) ||
+   (conn->conn_transport->transport_type == ISCSI_HW_OFFLOAD))
sleep = cmpxchg(&conn->tx_thread_active, true, false);
 
atomic_set(&conn->conn_logout_remove, 0);
@@ -4434,7 +4435,8 @@ static void iscsit_logout_post_handler_samecid(
 {
int sleep = 1;
 
-   if (conn->conn_transport->transport_type == ISCSI_TCP)
+   if ((conn->conn_transport->transport_type == ISCSI_TCP) ||
+   (conn->conn_transport->transport_type == ISCSI_HW_OFFLOAD))
sleep = cmpxchg(&conn->tx_thread_active, true, false);
 
atomic_set(&conn->conn_logout_remove, 0);
-- 
2.0.2

--
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 14/16] iscsi-target: export symbols

2016-04-09 Thread Varun Prakash
export symbols for ISCSI_HW_OFFLOAD
transport drivers.

Signed-off-by: Varun Prakash 
---
 drivers/target/iscsi/iscsi_target.c   | 25 ++---
 drivers/target/iscsi/iscsi_target_datain_values.c |  1 +
 drivers/target/iscsi/iscsi_target_login.c |  3 ++-
 drivers/target/iscsi/iscsi_target_nego.c  |  1 +
 drivers/target/iscsi/iscsi_target_parameters.c|  1 +
 drivers/target/iscsi/iscsi_target_util.c  |  2 ++
 include/target/iscsi/iscsi_transport.h| 33 +++
 7 files changed, 56 insertions(+), 10 deletions(-)

diff --git a/drivers/target/iscsi/iscsi_target.c 
b/drivers/target/iscsi/iscsi_target.c
index edce5af..941f676 100644
--- a/drivers/target/iscsi/iscsi_target.c
+++ b/drivers/target/iscsi/iscsi_target.c
@@ -478,17 +478,16 @@ int iscsit_del_np(struct iscsi_np *np)
return 0;
 }
 
-static int iscsit_immediate_queue(struct iscsi_conn *, struct iscsi_cmd *, 
int);
-static int iscsit_response_queue(struct iscsi_conn *, struct iscsi_cmd *, int);
 static void iscsit_get_rx_pdu(struct iscsi_conn *);
 
-static int iscsit_queue_rsp(struct iscsi_conn *conn, struct iscsi_cmd *cmd)
+int iscsit_queue_rsp(struct iscsi_conn *conn, struct iscsi_cmd *cmd)
 {
iscsit_add_cmd_to_response_queue(cmd, cmd->conn, cmd->i_state);
return 0;
 }
+EXPORT_SYMBOL(iscsit_queue_rsp);
 
-static void iscsit_aborted_task(struct iscsi_conn *conn, struct iscsi_cmd *cmd)
+void iscsit_aborted_task(struct iscsi_conn *conn, struct iscsi_cmd *cmd)
 {
bool scsi_cmd = (cmd->iscsi_opcode == ISCSI_OP_SCSI_CMD);
 
@@ -499,6 +498,7 @@ static void iscsit_aborted_task(struct iscsi_conn *conn, 
struct iscsi_cmd *cmd)
 
__iscsit_free_cmd(cmd, scsi_cmd, true);
 }
+EXPORT_SYMBOL(iscsit_aborted_task);
 
 static void *iscsit_alloc_pdu(struct iscsi_conn *conn, struct iscsi_cmd *cmd)
 {
@@ -795,7 +795,7 @@ static void __exit iscsi_target_cleanup_module(void)
kfree(iscsit_global);
 }
 
-static int iscsit_add_reject(
+int iscsit_add_reject(
struct iscsi_conn *conn,
u8 reason,
unsigned char *buf)
@@ -825,6 +825,7 @@ static int iscsit_add_reject(
 
return -1;
 }
+EXPORT_SYMBOL(iscsit_add_reject);
 
 static int iscsit_add_reject_from_cmd(
struct iscsi_cmd *cmd,
@@ -880,6 +881,7 @@ int iscsit_reject_cmd(struct iscsi_cmd *cmd, u8 reason, 
unsigned char *buf)
 {
return iscsit_add_reject_from_cmd(cmd, reason, false, buf);
 }
+EXPORT_SYMBOL(iscsit_reject_cmd);
 
 /*
  * Map some portion of the allocated scatterlist to an iovec, suitable for
@@ -2496,7 +2498,7 @@ iscsit_handle_logout_cmd(struct iscsi_conn *conn, struct 
iscsi_cmd *cmd,
 }
 EXPORT_SYMBOL(iscsit_handle_logout_cmd);
 
-static int iscsit_handle_snack(
+int iscsit_handle_snack(
struct iscsi_conn *conn,
unsigned char *buf)
 {
@@ -2549,6 +2551,7 @@ static int iscsit_handle_snack(
 
return 0;
 }
+EXPORT_SYMBOL(iscsit_handle_snack);
 
 static void iscsit_rx_thread_wait_for_tcp(struct iscsi_conn *conn)
 {
@@ -2732,7 +2735,7 @@ static void iscsit_tx_thread_wait_for_tcp(struct 
iscsi_conn *conn)
}
 }
 
-static void
+void
 iscsit_build_datain_pdu(struct iscsi_cmd *cmd, struct iscsi_conn *conn,
struct iscsi_datain *datain, struct iscsi_data_rsp *hdr,
bool set_statsn)
@@ -2776,6 +2779,7 @@ iscsit_build_datain_pdu(struct iscsi_cmd *cmd, struct 
iscsi_conn *conn,
cmd->init_task_tag, ntohl(hdr->statsn), ntohl(hdr->datasn),
ntohl(hdr->offset), datain->length, conn->cid);
 }
+EXPORT_SYMBOL(iscsit_build_datain_pdu);
 
 static int iscsit_send_datain(struct iscsi_cmd *cmd, struct iscsi_conn *conn)
 {
@@ -3174,6 +3178,7 @@ int iscsit_build_r2ts_for_cmd(
 
return 0;
 }
+EXPORT_SYMBOL(iscsit_build_r2ts_for_cmd);
 
 void iscsit_build_rsp_pdu(struct iscsi_cmd *cmd, struct iscsi_conn *conn,
bool inc_stat_sn, struct iscsi_scsi_rsp *hdr)
@@ -3619,7 +3624,7 @@ void iscsit_thread_get_cpumask(struct iscsi_conn *conn)
cpumask_setall(conn->conn_cpumask);
 }
 
-static int
+int
 iscsit_immediate_queue(struct iscsi_conn *conn, struct iscsi_cmd *cmd, int 
state)
 {
int ret;
@@ -3661,6 +3666,7 @@ iscsit_immediate_queue(struct iscsi_conn *conn, struct 
iscsi_cmd *cmd, int state
 err:
return -1;
 }
+EXPORT_SYMBOL(iscsit_immediate_queue);
 
 static int
 iscsit_handle_immediate_queue(struct iscsi_conn *conn)
@@ -3685,7 +3691,7 @@ iscsit_handle_immediate_queue(struct iscsi_conn *conn)
return 0;
 }
 
-static int
+int
 iscsit_response_queue(struct iscsi_conn *conn, struct iscsi_cmd *cmd, int 
state)
 {
int ret;
@@ -3790,6 +3796,7 @@ check_rsp_state:
 err:
return -1;
 }
+EXPORT_SYMBOL(iscsit_response_queue);
 
 static int iscsit_handle_response_queue(struct iscsi_conn *conn)
 {
diff --git a/drivers/target/iscsi/iscsi_target_datain_values.c 
b/drivers/target/iscsi/iscsi_target_datain_values.c
index f

[PATCH v2 07/16] iscsi-target: add int (*iscsit_validate_params)()

2016-04-09 Thread Varun Prakash
Add int (*iscsit_validate_params)() to
struct iscsit_transport, iscsi-target
uses this callback for validating
conn operational parameters.

Signed-off-by: Varun Prakash 
---
 drivers/target/iscsi/iscsi_target_login.c | 10 ++
 include/target/iscsi/iscsi_transport.h|  1 +
 2 files changed, 11 insertions(+)

diff --git a/drivers/target/iscsi/iscsi_target_login.c 
b/drivers/target/iscsi/iscsi_target_login.c
index 8436d56..83574eea 100644
--- a/drivers/target/iscsi/iscsi_target_login.c
+++ b/drivers/target/iscsi/iscsi_target_login.c
@@ -1387,6 +1387,16 @@ static int __iscsi_target_login_thread(struct iscsi_np 
*np)
goto old_sess_out;
}
 
+   if (conn->conn_transport->iscsit_validate_params) {
+   ret = conn->conn_transport->iscsit_validate_params(conn);
+   if (ret < 0) {
+   if (zero_tsih)
+   goto new_sess_out;
+   else
+   goto old_sess_out;
+   }
+   }
+
ret = iscsi_target_start_negotiation(login, conn);
if (ret < 0)
goto new_sess_out;
diff --git a/include/target/iscsi/iscsi_transport.h 
b/include/target/iscsi/iscsi_transport.h
index 1f63d8c..dbef892 100644
--- a/include/target/iscsi/iscsi_transport.h
+++ b/include/target/iscsi/iscsi_transport.h
@@ -31,6 +31,7 @@ struct iscsit_transport {
  struct iscsi_datain *);
void (*iscsit_release_cmd)(struct iscsi_conn *, struct iscsi_cmd *);
void (*iscsit_get_rx_pdu)(struct iscsi_conn *);
+   int (*iscsit_validate_params)(struct iscsi_conn *);
enum target_prot_op (*iscsit_get_sup_prot_ops)(struct iscsi_conn *);
 };
 
-- 
2.0.2

--
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 03/16] iscsi-target: add int (*iscsit_xmit_datain_pdu)()

2016-04-09 Thread Varun Prakash
Add int (*iscsit_xmit_datain_pdu)() to
struct iscsit_transport, iscsi-target
uses this callback to transmit a DATAIN
iSCSI PDU.

Signed-off-by: Varun Prakash 
---
 drivers/target/iscsi/iscsi_target.c| 143 +++--
 include/target/iscsi/iscsi_transport.h |   3 +
 2 files changed, 86 insertions(+), 60 deletions(-)

diff --git a/drivers/target/iscsi/iscsi_target.c 
b/drivers/target/iscsi/iscsi_target.c
index 0e7a481..9e65e5d 100644
--- a/drivers/target/iscsi/iscsi_target.c
+++ b/drivers/target/iscsi/iscsi_target.c
@@ -577,6 +577,84 @@ static int iscsit_xmit_pdu(struct iscsi_conn *conn, struct 
iscsi_cmd *cmd,
return 0;
 }
 
+static int iscsit_map_iovec(struct iscsi_cmd *, struct kvec *, u32, u32);
+static void iscsit_unmap_iovec(struct iscsi_cmd *);
+static u32 iscsit_do_crypto_hash_sg(struct ahash_request *, struct iscsi_cmd *,
+   u32, u32, u32, u8 *);
+static int
+iscsit_xmit_datain_pdu(struct iscsi_conn *conn, struct iscsi_cmd *cmd,
+  struct iscsi_datain_req *dr, struct iscsi_datain *datain)
+{
+   struct kvec *iov;
+   u32 iov_count = 0, tx_size = 0;
+   int ret, iov_ret;
+
+   iov = &cmd->iov_data[0];
+   iov[iov_count].iov_base = cmd->pdu;
+   iov[iov_count++].iov_len = ISCSI_HDR_LEN;
+   tx_size += ISCSI_HDR_LEN;
+
+   if (conn->conn_ops->HeaderDigest) {
+   u32 *header_digest = (u32 *)&cmd->pdu[ISCSI_HDR_LEN];
+
+   iscsit_do_crypto_hash_buf(conn->conn_tx_hash, cmd->pdu,
+ ISCSI_HDR_LEN, 0, NULL,
+ (u8 *)header_digest);
+
+   iov[0].iov_len += ISCSI_CRC_LEN;
+   tx_size += ISCSI_CRC_LEN;
+
+   pr_debug("Attaching CRC32 HeaderDigest for DataIN PDU 0x%08x\n",
+*header_digest);
+   }
+
+   iov_ret = iscsit_map_iovec(cmd, &cmd->iov_data[1],
+  datain->offset, datain->length);
+   if (iov_ret < 0)
+   return -1;
+
+   iov_count += iov_ret;
+   tx_size += datain->length;
+
+   cmd->padding = ((-datain->length) & 3);
+   if (cmd->padding) {
+   iov[iov_count].iov_base = cmd->pad_bytes;
+   iov[iov_count++].iov_len= cmd->padding;
+   tx_size += cmd->padding;
+
+   pr_debug("Attaching %u padding bytes\n", cmd->padding);
+   }
+
+   if (conn->conn_ops->DataDigest) {
+   cmd->data_crc = iscsit_do_crypto_hash_sg(conn->conn_tx_hash,
+cmd, datain->offset,
+datain->length,
+cmd->padding,
+cmd->pad_bytes);
+
+   iov[iov_count].iov_base = &cmd->data_crc;
+   iov[iov_count++].iov_len = ISCSI_CRC_LEN;
+   tx_size += ISCSI_CRC_LEN;
+
+   pr_debug("Attached CRC32C DataDigest %d bytes, crc 0x%08x\n",
+datain->length + cmd->padding, cmd->data_crc);
+   }
+
+   cmd->iov_data_count = iov_count;
+   cmd->tx_size = tx_size;
+
+   ret = iscsit_fe_sendpage_sg(cmd, conn);
+
+   iscsit_unmap_iovec(cmd);
+
+   if (ret < 0) {
+   iscsit_tx_thread_wait_for_tcp(conn);
+   return ret;
+   }
+
+   return 0;
+}
+
 static enum target_prot_op iscsit_get_sup_prot_ops(struct iscsi_conn *conn)
 {
return TARGET_PROT_NORMAL;
@@ -599,6 +677,7 @@ static struct iscsit_transport iscsi_target_transport = {
.iscsit_aborted_task= iscsit_aborted_task,
.iscsit_alloc_pdu   = iscsit_alloc_pdu,
.iscsit_xmit_pdu= iscsit_xmit_pdu,
+   .iscsit_xmit_datain_pdu = iscsit_xmit_datain_pdu,
.iscsit_get_sup_prot_ops = iscsit_get_sup_prot_ops,
 };
 
@@ -2701,9 +2780,7 @@ static int iscsit_send_datain(struct iscsi_cmd *cmd, 
struct iscsi_conn *conn)
struct iscsi_data_rsp *hdr;
struct iscsi_datain datain;
struct iscsi_datain_req *dr;
-   struct kvec *iov;
-   u32 iov_count = 0, tx_size = 0;
-   int eodr = 0, ret, iov_ret;
+   int eodr = 0, ret;
bool set_statsn = false;
 
memset(&datain, 0, sizeof(struct iscsi_datain));
@@ -2749,64 +2826,10 @@ static int iscsit_send_datain(struct iscsi_cmd *cmd, 
struct iscsi_conn *conn)
 
iscsit_build_datain_pdu(cmd, conn, &datain, hdr, set_statsn);
 
-   iov = &cmd->iov_data[0];
-   iov[iov_count].iov_base = cmd->pdu;
-   iov[iov_count++].iov_len= ISCSI_HDR_LEN;
-   tx_size += ISCSI_HDR_LEN;
-
-   if (conn->conn_ops->HeaderDigest) {
-   u32 *header_digest = (u32 *)&cmd->pdu[ISCSI_HDR_LEN];
-
-   iscsit_do_crypto_hash_buf(conn->conn_tx_hash, cmd->pdu,
-   I

[PATCH v2 11/16] iscsi-target: add new offload transport type

2016-04-09 Thread Varun Prakash
Add new transport type ISCSI_HW_OFFLOAD,
hw offload transport drivers will use
this transport type.

Signed-off-by: Varun Prakash 
---
 drivers/target/iscsi/iscsi_target_configfs.c | 76 
 include/target/iscsi/iscsi_target_core.h |  1 +
 2 files changed, 77 insertions(+)

diff --git a/drivers/target/iscsi/iscsi_target_configfs.c 
b/drivers/target/iscsi/iscsi_target_configfs.c
index 97e5b69..3565e07 100644
--- a/drivers/target/iscsi/iscsi_target_configfs.c
+++ b/drivers/target/iscsi/iscsi_target_configfs.c
@@ -182,12 +182,88 @@ out:
return rc;
 }
 
+static ssize_t lio_target_np_hw_offload_show(struct config_item *item,
+char *page)
+{
+   struct iscsi_tpg_np *tpg_np = to_iscsi_tpg_np(item);
+   struct iscsi_tpg_np *tpg_np_hw_offload;
+   ssize_t rb;
+
+   tpg_np_hw_offload = iscsit_tpg_locate_child_np(tpg_np,
+  ISCSI_HW_OFFLOAD);
+   if (tpg_np_hw_offload)
+   rb = sprintf(page, "1\n");
+   else
+   rb = sprintf(page, "0\n");
+
+   return rb;
+}
+
+static ssize_t lio_target_np_hw_offload_store(struct config_item *item,
+ const char *page, size_t count)
+{
+   struct iscsi_tpg_np *tpg_np = to_iscsi_tpg_np(item);
+   struct iscsi_np *np;
+   struct iscsi_portal_group *tpg;
+   struct iscsi_tpg_np *tpg_np_hw_offload = NULL;
+   u32 op;
+   int rc = 0;
+
+   rc = kstrtou32(page, 0, &op);
+   if (rc)
+   return rc;
+
+   if ((op != 1) && (op != 0)) {
+   pr_err("Illegal value for tpg_enable: %u\n", op);
+   return -EINVAL;
+   }
+
+   np = tpg_np->tpg_np;
+   if (!np) {
+   pr_err("Unable to locate struct iscsi_np from"
+  " struct iscsi_tpg_np\n");
+   return -EINVAL;
+   }
+
+   tpg = tpg_np->tpg;
+   if (iscsit_get_tpg(tpg) < 0)
+   return -EINVAL;
+
+   if (op) {
+   tpg_np_hw_offload = iscsit_tpg_add_network_portal(tpg,
+   &np->np_sockaddr, tpg_np, ISCSI_HW_OFFLOAD);
+
+   if (IS_ERR(tpg_np_hw_offload)) {
+   rc = PTR_ERR(tpg_np_hw_offload);
+   goto out;
+   }
+   } else {
+   tpg_np_hw_offload = iscsit_tpg_locate_child_np(tpg_np,
+   ISCSI_HW_OFFLOAD);
+
+   if (tpg_np_hw_offload) {
+   rc = iscsit_tpg_del_network_portal(tpg,
+  tpg_np_hw_offload);
+   if (rc < 0)
+   goto out;
+   }
+   }
+
+   iscsit_put_tpg(tpg);
+   return count;
+out:
+   iscsit_put_tpg(tpg);
+   return rc;
+}
+
 CONFIGFS_ATTR(lio_target_np_, sctp);
 CONFIGFS_ATTR(lio_target_np_, iser);
+CONFIGFS_ATTR(lio_target_np_, hw_offload);
 
 static struct configfs_attribute *lio_target_portal_attrs[] = {
&lio_target_np_attr_sctp,
&lio_target_np_attr_iser,
+   &lio_target_np_attr_hw_offload,
NULL,
 };
 
diff --git a/include/target/iscsi/iscsi_target_core.h 
b/include/target/iscsi/iscsi_target_core.h
index 01c41f2..110c1fd 100644
--- a/include/target/iscsi/iscsi_target_core.h
+++ b/include/target/iscsi/iscsi_target_core.h
@@ -74,6 +74,7 @@ enum iscsit_transport_type {
ISCSI_IWARP_TCP = 3,
ISCSI_IWARP_SCTP= 4,
ISCSI_INFINIBAND= 5,
+   ISCSI_HW_OFFLOAD= 6,
 };
 
 /* RFC-3720 7.1.4  Standard Connection State Diagram for a Target */
-- 
2.0.2

--
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 10/16] iscsi-target: use conn->network_transport in text rsp

2016-04-09 Thread Varun Prakash
Use conn->network_transport instead of
ISCSI_TCP to build text response.

Signed-off-by: Varun Prakash 
---
 drivers/target/iscsi/iscsi_target.c | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)

diff --git a/drivers/target/iscsi/iscsi_target.c 
b/drivers/target/iscsi/iscsi_target.c
index b655f0c..e61249d 100644
--- a/drivers/target/iscsi/iscsi_target.c
+++ b/drivers/target/iscsi/iscsi_target.c
@@ -3546,7 +3546,8 @@ static int iscsit_send_text_rsp(
if (unlikely(!hdr))
return -ENOMEM;
 
-   text_length = iscsit_build_text_rsp(cmd, conn, hdr, ISCSI_TCP);
+   text_length = iscsit_build_text_rsp(cmd, conn, hdr,
+   conn->network_transport);
if (text_length < 0) {
if (conn->conn_transport->iscsit_free_pdu)
conn->conn_transport->iscsit_free_pdu(conn, cmd);
-- 
2.0.2

--
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 04/16] iscsi-target: add void (*iscsit_release_cmd)()

2016-04-09 Thread Varun Prakash
Add void (*iscsit_release_cmd)() to
struct iscsit_transport, iscsi-target
uses this callback to release transport
driver resources associated with an iSCSI cmd.

Signed-off-by: Varun Prakash 
---
 drivers/target/iscsi/iscsi_target_util.c | 3 +++
 include/target/iscsi/iscsi_transport.h   | 1 +
 2 files changed, 4 insertions(+)

diff --git a/drivers/target/iscsi/iscsi_target_util.c 
b/drivers/target/iscsi/iscsi_target_util.c
index 428b0d9..a533017 100644
--- a/drivers/target/iscsi/iscsi_target_util.c
+++ b/drivers/target/iscsi/iscsi_target_util.c
@@ -725,6 +725,9 @@ void __iscsit_free_cmd(struct iscsi_cmd *cmd, bool scsi_cmd,
iscsit_remove_cmd_from_immediate_queue(cmd, conn);
iscsit_remove_cmd_from_response_queue(cmd, conn);
}
+
+   if (conn && conn->conn_transport->iscsit_release_cmd)
+   conn->conn_transport->iscsit_release_cmd(conn, cmd);
 }
 
 void iscsit_free_cmd(struct iscsi_cmd *cmd, bool shutdown)
diff --git a/include/target/iscsi/iscsi_transport.h 
b/include/target/iscsi/iscsi_transport.h
index 77ae41e..19cef94 100644
--- a/include/target/iscsi/iscsi_transport.h
+++ b/include/target/iscsi/iscsi_transport.h
@@ -29,6 +29,7 @@ struct iscsit_transport {
int (*iscsit_xmit_datain_pdu)(struct iscsi_conn *, struct iscsi_cmd *,
  struct iscsi_datain_req *,
  struct iscsi_datain *);
+   void (*iscsit_release_cmd)(struct iscsi_conn *, struct iscsi_cmd *);
enum target_prot_op (*iscsit_get_sup_prot_ops)(struct iscsi_conn *);
 };
 
-- 
2.0.2

--
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 08/16] iscsi-target: add void (*iscsit_get_r2t_ttt)()

2016-04-09 Thread Varun Prakash
Add void (*iscsit_get_r2t_ttt)() to
struct iscsit_transport, iscsi-target
uses this callback to get
r2t->targ_xfer_tag.

Signed-off-by: Varun Prakash 
---
 drivers/target/iscsi/iscsi_target.c| 5 -
 include/target/iscsi/iscsi_transport.h | 2 ++
 2 files changed, 6 insertions(+), 1 deletion(-)

diff --git a/drivers/target/iscsi/iscsi_target.c 
b/drivers/target/iscsi/iscsi_target.c
index 98d96d4..ec785c8 100644
--- a/drivers/target/iscsi/iscsi_target.c
+++ b/drivers/target/iscsi/iscsi_target.c
@@ -3060,7 +3060,10 @@ static int iscsit_send_r2t(
int_to_scsilun(cmd->se_cmd.orig_fe_lun,
(struct scsi_lun *)&hdr->lun);
hdr->itt= cmd->init_task_tag;
-   r2t->targ_xfer_tag  = session_get_next_ttt(conn->sess);
+   if (conn->conn_transport->iscsit_get_r2t_ttt)
+   conn->conn_transport->iscsit_get_r2t_ttt(conn, cmd, r2t);
+   else
+   r2t->targ_xfer_tag = session_get_next_ttt(conn->sess);
hdr->ttt= cpu_to_be32(r2t->targ_xfer_tag);
hdr->statsn = cpu_to_be32(conn->stat_sn);
hdr->exp_cmdsn  = cpu_to_be32(conn->sess->exp_cmd_sn);
diff --git a/include/target/iscsi/iscsi_transport.h 
b/include/target/iscsi/iscsi_transport.h
index dbef892..f949e70 100644
--- a/include/target/iscsi/iscsi_transport.h
+++ b/include/target/iscsi/iscsi_transport.h
@@ -32,6 +32,8 @@ struct iscsit_transport {
void (*iscsit_release_cmd)(struct iscsi_conn *, struct iscsi_cmd *);
void (*iscsit_get_rx_pdu)(struct iscsi_conn *);
int (*iscsit_validate_params)(struct iscsi_conn *);
+   void (*iscsit_get_r2t_ttt)(struct iscsi_conn *, struct iscsi_cmd *,
+  struct iscsi_r2t *);
enum target_prot_op (*iscsit_get_sup_prot_ops)(struct iscsi_conn *);
 };
 
-- 
2.0.2

--
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 09/16] iscsi-target: move iscsit_thread_check_cpumask()

2016-04-09 Thread Varun Prakash
Move iscsit_thread_check_cpumask() to header
file so that ISCSI_HW_OFFLOAD and other transport drivers
can call this function to ensure both tx and rx thread
runs on same cpu.

Signed-off-by: Varun Prakash 
---
 drivers/target/iscsi/iscsi_target.c  | 26 --
 include/target/iscsi/iscsi_target_core.h | 26 ++
 2 files changed, 26 insertions(+), 26 deletions(-)

diff --git a/drivers/target/iscsi/iscsi_target.c 
b/drivers/target/iscsi/iscsi_target.c
index ec785c8..b655f0c 100644
--- a/drivers/target/iscsi/iscsi_target.c
+++ b/drivers/target/iscsi/iscsi_target.c
@@ -3618,32 +3618,6 @@ void iscsit_thread_get_cpumask(struct iscsi_conn *conn)
cpumask_setall(conn->conn_cpumask);
 }
 
-static inline void iscsit_thread_check_cpumask(
-   struct iscsi_conn *conn,
-   struct task_struct *p,
-   int mode)
-{
-   /*
-* mode == 1 signals iscsi_target_tx_thread() usage.
-* mode == 0 signals iscsi_target_rx_thread() usage.
-*/
-   if (mode == 1) {
-   if (!conn->conn_tx_reset_cpumask)
-   return;
-   conn->conn_tx_reset_cpumask = 0;
-   } else {
-   if (!conn->conn_rx_reset_cpumask)
-   return;
-   conn->conn_rx_reset_cpumask = 0;
-   }
-   /*
-* Update the CPU mask for this single kthread so that
-* both TX and RX kthreads are scheduled to run on the
-* same CPU.
-*/
-   set_cpus_allowed_ptr(p, conn->conn_cpumask);
-}
-
 static int
 iscsit_immediate_queue(struct iscsi_conn *conn, struct iscsi_cmd *cmd, int 
state)
 {
diff --git a/include/target/iscsi/iscsi_target_core.h 
b/include/target/iscsi/iscsi_target_core.h
index c3371fa..01c41f2 100644
--- a/include/target/iscsi/iscsi_target_core.h
+++ b/include/target/iscsi/iscsi_target_core.h
@@ -890,4 +890,30 @@ static inline u32 session_get_next_ttt(struct 
iscsi_session *session)
 }
 
 extern struct iscsi_cmd *iscsit_find_cmd_from_itt(struct iscsi_conn *, itt_t);
+
+static inline void iscsit_thread_check_cpumask(
+   struct iscsi_conn *conn,
+   struct task_struct *p,
+   int mode)
+{
+   /*
+* mode == 1 signals iscsi_target_tx_thread() usage.
+* mode == 0 signals iscsi_target_rx_thread() usage.
+*/
+   if (mode == 1) {
+   if (!conn->conn_tx_reset_cpumask)
+   return;
+   conn->conn_tx_reset_cpumask = 0;
+   } else {
+   if (!conn->conn_rx_reset_cpumask)
+   return;
+   conn->conn_rx_reset_cpumask = 0;
+   }
+   /*
+* Update the CPU mask for this single kthread so that
+* both TX and RX kthreads are scheduled to run on the
+* same CPU.
+*/
+   set_cpus_allowed_ptr(p, conn->conn_cpumask);
+}
 #endif /* ISCSI_TARGET_CORE_H */
-- 
2.0.2

--
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 15/16] iscsi-target: fix seq_end_offset calculation

2016-04-09 Thread Varun Prakash
In case of unsolicited data, seq end offset for first
sequence must be equal to the min of firstburstlength
and data length.

Signed-off-by: Varun Prakash 
---
 drivers/target/iscsi/iscsi_target_erl0.c | 6 +++---
 1 file changed, 3 insertions(+), 3 deletions(-)

diff --git a/drivers/target/iscsi/iscsi_target_erl0.c 
b/drivers/target/iscsi/iscsi_target_erl0.c
index 210f6e4..a0fb5a8 100644
--- a/drivers/target/iscsi/iscsi_target_erl0.c
+++ b/drivers/target/iscsi/iscsi_target_erl0.c
@@ -44,10 +44,10 @@ void iscsit_set_dataout_sequence_values(
 */
if (cmd->unsolicited_data) {
cmd->seq_start_offset = cmd->write_data_done;
-   cmd->seq_end_offset = (cmd->write_data_done +
-   ((cmd->se_cmd.data_length >
+   cmd->seq_end_offset = (cmd->se_cmd.data_length >
  conn->sess->sess_ops->FirstBurstLength) ?
-conn->sess->sess_ops->FirstBurstLength : 
cmd->se_cmd.data_length));
+conn->sess->sess_ops->FirstBurstLength :
+cmd->se_cmd.data_length;
return;
}
 
-- 
2.0.2

--
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 13/16] iscsi-target: call complete on conn_logout_comp

2016-04-09 Thread Varun Prakash
ISCSI_HW_OFFLOAD transport drivers waits
on conn_logout_comp as ISCSI_TCP driver
so call complete if transport type
is ISCSI_HW_OFFLOAD.

Signed-off-by: Varun Prakash 
---
 drivers/target/iscsi/iscsi_target.c | 10 ++
 1 file changed, 6 insertions(+), 4 deletions(-)

diff --git a/drivers/target/iscsi/iscsi_target.c 
b/drivers/target/iscsi/iscsi_target.c
index 959644f..edce5af 100644
--- a/drivers/target/iscsi/iscsi_target.c
+++ b/drivers/target/iscsi/iscsi_target.c
@@ -4101,16 +4101,18 @@ int iscsit_close_connection(
pr_debug("Closing iSCSI connection CID %hu on SID:"
" %u\n", conn->cid, sess->sid);
/*
-* Always up conn_logout_comp for the traditional TCP case just in case
-* the RX Thread in iscsi_target_rx_opcode() is sleeping and the logout
-* response never got sent because the connection failed.
+* Always up conn_logout_comp for the traditional TCP and HW_OFFLOAD
+* case just in case the RX Thread in iscsi_target_rx_opcode() is
+* sleeping and the logout response never got sent because the
+* connection failed.
 *
 * However for iser-target, isert_wait4logout() is using 
conn_logout_comp
 * to signal logout response TX interrupt completion.  Go ahead and skip
 * this for iser since isert_rx_opcode() does not wait on logout 
failure,
 * and to avoid iscsi_conn pointer dereference in iser-target code.
 */
-   if (conn->conn_transport->transport_type == ISCSI_TCP)
+   if ((conn->conn_transport->transport_type == ISCSI_TCP) ||
+   (conn->conn_transport->transport_type == ISCSI_HW_OFFLOAD))
complete(&conn->conn_logout_comp);
 
if (!strcmp(current->comm, ISCSI_RX_THREAD_NAME)) {
-- 
2.0.2

--
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 16/16] cxgbit: add files for cxgbit.ko

2016-04-09 Thread Varun Prakash
cxgbit.h - This file contains data structure
definitions for cxgbit.ko.

cxgbit_lro.h - This file contains data structure
definitions for LRO support.

cxgbit_main.c - This file contains code for
registering with iscsi target transport and
cxgb4 driver.

cxgbit_cm.c - This file contains code for
connection management.

cxgbit_target.c - This file contains code
for processing iSCSI PDU.

cxgbit_ddp.c - This file contains code for
Direct Data Placement.
v2: added check for NULL sg in cxgbit_set_one_ppod()

Reported-by: Dan Carpenter 

cxgbit: add Kconfig and Makefile
v2: added dependency on INET

Reported-by: Arnd Bergmann 

iscsi-target: update Kconfig and Makefile
for compiling cxgbit.ko.

Signed-off-by: Varun Prakash 
---
 drivers/target/iscsi/Kconfig|2 +
 drivers/target/iscsi/Makefile   |1 +
 drivers/target/iscsi/cxgbit/Kconfig |7 +
 drivers/target/iscsi/cxgbit/Makefile|6 +
 drivers/target/iscsi/cxgbit/cxgbit.h|  358 +
 drivers/target/iscsi/cxgbit/cxgbit_cm.c | 2086 +++
 drivers/target/iscsi/cxgbit/cxgbit_ddp.c|  325 +
 drivers/target/iscsi/cxgbit/cxgbit_lro.h|   72 +
 drivers/target/iscsi/cxgbit/cxgbit_main.c   |  703 +
 drivers/target/iscsi/cxgbit/cxgbit_target.c | 1601 
 10 files changed, 5161 insertions(+)
 create mode 100644 drivers/target/iscsi/cxgbit/Kconfig
 create mode 100644 drivers/target/iscsi/cxgbit/Makefile
 create mode 100644 drivers/target/iscsi/cxgbit/cxgbit.h
 create mode 100644 drivers/target/iscsi/cxgbit/cxgbit_cm.c
 create mode 100644 drivers/target/iscsi/cxgbit/cxgbit_ddp.c
 create mode 100644 drivers/target/iscsi/cxgbit/cxgbit_lro.h
 create mode 100644 drivers/target/iscsi/cxgbit/cxgbit_main.c
 create mode 100644 drivers/target/iscsi/cxgbit/cxgbit_target.c

diff --git a/drivers/target/iscsi/Kconfig b/drivers/target/iscsi/Kconfig
index 8345fb4..bbdbf9c 100644
--- a/drivers/target/iscsi/Kconfig
+++ b/drivers/target/iscsi/Kconfig
@@ -7,3 +7,5 @@ config ISCSI_TARGET
help
Say M here to enable the ConfigFS enabled Linux-iSCSI.org iSCSI
Target Mode Stack.
+
+source "drivers/target/iscsi/cxgbit/Kconfig"
diff --git a/drivers/target/iscsi/Makefile b/drivers/target/iscsi/Makefile
index 0f43be9..0f18295 100644
--- a/drivers/target/iscsi/Makefile
+++ b/drivers/target/iscsi/Makefile
@@ -18,3 +18,4 @@ iscsi_target_mod-y += iscsi_target_parameters.o \
iscsi_target_transport.o
 
 obj-$(CONFIG_ISCSI_TARGET) += iscsi_target_mod.o
+obj-$(CONFIG_ISCSI_TARGET_CXGB4) += cxgbit/
diff --git a/drivers/target/iscsi/cxgbit/Kconfig 
b/drivers/target/iscsi/cxgbit/Kconfig
new file mode 100644
index 000..c9b6a3c
--- /dev/null
+++ b/drivers/target/iscsi/cxgbit/Kconfig
@@ -0,0 +1,7 @@
+config ISCSI_TARGET_CXGB4
+   tristate "Chelsio iSCSI target offload driver"
+   depends on ISCSI_TARGET && CHELSIO_T4 && INET
+   select CHELSIO_T4_UWIRE
+   ---help---
+   To compile this driver as module, choose M here: the module
+   will be called cxgbit.
diff --git a/drivers/target/iscsi/cxgbit/Makefile 
b/drivers/target/iscsi/cxgbit/Makefile
new file mode 100644
index 000..bd56c07
--- /dev/null
+++ b/drivers/target/iscsi/cxgbit/Makefile
@@ -0,0 +1,6 @@
+ccflags-y := -Idrivers/net/ethernet/chelsio/cxgb4
+ccflags-y += -Idrivers/target/iscsi
+
+obj-$(CONFIG_ISCSI_TARGET_CXGB4)  += cxgbit.o
+
+cxgbit-y  := cxgbit_main.o cxgbit_cm.o cxgbit_target.o cxgbit_ddp.o
diff --git a/drivers/target/iscsi/cxgbit/cxgbit.h 
b/drivers/target/iscsi/cxgbit/cxgbit.h
new file mode 100644
index 000..3aa9a3c
--- /dev/null
+++ b/drivers/target/iscsi/cxgbit/cxgbit.h
@@ -0,0 +1,358 @@
+/*
+ * Copyright (c) 2016 Chelsio Communications, Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#ifndef __CXGBIT_H__
+#define __CXGBIT_H__
+
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+
+#include 
+
+#include 
+
+#include 
+#include 
+#include 
+
+#include "t4_regs.h"
+#include "t4_msg.h"
+#include "cxgb4.h"
+#include "cxgb4_uld.h"
+#include "l2t.h"
+#include "cxgb4_ppm.h"
+#include "cxgbit_lro.h"
+
+extern struct mutex cdev_list_lock;
+extern struct list_head cdev_list_head;
+struct cxgbit_np;
+
+struct cxgbit_sock;
+
+struct cxgbit_cmd {
+   struct sk_buff *skb;
+   struct scatterlist sg;
+   struct cxgbi_task_tag_info ttinfo;
+   bool setup_ddp;
+   bool release;
+};
+
+#define CXGBIT_MAX_ISO_PAYLOAD \
+   min_t(u32, MAX_SKB_FRAGS * PAGE_SIZE, 65535)
+
+struct cxgbit_iso_info {
+   u8 flags;
+   u32 mpdu;
+   u32 len;
+   u32 burst_len;
+};
+
+enum cxgbit_skcb_flags {
+   SKCBF_TX_NEED_HDR   = (1 << 0), /* packet nee

LOAN

2016-04-09 Thread darlehen
Brauchen Sie einen Kredit? Wir bieten Darlehen in 2% gelten heute Kontakt mit 
uns auf: legacyassetgro...@hotmail.com
--
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] sd: fixup capacity calculation for 4k drives

2016-04-09 Thread Lee Duncan
On 03/29/2016 01:06 AM, Hannes Reinecke wrote:
> in sd_read_capacity() the sdkp->capacity field changes its meaning:
> after the call to read_capacity_XX() it carries the _unscaled_ values,
> making the comparison between the original value and the new value
> always false for drives with a sector size != 512.
> 
> Signed-off-by: Hannes Reinecke 
> ---
>  drivers/scsi/sd.c | 69 
> +++
>  1 file changed, 39 insertions(+), 30 deletions(-)
> 
> diff --git a/drivers/scsi/sd.c b/drivers/scsi/sd.c
> index 5a5457a..0afe113 100644
> --- a/drivers/scsi/sd.c
> +++ b/drivers/scsi/sd.c
> @@ -2046,7 +2046,7 @@ static void read_capacity_error(struct scsi_disk *sdkp, 
> struct scsi_device *sdp,
>  #define READ_CAPACITY_RETRIES_ON_RESET   10
>  
>  static int read_capacity_16(struct scsi_disk *sdkp, struct scsi_device *sdp,
> - unsigned char *buffer)
> + unsigned char *buffer, u64 *capacity)
>  {
>   unsigned char cmd[16];
>   struct scsi_sense_hdr sshdr;
> @@ -2054,8 +2054,8 @@ static int read_capacity_16(struct scsi_disk *sdkp, 
> struct scsi_device *sdp,
>   int the_result;
>   int retries = 3, reset_retries = READ_CAPACITY_RETRIES_ON_RESET;
>   unsigned int alignment;
> - unsigned long long lba;
> - unsigned sector_size;
> + u64 lba;
> + u32 sector_size;
>  
>   if (sdp->no_read_capacity_16)
>   return -EINVAL;
> @@ -2114,7 +2114,7 @@ static int read_capacity_16(struct scsi_disk *sdkp, 
> struct scsi_device *sdp,
>   sd_printk(KERN_ERR, sdkp, "Too big for this kernel. Use a "
>   "kernel compiled with support for large block "
>   "devices.\n");
> - sdkp->capacity = 0;
> + *capacity = 0;
>   return -EOVERFLOW;
>   }
>  
> @@ -2137,20 +2137,20 @@ static int read_capacity_16(struct scsi_disk *sdkp, 
> struct scsi_device *sdp,
>   sd_config_discard(sdkp, SD_LBP_WS16);
>   }
>  
> - sdkp->capacity = lba + 1;
> + *capacity = lba + 1;
>   return sector_size;
>  }
>  
>  static int read_capacity_10(struct scsi_disk *sdkp, struct scsi_device *sdp,
> - unsigned char *buffer)
> + unsigned char *buffer, u64 *capacity)
>  {
>   unsigned char cmd[16];
>   struct scsi_sense_hdr sshdr;
>   int sense_valid = 0;
>   int the_result;
>   int retries = 3, reset_retries = READ_CAPACITY_RETRIES_ON_RESET;
> - sector_t lba;
> - unsigned sector_size;
> + u32 lba;
> + u32 sector_size;
>  
>   do {
>   cmd[0] = READ_CAPACITY;
> @@ -2191,7 +2191,7 @@ static int read_capacity_10(struct scsi_disk *sdkp, 
> struct scsi_device *sdp,
>   /* Some buggy (usb cardreader) devices return an lba of
>  0x when the want to report a size of 0 (with
>  which they really mean no media is present) */
> - sdkp->capacity = 0;
> + *capacity = 0;
>   sdkp->physical_block_size = sector_size;
>   return sector_size;
>   }
> @@ -2200,11 +2200,11 @@ static int read_capacity_10(struct scsi_disk *sdkp, 
> struct scsi_device *sdp,
>   sd_printk(KERN_ERR, sdkp, "Too big for this kernel. Use a "
>   "kernel compiled with support for large block "
>   "devices.\n");
> - sdkp->capacity = 0;
> + *capacity = 0;
>   return -EOVERFLOW;
>   }
>  
> - sdkp->capacity = lba + 1;
> + *capacity = (u64)lba + 1;
>   sdkp->physical_block_size = sector_size;
>   return sector_size;
>  }
> @@ -2230,34 +2230,38 @@ sd_read_capacity(struct scsi_disk *sdkp, unsigned 
> char *buffer)
>  {
>   int sector_size;
>   struct scsi_device *sdp = sdkp->device;
> - sector_t old_capacity = sdkp->capacity;
> + u64 old_capacity = sdkp->capacity, new_capacity;
>  
>   if (sd_try_rc16_first(sdp)) {
> - sector_size = read_capacity_16(sdkp, sdp, buffer);
> + sector_size = read_capacity_16(sdkp, sdp, buffer,
> +&new_capacity);
>   if (sector_size == -EOVERFLOW)
>   goto got_data;
>   if (sector_size == -ENODEV)
>   return;
>   if (sector_size < 0)
> - sector_size = read_capacity_10(sdkp, sdp, buffer);
> + sector_size = read_capacity_10(sdkp, sdp, buffer,
> +&new_capacity);
>   if (sector_size < 0)
>   return;
>   } else {
> - sector_size = read_capacity_10(sdkp, sdp, buffer);
> + sector_size = read_capacity_10(sdkp, sdp, buffer,
> +&new_capacit