- Fixes incorrect allocation length 0 by scst_user module
authorvlnb <vlnb@d57e44dd-8a1f-0410-8b47-8ef2f437770f>
Mon, 23 Jun 2008 16:32:51 +0000 (16:32 +0000)
committervlnb <vlnb@d57e44dd-8a1f-0410-8b47-8ef2f437770f>
Mon, 23 Jun 2008 16:32:51 +0000 (16:32 +0000)
 - Fixes missed case of "allocation length 0 for READ6/WRITE6 means 256".

git-svn-id: https://scst.svn.sourceforge.net/svnroot/scst/trunk@420 d57e44dd-8a1f-0410-8b47-8ef2f437770f

scst/src/dev_handlers/scst_user.c
scst/src/scst_cdbprobe.h
scst/src/scst_lib.c

index 2dcd3ec..68654b9 100644 (file)
@@ -490,6 +490,12 @@ static int dev_user_alloc_sg(struct scst_user_cmd *ucmd, int cached_buff)
 
        TRACE_ENTRY();
 
+       /* User space can return from PARSE bufflen 0 and direction non-NONE */
+       if (unlikely(bufflen == 0)) {
+               cmd->data_direction = SCST_DATA_NONE;
+               goto out;
+       }
+
        gfp_mask = __GFP_NOWARN;
        gfp_mask |= (scst_cmd_atomic(cmd) ? GFP_ATOMIC : GFP_KERNEL);
 
index ac0dcf8..c4b94e8 100644 (file)
@@ -23,6 +23,7 @@
 
 /* get_trans_len_x extract x bytes from cdb as length starting from off */
 static int get_trans_len_1(struct scst_cmd *cmd, uint8_t off);
+static int get_trans_len_1_256(struct scst_cmd *cmd, uint8_t off);
 static int get_trans_len_2(struct scst_cmd *cmd, uint8_t off);
 static int get_trans_len_3(struct scst_cmd *cmd, uint8_t off);
 static int get_trans_len_4(struct scst_cmd *cmd, uint8_t off);
@@ -131,7 +132,7 @@ static const struct scst_sdbops scst_scsi_op_table[] = {
        {0x07, "OVV O  OV       ", "REASSIGN BLOCKS",
         SCST_DATA_NONE, FLAG_NONE, 0, get_trans_len_none},
        {0x08, "O               ", "READ(6)",
-        SCST_DATA_READ, SCST_TRANSFER_LEN_TYPE_FIXED, 4, get_trans_len_1},
+        SCST_DATA_READ, SCST_TRANSFER_LEN_TYPE_FIXED, 4, get_trans_len_1_256},
        {0x08, " MV OO OV       ", "READ(6)",
         SCST_DATA_READ, SCST_TRANSFER_LEN_TYPE_FIXED, 2, get_trans_len_3},
        {0x08, "         M      ", "GET MESSAGE(6)",
@@ -141,7 +142,7 @@ static const struct scst_sdbops scst_scsi_op_table[] = {
        {0x09, "VVVVVV  V       ", "",
         SCST_DATA_NONE, FLAG_NONE, 0, get_trans_len_none},
        {0x0A, "O               ", "WRITE(6)",
-        SCST_DATA_WRITE, SCST_TRANSFER_LEN_TYPE_FIXED, 4, get_trans_len_1},
+        SCST_DATA_WRITE, SCST_TRANSFER_LEN_TYPE_FIXED, 4, get_trans_len_1_256},
        {0x0A, " M  O  OV       ", "WRITE(6)",
         SCST_DATA_WRITE, SCST_TRANSFER_LEN_TYPE_FIXED, 2, get_trans_len_3},
        {0x0A, "  M             ", "PRINT",
index 2b1638b..e4d0a9c 100644 (file)
@@ -1657,6 +1657,7 @@ int scst_alloc_space(struct scst_cmd *cmd)
                flags |= SCST_POOL_ALLOC_NO_CACHED;
 
        if (unlikely(cmd->bufflen == 0)) {
+               /* ToDo: remove when 1.0.1 will be started */
                TRACE(TRACE_MGMT_MINOR, "Warning: data direction %d or/and "
                        "zero buffer length. Opcode 0x%x, handler %s, target "
                        "%s", cmd->data_direction, cmd->cdb[0],
@@ -1811,6 +1812,14 @@ static int get_trans_len_1(struct scst_cmd *cmd, uint8_t off)
        return 0;
 }
 
+static int get_trans_len_1_256(struct scst_cmd *cmd, uint8_t off)
+{
+       cmd->bufflen = (u32)cmd->cdb[off];
+       if (cmd->bufflen == 0)
+               cmd->bufflen = 256;
+       return 0;
+}
+
 static int get_trans_len_2(struct scst_cmd *cmd, uint8_t off)
 {
        const uint8_t *p = cmd->cdb + off;
@@ -1907,6 +1916,15 @@ int scst_get_cdb_info(struct scst_cmd *cmd)
        cmd->data_direction = ptr->direction;
        cmd->op_flags = ptr->flags;
        res = (*ptr->get_trans_len)(cmd, ptr->off);
+#if 0 /* ToDo: enable when 1.0.1 will be started and fix all scst_get_buf_first() returns 0 cases */
+       if (unlikely(cmd->bufflen == 0)) {
+               /*
+                * According to SPC bufflen 0 for data transfer commands isn't
+                * an error, so we need to fix the transfer direction.
+                */
+               cmd->data_direction = SCST_DATA_NONE;
+       }
+#endif
 
 out:
        TRACE_EXIT();