aboutsummaryrefslogtreecommitdiff
path: root/drivers/target/target_core_alua.c
diff options
context:
space:
mode:
authorAndy Grover <agrover@redhat.com>2011-07-20 19:13:28 +0000
committerNicholas Bellinger <nab@linux-iscsi.org>2011-07-22 09:37:48 +0000
commit05d1c7c0d0db4cc25548d9aadebb416888a82327 (patch)
tree290243526d188a7f6a683b0e13a63c7207471fa1 /drivers/target/target_core_alua.c
parente22a7f075226c51f3f71b922e9eeb4f99fac1475 (diff)
downloadvexpress-lsk-05d1c7c0d0db4cc25548d9aadebb416888a82327.tar.gz
target: Make all control CDBs scatter-gather
Previously, some control CDBs did not allocate memory in pages for their data buffer, but just did a kmalloc. This patch makes all cdbs allocate pages. This has the benefit of streamlining some paths that had to behave differently when we used two allocation methods. The downside is that all accesses to the data buffer need to kmap it before use, and need to handle data in page-sized chunks if more than a page is needed for a given command's data buffer. Finally, note that cdbs with no data buffers are handled a little differently. Before, SCSI_NON_DATA_CDBs would not call get_mem at all (they'd be in the final else in transport_allocate_resources) but now these will make it into generic_get_mem, but just not allocate any buffers. Signed-off-by: Andy Grover <agrover@redhat.com> Signed-off-by: Nicholas Bellinger <nab@linux-iscsi.org>
Diffstat (limited to 'drivers/target/target_core_alua.c')
-rw-r--r--drivers/target/target_core_alua.c42
1 files changed, 31 insertions, 11 deletions
diff --git a/drivers/target/target_core_alua.c b/drivers/target/target_core_alua.c
index 76d506fe99e..dba412ff371 100644
--- a/drivers/target/target_core_alua.c
+++ b/drivers/target/target_core_alua.c
@@ -65,10 +65,12 @@ int core_emulate_report_target_port_groups(struct se_cmd *cmd)
struct se_port *port;
struct t10_alua_tg_pt_gp *tg_pt_gp;
struct t10_alua_tg_pt_gp_member *tg_pt_gp_mem;
- unsigned char *buf = (unsigned char *)cmd->t_task_buf;
+ unsigned char *buf;
u32 rd_len = 0, off = 4; /* Skip over RESERVED area to first
Target port group descriptor */
+ buf = transport_kmap_first_data_page(cmd);
+
spin_lock(&su_dev->t10_alua.tg_pt_gps_lock);
list_for_each_entry(tg_pt_gp, &su_dev->t10_alua.tg_pt_gps_list,
tg_pt_gp_list) {
@@ -141,6 +143,8 @@ int core_emulate_report_target_port_groups(struct se_cmd *cmd)
buf[2] = ((rd_len >> 8) & 0xff);
buf[3] = (rd_len & 0xff);
+ transport_kunmap_first_data_page(cmd);
+
return 0;
}
@@ -157,14 +161,17 @@ int core_emulate_set_target_port_groups(struct se_cmd *cmd)
struct se_node_acl *nacl = cmd->se_sess->se_node_acl;
struct t10_alua_tg_pt_gp *tg_pt_gp = NULL, *l_tg_pt_gp;
struct t10_alua_tg_pt_gp_member *tg_pt_gp_mem, *l_tg_pt_gp_mem;
- unsigned char *buf = (unsigned char *)cmd->t_task_buf;
- unsigned char *ptr = &buf[4]; /* Skip over RESERVED area in header */
+ unsigned char *buf;
+ unsigned char *ptr;
u32 len = 4; /* Skip over RESERVED area in header */
int alua_access_state, primary = 0, rc;
u16 tg_pt_id, rtpi;
if (!(l_port))
return PYX_TRANSPORT_LU_COMM_FAILURE;
+
+ buf = transport_kmap_first_data_page(cmd);
+
/*
* Determine if explict ALUA via SET_TARGET_PORT_GROUPS is allowed
* for the local tg_pt_gp.
@@ -172,14 +179,16 @@ int core_emulate_set_target_port_groups(struct se_cmd *cmd)
l_tg_pt_gp_mem = l_port->sep_alua_tg_pt_gp_mem;
if (!(l_tg_pt_gp_mem)) {
printk(KERN_ERR "Unable to access l_port->sep_alua_tg_pt_gp_mem\n");
- return PYX_TRANSPORT_UNKNOWN_SAM_OPCODE;
+ rc = PYX_TRANSPORT_UNKNOWN_SAM_OPCODE;
+ goto out;
}
spin_lock(&l_tg_pt_gp_mem->tg_pt_gp_mem_lock);
l_tg_pt_gp = l_tg_pt_gp_mem->tg_pt_gp;
if (!(l_tg_pt_gp)) {
spin_unlock(&l_tg_pt_gp_mem->tg_pt_gp_mem_lock);
printk(KERN_ERR "Unable to access *l_tg_pt_gp_mem->tg_pt_gp\n");
- return PYX_TRANSPORT_UNKNOWN_SAM_OPCODE;
+ rc = PYX_TRANSPORT_UNKNOWN_SAM_OPCODE;
+ goto out;
}
rc = (l_tg_pt_gp->tg_pt_gp_alua_access_type & TPGS_EXPLICT_ALUA);
spin_unlock(&l_tg_pt_gp_mem->tg_pt_gp_mem_lock);
@@ -187,9 +196,12 @@ int core_emulate_set_target_port_groups(struct se_cmd *cmd)
if (!(rc)) {
printk(KERN_INFO "Unable to process SET_TARGET_PORT_GROUPS"
" while TPGS_EXPLICT_ALUA is disabled\n");
- return PYX_TRANSPORT_UNKNOWN_SAM_OPCODE;
+ rc = PYX_TRANSPORT_UNKNOWN_SAM_OPCODE;
+ goto out;
}
+ ptr = &buf[4]; /* Skip over RESERVED area in header */
+
while (len < cmd->data_length) {
alua_access_state = (ptr[0] & 0x0f);
/*
@@ -209,7 +221,8 @@ int core_emulate_set_target_port_groups(struct se_cmd *cmd)
* REQUEST, and the additional sense code set to INVALID
* FIELD IN PARAMETER LIST.
*/
- return PYX_TRANSPORT_INVALID_PARAMETER_LIST;
+ rc = PYX_TRANSPORT_INVALID_PARAMETER_LIST;
+ goto out;
}
rc = -1;
/*
@@ -260,8 +273,10 @@ int core_emulate_set_target_port_groups(struct se_cmd *cmd)
* If not matching target port group ID can be located
* throw an exception with ASCQ: INVALID_PARAMETER_LIST
*/
- if (rc != 0)
- return PYX_TRANSPORT_INVALID_PARAMETER_LIST;
+ if (rc != 0) {
+ rc = PYX_TRANSPORT_INVALID_PARAMETER_LIST;
+ goto out;
+ }
} else {
/*
* Extact the RELATIVE TARGET PORT IDENTIFIER to identify
@@ -295,14 +310,19 @@ int core_emulate_set_target_port_groups(struct se_cmd *cmd)
* be located, throw an exception with ASCQ:
* INVALID_PARAMETER_LIST
*/
- if (rc != 0)
- return PYX_TRANSPORT_INVALID_PARAMETER_LIST;
+ if (rc != 0) {
+ rc = PYX_TRANSPORT_INVALID_PARAMETER_LIST;
+ goto out;
+ }
}
ptr += 4;
len += 4;
}
+out:
+ transport_kunmap_first_data_page(cmd);
+
return 0;
}