[PATCH 1/1] scsi: add Synology to 1024 sector blacklist

2015-05-22 Thread michaelc
From: Mike Christie 

Another day another iSCSI target that cannot handle large IOs.
The Synology iSCSI targets report:

Block limits VPD page (SBC):
  Write same no zero (WSNZ): 0
  Maximum compare and write length: 0 blocks
  Optimal transfer length granularity: 0 blocks
  Maximum transfer length: 0 blocks
  Optimal transfer length: 0 blocks
  Maximum prefetch length: 0 blocks
  Maximum unmap LBA count: 0
  Maximum unmap block descriptor count: 0
  Optimal unmap granularity: 0
  Unmap granularity alignment valid: 0
  Unmap granularity alignment: 0
  Maximum write same length: 0x0 blocks

and the size of the command it can handle seems to depend on how much
memory it can allocate at the time. This results in IO errors when
handling large IOs. This patch just has us use the old 1024 default
sectors for this target by adding it to the scsi blacklist.

Reported-by: Ancoron Luciferis 
Signed-off-by: Mike Christie 
---
 drivers/scsi/scsi_devinfo.c | 1 +
 1 file changed, 1 insertion(+)

diff --git a/drivers/scsi/scsi_devinfo.c b/drivers/scsi/scsi_devinfo.c
index 848c7ca..d2a8bdf 100644
--- a/drivers/scsi/scsi_devinfo.c
+++ b/drivers/scsi/scsi_devinfo.c
@@ -227,6 +227,7 @@ static struct {
{"Promise", "VTrak E610f", NULL, BLIST_SPARSELUN | BLIST_NO_RSOC},
{"Promise", "", NULL, BLIST_SPARSELUN},
{"QNAP", "iSCSI Storage", NULL, BLIST_MAX_1024}, 
+   {"SYNOLOGY", "iSCSI Storage", NULL, BLIST_MAX_1024},
{"QUANTUM", "XP34301", "1071", BLIST_NOTQ},
{"REGAL", "CDC-4X", NULL, BLIST_MAX5LUN | BLIST_SINGLELUN},
{"SanDisk", "ImageMate CF-SD1", NULL, BLIST_FORCELUN},
-- 
1.8.3.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 1/1] SCSI: add 1024 max sectors black list flag

2015-04-20 Thread michaelc
From: Mike Christie 

This works around a issue with qnap iscsi targets not handling large IOs
very well.

The target returns:

VPD INQUIRY: Block limits page (SBC)
  Maximum compare and write length: 1 blocks
  Optimal transfer length granularity: 1 blocks
  Maximum transfer length: 4294967295 blocks
  Optimal transfer length: 4294967295 blocks
  Maximum prefetch, xdread, xdwrite transfer length: 0 blocks
  Maximum unmap LBA count: 8388607
  Maximum unmap block descriptor count: 1
  Optimal unmap granularity: 16383
  Unmap granularity alignment valid: 0
  Unmap granularity alignment: 0
  Maximum write same length: 0x blocks
  Maximum atomic transfer length: 0
  Atomic alignment: 0
  Atomic transfer length granularity: 0

and it is *sometimes* able to handle at least one IO of size up to 8 MB. We
have seen in traces where it will sometimes work, but other times it
looks like it fails and it looks like it returns failures if we send
multiple large IOs sometimes. Also it looks like it can return 2 different
errors. It will sometimes send iscsi reject errors indicating out of
resources or it will send invalid cdb illegal requests check conditions.
And then when it sends iscsi rejects it does not seem to handle retries
when there are command sequence holes, so I could not just add code to
try and gracefully handle that error code.

The problem is that we do not have a good contact for the company,
so we are not able to determine under what conditions it returns
which error and why it sometimes works.

So, this patch just adds a new black list flag to set targets like this to
the old max safe sectors of 1024. The max_hw_sectors changes added in 3.19
caused this regression, so I also ccing stable.

Reported-by: Christian Hesse 
Signed-off-by: Mike Christie 
Cc: sta...@vger.kernel.org

---
 drivers/scsi/scsi_devinfo.c | 1 +
 drivers/scsi/scsi_scan.c| 6 ++
 include/scsi/scsi_devinfo.h | 1 +
 3 files changed, 8 insertions(+)

diff --git a/drivers/scsi/scsi_devinfo.c b/drivers/scsi/scsi_devinfo.c
index 262ab83..848c7ca 100644
--- a/drivers/scsi/scsi_devinfo.c
+++ b/drivers/scsi/scsi_devinfo.c
@@ -226,6 +226,7 @@ static struct {
{"PIONEER", "CD-ROM DRM-624X", NULL, BLIST_FORCELUN | BLIST_SINGLELUN},
{"Promise", "VTrak E610f", NULL, BLIST_SPARSELUN | BLIST_NO_RSOC},
{"Promise", "", NULL, BLIST_SPARSELUN},
+   {"QNAP", "iSCSI Storage", NULL, BLIST_MAX_1024}, 
{"QUANTUM", "XP34301", "1071", BLIST_NOTQ},
{"REGAL", "CDC-4X", NULL, BLIST_MAX5LUN | BLIST_SINGLELUN},
{"SanDisk", "ImageMate CF-SD1", NULL, BLIST_FORCELUN},
diff --git a/drivers/scsi/scsi_scan.c b/drivers/scsi/scsi_scan.c
index 9c0a520..3e6142f 100644
--- a/drivers/scsi/scsi_scan.c
+++ b/drivers/scsi/scsi_scan.c
@@ -897,6 +897,12 @@ static int scsi_add_lun(struct scsi_device *sdev, unsigned 
char *inq_result,
 */
if (*bflags & BLIST_MAX_512)
blk_queue_max_hw_sectors(sdev->request_queue, 512);
+   /*
+* Max 1024 sector transfer length for targets that report incorrect
+* max/optimal lengths and relied on the old block layer safe default
+*/
+   else if (*bflags & BLIST_MAX_1024)
+   blk_queue_max_hw_sectors(sdev->request_queue, 1024);
 
/*
 * Some devices may not want to have a start command automatically
diff --git a/include/scsi/scsi_devinfo.h b/include/scsi/scsi_devinfo.h
index 183eaab..96e3f56 100644
--- a/include/scsi/scsi_devinfo.h
+++ b/include/scsi/scsi_devinfo.h
@@ -36,5 +36,6 @@
 for sequential scan */
 #define BLIST_TRY_VPD_PAGES0x1000 /* Attempt to read VPD pages */
 #define BLIST_NO_RSOC  0x2000 /* don't try to issue RSOC */
+#define BLIST_MAX_1024 0x4000 /* maximum 1024 sector cdb length */
 
 #endif
-- 
1.8.3.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 1/1] Sync iscsi fw boot flags

2015-02-03 Thread michaelc
From: Mike Christie 

iBFT and non-iBFT drivers use the same iscsi boot sysfs
interface. For iBFT we just directly export whatever
is left by the FW. For non-iBFT drivers we do vendor
specific commands to get the info or its just hard coded.

This patch syncs up how non-iBFT drivers export boot flag
info. The boot flags being defined in this patch match
the iBFT flags that indicate if the boot info found was
valid and if it was used for to boot with.

Signed-off-by: Mike Christie 
---
 drivers/scsi/be2iscsi/be_main.c  | 8 +---
 drivers/scsi/qla4xxx/ql4_def.h   | 1 -
 drivers/scsi/qla4xxx/ql4_os.c| 6 --
 include/linux/iscsi_boot_sysfs.h | 3 +++
 4 files changed, 12 insertions(+), 6 deletions(-)

diff --git a/drivers/scsi/be2iscsi/be_main.c b/drivers/scsi/be2iscsi/be_main.c
index f319340..cd4aff9 100644
--- a/drivers/scsi/be2iscsi/be_main.c
+++ b/drivers/scsi/be2iscsi/be_main.c
@@ -429,7 +429,8 @@ static ssize_t beiscsi_show_boot_tgt_info(void *data, int 
type, char *buf)
 auth_data.chap.intr_secret);
break;
case ISCSI_BOOT_TGT_FLAGS:
-   rc = sprintf(str, "2\n");
+   rc = sprintf(str, "%u\n",
+ISCSI_BOOT_FLAG_VALID | 
ISCSI_BOOT_FLAG_FW_BOOT_SEL);
break;
case ISCSI_BOOT_TGT_NIC_ASSOC:
rc = sprintf(str, "0\n");
@@ -466,8 +467,9 @@ static ssize_t beiscsi_show_boot_eth_info(void *data, int 
type, char *buf)
 
switch (type) {
case ISCSI_BOOT_ETH_FLAGS:
-   rc = sprintf(str, "2\n");
-   break;
+   rc = sprintf(str, "%u\n",
+ISCSI_BOOT_FLAG_VALID | 
ISCSI_BOOT_FLAG_FW_BOOT_SEL);
+   break;
case ISCSI_BOOT_ETH_INDEX:
rc = sprintf(str, "0\n");
break;
diff --git a/drivers/scsi/qla4xxx/ql4_def.h b/drivers/scsi/qla4xxx/ql4_def.h
index 8f6d0fb..0380669 100644
--- a/drivers/scsi/qla4xxx/ql4_def.h
+++ b/drivers/scsi/qla4xxx/ql4_def.h
@@ -796,7 +796,6 @@ struct scsi_qla_host {
 #define CHAP_DMA_BLOCK_SIZE512
struct workqueue_struct *task_wq;
unsigned long ddb_idx_map[MAX_DDB_ENTRIES / BITS_PER_LONG];
-#define SYSFS_FLAG_FW_SEL_BOOT 2
struct iscsi_boot_kset *boot_kset;
struct ql4_boot_tgt_info boot_tgt;
uint16_t phy_port_num;
diff --git a/drivers/scsi/qla4xxx/ql4_os.c b/drivers/scsi/qla4xxx/ql4_os.c
index 6d25879..b63985f 100644
--- a/drivers/scsi/qla4xxx/ql4_os.c
+++ b/drivers/scsi/qla4xxx/ql4_os.c
@@ -5705,7 +5705,8 @@ static ssize_t qla4xxx_show_boot_eth_info(void *data, int 
type, char *buf)
 
switch (type) {
case ISCSI_BOOT_ETH_FLAGS:
-   rc = sprintf(str, "%d\n", SYSFS_FLAG_FW_SEL_BOOT);
+   rc = sprintf(str, "%d\n",
+ISCSI_BOOT_FLAG_VALID | 
ISCSI_BOOT_FLAG_FW_BOOT_SEL);
break;
case ISCSI_BOOT_ETH_INDEX:
rc = sprintf(str, "0\n");
@@ -5814,7 +5815,8 @@ qla4xxx_show_boot_tgt_info(struct ql4_boot_session_info 
*boot_sess, int type,
 (char *)&boot_conn->chap.intr_secret);
break;
case ISCSI_BOOT_TGT_FLAGS:
-   rc = sprintf(str, "%d\n", SYSFS_FLAG_FW_SEL_BOOT);
+   rc = sprintf(str, "%d\n",
+ISCSI_BOOT_FLAG_VALID | 
ISCSI_BOOT_FLAG_FW_BOOT_SEL);
break;
case ISCSI_BOOT_TGT_NIC_ASSOC:
rc = sprintf(str, "0\n");
diff --git a/include/linux/iscsi_boot_sysfs.h b/include/linux/iscsi_boot_sysfs.h
index 2a8b165..3f273d6 100644
--- a/include/linux/iscsi_boot_sysfs.h
+++ b/include/linux/iscsi_boot_sysfs.h
@@ -16,6 +16,9 @@
 #ifndef _ISCSI_BOOT_SYSFS_
 #define _ISCSI_BOOT_SYSFS_
 
+#define ISCSI_BOOT_FLAG_VALID  0x1
+#define ISCSI_BOOT_FLAG_FW_BOOT_SEL0x2
+
 /*
  * The text attributes names for each of the kobjects.
 */
-- 
1.8.3.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 1/1] [PATCH REGRESSION] alua: fix bus detach oops

2015-01-28 Thread michaelc
From: Mike Christie 

This fixes a regression caused by commit
1d5203284d8acbdfdf9b478d434450b34f338f28

The bug is that the alua detach() callout will try to access the
sddev->scsi_dh_data, but we have already set it to NULL. This patch
moves the clearing of that field to after detach() is called.

It looks like the regression was added during 3.19 development,
so it has not been in a released kernel, and so I did not cc
stable.

Signed-off-by: Mike Christie 

---
 drivers/scsi/device_handler/scsi_dh.c | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)

diff --git a/drivers/scsi/device_handler/scsi_dh.c 
b/drivers/scsi/device_handler/scsi_dh.c
index 1dba62c..1efebc9 100644
--- a/drivers/scsi/device_handler/scsi_dh.c
+++ b/drivers/scsi/device_handler/scsi_dh.c
@@ -136,11 +136,12 @@ static void __detach_handler (struct kref *kref)
struct scsi_device_handler *scsi_dh = scsi_dh_data->scsi_dh;
struct scsi_device *sdev = scsi_dh_data->sdev;
 
+   scsi_dh->detach(sdev);
+
spin_lock_irq(sdev->request_queue->queue_lock);
sdev->scsi_dh_data = NULL;
spin_unlock_irq(sdev->request_queue->queue_lock);
 
-   scsi_dh->detach(sdev);
sdev_printk(KERN_NOTICE, sdev, "%s: Detached\n", scsi_dh->name);
module_put(scsi_dh->module);
 }
-- 
1.8.3.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 2/5] block: add function to issue compare and write

2014-10-15 Thread michaelc
From: Mike Christie 

This patch adds block layer helpers to send a compare and write request.
It differs from requests like discard and write same in that there is a
setup function and a issue one. I did this to allow callers add multiple
pages with variying offsets and lengths.

For the miscompare failure case I am currently having drivers return
-ECANCELED, but was not sure if there is a better return code.

Signed-off-by: Mike Christie 
---
 block/blk-lib.c   |   79 +
 include/linux/blk_types.h |6 ++-
 include/linux/blkdev.h|6 +++
 3 files changed, 89 insertions(+), 2 deletions(-)

diff --git a/block/blk-lib.c b/block/blk-lib.c
index 8411be3..fbb1a91 100644
--- a/block/blk-lib.c
+++ b/block/blk-lib.c
@@ -141,6 +141,85 @@ int blkdev_issue_discard(struct block_device *bdev, 
sector_t sector,
 }
 EXPORT_SYMBOL(blkdev_issue_discard);
 
+struct bio_cmp_and_write_data {
+   int err;
+   struct completion   *wait;
+};
+
+static void bio_cmp_and_write_end_io(struct bio *bio, int err)
+{
+   struct bio_cmp_and_write_data *data = bio->bi_private;
+
+   data->err = err;
+   complete(data->wait);
+   bio_put(bio);
+}
+
+/**
+ * blkdev_setup_cmp_and_write - setup a bio for a compare and write operation
+ * @bdev:  blockdev to issue discard for
+ * @sector:start sector
+ * @gfp_mask:  memory allocation flags (for bio_alloc)
+ * @nr_pages:  number of pages that contain the data to be written and compared
+ *
+ * This function should be called to allocate the bio used for
+ * blkdev_issue_cmp_and_write. The caller should add the pages to be compared
+ * followed by the write pages using bio_add_pc_page.
+ */
+struct bio *blkdev_setup_cmp_and_write(struct block_device *bdev,
+  sector_t sector, gfp_t gfp_mask,
+  int nr_pages)
+{
+   struct bio *bio;
+
+   bio = bio_alloc(gfp_mask, nr_pages);
+   if (!bio)
+   return NULL;
+
+   bio->bi_iter.bi_sector = sector;
+   bio->bi_end_io = bio_cmp_and_write_end_io;
+   bio->bi_bdev = bdev;
+   return bio;
+}
+EXPORT_SYMBOL(blkdev_setup_cmp_and_write);
+
+/**
+ * blkdev_issue_cmp_and_write - queue a compare and write operation
+ * @bio:   bio prepd with blkdev_setup_cmp_and_write.
+ * Description:
+ *Issue a compare and write bio for the sectors in question. For the
+ *execution of this request the handler should atomically read @nr_sects
+ *from starting sector @sector, compare them, and if matched write
+ *@nr_sects to @sector.
+ *
+ *If the compare fails and data is not written the handler should return
+ *-ECANCELED.
+ */
+int blkdev_issue_cmp_and_write(struct bio *bio)
+{
+   struct request_queue *q = bdev_get_queue(bio->bi_bdev);
+   DECLARE_COMPLETION_ONSTACK(wait);
+   struct bio_cmp_and_write_data data;
+   unsigned int max_cmp_and_write_sectors;
+
+   max_cmp_and_write_sectors = q->limits.max_cmp_and_write_sectors;
+   if (max_cmp_and_write_sectors == 0)
+   return -EOPNOTSUPP;
+
+   if (max_cmp_and_write_sectors < bio->bi_iter.bi_size >> 9)
+   return -EINVAL;
+
+   data.err = 0;
+   data.wait = &wait;
+   bio->bi_private = &data;
+
+   submit_bio(REQ_WRITE | REQ_CMP_AND_WRITE, bio);
+   /* Wait for bio in-flight */
+   wait_for_completion_io(&wait);
+   return data.err;
+}
+EXPORT_SYMBOL(blkdev_issue_cmp_and_write);
+
 /**
  * blkdev_issue_write_same - queue a write same operation
  * @bdev:  target blockdev
diff --git a/include/linux/blk_types.h b/include/linux/blk_types.h
index 66c2167..37d1eff 100644
--- a/include/linux/blk_types.h
+++ b/include/linux/blk_types.h
@@ -160,7 +160,7 @@ enum rq_flag_bits {
__REQ_DISCARD,  /* request to discard sectors */
__REQ_SECURE,   /* secure discard (used with __REQ_DISCARD) */
__REQ_WRITE_SAME,   /* write same block many times */
-
+   __REQ_CMP_AND_WRITE,/* compare data and write if matched */
__REQ_NOIDLE,   /* don't anticipate more IO after this one */
__REQ_FUA,  /* forced unit access */
__REQ_FLUSH,/* request for cache flush */
@@ -203,14 +203,16 @@ enum rq_flag_bits {
 #define REQ_PRIO   (1ULL << __REQ_PRIO)
 #define REQ_DISCARD(1ULL << __REQ_DISCARD)
 #define REQ_WRITE_SAME (1ULL << __REQ_WRITE_SAME)
+#define REQ_CMP_AND_WRITE  (1ULL << __REQ_CMP_AND_WRITE)
 #define REQ_NOIDLE (1ULL << __REQ_NOIDLE)
 
+
 #define REQ_FAILFAST_MASK \
(REQ_FAILFAST_DEV | REQ_FAILFAST_TRANSPORT | REQ_FAILFAST_DRIVER)
 #define REQ_COMMON_MASK \
(REQ_WRITE | REQ_FAILFAST_MASK | REQ_SYNC | REQ_META | REQ_PRIO | \
 REQ_DISCARD | REQ_WRITE_SAME | REQ_NOIDLE | REQ_FLUSH | REQ_FUA | \
-REQ_SECURE)
+REQ_SECURE | REQ_CMP

[PATCH 4/5] lio: use REQ_COMPARE_AND_WRITE if supported

2014-10-15 Thread michaelc
From: Mike Christie 

This has lio callout to the backing store module if it supports
using REQ_COMPARE_AND_WRITE. The backing store would set the
device attribute max_compare_and_write_len if it supports using
the new request type. If it is not supported then we do the
read/cmp/write emulation in the sbc layer like before.

Signed-off-by: Mike Christie 
---
 drivers/target/target_core_sbc.c   |   21 -
 drivers/target/target_core_spc.c   |   12 ++--
 drivers/target/target_core_transport.c |1 +
 include/target/target_core_backend.h   |1 +
 include/target/target_core_base.h  |1 +
 5 files changed, 29 insertions(+), 7 deletions(-)

diff --git a/drivers/target/target_core_sbc.c b/drivers/target/target_core_sbc.c
index ebe62af..fe0c16a 100644
--- a/drivers/target/target_core_sbc.c
+++ b/drivers/target/target_core_sbc.c
@@ -555,6 +555,21 @@ sbc_compare_and_write(struct se_cmd *cmd)
return TCM_NO_SENSE;
 }
 
+static void sbc_setup_compare_and_write(struct se_cmd *cmd, struct sbc_ops 
*ops,
+   u32 sectors)
+{
+   cmd->t_task_nolb = sectors;
+   cmd->se_cmd_flags |= SCF_SCSI_DATA_CDB | SCF_COMPARE_AND_WRITE;
+
+   if (cmd->se_dev->dev_attrib.max_compare_and_write_len) {
+   cmd->execute_cmd = ops->execute_compare_and_write;
+   } else {
+   cmd->execute_rw = ops->execute_rw;
+   cmd->execute_cmd = sbc_compare_and_write;
+   cmd->transport_complete_callback = compare_and_write_callback;
+   }
+}
+
 static int
 sbc_set_prot_op_checks(u8 protect, enum target_prot_type prot_type,
   bool is_write, struct se_cmd *cmd)
@@ -842,11 +857,7 @@ sbc_parse_cdb(struct se_cmd *cmd, struct sbc_ops *ops)
 */
size = 2 * sbc_get_size(cmd, sectors);
cmd->t_task_lba = get_unaligned_be64(&cdb[2]);
-   cmd->t_task_nolb = sectors;
-   cmd->se_cmd_flags |= SCF_SCSI_DATA_CDB | SCF_COMPARE_AND_WRITE;
-   cmd->execute_rw = ops->execute_rw;
-   cmd->execute_cmd = sbc_compare_and_write;
-   cmd->transport_complete_callback = compare_and_write_callback;
+   sbc_setup_compare_and_write(cmd, ops, sectors);
break;
case READ_CAPACITY:
size = READ_CAP_LEN;
diff --git a/drivers/target/target_core_spc.c b/drivers/target/target_core_spc.c
index 6cd7222..7db8c22 100644
--- a/drivers/target/target_core_spc.c
+++ b/drivers/target/target_core_spc.c
@@ -525,8 +525,16 @@ spc_emulate_evpd_b0(struct se_cmd *cmd, unsigned char *buf)
/*
 * Set MAXIMUM COMPARE AND WRITE LENGTH
 */
-   if (dev->dev_attrib.emulate_caw)
-   buf[5] = 0x01;
+   if (dev->dev_attrib.emulate_caw) {
+   if (!dev->dev_attrib.max_compare_and_write_len)
+   /*
+* if backing device does not have special handling
+* then sbc will support up to 1 block.
+*/
+   buf[5] = 0x01;
+   else
+   buf[5] = dev->dev_attrib.max_compare_and_write_len;
+   }
 
/*
 * Set OPTIMAL TRANSFER LENGTH GRANULARITY
diff --git a/drivers/target/target_core_transport.c 
b/drivers/target/target_core_transport.c
index 9ea0d5f..e7706f9 100644
--- a/drivers/target/target_core_transport.c
+++ b/drivers/target/target_core_transport.c
@@ -1637,6 +1637,7 @@ void transport_generic_request_failure(struct se_cmd *cmd,
case TCM_LOGICAL_BLOCK_GUARD_CHECK_FAILED:
case TCM_LOGICAL_BLOCK_APP_TAG_CHECK_FAILED:
case TCM_LOGICAL_BLOCK_REF_TAG_CHECK_FAILED:
+   case TCM_MISCOMPARE_VERIFY:
break;
case TCM_OUT_OF_RESOURCES:
sense_reason = TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE;
diff --git a/include/target/target_core_backend.h 
b/include/target/target_core_backend.h
index 9adc1bc..06924b1 100644
--- a/include/target/target_core_backend.h
+++ b/include/target/target_core_backend.h
@@ -53,6 +53,7 @@ struct sbc_ops {
sense_reason_t (*execute_write_same)(struct se_cmd *cmd);
sense_reason_t (*execute_write_same_unmap)(struct se_cmd *cmd);
sense_reason_t (*execute_unmap)(struct se_cmd *cmd);
+   sense_reason_t (*execute_compare_and_write)(struct se_cmd *cmd);
 };
 
 inttransport_subsystem_register(struct se_subsystem_api *);
diff --git a/include/target/target_core_base.h 
b/include/target/target_core_base.h
index 23c518a..bc0a26e 100644
--- a/include/target/target_core_base.h
+++ b/include/target/target_core_base.h
@@ -697,6 +697,7 @@ struct se_dev_attrib {
u32 unmap_granularity;
u32 unmap_granularity_alignment;
u32 max_write_same_len;
+   u32 max_compare_and_write_len;
u32 max_bytes_per_io;
st

[PATCH 0/5] block/scsi/lio support for COMPARE_AND_WRITE

2014-10-15 Thread michaelc
The following patches implement the SCSI command COMPARE_AND_WRITE as a new
bio/request type REQ_CMP_AND_WRITE. COMPARE_AND_WRITE is defined in the
SCSI SBC (SCSI block command) specs as:

The COMPARE AND WRITE command requests that the device server perform the
following as an uninterrupted series of actions:

1) perform the following operations:
A) read the specified logical blocks; and
B) transfer the specified number of logical blocks from the Data-Out
Buffer (i.e., the verify instance of the data is transferred from the
Data-Out Buffer);

2) compare the data read from the specified logical blocks with the verify
instance of the data; and
3) If the compared data matches, then perform the following operations:
1) transfer the specified number of logical blocks from the Data-Out
Buffer (i.e., the write instance of the data transferred from the
Data-Out Buffer); and
2) write those logical blocks.

The most command use of this command today is in VMware ESX where it is used
for locking. See
http://blogs.vmware.com/vsphere/2012/05/vmfs-locking-uncovered.html
[in ESX is it is called ATS (atomic test and set)] for more VMware info.
Linux fits into this use, because its SCSI target layer (LIO) is commonly
used as storage for ESX VMs.

Currently, to support this command in LIO we emulate it by taking a lock,
doing a read, comparing it, then doing a write. The problem this patchset
tries to solve is that in many cases it is more efficient to pass the one
COMPARE_AND_REQUEST request directly to the device where it might have
optimized locking and also will require fewer requests to/from the target
and backing storage device.

I am also bugging the ceph-devel list, because I am working on LIO + ceph
support. I am interested in using ceph's rbd device for the backing
storage for LIO, and I was thinking this request could be implemented similar
to how REQ_DISCARD (unmap/trim) is going to be, and I wanted to get some early
feedback. I know the scsi layer better, so I have only added support in sd in
this patchset.

The following patches were made over the target-pending for-next branch but
also apply to Linus's tree.



--
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 3/5] scsi: add support for COMPARE_AND_WRITE

2014-10-15 Thread michaelc
From: Mike Christie 

This patch adds support to detect if a device supports COMPARE_AND_WRITE
and execute REQ_COMPARE_AND_WRITE commands.

Signed-off-by: Mike Christie 
---
 drivers/scsi/scsi_lib.c |7 +
 drivers/scsi/sd.c   |   63 +++
 drivers/scsi/sd.h   |1 +
 3 files changed, 71 insertions(+), 0 deletions(-)

diff --git a/drivers/scsi/scsi_lib.c b/drivers/scsi/scsi_lib.c
index d837dc1..9e7ba4f 100644
--- a/drivers/scsi/scsi_lib.c
+++ b/drivers/scsi/scsi_lib.c
@@ -1021,6 +1021,13 @@ void scsi_io_completion(struct scsi_cmnd *cmd, unsigned 
int good_bytes)
/* See SSC3rXX or current. */
action = ACTION_FAIL;
break;
+   case MISCOMPARE:
+   /* miscompare during verify */
+   if (sshdr.asc == 0x1d)
+   /* TODO: better error code to use ??? */
+   error = -ECANCELED;
+   action = ACTION_FAIL;
+   break;
default:
action = ACTION_FAIL;
break;
diff --git a/drivers/scsi/sd.c b/drivers/scsi/sd.c
index 2c2041c..d1fa4ef 100644
--- a/drivers/scsi/sd.c
+++ b/drivers/scsi/sd.c
@@ -477,6 +477,16 @@ max_write_same_blocks_store(struct device *dev, struct 
device_attribute *attr,
 }
 static DEVICE_ATTR_RW(max_write_same_blocks);
 
+static ssize_t
+max_cmp_and_write_blocks_show(struct device *dev, struct device_attribute 
*attr,
+ char *buf)
+{
+   struct scsi_disk *sdkp = to_scsi_disk(dev);
+
+   return snprintf(buf, 20, "%u\n", sdkp->max_cmp_and_write_blocks);
+}
+static DEVICE_ATTR_RO(max_cmp_and_write_blocks);
+
 static struct attribute *sd_disk_attrs[] = {
&dev_attr_cache_type.attr,
&dev_attr_FUA.attr,
@@ -488,6 +498,7 @@ static struct attribute *sd_disk_attrs[] = {
&dev_attr_thin_provisioning.attr,
&dev_attr_provisioning_mode.attr,
&dev_attr_max_write_same_blocks.attr,
+   &dev_attr_max_cmp_and_write_blocks.attr,
&dev_attr_max_medium_access_timeouts.attr,
NULL,
 };
@@ -635,6 +646,54 @@ static void sd_prot_op(struct scsi_cmnd *scmd, unsigned 
int dif)
scsi_set_prot_type(scmd, dif);
 }
 
+static void sd_config_cmp_and_write(struct scsi_disk *sdkp)
+{
+   if (sdkp->max_cmp_and_write_blocks > sdkp->max_xfer_blocks) {
+   /* Invalid settings returned. Do not try to support for now */
+   blk_queue_max_cmp_and_write_sectors(sdkp->disk->queue, 0);
+   return;
+   }
+
+   /*
+* mult by 2, because the block layer wants the total number of
+* sectors that will be put in bios and transferred.
+*/
+   blk_queue_max_cmp_and_write_sectors(sdkp->disk->queue,
+   2 * sdkp->max_cmp_and_write_blocks *
+   (sdkp->device->sector_size  >> 9));
+}
+
+/**
+ * sd_setup_cmp_and_write_cmnd - compare and write data
+ * @cmd: scsi_cmnd to prepare
+ **/
+static int sd_setup_cmd_and_write_cmd(struct scsi_cmnd *cmd)
+{
+   struct request *rq = cmd->request;
+   struct scsi_device *sdp = cmd->device;
+   sector_t sector = blk_rq_pos(rq);
+   unsigned int nr_sectors = blk_rq_sectors(rq);
+
+   sector >>= ilog2(sdp->sector_size) - 9;
+   nr_sectors >>= ilog2(sdp->sector_size) - 9;
+
+   cmd->cmnd[0] = COMPARE_AND_WRITE;
+   put_unaligned_be64(sector, &cmd->cmnd[2]);
+   /*
+* rq/bio contains total data to transfer, but the nr LBAs field
+* is only the data to be compared/written in each step of the
+* operation.
+*/
+   cmd->cmnd[13] = nr_sectors >> 1;
+   /* TODO - wrprotect and FUA and DPO flags */
+
+   cmd->transfersize = sdp->sector_size;
+   cmd->allowed = SD_MAX_RETRIES;
+   rq->timeout = SD_TIMEOUT;
+
+   return scsi_init_io(cmd, GFP_ATOMIC);
+}
+
 static void sd_config_discard(struct scsi_disk *sdkp, unsigned int mode)
 {
struct request_queue *q = sdkp->disk->queue;
@@ -1134,6 +1193,8 @@ static int sd_init_command(struct scsi_cmnd *cmd)
return sd_setup_write_same_cmnd(cmd);
else if (rq->cmd_flags & REQ_FLUSH)
return sd_setup_flush_cmnd(cmd);
+   else if (rq->cmd_flags & REQ_CMP_AND_WRITE)
+   return sd_setup_cmd_and_write_cmd(cmd);
else
return sd_setup_read_write_cmnd(cmd);
 }
@@ -2596,6 +2657,8 @@ static void sd_read_block_limits(struct scsi_disk *sdkp)
 get_unaligned_be16(&buffer[6]) * sector_sz);
blk_queue_io_opt(sdkp->disk->queue,
 get_unaligned_be32(&buffer[12]) * sector_sz);
+   sdkp->max_cmp_and_write_blocks = buffer[5];
+   sd_config_cmp_and_write(sdkp);
 
if (buffer[3] == 0x3c) {
uns

[PATCH 1/5] block: set the nr of sectors a dev can compare and write atomically

2014-10-15 Thread michaelc
From: Mike Christie 

This adds blk settings helpers to allow drivers to tell the block layer
how many sectors it can process in a COMPARE_AND_WRITE/ATS request.

Signed-off-by: Mike Christie 
---
 block/blk-settings.c   |   20 
 block/blk-sysfs.c  |   11 +++
 include/linux/blkdev.h |3 +++
 3 files changed, 34 insertions(+), 0 deletions(-)

diff --git a/block/blk-settings.c b/block/blk-settings.c
index f1a1795..b33cf1c 100644
--- a/block/blk-settings.c
+++ b/block/blk-settings.c
@@ -114,6 +114,7 @@ void blk_set_default_limits(struct queue_limits *lim)
lim->max_segment_size = BLK_MAX_SEGMENT_SIZE;
lim->max_sectors = lim->max_hw_sectors = BLK_SAFE_MAX_SECTORS;
lim->chunk_sectors = 0;
+   lim->max_cmp_and_write_sectors = 0;
lim->max_write_same_sectors = 0;
lim->max_discard_sectors = 0;
lim->discard_granularity = 0;
@@ -147,6 +148,7 @@ void blk_set_stacking_limits(struct queue_limits *lim)
lim->max_hw_sectors = UINT_MAX;
lim->max_segment_size = UINT_MAX;
lim->max_sectors = UINT_MAX;
+   lim->max_cmp_and_write_sectors = UINT_MAX;
lim->max_write_same_sectors = UINT_MAX;
 }
 EXPORT_SYMBOL(blk_set_stacking_limits);
@@ -298,6 +300,22 @@ void blk_queue_chunk_sectors(struct request_queue *q, 
unsigned int chunk_sectors
 EXPORT_SYMBOL(blk_queue_chunk_sectors);
 
 /**
+ * blk_queue_max_cmp_and_write_sectors - set max sectors for a single request
+ * @q:  the request queue for the device
+ * @max_cmp_and_write_sectors: maximum number of 512b sectors to cmp and write
+ *
+ * Description:
+ *This sets the total number of sectors that the device can process
+ *in a compare and write operation.
+ **/
+void blk_queue_max_cmp_and_write_sectors(struct request_queue *q,
+unsigned int max_cmp_and_write_sectors)
+{
+   q->limits.max_cmp_and_write_sectors = max_cmp_and_write_sectors;
+}
+EXPORT_SYMBOL(blk_queue_max_cmp_and_write_sectors);
+
+/**
  * blk_queue_max_discard_sectors - set max sectors for a single discard
  * @q:  the request queue for the device
  * @max_discard_sectors: maximum number of sectors to discard
@@ -548,6 +566,8 @@ int blk_stack_limits(struct queue_limits *t, struct 
queue_limits *b,
t->max_hw_sectors = min_not_zero(t->max_hw_sectors, b->max_hw_sectors);
t->max_write_same_sectors = min(t->max_write_same_sectors,
b->max_write_same_sectors);
+   t->max_cmp_and_write_sectors = min(t->max_cmp_and_write_sectors,
+  b->max_cmp_and_write_sectors);
t->bounce_pfn = min_not_zero(t->bounce_pfn, b->bounce_pfn);
 
t->seg_boundary_mask = min_not_zero(t->seg_boundary_mask,
diff --git a/block/blk-sysfs.c b/block/blk-sysfs.c
index 17f5c84..c546400 100644
--- a/block/blk-sysfs.c
+++ b/block/blk-sysfs.c
@@ -161,6 +161,11 @@ static ssize_t queue_write_same_max_show(struct 
request_queue *q, char *page)
(unsigned long long)q->limits.max_write_same_sectors << 9);
 }
 
+static ssize_t queue_cmp_and_write_max_show(struct request_queue *q, char 
*page)
+{
+   return sprintf(page, "%llu\n",
+   (unsigned long long)q->limits.max_cmp_and_write_sectors << 9);
+}
 
 static ssize_t
 queue_max_sectors_store(struct request_queue *q, const char *page, size_t 
count)
@@ -374,6 +379,11 @@ static struct queue_sysfs_entry queue_write_same_max_entry 
= {
.show = queue_write_same_max_show,
 };
 
+static struct queue_sysfs_entry queue_cmp_and_write_max_entry = {
+   .attr = {.name = "cmp_and_write_max_bytes", .mode = S_IRUGO },
+   .show = queue_cmp_and_write_max_show,
+};
+
 static struct queue_sysfs_entry queue_nonrot_entry = {
.attr = {.name = "rotational", .mode = S_IRUGO | S_IWUSR },
.show = queue_show_nonrot,
@@ -422,6 +432,7 @@ static struct attribute *default_attrs[] = {
&queue_discard_max_entry.attr,
&queue_discard_zeroes_data_entry.attr,
&queue_write_same_max_entry.attr,
+   &queue_cmp_and_write_max_entry.attr,
&queue_nonrot_entry.attr,
&queue_nomerges_entry.attr,
&queue_rq_affinity_entry.attr,
diff --git a/include/linux/blkdev.h b/include/linux/blkdev.h
index 518b465..6d03206 100644
--- a/include/linux/blkdev.h
+++ b/include/linux/blkdev.h
@@ -290,6 +290,7 @@ struct queue_limits {
unsigned intio_opt;
unsigned intmax_discard_sectors;
unsigned intmax_write_same_sectors;
+   unsigned intmax_cmp_and_write_sectors;
unsigned intdiscard_granularity;
unsigned intdiscard_alignment;
 
@@ -1009,6 +1010,8 @@ extern void blk_queue_max_hw_sectors(struct request_queue 
*, unsigned int);
 extern void blk_queue_chunk_sectors(struct request_queue *, unsigned int);
 extern void blk_queue_max_segments(struct request_queue *, unsigned short);

[PATCH 5/5] lio iblock: add support for REQ_CMP_AND_WRITE

2014-10-15 Thread michaelc
From: Mike Christie 

This patch has the iblock backing store use blkdev_issue_cmp_and_write
if the backing store device/queue supports it.

Signed-off-by: Mike Christie 
---
 drivers/target/target_core_iblock.c |   85 ---
 1 files changed, 68 insertions(+), 17 deletions(-)

diff --git a/drivers/target/target_core_iblock.c 
b/drivers/target/target_core_iblock.c
index 7e6b857..cac928a 100644
--- a/drivers/target/target_core_iblock.c
+++ b/drivers/target/target_core_iblock.c
@@ -153,6 +153,11 @@ static int iblock_configure_device(struct se_device *dev)
 */
dev->dev_attrib.max_write_same_len = 0x;
 
+   /* convert from linux block layer 512 byte sector to our block size */
+   dev->dev_attrib.max_compare_and_write_len =
+   (q->limits.max_cmp_and_write_sectors << IBLOCK_LBA_SHIFT) /
+   dev->dev_attrib.hw_block_size;
+
if (blk_queue_nonrot(q))
dev->dev_attrib.is_nonrot = 1;
 
@@ -413,6 +418,67 @@ iblock_execute_sync_cache(struct se_cmd *cmd)
return 0;
 }
 
+/*
+ * Convert the blocksize advertised to the initiator to the 512 byte
+ * units unconditionally used by the Linux block layer.
+ */
+static int iblock_get_lba_shift(struct se_cmd *cmd)
+{
+   struct se_device *dev = cmd->se_dev;
+
+   if (dev->dev_attrib.block_size == 4096)
+   return 3;
+   else if (dev->dev_attrib.block_size == 2048)
+   return 2;
+   else if (dev->dev_attrib.block_size == 1024)
+   return 1;
+   else
+   return 0;
+}
+
+static sense_reason_t
+iblock_execute_compare_and_write(struct se_cmd *cmd)
+{
+   struct block_device *bdev = IBLOCK_DEV(cmd->se_dev)->ibd_bd;
+   int ret, i = 0;
+   sector_t block_lba;
+   struct scatterlist *sg;
+   struct bio *bio;
+
+   block_lba = cmd->t_task_lba << iblock_get_lba_shift(cmd);
+
+   /* assumes SGLs are PAGE_SIZE */
+   bio = blkdev_setup_cmp_and_write(bdev, block_lba, GFP_KERNEL,
+cmd->t_data_nents);
+   if (!bio) {
+   pr_err("blkdev_setup_cmp_and_write() failed\n");
+   return TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE;
+   }
+
+   for_each_sg(cmd->t_data_sg, sg, cmd->t_data_nents, i) {
+   ret = bio_add_pc_page(bdev_get_queue(bdev), bio, sg_page(sg),
+ sg->length, sg->offset);
+   if (ret != sg->length) {
+   bio_put(bio);
+   pr_err("bio_add_pc_page() failed\n");
+   return TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE;
+   }
+   }
+
+   ret = blkdev_issue_cmp_and_write(bio);
+   if (ret == -ECANCELED) {
+   pr_warn("Target/%s: Send MISCOMPARE check condition and 
sense\n",
+   cmd->se_dev->transport->name);
+   return TCM_MISCOMPARE_VERIFY;
+   } else if (ret < 0) {
+   pr_err("blkdev_issue_cmp_and_write() failed: %d\n", ret);
+   return TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE;
+   }
+
+   target_complete_cmd(cmd, GOOD);
+   return 0;
+}
+
 static sense_reason_t
 iblock_do_unmap(struct se_cmd *cmd, void *priv,
sector_t lba, sector_t nolb)
@@ -701,23 +767,7 @@ iblock_execute_rw(struct se_cmd *cmd, struct scatterlist 
*sgl, u32 sgl_nents,
rw = READ;
}
 
-   /*
-* Convert the blocksize advertised to the initiator to the 512 byte
-* units unconditionally used by the Linux block layer.
-*/
-   if (dev->dev_attrib.block_size == 4096)
-   block_lba = (cmd->t_task_lba << 3);
-   else if (dev->dev_attrib.block_size == 2048)
-   block_lba = (cmd->t_task_lba << 2);
-   else if (dev->dev_attrib.block_size == 1024)
-   block_lba = (cmd->t_task_lba << 1);
-   else if (dev->dev_attrib.block_size == 512)
-   block_lba = cmd->t_task_lba;
-   else {
-   pr_err("Unsupported SCSI -> BLOCK LBA conversion:"
-   " %u\n", dev->dev_attrib.block_size);
-   return TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE;
-   }
+   block_lba = cmd->t_task_lba << iblock_get_lba_shift(cmd);
 
ibr = kzalloc(sizeof(struct iblock_req), GFP_KERNEL);
if (!ibr)
@@ -841,6 +891,7 @@ static struct sbc_ops iblock_sbc_ops = {
.execute_write_same = iblock_execute_write_same,
.execute_write_same_unmap = iblock_execute_write_same_unmap,
.execute_unmap  = iblock_execute_unmap,
+   .execute_compare_and_write = iblock_execute_compare_and_write,
 };
 
 static sense_reason_t
-- 
1.7.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 0/2] iscsi patches for 3.18

2014-09-29 Thread michaelc
A couple patches made over the scsi-queue drivers-for-3.18 branch.
They just fix a possible bug with be2iscsi that Dan reported and
also export the iscsi port being used.

--
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 1/2] be2iscsi: check ip buffer before copying

2014-09-29 Thread michaelc
From: Mike Christie 

Dan Carpenter found a issue where be2iscsi would copy the ip
from userspace to the driver buffer before checking the len
of the data being copied:
http://marc.info/?l=linux-scsi&m=140982651504251&w=2

This patch just has us only copy what we the driver buffer
can support.

Tested-by: John Soni Jose 
Signed-off-by: Mike Christie 

---
 drivers/scsi/be2iscsi/be_mgmt.c |   13 -
 1 files changed, 8 insertions(+), 5 deletions(-)

diff --git a/drivers/scsi/be2iscsi/be_mgmt.c b/drivers/scsi/be2iscsi/be_mgmt.c
index 8478506..681d4e8 100644
--- a/drivers/scsi/be2iscsi/be_mgmt.c
+++ b/drivers/scsi/be2iscsi/be_mgmt.c
@@ -943,17 +943,20 @@ mgmt_static_ip_modify(struct beiscsi_hba *phba,
 
if (ip_action == IP_ACTION_ADD) {
memcpy(req->ip_params.ip_record.ip_addr.addr, ip_param->value,
-  ip_param->len);
+  sizeof(req->ip_params.ip_record.ip_addr.addr));
 
if (subnet_param)
memcpy(req->ip_params.ip_record.ip_addr.subnet_mask,
-  subnet_param->value, subnet_param->len);
+  subnet_param->value,
+  
sizeof(req->ip_params.ip_record.ip_addr.subnet_mask));
} else {
memcpy(req->ip_params.ip_record.ip_addr.addr,
-  if_info->ip_addr.addr, ip_param->len);
+  if_info->ip_addr.addr,
+  sizeof(req->ip_params.ip_record.ip_addr.addr));
 
memcpy(req->ip_params.ip_record.ip_addr.subnet_mask,
-  if_info->ip_addr.subnet_mask, ip_param->len);
+  if_info->ip_addr.subnet_mask,
+  sizeof(req->ip_params.ip_record.ip_addr.subnet_mask));
}
 
rc = mgmt_exec_nonemb_cmd(phba, &nonemb_cmd, NULL, 0);
@@ -981,7 +984,7 @@ static int mgmt_modify_gateway(struct beiscsi_hba *phba, 
uint8_t *gt_addr,
req->action = gtway_action;
req->ip_addr.ip_type = BE2_IPV4;
 
-   memcpy(req->ip_addr.addr, gt_addr, param_len);
+   memcpy(req->ip_addr.addr, gt_addr, sizeof(req->ip_addr.addr));
 
return mgmt_exec_nonemb_cmd(phba, &nonemb_cmd, NULL, 0);
 }
-- 
1.7.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 2/2] iscsi_tcp: export port being used

2014-09-29 Thread michaelc
From: Mike Christie 

This just has iscsi_tcp support ISCSI_PARAM_LOCAL_PORT which
exports the local port being used by the iscsi connection.

Signed-off-by: Mike Christie 
---
 drivers/scsi/iscsi_tcp.c |   10 --
 drivers/scsi/libiscsi.c  |1 +
 2 files changed, 9 insertions(+), 2 deletions(-)

diff --git a/drivers/scsi/iscsi_tcp.c b/drivers/scsi/iscsi_tcp.c
index a669f2d..427af0f 100644
--- a/drivers/scsi/iscsi_tcp.c
+++ b/drivers/scsi/iscsi_tcp.c
@@ -726,13 +726,18 @@ static int iscsi_sw_tcp_conn_get_param(struct 
iscsi_cls_conn *cls_conn,
switch(param) {
case ISCSI_PARAM_CONN_PORT:
case ISCSI_PARAM_CONN_ADDRESS:
+   case ISCSI_PARAM_LOCAL_PORT:
spin_lock_bh(&conn->session->frwd_lock);
if (!tcp_sw_conn || !tcp_sw_conn->sock) {
spin_unlock_bh(&conn->session->frwd_lock);
return -ENOTCONN;
}
-   rc = kernel_getpeername(tcp_sw_conn->sock,
-   (struct sockaddr *)&addr, &len);
+   if (param == ISCSI_PARAM_LOCAL_PORT)
+   rc = kernel_getsockname(tcp_sw_conn->sock,
+   (struct sockaddr *)&addr, &len);
+   else
+   rc = kernel_getpeername(tcp_sw_conn->sock,
+   (struct sockaddr *)&addr, &len);
spin_unlock_bh(&conn->session->frwd_lock);
if (rc)
return rc;
@@ -895,6 +900,7 @@ static umode_t iscsi_sw_tcp_attr_is_visible(int param_type, 
int param)
case ISCSI_PARAM_DATADGST_EN:
case ISCSI_PARAM_CONN_ADDRESS:
case ISCSI_PARAM_CONN_PORT:
+   case ISCSI_PARAM_LOCAL_PORT:
case ISCSI_PARAM_EXP_STATSN:
case ISCSI_PARAM_PERSISTENT_ADDRESS:
case ISCSI_PARAM_PERSISTENT_PORT:
diff --git a/drivers/scsi/libiscsi.c b/drivers/scsi/libiscsi.c
index 191b597..0d8bc6c 100644
--- a/drivers/scsi/libiscsi.c
+++ b/drivers/scsi/libiscsi.c
@@ -3505,6 +3505,7 @@ int iscsi_conn_get_addr_param(struct sockaddr_storage 
*addr,
len = sprintf(buf, "%pI6\n", &sin6->sin6_addr);
break;
case ISCSI_PARAM_CONN_PORT:
+   case ISCSI_PARAM_LOCAL_PORT:
if (sin)
len = sprintf(buf, "%hu\n", be16_to_cpu(sin->sin_port));
else
-- 
1.7.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 1/1] libiscsi: fix potential buffer overrun in __iscsi_conn_send_pdu

2014-09-02 Thread michaelc
From: Mike Christie 

This patches fixes a potential buffer overrun in __iscsi_conn_send_pdu.
This function is used by iscsi drivers and userspace to send iscsi PDUs/
commands. For login commands, we have a set buffer size. For all other
commands we do not support data buffers.

This was reported by Dan Carpenter here:
http://www.spinics.net/lists/linux-scsi/msg66838.html

Reported-by: Dan Carpenter 
Signed-off-by: Mike Christie 
---
 drivers/scsi/libiscsi.c |   10 ++
 1 files changed, 10 insertions(+), 0 deletions(-)

diff --git a/drivers/scsi/libiscsi.c b/drivers/scsi/libiscsi.c
index ea025e4..191b597 100644
--- a/drivers/scsi/libiscsi.c
+++ b/drivers/scsi/libiscsi.c
@@ -717,11 +717,21 @@ __iscsi_conn_send_pdu(struct iscsi_conn *conn, struct 
iscsi_hdr *hdr,
return NULL;
}
 
+   if (data_size > ISCSI_DEF_MAX_RECV_SEG_LEN) {
+   iscsi_conn_printk(KERN_ERR, conn, "Invalid buffer len 
of %u for login task. Max len is %u\n", data_size, ISCSI_DEF_MAX_RECV_SEG_LEN);
+   return NULL;
+   }
+
task = conn->login_task;
} else {
if (session->state != ISCSI_STATE_LOGGED_IN)
return NULL;
 
+   if (data_size != 0) {
+   iscsi_conn_printk(KERN_ERR, conn, "Can not send data 
buffer of len %u for op 0x%x\n", data_size, opcode);
+   return NULL;
+   }
+
BUG_ON(conn->c_stage == ISCSI_CONN_INITIAL_STAGE);
BUG_ON(conn->c_stage == ISCSI_CONN_STOPPED);
 
-- 
1.7.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 1/1] iscsi class: Fix freeing of skb in get host error path

2014-08-03 Thread michaelc
From: Mike Christie 

If get_host_stats failes we are using kfree to free the
skb. We should be using kfree_skb.

This patch was made over Christoph's scsi-queue drivers-for-3.17 branch.

Signed-off-by: Mike Christie 
---
 drivers/scsi/scsi_transport_iscsi.c |2 +-
 1 files changed, 1 insertions(+), 1 deletions(-)

diff --git a/drivers/scsi/scsi_transport_iscsi.c 
b/drivers/scsi/scsi_transport_iscsi.c
index 534d3fb..67d43e3 100644
--- a/drivers/scsi/scsi_transport_iscsi.c
+++ b/drivers/scsi/scsi_transport_iscsi.c
@@ -3468,7 +3468,7 @@ iscsi_get_host_stats(struct iscsi_transport *transport, 
struct nlmsghdr *nlh)
 
err = transport->get_host_stats(shost, buf, host_stats_size);
if (err) {
-   kfree(skbhost_stats);
+   kfree_skb(skbhost_stats);
goto exit_host_stats;
}
 
-- 
1.7.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 3/4] iscsi class: fix get_host_stats return code when not supported

2014-07-12 Thread michaelc
From: Mike Christie 

When the get_host_stats call was not supported we were
returing EINVAL. This has us return ENOSYS, because for
software iscsi drivers where there is no host it is ok to not
have this callout.

Signed-off-by: Mike Christie 
---
 drivers/scsi/scsi_transport_iscsi.c |2 +-
 1 files changed, 1 insertions(+), 1 deletions(-)

diff --git a/drivers/scsi/scsi_transport_iscsi.c 
b/drivers/scsi/scsi_transport_iscsi.c
index 14bfa53..534d3fb 100644
--- a/drivers/scsi/scsi_transport_iscsi.c
+++ b/drivers/scsi/scsi_transport_iscsi.c
@@ -3429,7 +3429,7 @@ iscsi_get_host_stats(struct iscsi_transport *transport, 
struct nlmsghdr *nlh)
char *buf;
 
if (!transport->get_host_stats)
-   return -EINVAL;
+   return -ENOSYS;
 
priv = iscsi_if_transport_lookup(transport);
if (!priv)
-- 
1.7.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 4/4] libiscsi: return new error code when nop times out

2014-07-12 Thread michaelc
From: Mike Christie 

When a iscsi nop as ping timedout we were failing with the
common connection error code, ISCSI_ERR_CONN_FAILED. This
patch adds a new error code for this problem so can properly
track/distinguish in userspace.

Signed-off-by: Mike Christie 
---
 drivers/scsi/libiscsi.c |2 +-
 include/scsi/iscsi_if.h |1 +
 2 files changed, 2 insertions(+), 1 deletions(-)

diff --git a/drivers/scsi/libiscsi.c b/drivers/scsi/libiscsi.c
index f2db82b..b0813fd 100644
--- a/drivers/scsi/libiscsi.c
+++ b/drivers/scsi/libiscsi.c
@@ -2097,7 +2097,7 @@ static void iscsi_check_transport_timeouts(unsigned long 
data)
  conn->ping_timeout, conn->recv_timeout,
  last_recv, conn->last_ping, jiffies);
spin_unlock(&session->frwd_lock);
-   iscsi_conn_failure(conn, ISCSI_ERR_CONN_FAILED);
+   iscsi_conn_failure(conn, ISCSI_ERR_NOP_TIMEDOUT);
return;
}
 
diff --git a/include/scsi/iscsi_if.h b/include/scsi/iscsi_if.h
index fd0421c..95ed942 100644
--- a/include/scsi/iscsi_if.h
+++ b/include/scsi/iscsi_if.h
@@ -527,6 +527,7 @@ enum iscsi_err {
ISCSI_ERR_XMIT_FAILED   = ISCSI_ERR_BASE + 19,
ISCSI_ERR_TCP_CONN_CLOSE= ISCSI_ERR_BASE + 20,
ISCSI_ERR_SCSI_EH_SESSION_RST   = ISCSI_ERR_BASE + 21,
+   ISCSI_ERR_NOP_TIMEDOUT  = ISCSI_ERR_BASE + 22,
 };
 
 /*
-- 
1.7.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 1/4] iscsi class: fix get_host_stats error handling

2014-07-12 Thread michaelc
From: Mike Christie 

iscsi_get_host_stats was dropping the error code returned
by drivers like qla4xxx.

Signed-off-by: Mike Christie 
---
 drivers/scsi/scsi_transport_iscsi.c |4 
 1 files changed, 4 insertions(+), 0 deletions(-)

diff --git a/drivers/scsi/scsi_transport_iscsi.c 
b/drivers/scsi/scsi_transport_iscsi.c
index b481e62..14bfa53 100644
--- a/drivers/scsi/scsi_transport_iscsi.c
+++ b/drivers/scsi/scsi_transport_iscsi.c
@@ -3467,6 +3467,10 @@ iscsi_get_host_stats(struct iscsi_transport *transport, 
struct nlmsghdr *nlh)
memset(buf, 0, host_stats_size);
 
err = transport->get_host_stats(shost, buf, host_stats_size);
+   if (err) {
+   kfree(skbhost_stats);
+   goto exit_host_stats;
+   }
 
actual_size = nlmsg_total_size(sizeof(*ev) + host_stats_size);
skb_trim(skbhost_stats, NLMSG_ALIGN(actual_size));
-- 
1.7.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 2/4] qla4xxx: fix get_host_stats error propagation

2014-07-12 Thread michaelc
From: Mike Christie 

qla4xxx was not always returning -EXYZ error codes when
qla4xxx_get_host_stats failed.

Signed-off-by: Mike Christie 
Acked-by: Vikas Chaudhary 

---
 drivers/scsi/qla4xxx/ql4_os.c |2 ++
 1 files changed, 2 insertions(+), 0 deletions(-)

diff --git a/drivers/scsi/qla4xxx/ql4_os.c b/drivers/scsi/qla4xxx/ql4_os.c
index c5d9564..b79b48c 100644
--- a/drivers/scsi/qla4xxx/ql4_os.c
+++ b/drivers/scsi/qla4xxx/ql4_os.c
@@ -1050,6 +1050,7 @@ static int qla4xxx_get_host_stats(struct Scsi_Host 
*shost, char *buf, int len)
if (!ql_iscsi_stats) {
ql4_printk(KERN_ERR, ha,
   "Unable to allocate memory for iscsi stats\n");
+   ret = -ENOMEM;
goto exit_host_stats;
}
 
@@ -1058,6 +1059,7 @@ static int qla4xxx_get_host_stats(struct Scsi_Host 
*shost, char *buf, int len)
if (ret != QLA_SUCCESS) {
ql4_printk(KERN_ERR, ha,
   "Unable to retrieve iscsi stats\n");
+   ret = -EIO;
goto exit_host_stats;
}
host_stats->mactx_frames = le64_to_cpu(ql_iscsi_stats->mac_tx_frames);
-- 
1.7.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 0/4] iscsi: iscsi changes for 3.17

2014-07-12 Thread michaelc
The following patches were made over Chrisoph's scsi-queue drivers-for-3.17
branch. They are some fixes to the get_host_stats code and new error code
for when a iscsi ping times out.

Note for applying/merging:

The patches also apply over James's scsi misc branch, but that branch
is missing some patches that Chrisoph has picked up.

--
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 2/2] bnx2i, be2iscsi: fix custom stats length

2014-07-01 Thread michaelc
From: Mike Christie 

The custom stats is an array with custom_length indicating the length
of the array. This patch fixes bnx2i and be2iscsi's setting of the
custom stats length. They both just have the one, eh_abort_cnt, so that should
be in the first entry of the custom array and custom_length should then
be one.

Reported-by: Rickard Strandqvist 
Signed-off-by: Mike Christie 
Acked-by: Eddie Wai 

---
 drivers/scsi/be2iscsi/be_iscsi.c |2 +-
 drivers/scsi/bnx2i/bnx2i_iscsi.c |7 +++
 2 files changed, 4 insertions(+), 5 deletions(-)

diff --git a/drivers/scsi/be2iscsi/be_iscsi.c b/drivers/scsi/be2iscsi/be_iscsi.c
index fd284ff..8616281 100644
--- a/drivers/scsi/be2iscsi/be_iscsi.c
+++ b/drivers/scsi/be2iscsi/be_iscsi.c
@@ -914,7 +914,7 @@ void beiscsi_conn_get_stats(struct iscsi_cls_conn *cls_conn,
stats->r2t_pdus = conn->r2t_pdus_cnt;
stats->digest_err = 0;
stats->timeout_err = 0;
-   stats->custom_length = 0;
+   stats->custom_length = 1;
strcpy(stats->custom[0].desc, "eh_abort_cnt");
stats->custom[0].value = conn->eh_abort_cnt;
 }
diff --git a/drivers/scsi/bnx2i/bnx2i_iscsi.c b/drivers/scsi/bnx2i/bnx2i_iscsi.c
index 166543f..9bd9b81 100644
--- a/drivers/scsi/bnx2i/bnx2i_iscsi.c
+++ b/drivers/scsi/bnx2i/bnx2i_iscsi.c
@@ -1643,12 +1643,11 @@ static void bnx2i_conn_get_stats(struct iscsi_cls_conn 
*cls_conn,
stats->r2t_pdus = conn->r2t_pdus_cnt;
stats->tmfcmd_pdus = conn->tmfcmd_pdus_cnt;
stats->tmfrsp_pdus = conn->tmfrsp_pdus_cnt;
-   stats->custom_length = 3;
-   strcpy(stats->custom[2].desc, "eh_abort_cnt");
-   stats->custom[2].value = conn->eh_abort_cnt;
stats->digest_err = 0;
stats->timeout_err = 0;
-   stats->custom_length = 0;
+   strcpy(stats->custom[0].desc, "eh_abort_cnt");
+   stats->custom[0].value = conn->eh_abort_cnt;
+   stats->custom_length = 1;
 }
 
 
-- 
1.7.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 1/2] iscsi: kill redundant casts

2014-07-01 Thread michaelc
From: Nick Black' via open-iscsi 

Remove two redundant casts from char * to char *.

Signed-off-by: Nick Black 
Signed-off-by: Mike Christie 
---
 drivers/scsi/scsi_transport_iscsi.c |4 ++--
 1 files changed, 2 insertions(+), 2 deletions(-)

diff --git a/drivers/scsi/scsi_transport_iscsi.c 
b/drivers/scsi/scsi_transport_iscsi.c
index 126bf26..b481e62 100644
--- a/drivers/scsi/scsi_transport_iscsi.c
+++ b/drivers/scsi/scsi_transport_iscsi.c
@@ -3059,7 +3059,7 @@ iscsi_get_chap(struct iscsi_transport *transport, struct 
nlmsghdr *nlh)
evchap->u.get_chap.host_no = ev->u.get_chap.host_no;
evchap->u.get_chap.chap_tbl_idx = ev->u.get_chap.chap_tbl_idx;
evchap->u.get_chap.num_entries = ev->u.get_chap.num_entries;
-   buf = (char *) ((char *)evchap + sizeof(*evchap));
+   buf = (char *)evchap + sizeof(*evchap);
memset(buf, 0, chap_buf_size);
 
err = transport->get_chap(shost, ev->u.get_chap.chap_tbl_idx,
@@ -3463,7 +3463,7 @@ iscsi_get_host_stats(struct iscsi_transport *transport, 
struct nlmsghdr *nlh)
evhost_stats->type = nlh->nlmsg_type;
evhost_stats->u.get_host_stats.host_no =
ev->u.get_host_stats.host_no;
-   buf = (char *)((char *)evhost_stats + sizeof(*evhost_stats));
+   buf = (char *)evhost_stats + sizeof(*evhost_stats);
memset(buf, 0, host_stats_size);
 
err = transport->get_host_stats(shost, buf, host_stats_size);
-- 
1.7.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 0/2] iscsi changes for 3.17

2014-07-01 Thread michaelc
This patchset has iscsi changes built over Christoph's scsi-queue
for-3.17 branch. The patches also apply to James's misc tree. They are
not critical bug fixes, so they are best for 3.17 feature window.


--
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 5/6] iscsi_boot_sysfs: Fix a memory leak in iscsi_boot_destroy_kset()

2014-02-06 Thread michaelc
From: Ethan Zhao 

Load and unload iscsi_ibft module will cause kernel memory leak, fix it
in scsi/iscsi_boot_sysfs.c iscsi_boot_destroy_kset().

Signed-off-by: Ethan Zhao 
Signed-off-by: Mike Christie 
---
 drivers/scsi/iscsi_boot_sysfs.c |1 +
 1 files changed, 1 insertions(+), 0 deletions(-)

diff --git a/drivers/scsi/iscsi_boot_sysfs.c b/drivers/scsi/iscsi_boot_sysfs.c
index 14c1c8f..680bf6f 100644
--- a/drivers/scsi/iscsi_boot_sysfs.c
+++ b/drivers/scsi/iscsi_boot_sysfs.c
@@ -490,5 +490,6 @@ void iscsi_boot_destroy_kset(struct iscsi_boot_kset 
*boot_kset)
iscsi_boot_remove_kobj(boot_kobj);
 
kset_unregister(boot_kset->kset);
+   kfree(boot_kset);
 }
 EXPORT_SYMBOL_GPL(iscsi_boot_destroy_kset);
-- 
1.7.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 4/6] be2iscsi: fix lun test in device reset callout

2014-02-06 Thread michaelc
From: Mike Christie 

We want to be checking the scsi_cmnd's lun against
the possible tasks in the driver. Current check tests
task against itself which was useless.

Signed-off-by: Mike Christie 
---
 drivers/scsi/be2iscsi/be_main.c |2 +-
 1 files changed, 1 insertions(+), 1 deletions(-)

diff --git a/drivers/scsi/be2iscsi/be_main.c b/drivers/scsi/be2iscsi/be_main.c
index 8d82f2c..bc77a6f 100644
--- a/drivers/scsi/be2iscsi/be_main.c
+++ b/drivers/scsi/be2iscsi/be_main.c
@@ -325,7 +325,7 @@ static int beiscsi_eh_device_reset(struct scsi_cmnd *sc)
if (!abrt_task->sc || abrt_task->state == ISCSI_TASK_FREE)
continue;
 
-   if (abrt_task->sc->device->lun != abrt_task->sc->device->lun)
+   if (sc->device->lun != abrt_task->sc->device->lun)
continue;
 
/* Invalidate WRB Posted for this Task */
-- 
1.7.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 1/6] SCSI/libiscsi: Restructure iscsi_tcp r2t response logic

2014-02-06 Thread michaelc
From: Shlomo Pongratz 

Restructure the iscsi_tcp_r2t_rsp routine in order to avoid allocating
r2t from r2tpool.queue and returning it back in case the parameters
rhdr->data_length and or rhdr->data_offset prohibit the requing.

Since the values of these parameters are known prior to the allocation,
we can pre-check and thus avoid futile allocations.

Signed-off-by: Shlomo Pongratz 
Signed-off-by: Or Gerlitz 
Signed-off-by: Mike Christie 
---
 drivers/scsi/libiscsi_tcp.c |   43 ++-
 1 files changed, 22 insertions(+), 21 deletions(-)

diff --git a/drivers/scsi/libiscsi_tcp.c b/drivers/scsi/libiscsi_tcp.c
index 1d58d53..7f59073 100644
--- a/drivers/scsi/libiscsi_tcp.c
+++ b/drivers/scsi/libiscsi_tcp.c
@@ -529,6 +529,8 @@ static int iscsi_tcp_r2t_rsp(struct iscsi_conn *conn, 
struct iscsi_task *task)
struct iscsi_r2t_rsp *rhdr = (struct iscsi_r2t_rsp *)tcp_conn->in.hdr;
struct iscsi_r2t_info *r2t;
int r2tsn = be32_to_cpu(rhdr->r2tsn);
+   u32 data_length;
+   u32 data_offset;
int rc;
 
if (tcp_conn->in.datalen) {
@@ -554,40 +556,39 @@ static int iscsi_tcp_r2t_rsp(struct iscsi_conn *conn, 
struct iscsi_task *task)
return 0;
}
 
-   rc = kfifo_out(&tcp_task->r2tpool.queue, (void*)&r2t, sizeof(void*));
-   if (!rc) {
-   iscsi_conn_printk(KERN_ERR, conn, "Could not allocate R2T. "
- "Target has sent more R2Ts than it "
- "negotiated for or driver has leaked.\n");
-   return ISCSI_ERR_PROTO;
-   }
-
-   r2t->exp_statsn = rhdr->statsn;
-   r2t->data_length = be32_to_cpu(rhdr->data_length);
-   if (r2t->data_length == 0) {
+   data_length = be32_to_cpu(rhdr->data_length);
+   if (data_length == 0) {
iscsi_conn_printk(KERN_ERR, conn,
  "invalid R2T with zero data len\n");
-   kfifo_in(&tcp_task->r2tpool.queue, (void*)&r2t,
-   sizeof(void*));
return ISCSI_ERR_DATALEN;
}
 
-   if (r2t->data_length > session->max_burst)
+   if (data_length > session->max_burst)
ISCSI_DBG_TCP(conn, "invalid R2T with data len %u and max "
  "burst %u. Attempting to execute request.\n",
- r2t->data_length, session->max_burst);
+ data_length, session->max_burst);
 
-   r2t->data_offset = be32_to_cpu(rhdr->data_offset);
-   if (r2t->data_offset + r2t->data_length > scsi_out(task->sc)->length) {
+   data_offset = be32_to_cpu(rhdr->data_offset);
+   if (data_offset + data_length > scsi_out(task->sc)->length) {
iscsi_conn_printk(KERN_ERR, conn,
  "invalid R2T with data len %u at offset %u "
- "and total length %d\n", r2t->data_length,
- r2t->data_offset, scsi_out(task->sc)->length);
-   kfifo_in(&tcp_task->r2tpool.queue, (void*)&r2t,
-   sizeof(void*));
+ "and total length %d\n", data_length,
+ data_offset, scsi_out(task->sc)->length);
return ISCSI_ERR_DATALEN;
}
 
+   rc = kfifo_out(&tcp_task->r2tpool.queue, (void*)&r2t, sizeof(void*));
+   if (!rc) {
+   iscsi_conn_printk(KERN_ERR, conn, "Could not allocate R2T. "
+ "Target has sent more R2Ts than it "
+ "negotiated for or driver has leaked.\n");
+   return ISCSI_ERR_PROTO;
+   }
+
+   r2t->exp_statsn = rhdr->statsn;
+   r2t->data_length = data_length;
+   r2t->data_offset = data_offset;
+
r2t->ttt = rhdr->ttt; /* no flip */
r2t->datasn = 0;
r2t->sent = 0;
-- 
1.7.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 3/6] libiscsi: remove unneeded queue work when max_cmdsn is increased

2014-02-06 Thread michaelc
From: Mike Christie 

iscsi_queuecommand will only take in commands that can fit in the
current window. So, if a command is on the cmdqueue then it can
fit in the current window. If a command is on the mgmtqueue, then
we are setting the immediate bit so they will also fit in the
window. As a result, we never need to to do a iscsi_conn_queue_work
when the maxCmdSn is increased.

What should happen is that a command will complete the window will
be increased, then the scsi layer will send us more commands by
running the scsi_device queues.

Signed-off-by: Mike Christie 
---
 drivers/scsi/libiscsi.c |   10 +-
 1 files changed, 1 insertions(+), 9 deletions(-)

diff --git a/drivers/scsi/libiscsi.c b/drivers/scsi/libiscsi.c
index 6afb6fc..9ca42a2 100644
--- a/drivers/scsi/libiscsi.c
+++ b/drivers/scsi/libiscsi.c
@@ -110,16 +110,8 @@ static void __iscsi_update_cmdsn(struct iscsi_session 
*session,
session->exp_cmdsn = exp_cmdsn;
 
if (max_cmdsn != session->max_cmdsn &&
-   !iscsi_sna_lt(max_cmdsn, session->max_cmdsn)) {
+   !iscsi_sna_lt(max_cmdsn, session->max_cmdsn))
session->max_cmdsn = max_cmdsn;
-   /*
-* if the window closed with IO queued, then kick the
-* xmit thread
-*/
-   if (!list_empty(&session->leadconn->cmdqueue) ||
-   !list_empty(&session->leadconn->mgmtqueue))
-   iscsi_conn_queue_work(session->leadconn);
-   }
 }
 
 void iscsi_update_cmdsn(struct iscsi_session *session, struct iscsi_nopin *hdr)
-- 
1.7.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 2/6] SCSI/libiscsi: Reduce locking contention in fast path (v2)

2014-02-06 Thread michaelc
From: Shlomo Pongratz 

Replace the session lock with two locks, a forward lock and
a backwards lock named frwd_lock and back_lock respectively.

The forward lock protects resources that change while sending a
request to the target, such as cmdsn, queued_cmdsn, and allocating
task from the commands' pool with kfifo_out.

The backward lock protects resources that change while processing
a response or in error path, such as cmdsn_exp, cmdsn_max, and
returning tasks to the commands' pool with kfifo_in.

Under a steady state fast-path situation, that is when one
or more processes/threads submit IO to an iscsi device and
a single kernel upcall (e.g softirq) is dealing with processing
of responses without errors, this patch eliminates the contention
between the queuecommand()/request response/scsi_done() flows
associated with iscsi sessions.

Between the forward and the backward locks exists a strict locking
hierarchy. The mutual exclusion zone protected by the forward lock can
enclose the mutual exclusion zone protected by the backward lock but not
vice versa.

For example, in iscsi_conn_teardown or in iscsi_xmit_data when there is
a failure and __iscsi_put_task is called, the backward lock is taken while
the forward lock is still taken. On the other hand, if in the RX path a nop
is to be sent, for example in iscsi_handle_reject or __iscsi_complete_pdu
than the forward lock is released and the backward lock is taken for the
duration of iscsi_send_nopout, later the backward lock is released and the
forward lock is retaken.

libiscsi_tcp uses two kernel fifos the r2t pool and the r2t queue.

The insertion and deletion from these queues didn't corespond to the
assumption taken by the new forward/backwards session locking paradigm.

That is, in iscsi_tcp_clenup_task which belongs to the RX (backwards)
path, r2t is taken out from r2t queue and inserted to the r2t pool.
In iscsi_tcp_get_curr_r2t which belong to the TX (forward) path, r2t
is also inserted to the r2t pool and another r2t is pulled from r2t
queue.

Only in iscsi_tcp_r2t_rsp which is called in the RX path but can requeue
to the TX path, r2t is taken from the r2t pool and inserted to the r2t
queue.

In order to cope with this situation, two spin locks were added,
pool2queue and queue2pool. The former protects extracting from the
r2t pool and inserting to the r2t queue, and the later protects the
extracing from the r2t queue and inserting to the r2t pool.

Signed-off-by: Shlomo Pongratz 
Signed-off-by: Or Gerlitz 
[minor fix up to apply cleanly and compile fix]
Signed-off-by: Mike Christie 
---
 drivers/scsi/be2iscsi/be_main.c  |   26 +++---
 drivers/scsi/bnx2i/bnx2i_hwi.c   |   46 
 drivers/scsi/bnx2i/bnx2i_iscsi.c |8 +-
 drivers/scsi/iscsi_tcp.c |   22 ++--
 drivers/scsi/libiscsi.c  |  214 +
 drivers/scsi/libiscsi_tcp.c  |   28 +++--
 drivers/scsi/qla4xxx/ql4_isr.c   |4 +-
 include/scsi/libiscsi.h  |   17 ++-
 include/scsi/libiscsi_tcp.h  |2 +
 9 files changed, 206 insertions(+), 161 deletions(-)

diff --git a/drivers/scsi/be2iscsi/be_main.c b/drivers/scsi/be2iscsi/be_main.c
index 1f37505..8d82f2c 100644
--- a/drivers/scsi/be2iscsi/be_main.c
+++ b/drivers/scsi/be2iscsi/be_main.c
@@ -232,20 +232,20 @@ static int beiscsi_eh_abort(struct scsi_cmnd *sc)
cls_session = starget_to_session(scsi_target(sc->device));
session = cls_session->dd_data;
 
-   spin_lock_bh(&session->lock);
+   spin_lock_bh(&session->frwd_lock);
if (!aborted_task || !aborted_task->sc) {
/* we raced */
-   spin_unlock_bh(&session->lock);
+   spin_unlock_bh(&session->frwd_lock);
return SUCCESS;
}
 
aborted_io_task = aborted_task->dd_data;
if (!aborted_io_task->scsi_cmnd) {
/* raced or invalid command */
-   spin_unlock_bh(&session->lock);
+   spin_unlock_bh(&session->frwd_lock);
return SUCCESS;
}
-   spin_unlock_bh(&session->lock);
+   spin_unlock_bh(&session->frwd_lock);
/* Invalidate WRB Posted for this Task */
AMAP_SET_BITS(struct amap_iscsi_wrb, invld,
  aborted_io_task->pwrb_handle->pwrb,
@@ -307,9 +307,9 @@ static int beiscsi_eh_device_reset(struct scsi_cmnd *sc)
/* invalidate iocbs */
cls_session = starget_to_session(scsi_target(sc->device));
session = cls_session->dd_data;
-   spin_lock_bh(&session->lock);
+   spin_lock_bh(&session->frwd_lock);
if (!session->leadconn || session->state != ISCSI_STATE_LOGGED_IN) {
-   spin_unlock_bh(&session->lock);
+   spin_unlock_bh(&session->frwd_lock);
return FAILED;
}
conn = session->leadconn;
@@ -338,7 +338,7 @@ static int beiscsi_eh_device_reset(struct scsi_cmnd *sc)
num_invalidate++;
inv_tbl++;
}
-   sp

[PATCH 0/6]: iscsi changes for scsi-misc (v2)

2014-02-06 Thread michaelc
This patchset has Mellanox's libiscsi locking changes, and various
fixes.

V2 - Fix for MaxCmdSn handling in patch 3/6 where the part of the function
that also updates the MaxCmdSn also got cut by accident.

--
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 6/6] iscsi_tcp: check for valid session before accessing

2014-02-06 Thread michaelc
From: Mike Christie 

Check that the session is setup before accessing its
connection. This fixes a oops where userspace tries
to get the ip address before the session is bound to
a host.

Signed-off-by: Mike Christie 
---
 drivers/scsi/iscsi_tcp.c |3 +++
 1 files changed, 3 insertions(+), 0 deletions(-)

diff --git a/drivers/scsi/iscsi_tcp.c b/drivers/scsi/iscsi_tcp.c
index 12b3512..bfb6d07 100644
--- a/drivers/scsi/iscsi_tcp.c
+++ b/drivers/scsi/iscsi_tcp.c
@@ -759,6 +759,9 @@ static int iscsi_sw_tcp_host_get_param(struct Scsi_Host 
*shost,
 
switch (param) {
case ISCSI_HOST_PARAM_IPADDRESS:
+   if (!session)
+   return -ENOTCONN;
+
spin_lock_bh(&session->frwd_lock);
conn = session->leadconn;
if (!conn) {
-- 
1.7.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 3/6] SCSI/libiscsi: Remove unneeded code

2013-12-20 Thread michaelc
From: Shlomo Pongratz 

We never will have a closed window and something on one of those lists.

Signed-off-by: Mike Christie 
Signed-off-by: Shlomo Pongratz 
---
 drivers/scsi/libiscsi.c |   12 
 1 files changed, 0 insertions(+), 12 deletions(-)

diff --git a/drivers/scsi/libiscsi.c b/drivers/scsi/libiscsi.c
index e77c41f..cc19cc2 100644
--- a/drivers/scsi/libiscsi.c
+++ b/drivers/scsi/libiscsi.c
@@ -108,18 +108,6 @@ static void __iscsi_update_cmdsn(struct iscsi_session 
*session,
if (exp_cmdsn != session->exp_cmdsn &&
!iscsi_sna_lt(exp_cmdsn, session->exp_cmdsn))
session->exp_cmdsn = exp_cmdsn;
-
-   if (max_cmdsn != session->max_cmdsn &&
-   !iscsi_sna_lt(max_cmdsn, session->max_cmdsn)) {
-   session->max_cmdsn = max_cmdsn;
-   /*
-* if the window closed with IO queued, then kick the
-* xmit thread
-*/
-   if (!list_empty(&session->leadconn->cmdqueue) ||
-   !list_empty(&session->leadconn->mgmtqueue))
-   iscsi_conn_queue_work(session->leadconn);
-   }
 }
 
 void iscsi_update_cmdsn(struct iscsi_session *session, struct iscsi_nopin *hdr)
-- 
1.7.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 4/6] be2iscsi: fix lun test in device reset callout

2013-12-20 Thread michaelc
From: Mike Christie 

We want to be checking the scsi_cmnd's lun against
the possible tasks in the driver. Current check tests
task against itself which was useless.

Signed-off-by: Mike Christie 
---
 drivers/scsi/be2iscsi/be_main.c |2 +-
 1 files changed, 1 insertions(+), 1 deletions(-)

diff --git a/drivers/scsi/be2iscsi/be_main.c b/drivers/scsi/be2iscsi/be_main.c
index 1fb16b1..3ffe8ca 100644
--- a/drivers/scsi/be2iscsi/be_main.c
+++ b/drivers/scsi/be2iscsi/be_main.c
@@ -325,7 +325,7 @@ static int beiscsi_eh_device_reset(struct scsi_cmnd *sc)
if (!abrt_task->sc || abrt_task->state == ISCSI_TASK_FREE)
continue;
 
-   if (abrt_task->sc->device->lun != abrt_task->sc->device->lun)
+   if (sc->device->lun != abrt_task->sc->device->lun)
continue;
 
/* Invalidate WRB Posted for this Task */
-- 
1.7.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 5/6] iscsi_boot_sysfs: Fix a memory leak in iscsi_boot_destroy_kset()

2013-12-20 Thread michaelc
From: Ethan Zhao 

Load and unload iscsi_ibft module will cause kernel memory leak, fix it
in scsi/iscsi_boot_sysfs.c iscsi_boot_destroy_kset().

Signed-off-by: Ethan Zhao 
Signed-off-by: Mike Christie 
---
 drivers/scsi/iscsi_boot_sysfs.c |1 +
 1 files changed, 1 insertions(+), 0 deletions(-)

diff --git a/drivers/scsi/iscsi_boot_sysfs.c b/drivers/scsi/iscsi_boot_sysfs.c
index 14c1c8f..680bf6f 100644
--- a/drivers/scsi/iscsi_boot_sysfs.c
+++ b/drivers/scsi/iscsi_boot_sysfs.c
@@ -490,5 +490,6 @@ void iscsi_boot_destroy_kset(struct iscsi_boot_kset 
*boot_kset)
iscsi_boot_remove_kobj(boot_kobj);
 
kset_unregister(boot_kset->kset);
+   kfree(boot_kset);
 }
 EXPORT_SYMBOL_GPL(iscsi_boot_destroy_kset);
-- 
1.7.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 6/6] iscsi_tcp: check for valid session before accessing

2013-12-20 Thread michaelc
From: Mike Christie 

Check that the session is setup before accessing its
connection. This fixes a oops where userspace tries
to get the ip address before the session is bound to
a host.

Signed-off-by: Mike Christie 
---
 drivers/scsi/iscsi_tcp.c |3 +++
 1 files changed, 3 insertions(+), 0 deletions(-)

diff --git a/drivers/scsi/iscsi_tcp.c b/drivers/scsi/iscsi_tcp.c
index 12b3512..bfb6d07 100644
--- a/drivers/scsi/iscsi_tcp.c
+++ b/drivers/scsi/iscsi_tcp.c
@@ -759,6 +759,9 @@ static int iscsi_sw_tcp_host_get_param(struct Scsi_Host 
*shost,
 
switch (param) {
case ISCSI_HOST_PARAM_IPADDRESS:
+   if (!session)
+   return -ENOTCONN;
+
spin_lock_bh(&session->frwd_lock);
conn = session->leadconn;
if (!conn) {
-- 
1.7.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 2/6] SCSI/libiscsi: Reduce locking contention in fast path

2013-12-20 Thread michaelc
From: Shlomo Pongratz 

Replace the session lock with two locks, a forward lock and
a backwards lock named frwd_lock and back_lock respectively.

The forward lock protects resources that change while sending a
request to the target, such as cmdsn, queued_cmdsn, and allocating
task from the commands' pool with kfifo_out.

The backward lock protects resources that change while processing
a response or in error path, such as cmdsn_exp, cmdsn_max, and
returning tasks to the commands' pool with kfifo_in.

Under a steady state fast-path situation, that is when one
or more processes/threads submit IO to an iscsi device and
a single kernel upcall (e.g softirq) is dealing with processing
of responses without errors, this patch eliminates the contention
between the queuecommand()/request response/scsi_done() flows
associated with iscsi sessions.

Between the forward and the backward locks exists a strict locking
hierarchy.
The mutual exclusion zone protected by the forward lock can enclose the
mutual exclusion zone protected by the backward lock but not vice versa.

For example, in iscsi_conn_teardown or in iscsi_xmit_data when there is
a
failure and __iscsi_put_task is called, the backward lock is taken while
the
forward lock is still taken. On the other hand, if in the RX path a nop
is
to be sent, for example in iscsi_handle_reject or __iscsi_complete_pdu
than
the forward lock is released and the backward lock is taken for the
duration
of iscsi_send_nopout, later the backward lock is released and the
forward
lock is retaken.

libiscsi_tcp uses two kernel fifos the r2t pool and the r2t queue.

The insertion and deletion from these queues didn't corespond to the
assumption taken by the new forward/backwards session locking paradigm.

That is, in iscsi_tcp_clenup_task which belongs to the RX (backwards)
path, r2t is taken out from r2t queue and inserted to the r2t pool.
In iscsi_tcp_get_curr_r2t which belong to the TX (forward) path, r2t
is also inserted to the r2t pool and another r2t is pulled from r2t
queue.

Only in iscsi_tcp_r2t_rsp which is called in the RX path but can requeue
to the TX path, r2t is taken from the r2t pool and inserted to the r2t
queue.

In order to cope with this situation, two spin locks were added,
pool2queue and queue2pool. The former protects extracting from the
r2t pool and inserting to the r2t queue, and the later protects the
extracing from the r2t queue and inserting to the r2t pool.

Signed-off-by: Shlomo Pongratz 
Signed-off-by: Or Gerlitz 
[minor fix up to apply cleanly]
Signed-off-by: Mike Christie 
---
 drivers/scsi/be2iscsi/be_main.c  |   26 +++---
 drivers/scsi/bnx2i/bnx2i_hwi.c   |   46 +-
 drivers/scsi/bnx2i/bnx2i_iscsi.c |8 +-
 drivers/scsi/iscsi_tcp.c |   22 ++--
 drivers/scsi/libiscsi.c  |  192 ++
 drivers/scsi/libiscsi_tcp.c  |   28 --
 drivers/scsi/qla4xxx/ql4_isr.c   |4 +-
 include/scsi/libiscsi.h  |   17 +++-
 include/scsi/libiscsi_tcp.h  |2 +
 9 files changed, 195 insertions(+), 150 deletions(-)

diff --git a/drivers/scsi/be2iscsi/be_main.c b/drivers/scsi/be2iscsi/be_main.c
index 1f37505..1fb16b1 100644
--- a/drivers/scsi/be2iscsi/be_main.c
+++ b/drivers/scsi/be2iscsi/be_main.c
@@ -232,20 +232,20 @@ static int beiscsi_eh_abort(struct scsi_cmnd *sc)
cls_session = starget_to_session(scsi_target(sc->device));
session = cls_session->dd_data;
 
-   spin_lock_bh(&session->lock);
+   spin_lock_bh(&session->frwd_lock);
if (!aborted_task || !aborted_task->sc) {
/* we raced */
-   spin_unlock_bh(&session->lock);
+   spin_unlock_bh(&session->fwrd_lock);
return SUCCESS;
}
 
aborted_io_task = aborted_task->dd_data;
if (!aborted_io_task->scsi_cmnd) {
/* raced or invalid command */
-   spin_unlock_bh(&session->lock);
+   spin_unlock_bh(&session->fwrd_lock);
return SUCCESS;
}
-   spin_unlock_bh(&session->lock);
+   spin_unlock_bh(&session->fwrd_lock);
/* Invalidate WRB Posted for this Task */
AMAP_SET_BITS(struct amap_iscsi_wrb, invld,
  aborted_io_task->pwrb_handle->pwrb,
@@ -307,9 +307,9 @@ static int beiscsi_eh_device_reset(struct scsi_cmnd *sc)
/* invalidate iocbs */
cls_session = starget_to_session(scsi_target(sc->device));
session = cls_session->dd_data;
-   spin_lock_bh(&session->lock);
+   spin_lock_bh(&session->frwd_lock);
if (!session->leadconn || session->state != ISCSI_STATE_LOGGED_IN) {
-   spin_unlock_bh(&session->lock);
+   spin_unlock_bh(&session->frwd_lock);
return FAILED;
}
conn = session->leadconn;
@@ -338,7 +338,7 @@ static int beiscsi_eh_device_reset(struct scsi_cmnd *sc)
num_invalidate++;
inv_tbl++;
}
-   spin_unlock_b

[PATCH 1/6] SCSI/libiscsi: Restructure iscsi_tcp r2t response logic

2013-12-20 Thread michaelc
From: Shlomo Pongratz 

Restructure the iscsi_tcp_r2t_rsp routine in order to avoid allocating
r2t from r2tpool.queue and returning it back in case the parameters
rhdr->data_length and or rhdr->data_offset prohibit the requing.

Since the values of these parameters are known prior to the allocation,
we can pre-check and thus avoid futile allocations.

Signed-off-by: Shlomo Pongratz 
Signed-off-by: Or Gerlitz 
Signed-off-by: Mike Christie 
---
 drivers/scsi/libiscsi_tcp.c |   43 ++-
 1 files changed, 22 insertions(+), 21 deletions(-)

diff --git a/drivers/scsi/libiscsi_tcp.c b/drivers/scsi/libiscsi_tcp.c
index 1d58d53..7f59073 100644
--- a/drivers/scsi/libiscsi_tcp.c
+++ b/drivers/scsi/libiscsi_tcp.c
@@ -529,6 +529,8 @@ static int iscsi_tcp_r2t_rsp(struct iscsi_conn *conn, 
struct iscsi_task *task)
struct iscsi_r2t_rsp *rhdr = (struct iscsi_r2t_rsp *)tcp_conn->in.hdr;
struct iscsi_r2t_info *r2t;
int r2tsn = be32_to_cpu(rhdr->r2tsn);
+   u32 data_length;
+   u32 data_offset;
int rc;
 
if (tcp_conn->in.datalen) {
@@ -554,40 +556,39 @@ static int iscsi_tcp_r2t_rsp(struct iscsi_conn *conn, 
struct iscsi_task *task)
return 0;
}
 
-   rc = kfifo_out(&tcp_task->r2tpool.queue, (void*)&r2t, sizeof(void*));
-   if (!rc) {
-   iscsi_conn_printk(KERN_ERR, conn, "Could not allocate R2T. "
- "Target has sent more R2Ts than it "
- "negotiated for or driver has leaked.\n");
-   return ISCSI_ERR_PROTO;
-   }
-
-   r2t->exp_statsn = rhdr->statsn;
-   r2t->data_length = be32_to_cpu(rhdr->data_length);
-   if (r2t->data_length == 0) {
+   data_length = be32_to_cpu(rhdr->data_length);
+   if (data_length == 0) {
iscsi_conn_printk(KERN_ERR, conn,
  "invalid R2T with zero data len\n");
-   kfifo_in(&tcp_task->r2tpool.queue, (void*)&r2t,
-   sizeof(void*));
return ISCSI_ERR_DATALEN;
}
 
-   if (r2t->data_length > session->max_burst)
+   if (data_length > session->max_burst)
ISCSI_DBG_TCP(conn, "invalid R2T with data len %u and max "
  "burst %u. Attempting to execute request.\n",
- r2t->data_length, session->max_burst);
+ data_length, session->max_burst);
 
-   r2t->data_offset = be32_to_cpu(rhdr->data_offset);
-   if (r2t->data_offset + r2t->data_length > scsi_out(task->sc)->length) {
+   data_offset = be32_to_cpu(rhdr->data_offset);
+   if (data_offset + data_length > scsi_out(task->sc)->length) {
iscsi_conn_printk(KERN_ERR, conn,
  "invalid R2T with data len %u at offset %u "
- "and total length %d\n", r2t->data_length,
- r2t->data_offset, scsi_out(task->sc)->length);
-   kfifo_in(&tcp_task->r2tpool.queue, (void*)&r2t,
-   sizeof(void*));
+ "and total length %d\n", data_length,
+ data_offset, scsi_out(task->sc)->length);
return ISCSI_ERR_DATALEN;
}
 
+   rc = kfifo_out(&tcp_task->r2tpool.queue, (void*)&r2t, sizeof(void*));
+   if (!rc) {
+   iscsi_conn_printk(KERN_ERR, conn, "Could not allocate R2T. "
+ "Target has sent more R2Ts than it "
+ "negotiated for or driver has leaked.\n");
+   return ISCSI_ERR_PROTO;
+   }
+
+   r2t->exp_statsn = rhdr->statsn;
+   r2t->data_length = data_length;
+   r2t->data_offset = data_offset;
+
r2t->ttt = rhdr->ttt; /* no flip */
r2t->datasn = 0;
r2t->sent = 0;
-- 
1.7.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 0/6] iscsi changes for scsi-misc

2013-12-20 Thread michaelc
The following patches are some features and fixes for scsi-misc.

James, if you were going to merge the libiscsi locking changes here
http://www.spinics.net/lists/linux-scsi/msg69903.html
do not bother. The qlogic patches that were just merged had a conflict.
The patches in the following emails should apply cleanly to misc.


--
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] block: free bios when failing blk_execute_rq_nowait calls

2013-09-18 Thread michaelc
From: Mike Christie 

If the queue is dying then we only call the rq->end_io callout.
This leaves bios setup on the request, because the caller assumes when
the blk_execute_rq_nowait/blk_execute_rq call has completed that
the rq->bios have been cleaned up.

This patch has blk_execute_rq_nowait use __blk_end_request_all
to free bios and also call rq->end_io.

Signed-off-by: Mike Christie 
---
 block/blk-exec.c |4 ++--
 1 files changed, 2 insertions(+), 2 deletions(-)

diff --git a/block/blk-exec.c b/block/blk-exec.c
index e706213..ae4f27d 100644
--- a/block/blk-exec.c
+++ b/block/blk-exec.c
@@ -68,9 +68,9 @@ void blk_execute_rq_nowait(struct request_queue *q, struct 
gendisk *bd_disk,
spin_lock_irq(q->queue_lock);
 
if (unlikely(blk_queue_dying(q))) {
+   rq->cmd_flags |= REQ_QUIET; 
rq->errors = -ENXIO;
-   if (rq->end_io)
-   rq->end_io(rq, rq->errors);
+   __blk_end_request_all(rq, rq->errors);
spin_unlock_irq(q->queue_lock);
return;
}
-- 
1.7.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 1/2] libiscsi: avoid unnecessary multiple NULL assignments

2013-04-10 Thread michaelc
From: Masatake YAMATO 

In iscsi_free_task, NULL is assigned to task->sc twice: before and
after kfifo_in invocatoin. Allocating and freeing iscsi_task are guarded
with session->lock, so multiple NULL assignments cause no trouble. But
people reading the source code may be confused.

The second NULL assignment comes from commit:

3e5c28ad0391389959ccae81c938c7533efb3490

It seems that the line after kfifo_in invocation was introduced
accidentally.

Signed-off-by: Masatake YAMATO 
Reviewed-by: Mike Christie 
Signed-off-by: Mike Christie 
---
 drivers/scsi/libiscsi.c |1 -
 1 files changed, 0 insertions(+), 1 deletions(-)

diff --git a/drivers/scsi/libiscsi.c b/drivers/scsi/libiscsi.c
index d5e5c44..5de9469 100644
--- a/drivers/scsi/libiscsi.c
+++ b/drivers/scsi/libiscsi.c
@@ -507,7 +507,6 @@ static void iscsi_free_task(struct iscsi_task *task)
kfifo_in(&session->cmdpool.queue, (void*)&task, sizeof(void*));
 
if (sc) {
-   task->sc = NULL;
/* SCSI eh reuses commands to verify us */
sc->SCp.ptr = NULL;
/*
-- 
1.7.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 2/2] iscsi_tcp: support PF_MEMALLOC/__GFP_MEMALLOC

2013-04-10 Thread michaelc
From: Mike Christie 

This patch has software iscsi use PF_MEMALLOC/__GFP_MEMALLOC
to be able to better support swap over iscsi disks similar to
what was added for nbd.

Signed-off-by: Mike Christie 
---
 drivers/scsi/iscsi_tcp.c |   18 +-
 1 files changed, 13 insertions(+), 5 deletions(-)

diff --git a/drivers/scsi/iscsi_tcp.c b/drivers/scsi/iscsi_tcp.c
index 1b91ca0..9e2588a 100644
--- a/drivers/scsi/iscsi_tcp.c
+++ b/drivers/scsi/iscsi_tcp.c
@@ -370,17 +370,24 @@ static inline int iscsi_sw_tcp_xmit_qlen(struct 
iscsi_conn *conn)
 static int iscsi_sw_tcp_pdu_xmit(struct iscsi_task *task)
 {
struct iscsi_conn *conn = task->conn;
-   int rc;
+   unsigned long pflags = current->flags;
+   int rc = 0;
+
+   current->flags |= PF_MEMALLOC;
 
while (iscsi_sw_tcp_xmit_qlen(conn)) {
rc = iscsi_sw_tcp_xmit(conn);
-   if (rc == 0)
-   return -EAGAIN;
+   if (rc == 0) {
+   rc = -EAGAIN;
+   break;
+   }
if (rc < 0)
-   return rc;
+   break;
+   rc = 0;
}
 
-   return 0;
+   tsk_restore_flags(current, pflags, PF_MEMALLOC);
+   return rc;
 }
 
 /*
@@ -665,6 +672,7 @@ iscsi_sw_tcp_conn_bind(struct iscsi_cls_session 
*cls_session,
sk->sk_reuse = SK_CAN_REUSE;
sk->sk_sndtimeo = 15 * HZ; /* FIXME: make it configurable */
sk->sk_allocation = GFP_ATOMIC;
+   sk_set_memalloc(sk);
 
iscsi_sw_tcp_conn_set_callbacks(conn);
tcp_sw_conn->sendpage = tcp_sw_conn->sock->ops->sendpage;
-- 
1.7.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 0/2] iscsi changes for scsi misc

2013-04-10 Thread michaelc
The following 2 patches are for the misc branch in the scsi tree.
They cleanup duplicated code from a previous patch and add
better support for swap over software iscsi by using the
PF_MEMALLOC/__GFP_MEMALLOC flags like what was recently added for
nbd.

--
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 1/1] scsi_dh_alua: fix stpg sense handling

2013-03-05 Thread michaelc
From: Mike Christie 

For the stpg_endio path we are not evaluating the sense. The bug
is that

1. The error value is set to -EIO when there is sense, so we hit the first
error check and always return SCSI_DH_IO.

2. h->senselen is set to zero in submit_stpg. It is not later set to
req->sense_len like in the synchrounous exection paths, so we must
check the req->sense_len field.

Signed-off-by: Mike Christie 
---
 drivers/scsi/device_handler/scsi_dh_alua.c |   10 ++
 1 files changed, 6 insertions(+), 4 deletions(-)

diff --git a/drivers/scsi/device_handler/scsi_dh_alua.c 
b/drivers/scsi/device_handler/scsi_dh_alua.c
index 6f4d8e6..6648ffb 100644
--- a/drivers/scsi/device_handler/scsi_dh_alua.c
+++ b/drivers/scsi/device_handler/scsi_dh_alua.c
@@ -232,13 +232,13 @@ static void stpg_endio(struct request *req, int error)
struct scsi_sense_hdr sense_hdr;
unsigned err = SCSI_DH_OK;
 
-   if (error || host_byte(req->errors) != DID_OK ||
-   msg_byte(req->errors) != COMMAND_COMPLETE) {
+   if (host_byte(req->errors) != DID_OK ||
+   msg_byte(req->errors) != COMMAND_COMPLETE) {
err = SCSI_DH_IO;
goto done;
}
 
-   if (h->senselen > 0) {
+   if (req->sense_len > 0) {
err = scsi_normalize_sense(h->sense, SCSI_SENSE_BUFFERSIZE,
   &sense_hdr);
if (!err) {
@@ -255,7 +255,9 @@ static void stpg_endio(struct request *req, int error)
ALUA_DH_NAME, sense_hdr.sense_key,
sense_hdr.asc, sense_hdr.ascq);
err = SCSI_DH_IO;
-   }
+   } else if (error)
+   err = SCSI_DH_IO;
+
if (err == SCSI_DH_OK) {
h->state = TPGS_STATE_OPTIMIZED;
sdev_printk(KERN_INFO, h->sdev,
-- 
1.7.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 1/1] iscsi regression: check for zero max session cmds

2008-02-26 Thread michaelc
From: Mike Christie <[EMAIL PROTECTED]>

The old tools did not set max session cmds. This is a regression.
I removed the check when merging the power of 2 patch.

Signed-off-by: Mike Christie <[EMAIL PROTECTED]>
---
 drivers/scsi/libiscsi.c |4 ++--
 drivers/scsi/scsi_transport_iscsi.c |2 +-
 2 files changed, 3 insertions(+), 3 deletions(-)

diff --git a/drivers/scsi/libiscsi.c b/drivers/scsi/libiscsi.c
index 59f8445..bdd7de7 100644
--- a/drivers/scsi/libiscsi.c
+++ b/drivers/scsi/libiscsi.c
@@ -1708,8 +1708,8 @@ iscsi_session_setup(struct iscsi_transport *iscsit,
qdepth = ISCSI_DEF_CMD_PER_LUN;
}
 
-   if (!is_power_of_2(cmds_max) ||
-   cmds_max >= ISCSI_MGMT_ITT_OFFSET) {
+   if (!is_power_of_2(cmds_max) || cmds_max >= ISCSI_MGMT_ITT_OFFSET ||
+   cmds_max < 2) {
if (cmds_max != 0)
printk(KERN_ERR "iscsi: invalid can_queue of %d. "
   "can_queue must be a power of 2 and between "
diff --git a/drivers/scsi/scsi_transport_iscsi.c 
b/drivers/scsi/scsi_transport_iscsi.c
index 9981682..dfb026b 100644
--- a/drivers/scsi/scsi_transport_iscsi.c
+++ b/drivers/scsi/scsi_transport_iscsi.c
@@ -33,7 +33,7 @@
 #define ISCSI_SESSION_ATTRS 19
 #define ISCSI_CONN_ATTRS 13
 #define ISCSI_HOST_ATTRS 4
-#define ISCSI_TRANSPORT_VERSION "2.0-868"
+#define ISCSI_TRANSPORT_VERSION "2.0-869"
 
 struct iscsi_internal {
int daemon_pid;
-- 
1.5.1.2

-
To unsubscribe from this list: send the line "unsubscribe linux-scsi" in
the body of a message to [EMAIL PROTECTED]
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATCH 1/2] scsi-ml: Add helper code so transport classes can control queueing

2008-01-31 Thread michaelc
From: Mike Christie <[EMAIL PROTECTED]>

SCSI-ml manages the queueing limits for the device and host, but
does not do so at the target level. Currently this is not needed
and is probably more for the transport code to handle. However,
for bnx2i we will need to be able to limit queueing at this level.
bnx2i will hook into libiscsi, but will allocate a scsi host per
netdevice/hba, so unlike pure software iscsi/iser which is allocating
a host per session, it cannot set the scsi_host->can_queue and return
SCSI_MLQUEUE_HOST_BUSY to reflect queueing limits on the transport.

This patch adds some basic helper code for scsi-ml, that the transport
classes can utilize.

The patch adds code similar to the exisiting SCSI_ML_*BUSY handlers.
You can now return SCSI_MLQUEUE_TARGET_BUSY when we hit
a transport level queueing issue like the hw cannot allocate some
resource at the iscsi session/connection level or the target has temporarily
closed or shrunk the queueing window.

The iscsi class/driver can also set a scsi_target->can_queue value which
reflects the max commands the driver/class can support. For iscsi this
reflects the number of commands we can support for each session due to
session/connection hw limits, driver limits, and to also reflect the
session/targets's queueing window.

This patch was made over the last patchset I sent. It is not for
mergeing into 2.6.25 or scsi-misc yet. I just want to put it out
here, and make sure it is ok and get feedback on what else I might
need to do for this patch before broadcom and I push the bnx2i driver.

Signed-off-by: Mike Christie <[EMAIL PROTECTED]>
---
 drivers/scsi/scsi.c|   11 +--
 drivers/scsi/scsi_lib.c|   70 +--
 drivers/scsi/scsi_scan.c   |1 +
 include/scsi/scsi.h|1 +
 include/scsi/scsi_device.h |   10 ++
 5 files changed, 80 insertions(+), 13 deletions(-)

diff --git a/drivers/scsi/scsi.c b/drivers/scsi/scsi.c
index b35d194..339760a 100644
--- a/drivers/scsi/scsi.c
+++ b/drivers/scsi/scsi.c
@@ -628,9 +628,12 @@ int scsi_dispatch_cmd(struct scsi_cmnd *cmd)
if (rtn) {
if (scsi_delete_timer(cmd)) {
atomic_inc(&cmd->device->iodone_cnt);
-   scsi_queue_insert(cmd,
- (rtn == SCSI_MLQUEUE_DEVICE_BUSY) ?
- rtn : SCSI_MLQUEUE_HOST_BUSY);
+
+   if (rtn != SCSI_MLQUEUE_DEVICE_BUSY &&
+   rtn != SCSI_MLQUEUE_TARGET_BUSY)
+   rtn = SCSI_MLQUEUE_HOST_BUSY;
+
+   scsi_queue_insert(cmd, rtn);
}
SCSI_LOG_MLQUEUE(3,
printk("queuecommand : request rejected\n"));
@@ -729,6 +732,7 @@ static struct scsi_driver *scsi_cmd_to_driver(struct 
scsi_cmnd *cmd)
 void scsi_finish_command(struct scsi_cmnd *cmd)
 {
struct scsi_device *sdev = cmd->device;
+   struct scsi_target *starget = scsi_target(sdev);
struct Scsi_Host *shost = sdev->host;
struct scsi_driver *drv;
unsigned int good_bytes;
@@ -744,6 +748,7 @@ void scsi_finish_command(struct scsi_cmnd *cmd)
 * XXX(hch): What about locking?
  */
 shost->host_blocked = 0;
+   starget->target_blocked = 0;
 sdev->device_blocked = 0;
 
/*
diff --git a/drivers/scsi/scsi_lib.c b/drivers/scsi/scsi_lib.c
index b12fb31..9c76d10 100644
--- a/drivers/scsi/scsi_lib.c
+++ b/drivers/scsi/scsi_lib.c
@@ -114,6 +114,7 @@ int scsi_queue_insert(struct scsi_cmnd *cmd, int reason)
 {
struct Scsi_Host *host = cmd->device->host;
struct scsi_device *device = cmd->device;
+   struct scsi_target *starget = scsi_target(device);
struct request_queue *q = device->request_queue;
unsigned long flags;
 
@@ -133,10 +134,17 @@ int scsi_queue_insert(struct scsi_cmnd *cmd, int reason)
 * if a command is requeued with no other commands outstanding
 * either for the device or for the host.
 */
-   if (reason == SCSI_MLQUEUE_HOST_BUSY)
-   host->host_blocked = host->max_host_blocked;
-   else if (reason == SCSI_MLQUEUE_DEVICE_BUSY)
-   device->device_blocked = device->max_device_blocked;
+   switch (reason) {
+   case SCSI_MLQUEUE_HOST_BUSY:
+   host->host_blocked = host->max_host_blocked;
+   break;
+   case SCSI_MLQUEUE_DEVICE_BUSY:
+   device->device_blocked = device->max_device_blocked;
+   break;
+   case SCSI_MLQUEUE_TARGET_BUSY:
+   starget->target_blocked = starget->max_target_blocked;
+   break;
+   }
 
/*
 * Decrement the counters, since these commands are no longer
@@ -452,10 +460,12 @@ static void scsi_init_cmd_errh(struct scsi_cmnd *cmd)
 void scsi_device_unbusy(struct scsi_device *sdev)
 {
struct Scsi_Host *shost = sdev->ho

[PATCH 2/2] iscsi: user per target can_queue

2008-01-31 Thread michaelc
From: Mike Christie <[EMAIL PROTECTED]>

This hooks iscsi_tcp and libiscsi into the target->can_queue
code and it has libiscsi use SCSI_MLQUEUE_TARGET_BUSY.

Signed-off-by: Mike Christie <[EMAIL PROTECTED]>
---
 drivers/infiniband/ulp/iser/iscsi_iser.c |1 +
 drivers/scsi/iscsi_tcp.c |1 +
 drivers/scsi/libiscsi.c  |   19 +--
 include/scsi/libiscsi.h  |1 +
 4 files changed, 20 insertions(+), 2 deletions(-)

diff --git a/drivers/infiniband/ulp/iser/iscsi_iser.c 
b/drivers/infiniband/ulp/iser/iscsi_iser.c
index be1b9fb..c818707 100644
--- a/drivers/infiniband/ulp/iser/iscsi_iser.c
+++ b/drivers/infiniband/ulp/iser/iscsi_iser.c
@@ -552,6 +552,7 @@ static struct scsi_host_template iscsi_iser_sht = {
.sg_tablesize   = ISCSI_ISER_SG_TABLESIZE,
.max_sectors= 1024,
.cmd_per_lun= ISCSI_MAX_CMD_PER_LUN,
+   .slave_alloc= iscsi_slave_alloc,
.eh_abort_handler   = iscsi_eh_abort,
.eh_device_reset_handler= iscsi_eh_device_reset,
.eh_host_reset_handler  = iscsi_eh_host_reset,
diff --git a/drivers/scsi/iscsi_tcp.c b/drivers/scsi/iscsi_tcp.c
index 8a17867..c63e0e8 100644
--- a/drivers/scsi/iscsi_tcp.c
+++ b/drivers/scsi/iscsi_tcp.c
@@ -1936,6 +1936,7 @@ static struct scsi_host_template iscsi_sht = {
.eh_device_reset_handler= iscsi_eh_device_reset,
.eh_host_reset_handler  = iscsi_eh_host_reset,
.use_clustering = DISABLE_CLUSTERING,
+   .slave_alloc= iscsi_slave_alloc,
.slave_configure= iscsi_tcp_slave_configure,
.proc_name  = "iscsi_tcp",
.this_id= -1,
diff --git a/drivers/scsi/libiscsi.c b/drivers/scsi/libiscsi.c
index 59f8445..6d6770c 100644
--- a/drivers/scsi/libiscsi.c
+++ b/drivers/scsi/libiscsi.c
@@ -1097,7 +1097,7 @@ reject:
spin_unlock(&session->lock);
debug_scsi("cmd 0x%x rejected (%d)\n", sc->cmnd[0], reason);
spin_lock(host->host_lock);
-   return SCSI_MLQUEUE_HOST_BUSY;
+   return SCSI_MLQUEUE_TARGET_BUSY;
 
 fault:
spin_unlock(&session->lock);
@@ -1118,6 +1118,21 @@ int iscsi_change_queue_depth(struct scsi_device *sdev, 
int depth)
 }
 EXPORT_SYMBOL_GPL(iscsi_change_queue_depth);
 
+int iscsi_slave_alloc(struct scsi_device *sdev)
+{
+   struct scsi_target *starget = scsi_target(sdev);
+   struct iscsi_cls_session *cls_session = starget_to_session(starget);
+   struct iscsi_session *session;
+
+   if (!cls_session || iscsi_session_chkready(cls_session))
+   return -ENXIO;
+
+   session = class_to_transport_session(cls_session);
+   starget->can_queue = session->cmds_max;
+   return 0;
+}
+EXPORT_SYMBOL_GPL(iscsi_slave_alloc);
+
 void iscsi_session_recovery_timedout(struct iscsi_cls_session *cls_session)
 {
struct iscsi_session *session = class_to_transport_session(cls_session);
@@ -1724,7 +1739,7 @@ iscsi_session_setup(struct iscsi_transport *iscsit,
return NULL;
 
/* the iscsi layer takes one task for reserve */
-   shost->can_queue = cmds_max - 1;
+   shost->can_queue = cmds_max;
shost->cmd_per_lun = qdepth;
shost->max_id = 1;
shost->max_channel = 0;
diff --git a/include/scsi/libiscsi.h b/include/scsi/libiscsi.h
index 7b90b63..3c2bdc4 100644
--- a/include/scsi/libiscsi.h
+++ b/include/scsi/libiscsi.h
@@ -308,6 +308,7 @@ struct iscsi_session {
 /*
  * scsi host template
  */
+extern int iscsi_slave_alloc(struct scsi_device *sdev);
 extern int iscsi_change_queue_depth(struct scsi_device *sdev, int depth);
 extern int iscsi_eh_abort(struct scsi_cmnd *sc);
 extern int iscsi_eh_host_reset(struct scsi_cmnd *sc);
-- 
1.5.2.1

-
To unsubscribe from this list: send the line "unsubscribe linux-scsi" in
the body of a message to [EMAIL PROTECTED]
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Add target queueing limit helpers to scsi-ml

2008-01-31 Thread michaelc
These two patches are for RFC, but could go into scsi-misc for
2.6.26 if they are ok off the bat.

They add the ability to limit queueing at the target level.
This will be needed for bnx2i, but also may be useful to
limit transport level commands when using bsg.


-
To unsubscribe from this list: send the line "unsubscribe linux-scsi" in
the body of a message to [EMAIL PROTECTED]
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATCH 12/12] bump iscsi version

2008-01-31 Thread michaelc
From: Mike Christie <[EMAIL PROTECTED]>

Set iscsi version to 2.0-868

Signed-off-by: Mike Christie <[EMAIL PROTECTED]>
---
 drivers/scsi/scsi_transport_iscsi.c |2 +-
 1 files changed, 1 insertions(+), 1 deletions(-)

diff --git a/drivers/scsi/scsi_transport_iscsi.c 
b/drivers/scsi/scsi_transport_iscsi.c
index 8e73ff0..fac7534 100644
--- a/drivers/scsi/scsi_transport_iscsi.c
+++ b/drivers/scsi/scsi_transport_iscsi.c
@@ -33,7 +33,7 @@
 #define ISCSI_SESSION_ATTRS 19
 #define ISCSI_CONN_ATTRS 13
 #define ISCSI_HOST_ATTRS 4
-#define ISCSI_TRANSPORT_VERSION "2.0-867"
+#define ISCSI_TRANSPORT_VERSION "2.0-868"
 
 struct iscsi_internal {
int daemon_pid;
-- 
1.5.2.1

-
To unsubscribe from this list: send the line "unsubscribe linux-scsi" in
the body of a message to [EMAIL PROTECTED]
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATCH 10/12] iscsi: fix up iscsi printk prefix

2008-01-31 Thread michaelc
From: Mike Christie <[EMAIL PROTECTED]>

Some iscsi class messages have the dev_printk prefix and some libiscsi
and iscsi_tcp messages have "iscsi" or the module name as a prefix which
is normally pretty useless when trying to figure out which session
or connection the message is attached to. This patch adds iscsi lib
and class dev_printks so all messages have a common prefix that
can be used to figure out which object printed it.

Signed-off-by: Mike Christie <[EMAIL PROTECTED]>
---
 drivers/scsi/iscsi_tcp.c|   57 ++
 drivers/scsi/libiscsi.c |   76 ---
 drivers/scsi/scsi_transport_iscsi.c |   56 ++
 include/scsi/libiscsi.h |7 +++
 include/scsi/scsi_transport_iscsi.h |6 +++
 5 files changed, 116 insertions(+), 86 deletions(-)

diff --git a/drivers/scsi/iscsi_tcp.c b/drivers/scsi/iscsi_tcp.c
index b6f99df..8a17867 100644
--- a/drivers/scsi/iscsi_tcp.c
+++ b/drivers/scsi/iscsi_tcp.c
@@ -629,8 +629,9 @@ iscsi_r2t_rsp(struct iscsi_conn *conn, struct 
iscsi_cmd_task *ctask)
int rc;
 
if (tcp_conn->in.datalen) {
-   printk(KERN_ERR "iscsi_tcp: invalid R2t with datalen %d\n",
-  tcp_conn->in.datalen);
+   iscsi_conn_printk(KERN_ERR, conn,
+ "invalid R2t with datalen %d\n",
+ tcp_conn->in.datalen);
return ISCSI_ERR_DATALEN;
}
 
@@ -644,8 +645,9 @@ iscsi_r2t_rsp(struct iscsi_conn *conn, struct 
iscsi_cmd_task *ctask)
iscsi_update_cmdsn(session, (struct iscsi_nopin*)rhdr);
 
if (!ctask->sc || session->state != ISCSI_STATE_LOGGED_IN) {
-   printk(KERN_INFO "iscsi_tcp: dropping R2T itt %d in "
-  "recovery...\n", ctask->itt);
+   iscsi_conn_printk(KERN_INFO, conn,
+ "dropping R2T itt %d in recovery.\n",
+ ctask->itt);
return 0;
}
 
@@ -655,7 +657,8 @@ iscsi_r2t_rsp(struct iscsi_conn *conn, struct 
iscsi_cmd_task *ctask)
r2t->exp_statsn = rhdr->statsn;
r2t->data_length = be32_to_cpu(rhdr->data_length);
if (r2t->data_length == 0) {
-   printk(KERN_ERR "iscsi_tcp: invalid R2T with zero data len\n");
+   iscsi_conn_printk(KERN_ERR, conn,
+ "invalid R2T with zero data len\n");
__kfifo_put(tcp_ctask->r2tpool.queue, (void*)&r2t,
sizeof(void*));
return ISCSI_ERR_DATALEN;
@@ -668,9 +671,10 @@ iscsi_r2t_rsp(struct iscsi_conn *conn, struct 
iscsi_cmd_task *ctask)
 
r2t->data_offset = be32_to_cpu(rhdr->data_offset);
if (r2t->data_offset + r2t->data_length > scsi_bufflen(ctask->sc)) {
-   printk(KERN_ERR "iscsi_tcp: invalid R2T with data len %u at "
-  "offset %u and total length %d\n", r2t->data_length,
-  r2t->data_offset, scsi_bufflen(ctask->sc));
+   iscsi_conn_printk(KERN_ERR, conn,
+ "invalid R2T with data len %u at offset %u "
+ "and total length %d\n", r2t->data_length,
+ r2t->data_offset, scsi_bufflen(ctask->sc));
__kfifo_put(tcp_ctask->r2tpool.queue, (void*)&r2t,
sizeof(void*));
return ISCSI_ERR_DATALEN;
@@ -736,8 +740,9 @@ iscsi_tcp_hdr_dissect(struct iscsi_conn *conn, struct 
iscsi_hdr *hdr)
/* verify PDU length */
tcp_conn->in.datalen = ntoh24(hdr->dlength);
if (tcp_conn->in.datalen > conn->max_recv_dlength) {
-   printk(KERN_ERR "iscsi_tcp: datalen %d > %d\n",
-  tcp_conn->in.datalen, conn->max_recv_dlength);
+   iscsi_conn_printk(KERN_ERR, conn,
+ "iscsi_tcp: datalen %d > %d\n",
+ tcp_conn->in.datalen, conn->max_recv_dlength);
return ISCSI_ERR_DATALEN;
}
 
@@ -819,10 +824,12 @@ iscsi_tcp_hdr_dissect(struct iscsi_conn *conn, struct 
iscsi_hdr *hdr)
 * For now we fail until we find a vendor that needs it
 */
if (ISCSI_DEF_MAX_RECV_SEG_LEN < tcp_conn->in.datalen) {
-   printk(KERN_ERR "iscsi_tcp: received buffer of len %u "
- "but conn buffer is only %u (opcode %0x)\n",
- tcp_conn->in.datalen,
- ISCSI_DEF_MAX_RECV_SEG_LEN, opcode);
+   iscsi_conn_printk(KERN_ERR, conn,
+ "iscsi_tcp: received buffer of "
+ "len %u but conn buffer is only %u "
+ "(opcode %0x)\n",
+ 

[PATCH 11/12] libiscsi: fix session age rollover and remove cid encoding

2008-01-31 Thread michaelc
From: Mike Christie <[EMAIL PROTECTED]>

The session age mask is only 4 bits, but session->age is 32. When
it gets larger then 15 and we try to or the bits some bits get
dropped and the check for session age in iscsi_verify_itt is useless.

The ISCSI_CID_MASK related bits are also useless since cid is always
one.

Signed-off-by: Mike Christie <[EMAIL PROTECTED]>
---
 drivers/scsi/libiscsi.c|   14 --
 include/scsi/iscsi_proto.h |4 ++--
 include/scsi/libiscsi.h|2 --
 3 files changed, 6 insertions(+), 14 deletions(-)

diff --git a/drivers/scsi/libiscsi.c b/drivers/scsi/libiscsi.c
index c76bd5c..cfffabd 100644
--- a/drivers/scsi/libiscsi.c
+++ b/drivers/scsi/libiscsi.c
@@ -160,7 +160,7 @@ static int iscsi_prep_scsi_cmd_pdu(struct iscsi_cmd_task 
*ctask)
hdr->opcode = ISCSI_OP_SCSI_CMD;
hdr->flags = ISCSI_ATTR_SIMPLE;
int_to_scsilun(sc->device->lun, (struct scsi_lun *)hdr->lun);
-   hdr->itt = build_itt(ctask->itt, conn->id, session->age);
+   hdr->itt = build_itt(ctask->itt, session->age);
hdr->data_length = cpu_to_be32(scsi_bufflen(sc));
hdr->cmdsn = cpu_to_be32(session->cmdsn);
session->cmdsn++;
@@ -706,14 +706,6 @@ int iscsi_verify_itt(struct iscsi_conn *conn, struct 
iscsi_hdr *hdr,
return ISCSI_ERR_BAD_ITT;
}
 
-   if (((__force u32)hdr->itt & ISCSI_CID_MASK) !=
-   (conn->id << ISCSI_CID_SHIFT)) {
-   iscsi_conn_printk(KERN_ERR, conn,
- "iscsi: received itt %x, expected "
- "CID (%x)\n",
- (__force u32)hdr->itt, conn->id);
-   return ISCSI_ERR_BAD_ITT;
-   }
itt = get_itt(hdr->itt);
} else
itt = ~0U;
@@ -777,7 +769,7 @@ static void iscsi_prep_mtask(struct iscsi_conn *conn,
 */
nop->cmdsn = cpu_to_be32(session->cmdsn);
if (hdr->itt != RESERVED_ITT) {
-   hdr->itt = build_itt(mtask->itt, conn->id, session->age);
+   hdr->itt = build_itt(mtask->itt, session->age);
/*
 * TODO: We always use immediate, so we never hit this.
 * If we start to send tmfs or nops as non-immediate then
@@ -2037,6 +2029,8 @@ int iscsi_conn_start(struct iscsi_cls_conn *cls_conn)
conn->stop_stage = 0;
conn->tmf_state = TMF_INITIAL;
session->age++;
+   if (session->age == 16)
+   session->age = 0;
break;
case STOP_CONN_TERM:
conn->stop_stage = 0;
diff --git a/include/scsi/iscsi_proto.h b/include/scsi/iscsi_proto.h
index 318a909..5ffec8a 100644
--- a/include/scsi/iscsi_proto.h
+++ b/include/scsi/iscsi_proto.h
@@ -45,8 +45,8 @@
 /* initiator tags; opaque for target */
 typedef uint32_t __bitwise__ itt_t;
 /* below makes sense only for initiator that created this tag */
-#define build_itt(itt, id, age) ((__force itt_t)\
-   ((itt) | ((id) << ISCSI_CID_SHIFT) | ((age) << ISCSI_AGE_SHIFT)))
+#define build_itt(itt, age) ((__force itt_t)\
+   ((itt) | ((age) << ISCSI_AGE_SHIFT)))
 #define get_itt(itt) ((__force uint32_t)(itt_t)(itt) & ISCSI_ITT_MASK)
 #define RESERVED_ITT ((__force itt_t)0x)
 
diff --git a/include/scsi/libiscsi.h b/include/scsi/libiscsi.h
index 5daa83c..9b955a9 100644
--- a/include/scsi/libiscsi.h
+++ b/include/scsi/libiscsi.h
@@ -70,8 +70,6 @@ enum {
 #define ISCSI_SUSPEND_BIT  1
 
 #define ISCSI_ITT_MASK (0xfff)
-#define ISCSI_CID_SHIFT12
-#define ISCSI_CID_MASK (0x << ISCSI_CID_SHIFT)
 #define ISCSI_AGE_SHIFT28
 #define ISCSI_AGE_MASK (0xf << ISCSI_AGE_SHIFT)
 
-- 
1.5.2.1

-
To unsubscribe from this list: send the line "unsubscribe linux-scsi" in
the body of a message to [EMAIL PROTECTED]
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATCH 09/12] iscsi class: fix iscsi conn attr counter

2008-01-31 Thread michaelc
From: Mike Christie <[EMAIL PROTECTED]>

There are 13 iscsi conn attrs, but since the IF/OF markers were not being
used we did not notice that we forgot to increment the ISCSI_CONN_ATTRS
counter.

Signed-off-by: Mike Christie <[EMAIL PROTECTED]>
---
 drivers/scsi/scsi_transport_iscsi.c |2 +-
 1 files changed, 1 insertions(+), 1 deletions(-)

diff --git a/drivers/scsi/scsi_transport_iscsi.c 
b/drivers/scsi/scsi_transport_iscsi.c
index af17997..35834bf 100644
--- a/drivers/scsi/scsi_transport_iscsi.c
+++ b/drivers/scsi/scsi_transport_iscsi.c
@@ -31,7 +31,7 @@
 #include 
 
 #define ISCSI_SESSION_ATTRS 19
-#define ISCSI_CONN_ATTRS 11
+#define ISCSI_CONN_ATTRS 13
 #define ISCSI_HOST_ATTRS 4
 #define ISCSI_TRANSPORT_VERSION "2.0-867"
 
-- 
1.5.2.1

-
To unsubscribe from this list: send the line "unsubscribe linux-scsi" in
the body of a message to [EMAIL PROTECTED]
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATCH 08/12] libiscsi: fix setting of nop timer

2008-01-31 Thread michaelc
From: Mike Christie <[EMAIL PROTECTED]>

If we rollover then we could get a next_timeout of zero, so we need
to set the new timer to that value.

Signed-off-by: Mike Christie <[EMAIL PROTECTED]>
---
 drivers/scsi/libiscsi.c |9 +++--
 1 files changed, 3 insertions(+), 6 deletions(-)

diff --git a/drivers/scsi/libiscsi.c b/drivers/scsi/libiscsi.c
index 8c41ddb..7e781fd 100644
--- a/drivers/scsi/libiscsi.c
+++ b/drivers/scsi/libiscsi.c
@@ -1385,14 +1385,11 @@ static void iscsi_check_transport_timeouts(unsigned 
long data)
iscsi_send_nopout(conn, NULL);
}
next_timeout = last_recv + timeout + (conn->ping_timeout * HZ);
-   } else {
+   } else
next_timeout = last_recv + timeout;
-   }
 
-   if (next_timeout) {
-   debug_scsi("Setting next tmo %lu\n", next_timeout);
-   mod_timer(&conn->transport_timer, next_timeout);
-   }
+   debug_scsi("Setting next tmo %lu\n", next_timeout);
+   mod_timer(&conn->transport_timer, next_timeout);
 done:
spin_unlock(&session->lock);
 }
-- 
1.5.2.1

-
To unsubscribe from this list: send the line "unsubscribe linux-scsi" in
the body of a message to [EMAIL PROTECTED]
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATCH 07/12] qla4xxx: add qla4xxx async scan support

2008-01-31 Thread michaelc
From: Mike Christie <[EMAIL PROTECTED]>

qla4xxx has the old school startup/probe where it finds presetup sessions
in its flash and then attempts to log into them before returning from the
probe. This however, makes it very simple to add a iscsi class scan finished
helper which the driver can use.

In future patches Dave or I will rip apart the driver to make it more
like qla2xxx, but for now this is a very simple two line patch which
fixes the problem of trying to figure out when the initial sessions
are done being scanned.

Signed-off-by: Mike Christie <[EMAIL PROTECTED]>
---
 drivers/scsi/qla4xxx/ql4_os.c |4 +++-
 1 files changed, 3 insertions(+), 1 deletions(-)

diff --git a/drivers/scsi/qla4xxx/ql4_os.c b/drivers/scsi/qla4xxx/ql4_os.c
index d4dd149..c3c59d7 100644
--- a/drivers/scsi/qla4xxx/ql4_os.c
+++ b/drivers/scsi/qla4xxx/ql4_os.c
@@ -89,6 +89,8 @@ static struct scsi_host_template qla4xxx_driver_template = {
.slave_alloc= qla4xxx_slave_alloc,
.slave_destroy  = qla4xxx_slave_destroy,
 
+   .scan_finished  = iscsi_scan_finished,
+
.this_id= -1,
.cmd_per_lun= 3,
.use_clustering = ENABLE_CLUSTERING,
@@ -1306,7 +1308,7 @@ static int __devinit qla4xxx_probe_adapter(struct pci_dev 
*pdev,
   qla4xxx_version_str, ha->pdev->device, pci_name(ha->pdev),
   ha->host_no, ha->firmware_version[0], ha->firmware_version[1],
   ha->patch_number, ha->build_number);
-
+   scsi_scan_host(host);
return 0;
 
 remove_host:
-- 
1.5.2.1

-
To unsubscribe from this list: send the line "unsubscribe linux-scsi" in
the body of a message to [EMAIL PROTECTED]
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATCH 04/12] iscsi class: add session scanning

2008-01-31 Thread michaelc
From: Mike Christie <[EMAIL PROTECTED]>

This just adds iscsi session scanning which works like fc rport scanning.
The future patches will hook the drivers into Mathew Wilcox's async
scanning infrastructure, so userspace does not have to special case
iscsi and so userspace does not have to make a extra special case for
hardware iscsi root scanning.

Signed-off-by: Mike Christie <[EMAIL PROTECTED]>
---
 drivers/scsi/scsi_transport_iscsi.c |   37 --
 include/scsi/scsi_transport_iscsi.h |7 +++--
 2 files changed, 34 insertions(+), 10 deletions(-)

diff --git a/drivers/scsi/scsi_transport_iscsi.c 
b/drivers/scsi/scsi_transport_iscsi.c
index f876b0a..af88955 100644
--- a/drivers/scsi/scsi_transport_iscsi.c
+++ b/drivers/scsi/scsi_transport_iscsi.c
@@ -128,11 +128,11 @@ static int iscsi_setup_host(struct transport_container 
*tc, struct device *dev,
INIT_LIST_HEAD(&ihost->sessions);
mutex_init(&ihost->mutex);
 
-   snprintf(ihost->unbind_workq_name, KOBJ_NAME_LEN, "iscsi_unbind_%d",
+   snprintf(ihost->scan_workq_name, KOBJ_NAME_LEN, "iscsi_scan_%d",
shost->host_no);
-   ihost->unbind_workq = create_singlethread_workqueue(
-   ihost->unbind_workq_name);
-   if (!ihost->unbind_workq)
+   ihost->scan_workq = create_singlethread_workqueue(
+   ihost->scan_workq_name);
+   if (!ihost->scan_workq)
return -ENOMEM;
return 0;
 }
@@ -143,7 +143,7 @@ static int iscsi_remove_host(struct transport_container 
*tc, struct device *dev,
struct Scsi_Host *shost = dev_to_shost(dev);
struct iscsi_host *ihost = shost->shost_data;
 
-   destroy_workqueue(ihost->unbind_workq);
+   destroy_workqueue(ihost->scan_workq);
return 0;
 }
 
@@ -302,6 +302,23 @@ static int iscsi_user_scan(struct Scsi_Host *shost, uint 
channel,
return 0;
 }
 
+static void iscsi_scan_session(struct work_struct *work)
+{
+   struct iscsi_cls_session *session =
+   container_of(work, struct iscsi_cls_session, scan_work);
+   unsigned long flags;
+
+   spin_lock_irqsave(&session->lock, flags);
+   if (session->state != ISCSI_SESSION_LOGGED_IN) {
+   spin_unlock_irqrestore(&session->lock, flags);
+   return;
+   }
+   spin_unlock_irqrestore(&session->lock, flags);
+
+   scsi_scan_target(&session->dev, 0, session->target_id,
+SCAN_WILD_CARD, 1);
+}
+
 static void session_recovery_timedout(struct work_struct *work)
 {
struct iscsi_cls_session *session =
@@ -340,6 +357,8 @@ void __iscsi_unblock_session(struct iscsi_cls_session 
*session)
 
 void iscsi_unblock_session(struct iscsi_cls_session *session)
 {
+   struct Scsi_Host *shost = iscsi_session_to_shost(session);
+   struct iscsi_host *ihost = shost->shost_data;
unsigned long flags;
 
spin_lock_irqsave(&session->lock, flags);
@@ -347,6 +366,7 @@ void iscsi_unblock_session(struct iscsi_cls_session 
*session)
spin_unlock_irqrestore(&session->lock, flags);
 
__iscsi_unblock_session(session);
+   queue_work(ihost->scan_workq, &session->scan_work);
 }
 EXPORT_SYMBOL_GPL(iscsi_unblock_session);
 
@@ -390,7 +410,7 @@ static int iscsi_unbind_session(struct iscsi_cls_session 
*session)
struct Scsi_Host *shost = iscsi_session_to_shost(session);
struct iscsi_host *ihost = shost->shost_data;
 
-   return queue_work(ihost->unbind_workq, &session->unbind_work);
+   return queue_work(ihost->scan_workq, &session->unbind_work);
 }
 
 struct iscsi_cls_session *
@@ -411,6 +431,7 @@ iscsi_alloc_session(struct Scsi_Host *shost,
INIT_LIST_HEAD(&session->host_list);
INIT_LIST_HEAD(&session->sess_list);
INIT_WORK(&session->unbind_work, __iscsi_unbind_session);
+   INIT_WORK(&session->scan_work, iscsi_scan_session);
spin_lock_init(&session->lock);
 
/* this is released in the dev's release function */
@@ -530,13 +551,15 @@ void iscsi_remove_session(struct iscsi_cls_session 
*session)
spin_unlock_irqrestore(&session->lock, flags);
__iscsi_unblock_session(session);
iscsi_unbind_session(session);
+
+   /* flush running scans */
+   flush_workqueue(ihost->scan_workq);
/*
 * If the session dropped while removing devices then we need to make
 * sure it is not blocked
 */
if (!cancel_delayed_work(&session->recovery_work))
flush_workqueue(iscsi_eh_timer_workq);
-   flush_workqueue(ihost->unbind_workq);
 
/* hw iscsi may not have removed all connections from session */
err = device_for_each_child(&session->dev, NULL,
diff --git a/include/scsi/scsi_transport_iscsi.h 
b/include/scsi/scsi_transport_iscsi.h
index 0e869d9..1f0ec46 100644
--- a/include/scsi/scsi_transport_iscsi.h
+++ b/include/sc

[PATCH 06/12] iscsi class: add async scan helper

2008-01-31 Thread michaelc
From: Mike Christie <[EMAIL PROTECTED]>

In qla4xxx's probe it will call the iscsi session setup functions
for session that got setup on the initial start. This then makes
it easy for the iscsi class to export a helper which indicates
when those scans are done.

Signed-off-by: Mike Christie <[EMAIL PROTECTED]>
---
 drivers/scsi/scsi_transport_iscsi.c |   38 --
 include/scsi/scsi_transport_iscsi.h |3 +-
 2 files changed, 37 insertions(+), 4 deletions(-)

diff --git a/drivers/scsi/scsi_transport_iscsi.c 
b/drivers/scsi/scsi_transport_iscsi.c
index af88955..af17997 100644
--- a/drivers/scsi/scsi_transport_iscsi.c
+++ b/drivers/scsi/scsi_transport_iscsi.c
@@ -127,6 +127,7 @@ static int iscsi_setup_host(struct transport_container *tc, 
struct device *dev,
memset(ihost, 0, sizeof(*ihost));
INIT_LIST_HEAD(&ihost->sessions);
mutex_init(&ihost->mutex);
+   atomic_set(&ihost->nr_scans, 0);
 
snprintf(ihost->scan_workq_name, KOBJ_NAME_LEN, "iscsi_scan_%d",
shost->host_no);
@@ -284,6 +285,25 @@ static int iscsi_is_session_dev(const struct device *dev)
return dev->release == iscsi_session_release;
 }
 
+/**
+ * iscsi_scan_finished - helper to report when running scans are done
+ * @shost: scsi host
+ * @time: scan run time
+ *
+ * This function can be used by drives like qla4xxx to report to the scsi
+ * layer when the scans it kicked off at module load time are done.
+ */
+int iscsi_scan_finished(struct Scsi_Host *shost, unsigned long time)
+{
+   struct iscsi_host *ihost = shost->shost_data;
+   /*
+* qla4xxx will have kicked off some session unblocks before calling
+* scsi_scan_host, so just wait for them to complete.
+*/
+   return !atomic_read(&ihost->nr_scans);
+}
+EXPORT_SYMBOL_GPL(iscsi_scan_finished);
+
 static int iscsi_user_scan(struct Scsi_Host *shost, uint channel,
   uint id, uint lun)
 {
@@ -306,17 +326,21 @@ static void iscsi_scan_session(struct work_struct *work)
 {
struct iscsi_cls_session *session =
container_of(work, struct iscsi_cls_session, scan_work);
+   struct Scsi_Host *shost = iscsi_session_to_shost(session);
+   struct iscsi_host *ihost = shost->shost_data;
unsigned long flags;
 
spin_lock_irqsave(&session->lock, flags);
if (session->state != ISCSI_SESSION_LOGGED_IN) {
spin_unlock_irqrestore(&session->lock, flags);
-   return;
+   goto done;
}
spin_unlock_irqrestore(&session->lock, flags);
 
scsi_scan_target(&session->dev, 0, session->target_id,
 SCAN_WILD_CARD, 1);
+done:
+   atomic_dec(&ihost->nr_scans);
 }
 
 static void session_recovery_timedout(struct work_struct *work)
@@ -366,7 +390,15 @@ void iscsi_unblock_session(struct iscsi_cls_session 
*session)
spin_unlock_irqrestore(&session->lock, flags);
 
__iscsi_unblock_session(session);
-   queue_work(ihost->scan_workq, &session->scan_work);
+   /*
+* Only do kernel scanning if the driver is properly hooked into
+* the async scanning code (drivers like iscsi_tcp do login and
+* scanning from userspace).
+*/
+   if (shost->hostt->scan_finished) {
+   if (queue_work(ihost->scan_workq, &session->scan_work))
+   atomic_inc(&ihost->nr_scans);
+   }
 }
 EXPORT_SYMBOL_GPL(iscsi_unblock_session);
 
@@ -550,7 +582,7 @@ void iscsi_remove_session(struct iscsi_cls_session *session)
session->state = ISCSI_SESSION_FREE;
spin_unlock_irqrestore(&session->lock, flags);
__iscsi_unblock_session(session);
-   iscsi_unbind_session(session);
+   __iscsi_unbind_session(&session->unbind_work);
 
/* flush running scans */
flush_workqueue(ihost->scan_workq);
diff --git a/include/scsi/scsi_transport_iscsi.h 
b/include/scsi/scsi_transport_iscsi.h
index 1f0ec46..83693ba 100644
--- a/include/scsi/scsi_transport_iscsi.h
+++ b/include/scsi/scsi_transport_iscsi.h
@@ -203,6 +203,7 @@ struct iscsi_cls_session {
 
 struct iscsi_host {
struct list_head sessions;
+   atomic_t nr_scans;
struct mutex mutex;
struct workqueue_struct *scan_workq;
char scan_workq_name[KOBJ_NAME_LEN];
@@ -229,6 +230,6 @@ extern struct iscsi_cls_conn *iscsi_create_conn(struct 
iscsi_cls_session *sess,
 extern int iscsi_destroy_conn(struct iscsi_cls_conn *conn);
 extern void iscsi_unblock_session(struct iscsi_cls_session *session);
 extern void iscsi_block_session(struct iscsi_cls_session *session);
-
+extern int iscsi_scan_finished(struct Scsi_Host *shost, unsigned long time);
 
 #endif
-- 
1.5.2.1

-
To unsubscribe from this list: send the line "unsubscribe linux-scsi" in
the body of a message to [EMAIL PROTECTED]
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATCH 05/12] qla4xxx: fix recovery timer and session unblock race

2008-01-31 Thread michaelc
From: Mike Christie <[EMAIL PROTECTED]>

If qla4xxx is resetting up a session and the recovery timer
fires we do not want to just set it to dead, because
the dpc thread could have just set it to online and is in the
middle of resetting it up.

Signed-off-by: Mike Christie <[EMAIL PROTECTED]>
---
 drivers/scsi/qla4xxx/ql4_os.c |   19 +++
 1 files changed, 11 insertions(+), 8 deletions(-)

diff --git a/drivers/scsi/qla4xxx/ql4_os.c b/drivers/scsi/qla4xxx/ql4_os.c
index 437d169..d4dd149 100644
--- a/drivers/scsi/qla4xxx/ql4_os.c
+++ b/drivers/scsi/qla4xxx/ql4_os.c
@@ -124,16 +124,19 @@ static void qla4xxx_recovery_timedout(struct 
iscsi_cls_session *session)
struct ddb_entry *ddb_entry = session->dd_data;
struct scsi_qla_host *ha = ddb_entry->ha;
 
-   DEBUG2(printk("scsi%ld: %s: index [%d] port down retry count of (%d) "
- "secs exhausted, marking device DEAD.\n", ha->host_no,
- __func__, ddb_entry->fw_ddb_index,
- ha->port_down_retry_count));
+   if (atomic_read(&ddb_entry->state) != DDB_STATE_ONLINE) {
+   atomic_set(&ddb_entry->state, DDB_STATE_DEAD);
 
-   atomic_set(&ddb_entry->state, DDB_STATE_DEAD);
+   DEBUG2(printk("scsi%ld: %s: index [%d] port down retry count "
+ "of (%d) secs exhausted, marking device DEAD.\n",
+ ha->host_no, __func__, ddb_entry->fw_ddb_index,
+ ha->port_down_retry_count));
 
-   DEBUG2(printk("scsi%ld: %s: scheduling dpc routine - dpc flags = "
- "0x%lx\n", ha->host_no, __func__, ha->dpc_flags));
-   queue_work(ha->dpc_thread, &ha->dpc_work);
+   DEBUG2(printk("scsi%ld: %s: scheduling dpc routine - dpc "
+ "flags = 0x%lx\n",
+ ha->host_no, __func__, ha->dpc_flags));
+   queue_work(ha->dpc_thread, &ha->dpc_work);
+   }
 }
 
 static int qla4xxx_host_get_param(struct Scsi_Host *shost,
-- 
1.5.2.1

-
To unsubscribe from this list: send the line "unsubscribe linux-scsi" in
the body of a message to [EMAIL PROTECTED]
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATCH 03/12] qla4xxx: have qla4xxx use iscsi class session state check ready

2008-01-31 Thread michaelc
From: Mike Christie <[EMAIL PROTECTED]>

This has qla4xxx use the iscsi class's check ready function
in the queue command function, so all iscsi drivers return the
same error value for common problems.

Signed-off-by: Mike Christie <[EMAIL PROTECTED]>
---
 drivers/scsi/qla4xxx/ql4_os.c |   12 
 1 files changed, 12 insertions(+), 0 deletions(-)

diff --git a/drivers/scsi/qla4xxx/ql4_os.c b/drivers/scsi/qla4xxx/ql4_os.c
index a87fb9f..437d169 100644
--- a/drivers/scsi/qla4xxx/ql4_os.c
+++ b/drivers/scsi/qla4xxx/ql4_os.c
@@ -398,9 +398,21 @@ static int qla4xxx_queuecommand(struct scsi_cmnd *cmd,
 {
struct scsi_qla_host *ha = to_qla_host(cmd->device->host);
struct ddb_entry *ddb_entry = cmd->device->hostdata;
+   struct iscsi_cls_session *sess = ddb_entry->sess;
struct srb *srb;
int rval;
 
+   if (!sess) {
+   cmd->result = DID_IMM_RETRY << 16;
+   goto qc_fail_command;
+   }
+
+   rval = iscsi_session_chkready(sess);
+   if (rval) {
+   cmd->result = rval;
+   goto qc_fail_command;
+   }
+
if (atomic_read(&ddb_entry->state) != DDB_STATE_ONLINE) {
if (atomic_read(&ddb_entry->state) == DDB_STATE_DEAD) {
cmd->result = DID_NO_CONNECT << 16;
-- 
1.5.2.1

-
To unsubscribe from this list: send the line "unsubscribe linux-scsi" in
the body of a message to [EMAIL PROTECTED]
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATCH 02/12] qla4xxx: have qla4xxx directly call iscsi recovery functions

2008-01-31 Thread michaelc
From: Mike Christie <[EMAIL PROTECTED]>

Qla4xxx can just call the iscsi recovery functions directly.
There is no need for userspace to do this for qla4xxx, because
we do not use the mutex to iterate over devices anymore and iscsi_block
/unblock_session can be called from interrupt context or the dpc thread.
And having userspace do this just creates uneeded headaches for qla4xxx root
situations where the session may experience problems. For example
during the kernel shutdown the scsi layer wants to send sync caches, but at
this time userspace is not up (iscsid is not running), so we cannot
recover from the problem.

Signed-off-by: Mike Christie <[EMAIL PROTECTED]>
---
 drivers/scsi/qla4xxx/ql4_init.c |1 +
 drivers/scsi/qla4xxx/ql4_os.c   |   40 +++---
 2 files changed, 5 insertions(+), 36 deletions(-)

diff --git a/drivers/scsi/qla4xxx/ql4_init.c b/drivers/scsi/qla4xxx/ql4_init.c
index cbe0a17..03e66cb 100644
--- a/drivers/scsi/qla4xxx/ql4_init.c
+++ b/drivers/scsi/qla4xxx/ql4_init.c
@@ -1306,6 +1306,7 @@ int qla4xxx_process_ddb_changed(struct scsi_qla_host *ha,
atomic_set(&ddb_entry->relogin_timer, 0);
clear_bit(DF_RELOGIN, &ddb_entry->flags);
clear_bit(DF_NO_RELOGIN, &ddb_entry->flags);
+   iscsi_unblock_session(ddb_entry->sess);
iscsi_session_event(ddb_entry->sess,
ISCSI_KEVENT_CREATE_SESSION);
/*
diff --git a/drivers/scsi/qla4xxx/ql4_os.c b/drivers/scsi/qla4xxx/ql4_os.c
index 2e2b9fe..a87fb9f 100644
--- a/drivers/scsi/qla4xxx/ql4_os.c
+++ b/drivers/scsi/qla4xxx/ql4_os.c
@@ -63,8 +63,6 @@ static int qla4xxx_sess_get_param(struct iscsi_cls_session 
*sess,
  enum iscsi_param param, char *buf);
 static int qla4xxx_host_get_param(struct Scsi_Host *shost,
  enum iscsi_host_param param, char *buf);
-static void qla4xxx_conn_stop(struct iscsi_cls_conn *conn, int flag);
-static int qla4xxx_conn_start(struct iscsi_cls_conn *conn);
 static void qla4xxx_recovery_timedout(struct iscsi_cls_session *session);
 
 /*
@@ -116,8 +114,6 @@ static struct iscsi_transport qla4xxx_iscsi_transport = {
.get_conn_param = qla4xxx_conn_get_param,
.get_session_param  = qla4xxx_sess_get_param,
.get_host_param = qla4xxx_host_get_param,
-   .start_conn = qla4xxx_conn_start,
-   .stop_conn  = qla4xxx_conn_stop,
.session_recovery_timedout = qla4xxx_recovery_timedout,
 };
 
@@ -140,38 +136,6 @@ static void qla4xxx_recovery_timedout(struct 
iscsi_cls_session *session)
queue_work(ha->dpc_thread, &ha->dpc_work);
 }
 
-static int qla4xxx_conn_start(struct iscsi_cls_conn *conn)
-{
-   struct iscsi_cls_session *session;
-   struct ddb_entry *ddb_entry;
-
-   session = iscsi_dev_to_session(conn->dev.parent);
-   ddb_entry = session->dd_data;
-
-   DEBUG2(printk("scsi%ld: %s: index [%d] starting conn\n",
- ddb_entry->ha->host_no, __func__,
- ddb_entry->fw_ddb_index));
-   iscsi_unblock_session(session);
-   return 0;
-}
-
-static void qla4xxx_conn_stop(struct iscsi_cls_conn *conn, int flag)
-{
-   struct iscsi_cls_session *session;
-   struct ddb_entry *ddb_entry;
-
-   session = iscsi_dev_to_session(conn->dev.parent);
-   ddb_entry = session->dd_data;
-
-   DEBUG2(printk("scsi%ld: %s: index [%d] stopping conn\n",
- ddb_entry->ha->host_no, __func__,
- ddb_entry->fw_ddb_index));
-   if (flag == STOP_CONN_RECOVER)
-   iscsi_block_session(session);
-   else
-   printk(KERN_ERR "iscsi: invalid stop flag %d\n", flag);
-}
-
 static int qla4xxx_host_get_param(struct Scsi_Host *shost,
  enum iscsi_host_param param, char *buf)
 {
@@ -308,6 +272,9 @@ int qla4xxx_add_sess(struct ddb_entry *ddb_entry)
DEBUG2(printk(KERN_ERR "Could not add connection.\n"));
return -ENOMEM;
}
+
+   /* finally ready to go */
+   iscsi_unblock_session(ddb_entry->sess);
return 0;
 }
 
@@ -364,6 +331,7 @@ void qla4xxx_mark_device_missing(struct scsi_qla_host *ha,
DEBUG3(printk("scsi%d:%d:%d: index [%d] marked MISSING\n",
  ha->host_no, ddb_entry->bus, ddb_entry->target,
  ddb_entry->fw_ddb_index));
+   iscsi_block_session(ddb_entry->sess);
iscsi_conn_error(ddb_entry->conn, ISCSI_ERR_CONN_FAILED);
 }
 
-- 
1.5.2.1

-
To unsubscribe from this list: send the line "unsubscribe linux-scsi" in
the body of a message to [EMAIL PROTECTED]
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATCH 01/12] iscsi class, libiscsi: add iscsi sysfs session state file

2008-01-31 Thread michaelc
From: Mike Christie <[EMAIL PROTECTED]>

This adds a iscsi session state file which exports the session
state for both software and hardware iscsi. It also hooks libiscsi
in.

Signed-off-by: Mike Christie <[EMAIL PROTECTED]>
---
 drivers/scsi/libiscsi.c |   41 +-
 drivers/scsi/scsi_transport_iscsi.c |  107 ++-
 include/scsi/libiscsi.h |   19 ++
 include/scsi/scsi_transport_iscsi.h |   27 -
 4 files changed, 161 insertions(+), 33 deletions(-)

diff --git a/drivers/scsi/libiscsi.c b/drivers/scsi/libiscsi.c
index 553168a..8c41ddb 100644
--- a/drivers/scsi/libiscsi.c
+++ b/drivers/scsi/libiscsi.c
@@ -997,6 +997,7 @@ enum {
FAILURE_SESSION_IN_RECOVERY,
FAILURE_SESSION_RECOVERY_TIMEOUT,
FAILURE_SESSION_LOGGING_OUT,
+   FAILURE_SESSION_NOT_READY,
 };
 
 int iscsi_queuecommand(struct scsi_cmnd *sc, void (*done)(struct scsi_cmnd *))
@@ -1017,6 +1018,12 @@ int iscsi_queuecommand(struct scsi_cmnd *sc, void 
(*done)(struct scsi_cmnd *))
session = iscsi_hostdata(host->hostdata);
spin_lock(&session->lock);
 
+   reason = iscsi_session_chkready(session_to_cls(session));
+   if (reason) {
+   sc->result = reason;
+   goto fault;
+   }
+
/*
 * ISCSI_STATE_FAILED is a temp. state. The recovery
 * code will decide what is best to do with command queued
@@ -1033,18 +1040,23 @@ int iscsi_queuecommand(struct scsi_cmnd *sc, void 
(*done)(struct scsi_cmnd *))
switch (session->state) {
case ISCSI_STATE_IN_RECOVERY:
reason = FAILURE_SESSION_IN_RECOVERY;
-   goto reject;
+   sc->result = DID_IMM_RETRY << 16;
+   break;
case ISCSI_STATE_LOGGING_OUT:
reason = FAILURE_SESSION_LOGGING_OUT;
-   goto reject;
+   sc->result = DID_IMM_RETRY << 16;
+   break;
case ISCSI_STATE_RECOVERY_FAILED:
reason = FAILURE_SESSION_RECOVERY_TIMEOUT;
+   sc->result = DID_NO_CONNECT << 16;
break;
case ISCSI_STATE_TERMINATE:
reason = FAILURE_SESSION_TERMINATE;
+   sc->result = DID_NO_CONNECT << 16;
break;
default:
reason = FAILURE_SESSION_FREED;
+   sc->result = DID_NO_CONNECT << 16;
}
goto fault;
}
@@ -1052,6 +1064,7 @@ int iscsi_queuecommand(struct scsi_cmnd *sc, void 
(*done)(struct scsi_cmnd *))
conn = session->leadconn;
if (!conn) {
reason = FAILURE_SESSION_FREED;
+   sc->result = DID_NO_CONNECT << 16;
goto fault;
}
 
@@ -1091,9 +1104,7 @@ reject:
 
 fault:
spin_unlock(&session->lock);
-   printk(KERN_ERR "iscsi: cmd 0x%x is not queued (%d)\n",
-  sc->cmnd[0], reason);
-   sc->result = (DID_NO_CONNECT << 16);
+   debug_scsi("iscsi: cmd 0x%x is not queued (%d)\n", sc->cmnd[0], reason);
scsi_set_resid(sc, scsi_bufflen(sc));
sc->scsi_done(sc);
spin_lock(host->host_lock);
@@ -1239,7 +1250,8 @@ static int iscsi_exec_task_mgmt_fn(struct iscsi_conn 
*conn,
  * Fail commands. session lock held and recv side suspended and xmit
  * thread flushed
  */
-static void fail_all_commands(struct iscsi_conn *conn, unsigned lun)
+static void fail_all_commands(struct iscsi_conn *conn, unsigned lun,
+ int error)
 {
struct iscsi_cmd_task *ctask, *tmp;
 
@@ -1251,7 +1263,7 @@ static void fail_all_commands(struct iscsi_conn *conn, 
unsigned lun)
if (lun == ctask->sc->device->lun || lun == -1) {
debug_scsi("failing pending sc %p itt 0x%x\n",
   ctask->sc, ctask->itt);
-   fail_command(conn, ctask, DID_BUS_BUSY << 16);
+   fail_command(conn, ctask, error << 16);
}
}
 
@@ -1259,7 +1271,7 @@ static void fail_all_commands(struct iscsi_conn *conn, 
unsigned lun)
if (lun == ctask->sc->device->lun || lun == -1) {
debug_scsi("failing requeued sc %p itt 0x%x\n",
   ctask->sc, ctask->itt);
-   fail_command(conn, ctask, DID_BUS_BUSY << 16);
+   fail_command(conn, ctask, error << 16);
}
}
 
@@ -1573,7 +1585,7 @@ int iscsi_eh_device_reset(struct scsi_cmnd *sc)
/* need to grab the recv lock then session lock */
write_lock_bh(conn->recv_lock);
spin_lock(&session->lock);
-   fail_all_commands(conn, sc->device->lun);
+   fail_all_commands(conn, sc->device->lun, DID_ERROR);
conn

iscsi update

2008-01-31 Thread michaelc
The following patches were made over scsi-misc.

The bugs fixed are:

- Have qla4xxx hook into block/unblock code, and use new session
state to fail/requeue IO during transport problems.
- Hook qla4xxx into async scanning code. Qla4xxx looks more
like a normal old scsi card than a iscsi card. There is very
little iscsi stuff going on in the driver, so it is much
easier to just have this type of iscsi card work like other
FC and SPI cards. Currently distros are doing crazy things
to special case qla4xxx, so you can boot from it.
- Fix libiscsi nop timer setting, bad printks and
session age testing.



-
To unsubscribe from this list: send the line "unsubscribe linux-scsi" in
the body of a message to [EMAIL PROTECTED]
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATCH 1/2] scsi error: add target reset eh handler

2007-12-18 Thread michaelc
From: Mike Christie <[EMAIL PROTECTED]>

Drivers like qla4xxx and bnx2i (and it looks like some fcp drivers too),
want to be able to send a lun reset in the eh device handler and then a
target reset in some other handler. The old linux-iscsi driver, which did
the host per session like open-iscsi did the target reset in the host reset,
because the scsi command accounting that scsi_error.c does worked out
nicely for software iscsi, but does not work for hardware iscsi well.

This patch adds a eh_target_reset_handler any driver can use to send
a target reset.

The next patch will hook qla4xxx into it, and patches for iscsi_tcp/iser
and bnx2i will follow later when bnx2i is closer to getting merged.

Signed-off-by: Mike Christie <[EMAIL PROTECTED]>
---
 drivers/scsi/scsi_error.c |  121 ++---
 include/scsi/scsi_eh.h|1 +
 include/scsi/scsi_host.h  |1 +
 3 files changed, 105 insertions(+), 18 deletions(-)

diff --git a/drivers/scsi/scsi_error.c b/drivers/scsi/scsi_error.c
index 169bc59..fb1f5bc 100644
--- a/drivers/scsi/scsi_error.c
+++ b/drivers/scsi/scsi_error.c
@@ -524,6 +524,41 @@ static int scsi_try_bus_reset(struct scsi_cmnd *scmd)
return rtn;
 }
 
+static void __scsi_report_device_reset(struct scsi_device *sdev, void *data)
+{
+   sdev->was_reset = 1;
+   sdev->expecting_cc_ua = 1;
+}
+
+/**
+ * scsi_try_target_reset - Ask host to perform a target reset
+ * @scmd:  SCSI cmd used to send a target reset
+ *
+ * Notes:
+ *There is no timeout for this operation.  if this operation is
+ *unreliable for a given host, then the host itself needs to put a
+ *timer on it, and set the host back to a consistent state prior to
+ *returning.
+ */
+static int scsi_try_target_reset(struct scsi_cmnd *scmd)
+{
+   unsigned long flags;
+   int rtn;
+
+   if (!scmd->device->host->hostt->eh_target_reset_handler)
+   return FAILED;
+
+   rtn = scmd->device->host->hostt->eh_target_reset_handler(scmd);
+   if (rtn == SUCCESS) {
+   spin_lock_irqsave(scmd->device->host->host_lock, flags);
+   __starget_for_each_device(scsi_target(scmd->device), NULL,
+ __scsi_report_device_reset);
+   spin_unlock_irqrestore(scmd->device->host->host_lock, flags);
+   }
+
+   return rtn;
+}
+
 /**
  * scsi_try_bus_device_reset - Ask host to perform a BDR on a dev
  * @scmd:  SCSI cmd used to send BDR
@@ -542,11 +577,8 @@ static int scsi_try_bus_device_reset(struct scsi_cmnd 
*scmd)
return FAILED;
 
rtn = scmd->device->host->hostt->eh_device_reset_handler(scmd);
-   if (rtn == SUCCESS) {
-   scmd->device->was_reset = 1;
-   scmd->device->expecting_cc_ua = 1;
-   }
-
+   if (rtn == SUCCESS)
+   __scsi_report_device_reset(scmd->device, NULL);
return rtn;
 }
 
@@ -584,8 +616,9 @@ static void scsi_abort_eh_cmnd(struct scsi_cmnd *scmd)
 {
if (__scsi_try_to_abort_cmd(scmd) != SUCCESS)
if (scsi_try_bus_device_reset(scmd) != SUCCESS)
-   if (scsi_try_bus_reset(scmd) != SUCCESS)
-   scsi_try_host_reset(scmd);
+   if (scsi_try_target_reset(scmd) != SUCCESS)
+   if (scsi_try_bus_reset(scmd) != SUCCESS)
+   scsi_try_host_reset(scmd);
 }
 
 /**
@@ -1064,6 +1097,56 @@ static int scsi_eh_bus_device_reset(struct Scsi_Host 
*shost,
 }
 
 /**
+ * scsi_eh_target_reset - send target reset if needed
+ * @shost: scsi host being recovered.
+ * @work_q: &list_head for pending commands.
+ * @done_q:&list_head for processed commands.
+ *
+ * Notes:
+ *Try a target reset.
+ */
+static int scsi_eh_target_reset(struct Scsi_Host *shost,
+   struct list_head *work_q,
+   struct list_head *done_q)
+{
+   struct scsi_cmnd *scmd, *tgtr_scmd, *next;
+   unsigned int id;
+   int rtn;
+
+   for (id = 0; id <= shost->max_id; id++) {
+   tgtr_scmd = NULL;
+   list_for_each_entry(scmd, work_q, eh_entry) {
+   if (id == scmd_id(scmd)) {
+   tgtr_scmd = scmd;
+   break;
+   }
+   }
+   if (!tgtr_scmd)
+   continue;
+
+   SCSI_LOG_ERROR_RECOVERY(3, printk("%s: Sending target reset "
+ "to target %d\n",
+ current->comm, id));
+   rtn = scsi_try_target_reset(tgtr_scmd);
+   if (rtn == SUCCESS) {
+   list_for_each_entry_safe(scmd, next, work_q, eh_entry) {
+   if (id == scmd_id(scmd))
+   if (!scsi_de

[PATCH 2/2] qla4xxx: Add target reset functionality

2007-12-18 Thread michaelc
From: Mike Christie <[EMAIL PROTECTED]>

This patch adds target reset functionalty.

Signed-off-by: Mike Christie <[EMAIL PROTECTED]>
---
 drivers/scsi/qla4xxx/ql4_fw.h   |1 +
 drivers/scsi/qla4xxx/ql4_glbl.h |2 +
 drivers/scsi/qla4xxx/ql4_mbx.c  |   39 
 drivers/scsi/qla4xxx/ql4_os.c   |   74 ++-
 4 files changed, 107 insertions(+), 9 deletions(-)

diff --git a/drivers/scsi/qla4xxx/ql4_fw.h b/drivers/scsi/qla4xxx/ql4_fw.h
index fe415ec..ed8ee66 100644
--- a/drivers/scsi/qla4xxx/ql4_fw.h
+++ b/drivers/scsi/qla4xxx/ql4_fw.h
@@ -216,6 +216,7 @@ union external_hw_config_reg {
 #define MBOX_CMD_ABOUT_FW  0x0009
 #define MBOX_CMD_PING  0x000B
 #define MBOX_CMD_LUN_RESET 0x0016
+#define MBOX_CMD_TARGET_WARM_RESET 0x0017
 #define MBOX_CMD_GET_MANAGEMENT_DATA   0x001E
 #define MBOX_CMD_GET_FW_STATUS 0x001F
 #define MBOX_CMD_SET_ISNS_SERVICE  0x0021
diff --git a/drivers/scsi/qla4xxx/ql4_glbl.h b/drivers/scsi/qla4xxx/ql4_glbl.h
index a3608e0..b403a17 100644
--- a/drivers/scsi/qla4xxx/ql4_glbl.h
+++ b/drivers/scsi/qla4xxx/ql4_glbl.h
@@ -27,6 +27,8 @@ int qla4xxx_relogin_device(struct scsi_qla_host * ha,
   struct ddb_entry * ddb_entry);
 int qla4xxx_reset_lun(struct scsi_qla_host * ha, struct ddb_entry * ddb_entry,
  int lun);
+int qla4xxx_reset_target(struct scsi_qla_host * ha,
+struct ddb_entry * ddb_entry);
 int qla4xxx_get_flash(struct scsi_qla_host * ha, dma_addr_t dma_addr,
  uint32_t offset, uint32_t len);
 int qla4xxx_get_firmware_status(struct scsi_qla_host * ha);
diff --git a/drivers/scsi/qla4xxx/ql4_mbx.c b/drivers/scsi/qla4xxx/ql4_mbx.c
index 35cd73c..c577d79 100644
--- a/drivers/scsi/qla4xxx/ql4_mbx.c
+++ b/drivers/scsi/qla4xxx/ql4_mbx.c
@@ -713,6 +713,45 @@ int qla4xxx_reset_lun(struct scsi_qla_host * ha, struct 
ddb_entry * ddb_entry,
return status;
 }
 
+/**
+ * qla4xxx_reset_target - issues target Reset
+ * @ha: Pointer to host adapter structure.
+ * @db_entry: Pointer to device database entry
+ * @un_entry: Pointer to lun entry structure
+ *
+ * This routine performs a TARGET RESET on the specified target.
+ * The caller must ensure that the ddb_entry pointers
+ * are valid before calling this routine.
+ **/
+int qla4xxx_reset_target(struct scsi_qla_host *ha,
+struct ddb_entry *ddb_entry)
+{
+   uint32_t mbox_cmd[MBOX_REG_COUNT];
+   uint32_t mbox_sts[MBOX_REG_COUNT];
+   int status = QLA_SUCCESS;
+
+   DEBUG2(printk("scsi%ld:%d: target reset issued\n", ha->host_no,
+ ddb_entry->os_target_id));
+
+   /*
+* Send target reset command to ISP, so that the ISP will return all
+* outstanding requests with RESET status
+*/
+   memset(&mbox_cmd, 0, sizeof(mbox_cmd));
+   memset(&mbox_sts, 0, sizeof(mbox_sts));
+
+   mbox_cmd[0] = MBOX_CMD_TARGET_WARM_RESET;
+   mbox_cmd[1] = ddb_entry->fw_ddb_index;
+   mbox_cmd[5] = 0x01; /* Immediate Command Enable */
+
+   qla4xxx_mailbox_command(ha, MBOX_REG_COUNT, 1, &mbox_cmd[0],
+   &mbox_sts[0]);
+   if (mbox_sts[0] != MBOX_STS_COMMAND_COMPLETE &&
+   mbox_sts[0] != MBOX_STS_COMMAND_ERROR)
+   status = QLA_ERROR;
+
+   return status;
+}
 
 int qla4xxx_get_flash(struct scsi_qla_host * ha, dma_addr_t dma_addr,
  uint32_t offset, uint32_t len)
diff --git a/drivers/scsi/qla4xxx/ql4_os.c b/drivers/scsi/qla4xxx/ql4_os.c
index f55b9f7..05e6991 100644
--- a/drivers/scsi/qla4xxx/ql4_os.c
+++ b/drivers/scsi/qla4xxx/ql4_os.c
@@ -73,6 +73,7 @@ static void qla4xxx_recovery_timedout(struct 
iscsi_cls_session *session);
 static int qla4xxx_queuecommand(struct scsi_cmnd *cmd,
void (*done) (struct scsi_cmnd *));
 static int qla4xxx_eh_device_reset(struct scsi_cmnd *cmd);
+static int qla4xxx_eh_target_reset(struct scsi_cmnd *cmd);
 static int qla4xxx_eh_host_reset(struct scsi_cmnd *cmd);
 static int qla4xxx_slave_alloc(struct scsi_device *device);
 static int qla4xxx_slave_configure(struct scsi_device *device);
@@ -85,6 +86,7 @@ static struct scsi_host_template qla4xxx_driver_template = {
.queuecommand   = qla4xxx_queuecommand,
 
.eh_device_reset_handler = qla4xxx_eh_device_reset,
+   .eh_target_reset_handler = qla4xxx_eh_target_reset,
.eh_host_reset_handler  = qla4xxx_eh_host_reset,
 
.slave_configure= qla4xxx_slave_configure,
@@ -1506,7 +1508,7 @@ static int qla4xxx_wait_for_hba_online(struct 
scsi_qla_host *ha)
 }
 
 /**
- * qla4xxx_eh_wait_for_active_target_commands - wait for active cmds to finish.
+ * qla4xxx_eh_wait_for_commands - wait for active cmds to finish.
  * @ha: pointer to to HBA
  * @t: target id
  * @l: lun id
@@ -1514,20 +1516,

RFC: add target reset handler to scsi_error.c

2007-12-18 Thread michaelc
These patches add a target reset handler to scsi_error.c's error
handler. It is needed because drivers like qla4xxx either have to
do a target reset in the eh_device_reset_handler then do some
tricks so that when that handler is called again we do not send
extra resets, or the driver has to do its own loop in the bus
or host reset handler that loops over the host's targets and sends a
target reset for each target.

Patches were made over scsi-misc.


-
To unsubscribe from this list: send the line "unsubscribe linux-scsi" in
the body of a message to [EMAIL PROTECTED]
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATCH 04/24] iscsi_tcp, libiscsi: initial AHS Support

2007-12-13 Thread michaelc
From: Mike Christie <[EMAIL PROTECTED]>

  at libiscsi generic code
  - currently code assumes a storage space of pdu header is allocated
at llds ctask and is pointed to by iscsi_cmd_task->hdr. Here I add
a hdr_max field pertaining to that storage, and an hdr_len that
accumulates the current use of the pdu-header.

  - Add an iscsi_next_hdr() inline which returns the next free space
to write new Header at. Also iscsi_next_hdr() is used to retrieve
the address at which to write the header-digest.

  - Add iscsi_add_hdr(length). What the user do is calls iscsi_next_hdr()
for address of the new header, than calls iscsi_add_hdr(length) with
the size of the new header. iscsi_add_hdr() will check if space is
available and update to the new size. length must be padded according
to standard.

  - Add 2 padding inline helpers thanks to Olaf. Current patch does not
use them but Following patches will.
Also moved definition of ISCSI_PAD_LEN to iscsi_proto.h which had
PAD_WORD_LEN that was never used anywhere.

  - Let iscsi_prep_scsi_cmd_pdu() signal an Error return since now  it is
possible that it will fail.

  - I was tired of yet again writing a "this is a digest" comment next to
sizeof(__u32) so I defined a new ISCSI_DIGEST_SIZE. Now I don't need
any comments. Changed all places that used sizeof(__u32) or "4" in
connection to a digest.

  iscsi_tcp specific code
  - At struct iscsi_tcp_cmd_task allocate maximum space allowed in
standard for all headers following the iscsi_cmd header. and mark
it so in iscsi_tcp_session_create()
  - At iscsi_send_cmd_hdr() retrieve the correct headers size and
write header digest at iscsi_next_hdr().

Signed-off-by: Boaz Harrosh <[EMAIL PROTECTED]>
Acked-by: Olaf Kirch <[EMAIL PROTECTED]>
Signed-off-by: Mike Christie <[EMAIL PROTECTED]>
---
 drivers/scsi/iscsi_tcp.c   |   16 
 drivers/scsi/iscsi_tcp.h   |   13 +++--
 drivers/scsi/libiscsi.c|   41 +++--
 include/scsi/iscsi_proto.h |   10 +-
 include/scsi/libiscsi.h|   33 +++--
 5 files changed, 94 insertions(+), 19 deletions(-)

diff --git a/drivers/scsi/iscsi_tcp.c b/drivers/scsi/iscsi_tcp.c
index fd88777..491845f 100644
--- a/drivers/scsi/iscsi_tcp.c
+++ b/drivers/scsi/iscsi_tcp.c
@@ -113,7 +113,7 @@ iscsi_hdr_digest(struct iscsi_conn *conn, struct iscsi_buf 
*buf,
struct iscsi_tcp_conn *tcp_conn = conn->dd_data;
 
crypto_hash_digest(&tcp_conn->tx_hash, &buf->sg, buf->sg.length, crc);
-   buf->sg.length += sizeof(u32);
+   buf->sg.length += ISCSI_DIGEST_SIZE;
 }
 
 /*
@@ -220,6 +220,7 @@ static inline int
 iscsi_tcp_chunk_done(struct iscsi_chunk *chunk)
 {
static unsigned char padbuf[ISCSI_PAD_LEN];
+   unsigned int pad;
 
if (chunk->copied < chunk->size) {
iscsi_tcp_chunk_map(chunk);
@@ -243,10 +244,8 @@ iscsi_tcp_chunk_done(struct iscsi_chunk *chunk)
}
 
/* Do we need to handle padding? */
-   if (chunk->total_copied & (ISCSI_PAD_LEN-1)) {
-   unsigned int pad;
-
-   pad = ISCSI_PAD_LEN - (chunk->total_copied & (ISCSI_PAD_LEN-1));
+   pad = iscsi_padding(chunk->total_copied);
+   if (pad != 0) {
debug_tcp("consume %d pad bytes\n", pad);
chunk->total_size += pad;
chunk->size = pad;
@@ -1385,11 +1384,11 @@ iscsi_send_cmd_hdr(struct iscsi_conn *conn, struct 
iscsi_cmd_task *ctask)
}
 
iscsi_buf_init_iov(&tcp_ctask->headbuf, (char*)ctask->hdr,
- sizeof(struct iscsi_hdr));
+ ctask->hdr_len);
 
if (conn->hdrdgst_en)
iscsi_hdr_digest(conn, &tcp_ctask->headbuf,
-(u8*)tcp_ctask->hdrext);
+iscsi_next_hdr(ctask));
tcp_ctask->xmstate &= ~XMSTATE_CMD_HDR_INIT;
tcp_ctask->xmstate |= XMSTATE_CMD_HDR_XMIT;
}
@@ -2176,7 +2175,8 @@ iscsi_tcp_session_create(struct iscsi_transport *iscsit,
struct iscsi_cmd_task *ctask = session->cmds[cmd_i];
struct iscsi_tcp_cmd_task *tcp_ctask = ctask->dd_data;
 
-   ctask->hdr = &tcp_ctask->hdr;
+   ctask->hdr = &tcp_ctask->hdr.cmd_hdr;
+   ctask->hdr_max = sizeof(tcp_ctask->hdr) - ISCSI_DIGEST_SIZE;
}
 
for (cmd_i = 0; cmd_i < session->mgmtpool_max; cmd_i++) {
diff --git a/drivers/scsi/iscsi_tcp.h b/drivers/scsi/iscsi_tcp.h
index f1c5411..eb3784f 100644
--- a/drivers/scsi/iscsi_tcp.h
+++ b/drivers/scsi/iscsi_tcp.h
@@ -41,7 +41,6 @@
 #define XMSTATE_IMM_HDR_INIT   0x1000
 #define XMSTATE_SOL_HDR_INIT   0x2000
 
-#define ISCSI_PAD_LEN  4
 #define ISCSI_SG_TABLESIZE SG_ALL
 #define ISCSI_TCP_MAX_CMD_LEN

[PATCH 05/24] iser patching for AHS support

2007-12-13 Thread michaelc
From: Mike Christie <[EMAIL PROTECTED]>

from Boaz Harrosh <[EMAIL PROTECTED]>

  - The default initialization of hdr_max is the minimum -
sizeof(struct iscsi_cmd) - Once this patch goes into iser the default
initialization at libiscsi can be removed.
  - This is not yet full support for AHSs at iser end. But it should be easy.
Just allocate more space at iser_desc right after iscsi_hdr. Than
at transmission time use ctask->hdr_len to retrieve the total
size of all iscsi pdu headers. See previous patch at iscsi_tcp.[ch]

Signed-off-by: Boaz Harrosh <[EMAIL PROTECTED]>
Signed-off-by: Mike Christie <[EMAIL PROTECTED]>
---
 drivers/infiniband/ulp/iser/iscsi_iser.c |1 +
 drivers/scsi/libiscsi.c  |1 -
 2 files changed, 1 insertions(+), 1 deletions(-)

diff --git a/drivers/infiniband/ulp/iser/iscsi_iser.c 
b/drivers/infiniband/ulp/iser/iscsi_iser.c
index 2eadb6d..a2622f4 100644
--- a/drivers/infiniband/ulp/iser/iscsi_iser.c
+++ b/drivers/infiniband/ulp/iser/iscsi_iser.c
@@ -400,6 +400,7 @@ iscsi_iser_session_create(struct iscsi_transport *iscsit,
ctask  = session->cmds[i];
iser_ctask = ctask->dd_data;
ctask->hdr = (struct iscsi_cmd *)&iser_ctask->desc.iscsi_header;
+   ctask->hdr_max = sizeof(iser_ctask->desc.iscsi_header);
}
 
for (i = 0; i < session->mgmtpool_max; i++) {
diff --git a/drivers/scsi/libiscsi.c b/drivers/scsi/libiscsi.c
index 0d7914f..5936586 100644
--- a/drivers/scsi/libiscsi.c
+++ b/drivers/scsi/libiscsi.c
@@ -1570,7 +1570,6 @@ iscsi_session_setup(struct iscsi_transport *iscsit,
if (cmd_task_size)
ctask->dd_data = &ctask[1];
ctask->itt = cmd_i;
-   ctask->hdr_max = sizeof(struct iscsi_cmd);
INIT_LIST_HEAD(&ctask->running);
}
 
-- 
1.5.1.2

-
To unsubscribe from this list: send the line "unsubscribe linux-scsi" in
the body of a message to [EMAIL PROTECTED]
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATCH 03/24] Prettify resid handling and some extra checks

2007-12-13 Thread michaelc
From: Mike Christie <[EMAIL PROTECTED]>

from Boaz Harrosh:
  - Check to see that OVERFLOW is not negative indicating
a bug.
  - Unify handling of UNDERFLOW and OVERFLOW to the same
code.
  - Also handle BIDI_OVERFLOW.

Signed-off-by: Boaz Harrosh <[EMAIL PROTECTED]>
Signed-off-by: Mike Christie <[EMAIL PROTECTED]>
---
 drivers/scsi/iscsi_tcp.c |   16 +++-
 drivers/scsi/libiscsi.c  |   12 +++-
 2 files changed, 14 insertions(+), 14 deletions(-)

diff --git a/drivers/scsi/iscsi_tcp.c b/drivers/scsi/iscsi_tcp.c
index 1b540e0..fd88777 100644
--- a/drivers/scsi/iscsi_tcp.c
+++ b/drivers/scsi/iscsi_tcp.c
@@ -507,22 +507,20 @@ iscsi_data_rsp(struct iscsi_conn *conn, struct 
iscsi_cmd_task *ctask)
}
 
if (rhdr->flags & ISCSI_FLAG_DATA_STATUS) {
+   sc->result = (DID_OK << 16) | rhdr->cmd_status;
conn->exp_statsn = be32_to_cpu(rhdr->statsn) + 1;
-   if (rhdr->flags & ISCSI_FLAG_DATA_UNDERFLOW) {
+   if (rhdr->flags & (ISCSI_FLAG_DATA_UNDERFLOW |
+  ISCSI_FLAG_DATA_OVERFLOW)) {
int res_count = be32_to_cpu(rhdr->residual_count);
 
if (res_count > 0 &&
-   res_count <= scsi_bufflen(sc)) {
+   (rhdr->flags & ISCSI_FLAG_CMD_OVERFLOW ||
+res_count <= scsi_bufflen(sc)))
scsi_set_resid(sc, res_count);
-   sc->result = (DID_OK << 16) | rhdr->cmd_status;
-   } else
+   else
sc->result = (DID_BAD_TARGET << 16) |
rhdr->cmd_status;
-   } else if (rhdr->flags & ISCSI_FLAG_DATA_OVERFLOW) {
-   scsi_set_resid(sc, be32_to_cpu(rhdr->residual_count));
-   sc->result = (DID_OK << 16) | rhdr->cmd_status;
-   } else
-   sc->result = (DID_OK << 16) | rhdr->cmd_status;
+   }
}
 
conn->datain_pdus_cnt++;
diff --git a/drivers/scsi/libiscsi.c b/drivers/scsi/libiscsi.c
index 176458f..0beb4c6 100644
--- a/drivers/scsi/libiscsi.c
+++ b/drivers/scsi/libiscsi.c
@@ -291,17 +291,19 @@ invalid_datalen:
   min_t(uint16_t, senselen, SCSI_SENSE_BUFFERSIZE));
}
 
-   if (rhdr->flags & ISCSI_FLAG_CMD_UNDERFLOW) {
+   if (rhdr->flags & (ISCSI_FLAG_CMD_UNDERFLOW |
+  ISCSI_FLAG_CMD_OVERFLOW)) {
int res_count = be32_to_cpu(rhdr->residual_count);
 
-   if (res_count > 0 && res_count <= scsi_bufflen(sc))
+   if (res_count > 0 &&
+   (rhdr->flags & ISCSI_FLAG_CMD_OVERFLOW ||
+res_count <= scsi_bufflen(sc)))
scsi_set_resid(sc, res_count);
else
sc->result = (DID_BAD_TARGET << 16) | rhdr->cmd_status;
-   } else if (rhdr->flags & ISCSI_FLAG_CMD_BIDI_UNDERFLOW)
+   } else if (rhdr->flags & (ISCSI_FLAG_CMD_BIDI_UNDERFLOW |
+ ISCSI_FLAG_CMD_BIDI_OVERFLOW))
sc->result = (DID_BAD_TARGET << 16) | rhdr->cmd_status;
-   else if (rhdr->flags & ISCSI_FLAG_CMD_OVERFLOW)
-   scsi_set_resid(sc, be32_to_cpu(rhdr->residual_count));
 
 out:
debug_scsi("done [sc %lx res %d itt 0x%x]\n",
-- 
1.5.1.2

-
To unsubscribe from this list: send the line "unsubscribe linux-scsi" in
the body of a message to [EMAIL PROTECTED]
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATCH 06/24] libiscsi, iscsi_tcp: iscsi pool cleanup

2007-12-13 Thread michaelc
From: Mike Christie <[EMAIL PROTECTED]>

from [EMAIL PROTECTED]

iscsi_pool_init simplified

iscsi_pool_init currently has a lot of duplicate kfree() calls it does
when some allocation fails. This patch simplifies the code a little by
using iscsi_pool_free to tear down the pool in case of an error.

iscsi_pool_init also returns a copy of the item array to the caller.
Not all callers use this array, so we make it optional.

Instead of allocating a second array and return that, allocate just one
array, of twice the size.

Update users of iscsi_pool_{init,free}

This patch drops the (now useless) second argument to
iscsi_pool_free, and updates all callers.

It also removes the ctask->r2ts array, which was never
used anyway. Since the items argument to iscsi_pool_init
is now optional, we can pass NULL instead.

Signed-off-by: Olaf Kirch <[EMAIL PROTECTED]>
Signed-off-by: Mike Christie <[EMAIL PROTECTED]>
---
 drivers/scsi/iscsi_tcp.c |   12 ++-
 drivers/scsi/iscsi_tcp.h |3 +-
 drivers/scsi/libiscsi.c  |   75 -
 include/scsi/libiscsi.h  |   10 +++---
 4 files changed, 50 insertions(+), 50 deletions(-)

diff --git a/drivers/scsi/iscsi_tcp.c b/drivers/scsi/iscsi_tcp.c
index 491845f..f79a457 100644
--- a/drivers/scsi/iscsi_tcp.c
+++ b/drivers/scsi/iscsi_tcp.c
@@ -1998,8 +1998,7 @@ iscsi_r2tpool_alloc(struct iscsi_session *session)
 */
 
/* R2T pool */
-   if (iscsi_pool_init(&tcp_ctask->r2tpool, session->max_r2t * 4,
-   (void***)&tcp_ctask->r2ts,
+   if (iscsi_pool_init(&tcp_ctask->r2tpool, session->max_r2t * 4, 
NULL,
sizeof(struct iscsi_r2t_info))) {
goto r2t_alloc_fail;
}
@@ -2008,8 +2007,7 @@ iscsi_r2tpool_alloc(struct iscsi_session *session)
tcp_ctask->r2tqueue = kfifo_alloc(
  session->max_r2t * 4 * sizeof(void*), GFP_KERNEL, NULL);
if (tcp_ctask->r2tqueue == ERR_PTR(-ENOMEM)) {
-   iscsi_pool_free(&tcp_ctask->r2tpool,
-   (void**)tcp_ctask->r2ts);
+   iscsi_pool_free(&tcp_ctask->r2tpool);
goto r2t_alloc_fail;
}
}
@@ -2022,8 +2020,7 @@ r2t_alloc_fail:
struct iscsi_tcp_cmd_task *tcp_ctask = ctask->dd_data;
 
kfifo_free(tcp_ctask->r2tqueue);
-   iscsi_pool_free(&tcp_ctask->r2tpool,
-   (void**)tcp_ctask->r2ts);
+   iscsi_pool_free(&tcp_ctask->r2tpool);
}
return -ENOMEM;
 }
@@ -2038,8 +2035,7 @@ iscsi_r2tpool_free(struct iscsi_session *session)
struct iscsi_tcp_cmd_task *tcp_ctask = ctask->dd_data;
 
kfifo_free(tcp_ctask->r2tqueue);
-   iscsi_pool_free(&tcp_ctask->r2tpool,
-   (void**)tcp_ctask->r2ts);
+   iscsi_pool_free(&tcp_ctask->r2tpool);
}
 }
 
diff --git a/drivers/scsi/iscsi_tcp.h b/drivers/scsi/iscsi_tcp.h
index eb3784f..d49d876 100644
--- a/drivers/scsi/iscsi_tcp.h
+++ b/drivers/scsi/iscsi_tcp.h
@@ -175,9 +175,8 @@ struct iscsi_tcp_cmd_task {
uint32_texp_datasn; /* expected target's 
R2TSN/DataSN */
int data_offset;
struct iscsi_r2t_info   *r2t;   /* in progress R2T*/
-   struct iscsi_queue  r2tpool;
+   struct iscsi_pool   r2tpool;
struct kfifo*r2tqueue;
-   struct iscsi_r2t_info   **r2ts;
int digest_count;
uint32_timmdigest;  /* for imm data */
struct iscsi_bufimmbuf; /* for imm data digest 
*/
diff --git a/drivers/scsi/libiscsi.c b/drivers/scsi/libiscsi.c
index 5936586..d43f909 100644
--- a/drivers/scsi/libiscsi.c
+++ b/drivers/scsi/libiscsi.c
@@ -1413,59 +1413,64 @@ done:
 }
 EXPORT_SYMBOL_GPL(iscsi_eh_device_reset);
 
+/*
+ * Pre-allocate a pool of @max items of @item_size. By default, the pool
+ * should be accessed via kfifo_{get,put} on q->queue.
+ * Optionally, the caller can obtain the array of object pointers
+ * by passing in a non-NULL @items pointer
+ */
 int
-iscsi_pool_init(struct iscsi_queue *q, int max, void ***items, int item_size)
+iscsi_pool_init(struct iscsi_pool *q, int max, void ***items, int item_size)
 {
-   int i;
+   int i, num_arrays = 1;
 
-   *items = kmalloc(max * sizeof(void*), GFP_KERNEL);
-   if (*items == NULL)
-   return -ENOMEM;
+   memset(q, 0, sizeof(*q));
 
q->max = max;
-   q->pool = kmalloc(max * sizeof(void*), GFP_KERNEL);
-   if (q->pool == NULL) {
-   kfree(*items);
-   return -ENOMEM;
-   }
+
+   /* If the user passed an items pointer, he wants a copy of
+* the array. */
+

[PATCH 02/24] iscsi_tcp: rewrite recv path

2007-12-13 Thread michaelc
From: Mike Christie <[EMAIL PROTECTED]>

>From Olaf Kirch:

Rewrite recv path. Fixes:
- data digest processing and error handling.
- ahs support.

Some fixups by Mike Christie

Signed-off-by: [EMAIL PROTECTED]
Signed-off-by: Mike Christie <[EMAIL PROTECTED]>
---
 drivers/scsi/iscsi_tcp.c | 1018 +++---
 drivers/scsi/iscsi_tcp.h |   66 ++--
 include/scsi/libiscsi.h  |4 +
 3 files changed, 552 insertions(+), 536 deletions(-)

diff --git a/drivers/scsi/iscsi_tcp.c b/drivers/scsi/iscsi_tcp.c
index 4b226b8..1b540e0 100644
--- a/drivers/scsi/iscsi_tcp.c
+++ b/drivers/scsi/iscsi_tcp.c
@@ -48,7 +48,7 @@ MODULE_AUTHOR("Dmitry Yusupov <[EMAIL PROTECTED]>, "
  "Alex Aizman <[EMAIL PROTECTED]>");
 MODULE_DESCRIPTION("iSCSI/TCP data-path");
 MODULE_LICENSE("GPL");
-/* #define DEBUG_TCP */
+#undef DEBUG_TCP
 #define DEBUG_ASSERT
 
 #ifdef DEBUG_TCP
@@ -67,10 +67,15 @@ MODULE_LICENSE("GPL");
 static unsigned int iscsi_max_lun = 512;
 module_param_named(max_lun, iscsi_max_lun, uint, S_IRUGO);
 
+static int iscsi_tcp_hdr_recv_done(struct iscsi_tcp_conn *tcp_conn,
+  struct iscsi_chunk *chunk);
+
 static inline void
 iscsi_buf_init_iov(struct iscsi_buf *ibuf, char *vbuf, int size)
 {
-   sg_init_one(&ibuf->sg, vbuf, size);
+   ibuf->sg.page = virt_to_page(vbuf);
+   ibuf->sg.offset = offset_in_page(vbuf);
+   ibuf->sg.length = size;
ibuf->sent = 0;
ibuf->use_sendmsg = 1;
 }
@@ -78,12 +83,13 @@ iscsi_buf_init_iov(struct iscsi_buf *ibuf, char *vbuf, int 
size)
 static inline void
 iscsi_buf_init_sg(struct iscsi_buf *ibuf, struct scatterlist *sg)
 {
-   sg_init_table(&ibuf->sg, 1);
-   sg_set_page(&ibuf->sg, sg_page(sg), sg->length, sg->offset);
+   ibuf->sg.page = sg->page;
+   ibuf->sg.offset = sg->offset;
+   ibuf->sg.length = sg->length;
/*
 * Fastpath: sg element fits into single page
 */
-   if (sg->length + sg->offset <= PAGE_SIZE && !PageSlab(sg_page(sg)))
+   if (sg->length + sg->offset <= PAGE_SIZE && !PageSlab(sg->page))
ibuf->use_sendmsg = 0;
else
ibuf->use_sendmsg = 1;
@@ -110,72 +116,331 @@ iscsi_hdr_digest(struct iscsi_conn *conn, struct 
iscsi_buf *buf,
buf->sg.length += sizeof(u32);
 }
 
+/*
+ * Scatterlist handling: inside the iscsi_chunk, we
+ * remember an index into the scatterlist, and set data/size
+ * to the current scatterlist entry. For highmem pages, we
+ * kmap as needed.
+ *
+ * Note that the page is unmapped when we return from
+ * TCP's data_ready handler, so we may end up mapping and
+ * unmapping the same page repeatedly. The whole reason
+ * for this is that we shouldn't keep the page mapped
+ * outside the softirq.
+ */
+
+/**
+ * iscsi_tcp_chunk_init_sg - init indicated scatterlist entry
+ * @chunk: the buffer object
+ * @idx: index into scatterlist
+ * @offset: byte offset into that sg entry
+ *
+ * This function sets up the chunk so that subsequent
+ * data is copied to the indicated sg entry, at the given
+ * offset.
+ */
+static inline void
+iscsi_tcp_chunk_init_sg(struct iscsi_chunk *chunk,
+   unsigned int idx, unsigned int offset)
+{
+   struct scatterlist *sg;
+
+   BUG_ON(chunk->sg == NULL);
+
+   sg = &chunk->sg[idx];
+   chunk->sg_index = idx;
+   chunk->sg_offset = offset;
+   chunk->size = min(sg->length - offset, chunk->total_size);
+   chunk->data = NULL;
+}
+
+/**
+ * iscsi_tcp_chunk_map - map the current S/G page
+ * @chunk: iscsi chunk
+ *
+ * We only need to possibly kmap data if scatter lists are being used,
+ * because the iscsi passthrough and internal IO paths will never use high
+ * mem pages.
+ */
+static inline void
+iscsi_tcp_chunk_map(struct iscsi_chunk *chunk)
+{
+   struct scatterlist *sg;
+
+   if (chunk->data != NULL || !chunk->sg)
+   return;
+
+   sg = &chunk->sg[chunk->sg_index];
+   BUG_ON(chunk->sg_mapped);
+   BUG_ON(sg->length == 0);
+   chunk->sg_mapped = kmap_atomic(sg->page, KM_SOFTIRQ0);
+   chunk->data = chunk->sg_mapped + sg->offset + chunk->sg_offset;
+}
+
+static inline void
+iscsi_tcp_chunk_unmap(struct iscsi_chunk *chunk)
+{
+   if (chunk->sg_mapped) {
+   kunmap_atomic(chunk->sg_mapped, KM_SOFTIRQ0);
+   chunk->sg_mapped = NULL;
+   chunk->data = NULL;
+   }
+}
+
+/*
+ * Splice the digest buffer into the buffer
+ */
+static inline void
+iscsi_tcp_chunk_splice_digest(struct iscsi_chunk *chunk, void *digest)
+{
+   chunk->data = digest;
+   chunk->digest_len = ISCSI_DIGEST_SIZE;
+   chunk->total_size += ISCSI_DIGEST_SIZE;
+   chunk->size = ISCSI_DIGEST_SIZE;
+   chunk->copied = 0;
+   chunk->sg = NULL;
+   chunk->sg_index = 0;
+   chunk->hash = NULL;
+}
+
+/**
+ * iscsi_tcp_chunk_done - check whether the chunk is complete
+ * @chunk: iscsi chunk to check
+ *
+ * Check 

[PATCH 17/24] iscsi_tcp: stop leaking r2t_info's when the incoming R2T is bad

2007-12-13 Thread michaelc
From: Mike Christie <[EMAIL PROTECTED]>

from [EMAIL PROTECTED]:

iscsi_r2t_rsp checks the incoming R2T for sanity, and if it
thinks it's fishy, it will drop it silently. In this case, we
leaked an r2t_info object. If we do this often enough, we run
into a BUG_ON some time later.

Removed r2t wrappers and update patch by Mike Christie

Signed-off-by: Olaf Kirch <[EMAIL PROTECTED]>
Signed-off-by: Mike Christie <[EMAIL PROTECTED]>
---
 drivers/scsi/iscsi_tcp.c |6 +-
 1 files changed, 5 insertions(+), 1 deletions(-)

diff --git a/drivers/scsi/iscsi_tcp.c b/drivers/scsi/iscsi_tcp.c
index 7212fe9..ecba606 100644
--- a/drivers/scsi/iscsi_tcp.c
+++ b/drivers/scsi/iscsi_tcp.c
@@ -658,6 +658,8 @@ iscsi_r2t_rsp(struct iscsi_conn *conn, struct 
iscsi_cmd_task *ctask)
r2t->data_length = be32_to_cpu(rhdr->data_length);
if (r2t->data_length == 0) {
printk(KERN_ERR "iscsi_tcp: invalid R2T with zero data len\n");
+   __kfifo_put(tcp_ctask->r2tpool.queue, (void*)&r2t,
+   sizeof(void*));
spin_unlock(&session->lock);
return ISCSI_ERR_DATALEN;
}
@@ -669,10 +671,12 @@ iscsi_r2t_rsp(struct iscsi_conn *conn, struct 
iscsi_cmd_task *ctask)
 
r2t->data_offset = be32_to_cpu(rhdr->data_offset);
if (r2t->data_offset + r2t->data_length > scsi_bufflen(ctask->sc)) {
-   spin_unlock(&session->lock);
printk(KERN_ERR "iscsi_tcp: invalid R2T with data len %u at "
   "offset %u and total length %d\n", r2t->data_length,
   r2t->data_offset, scsi_bufflen(ctask->sc));
+   __kfifo_put(tcp_ctask->r2tpool.queue, (void*)&r2t,
+   sizeof(void*));
+   spin_unlock(&session->lock);
return ISCSI_ERR_DATALEN;
}
 
-- 
1.5.1.2

-
To unsubscribe from this list: send the line "unsubscribe linux-scsi" in
the body of a message to [EMAIL PROTECTED]
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATCH 24/24] iscsi class: bump version

2007-12-13 Thread michaelc
From: Mike Christie <[EMAIL PROTECTED]>

Update version.

Signed-off-by: Mike Christie <[EMAIL PROTECTED]>
---
 drivers/scsi/scsi_transport_iscsi.c |2 +-
 1 files changed, 1 insertions(+), 1 deletions(-)

diff --git a/drivers/scsi/scsi_transport_iscsi.c 
b/drivers/scsi/scsi_transport_iscsi.c
index 3585599..ef0e742 100644
--- a/drivers/scsi/scsi_transport_iscsi.c
+++ b/drivers/scsi/scsi_transport_iscsi.c
@@ -33,7 +33,7 @@
 #define ISCSI_SESSION_ATTRS 18
 #define ISCSI_CONN_ATTRS 11
 #define ISCSI_HOST_ATTRS 4
-#define ISCSI_TRANSPORT_VERSION "2.0-724"
+#define ISCSI_TRANSPORT_VERSION "2.0-867"
 
 struct iscsi_internal {
int daemon_pid;
-- 
1.5.1.2

-
To unsubscribe from this list: send the line "unsubscribe linux-scsi" in
the body of a message to [EMAIL PROTECTED]
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATCH 22/24] libiscsi: use is_power_of_2

2007-12-13 Thread michaelc
From: Mike Christie <[EMAIL PROTECTED]>

Patch from vignesh babu <[EMAIL PROTECTED]>:

Replacing n & (n - 1) for power of 2 check by is_power_of_2(n)

Signed-off-by: vignesh babu <[EMAIL PROTECTED]>
Signed-off-by: Mike Christie <[EMAIL PROTECTED]>
---
 drivers/scsi/libiscsi.c |3 ++-
 1 files changed, 2 insertions(+), 1 deletions(-)

diff --git a/drivers/scsi/libiscsi.c b/drivers/scsi/libiscsi.c
index 6573223..553168a 100644
--- a/drivers/scsi/libiscsi.c
+++ b/drivers/scsi/libiscsi.c
@@ -24,6 +24,7 @@
 #include 
 #include 
 #include 
+#include 
 #include 
 #include 
 #include 
@@ -1700,7 +1701,7 @@ iscsi_session_setup(struct iscsi_transport *iscsit,
qdepth = ISCSI_DEF_CMD_PER_LUN;
}
 
-   if (cmds_max < 2 || (cmds_max & (cmds_max - 1)) ||
+   if (!is_power_of_2(cmds_max) ||
cmds_max >= ISCSI_MGMT_ITT_OFFSET) {
if (cmds_max != 0)
printk(KERN_ERR "iscsi: invalid can_queue of %d. "
-- 
1.5.1.2

-
To unsubscribe from this list: send the line "unsubscribe linux-scsi" in
the body of a message to [EMAIL PROTECTED]
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATCH 23/24] iscsi_tcp: fix setting of r2t

2007-12-13 Thread michaelc
From: Mike Christie <[EMAIL PROTECTED]>

If we negotiate for X r2ts we have to use only X r2ts. We cannot
round up (we could send less though). It is ok to fail if it
is not something the driver can handle, so this patch just does
that.

Signed-off-by: Mike Christie <[EMAIL PROTECTED]>
---
 drivers/scsi/iscsi_tcp.c |6 +++---
 1 files changed, 3 insertions(+), 3 deletions(-)

diff --git a/drivers/scsi/iscsi_tcp.c b/drivers/scsi/iscsi_tcp.c
index edebdf2..e5be5fd 100644
--- a/drivers/scsi/iscsi_tcp.c
+++ b/drivers/scsi/iscsi_tcp.c
@@ -1774,12 +1774,12 @@ iscsi_conn_set_param(struct iscsi_cls_conn *cls_conn, 
enum iscsi_param param,
break;
case ISCSI_PARAM_MAX_R2T:
sscanf(buf, "%d", &value);
-   if (session->max_r2t == roundup_pow_of_two(value))
+   if (value <= 0 || !is_power_of_2(value))
+   return -EINVAL;
+   if (session->max_r2t == value)
break;
iscsi_r2tpool_free(session);
iscsi_set_param(cls_conn, param, buf, buflen);
-   if (session->max_r2t & (session->max_r2t - 1))
-   session->max_r2t = roundup_pow_of_two(session->max_r2t);
if (iscsi_r2tpool_alloc(session))
return -ENOMEM;
break;
-- 
1.5.1.2

-
To unsubscribe from this list: send the line "unsubscribe linux-scsi" in
the body of a message to [EMAIL PROTECTED]
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATCH 12/24] iscsi_tcp: update the website URL

2007-12-13 Thread michaelc
From: FUJITA Tomonori <[EMAIL PROTECTED]>

Use open-iscsi.org instead of linux-iscsi.sf.net, which hasn't been
updated for ages.

Signed-off-by: FUJITA Tomonori <[EMAIL PROTECTED]>
Signed-off-by: Mike Christie <[EMAIL PROTECTED]>
---
 drivers/scsi/Kconfig |2 +-
 1 files changed, 1 insertions(+), 1 deletions(-)

diff --git a/drivers/scsi/Kconfig b/drivers/scsi/Kconfig
index becbb09..4c7e99f 100644
--- a/drivers/scsi/Kconfig
+++ b/drivers/scsi/Kconfig
@@ -341,7 +341,7 @@ config ISCSI_TCP
 The userspace component needed to initialize the driver, documentation,
 and sample configuration files can be found here:
 
-http://linux-iscsi.sf.net
+http://open-iscsi.org
 
 config SGIWD93_SCSI
tristate "SGI WD93C93 SCSI Driver"
-- 
1.5.1.2

-
To unsubscribe from this list: send the line "unsubscribe linux-scsi" in
the body of a message to [EMAIL PROTECTED]
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATCH 20/24] iscsi_tcp: enable sg chaining

2007-12-13 Thread michaelc
From: Mike Christie <[EMAIL PROTECTED]>

The previous patches converted iscsi_tcp to support sg chaining.
This patch sets the proper flags and sets sg_table size to
4096. This allows fs io to be capped at max_sectors, but passthrough
IO to be limited by some other part of the kernel.

Signed-off-by: Mike Christie <[EMAIL PROTECTED]>
---
 drivers/scsi/iscsi_tcp.c |5 +++--
 drivers/scsi/iscsi_tcp.h |3 ---
 2 files changed, 3 insertions(+), 5 deletions(-)

diff --git a/drivers/scsi/iscsi_tcp.c b/drivers/scsi/iscsi_tcp.c
index 65df908..84c4a50 100644
--- a/drivers/scsi/iscsi_tcp.c
+++ b/drivers/scsi/iscsi_tcp.c
@@ -1928,13 +1928,14 @@ static struct scsi_host_template iscsi_sht = {
.queuecommand   = iscsi_queuecommand,
.change_queue_depth = iscsi_change_queue_depth,
.can_queue  = ISCSI_DEF_XMIT_CMDS_MAX - 1,
-   .sg_tablesize   = ISCSI_SG_TABLESIZE,
+   .sg_tablesize   = 4096,
.max_sectors= 0x,
.cmd_per_lun= ISCSI_DEF_CMD_PER_LUN,
.eh_abort_handler   = iscsi_eh_abort,
.eh_device_reset_handler= iscsi_eh_device_reset,
.eh_host_reset_handler  = iscsi_eh_host_reset,
.use_clustering = DISABLE_CLUSTERING,
+   .use_sg_chaining= ENABLE_SG_CHAINING,
.slave_configure= iscsi_tcp_slave_configure,
.proc_name  = "iscsi_tcp",
.this_id= -1,
@@ -1974,7 +1975,7 @@ static struct iscsi_transport iscsi_tcp_transport = {
.host_template  = &iscsi_sht,
.conndata_size  = sizeof(struct iscsi_conn),
.max_conn   = 1,
-   .max_cmd_len= ISCSI_TCP_MAX_CMD_LEN,
+   .max_cmd_len= 16,
/* session management */
.create_session = iscsi_tcp_session_create,
.destroy_session= iscsi_tcp_session_destroy,
diff --git a/drivers/scsi/iscsi_tcp.h b/drivers/scsi/iscsi_tcp.h
index 893cd2e..ed0b991 100644
--- a/drivers/scsi/iscsi_tcp.h
+++ b/drivers/scsi/iscsi_tcp.h
@@ -24,9 +24,6 @@
 
 #include 
 
-#define ISCSI_SG_TABLESIZE SG_ALL
-#define ISCSI_TCP_MAX_CMD_LEN  16
-
 struct crypto_hash;
 struct socket;
 struct iscsi_tcp_conn;
-- 
1.5.1.2

-
To unsubscribe from this list: send the line "unsubscribe linux-scsi" in
the body of a message to [EMAIL PROTECTED]
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATCH 21/24] iscsi_tcp: hold lock during data rsp processing

2007-12-13 Thread michaelc
From: Mike Christie <[EMAIL PROTECTED]>

iscsi_data_rsp needs to hold the sesison lock when it calls
iscsi_update_cmdsn.

Signed-off-by: Mike Christie <[EMAIL PROTECTED]>
---
 drivers/scsi/iscsi_tcp.c |   14 ++
 1 files changed, 6 insertions(+), 8 deletions(-)

diff --git a/drivers/scsi/iscsi_tcp.c b/drivers/scsi/iscsi_tcp.c
index 84c4a50..edebdf2 100644
--- a/drivers/scsi/iscsi_tcp.c
+++ b/drivers/scsi/iscsi_tcp.c
@@ -641,13 +641,11 @@ iscsi_r2t_rsp(struct iscsi_conn *conn, struct 
iscsi_cmd_task *ctask)
}
 
/* fill-in new R2T associated with the task */
-   spin_lock(&session->lock);
iscsi_update_cmdsn(session, (struct iscsi_nopin*)rhdr);
 
if (!ctask->sc || session->state != ISCSI_STATE_LOGGED_IN) {
printk(KERN_INFO "iscsi_tcp: dropping R2T itt %d in "
   "recovery...\n", ctask->itt);
-   spin_unlock(&session->lock);
return 0;
}
 
@@ -660,7 +658,6 @@ iscsi_r2t_rsp(struct iscsi_conn *conn, struct 
iscsi_cmd_task *ctask)
printk(KERN_ERR "iscsi_tcp: invalid R2T with zero data len\n");
__kfifo_put(tcp_ctask->r2tpool.queue, (void*)&r2t,
sizeof(void*));
-   spin_unlock(&session->lock);
return ISCSI_ERR_DATALEN;
}
 
@@ -676,7 +673,6 @@ iscsi_r2t_rsp(struct iscsi_conn *conn, struct 
iscsi_cmd_task *ctask)
   r2t->data_offset, scsi_bufflen(ctask->sc));
__kfifo_put(tcp_ctask->r2tpool.queue, (void*)&r2t,
sizeof(void*));
-   spin_unlock(&session->lock);
return ISCSI_ERR_DATALEN;
}
 
@@ -690,8 +686,6 @@ iscsi_r2t_rsp(struct iscsi_conn *conn, struct 
iscsi_cmd_task *ctask)
conn->r2t_pdus_cnt++;
 
iscsi_requeue_ctask(ctask);
-   spin_unlock(&session->lock);
-
return 0;
 }
 
@@ -764,7 +758,9 @@ iscsi_tcp_hdr_dissect(struct iscsi_conn *conn, struct 
iscsi_hdr *hdr)
switch(opcode) {
case ISCSI_OP_SCSI_DATA_IN:
ctask = session->cmds[itt];
+   spin_lock(&conn->session->lock);
rc = iscsi_data_rsp(conn, ctask);
+   spin_unlock(&conn->session->lock);
if (rc)
return rc;
if (tcp_conn->in.datalen) {
@@ -806,9 +802,11 @@ iscsi_tcp_hdr_dissect(struct iscsi_conn *conn, struct 
iscsi_hdr *hdr)
ctask = session->cmds[itt];
if (ahslen)
rc = ISCSI_ERR_AHSLEN;
-   else if (ctask->sc->sc_data_direction == DMA_TO_DEVICE)
+   else if (ctask->sc->sc_data_direction == DMA_TO_DEVICE) {
+   spin_lock(&session->lock);
rc = iscsi_r2t_rsp(conn, ctask);
-   else
+   spin_unlock(&session->lock);
+   } else
rc = ISCSI_ERR_PROTO;
break;
case ISCSI_OP_LOGIN_RSP:
-- 
1.5.1.2

-
To unsubscribe from this list: send the line "unsubscribe linux-scsi" in
the body of a message to [EMAIL PROTECTED]
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATCH 18/24] iscsi_tcp: drop session when itt does not match any command

2007-12-13 Thread michaelc
From: Mike Christie <[EMAIL PROTECTED]>

A target should never send us a itt that does not match a running
task. If it does we do not really know what is coming down after the header,
unless we evaluate the hdr and do some guessing sometimes. However,
even if we know what is coming we probably do not have buffers for it or we
cannot respond (if it is a r2t for example), so just drop the session.

Signed-off-by: Mike Christie <[EMAIL PROTECTED]>
---
 drivers/scsi/iscsi_tcp.c |6 +-
 1 files changed, 1 insertions(+), 5 deletions(-)

diff --git a/drivers/scsi/iscsi_tcp.c b/drivers/scsi/iscsi_tcp.c
index ecba606..65df908 100644
--- a/drivers/scsi/iscsi_tcp.c
+++ b/drivers/scsi/iscsi_tcp.c
@@ -755,11 +755,7 @@ iscsi_tcp_hdr_dissect(struct iscsi_conn *conn, struct 
iscsi_hdr *hdr)
opcode = hdr->opcode & ISCSI_OPCODE_MASK;
/* verify itt (itt encoding: age+cid+itt) */
rc = iscsi_verify_itt(conn, hdr, &itt);
-   if (rc == ISCSI_ERR_NO_SCSI_CMD) {
-   /* XXX: what does this do? */
-   tcp_conn->in.datalen = 0; /* force drop */
-   return 0;
-   } else if (rc)
+   if (rc)
return rc;
 
debug_tcp("opcode 0x%x ahslen %d datalen %d\n",
-- 
1.5.1.2

-
To unsubscribe from this list: send the line "unsubscribe linux-scsi" in
the body of a message to [EMAIL PROTECTED]
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATCH 19/24] libiscsi, iscsi class: set tmf to a safe default and export in sysfs

2007-12-13 Thread michaelc
From: Mike Christie <[EMAIL PROTECTED]>

Older tools will not be setting the tmf time outs since they
did not exists, so set them to a safe default.

And export abort and lu reset timeout values in sysfs.

Signed-off-by: Mike Christie <[EMAIL PROTECTED]>
---
 drivers/scsi/libiscsi.c |2 ++
 drivers/scsi/scsi_transport_iscsi.c |8 ++--
 2 files changed, 8 insertions(+), 2 deletions(-)

diff --git a/drivers/scsi/libiscsi.c b/drivers/scsi/libiscsi.c
index f15df8d..6573223 100644
--- a/drivers/scsi/libiscsi.c
+++ b/drivers/scsi/libiscsi.c
@@ -1732,6 +1732,8 @@ iscsi_session_setup(struct iscsi_transport *iscsit,
session->host = shost;
session->state = ISCSI_STATE_FREE;
session->fast_abort = 1;
+   session->lu_reset_timeout = 15;
+   session->abort_timeout = 10;
session->mgmtpool_max = ISCSI_MGMT_CMDS_MAX;
session->cmds_max = cmds_max;
session->queued_cmdsn = session->cmdsn = initial_cmdsn;
diff --git a/drivers/scsi/scsi_transport_iscsi.c 
b/drivers/scsi/scsi_transport_iscsi.c
index 36aa50e..3585599 100644
--- a/drivers/scsi/scsi_transport_iscsi.c
+++ b/drivers/scsi/scsi_transport_iscsi.c
@@ -30,7 +30,7 @@
 #include 
 #include 
 
-#define ISCSI_SESSION_ATTRS 16
+#define ISCSI_SESSION_ATTRS 18
 #define ISCSI_CONN_ATTRS 11
 #define ISCSI_HOST_ATTRS 4
 #define ISCSI_TRANSPORT_VERSION "2.0-724"
@@ -1242,7 +1242,9 @@ iscsi_session_attr(username, ISCSI_PARAM_USERNAME, 1);
 iscsi_session_attr(username_in, ISCSI_PARAM_USERNAME_IN, 1);
 iscsi_session_attr(password, ISCSI_PARAM_PASSWORD, 1);
 iscsi_session_attr(password_in, ISCSI_PARAM_PASSWORD_IN, 1);
-iscsi_session_attr(fast_abort, ISCSI_PARAM_FAST_ABORT, 1);
+iscsi_session_attr(fast_abort, ISCSI_PARAM_FAST_ABORT, 0);
+iscsi_session_attr(abort_tmo, ISCSI_PARAM_ABORT_TMO, 0);
+iscsi_session_attr(lu_reset_tmo, ISCSI_PARAM_LU_RESET_TMO, 0);
 
 #define iscsi_priv_session_attr_show(field, format)\
 static ssize_t \
@@ -1467,6 +1469,8 @@ iscsi_register_transport(struct iscsi_transport *tt)
SETUP_SESSION_RD_ATTR(username, ISCSI_PASSWORD);
SETUP_SESSION_RD_ATTR(username_in, ISCSI_PASSWORD_IN);
SETUP_SESSION_RD_ATTR(fast_abort, ISCSI_FAST_ABORT);
+   SETUP_SESSION_RD_ATTR(abort_tmo, ISCSI_ABORT_TMO);
+   SETUP_SESSION_RD_ATTR(lu_reset_tmo,ISCSI_LU_RESET_TMO);
SETUP_PRIV_SESSION_RD_ATTR(recovery_tmo);
 
BUG_ON(count > ISCSI_SESSION_ATTRS);
-- 
1.5.1.2

-
To unsubscribe from this list: send the line "unsubscribe linux-scsi" in
the body of a message to [EMAIL PROTECTED]
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATCH 14/24] clear conn->ctask when task is completed early

2007-12-13 Thread michaelc
From: Mike Christie <[EMAIL PROTECTED]>

If the current ctask is failed early, we legt the conn->ctask pointer
pointing to a invalid task. When the xmit thread would send data for
it, we would then oops.

Signed-off-by: Mike Christie <[EMAIL PROTECTED]>
---
 drivers/scsi/libiscsi.c |5 -
 1 files changed, 4 insertions(+), 1 deletions(-)

diff --git a/drivers/scsi/libiscsi.c b/drivers/scsi/libiscsi.c
index b17081b..4461317 100644
--- a/drivers/scsi/libiscsi.c
+++ b/drivers/scsi/libiscsi.c
@@ -248,13 +248,16 @@ static int iscsi_prep_scsi_cmd_pdu(struct iscsi_cmd_task 
*ctask)
  */
 static void iscsi_complete_command(struct iscsi_cmd_task *ctask)
 {
-   struct iscsi_session *session = ctask->conn->session;
+   struct iscsi_conn *conn = ctask->conn;
+   struct iscsi_session *session = conn->session;
struct scsi_cmnd *sc = ctask->sc;
 
ctask->state = ISCSI_TASK_COMPLETED;
ctask->sc = NULL;
/* SCSI eh reuses commands to verify us */
sc->SCp.ptr = NULL;
+   if (conn->ctask == ctask)
+   conn->ctask = NULL;
list_del_init(&ctask->running);
__kfifo_put(session->cmdpool.queue, (void*)&ctask, sizeof(void*));
sc->scsi_done(sc);
-- 
1.5.1.2

-
To unsubscribe from this list: send the line "unsubscribe linux-scsi" in
the body of a message to [EMAIL PROTECTED]
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATCH 15/24] Drop host lock in queuecommand

2007-12-13 Thread michaelc
From: Mike Christie <[EMAIL PROTECTED]>

The driver does not need the host lock in queuecommand so drop it.

Signed-off-by: Mike Christie <[EMAIL PROTECTED]>
---
 drivers/scsi/libiscsi.c |6 +-
 1 files changed, 5 insertions(+), 1 deletions(-)

diff --git a/drivers/scsi/libiscsi.c b/drivers/scsi/libiscsi.c
index 4461317..b0bc8c3 100644
--- a/drivers/scsi/libiscsi.c
+++ b/drivers/scsi/libiscsi.c
@@ -1010,8 +1010,9 @@ int iscsi_queuecommand(struct scsi_cmnd *sc, void 
(*done)(struct scsi_cmnd *))
sc->SCp.ptr = NULL;
 
host = sc->device->host;
-   session = iscsi_hostdata(host->hostdata);
+   spin_unlock(host->host_lock);
 
+   session = iscsi_hostdata(host->hostdata);
spin_lock(&session->lock);
 
/*
@@ -1077,11 +1078,13 @@ int iscsi_queuecommand(struct scsi_cmnd *sc, void 
(*done)(struct scsi_cmnd *))
spin_unlock(&session->lock);
 
scsi_queue_work(host, &conn->xmitwork);
+   spin_lock(host->host_lock);
return 0;
 
 reject:
spin_unlock(&session->lock);
debug_scsi("cmd 0x%x rejected (%d)\n", sc->cmnd[0], reason);
+   spin_lock(host->host_lock);
return SCSI_MLQUEUE_HOST_BUSY;
 
 fault:
@@ -1091,6 +1094,7 @@ fault:
sc->result = (DID_NO_CONNECT << 16);
scsi_set_resid(sc, scsi_bufflen(sc));
sc->scsi_done(sc);
+   spin_lock(host->host_lock);
return 0;
 }
 EXPORT_SYMBOL_GPL(iscsi_queuecommand);
-- 
1.5.1.2

-
To unsubscribe from this list: send the line "unsubscribe linux-scsi" in
the body of a message to [EMAIL PROTECTED]
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATCH 13/24] Do not fail commands immediately during logout

2007-12-13 Thread michaelc
From: Mike Christie <[EMAIL PROTECTED]>

If the target requests a logout, then we do not want
to fail commands to scsi-ml right away. This patch just
fails in pending commands for a requeue immediately, and then lets
iscsid handle running commands like normal recovery.

Signed-off-by: Mike Christie <[EMAIL PROTECTED]>
---
 drivers/scsi/libiscsi.c |   14 ++
 1 files changed, 6 insertions(+), 8 deletions(-)

diff --git a/drivers/scsi/libiscsi.c b/drivers/scsi/libiscsi.c
index 9688361..b17081b 100644
--- a/drivers/scsi/libiscsi.c
+++ b/drivers/scsi/libiscsi.c
@@ -917,7 +917,7 @@ check_mgmt:
conn->ctask = list_entry(conn->xmitqueue.next,
 struct iscsi_cmd_task, running);
if (conn->session->state == ISCSI_STATE_LOGGING_OUT) {
-   fail_command(conn, conn->ctask, DID_NO_CONNECT << 16);
+   fail_command(conn, conn->ctask, DID_IMM_RETRY << 16);
continue;
}
if (iscsi_prep_scsi_cmd_pdu(conn->ctask)) {
@@ -1024,21 +1024,19 @@ int iscsi_queuecommand(struct scsi_cmnd *sc, void 
(*done)(struct scsi_cmnd *))
 * be entering our queuecommand while a block is starting
 * up because the block code is not locked)
 */
-   if (session->state == ISCSI_STATE_IN_RECOVERY) {
+   switch (session->state) {
+   case ISCSI_STATE_IN_RECOVERY:
reason = FAILURE_SESSION_IN_RECOVERY;
goto reject;
-   }
-
-   switch (session->state) {
+   case ISCSI_STATE_LOGGING_OUT:
+   reason = FAILURE_SESSION_LOGGING_OUT;
+   goto reject;
case ISCSI_STATE_RECOVERY_FAILED:
reason = FAILURE_SESSION_RECOVERY_TIMEOUT;
break;
case ISCSI_STATE_TERMINATE:
reason = FAILURE_SESSION_TERMINATE;
break;
-   case ISCSI_STATE_LOGGING_OUT:
-   reason = FAILURE_SESSION_LOGGING_OUT;
-   break;
default:
reason = FAILURE_SESSION_FREED;
}
-- 
1.5.1.2

-
To unsubscribe from this list: send the line "unsubscribe linux-scsi" in
the body of a message to [EMAIL PROTECTED]
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATCH 09/24] libiscsi: grab eh_mutex during host reset

2007-12-13 Thread michaelc
From: Mike Christie <[EMAIL PROTECTED]>

I thought we may not need the eh mutex during host reset, but that is wrong
with the new shutdown code. When start_session_recovery sets the state to
terminate then drops the session lock. The scsi eh thread could then grab the
session lock see that we are terminating and then return failed to scsi-ml.
scsi-ml's eh then owns the command and will do whatever it wants
with it. But then the iscsi eh thread could grab the session lock
and want to complete the scsi commands that we in the LLD, but
it no longer owns them and kaboom.

Signed-off-by: Mike Christie <[EMAIL PROTECTED]>
---
 drivers/scsi/libiscsi.c |7 +--
 1 files changed, 5 insertions(+), 2 deletions(-)

diff --git a/drivers/scsi/libiscsi.c b/drivers/scsi/libiscsi.c
index b7a2b9a..441e351 100644
--- a/drivers/scsi/libiscsi.c
+++ b/drivers/scsi/libiscsi.c
@@ -1079,17 +1079,19 @@ int iscsi_eh_host_reset(struct scsi_cmnd *sc)
struct iscsi_session *session = iscsi_hostdata(host->hostdata);
struct iscsi_conn *conn = session->leadconn;
 
+   mutex_lock(&session->eh_mutex);
spin_lock_bh(&session->lock);
if (session->state == ISCSI_STATE_TERMINATE) {
 failed:
debug_scsi("failing host reset: session terminated "
   "[CID %d age %d]\n", conn->id, session->age);
spin_unlock_bh(&session->lock);
+   mutex_unlock(&session->eh_mutex);
return FAILED;
}
 
spin_unlock_bh(&session->lock);
-
+   mutex_unlock(&session->eh_mutex);
/*
 * we drop the lock here but the leadconn cannot be destoyed while
 * we are in the scsi eh
@@ -1104,13 +1106,14 @@ failed:
if (signal_pending(current))
flush_signals(current);
 
+   mutex_lock(&session->eh_mutex);
spin_lock_bh(&session->lock);
if (session->state == ISCSI_STATE_LOGGED_IN)
printk(KERN_INFO "iscsi: host reset succeeded\n");
else
goto failed;
spin_unlock_bh(&session->lock);
-
+   mutex_unlock(&session->eh_mutex);
return SUCCESS;
 }
 EXPORT_SYMBOL_GPL(iscsi_eh_host_reset);
-- 
1.5.1.2

-
To unsubscribe from this list: send the line "unsubscribe linux-scsi" in
the body of a message to [EMAIL PROTECTED]
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATCH 11/24] libiscsi: fix nop handling

2007-12-13 Thread michaelc
From: Mike Christie <[EMAIL PROTECTED]>

During root boot and shutdown the target could send us nops.
At this time iscsid cannot be running, so the target will drop
the session and the boot or shutdown will hang.

To handle this and allow us to better control when to check the network
this patch moves the nop handling to the kernel.

Signed-off-by: Mike Christie <[EMAIL PROTECTED]>
---
 drivers/infiniband/ulp/iser/iscsi_iser.c |4 +-
 drivers/scsi/iscsi_tcp.c |4 +-
 drivers/scsi/libiscsi.c  |  331 --
 drivers/scsi/scsi_transport_iscsi.c  |4 +
 include/scsi/iscsi_if.h  |   11 +
 include/scsi/libiscsi.h  |8 +
 6 files changed, 294 insertions(+), 68 deletions(-)

diff --git a/drivers/infiniband/ulp/iser/iscsi_iser.c 
b/drivers/infiniband/ulp/iser/iscsi_iser.c
index a2622f4..2656064 100644
--- a/drivers/infiniband/ulp/iser/iscsi_iser.c
+++ b/drivers/infiniband/ulp/iser/iscsi_iser.c
@@ -577,7 +577,9 @@ static struct iscsi_transport iscsi_iser_transport = {
  ISCSI_PERSISTENT_ADDRESS |
  ISCSI_TARGET_NAME | ISCSI_TPGT |
  ISCSI_USERNAME | ISCSI_PASSWORD |
- ISCSI_USERNAME_IN | ISCSI_PASSWORD_IN,
+ ISCSI_USERNAME_IN | ISCSI_PASSWORD_IN |
+ ISCSI_FAST_ABORT | ISCSI_ABORT_TMO |
+ ISCSI_PING_TMO | ISCSI_RECV_TMO,
.host_param_mask= ISCSI_HOST_HWADDRESS |
  ISCSI_HOST_NETDEV_NAME |
  ISCSI_HOST_INITIATOR_NAME,
diff --git a/drivers/scsi/iscsi_tcp.c b/drivers/scsi/iscsi_tcp.c
index 90eae8e..9b41852 100644
--- a/drivers/scsi/iscsi_tcp.c
+++ b/drivers/scsi/iscsi_tcp.c
@@ -2246,7 +2246,9 @@ static struct iscsi_transport iscsi_tcp_transport = {
  ISCSI_TARGET_NAME | ISCSI_TPGT |
  ISCSI_USERNAME | ISCSI_PASSWORD |
  ISCSI_USERNAME_IN | ISCSI_PASSWORD_IN |
- ISCSI_FAST_ABORT,
+ ISCSI_FAST_ABORT | ISCSI_ABORT_TMO |
+ ISCSI_LU_RESET_TMO |
+ ISCSI_PING_TMO | ISCSI_RECV_TMO,
.host_param_mask= ISCSI_HOST_HWADDRESS | ISCSI_HOST_IPADDRESS |
  ISCSI_HOST_INITIATOR_NAME |
  ISCSI_HOST_NETDEV_NAME,
diff --git a/drivers/scsi/libiscsi.c b/drivers/scsi/libiscsi.c
index 5205ef2..9688361 100644
--- a/drivers/scsi/libiscsi.c
+++ b/drivers/scsi/libiscsi.c
@@ -313,11 +313,70 @@ void iscsi_free_mgmt_task(struct iscsi_conn *conn,
list_del_init(&mtask->running);
if (conn->login_mtask == mtask)
return;
+
+   if (conn->ping_mtask == mtask)
+   conn->ping_mtask = NULL;
__kfifo_put(conn->session->mgmtpool.queue,
(void*)&mtask, sizeof(void*));
 }
 EXPORT_SYMBOL_GPL(iscsi_free_mgmt_task);
 
+static struct iscsi_mgmt_task *
+__iscsi_conn_send_pdu(struct iscsi_conn *conn, struct iscsi_hdr *hdr,
+ char *data, uint32_t data_size)
+{
+   struct iscsi_session *session = conn->session;
+   struct iscsi_mgmt_task *mtask;
+
+   if (session->state == ISCSI_STATE_TERMINATE)
+   return NULL;
+
+   if (hdr->opcode == (ISCSI_OP_LOGIN | ISCSI_OP_IMMEDIATE) ||
+   hdr->opcode == (ISCSI_OP_TEXT | ISCSI_OP_IMMEDIATE))
+   /*
+* Login and Text are sent serially, in
+* request-followed-by-response sequence.
+* Same mtask can be used. Same ITT must be used.
+* Note that login_mtask is preallocated at conn_create().
+*/
+   mtask = conn->login_mtask;
+   else {
+   BUG_ON(conn->c_stage == ISCSI_CONN_INITIAL_STAGE);
+   BUG_ON(conn->c_stage == ISCSI_CONN_STOPPED);
+
+   if (!__kfifo_get(session->mgmtpool.queue,
+(void*)&mtask, sizeof(void*)))
+   return NULL;
+   }
+
+   if (data_size) {
+   memcpy(mtask->data, data, data_size);
+   mtask->data_count = data_size;
+   } else
+   mtask->data_count = 0;
+
+   memcpy(mtask->hdr, hdr, sizeof(struct iscsi_hdr));
+   INIT_LIST_HEAD(&mtask->running);
+   list_add_tail(&mtask->running, &conn->mgmtqueue);
+   return mtask;
+}
+
+int iscsi_conn_send_pdu(struct iscsi_cls_conn *cls_conn, struct iscsi_hdr *hdr,
+   char *data, uint32_t data_size)
+{
+   struct iscsi_conn *conn = cls_conn->dd_data;
+   struct iscsi_session *session = conn->session;
+   int err = 0;
+
+   spin_lock_bh(&session->lock);
+   if (!

[PATCH 08/24] iscsi class: Use our own workq instead of common system one.

2007-12-13 Thread michaelc
From: Mike Christie <[EMAIL PROTECTED]>

There is just too much going on through the common workq and
something like a scsi device removal through sysfs affects
how long it will take to recover the transport, mark it as
failed, or shut it down gracefully.

Signed-off-by: Mike Christie <[EMAIL PROTECTED]>
---
 drivers/scsi/scsi_transport_iscsi.c |   16 
 1 files changed, 12 insertions(+), 4 deletions(-)

diff --git a/drivers/scsi/scsi_transport_iscsi.c 
b/drivers/scsi/scsi_transport_iscsi.c
index 75d3069..9cc2cc8 100644
--- a/drivers/scsi/scsi_transport_iscsi.c
+++ b/drivers/scsi/scsi_transport_iscsi.c
@@ -50,6 +50,7 @@ struct iscsi_internal {
 };
 
 static atomic_t iscsi_session_nr; /* sysfs session id for next new session */
+static struct workqueue_struct *iscsi_eh_timer_workq;
 
 /*
  * list of registered transports and lock that must
@@ -252,7 +253,7 @@ static void session_recovery_timedout(struct work_struct 
*work)
 void iscsi_unblock_session(struct iscsi_cls_session *session)
 {
if (!cancel_delayed_work(&session->recovery_work))
-   flush_scheduled_work();
+   flush_workqueue(iscsi_eh_timer_workq);
scsi_target_unblock(&session->dev);
 }
 EXPORT_SYMBOL_GPL(iscsi_unblock_session);
@@ -260,8 +261,8 @@ EXPORT_SYMBOL_GPL(iscsi_unblock_session);
 void iscsi_block_session(struct iscsi_cls_session *session)
 {
scsi_target_block(&session->dev);
-   schedule_delayed_work(&session->recovery_work,
-session->recovery_tmo * HZ);
+   queue_delayed_work(iscsi_eh_timer_workq, &session->recovery_work,
+  session->recovery_tmo * HZ);
 }
 EXPORT_SYMBOL_GPL(iscsi_block_session);
 
@@ -357,7 +358,7 @@ void iscsi_remove_session(struct iscsi_cls_session *session)
struct iscsi_host *ihost = shost->shost_data;
 
if (!cancel_delayed_work(&session->recovery_work))
-   flush_scheduled_work();
+   flush_workqueue(iscsi_eh_timer_workq);
 
mutex_lock(&ihost->mutex);
list_del(&session->host_list);
@@ -1521,8 +1522,14 @@ static __init int iscsi_transport_init(void)
goto unregister_session_class;
}
 
+   iscsi_eh_timer_workq = create_singlethread_workqueue("iscsi_eh");
+   if (!iscsi_eh_timer_workq)
+   goto release_nls;
+
return 0;
 
+release_nls:
+   sock_release(nls->sk_socket);
 unregister_session_class:
transport_class_unregister(&iscsi_session_class);
 unregister_conn_class:
@@ -1536,6 +1543,7 @@ unregister_transport_class:
 
 static void __exit iscsi_transport_exit(void)
 {
+   destroy_workqueue(iscsi_eh_timer_workq);
sock_release(nls->sk_socket);
transport_class_unregister(&iscsi_connection_class);
transport_class_unregister(&iscsi_session_class);
-- 
1.5.1.2

-
To unsubscribe from this list: send the line "unsubscribe linux-scsi" in
the body of a message to [EMAIL PROTECTED]
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATCH 10/24] libiscsi: fix shutdown

2007-12-13 Thread michaelc
From: Mike Christie <[EMAIL PROTECTED]>

We were using the device delete sysfs file to remove each device
then logout. Now in 2.6.21 this will not work because
the sysfs delete file returns immediately and does not wait for
the device removal to complete. This causes a hang if a cache sync
is needed during shutdown. Before .21, that approach had other
problems, so this patch fixes the shutdown code so that we remove the target
and unbind the session before logging out and shut down the session

Signed-off-by: Mike Christie <[EMAIL PROTECTED]>
---
 drivers/scsi/libiscsi.c |4 +-
 drivers/scsi/qla4xxx/ql4_init.c |4 +-
 drivers/scsi/qla4xxx/ql4_os.c   |7 +-
 drivers/scsi/scsi_transport_iscsi.c |  289 +++
 include/scsi/iscsi_if.h |7 +
 include/scsi/iscsi_proto.h  |2 +
 include/scsi/scsi_transport_iscsi.h |7 +-
 7 files changed, 176 insertions(+), 144 deletions(-)

diff --git a/drivers/scsi/libiscsi.c b/drivers/scsi/libiscsi.c
index 441e351..5205ef2 100644
--- a/drivers/scsi/libiscsi.c
+++ b/drivers/scsi/libiscsi.c
@@ -1662,7 +1662,7 @@ void iscsi_session_teardown(struct iscsi_cls_session 
*cls_session)
struct iscsi_session *session = iscsi_hostdata(shost->hostdata);
struct module *owner = cls_session->transport->owner;
 
-   iscsi_unblock_session(cls_session);
+   iscsi_remove_session(cls_session);
scsi_remove_host(shost);
 
iscsi_pool_free(&session->mgmtpool);
@@ -1677,7 +1677,7 @@ void iscsi_session_teardown(struct iscsi_cls_session 
*cls_session)
kfree(session->hwaddress);
kfree(session->initiatorname);
 
-   iscsi_destroy_session(cls_session);
+   iscsi_free_session(cls_session);
scsi_host_put(shost);
module_put(owner);
 }
diff --git a/drivers/scsi/qla4xxx/ql4_init.c b/drivers/scsi/qla4xxx/ql4_init.c
index d692c71..cbe0a17 100644
--- a/drivers/scsi/qla4xxx/ql4_init.c
+++ b/drivers/scsi/qla4xxx/ql4_init.c
@@ -5,6 +5,7 @@
  * See LICENSE.qla4xxx for copyright and licensing details.
  */
 
+#include 
 #include "ql4_def.h"
 #include "ql4_glbl.h"
 #include "ql4_dbg.h"
@@ -1305,7 +1306,8 @@ int qla4xxx_process_ddb_changed(struct scsi_qla_host *ha,
atomic_set(&ddb_entry->relogin_timer, 0);
clear_bit(DF_RELOGIN, &ddb_entry->flags);
clear_bit(DF_NO_RELOGIN, &ddb_entry->flags);
-   iscsi_if_create_session_done(ddb_entry->conn);
+   iscsi_session_event(ddb_entry->sess,
+   ISCSI_KEVENT_CREATE_SESSION);
/*
 * Change the lun state to READY in case the lun TIMEOUT before
 * the device came back.
diff --git a/drivers/scsi/qla4xxx/ql4_os.c b/drivers/scsi/qla4xxx/ql4_os.c
index 89460d2..f55b9f7 100644
--- a/drivers/scsi/qla4xxx/ql4_os.c
+++ b/drivers/scsi/qla4xxx/ql4_os.c
@@ -298,8 +298,7 @@ void qla4xxx_destroy_sess(struct ddb_entry *ddb_entry)
return;
 
if (ddb_entry->conn) {
-   iscsi_if_destroy_session_done(ddb_entry->conn);
-   iscsi_destroy_conn(ddb_entry->conn);
+   atomic_set(&ddb_entry->state, DDB_STATE_DEAD);
iscsi_remove_session(ddb_entry->sess);
}
iscsi_free_session(ddb_entry->sess);
@@ -309,6 +308,7 @@ int qla4xxx_add_sess(struct ddb_entry *ddb_entry)
 {
int err;
 
+   ddb_entry->sess->recovery_tmo = ddb_entry->ha->port_down_retry_count;
err = iscsi_add_session(ddb_entry->sess, ddb_entry->fw_ddb_index);
if (err) {
DEBUG2(printk(KERN_ERR "Could not add session.\n"));
@@ -321,9 +321,6 @@ int qla4xxx_add_sess(struct ddb_entry *ddb_entry)
DEBUG2(printk(KERN_ERR "Could not add connection.\n"));
return -ENOMEM;
}
-
-   ddb_entry->sess->recovery_tmo = ddb_entry->ha->port_down_retry_count;
-   iscsi_if_create_session_done(ddb_entry->conn);
return 0;
 }
 
diff --git a/drivers/scsi/scsi_transport_iscsi.c 
b/drivers/scsi/scsi_transport_iscsi.c
index 9cc2cc8..b82139d 100644
--- a/drivers/scsi/scsi_transport_iscsi.c
+++ b/drivers/scsi/scsi_transport_iscsi.c
@@ -116,6 +116,8 @@ static struct attribute_group iscsi_transport_group = {
.attrs = iscsi_transport_attrs,
 };
 
+
+
 static int iscsi_setup_host(struct transport_container *tc, struct device *dev,
struct class_device *cdev)
 {
@@ -125,13 +127,30 @@ static int iscsi_setup_host(struct transport_container 
*tc, struct device *dev,
memset(ihost, 0, sizeof(*ihost));
INIT_LIST_HEAD(&ihost->sessions);
mutex_init(&ihost->mutex);
+
+   snprintf(ihost->unbind_workq_name, KOBJ_NAME_LEN, "iscsi_unbind_%d",
+   shost->host_no);
+   ihost->unbind_workq = create_singlethread_workqueue(
+   ihost->unbind_workq_name);
+   if (!ihost->unbind_workq)
+ 

[PATCH 07/24] libiscsi: do not block session during logout

2007-12-13 Thread michaelc
From: Mike Christie <[EMAIL PROTECTED]>

There is not need to block the session during logout. Since
we are going to fail the commands that were blocked just fail them
immediately instead.

Signed-off-by: Mike Christie <[EMAIL PROTECTED]>
---
 drivers/infiniband/ulp/iser/iser_initiator.c |4 +-
 drivers/scsi/iscsi_tcp.c |4 +-
 drivers/scsi/libiscsi.c  |  153 ++
 include/scsi/libiscsi.h  |2 +
 include/scsi/scsi_transport_iscsi.h  |1 +
 5 files changed, 88 insertions(+), 76 deletions(-)

diff --git a/drivers/infiniband/ulp/iser/iser_initiator.c 
b/drivers/infiniband/ulp/iser/iser_initiator.c
index a6f2303..47f716c 100644
--- a/drivers/infiniband/ulp/iser/iser_initiator.c
+++ b/drivers/infiniband/ulp/iser/iser_initiator.c
@@ -621,9 +621,7 @@ void iser_snd_completion(struct iser_desc *tx_desc)
struct iscsi_session *session = conn->session;
 
spin_lock(&conn->session->lock);
-   list_del(&mtask->running);
-   __kfifo_put(session->mgmtpool.queue, (void*)&mtask,
-   sizeof(void*));
+   iscsi_free_mgmt_task(conn, mtask);
spin_unlock(&session->lock);
}
}
diff --git a/drivers/scsi/iscsi_tcp.c b/drivers/scsi/iscsi_tcp.c
index f79a457..90eae8e 100644
--- a/drivers/scsi/iscsi_tcp.c
+++ b/drivers/scsi/iscsi_tcp.c
@@ -1349,9 +1349,7 @@ iscsi_tcp_mtask_xmit(struct iscsi_conn *conn, struct 
iscsi_mgmt_task *mtask)
struct iscsi_session *session = conn->session;
 
spin_lock_bh(&session->lock);
-   list_del(&conn->mtask->running);
-   __kfifo_put(session->mgmtpool.queue, (void*)&conn->mtask,
-   sizeof(void*));
+   iscsi_free_mgmt_task(conn, mtask);
spin_unlock_bh(&session->lock);
}
return 0;
diff --git a/drivers/scsi/libiscsi.c b/drivers/scsi/libiscsi.c
index d43f909..b7a2b9a 100644
--- a/drivers/scsi/libiscsi.c
+++ b/drivers/scsi/libiscsi.c
@@ -37,9 +37,6 @@
 #include 
 #include 
 
-static void fail_command(struct iscsi_conn *conn, struct iscsi_cmd_task *ctask,
-int err);
-
 struct iscsi_session *
 class_to_transport_session(struct iscsi_cls_session *cls_session)
 {
@@ -274,6 +271,53 @@ static void __iscsi_put_ctask(struct iscsi_cmd_task *ctask)
iscsi_complete_command(ctask);
 }
 
+/*
+ * session lock must be held
+ */
+static void fail_command(struct iscsi_conn *conn, struct iscsi_cmd_task *ctask,
+int err)
+{
+   struct scsi_cmnd *sc;
+
+   sc = ctask->sc;
+   if (!sc)
+   return;
+
+   if (ctask->state == ISCSI_TASK_PENDING)
+   /*
+* cmd never made it to the xmit thread, so we should not count
+* the cmd in the sequencing
+*/
+   conn->session->queued_cmdsn--;
+   else
+   conn->session->tt->cleanup_cmd_task(conn, ctask);
+
+   sc->result = err;
+   scsi_set_resid(sc, scsi_bufflen(sc));
+   if (conn->ctask == ctask)
+   conn->ctask = NULL;
+   /* release ref from queuecommand */
+   __iscsi_put_ctask(ctask);
+}
+
+/**
+ * iscsi_free_mgmt_task - return mgmt task back to pool
+ * @conn: iscsi connection
+ * @mtask: mtask
+ *
+ * Must be called with session lock.
+ */
+void iscsi_free_mgmt_task(struct iscsi_conn *conn,
+ struct iscsi_mgmt_task *mtask)
+{
+   list_del_init(&mtask->running);
+   if (conn->login_mtask == mtask)
+   return;
+   __kfifo_put(conn->session->mgmtpool.queue,
+   (void*)&mtask, sizeof(void*));
+}
+EXPORT_SYMBOL_GPL(iscsi_free_mgmt_task);
+
 /**
  * iscsi_cmd_rsp - SCSI Command Response processing
  * @conn: iscsi connection
@@ -464,10 +508,7 @@ int __iscsi_complete_pdu(struct iscsi_conn *conn, struct 
iscsi_hdr *hdr,
 */
if (iscsi_recv_pdu(conn->cls_conn, hdr, data, datalen))
rc = ISCSI_ERR_CONN_FAILED;
-   list_del_init(&mtask->running);
-   if (conn->login_mtask != mtask)
-   __kfifo_put(session->mgmtpool.queue,
-   (void*)&mtask, sizeof(void*));
+   iscsi_free_mgmt_task(conn, mtask);
break;
case ISCSI_OP_SCSI_TMFUNC_RSP:
if (datalen) {
@@ -476,6 +517,7 @@ int __iscsi_complete_pdu(struct iscsi_conn *conn, struct 
iscsi_hdr *hdr,
}
 
iscsi_tmf_rsp(conn, hdr);
+   iscsi_free_mgmt_task(conn, mtask);
break;
case ISCSI_OP_NOOP_IN:
 

[PATCH 01/24] libiscsi, iscsi_tcp: add device support

2007-12-13 Thread michaelc
From: Mike Christie <[EMAIL PROTECTED]>

This patch adds logical unit reset support. This should work for ib_iser,
but I have not finished testing that driver so it is not hooked in yet.

This patch also temporarily reverts the iscsi_tcp r2t write out patch.
That code is completely rewritten in this patchset.

Signed-off-by: Mike Christie <[EMAIL PROTECTED]>
---
 drivers/infiniband/ulp/iser/iscsi_iser.c |6 -
 drivers/scsi/iscsi_tcp.c |  151 +-
 drivers/scsi/iscsi_tcp.h |   34 +-
 drivers/scsi/libiscsi.c  |  494 +-
 drivers/scsi/scsi_transport_iscsi.c  |4 +-
 include/scsi/iscsi_if.h  |2 +
 include/scsi/iscsi_proto.h   |2 +
 include/scsi/libiscsi.h  |   25 +-
 8 files changed, 396 insertions(+), 322 deletions(-)

diff --git a/drivers/infiniband/ulp/iser/iscsi_iser.c 
b/drivers/infiniband/ulp/iser/iscsi_iser.c
index bad8dac..2eadb6d 100644
--- a/drivers/infiniband/ulp/iser/iscsi_iser.c
+++ b/drivers/infiniband/ulp/iser/iscsi_iser.c
@@ -220,12 +220,6 @@ iscsi_iser_ctask_xmit(struct iscsi_conn *conn,
debug_scsi("ctask deq [cid %d itt 0x%x]\n",
   conn->id, ctask->itt);
 
-   /*
-* serialize with TMF AbortTask
-*/
-   if (ctask->mtask)
-   return error;
-
/* Send the cmd PDU */
if (!iser_ctask->command_sent) {
error = iser_send_command(conn, ctask);
diff --git a/drivers/scsi/iscsi_tcp.c b/drivers/scsi/iscsi_tcp.c
index 57ce225..4b226b8 100644
--- a/drivers/scsi/iscsi_tcp.c
+++ b/drivers/scsi/iscsi_tcp.c
@@ -197,7 +197,7 @@ iscsi_tcp_cleanup_ctask(struct iscsi_conn *conn, struct 
iscsi_cmd_task *ctask)
if (unlikely(!sc))
return;
 
-   tcp_ctask->xmstate = XMSTATE_VALUE_IDLE;
+   tcp_ctask->xmstate = XMSTATE_IDLE;
tcp_ctask->r2t = NULL;
 }
 
@@ -369,8 +369,7 @@ iscsi_r2t_rsp(struct iscsi_conn *conn, struct 
iscsi_cmd_task *ctask)
spin_lock(&session->lock);
iscsi_update_cmdsn(session, (struct iscsi_nopin*)rhdr);
 
-   if (!ctask->sc || ctask->mtask ||
-session->state != ISCSI_STATE_LOGGED_IN) {
+   if (!ctask->sc || session->state != ISCSI_STATE_LOGGED_IN) {
printk(KERN_INFO "iscsi_tcp: dropping R2T itt %d in "
   "recovery...\n", ctask->itt);
spin_unlock(&session->lock);
@@ -409,11 +408,10 @@ iscsi_r2t_rsp(struct iscsi_conn *conn, struct 
iscsi_cmd_task *ctask)
 
tcp_ctask->exp_datasn = r2tsn + 1;
__kfifo_put(tcp_ctask->r2tqueue, (void*)&r2t, sizeof(void*));
-   set_bit(XMSTATE_BIT_SOL_HDR_INIT, &tcp_ctask->xmstate);
-   list_move_tail(&ctask->running, &conn->xmitqueue);
-
-   scsi_queue_work(session->host, &conn->xmitwork);
+   tcp_ctask->xmstate |= XMSTATE_SOL_HDR_INIT;
conn->r2t_pdus_cnt++;
+
+   iscsi_requeue_ctask(ctask);
spin_unlock(&session->lock);
 
return 0;
@@ -1254,7 +1252,7 @@ static void iscsi_set_padding(struct iscsi_tcp_cmd_task 
*tcp_ctask,
 
tcp_ctask->pad_count = ISCSI_PAD_LEN - tcp_ctask->pad_count;
debug_scsi("write padding %d bytes\n", tcp_ctask->pad_count);
-   set_bit(XMSTATE_BIT_W_PAD, &tcp_ctask->xmstate);
+   tcp_ctask->xmstate |= XMSTATE_W_PAD;
 }
 
 /**
@@ -1269,7 +1267,7 @@ iscsi_tcp_cmd_init(struct iscsi_cmd_task *ctask)
struct iscsi_tcp_cmd_task *tcp_ctask = ctask->dd_data;
 
BUG_ON(__kfifo_len(tcp_ctask->r2tqueue));
-   tcp_ctask->xmstate = 1 << XMSTATE_BIT_CMD_HDR_INIT;
+   tcp_ctask->xmstate = XMSTATE_CMD_HDR_INIT;
 }
 
 /**
@@ -1283,10 +1281,10 @@ iscsi_tcp_cmd_init(struct iscsi_cmd_task *ctask)
  * xmit.
  *
  * Management xmit state machine consists of these states:
- * XMSTATE_BIT_IMM_HDR_INIT - calculate digest of PDU Header
- * XMSTATE_BIT_IMM_HDR  - PDU Header xmit in progress
- * XMSTATE_BIT_IMM_DATA - PDU Data xmit in progress
- * XMSTATE_VALUE_IDLE   - management PDU is done
+ * XMSTATE_IMM_HDR_INIT- calculate digest of PDU Header
+ * XMSTATE_IMM_HDR - PDU Header xmit in progress
+ * XMSTATE_IMM_DATA- PDU Data xmit in progress
+ * XMSTATE_IDLE- management PDU is done
  **/
 static int
 iscsi_tcp_mtask_xmit(struct iscsi_conn *conn, struct iscsi_mgmt_task *mtask)
@@ -1297,12 +1295,12 @@ iscsi_tcp_mtask_xmit(struct iscsi_conn *conn, struct 
iscsi_mgmt_task *mtask)
debug_scsi("mtask deq [cid %d state %x itt 0x%x]\n",
conn->id, tcp_mtask->xmstate, mtask->itt);
 
-   if (test_bit(XMSTATE_BIT_IMM_HDR_INIT, &tcp_mtask->xmstate)) {
+   if (tcp_mtask->xmstate & XMSTATE_IMM_HDR_INIT) {
iscsi_buf_init_iov(&tcp_mtask->headbuf, (char*)mtask->hdr,
   sizeof(struct iscsi_hdr));
 

RESEND: iscsi update for 2.6.25

2007-12-13 Thread michaelc
Between the time I made my last patchset and when James rebased
scsi-misc a patch to scsi_transport_iscsi.c got merged and that
broke my patchset. This is a resend of the patchset, but rebased
against scsi-misc.

Sorry for the bigger than normal update. There are patches from Olaf and
Boaz which do the following:

- Rewrite iscsi_tcp data path (from Olaf), so we do not have two ulgy
abstractions for the send and recv path. Now we have one nice iscsi_segment
struct that works for both paths.
- Add basic iscsi spec handling we will need for Bidi support (from Boaz).
This does not add bidi support. It just adds code that is common.
- Device reset support. Some clustering software needed at least
device reset support, so I cleaned up that code and added device
logical unit reset support. I will add warm target reset support
later.
- Lots of fixes for things like shutdown, r2t leaks, and lots of clean
up from Olaf.
- sg chaining support.


-
To unsubscribe from this list: send the line "unsubscribe linux-scsi" in
the body of a message to [EMAIL PROTECTED]
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATCH 05/23] iser patching for AHS support

2007-12-04 Thread michaelc
From: Mike Christie <[EMAIL PROTECTED]>

from Boaz Harrosh <[EMAIL PROTECTED]>

  - The default initialization of hdr_max is the minimum -
sizeof(struct iscsi_cmd) - Once this patch goes into iser the default
initialization at libiscsi can be removed.
  - This is not yet full support for AHSs at iser end. But it should be easy.
Just allocate more space at iser_desc right after iscsi_hdr. Than
at transmission time use ctask->hdr_len to retrieve the total
size of all iscsi pdu headers. See previous patch at iscsi_tcp.[ch]

Signed-off-by: Boaz Harrosh <[EMAIL PROTECTED]>
Signed-off-by: Mike Christie <[EMAIL PROTECTED]>
---
 drivers/infiniband/ulp/iser/iscsi_iser.c |1 +
 drivers/scsi/libiscsi.c  |1 -
 2 files changed, 1 insertions(+), 1 deletions(-)

diff --git a/drivers/infiniband/ulp/iser/iscsi_iser.c 
b/drivers/infiniband/ulp/iser/iscsi_iser.c
index 2eadb6d..a2622f4 100644
--- a/drivers/infiniband/ulp/iser/iscsi_iser.c
+++ b/drivers/infiniband/ulp/iser/iscsi_iser.c
@@ -400,6 +400,7 @@ iscsi_iser_session_create(struct iscsi_transport *iscsit,
ctask  = session->cmds[i];
iser_ctask = ctask->dd_data;
ctask->hdr = (struct iscsi_cmd *)&iser_ctask->desc.iscsi_header;
+   ctask->hdr_max = sizeof(iser_ctask->desc.iscsi_header);
}
 
for (i = 0; i < session->mgmtpool_max; i++) {
diff --git a/drivers/scsi/libiscsi.c b/drivers/scsi/libiscsi.c
index 0d7914f..5936586 100644
--- a/drivers/scsi/libiscsi.c
+++ b/drivers/scsi/libiscsi.c
@@ -1570,7 +1570,6 @@ iscsi_session_setup(struct iscsi_transport *iscsit,
if (cmd_task_size)
ctask->dd_data = &ctask[1];
ctask->itt = cmd_i;
-   ctask->hdr_max = sizeof(struct iscsi_cmd);
INIT_LIST_HEAD(&ctask->running);
}
 
-- 
1.5.1.2

-
To unsubscribe from this list: send the line "unsubscribe linux-scsi" in
the body of a message to [EMAIL PROTECTED]
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATCH 17/23] iscsi_tcp: stop leaking r2t_info's when the incoming R2T is bad

2007-12-04 Thread michaelc
From: Mike Christie <[EMAIL PROTECTED]>

from [EMAIL PROTECTED]:

iscsi_r2t_rsp checks the incoming R2T for sanity, and if it
thinks it's fishy, it will drop it silently. In this case, we
leaked an r2t_info object. If we do this often enough, we run
into a BUG_ON some time later.

Removed r2t wrappers and update patch by Mike Christie

Signed-off-by: Olaf Kirch <[EMAIL PROTECTED]>
Signed-off-by: Mike Christie <[EMAIL PROTECTED]>
---
 drivers/scsi/iscsi_tcp.c |6 +-
 1 files changed, 5 insertions(+), 1 deletions(-)

diff --git a/drivers/scsi/iscsi_tcp.c b/drivers/scsi/iscsi_tcp.c
index 7212fe9..ecba606 100644
--- a/drivers/scsi/iscsi_tcp.c
+++ b/drivers/scsi/iscsi_tcp.c
@@ -658,6 +658,8 @@ iscsi_r2t_rsp(struct iscsi_conn *conn, struct 
iscsi_cmd_task *ctask)
r2t->data_length = be32_to_cpu(rhdr->data_length);
if (r2t->data_length == 0) {
printk(KERN_ERR "iscsi_tcp: invalid R2T with zero data len\n");
+   __kfifo_put(tcp_ctask->r2tpool.queue, (void*)&r2t,
+   sizeof(void*));
spin_unlock(&session->lock);
return ISCSI_ERR_DATALEN;
}
@@ -669,10 +671,12 @@ iscsi_r2t_rsp(struct iscsi_conn *conn, struct 
iscsi_cmd_task *ctask)
 
r2t->data_offset = be32_to_cpu(rhdr->data_offset);
if (r2t->data_offset + r2t->data_length > scsi_bufflen(ctask->sc)) {
-   spin_unlock(&session->lock);
printk(KERN_ERR "iscsi_tcp: invalid R2T with data len %u at "
   "offset %u and total length %d\n", r2t->data_length,
   r2t->data_offset, scsi_bufflen(ctask->sc));
+   __kfifo_put(tcp_ctask->r2tpool.queue, (void*)&r2t,
+   sizeof(void*));
+   spin_unlock(&session->lock);
return ISCSI_ERR_DATALEN;
}
 
-- 
1.5.1.2

-
To unsubscribe from this list: send the line "unsubscribe linux-scsi" in
the body of a message to [EMAIL PROTECTED]
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATCH 04/23] iscsi_tcp, libiscsi: initial AHS Support

2007-12-04 Thread michaelc
From: Mike Christie <[EMAIL PROTECTED]>

  at libiscsi generic code
  - currently code assumes a storage space of pdu header is allocated
at llds ctask and is pointed to by iscsi_cmd_task->hdr. Here I add
a hdr_max field pertaining to that storage, and an hdr_len that
accumulates the current use of the pdu-header.

  - Add an iscsi_next_hdr() inline which returns the next free space
to write new Header at. Also iscsi_next_hdr() is used to retrieve
the address at which to write the header-digest.

  - Add iscsi_add_hdr(length). What the user do is calls iscsi_next_hdr()
for address of the new header, than calls iscsi_add_hdr(length) with
the size of the new header. iscsi_add_hdr() will check if space is
available and update to the new size. length must be padded according
to standard.

  - Add 2 padding inline helpers thanks to Olaf. Current patch does not
use them but Following patches will.
Also moved definition of ISCSI_PAD_LEN to iscsi_proto.h which had
PAD_WORD_LEN that was never used anywhere.

  - Let iscsi_prep_scsi_cmd_pdu() signal an Error return since now  it is
possible that it will fail.

  - I was tired of yet again writing a "this is a digest" comment next to
sizeof(__u32) so I defined a new ISCSI_DIGEST_SIZE. Now I don't need
any comments. Changed all places that used sizeof(__u32) or "4" in
connection to a digest.

  iscsi_tcp specific code
  - At struct iscsi_tcp_cmd_task allocate maximum space allowed in
standard for all headers following the iscsi_cmd header. and mark
it so in iscsi_tcp_session_create()
  - At iscsi_send_cmd_hdr() retrieve the correct headers size and
write header digest at iscsi_next_hdr().

Signed-off-by: Boaz Harrosh <[EMAIL PROTECTED]>
Acked-by: Olaf Kirch <[EMAIL PROTECTED]>
Signed-off-by: Mike Christie <[EMAIL PROTECTED]>
---
 drivers/scsi/iscsi_tcp.c   |   16 
 drivers/scsi/iscsi_tcp.h   |   13 +++--
 drivers/scsi/libiscsi.c|   41 +++--
 include/scsi/iscsi_proto.h |   10 +-
 include/scsi/libiscsi.h|   33 +++--
 5 files changed, 94 insertions(+), 19 deletions(-)

diff --git a/drivers/scsi/iscsi_tcp.c b/drivers/scsi/iscsi_tcp.c
index fd88777..491845f 100644
--- a/drivers/scsi/iscsi_tcp.c
+++ b/drivers/scsi/iscsi_tcp.c
@@ -113,7 +113,7 @@ iscsi_hdr_digest(struct iscsi_conn *conn, struct iscsi_buf 
*buf,
struct iscsi_tcp_conn *tcp_conn = conn->dd_data;
 
crypto_hash_digest(&tcp_conn->tx_hash, &buf->sg, buf->sg.length, crc);
-   buf->sg.length += sizeof(u32);
+   buf->sg.length += ISCSI_DIGEST_SIZE;
 }
 
 /*
@@ -220,6 +220,7 @@ static inline int
 iscsi_tcp_chunk_done(struct iscsi_chunk *chunk)
 {
static unsigned char padbuf[ISCSI_PAD_LEN];
+   unsigned int pad;
 
if (chunk->copied < chunk->size) {
iscsi_tcp_chunk_map(chunk);
@@ -243,10 +244,8 @@ iscsi_tcp_chunk_done(struct iscsi_chunk *chunk)
}
 
/* Do we need to handle padding? */
-   if (chunk->total_copied & (ISCSI_PAD_LEN-1)) {
-   unsigned int pad;
-
-   pad = ISCSI_PAD_LEN - (chunk->total_copied & (ISCSI_PAD_LEN-1));
+   pad = iscsi_padding(chunk->total_copied);
+   if (pad != 0) {
debug_tcp("consume %d pad bytes\n", pad);
chunk->total_size += pad;
chunk->size = pad;
@@ -1385,11 +1384,11 @@ iscsi_send_cmd_hdr(struct iscsi_conn *conn, struct 
iscsi_cmd_task *ctask)
}
 
iscsi_buf_init_iov(&tcp_ctask->headbuf, (char*)ctask->hdr,
- sizeof(struct iscsi_hdr));
+ ctask->hdr_len);
 
if (conn->hdrdgst_en)
iscsi_hdr_digest(conn, &tcp_ctask->headbuf,
-(u8*)tcp_ctask->hdrext);
+iscsi_next_hdr(ctask));
tcp_ctask->xmstate &= ~XMSTATE_CMD_HDR_INIT;
tcp_ctask->xmstate |= XMSTATE_CMD_HDR_XMIT;
}
@@ -2176,7 +2175,8 @@ iscsi_tcp_session_create(struct iscsi_transport *iscsit,
struct iscsi_cmd_task *ctask = session->cmds[cmd_i];
struct iscsi_tcp_cmd_task *tcp_ctask = ctask->dd_data;
 
-   ctask->hdr = &tcp_ctask->hdr;
+   ctask->hdr = &tcp_ctask->hdr.cmd_hdr;
+   ctask->hdr_max = sizeof(tcp_ctask->hdr) - ISCSI_DIGEST_SIZE;
}
 
for (cmd_i = 0; cmd_i < session->mgmtpool_max; cmd_i++) {
diff --git a/drivers/scsi/iscsi_tcp.h b/drivers/scsi/iscsi_tcp.h
index f1c5411..eb3784f 100644
--- a/drivers/scsi/iscsi_tcp.h
+++ b/drivers/scsi/iscsi_tcp.h
@@ -41,7 +41,6 @@
 #define XMSTATE_IMM_HDR_INIT   0x1000
 #define XMSTATE_SOL_HDR_INIT   0x2000
 
-#define ISCSI_PAD_LEN  4
 #define ISCSI_SG_TABLESIZE SG_ALL
 #define ISCSI_TCP_MAX_CMD_LEN

[PATCH 12/23] iscsi_tcp: update the website URL

2007-12-04 Thread michaelc
From: FUJITA Tomonori <[EMAIL PROTECTED]>

Use open-iscsi.org instead of linux-iscsi.sf.net, which hasn't been
updated for ages.

Signed-off-by: FUJITA Tomonori <[EMAIL PROTECTED]>
Signed-off-by: Mike Christie <[EMAIL PROTECTED]>
---
 drivers/scsi/Kconfig |2 +-
 1 files changed, 1 insertions(+), 1 deletions(-)

diff --git a/drivers/scsi/Kconfig b/drivers/scsi/Kconfig
index a6676be..ab965f5 100644
--- a/drivers/scsi/Kconfig
+++ b/drivers/scsi/Kconfig
@@ -341,7 +341,7 @@ config ISCSI_TCP
 The userspace component needed to initialize the driver, documentation,
 and sample configuration files can be found here:
 
-http://linux-iscsi.sf.net
+http://open-iscsi.org
 
 config SGIWD93_SCSI
tristate "SGI WD93C93 SCSI Driver"
-- 
1.5.1.2

-
To unsubscribe from this list: send the line "unsubscribe linux-scsi" in
the body of a message to [EMAIL PROTECTED]
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATCH 03/23] Prettify resid handling and some extra checks

2007-12-04 Thread michaelc
From: Mike Christie <[EMAIL PROTECTED]>

from Boaz Harrosh:
  - Check to see that OVERFLOW is not negative indicating
a bug.
  - Unify handling of UNDERFLOW and OVERFLOW to the same
code.
  - Also handle BIDI_OVERFLOW.

Signed-off-by: Boaz Harrosh <[EMAIL PROTECTED]>
Signed-off-by: Mike Christie <[EMAIL PROTECTED]>
---
 drivers/scsi/iscsi_tcp.c |   16 +++-
 drivers/scsi/libiscsi.c  |   12 +++-
 2 files changed, 14 insertions(+), 14 deletions(-)

diff --git a/drivers/scsi/iscsi_tcp.c b/drivers/scsi/iscsi_tcp.c
index 1b540e0..fd88777 100644
--- a/drivers/scsi/iscsi_tcp.c
+++ b/drivers/scsi/iscsi_tcp.c
@@ -507,22 +507,20 @@ iscsi_data_rsp(struct iscsi_conn *conn, struct 
iscsi_cmd_task *ctask)
}
 
if (rhdr->flags & ISCSI_FLAG_DATA_STATUS) {
+   sc->result = (DID_OK << 16) | rhdr->cmd_status;
conn->exp_statsn = be32_to_cpu(rhdr->statsn) + 1;
-   if (rhdr->flags & ISCSI_FLAG_DATA_UNDERFLOW) {
+   if (rhdr->flags & (ISCSI_FLAG_DATA_UNDERFLOW |
+  ISCSI_FLAG_DATA_OVERFLOW)) {
int res_count = be32_to_cpu(rhdr->residual_count);
 
if (res_count > 0 &&
-   res_count <= scsi_bufflen(sc)) {
+   (rhdr->flags & ISCSI_FLAG_CMD_OVERFLOW ||
+res_count <= scsi_bufflen(sc)))
scsi_set_resid(sc, res_count);
-   sc->result = (DID_OK << 16) | rhdr->cmd_status;
-   } else
+   else
sc->result = (DID_BAD_TARGET << 16) |
rhdr->cmd_status;
-   } else if (rhdr->flags & ISCSI_FLAG_DATA_OVERFLOW) {
-   scsi_set_resid(sc, be32_to_cpu(rhdr->residual_count));
-   sc->result = (DID_OK << 16) | rhdr->cmd_status;
-   } else
-   sc->result = (DID_OK << 16) | rhdr->cmd_status;
+   }
}
 
conn->datain_pdus_cnt++;
diff --git a/drivers/scsi/libiscsi.c b/drivers/scsi/libiscsi.c
index 176458f..0beb4c6 100644
--- a/drivers/scsi/libiscsi.c
+++ b/drivers/scsi/libiscsi.c
@@ -291,17 +291,19 @@ invalid_datalen:
   min_t(uint16_t, senselen, SCSI_SENSE_BUFFERSIZE));
}
 
-   if (rhdr->flags & ISCSI_FLAG_CMD_UNDERFLOW) {
+   if (rhdr->flags & (ISCSI_FLAG_CMD_UNDERFLOW |
+  ISCSI_FLAG_CMD_OVERFLOW)) {
int res_count = be32_to_cpu(rhdr->residual_count);
 
-   if (res_count > 0 && res_count <= scsi_bufflen(sc))
+   if (res_count > 0 &&
+   (rhdr->flags & ISCSI_FLAG_CMD_OVERFLOW ||
+res_count <= scsi_bufflen(sc)))
scsi_set_resid(sc, res_count);
else
sc->result = (DID_BAD_TARGET << 16) | rhdr->cmd_status;
-   } else if (rhdr->flags & ISCSI_FLAG_CMD_BIDI_UNDERFLOW)
+   } else if (rhdr->flags & (ISCSI_FLAG_CMD_BIDI_UNDERFLOW |
+ ISCSI_FLAG_CMD_BIDI_OVERFLOW))
sc->result = (DID_BAD_TARGET << 16) | rhdr->cmd_status;
-   else if (rhdr->flags & ISCSI_FLAG_CMD_OVERFLOW)
-   scsi_set_resid(sc, be32_to_cpu(rhdr->residual_count));
 
 out:
debug_scsi("done [sc %lx res %d itt 0x%x]\n",
-- 
1.5.1.2

-
To unsubscribe from this list: send the line "unsubscribe linux-scsi" in
the body of a message to [EMAIL PROTECTED]
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATCH 22/23] libiscsi: use is_power_of_2

2007-12-04 Thread michaelc
From: Mike Christie <[EMAIL PROTECTED]>

Patch from vignesh babu <[EMAIL PROTECTED]>:

Replacing n & (n - 1) for power of 2 check by is_power_of_2(n)

Signed-off-by: vignesh babu <[EMAIL PROTECTED]>
Signed-off-by: Mike Christie <[EMAIL PROTECTED]>
---
 drivers/scsi/libiscsi.c |3 ++-
 1 files changed, 2 insertions(+), 1 deletions(-)

diff --git a/drivers/scsi/libiscsi.c b/drivers/scsi/libiscsi.c
index 6573223..553168a 100644
--- a/drivers/scsi/libiscsi.c
+++ b/drivers/scsi/libiscsi.c
@@ -24,6 +24,7 @@
 #include 
 #include 
 #include 
+#include 
 #include 
 #include 
 #include 
@@ -1700,7 +1701,7 @@ iscsi_session_setup(struct iscsi_transport *iscsit,
qdepth = ISCSI_DEF_CMD_PER_LUN;
}
 
-   if (cmds_max < 2 || (cmds_max & (cmds_max - 1)) ||
+   if (!is_power_of_2(cmds_max) ||
cmds_max >= ISCSI_MGMT_ITT_OFFSET) {
if (cmds_max != 0)
printk(KERN_ERR "iscsi: invalid can_queue of %d. "
-- 
1.5.1.2

-
To unsubscribe from this list: send the line "unsubscribe linux-scsi" in
the body of a message to [EMAIL PROTECTED]
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATCH 23/23] iscsi_tcp: fix setting of r2t

2007-12-04 Thread michaelc
From: Mike Christie <[EMAIL PROTECTED]>

If we negotiate for X r2ts we have to use only X r2ts. We cannot
round up (we could send less though). It is ok to fail if it
is not something the driver can handle, so this patch just does
that.

Signed-off-by: Mike Christie <[EMAIL PROTECTED]>
---
 drivers/scsi/iscsi_tcp.c |6 +++---
 1 files changed, 3 insertions(+), 3 deletions(-)

diff --git a/drivers/scsi/iscsi_tcp.c b/drivers/scsi/iscsi_tcp.c
index edebdf2..e5be5fd 100644
--- a/drivers/scsi/iscsi_tcp.c
+++ b/drivers/scsi/iscsi_tcp.c
@@ -1774,12 +1774,12 @@ iscsi_conn_set_param(struct iscsi_cls_conn *cls_conn, 
enum iscsi_param param,
break;
case ISCSI_PARAM_MAX_R2T:
sscanf(buf, "%d", &value);
-   if (session->max_r2t == roundup_pow_of_two(value))
+   if (value <= 0 || !is_power_of_2(value))
+   return -EINVAL;
+   if (session->max_r2t == value)
break;
iscsi_r2tpool_free(session);
iscsi_set_param(cls_conn, param, buf, buflen);
-   if (session->max_r2t & (session->max_r2t - 1))
-   session->max_r2t = roundup_pow_of_two(session->max_r2t);
if (iscsi_r2tpool_alloc(session))
return -ENOMEM;
break;
-- 
1.5.1.2

-
To unsubscribe from this list: send the line "unsubscribe linux-scsi" in
the body of a message to [EMAIL PROTECTED]
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATCH 20/23] iscsi_tcp: enable sg chaining

2007-12-04 Thread michaelc
From: Mike Christie <[EMAIL PROTECTED]>

The previous patches converted iscsi_tcp to support sg chaining.
This patch sets the proper flags and sets sg_table size to
4096. This allows fs io to be capped at max_sectors, but passthrough
IO to be limited by some other part of the kernel.

Signed-off-by: Mike Christie <[EMAIL PROTECTED]>
---
 drivers/scsi/iscsi_tcp.c |5 +++--
 drivers/scsi/iscsi_tcp.h |3 ---
 2 files changed, 3 insertions(+), 5 deletions(-)

diff --git a/drivers/scsi/iscsi_tcp.c b/drivers/scsi/iscsi_tcp.c
index 65df908..84c4a50 100644
--- a/drivers/scsi/iscsi_tcp.c
+++ b/drivers/scsi/iscsi_tcp.c
@@ -1928,13 +1928,14 @@ static struct scsi_host_template iscsi_sht = {
.queuecommand   = iscsi_queuecommand,
.change_queue_depth = iscsi_change_queue_depth,
.can_queue  = ISCSI_DEF_XMIT_CMDS_MAX - 1,
-   .sg_tablesize   = ISCSI_SG_TABLESIZE,
+   .sg_tablesize   = 4096,
.max_sectors= 0x,
.cmd_per_lun= ISCSI_DEF_CMD_PER_LUN,
.eh_abort_handler   = iscsi_eh_abort,
.eh_device_reset_handler= iscsi_eh_device_reset,
.eh_host_reset_handler  = iscsi_eh_host_reset,
.use_clustering = DISABLE_CLUSTERING,
+   .use_sg_chaining= ENABLE_SG_CHAINING,
.slave_configure= iscsi_tcp_slave_configure,
.proc_name  = "iscsi_tcp",
.this_id= -1,
@@ -1974,7 +1975,7 @@ static struct iscsi_transport iscsi_tcp_transport = {
.host_template  = &iscsi_sht,
.conndata_size  = sizeof(struct iscsi_conn),
.max_conn   = 1,
-   .max_cmd_len= ISCSI_TCP_MAX_CMD_LEN,
+   .max_cmd_len= 16,
/* session management */
.create_session = iscsi_tcp_session_create,
.destroy_session= iscsi_tcp_session_destroy,
diff --git a/drivers/scsi/iscsi_tcp.h b/drivers/scsi/iscsi_tcp.h
index 893cd2e..ed0b991 100644
--- a/drivers/scsi/iscsi_tcp.h
+++ b/drivers/scsi/iscsi_tcp.h
@@ -24,9 +24,6 @@
 
 #include 
 
-#define ISCSI_SG_TABLESIZE SG_ALL
-#define ISCSI_TCP_MAX_CMD_LEN  16
-
 struct crypto_hash;
 struct socket;
 struct iscsi_tcp_conn;
-- 
1.5.1.2

-
To unsubscribe from this list: send the line "unsubscribe linux-scsi" in
the body of a message to [EMAIL PROTECTED]
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATCH 21/23] iscsi_tcp: hold lock during data rsp processing

2007-12-04 Thread michaelc
From: Mike Christie <[EMAIL PROTECTED]>

iscsi_data_rsp needs to hold the sesison lock when it calls
iscsi_update_cmdsn.

Signed-off-by: Mike Christie <[EMAIL PROTECTED]>
---
 drivers/scsi/iscsi_tcp.c |   14 ++
 1 files changed, 6 insertions(+), 8 deletions(-)

diff --git a/drivers/scsi/iscsi_tcp.c b/drivers/scsi/iscsi_tcp.c
index 84c4a50..edebdf2 100644
--- a/drivers/scsi/iscsi_tcp.c
+++ b/drivers/scsi/iscsi_tcp.c
@@ -641,13 +641,11 @@ iscsi_r2t_rsp(struct iscsi_conn *conn, struct 
iscsi_cmd_task *ctask)
}
 
/* fill-in new R2T associated with the task */
-   spin_lock(&session->lock);
iscsi_update_cmdsn(session, (struct iscsi_nopin*)rhdr);
 
if (!ctask->sc || session->state != ISCSI_STATE_LOGGED_IN) {
printk(KERN_INFO "iscsi_tcp: dropping R2T itt %d in "
   "recovery...\n", ctask->itt);
-   spin_unlock(&session->lock);
return 0;
}
 
@@ -660,7 +658,6 @@ iscsi_r2t_rsp(struct iscsi_conn *conn, struct 
iscsi_cmd_task *ctask)
printk(KERN_ERR "iscsi_tcp: invalid R2T with zero data len\n");
__kfifo_put(tcp_ctask->r2tpool.queue, (void*)&r2t,
sizeof(void*));
-   spin_unlock(&session->lock);
return ISCSI_ERR_DATALEN;
}
 
@@ -676,7 +673,6 @@ iscsi_r2t_rsp(struct iscsi_conn *conn, struct 
iscsi_cmd_task *ctask)
   r2t->data_offset, scsi_bufflen(ctask->sc));
__kfifo_put(tcp_ctask->r2tpool.queue, (void*)&r2t,
sizeof(void*));
-   spin_unlock(&session->lock);
return ISCSI_ERR_DATALEN;
}
 
@@ -690,8 +686,6 @@ iscsi_r2t_rsp(struct iscsi_conn *conn, struct 
iscsi_cmd_task *ctask)
conn->r2t_pdus_cnt++;
 
iscsi_requeue_ctask(ctask);
-   spin_unlock(&session->lock);
-
return 0;
 }
 
@@ -764,7 +758,9 @@ iscsi_tcp_hdr_dissect(struct iscsi_conn *conn, struct 
iscsi_hdr *hdr)
switch(opcode) {
case ISCSI_OP_SCSI_DATA_IN:
ctask = session->cmds[itt];
+   spin_lock(&conn->session->lock);
rc = iscsi_data_rsp(conn, ctask);
+   spin_unlock(&conn->session->lock);
if (rc)
return rc;
if (tcp_conn->in.datalen) {
@@ -806,9 +802,11 @@ iscsi_tcp_hdr_dissect(struct iscsi_conn *conn, struct 
iscsi_hdr *hdr)
ctask = session->cmds[itt];
if (ahslen)
rc = ISCSI_ERR_AHSLEN;
-   else if (ctask->sc->sc_data_direction == DMA_TO_DEVICE)
+   else if (ctask->sc->sc_data_direction == DMA_TO_DEVICE) {
+   spin_lock(&session->lock);
rc = iscsi_r2t_rsp(conn, ctask);
-   else
+   spin_unlock(&session->lock);
+   } else
rc = ISCSI_ERR_PROTO;
break;
case ISCSI_OP_LOGIN_RSP:
-- 
1.5.1.2

-
To unsubscribe from this list: send the line "unsubscribe linux-scsi" in
the body of a message to [EMAIL PROTECTED]
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATCH 18/23] iscsi_tcp: drop session when itt does not match any command

2007-12-04 Thread michaelc
From: Mike Christie <[EMAIL PROTECTED]>

A target should never send us a itt that does not match a running
task. If it does we do not really know what is coming down after the header,
unless we evaluate the hdr and do some guessing sometimes. However,
even if we know what is coming we probably do not have buffers for it or we
cannot respond (if it is a r2t for example), so just drop the session.

Signed-off-by: Mike Christie <[EMAIL PROTECTED]>
---
 drivers/scsi/iscsi_tcp.c |6 +-
 1 files changed, 1 insertions(+), 5 deletions(-)

diff --git a/drivers/scsi/iscsi_tcp.c b/drivers/scsi/iscsi_tcp.c
index ecba606..65df908 100644
--- a/drivers/scsi/iscsi_tcp.c
+++ b/drivers/scsi/iscsi_tcp.c
@@ -755,11 +755,7 @@ iscsi_tcp_hdr_dissect(struct iscsi_conn *conn, struct 
iscsi_hdr *hdr)
opcode = hdr->opcode & ISCSI_OPCODE_MASK;
/* verify itt (itt encoding: age+cid+itt) */
rc = iscsi_verify_itt(conn, hdr, &itt);
-   if (rc == ISCSI_ERR_NO_SCSI_CMD) {
-   /* XXX: what does this do? */
-   tcp_conn->in.datalen = 0; /* force drop */
-   return 0;
-   } else if (rc)
+   if (rc)
return rc;
 
debug_tcp("opcode 0x%x ahslen %d datalen %d\n",
-- 
1.5.1.2

-
To unsubscribe from this list: send the line "unsubscribe linux-scsi" in
the body of a message to [EMAIL PROTECTED]
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATCH 19/23] libiscsi, iscsi class: set tmf to a safe default and export in sysfs

2007-12-04 Thread michaelc
From: Mike Christie <[EMAIL PROTECTED]>

Older tools will not be setting the tmf time outs since they
did not exists, so set them to a safe default.

And export abort and lu reset timeout values in sysfs.

Signed-off-by: Mike Christie <[EMAIL PROTECTED]>
---
 drivers/scsi/libiscsi.c |2 ++
 drivers/scsi/scsi_transport_iscsi.c |8 ++--
 2 files changed, 8 insertions(+), 2 deletions(-)

diff --git a/drivers/scsi/libiscsi.c b/drivers/scsi/libiscsi.c
index f15df8d..6573223 100644
--- a/drivers/scsi/libiscsi.c
+++ b/drivers/scsi/libiscsi.c
@@ -1732,6 +1732,8 @@ iscsi_session_setup(struct iscsi_transport *iscsit,
session->host = shost;
session->state = ISCSI_STATE_FREE;
session->fast_abort = 1;
+   session->lu_reset_timeout = 15;
+   session->abort_timeout = 10;
session->mgmtpool_max = ISCSI_MGMT_CMDS_MAX;
session->cmds_max = cmds_max;
session->queued_cmdsn = session->cmdsn = initial_cmdsn;
diff --git a/drivers/scsi/scsi_transport_iscsi.c 
b/drivers/scsi/scsi_transport_iscsi.c
index fb8a765..d3db318 100644
--- a/drivers/scsi/scsi_transport_iscsi.c
+++ b/drivers/scsi/scsi_transport_iscsi.c
@@ -30,7 +30,7 @@
 #include 
 #include 
 
-#define ISCSI_SESSION_ATTRS 16
+#define ISCSI_SESSION_ATTRS 18
 #define ISCSI_CONN_ATTRS 11
 #define ISCSI_HOST_ATTRS 4
 #define ISCSI_TRANSPORT_VERSION "2.0-724"
@@ -1241,7 +1241,9 @@ iscsi_session_attr(username, ISCSI_PARAM_USERNAME, 1);
 iscsi_session_attr(username_in, ISCSI_PARAM_USERNAME_IN, 1);
 iscsi_session_attr(password, ISCSI_PARAM_PASSWORD, 1);
 iscsi_session_attr(password_in, ISCSI_PARAM_PASSWORD_IN, 1);
-iscsi_session_attr(fast_abort, ISCSI_PARAM_FAST_ABORT, 1);
+iscsi_session_attr(fast_abort, ISCSI_PARAM_FAST_ABORT, 0);
+iscsi_session_attr(abort_tmo, ISCSI_PARAM_ABORT_TMO, 0);
+iscsi_session_attr(lu_reset_tmo, ISCSI_PARAM_LU_RESET_TMO, 0);
 
 #define iscsi_priv_session_attr_show(field, format)\
 static ssize_t \
@@ -1466,6 +1468,8 @@ iscsi_register_transport(struct iscsi_transport *tt)
SETUP_SESSION_RD_ATTR(username, ISCSI_PASSWORD);
SETUP_SESSION_RD_ATTR(username_in, ISCSI_PASSWORD_IN);
SETUP_SESSION_RD_ATTR(fast_abort, ISCSI_FAST_ABORT);
+   SETUP_SESSION_RD_ATTR(abort_tmo, ISCSI_ABORT_TMO);
+   SETUP_SESSION_RD_ATTR(lu_reset_tmo,ISCSI_LU_RESET_TMO);
SETUP_PRIV_SESSION_RD_ATTR(recovery_tmo);
 
BUG_ON(count > ISCSI_SESSION_ATTRS);
-- 
1.5.1.2

-
To unsubscribe from this list: send the line "unsubscribe linux-scsi" in
the body of a message to [EMAIL PROTECTED]
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATCH 06/23] libiscsi, iscsi_tcp: iscsi pool cleanup

2007-12-04 Thread michaelc
From: Mike Christie <[EMAIL PROTECTED]>

from [EMAIL PROTECTED]

iscsi_pool_init simplified

iscsi_pool_init currently has a lot of duplicate kfree() calls it does
when some allocation fails. This patch simplifies the code a little by
using iscsi_pool_free to tear down the pool in case of an error.

iscsi_pool_init also returns a copy of the item array to the caller.
Not all callers use this array, so we make it optional.

Instead of allocating a second array and return that, allocate just one
array, of twice the size.

Update users of iscsi_pool_{init,free}

This patch drops the (now useless) second argument to
iscsi_pool_free, and updates all callers.

It also removes the ctask->r2ts array, which was never
used anyway. Since the items argument to iscsi_pool_init
is now optional, we can pass NULL instead.

Signed-off-by: Olaf Kirch <[EMAIL PROTECTED]>
Signed-off-by: Mike Christie <[EMAIL PROTECTED]>
---
 drivers/scsi/iscsi_tcp.c |   12 ++-
 drivers/scsi/iscsi_tcp.h |3 +-
 drivers/scsi/libiscsi.c  |   75 -
 include/scsi/libiscsi.h  |   10 +++---
 4 files changed, 50 insertions(+), 50 deletions(-)

diff --git a/drivers/scsi/iscsi_tcp.c b/drivers/scsi/iscsi_tcp.c
index 491845f..f79a457 100644
--- a/drivers/scsi/iscsi_tcp.c
+++ b/drivers/scsi/iscsi_tcp.c
@@ -1998,8 +1998,7 @@ iscsi_r2tpool_alloc(struct iscsi_session *session)
 */
 
/* R2T pool */
-   if (iscsi_pool_init(&tcp_ctask->r2tpool, session->max_r2t * 4,
-   (void***)&tcp_ctask->r2ts,
+   if (iscsi_pool_init(&tcp_ctask->r2tpool, session->max_r2t * 4, 
NULL,
sizeof(struct iscsi_r2t_info))) {
goto r2t_alloc_fail;
}
@@ -2008,8 +2007,7 @@ iscsi_r2tpool_alloc(struct iscsi_session *session)
tcp_ctask->r2tqueue = kfifo_alloc(
  session->max_r2t * 4 * sizeof(void*), GFP_KERNEL, NULL);
if (tcp_ctask->r2tqueue == ERR_PTR(-ENOMEM)) {
-   iscsi_pool_free(&tcp_ctask->r2tpool,
-   (void**)tcp_ctask->r2ts);
+   iscsi_pool_free(&tcp_ctask->r2tpool);
goto r2t_alloc_fail;
}
}
@@ -2022,8 +2020,7 @@ r2t_alloc_fail:
struct iscsi_tcp_cmd_task *tcp_ctask = ctask->dd_data;
 
kfifo_free(tcp_ctask->r2tqueue);
-   iscsi_pool_free(&tcp_ctask->r2tpool,
-   (void**)tcp_ctask->r2ts);
+   iscsi_pool_free(&tcp_ctask->r2tpool);
}
return -ENOMEM;
 }
@@ -2038,8 +2035,7 @@ iscsi_r2tpool_free(struct iscsi_session *session)
struct iscsi_tcp_cmd_task *tcp_ctask = ctask->dd_data;
 
kfifo_free(tcp_ctask->r2tqueue);
-   iscsi_pool_free(&tcp_ctask->r2tpool,
-   (void**)tcp_ctask->r2ts);
+   iscsi_pool_free(&tcp_ctask->r2tpool);
}
 }
 
diff --git a/drivers/scsi/iscsi_tcp.h b/drivers/scsi/iscsi_tcp.h
index eb3784f..d49d876 100644
--- a/drivers/scsi/iscsi_tcp.h
+++ b/drivers/scsi/iscsi_tcp.h
@@ -175,9 +175,8 @@ struct iscsi_tcp_cmd_task {
uint32_texp_datasn; /* expected target's 
R2TSN/DataSN */
int data_offset;
struct iscsi_r2t_info   *r2t;   /* in progress R2T*/
-   struct iscsi_queue  r2tpool;
+   struct iscsi_pool   r2tpool;
struct kfifo*r2tqueue;
-   struct iscsi_r2t_info   **r2ts;
int digest_count;
uint32_timmdigest;  /* for imm data */
struct iscsi_bufimmbuf; /* for imm data digest 
*/
diff --git a/drivers/scsi/libiscsi.c b/drivers/scsi/libiscsi.c
index 5936586..d43f909 100644
--- a/drivers/scsi/libiscsi.c
+++ b/drivers/scsi/libiscsi.c
@@ -1413,59 +1413,64 @@ done:
 }
 EXPORT_SYMBOL_GPL(iscsi_eh_device_reset);
 
+/*
+ * Pre-allocate a pool of @max items of @item_size. By default, the pool
+ * should be accessed via kfifo_{get,put} on q->queue.
+ * Optionally, the caller can obtain the array of object pointers
+ * by passing in a non-NULL @items pointer
+ */
 int
-iscsi_pool_init(struct iscsi_queue *q, int max, void ***items, int item_size)
+iscsi_pool_init(struct iscsi_pool *q, int max, void ***items, int item_size)
 {
-   int i;
+   int i, num_arrays = 1;
 
-   *items = kmalloc(max * sizeof(void*), GFP_KERNEL);
-   if (*items == NULL)
-   return -ENOMEM;
+   memset(q, 0, sizeof(*q));
 
q->max = max;
-   q->pool = kmalloc(max * sizeof(void*), GFP_KERNEL);
-   if (q->pool == NULL) {
-   kfree(*items);
-   return -ENOMEM;
-   }
+
+   /* If the user passed an items pointer, he wants a copy of
+* the array. */
+

[PATCH 02/23] iscsi_tcp: rewrite recv path

2007-12-04 Thread michaelc
From: Mike Christie <[EMAIL PROTECTED]>

>From Olaf Kirch:

Rewrite recv path. Fixes:
- data digest processing and error handling.
- ahs support.

Some fixups by Mike Christie

Signed-off-by: [EMAIL PROTECTED]
Signed-off-by: Mike Christie <[EMAIL PROTECTED]>
---
 drivers/scsi/iscsi_tcp.c | 1018 +++---
 drivers/scsi/iscsi_tcp.h |   66 ++--
 include/scsi/libiscsi.h  |4 +
 3 files changed, 552 insertions(+), 536 deletions(-)

diff --git a/drivers/scsi/iscsi_tcp.c b/drivers/scsi/iscsi_tcp.c
index 4b226b8..1b540e0 100644
--- a/drivers/scsi/iscsi_tcp.c
+++ b/drivers/scsi/iscsi_tcp.c
@@ -48,7 +48,7 @@ MODULE_AUTHOR("Dmitry Yusupov <[EMAIL PROTECTED]>, "
  "Alex Aizman <[EMAIL PROTECTED]>");
 MODULE_DESCRIPTION("iSCSI/TCP data-path");
 MODULE_LICENSE("GPL");
-/* #define DEBUG_TCP */
+#undef DEBUG_TCP
 #define DEBUG_ASSERT
 
 #ifdef DEBUG_TCP
@@ -67,10 +67,15 @@ MODULE_LICENSE("GPL");
 static unsigned int iscsi_max_lun = 512;
 module_param_named(max_lun, iscsi_max_lun, uint, S_IRUGO);
 
+static int iscsi_tcp_hdr_recv_done(struct iscsi_tcp_conn *tcp_conn,
+  struct iscsi_chunk *chunk);
+
 static inline void
 iscsi_buf_init_iov(struct iscsi_buf *ibuf, char *vbuf, int size)
 {
-   sg_init_one(&ibuf->sg, vbuf, size);
+   ibuf->sg.page = virt_to_page(vbuf);
+   ibuf->sg.offset = offset_in_page(vbuf);
+   ibuf->sg.length = size;
ibuf->sent = 0;
ibuf->use_sendmsg = 1;
 }
@@ -78,12 +83,13 @@ iscsi_buf_init_iov(struct iscsi_buf *ibuf, char *vbuf, int 
size)
 static inline void
 iscsi_buf_init_sg(struct iscsi_buf *ibuf, struct scatterlist *sg)
 {
-   sg_init_table(&ibuf->sg, 1);
-   sg_set_page(&ibuf->sg, sg_page(sg), sg->length, sg->offset);
+   ibuf->sg.page = sg->page;
+   ibuf->sg.offset = sg->offset;
+   ibuf->sg.length = sg->length;
/*
 * Fastpath: sg element fits into single page
 */
-   if (sg->length + sg->offset <= PAGE_SIZE && !PageSlab(sg_page(sg)))
+   if (sg->length + sg->offset <= PAGE_SIZE && !PageSlab(sg->page))
ibuf->use_sendmsg = 0;
else
ibuf->use_sendmsg = 1;
@@ -110,72 +116,331 @@ iscsi_hdr_digest(struct iscsi_conn *conn, struct 
iscsi_buf *buf,
buf->sg.length += sizeof(u32);
 }
 
+/*
+ * Scatterlist handling: inside the iscsi_chunk, we
+ * remember an index into the scatterlist, and set data/size
+ * to the current scatterlist entry. For highmem pages, we
+ * kmap as needed.
+ *
+ * Note that the page is unmapped when we return from
+ * TCP's data_ready handler, so we may end up mapping and
+ * unmapping the same page repeatedly. The whole reason
+ * for this is that we shouldn't keep the page mapped
+ * outside the softirq.
+ */
+
+/**
+ * iscsi_tcp_chunk_init_sg - init indicated scatterlist entry
+ * @chunk: the buffer object
+ * @idx: index into scatterlist
+ * @offset: byte offset into that sg entry
+ *
+ * This function sets up the chunk so that subsequent
+ * data is copied to the indicated sg entry, at the given
+ * offset.
+ */
+static inline void
+iscsi_tcp_chunk_init_sg(struct iscsi_chunk *chunk,
+   unsigned int idx, unsigned int offset)
+{
+   struct scatterlist *sg;
+
+   BUG_ON(chunk->sg == NULL);
+
+   sg = &chunk->sg[idx];
+   chunk->sg_index = idx;
+   chunk->sg_offset = offset;
+   chunk->size = min(sg->length - offset, chunk->total_size);
+   chunk->data = NULL;
+}
+
+/**
+ * iscsi_tcp_chunk_map - map the current S/G page
+ * @chunk: iscsi chunk
+ *
+ * We only need to possibly kmap data if scatter lists are being used,
+ * because the iscsi passthrough and internal IO paths will never use high
+ * mem pages.
+ */
+static inline void
+iscsi_tcp_chunk_map(struct iscsi_chunk *chunk)
+{
+   struct scatterlist *sg;
+
+   if (chunk->data != NULL || !chunk->sg)
+   return;
+
+   sg = &chunk->sg[chunk->sg_index];
+   BUG_ON(chunk->sg_mapped);
+   BUG_ON(sg->length == 0);
+   chunk->sg_mapped = kmap_atomic(sg->page, KM_SOFTIRQ0);
+   chunk->data = chunk->sg_mapped + sg->offset + chunk->sg_offset;
+}
+
+static inline void
+iscsi_tcp_chunk_unmap(struct iscsi_chunk *chunk)
+{
+   if (chunk->sg_mapped) {
+   kunmap_atomic(chunk->sg_mapped, KM_SOFTIRQ0);
+   chunk->sg_mapped = NULL;
+   chunk->data = NULL;
+   }
+}
+
+/*
+ * Splice the digest buffer into the buffer
+ */
+static inline void
+iscsi_tcp_chunk_splice_digest(struct iscsi_chunk *chunk, void *digest)
+{
+   chunk->data = digest;
+   chunk->digest_len = ISCSI_DIGEST_SIZE;
+   chunk->total_size += ISCSI_DIGEST_SIZE;
+   chunk->size = ISCSI_DIGEST_SIZE;
+   chunk->copied = 0;
+   chunk->sg = NULL;
+   chunk->sg_index = 0;
+   chunk->hash = NULL;
+}
+
+/**
+ * iscsi_tcp_chunk_done - check whether the chunk is complete
+ * @chunk: iscsi chunk to check
+ *
+ * Check 

[PATCH 15/23] Drop host lock in queuecommand

2007-12-04 Thread michaelc
From: Mike Christie <[EMAIL PROTECTED]>

The driver does not need the host lock in queuecommand so drop it.

Signed-off-by: Mike Christie <[EMAIL PROTECTED]>
---
 drivers/scsi/libiscsi.c |6 +-
 1 files changed, 5 insertions(+), 1 deletions(-)

diff --git a/drivers/scsi/libiscsi.c b/drivers/scsi/libiscsi.c
index 4461317..b0bc8c3 100644
--- a/drivers/scsi/libiscsi.c
+++ b/drivers/scsi/libiscsi.c
@@ -1010,8 +1010,9 @@ int iscsi_queuecommand(struct scsi_cmnd *sc, void 
(*done)(struct scsi_cmnd *))
sc->SCp.ptr = NULL;
 
host = sc->device->host;
-   session = iscsi_hostdata(host->hostdata);
+   spin_unlock(host->host_lock);
 
+   session = iscsi_hostdata(host->hostdata);
spin_lock(&session->lock);
 
/*
@@ -1077,11 +1078,13 @@ int iscsi_queuecommand(struct scsi_cmnd *sc, void 
(*done)(struct scsi_cmnd *))
spin_unlock(&session->lock);
 
scsi_queue_work(host, &conn->xmitwork);
+   spin_lock(host->host_lock);
return 0;
 
 reject:
spin_unlock(&session->lock);
debug_scsi("cmd 0x%x rejected (%d)\n", sc->cmnd[0], reason);
+   spin_lock(host->host_lock);
return SCSI_MLQUEUE_HOST_BUSY;
 
 fault:
@@ -1091,6 +1094,7 @@ fault:
sc->result = (DID_NO_CONNECT << 16);
scsi_set_resid(sc, scsi_bufflen(sc));
sc->scsi_done(sc);
+   spin_lock(host->host_lock);
return 0;
 }
 EXPORT_SYMBOL_GPL(iscsi_queuecommand);
-- 
1.5.1.2

-
To unsubscribe from this list: send the line "unsubscribe linux-scsi" in
the body of a message to [EMAIL PROTECTED]
More majordomo info at  http://vger.kernel.org/majordomo-info.html


  1   2   >