Merge branch 'for-next' of git://git.kernel.org/pub/scm/linux/kernel/git/nab/target-pending

* 'for-next' of git://git.kernel.org/pub/scm/linux/kernel/git/nab/target-pending: (62 commits)
  target: Fix compile warning w/ missing module.h include
  target: Remove legacy se_task->task_timer and associated logic
  target: Fix incorrect transport_sent usage
  target: re-use the command S/G list for single-task commands
  target: Fix BIDI t_task_cdb handling in transport_generic_new_cmd
  target: remove transport_allocate_tasks
  target: merge transport_new_cmd_obj into transport_generic_new_cmd
  target: remove the task_sg_bidi field se_task and pSCSI BIDI support
  target: transport_subsystem_check_init cleanups
  target: use a workqueue for I/O completions
  target: remove unused TRANSPORT_ states
  target: remove TRANSPORT_DEFERRED_CMD state
  target: remove the TRANSPORT_REMOVE state
  target: move depth_left manipulation out of transport_generic_request_failure
  target: stop task timers earlier
  target: remove TF_TIMER_STOP
  target: factor some duplicate code for stopping a task
  target: fix list walking in transport_free_dev_tasks
  target: use transport_cmd_check_stop_to_fabric consistently
  target: do not pass the queue object to transport_remove_cmd_from_queue
  ...
This commit is contained in:
Linus Torvalds
2011-10-25 11:17:39 +02:00
36 changed files with 938 additions and 2069 deletions

View File

@@ -6,7 +6,6 @@ target_core_mod-y := target_core_configfs.o \
target_core_hba.o \
target_core_pr.o \
target_core_alua.o \
target_core_scdb.o \
target_core_tmr.o \
target_core_tpg.o \
target_core_transport.o \

View File

@@ -765,7 +765,7 @@ static int iscsit_allocate_iovecs(struct iscsi_cmd *cmd)
u32 iov_count = (cmd->se_cmd.t_data_nents == 0) ? 1 :
cmd->se_cmd.t_data_nents;
iov_count += TRANSPORT_IOV_DATA_BUFFER;
iov_count += ISCSI_IOV_DATA_BUFFER;
cmd->iov_data = kzalloc(iov_count * sizeof(struct kvec), GFP_KERNEL);
if (!cmd->iov_data) {
@@ -3538,16 +3538,8 @@ get_immediate:
spin_lock_bh(&conn->cmd_lock);
list_del(&cmd->i_list);
spin_unlock_bh(&conn->cmd_lock);
/*
* Determine if a struct se_cmd is assoicated with
* this struct iscsi_cmd.
*/
if (!(cmd->se_cmd.se_cmd_flags & SCF_SE_LUN_CMD) &&
!(cmd->tmr_req))
iscsit_release_cmd(cmd);
else
transport_generic_free_cmd(&cmd->se_cmd,
1, 0);
iscsit_free_cmd(cmd);
goto get_immediate;
case ISTATE_SEND_NOPIN_WANT_RESPONSE:
spin_unlock_bh(&cmd->istate_lock);
@@ -3940,7 +3932,6 @@ static void iscsit_release_commands_from_conn(struct iscsi_conn *conn)
{
struct iscsi_cmd *cmd = NULL, *cmd_tmp = NULL;
struct iscsi_session *sess = conn->sess;
struct se_cmd *se_cmd;
/*
* We expect this function to only ever be called from either RX or TX
* thread context via iscsit_close_connection() once the other context
@@ -3948,35 +3939,13 @@ static void iscsit_release_commands_from_conn(struct iscsi_conn *conn)
*/
spin_lock_bh(&conn->cmd_lock);
list_for_each_entry_safe(cmd, cmd_tmp, &conn->conn_cmd_list, i_list) {
if (!(cmd->se_cmd.se_cmd_flags & SCF_SE_LUN_CMD)) {
list_del(&cmd->i_list);
spin_unlock_bh(&conn->cmd_lock);
iscsit_increment_maxcmdsn(cmd, sess);
se_cmd = &cmd->se_cmd;
/*
* Special cases for active iSCSI TMR, and
* transport_lookup_cmd_lun() failing from
* iscsit_get_lun_for_cmd() in iscsit_handle_scsi_cmd().
*/
if (cmd->tmr_req && se_cmd->transport_wait_for_tasks)
se_cmd->transport_wait_for_tasks(se_cmd, 1, 1);
else if (cmd->se_cmd.se_cmd_flags & SCF_SE_LUN_CMD)
transport_release_cmd(se_cmd);
else
iscsit_release_cmd(cmd);
spin_lock_bh(&conn->cmd_lock);
continue;
}
list_del(&cmd->i_list);
spin_unlock_bh(&conn->cmd_lock);
iscsit_increment_maxcmdsn(cmd, sess);
se_cmd = &cmd->se_cmd;
if (se_cmd->transport_wait_for_tasks)
se_cmd->transport_wait_for_tasks(se_cmd, 1, 1);
iscsit_free_cmd(cmd);
spin_lock_bh(&conn->cmd_lock);
}

View File

@@ -18,6 +18,7 @@
* GNU General Public License for more details.
******************************************************************************/
#include <linux/kernel.h>
#include <linux/string.h>
#include <linux/crypto.h>
#include <linux/err.h>
@@ -27,40 +28,11 @@
#include "iscsi_target_nego.h"
#include "iscsi_target_auth.h"
static unsigned char chap_asciihex_to_binaryhex(unsigned char val[2])
{
unsigned char result = 0;
/*
* MSB
*/
if ((val[0] >= 'a') && (val[0] <= 'f'))
result = ((val[0] - 'a' + 10) & 0xf) << 4;
else
if ((val[0] >= 'A') && (val[0] <= 'F'))
result = ((val[0] - 'A' + 10) & 0xf) << 4;
else /* digit */
result = ((val[0] - '0') & 0xf) << 4;
/*
* LSB
*/
if ((val[1] >= 'a') && (val[1] <= 'f'))
result |= ((val[1] - 'a' + 10) & 0xf);
else
if ((val[1] >= 'A') && (val[1] <= 'F'))
result |= ((val[1] - 'A' + 10) & 0xf);
else /* digit */
result |= ((val[1] - '0') & 0xf);
return result;
}
static int chap_string_to_hex(unsigned char *dst, unsigned char *src, int len)
{
int i, j = 0;
int j = DIV_ROUND_UP(len, 2);
for (i = 0; i < len; i += 2) {
dst[j++] = (unsigned char) chap_asciihex_to_binaryhex(&src[i]);
}
hex2bin(dst, src, j);
dst[j] = '\0';
return j;

View File

@@ -57,6 +57,9 @@
#define TA_PROD_MODE_WRITE_PROTECT 0
#define TA_CACHE_CORE_NPS 0
#define ISCSI_IOV_DATA_BUFFER 5
enum tpg_np_network_transport_table {
ISCSI_TCP = 0,
ISCSI_SCTP_TCP = 1,
@@ -425,7 +428,6 @@ struct iscsi_cmd {
/* Number of times struct iscsi_cmd is present in immediate queue */
atomic_t immed_queue_count;
atomic_t response_queue_count;
atomic_t transport_sent;
spinlock_t datain_lock;
spinlock_t dataout_timeout_lock;
/* spinlock for protecting struct iscsi_cmd->i_state */

View File

@@ -143,12 +143,7 @@ void iscsit_free_connection_recovery_entires(struct iscsi_session *sess)
list_del(&cmd->i_list);
cmd->conn = NULL;
spin_unlock(&cr->conn_recovery_cmd_lock);
if (!(cmd->se_cmd.se_cmd_flags & SCF_SE_LUN_CMD) ||
!(cmd->se_cmd.transport_wait_for_tasks))
iscsit_release_cmd(cmd);
else
cmd->se_cmd.transport_wait_for_tasks(
&cmd->se_cmd, 1, 1);
iscsit_free_cmd(cmd);
spin_lock(&cr->conn_recovery_cmd_lock);
}
spin_unlock(&cr->conn_recovery_cmd_lock);
@@ -170,12 +165,7 @@ void iscsit_free_connection_recovery_entires(struct iscsi_session *sess)
list_del(&cmd->i_list);
cmd->conn = NULL;
spin_unlock(&cr->conn_recovery_cmd_lock);
if (!(cmd->se_cmd.se_cmd_flags & SCF_SE_LUN_CMD) ||
!(cmd->se_cmd.transport_wait_for_tasks))
iscsit_release_cmd(cmd);
else
cmd->se_cmd.transport_wait_for_tasks(
&cmd->se_cmd, 1, 1);
iscsit_free_cmd(cmd);
spin_lock(&cr->conn_recovery_cmd_lock);
}
spin_unlock(&cr->conn_recovery_cmd_lock);
@@ -260,12 +250,7 @@ void iscsit_discard_cr_cmds_by_expstatsn(
iscsit_remove_cmd_from_connection_recovery(cmd, sess);
spin_unlock(&cr->conn_recovery_cmd_lock);
if (!(cmd->se_cmd.se_cmd_flags & SCF_SE_LUN_CMD) ||
!(cmd->se_cmd.transport_wait_for_tasks))
iscsit_release_cmd(cmd);
else
cmd->se_cmd.transport_wait_for_tasks(
&cmd->se_cmd, 1, 0);
iscsit_free_cmd(cmd);
spin_lock(&cr->conn_recovery_cmd_lock);
}
spin_unlock(&cr->conn_recovery_cmd_lock);
@@ -319,12 +304,7 @@ int iscsit_discard_unacknowledged_ooo_cmdsns_for_conn(struct iscsi_conn *conn)
list_del(&cmd->i_list);
spin_unlock_bh(&conn->cmd_lock);
if (!(cmd->se_cmd.se_cmd_flags & SCF_SE_LUN_CMD) ||
!(cmd->se_cmd.transport_wait_for_tasks))
iscsit_release_cmd(cmd);
else
cmd->se_cmd.transport_wait_for_tasks(
&cmd->se_cmd, 1, 1);
iscsit_free_cmd(cmd);
spin_lock_bh(&conn->cmd_lock);
}
spin_unlock_bh(&conn->cmd_lock);
@@ -377,13 +357,7 @@ int iscsit_prepare_cmds_for_realligance(struct iscsi_conn *conn)
list_del(&cmd->i_list);
spin_unlock_bh(&conn->cmd_lock);
if (!(cmd->se_cmd.se_cmd_flags & SCF_SE_LUN_CMD) ||
!(cmd->se_cmd.transport_wait_for_tasks))
iscsit_release_cmd(cmd);
else
cmd->se_cmd.transport_wait_for_tasks(
&cmd->se_cmd, 1, 0);
iscsit_free_cmd(cmd);
spin_lock_bh(&conn->cmd_lock);
continue;
}
@@ -403,13 +377,7 @@ int iscsit_prepare_cmds_for_realligance(struct iscsi_conn *conn)
(cmd->cmd_sn >= conn->sess->exp_cmd_sn)) {
list_del(&cmd->i_list);
spin_unlock_bh(&conn->cmd_lock);
if (!(cmd->se_cmd.se_cmd_flags & SCF_SE_LUN_CMD) ||
!(cmd->se_cmd.transport_wait_for_tasks))
iscsit_release_cmd(cmd);
else
cmd->se_cmd.transport_wait_for_tasks(
&cmd->se_cmd, 1, 1);
iscsit_free_cmd(cmd);
spin_lock_bh(&conn->cmd_lock);
continue;
}
@@ -434,10 +402,7 @@ int iscsit_prepare_cmds_for_realligance(struct iscsi_conn *conn)
iscsit_free_all_datain_reqs(cmd);
if ((cmd->se_cmd.se_cmd_flags & SCF_SE_LUN_CMD) &&
cmd->se_cmd.transport_wait_for_tasks)
cmd->se_cmd.transport_wait_for_tasks(&cmd->se_cmd,
0, 0);
transport_wait_for_tasks(&cmd->se_cmd);
/*
* Add the struct iscsi_cmd to the connection recovery cmd list
*/

View File

@@ -250,7 +250,7 @@ static int iscsit_task_reassign_complete_write(
* so if we have received all DataOUT we can safety ignore Initiator.
*/
if (cmd->cmd_flags & ICF_GOT_LAST_DATAOUT) {
if (!atomic_read(&cmd->transport_sent)) {
if (!atomic_read(&cmd->se_cmd.t_transport_sent)) {
pr_debug("WRITE ITT: 0x%08x: t_state: %d"
" never sent to transport\n",
cmd->init_task_tag, cmd->se_cmd.t_state);
@@ -314,11 +314,11 @@ static int iscsit_task_reassign_complete_read(
cmd->acked_data_sn = (tmr_req->exp_data_sn - 1);
}
if (!atomic_read(&cmd->transport_sent)) {
if (!atomic_read(&cmd->se_cmd.t_transport_sent)) {
pr_debug("READ ITT: 0x%08x: t_state: %d never sent to"
" transport\n", cmd->init_task_tag,
cmd->se_cmd.t_state);
transport_generic_handle_cdb(se_cmd);
transport_handle_cdb_direct(se_cmd);
return 0;
}

View File

@@ -289,7 +289,8 @@ struct iscsi_cmd *iscsit_allocate_se_cmd_for_tmr(
}
se_cmd->se_tmr_req = core_tmr_alloc_req(se_cmd,
(void *)cmd->tmr_req, tcm_function);
(void *)cmd->tmr_req, tcm_function,
GFP_KERNEL);
if (!se_cmd->se_tmr_req)
goto out;
@@ -839,6 +840,23 @@ void iscsit_release_cmd(struct iscsi_cmd *cmd)
kmem_cache_free(lio_cmd_cache, cmd);
}
void iscsit_free_cmd(struct iscsi_cmd *cmd)
{
/*
* Determine if a struct se_cmd is assoicated with
* this struct iscsi_cmd.
*/
switch (cmd->iscsi_opcode) {
case ISCSI_OP_SCSI_CMD:
case ISCSI_OP_SCSI_TMFUNC:
transport_generic_free_cmd(&cmd->se_cmd, 1);
break;
default:
iscsit_release_cmd(cmd);
break;
}
}
int iscsit_check_session_usage_count(struct iscsi_session *sess)
{
spin_lock_bh(&sess->session_usage_lock);

View File

@@ -30,6 +30,7 @@ extern struct iscsi_queue_req *iscsit_get_cmd_from_response_queue(struct iscsi_c
extern void iscsit_remove_cmd_from_tx_queues(struct iscsi_cmd *, struct iscsi_conn *);
extern void iscsit_free_queue_reqs_for_conn(struct iscsi_conn *);
extern void iscsit_release_cmd(struct iscsi_cmd *);
extern void iscsit_free_cmd(struct iscsi_cmd *);
extern int iscsit_check_session_usage_count(struct iscsi_session *);
extern void iscsit_dec_session_usage_count(struct iscsi_session *);
extern void iscsit_inc_session_usage_count(struct iscsi_session *);

View File

@@ -200,7 +200,7 @@ static void tcm_loop_check_stop_free(struct se_cmd *se_cmd)
* Release the struct se_cmd, which will make a callback to release
* struct tcm_loop_cmd * in tcm_loop_deallocate_core_cmd()
*/
transport_generic_free_cmd(se_cmd, 0, 0);
transport_generic_free_cmd(se_cmd, 0);
}
static void tcm_loop_release_cmd(struct se_cmd *se_cmd)
@@ -290,6 +290,15 @@ static int tcm_loop_queuecommand(
*/
tl_hba = *(struct tcm_loop_hba **)shost_priv(sc->device->host);
tl_tpg = &tl_hba->tl_hba_tpgs[sc->device->id];
/*
* Ensure that this tl_tpg reference from the incoming sc->device->id
* has already been configured via tcm_loop_make_naa_tpg().
*/
if (!tl_tpg->tl_hba) {
set_host_byte(sc, DID_NO_CONNECT);
sc->scsi_done(sc);
return 0;
}
se_tpg = &tl_tpg->tl_se_tpg;
/*
* Determine the SAM Task Attribute and allocate tl_cmd and
@@ -366,7 +375,7 @@ static int tcm_loop_device_reset(struct scsi_cmnd *sc)
* Allocate the LUN_RESET TMR
*/
se_cmd->se_tmr_req = core_tmr_alloc_req(se_cmd, tl_tmr,
TMR_LUN_RESET);
TMR_LUN_RESET, GFP_KERNEL);
if (IS_ERR(se_cmd->se_tmr_req))
goto release;
/*
@@ -388,7 +397,7 @@ static int tcm_loop_device_reset(struct scsi_cmnd *sc)
SUCCESS : FAILED;
release:
if (se_cmd)
transport_generic_free_cmd(se_cmd, 1, 0);
transport_generic_free_cmd(se_cmd, 1);
else
kmem_cache_free(tcm_loop_cmd_cache, tl_cmd);
kfree(tl_tmr);
@@ -1245,6 +1254,9 @@ void tcm_loop_drop_naa_tpg(
*/
core_tpg_deregister(se_tpg);
tl_tpg->tl_hba = NULL;
tl_tpg->tl_tpgt = 0;
pr_debug("TCM_Loop_ConfigFS: Deallocated Emulated %s"
" Target Port %s,t,0x%04x\n", tcm_loop_dump_proto_id(tl_hba),
config_item_name(&wwn->wwn_group.cg_item), tpgt);

View File

@@ -24,7 +24,6 @@
*
******************************************************************************/
#include <linux/version.h>
#include <linux/slab.h>
#include <linux/spinlock.h>
#include <linux/configfs.h>
@@ -68,12 +67,32 @@ int core_emulate_report_target_port_groups(struct se_cmd *cmd)
unsigned char *buf;
u32 rd_len = 0, off = 4; /* Skip over RESERVED area to first
Target port group descriptor */
/*
* Need at least 4 bytes of response data or else we can't
* even fit the return data length.
*/
if (cmd->data_length < 4) {
pr_warn("REPORT TARGET PORT GROUPS allocation length %u"
" too small\n", cmd->data_length);
return -EINVAL;
}
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) {
/*
* Check if the Target port group and Target port descriptor list
* based on tg_pt_gp_members count will fit into the response payload.
* Otherwise, bump rd_len to let the initiator know we have exceeded
* the allocation length and the response is truncated.
*/
if ((off + 8 + (tg_pt_gp->tg_pt_gp_members * 4)) >
cmd->data_length) {
rd_len += 8 + (tg_pt_gp->tg_pt_gp_members * 4);
continue;
}
/*
* PREF: Preferred target port bit, determine if this
* bit should be set for port group.

View File

@@ -24,7 +24,7 @@
*/
#include <linux/kernel.h>
#include <linux/ctype.h>
#include <linux/module.h>
#include <asm/unaligned.h>
#include <scsi/scsi.h>
@@ -156,11 +156,12 @@ target_emulate_evpd_80(struct se_cmd *cmd, unsigned char *buf)
}
static void
target_parse_naa_6h_vendor_specific(struct se_device *dev, unsigned char *buf_off)
target_parse_naa_6h_vendor_specific(struct se_device *dev, unsigned char *buf)
{
unsigned char *p = &dev->se_sub_dev->t10_wwn.unit_serial[0];
unsigned char *buf = buf_off;
int cnt = 0, next = 1;
int cnt;
bool next = true;
/*
* Generate up to 36 bits of VENDOR SPECIFIC IDENTIFIER starting on
* byte 3 bit 3-0 for NAA IEEE Registered Extended DESIGNATOR field
@@ -169,19 +170,18 @@ target_parse_naa_6h_vendor_specific(struct se_device *dev, unsigned char *buf_of
* NUMBER set via vpd_unit_serial in target_core_configfs.c to ensure
* per device uniqeness.
*/
while (*p != '\0') {
if (cnt >= 13)
break;
if (!isxdigit(*p)) {
p++;
for (cnt = 0; *p && cnt < 13; p++) {
int val = hex_to_bin(*p);
if (val < 0)
continue;
}
if (next != 0) {
buf[cnt++] |= hex_to_bin(*p++);
next = 0;
if (next) {
next = false;
buf[cnt++] |= val;
} else {
buf[cnt] = hex_to_bin(*p++) << 4;
next = 1;
next = true;
buf[cnt] = val << 4;
}
}
}
@@ -1266,3 +1266,52 @@ transport_emulate_control_cdb(struct se_task *task)
return PYX_TRANSPORT_SENT_TO_TRANSPORT;
}
/*
* Write a CDB into @cdb that is based on the one the intiator sent us,
* but updated to only cover the sectors that the current task handles.
*/
void target_get_task_cdb(struct se_task *task, unsigned char *cdb)
{
struct se_cmd *cmd = task->task_se_cmd;
unsigned int cdb_len = scsi_command_size(cmd->t_task_cdb);
memcpy(cdb, cmd->t_task_cdb, cdb_len);
if (cmd->se_cmd_flags & SCF_SCSI_DATA_SG_IO_CDB) {
unsigned long long lba = task->task_lba;
u32 sectors = task->task_sectors;
switch (cdb_len) {
case 6:
/* 21-bit LBA and 8-bit sectors */
cdb[1] = (lba >> 16) & 0x1f;
cdb[2] = (lba >> 8) & 0xff;
cdb[3] = lba & 0xff;
cdb[4] = sectors & 0xff;
break;
case 10:
/* 32-bit LBA and 16-bit sectors */
put_unaligned_be32(lba, &cdb[2]);
put_unaligned_be16(sectors, &cdb[7]);
break;
case 12:
/* 32-bit LBA and 32-bit sectors */
put_unaligned_be32(lba, &cdb[2]);
put_unaligned_be32(sectors, &cdb[6]);
break;
case 16:
/* 64-bit LBA and 32-bit sectors */
put_unaligned_be64(lba, &cdb[2]);
put_unaligned_be32(sectors, &cdb[10]);
break;
case 32:
/* 64-bit LBA and 32-bit sectors, extended CDB */
put_unaligned_be64(lba, &cdb[12]);
put_unaligned_be32(sectors, &cdb[28]);
break;
default:
BUG();
}
}
}
EXPORT_SYMBOL(target_get_task_cdb);

View File

@@ -23,7 +23,6 @@
#include <linux/module.h>
#include <linux/moduleparam.h>
#include <linux/version.h>
#include <generated/utsrelease.h>
#include <linux/utsname.h>
#include <linux/init.h>
@@ -132,14 +131,6 @@ static struct config_group *target_core_register_fabric(
pr_debug("Target_Core_ConfigFS: REGISTER -> group: %p name:"
" %s\n", group, name);
/*
* Ensure that TCM subsystem plugins are loaded at this point for
* using the RAMDISK_DR virtual LUN 0 and all other struct se_port
* LUN symlinks.
*/
if (transport_subsystem_check_init() < 0)
return ERR_PTR(-EINVAL);
/*
* Below are some hardcoded request_module() calls to automatically
* local fabric modules when the following is called:
@@ -725,9 +716,6 @@ SE_DEV_ATTR_RO(hw_queue_depth);
DEF_DEV_ATTRIB(queue_depth);
SE_DEV_ATTR(queue_depth, S_IRUGO | S_IWUSR);
DEF_DEV_ATTRIB(task_timeout);
SE_DEV_ATTR(task_timeout, S_IRUGO | S_IWUSR);
DEF_DEV_ATTRIB(max_unmap_lba_count);
SE_DEV_ATTR(max_unmap_lba_count, S_IRUGO | S_IWUSR);
@@ -761,7 +749,6 @@ static struct configfs_attribute *target_core_dev_attrib_attrs[] = {
&target_core_dev_attrib_optimal_sectors.attr,
&target_core_dev_attrib_hw_queue_depth.attr,
&target_core_dev_attrib_queue_depth.attr,
&target_core_dev_attrib_task_timeout.attr,
&target_core_dev_attrib_max_unmap_lba_count.attr,
&target_core_dev_attrib_max_unmap_block_desc_count.attr,
&target_core_dev_attrib_unmap_granularity.attr,
@@ -3080,8 +3067,7 @@ static struct config_group *target_core_call_addhbatotarget(
/*
* Load up TCM subsystem plugins if they have not already been loaded.
*/
if (transport_subsystem_check_init() < 0)
return ERR_PTR(-EINVAL);
transport_subsystem_check_init();
hba = core_alloc_hba(se_plugin_str, plugin_dep_id, 0);
if (IS_ERR(hba))

View File

@@ -914,21 +914,6 @@ void se_dev_set_default_attribs(
dev->se_sub_dev->se_dev_attrib.queue_depth = dev_limits->queue_depth;
}
int se_dev_set_task_timeout(struct se_device *dev, u32 task_timeout)
{
if (task_timeout > DA_TASK_TIMEOUT_MAX) {
pr_err("dev[%p]: Passed task_timeout: %u larger then"
" DA_TASK_TIMEOUT_MAX\n", dev, task_timeout);
return -EINVAL;
} else {
dev->se_sub_dev->se_dev_attrib.task_timeout = task_timeout;
pr_debug("dev[%p]: Set SE Device task_timeout: %u\n",
dev, task_timeout);
}
return 0;
}
int se_dev_set_max_unmap_lba_count(
struct se_device *dev,
u32 max_unmap_lba_count)
@@ -972,36 +957,24 @@ int se_dev_set_unmap_granularity_alignment(
int se_dev_set_emulate_dpo(struct se_device *dev, int flag)
{
if ((flag != 0) && (flag != 1)) {
if (flag != 0 && flag != 1) {
pr_err("Illegal value %d\n", flag);
return -EINVAL;
}
if (dev->transport->dpo_emulated == NULL) {
pr_err("dev->transport->dpo_emulated is NULL\n");
return -EINVAL;
}
if (dev->transport->dpo_emulated(dev) == 0) {
pr_err("dev->transport->dpo_emulated not supported\n");
return -EINVAL;
}
dev->se_sub_dev->se_dev_attrib.emulate_dpo = flag;
pr_debug("dev[%p]: SE Device Page Out (DPO) Emulation"
" bit: %d\n", dev, dev->se_sub_dev->se_dev_attrib.emulate_dpo);
return 0;
pr_err("dpo_emulated not supported\n");
return -EINVAL;
}
int se_dev_set_emulate_fua_write(struct se_device *dev, int flag)
{
if ((flag != 0) && (flag != 1)) {
if (flag != 0 && flag != 1) {
pr_err("Illegal value %d\n", flag);
return -EINVAL;
}
if (dev->transport->fua_write_emulated == NULL) {
pr_err("dev->transport->fua_write_emulated is NULL\n");
return -EINVAL;
}
if (dev->transport->fua_write_emulated(dev) == 0) {
pr_err("dev->transport->fua_write_emulated not supported\n");
if (dev->transport->fua_write_emulated == 0) {
pr_err("fua_write_emulated not supported\n");
return -EINVAL;
}
dev->se_sub_dev->se_dev_attrib.emulate_fua_write = flag;
@@ -1012,36 +985,23 @@ int se_dev_set_emulate_fua_write(struct se_device *dev, int flag)
int se_dev_set_emulate_fua_read(struct se_device *dev, int flag)
{
if ((flag != 0) && (flag != 1)) {
if (flag != 0 && flag != 1) {
pr_err("Illegal value %d\n", flag);
return -EINVAL;
}
if (dev->transport->fua_read_emulated == NULL) {
pr_err("dev->transport->fua_read_emulated is NULL\n");
return -EINVAL;
}
if (dev->transport->fua_read_emulated(dev) == 0) {
pr_err("dev->transport->fua_read_emulated not supported\n");
return -EINVAL;
}
dev->se_sub_dev->se_dev_attrib.emulate_fua_read = flag;
pr_debug("dev[%p]: SE Device Forced Unit Access READs: %d\n",
dev, dev->se_sub_dev->se_dev_attrib.emulate_fua_read);
return 0;
pr_err("ua read emulated not supported\n");
return -EINVAL;
}
int se_dev_set_emulate_write_cache(struct se_device *dev, int flag)
{
if ((flag != 0) && (flag != 1)) {
if (flag != 0 && flag != 1) {
pr_err("Illegal value %d\n", flag);
return -EINVAL;
}
if (dev->transport->write_cache_emulated == NULL) {
pr_err("dev->transport->write_cache_emulated is NULL\n");
return -EINVAL;
}
if (dev->transport->write_cache_emulated(dev) == 0) {
pr_err("dev->transport->write_cache_emulated not supported\n");
if (dev->transport->write_cache_emulated == 0) {
pr_err("write_cache_emulated not supported\n");
return -EINVAL;
}
dev->se_sub_dev->se_dev_attrib.emulate_write_cache = flag;

View File

@@ -22,7 +22,6 @@
#include <linux/module.h>
#include <linux/moduleparam.h>
#include <linux/version.h>
#include <generated/utsrelease.h>
#include <linux/utsname.h>
#include <linux/init.h>

View File

@@ -26,7 +26,6 @@
*
******************************************************************************/
#include <linux/version.h>
#include <linux/string.h>
#include <linux/parser.h>
#include <linux/timer.h>
@@ -273,13 +272,14 @@ fd_alloc_task(unsigned char *cdb)
static int fd_do_readv(struct se_task *task)
{
struct fd_request *req = FILE_REQ(task);
struct fd_dev *dev = req->fd_task.se_dev->dev_ptr;
struct se_device *se_dev = req->fd_task.task_se_cmd->se_dev;
struct fd_dev *dev = se_dev->dev_ptr;
struct file *fd = dev->fd_file;
struct scatterlist *sg = task->task_sg;
struct iovec *iov;
mm_segment_t old_fs;
loff_t pos = (task->task_lba *
task->se_dev->se_sub_dev->se_dev_attrib.block_size);
se_dev->se_sub_dev->se_dev_attrib.block_size);
int ret = 0, i;
iov = kzalloc(sizeof(struct iovec) * task->task_sg_nents, GFP_KERNEL);
@@ -325,13 +325,14 @@ static int fd_do_readv(struct se_task *task)
static int fd_do_writev(struct se_task *task)
{
struct fd_request *req = FILE_REQ(task);
struct fd_dev *dev = req->fd_task.se_dev->dev_ptr;
struct se_device *se_dev = req->fd_task.task_se_cmd->se_dev;
struct fd_dev *dev = se_dev->dev_ptr;
struct file *fd = dev->fd_file;
struct scatterlist *sg = task->task_sg;
struct iovec *iov;
mm_segment_t old_fs;
loff_t pos = (task->task_lba *
task->se_dev->se_sub_dev->se_dev_attrib.block_size);
se_dev->se_sub_dev->se_dev_attrib.block_size);
int ret, i = 0;
iov = kzalloc(sizeof(struct iovec) * task->task_sg_nents, GFP_KERNEL);
@@ -398,33 +399,6 @@ static void fd_emulate_sync_cache(struct se_task *task)
transport_complete_sync_cache(cmd, ret == 0);
}
/*
* Tell TCM Core that we are capable of WriteCache emulation for
* an underlying struct se_device.
*/
static int fd_emulated_write_cache(struct se_device *dev)
{
return 1;
}
static int fd_emulated_dpo(struct se_device *dev)
{
return 0;
}
/*
* Tell TCM Core that we will be emulating Forced Unit Access (FUA) for WRITEs
* for TYPE_DISK.
*/
static int fd_emulated_fua_write(struct se_device *dev)
{
return 1;
}
static int fd_emulated_fua_read(struct se_device *dev)
{
return 0;
}
/*
* WRITE Force Unit Access (FUA) emulation on a per struct se_task
* LBA range basis..
@@ -608,17 +582,6 @@ static ssize_t fd_show_configfs_dev_params(
return bl;
}
/* fd_get_cdb(): (Part of se_subsystem_api_t template)
*
*
*/
static unsigned char *fd_get_cdb(struct se_task *task)
{
struct fd_request *req = FILE_REQ(task);
return req->fd_scsi_cdb;
}
/* fd_get_device_rev(): (Part of se_subsystem_api_t template)
*
*
@@ -650,15 +613,13 @@ static struct se_subsystem_api fileio_template = {
.name = "fileio",
.owner = THIS_MODULE,
.transport_type = TRANSPORT_PLUGIN_VHBA_PDEV,
.write_cache_emulated = 1,
.fua_write_emulated = 1,
.attach_hba = fd_attach_hba,
.detach_hba = fd_detach_hba,
.allocate_virtdevice = fd_allocate_virtdevice,
.create_virtdevice = fd_create_virtdevice,
.free_device = fd_free_device,
.dpo_emulated = fd_emulated_dpo,
.fua_write_emulated = fd_emulated_fua_write,
.fua_read_emulated = fd_emulated_fua_read,
.write_cache_emulated = fd_emulated_write_cache,
.alloc_task = fd_alloc_task,
.do_task = fd_do_task,
.do_sync_cache = fd_emulate_sync_cache,
@@ -666,7 +627,6 @@ static struct se_subsystem_api fileio_template = {
.check_configfs_dev_params = fd_check_configfs_dev_params,
.set_configfs_dev_params = fd_set_configfs_dev_params,
.show_configfs_dev_params = fd_show_configfs_dev_params,
.get_cdb = fd_get_cdb,
.get_device_rev = fd_get_device_rev,
.get_device_type = fd_get_device_type,
.get_blocks = fd_get_blocks,

View File

@@ -14,9 +14,7 @@
struct fd_request {
struct se_task fd_task;
/* SCSI CDB from iSCSI Command PDU */
unsigned char fd_scsi_cdb[TCM_MAX_COMMAND_SIZE];
} ____cacheline_aligned;
};
#define FBDF_HAS_PATH 0x01
#define FBDF_HAS_SIZE 0x02

View File

@@ -27,7 +27,6 @@
*
******************************************************************************/
#include <linux/version.h>
#include <linux/string.h>
#include <linux/parser.h>
#include <linux/timer.h>
@@ -314,104 +313,42 @@ static unsigned long long iblock_emulate_read_cap_with_block_size(
return blocks_long;
}
static void iblock_end_io_flush(struct bio *bio, int err)
{
struct se_cmd *cmd = bio->bi_private;
if (err)
pr_err("IBLOCK: cache flush failed: %d\n", err);
if (cmd)
transport_complete_sync_cache(cmd, err == 0);
bio_put(bio);
}
/*
* Emulate SYCHRONIZE_CACHE_*
* Implement SYCHRONIZE CACHE. Note that we can't handle lba ranges and must
* always flush the whole cache.
*/
static void iblock_emulate_sync_cache(struct se_task *task)
{
struct se_cmd *cmd = task->task_se_cmd;
struct iblock_dev *ib_dev = cmd->se_dev->dev_ptr;
int immed = (cmd->t_task_cdb[1] & 0x2);
sector_t error_sector;
int ret;
struct bio *bio;
/*
* If the Immediate bit is set, queue up the GOOD response
* for this SYNCHRONIZE_CACHE op
* for this SYNCHRONIZE_CACHE op.
*/
if (immed)
transport_complete_sync_cache(cmd, 1);
/*
* blkdev_issue_flush() does not support a specifying a range, so
* we have to flush the entire cache.
*/
ret = blkdev_issue_flush(ib_dev->ibd_bd, GFP_KERNEL, &error_sector);
if (ret != 0) {
pr_err("IBLOCK: block_issue_flush() failed: %d "
" error_sector: %llu\n", ret,
(unsigned long long)error_sector);
}
bio = bio_alloc(GFP_KERNEL, 0);
bio->bi_end_io = iblock_end_io_flush;
bio->bi_bdev = ib_dev->ibd_bd;
if (!immed)
transport_complete_sync_cache(cmd, ret == 0);
}
/*
* Tell TCM Core that we are capable of WriteCache emulation for
* an underlying struct se_device.
*/
static int iblock_emulated_write_cache(struct se_device *dev)
{
return 1;
}
static int iblock_emulated_dpo(struct se_device *dev)
{
return 0;
}
/*
* Tell TCM Core that we will be emulating Forced Unit Access (FUA) for WRITEs
* for TYPE_DISK.
*/
static int iblock_emulated_fua_write(struct se_device *dev)
{
return 1;
}
static int iblock_emulated_fua_read(struct se_device *dev)
{
return 0;
}
static int iblock_do_task(struct se_task *task)
{
struct se_device *dev = task->task_se_cmd->se_dev;
struct iblock_req *req = IBLOCK_REQ(task);
struct bio *bio = req->ib_bio, *nbio = NULL;
struct blk_plug plug;
int rw;
if (task->task_data_direction == DMA_TO_DEVICE) {
/*
* Force data to disk if we pretend to not have a volatile
* write cache, or the initiator set the Force Unit Access bit.
*/
if (dev->se_sub_dev->se_dev_attrib.emulate_write_cache == 0 ||
(dev->se_sub_dev->se_dev_attrib.emulate_fua_write > 0 &&
task->task_se_cmd->t_tasks_fua))
rw = WRITE_FUA;
else
rw = WRITE;
} else {
rw = READ;
}
blk_start_plug(&plug);
while (bio) {
nbio = bio->bi_next;
bio->bi_next = NULL;
pr_debug("Calling submit_bio() task: %p bio: %p"
" bio->bi_sector: %llu\n", task, bio,
(unsigned long long)bio->bi_sector);
submit_bio(rw, bio);
bio = nbio;
}
blk_finish_plug(&plug);
return PYX_TRANSPORT_SENT_TO_TRANSPORT;
bio->bi_private = cmd;
submit_bio(WRITE_FLUSH, bio);
}
static int iblock_do_discard(struct se_device *dev, sector_t lba, u32 range)
@@ -425,20 +362,7 @@ static int iblock_do_discard(struct se_device *dev, sector_t lba, u32 range)
static void iblock_free_task(struct se_task *task)
{
struct iblock_req *req = IBLOCK_REQ(task);
struct bio *bio, *hbio = req->ib_bio;
/*
* We only release the bio(s) here if iblock_bio_done() has not called
* bio_put() -> iblock_bio_destructor().
*/
while (hbio != NULL) {
bio = hbio;
hbio = hbio->bi_next;
bio->bi_next = NULL;
bio_put(bio);
}
kfree(req);
kfree(IBLOCK_REQ(task));
}
enum {
@@ -552,25 +476,21 @@ static ssize_t iblock_show_configfs_dev_params(
static void iblock_bio_destructor(struct bio *bio)
{
struct se_task *task = bio->bi_private;
struct iblock_dev *ib_dev = task->se_dev->dev_ptr;
struct iblock_dev *ib_dev = task->task_se_cmd->se_dev->dev_ptr;
bio_free(bio, ib_dev->ibd_bio_set);
}
static struct bio *iblock_get_bio(
struct se_task *task,
struct iblock_req *ib_req,
struct iblock_dev *ib_dev,
int *ret,
sector_t lba,
u32 sg_num)
static struct bio *
iblock_get_bio(struct se_task *task, sector_t lba, u32 sg_num)
{
struct iblock_dev *ib_dev = task->task_se_cmd->se_dev->dev_ptr;
struct iblock_req *ib_req = IBLOCK_REQ(task);
struct bio *bio;
bio = bio_alloc_bioset(GFP_NOIO, sg_num, ib_dev->ibd_bio_set);
if (!bio) {
pr_err("Unable to allocate memory for bio\n");
*ret = PYX_TRANSPORT_OUT_OF_MEMORY_RESOURCES;
return NULL;
}
@@ -591,17 +511,33 @@ static struct bio *iblock_get_bio(
return bio;
}
static int iblock_map_data_SG(struct se_task *task)
static int iblock_do_task(struct se_task *task)
{
struct se_cmd *cmd = task->task_se_cmd;
struct se_device *dev = cmd->se_dev;
struct iblock_dev *ib_dev = task->se_dev->dev_ptr;
struct iblock_req *ib_req = IBLOCK_REQ(task);
struct bio *bio = NULL, *hbio = NULL, *tbio = NULL;
struct bio *bio;
struct bio_list list;
struct scatterlist *sg;
int ret = 0;
u32 i, sg_num = task->task_sg_nents;
sector_t block_lba;
struct blk_plug plug;
int rw;
if (task->task_data_direction == DMA_TO_DEVICE) {
/*
* Force data to disk if we pretend to not have a volatile
* write cache, or the initiator set the Force Unit Access bit.
*/
if (dev->se_sub_dev->se_dev_attrib.emulate_write_cache == 0 ||
(dev->se_sub_dev->se_dev_attrib.emulate_fua_write > 0 &&
task->task_se_cmd->t_tasks_fua))
rw = WRITE_FUA;
else
rw = WRITE;
} else {
rw = READ;
}
/*
* Do starting conversion up from non 512-byte blocksize with
* struct se_task SCSI blocksize into Linux/Block 512 units for BIO.
@@ -620,68 +556,43 @@ static int iblock_map_data_SG(struct se_task *task)
return PYX_TRANSPORT_LU_COMM_FAILURE;
}
bio = iblock_get_bio(task, ib_req, ib_dev, &ret, block_lba, sg_num);
bio = iblock_get_bio(task, block_lba, sg_num);
if (!bio)
return ret;
return PYX_TRANSPORT_OUT_OF_MEMORY_RESOURCES;
bio_list_init(&list);
bio_list_add(&list, bio);
ib_req->ib_bio = bio;
hbio = tbio = bio;
/*
* Use fs/bio.c:bio_add_pages() to setup the bio_vec maplist
* from task->task_sg -> struct scatterlist memory.
*/
for_each_sg(task->task_sg, sg, task->task_sg_nents, i) {
pr_debug("task: %p bio: %p Calling bio_add_page(): page:"
" %p len: %u offset: %u\n", task, bio, sg_page(sg),
sg->length, sg->offset);
again:
ret = bio_add_page(bio, sg_page(sg), sg->length, sg->offset);
if (ret != sg->length) {
pr_debug("*** Set bio->bi_sector: %llu\n",
(unsigned long long)bio->bi_sector);
pr_debug("** task->task_size: %u\n",
task->task_size);
pr_debug("*** bio->bi_max_vecs: %u\n",
bio->bi_max_vecs);
pr_debug("*** bio->bi_vcnt: %u\n",
bio->bi_vcnt);
bio = iblock_get_bio(task, ib_req, ib_dev, &ret,
block_lba, sg_num);
/*
* XXX: if the length the device accepts is shorter than the
* length of the S/G list entry this will cause and
* endless loop. Better hope no driver uses huge pages.
*/
while (bio_add_page(bio, sg_page(sg), sg->length, sg->offset)
!= sg->length) {
bio = iblock_get_bio(task, block_lba, sg_num);
if (!bio)
goto fail;
tbio = tbio->bi_next = bio;
pr_debug("-----------------> Added +1 bio: %p to"
" list, Going to again\n", bio);
goto again;
bio_list_add(&list, bio);
}
/* Always in 512 byte units for Linux/Block */
block_lba += sg->length >> IBLOCK_LBA_SHIFT;
sg_num--;
pr_debug("task: %p bio-add_page() passed!, decremented"
" sg_num to %u\n", task, sg_num);
pr_debug("task: %p bio_add_page() passed!, increased lba"
" to %llu\n", task, (unsigned long long)block_lba);
pr_debug("task: %p bio_add_page() passed!, bio->bi_vcnt:"
" %u\n", task, bio->bi_vcnt);
}
return 0;
blk_start_plug(&plug);
while ((bio = bio_list_pop(&list)))
submit_bio(rw, bio);
blk_finish_plug(&plug);
return PYX_TRANSPORT_SENT_TO_TRANSPORT;
fail:
while (hbio) {
bio = hbio;
hbio = hbio->bi_next;
bio->bi_next = NULL;
while ((bio = bio_list_pop(&list)))
bio_put(bio);
}
return ret;
}
static unsigned char *iblock_get_cdb(struct se_task *task)
{
return IBLOCK_REQ(task)->ib_scsi_cdb;
return PYX_TRANSPORT_OUT_OF_MEMORY_RESOURCES;
}
static u32 iblock_get_device_rev(struct se_device *dev)
@@ -707,6 +618,7 @@ static void iblock_bio_done(struct bio *bio, int err)
{
struct se_task *task = bio->bi_private;
struct iblock_req *ibr = IBLOCK_REQ(task);
/*
* Set -EIO if !BIO_UPTODATE and the passed is still err=0
*/
@@ -721,50 +633,31 @@ static void iblock_bio_done(struct bio *bio, int err)
*/
atomic_inc(&ibr->ib_bio_err_cnt);
smp_mb__after_atomic_inc();
bio_put(bio);
/*
* Wait to complete the task until the last bio as completed.
*/
if (!atomic_dec_and_test(&ibr->ib_bio_cnt))
return;
ibr->ib_bio = NULL;
transport_complete_task(task, 0);
return;
}
pr_debug("done[%p] bio: %p task_lba: %llu bio_lba: %llu err=%d\n",
task, bio, task->task_lba, (unsigned long long)bio->bi_sector, err);
/*
* bio_put() will call iblock_bio_destructor() to release the bio back
* to ibr->ib_bio_set.
*/
bio_put(bio);
/*
* Wait to complete the task until the last bio as completed.
*/
if (!atomic_dec_and_test(&ibr->ib_bio_cnt))
return;
/*
* Return GOOD status for task if zero ib_bio_err_cnt exists.
*/
ibr->ib_bio = NULL;
transport_complete_task(task, (!atomic_read(&ibr->ib_bio_err_cnt)));
pr_debug("done[%p] bio: %p task_lba: %llu bio_lba: %llu err=%d\n",
task, bio, task->task_lba,
(unsigned long long)bio->bi_sector, err);
transport_complete_task(task, !atomic_read(&ibr->ib_bio_err_cnt));
}
static struct se_subsystem_api iblock_template = {
.name = "iblock",
.owner = THIS_MODULE,
.transport_type = TRANSPORT_PLUGIN_VHBA_PDEV,
.map_data_SG = iblock_map_data_SG,
.write_cache_emulated = 1,
.fua_write_emulated = 1,
.attach_hba = iblock_attach_hba,
.detach_hba = iblock_detach_hba,
.allocate_virtdevice = iblock_allocate_virtdevice,
.create_virtdevice = iblock_create_virtdevice,
.free_device = iblock_free_device,
.dpo_emulated = iblock_emulated_dpo,
.fua_write_emulated = iblock_emulated_fua_write,
.fua_read_emulated = iblock_emulated_fua_read,
.write_cache_emulated = iblock_emulated_write_cache,
.alloc_task = iblock_alloc_task,
.do_task = iblock_do_task,
.do_discard = iblock_do_discard,
@@ -773,7 +666,6 @@ static struct se_subsystem_api iblock_template = {
.check_configfs_dev_params = iblock_check_configfs_dev_params,
.set_configfs_dev_params = iblock_set_configfs_dev_params,
.show_configfs_dev_params = iblock_show_configfs_dev_params,
.get_cdb = iblock_get_cdb,
.get_device_rev = iblock_get_device_rev,
.get_device_type = iblock_get_device_type,
.get_blocks = iblock_get_blocks,

View File

@@ -8,10 +8,8 @@
struct iblock_req {
struct se_task ib_task;
unsigned char ib_scsi_cdb[TCM_MAX_COMMAND_SIZE];
atomic_t ib_bio_cnt;
atomic_t ib_bio_err_cnt;
struct bio *ib_bio;
} ____cacheline_aligned;
#define IBDF_HAS_UDEV_PATH 0x01

View File

@@ -25,7 +25,6 @@
*
******************************************************************************/
#include <linux/version.h>
#include <linux/slab.h>
#include <linux/spinlock.h>
#include <linux/list.h>

View File

@@ -26,7 +26,6 @@
*
******************************************************************************/
#include <linux/version.h>
#include <linux/string.h>
#include <linux/parser.h>
#include <linux/timer.h>
@@ -567,7 +566,7 @@ static struct se_device *pscsi_create_virtdevice(
if (IS_ERR(sh)) {
pr_err("pSCSI: Unable to locate"
" pdv_host_id: %d\n", pdv->pdv_host_id);
return (struct se_device *) sh;
return ERR_CAST(sh);
}
}
} else {
@@ -677,7 +676,7 @@ static inline struct pscsi_plugin_task *PSCSI_TASK(struct se_task *task)
*/
static int pscsi_transport_complete(struct se_task *task)
{
struct pscsi_dev_virt *pdv = task->se_dev->dev_ptr;
struct pscsi_dev_virt *pdv = task->task_se_cmd->se_dev->dev_ptr;
struct scsi_device *sd = pdv->pdv_sd;
int result;
struct pscsi_plugin_task *pt = PSCSI_TASK(task);
@@ -777,95 +776,6 @@ pscsi_alloc_task(unsigned char *cdb)
return &pt->pscsi_task;
}
static inline void pscsi_blk_init_request(
struct se_task *task,
struct pscsi_plugin_task *pt,
struct request *req,
int bidi_read)
{
/*
* Defined as "scsi command" in include/linux/blkdev.h.
*/
req->cmd_type = REQ_TYPE_BLOCK_PC;
/*
* For the extra BIDI-COMMAND READ struct request we do not
* need to setup the remaining structure members
*/
if (bidi_read)
return;
/*
* Setup the done function pointer for struct request,
* also set the end_io_data pointer.to struct se_task.
*/
req->end_io = pscsi_req_done;
req->end_io_data = task;
/*
* Load the referenced struct se_task's SCSI CDB into
* include/linux/blkdev.h:struct request->cmd
*/
req->cmd_len = scsi_command_size(pt->pscsi_cdb);
req->cmd = &pt->pscsi_cdb[0];
/*
* Setup pointer for outgoing sense data.
*/
req->sense = &pt->pscsi_sense[0];
req->sense_len = 0;
}
/*
* Used for pSCSI data payloads for all *NON* SCF_SCSI_DATA_SG_IO_CDB
*/
static int pscsi_blk_get_request(struct se_task *task)
{
struct pscsi_plugin_task *pt = PSCSI_TASK(task);
struct pscsi_dev_virt *pdv = task->se_dev->dev_ptr;
pt->pscsi_req = blk_get_request(pdv->pdv_sd->request_queue,
(task->task_data_direction == DMA_TO_DEVICE),
GFP_KERNEL);
if (!pt->pscsi_req || IS_ERR(pt->pscsi_req)) {
pr_err("PSCSI: blk_get_request() failed: %ld\n",
IS_ERR(pt->pscsi_req));
return PYX_TRANSPORT_LU_COMM_FAILURE;
}
/*
* Setup the newly allocated struct request for REQ_TYPE_BLOCK_PC,
* and setup rq callback, CDB and sense.
*/
pscsi_blk_init_request(task, pt, pt->pscsi_req, 0);
return 0;
}
/* pscsi_do_task(): (Part of se_subsystem_api_t template)
*
*
*/
static int pscsi_do_task(struct se_task *task)
{
struct pscsi_plugin_task *pt = PSCSI_TASK(task);
struct pscsi_dev_virt *pdv = task->se_dev->dev_ptr;
/*
* Set the struct request->timeout value based on peripheral
* device type from SCSI.
*/
if (pdv->pdv_sd->type == TYPE_DISK)
pt->pscsi_req->timeout = PS_TIMEOUT_DISK;
else
pt->pscsi_req->timeout = PS_TIMEOUT_OTHER;
pt->pscsi_req->retries = PS_RETRY;
/*
* Queue the struct request into the struct scsi_device->request_queue.
* Also check for HEAD_OF_QUEUE SAM TASK attr from received se_cmd
* descriptor
*/
blk_execute_rq_nowait(pdv->pdv_sd->request_queue, NULL, pt->pscsi_req,
(task->task_se_cmd->sam_task_attr == MSG_HEAD_TAG),
pscsi_req_done);
return PYX_TRANSPORT_SENT_TO_TRANSPORT;
}
static void pscsi_free_task(struct se_task *task)
{
struct pscsi_plugin_task *pt = PSCSI_TASK(task);
@@ -1049,15 +959,12 @@ static inline struct bio *pscsi_get_bio(int sg_num)
return bio;
}
static int __pscsi_map_SG(
struct se_task *task,
struct scatterlist *task_sg,
u32 task_sg_num,
int bidi_read)
static int pscsi_map_sg(struct se_task *task, struct scatterlist *task_sg,
struct bio **hbio)
{
struct pscsi_plugin_task *pt = PSCSI_TASK(task);
struct pscsi_dev_virt *pdv = task->se_dev->dev_ptr;
struct bio *bio = NULL, *hbio = NULL, *tbio = NULL;
struct pscsi_dev_virt *pdv = task->task_se_cmd->se_dev->dev_ptr;
u32 task_sg_num = task->task_sg_nents;
struct bio *bio = NULL, *tbio = NULL;
struct page *page;
struct scatterlist *sg;
u32 data_len = task->task_size, i, len, bytes, off;
@@ -1066,19 +973,8 @@ static int __pscsi_map_SG(
int nr_vecs = 0, rc, ret = PYX_TRANSPORT_OUT_OF_MEMORY_RESOURCES;
int rw = (task->task_data_direction == DMA_TO_DEVICE);
if (!task->task_size)
return 0;
/*
* For SCF_SCSI_DATA_SG_IO_CDB, Use fs/bio.c:bio_add_page() to setup
* the bio_vec maplist from task->task_sg ->
* struct scatterlist memory. The struct se_task->task_sg[] currently needs
* to be attached to struct bios for submission to Linux/SCSI using
* struct request to struct scsi_device->request_queue.
*
* Note that this will be changing post v2.6.28 as Target_Core_Mod/pSCSI
* is ported to upstream SCSI passthrough functionality that accepts
* struct scatterlist->page_link or struct page as a paraemeter.
*/
*hbio = NULL;
pr_debug("PSCSI: nr_pages: %d\n", nr_pages);
for_each_sg(task_sg, sg, task_sg_num, i) {
@@ -1115,8 +1011,8 @@ static int __pscsi_map_SG(
* bios need to be added to complete a given
* struct se_task
*/
if (!hbio)
hbio = tbio = bio;
if (!*hbio)
*hbio = tbio = bio;
else
tbio = tbio->bi_next = bio;
}
@@ -1152,92 +1048,82 @@ static int __pscsi_map_SG(
off = 0;
}
}
/*
* Setup the primary pt->pscsi_req used for non BIDI and BIDI-COMMAND
* primary SCSI WRITE poayload mapped for struct se_task->task_sg[]
*/
if (!bidi_read) {
/*
* Starting with v2.6.31, call blk_make_request() passing in *hbio to
* allocate the pSCSI task a struct request.
*/
pt->pscsi_req = blk_make_request(pdv->pdv_sd->request_queue,
hbio, GFP_KERNEL);
if (!pt->pscsi_req) {
pr_err("pSCSI: blk_make_request() failed\n");
goto fail;
}
/*
* Setup the newly allocated struct request for REQ_TYPE_BLOCK_PC,
* and setup rq callback, CDB and sense.
*/
pscsi_blk_init_request(task, pt, pt->pscsi_req, 0);
return task->task_sg_nents;
}
/*
* Setup the secondary pt->pscsi_req->next_rq used for the extra BIDI-COMMAND
* SCSI READ paylaod mapped for struct se_task->task_sg_bidi[]
*/
pt->pscsi_req->next_rq = blk_make_request(pdv->pdv_sd->request_queue,
hbio, GFP_KERNEL);
if (!pt->pscsi_req->next_rq) {
pr_err("pSCSI: blk_make_request() failed for BIDI\n");
goto fail;
}
pscsi_blk_init_request(task, pt, pt->pscsi_req->next_rq, 1);
return task->task_sg_nents;
fail:
while (hbio) {
bio = hbio;
hbio = hbio->bi_next;
while (*hbio) {
bio = *hbio;
*hbio = (*hbio)->bi_next;
bio->bi_next = NULL;
bio_endio(bio, 0);
bio_endio(bio, 0); /* XXX: should be error */
}
return ret;
}
/*
* pSCSI maps both ->map_control_SG() and ->map_data_SG() to a single call.
*/
static int pscsi_map_SG(struct se_task *task)
static int pscsi_do_task(struct se_task *task)
{
struct pscsi_dev_virt *pdv = task->task_se_cmd->se_dev->dev_ptr;
struct pscsi_plugin_task *pt = PSCSI_TASK(task);
struct request *req;
struct bio *hbio;
int ret;
/*
* Setup the main struct request for the task->task_sg[] payload
*/
target_get_task_cdb(task, pt->pscsi_cdb);
if (task->task_se_cmd->se_cmd_flags & SCF_SCSI_NON_DATA_CDB) {
req = blk_get_request(pdv->pdv_sd->request_queue,
(task->task_data_direction == DMA_TO_DEVICE),
GFP_KERNEL);
if (!req || IS_ERR(req)) {
pr_err("PSCSI: blk_get_request() failed: %ld\n",
req ? IS_ERR(req) : -ENOMEM);
return PYX_TRANSPORT_LU_COMM_FAILURE;
}
} else {
BUG_ON(!task->task_size);
ret = __pscsi_map_SG(task, task->task_sg, task->task_sg_nents, 0);
if (ret >= 0 && task->task_sg_bidi) {
/*
* If present, set up the extra BIDI-COMMAND SCSI READ
* struct request and payload.
* Setup the main struct request for the task->task_sg[] payload
*/
ret = __pscsi_map_SG(task, task->task_sg_bidi,
task->task_sg_nents, 1);
ret = pscsi_map_sg(task, task->task_sg, &hbio);
if (ret < 0)
return PYX_TRANSPORT_LU_COMM_FAILURE;
req = blk_make_request(pdv->pdv_sd->request_queue, hbio,
GFP_KERNEL);
if (!req) {
pr_err("pSCSI: blk_make_request() failed\n");
goto fail;
}
}
if (ret < 0)
return PYX_TRANSPORT_LU_COMM_FAILURE;
return 0;
}
req->cmd_type = REQ_TYPE_BLOCK_PC;
req->end_io = pscsi_req_done;
req->end_io_data = task;
req->cmd_len = scsi_command_size(pt->pscsi_cdb);
req->cmd = &pt->pscsi_cdb[0];
req->sense = &pt->pscsi_sense[0];
req->sense_len = 0;
if (pdv->pdv_sd->type == TYPE_DISK)
req->timeout = PS_TIMEOUT_DISK;
else
req->timeout = PS_TIMEOUT_OTHER;
req->retries = PS_RETRY;
static int pscsi_CDB_none(struct se_task *task)
{
return pscsi_blk_get_request(task);
}
blk_execute_rq_nowait(pdv->pdv_sd->request_queue, NULL, req,
(task->task_se_cmd->sam_task_attr == MSG_HEAD_TAG),
pscsi_req_done);
/* pscsi_get_cdb():
*
*
*/
static unsigned char *pscsi_get_cdb(struct se_task *task)
{
struct pscsi_plugin_task *pt = PSCSI_TASK(task);
return PYX_TRANSPORT_SENT_TO_TRANSPORT;
return pt->pscsi_cdb;
fail:
while (hbio) {
struct bio *bio = hbio;
hbio = hbio->bi_next;
bio->bi_next = NULL;
bio_endio(bio, 0); /* XXX: should be error */
}
return PYX_TRANSPORT_OUT_OF_MEMORY_RESOURCES;
}
/* pscsi_get_sense_buffer():
@@ -1328,23 +1214,13 @@ static void pscsi_req_done(struct request *req, int uptodate)
pt->pscsi_resid = req->resid_len;
pscsi_process_SAM_status(task, pt);
/*
* Release BIDI-READ if present
*/
if (req->next_rq != NULL)
__blk_put_request(req->q, req->next_rq);
__blk_put_request(req->q, req);
pt->pscsi_req = NULL;
}
static struct se_subsystem_api pscsi_template = {
.name = "pscsi",
.owner = THIS_MODULE,
.transport_type = TRANSPORT_PLUGIN_PHBA_PDEV,
.cdb_none = pscsi_CDB_none,
.map_control_SG = pscsi_map_SG,
.map_data_SG = pscsi_map_SG,
.attach_hba = pscsi_attach_hba,
.detach_hba = pscsi_detach_hba,
.pmode_enable_hba = pscsi_pmode_enable_hba,
@@ -1358,7 +1234,6 @@ static struct se_subsystem_api pscsi_template = {
.check_configfs_dev_params = pscsi_check_configfs_dev_params,
.set_configfs_dev_params = pscsi_set_configfs_dev_params,
.show_configfs_dev_params = pscsi_show_configfs_dev_params,
.get_cdb = pscsi_get_cdb,
.get_sense_buffer = pscsi_get_sense_buffer,
.get_device_rev = pscsi_get_device_rev,
.get_device_type = pscsi_get_device_type,

Some files were not shown because too many files have changed in this diff Show More