Skip to content

Commit

Permalink
Merge git://git.kernel.org/pub/scm/linux/kernel/git/nab/target-pending
Browse files Browse the repository at this point in the history
Pull SCSI target fixes from Nicholas Bellinger:
 "These are mostly minor fixes, with the exception of the following that
  address fall-out from recent v4.1-rc1 changes:

   - regression fix related to the big fabric API registration changes
     and configfs_depend_item() usage, that required cherry-picking one
     of HCH's patches from for-next to address the issue for v4.1 code.

   - remaining TCM-USER -v2 related changes to enforce full CDB
     passthrough from Andy + Ilias.

  Also included is a target_core_pscsi driver fix from Andy that
  addresses a long standing issue with a Scsi_Host reference being
  leaked on PSCSI device shutdown"

* git://git.kernel.org/pub/scm/linux/kernel/git/nab/target-pending:
  iser-target: Fix error path in isert_create_pi_ctx()
  target: Use a PASSTHROUGH flag instead of transport_types
  target: Move passthrough CDB parsing into a common function
  target/user: Only support full command pass-through
  target/user: Update example code for new ABI requirements
  target/pscsi: Don't leak scsi_host if hba is VIRTUAL_HOST
  target: Fix se_tpg_tfo->tf_subsys regression + remove tf_subsystem
  target: Drop signal_pending checks after interruptible lock acquire
  target: Add missing parentheses
  target: Fix bidi command handling
  target/user: Disallow full passthrough (pass_level=0)
  ISCSI: fix minor memory leak
  • Loading branch information
torvalds committed May 31, 2015
2 parents 30a5f11 + b2feda4 commit dae8f28
Show file tree
Hide file tree
Showing 24 changed files with 180 additions and 287 deletions.
33 changes: 7 additions & 26 deletions Documentation/target/tcmu-design.txt
Original file line number Diff line number Diff line change
Expand Up @@ -15,8 +15,7 @@ Contents:
a) Discovering and configuring TCMU uio devices
b) Waiting for events on the device(s)
c) Managing the command ring
3) Command filtering and pass_level
4) A final note
3) A final note


TCM Userspace Design
Expand Down Expand Up @@ -324,7 +323,7 @@ int handle_device_events(int fd, void *map)
/* Process events from cmd ring until we catch up with cmd_head */
while (ent != (void *)mb + mb->cmdr_off + mb->cmd_head) {

if (tcmu_hdr_get_op(&ent->hdr) == TCMU_OP_CMD) {
if (tcmu_hdr_get_op(ent->hdr.len_op) == TCMU_OP_CMD) {
uint8_t *cdb = (void *)mb + ent->req.cdb_off;
bool success = true;

Expand All @@ -339,8 +338,12 @@ int handle_device_events(int fd, void *map)
ent->rsp.scsi_status = SCSI_CHECK_CONDITION;
}
}
else if (tcmu_hdr_get_op(ent->hdr.len_op) != TCMU_OP_PAD) {
/* Tell the kernel we didn't handle unknown opcodes */
ent->hdr.uflags |= TCMU_UFLAG_UNKNOWN_OP;
}
else {
/* Do nothing for PAD entries */
/* Do nothing for PAD entries except update cmd_tail */
}

/* update cmd_tail */
Expand All @@ -360,28 +363,6 @@ int handle_device_events(int fd, void *map)
}


Command filtering and pass_level
--------------------------------

TCMU supports a "pass_level" option with valid values of 0 or 1. When
the value is 0 (the default), nearly all SCSI commands received for
the device are passed through to the handler. This allows maximum
flexibility but increases the amount of code required by the handler,
to support all mandatory SCSI commands. If pass_level is set to 1,
then only IO-related commands are presented, and the rest are handled
by LIO's in-kernel command emulation. The commands presented at level
1 include all versions of:

READ
WRITE
WRITE_VERIFY
XDWRITEREAD
WRITE_SAME
COMPARE_AND_WRITE
SYNCHRONIZE_CACHE
UNMAP


A final note
------------

Expand Down
6 changes: 3 additions & 3 deletions drivers/infiniband/ulp/isert/ib_isert.c
Original file line number Diff line number Diff line change
Expand Up @@ -547,11 +547,11 @@ isert_create_pi_ctx(struct fast_reg_descriptor *desc,
return 0;

err_prot_mr:
ib_dereg_mr(desc->pi_ctx->prot_mr);
ib_dereg_mr(pi_ctx->prot_mr);
err_prot_frpl:
ib_free_fast_reg_page_list(desc->pi_ctx->prot_frpl);
ib_free_fast_reg_page_list(pi_ctx->prot_frpl);
err_pi_ctx:
kfree(desc->pi_ctx);
kfree(pi_ctx);

return ret;
}
Expand Down
6 changes: 2 additions & 4 deletions drivers/scsi/qla2xxx/tcm_qla2xxx.c
Original file line number Diff line number Diff line change
Expand Up @@ -1020,8 +1020,7 @@ static void tcm_qla2xxx_depend_tpg(struct work_struct *work)
struct se_portal_group *se_tpg = &base_tpg->se_tpg;
struct scsi_qla_host *base_vha = base_tpg->lport->qla_vha;

if (!configfs_depend_item(se_tpg->se_tpg_tfo->tf_subsys,
&se_tpg->tpg_group.cg_item)) {
if (!target_depend_item(&se_tpg->tpg_group.cg_item)) {
atomic_set(&base_tpg->lport_tpg_enabled, 1);
qlt_enable_vha(base_vha);
}
Expand All @@ -1037,8 +1036,7 @@ static void tcm_qla2xxx_undepend_tpg(struct work_struct *work)

if (!qlt_stop_phase1(base_vha->vha_tgt.qla_tgt)) {
atomic_set(&base_tpg->lport_tpg_enabled, 0);
configfs_undepend_item(se_tpg->se_tpg_tfo->tf_subsys,
&se_tpg->tpg_group.cg_item);
target_undepend_item(&se_tpg->tpg_group.cg_item);
}
complete(&base_tpg->tpg_base_comp);
}
Expand Down
2 changes: 1 addition & 1 deletion drivers/target/iscsi/iscsi_target.c
Original file line number Diff line number Diff line change
Expand Up @@ -230,7 +230,7 @@ int iscsit_access_np(struct iscsi_np *np, struct iscsi_portal_group *tpg)
* Here we serialize access across the TIQN+TPG Tuple.
*/
ret = down_interruptible(&tpg->np_login_sem);
if ((ret != 0) || signal_pending(current))
if (ret != 0)
return -1;

spin_lock_bh(&tpg->tpg_state_lock);
Expand Down
1 change: 1 addition & 0 deletions drivers/target/iscsi/iscsi_target_login.c
Original file line number Diff line number Diff line change
Expand Up @@ -346,6 +346,7 @@ static int iscsi_login_zero_tsih_s1(
if (IS_ERR(sess->se_sess)) {
iscsit_tx_login_rsp(conn, ISCSI_STATUS_CLS_TARGET_ERR,
ISCSI_LOGIN_STATUS_NO_RESOURCES);
kfree(sess->sess_ops);
kfree(sess);
return -ENOMEM;
}
Expand Down
5 changes: 1 addition & 4 deletions drivers/target/iscsi/iscsi_target_tpg.c
Original file line number Diff line number Diff line change
Expand Up @@ -161,10 +161,7 @@ struct iscsi_portal_group *iscsit_get_tpg_from_np(
int iscsit_get_tpg(
struct iscsi_portal_group *tpg)
{
int ret;

ret = mutex_lock_interruptible(&tpg->tpg_access_lock);
return ((ret != 0) || signal_pending(current)) ? -1 : 0;
return mutex_lock_interruptible(&tpg->tpg_access_lock);
}

void iscsit_put_tpg(struct iscsi_portal_group *tpg)
Expand Down
4 changes: 2 additions & 2 deletions drivers/target/target_core_alua.c
Original file line number Diff line number Diff line change
Expand Up @@ -704,7 +704,7 @@ target_alua_state_check(struct se_cmd *cmd)

if (dev->se_hba->hba_flags & HBA_FLAGS_INTERNAL_USE)
return 0;
if (dev->transport->transport_type == TRANSPORT_PLUGIN_PHBA_PDEV)
if (dev->transport->transport_flags & TRANSPORT_FLAG_PASSTHROUGH)
return 0;

if (!port)
Expand Down Expand Up @@ -2377,7 +2377,7 @@ ssize_t core_alua_store_secondary_write_metadata(

int core_setup_alua(struct se_device *dev)
{
if (dev->transport->transport_type != TRANSPORT_PLUGIN_PHBA_PDEV &&
if (!(dev->transport->transport_flags & TRANSPORT_FLAG_PASSTHROUGH) &&
!(dev->se_hba->hba_flags & HBA_FLAGS_INTERNAL_USE)) {
struct t10_alua_lu_gp_member *lu_gp_mem;

Expand Down
40 changes: 19 additions & 21 deletions drivers/target/target_core_configfs.c
Original file line number Diff line number Diff line change
Expand Up @@ -212,10 +212,6 @@ static struct config_group *target_core_register_fabric(

pr_debug("Target_Core_ConfigFS: REGISTER -> Allocated Fabric:"
" %s\n", tf->tf_group.cg_item.ci_name);
/*
* Setup tf_ops.tf_subsys pointer for usage with configfs_depend_item()
*/
tf->tf_ops.tf_subsys = tf->tf_subsys;
tf->tf_fabric = &tf->tf_group.cg_item;
pr_debug("Target_Core_ConfigFS: REGISTER -> Set tf->tf_fabric"
" for %s\n", name);
Expand Down Expand Up @@ -291,10 +287,17 @@ static struct configfs_subsystem target_core_fabrics = {
},
};

struct configfs_subsystem *target_core_subsystem[] = {
&target_core_fabrics,
NULL,
};
int target_depend_item(struct config_item *item)
{
return configfs_depend_item(&target_core_fabrics, item);
}
EXPORT_SYMBOL(target_depend_item);

void target_undepend_item(struct config_item *item)
{
return configfs_undepend_item(&target_core_fabrics, item);
}
EXPORT_SYMBOL(target_undepend_item);

/*##############################################################################
// Start functions called by external Target Fabrics Modules
Expand Down Expand Up @@ -467,7 +470,6 @@ int target_register_template(const struct target_core_fabric_ops *fo)
* struct target_fabric_configfs->tf_cit_tmpl
*/
tf->tf_module = fo->module;
tf->tf_subsys = target_core_subsystem[0];
snprintf(tf->tf_name, TARGET_FABRIC_NAME_SIZE, "%s", fo->name);

tf->tf_ops = *fo;
Expand Down Expand Up @@ -809,7 +811,7 @@ static ssize_t target_core_dev_pr_show_attr_res_holder(struct se_device *dev,
{
int ret;

if (dev->transport->transport_type == TRANSPORT_PLUGIN_PHBA_PDEV)
if (dev->transport->transport_flags & TRANSPORT_FLAG_PASSTHROUGH)
return sprintf(page, "Passthrough\n");

spin_lock(&dev->dev_reservation_lock);
Expand Down Expand Up @@ -960,7 +962,7 @@ SE_DEV_PR_ATTR_RO(res_pr_type);
static ssize_t target_core_dev_pr_show_attr_res_type(
struct se_device *dev, char *page)
{
if (dev->transport->transport_type == TRANSPORT_PLUGIN_PHBA_PDEV)
if (dev->transport->transport_flags & TRANSPORT_FLAG_PASSTHROUGH)
return sprintf(page, "SPC_PASSTHROUGH\n");
else if (dev->dev_reservation_flags & DRF_SPC2_RESERVATIONS)
return sprintf(page, "SPC2_RESERVATIONS\n");
Expand All @@ -973,7 +975,7 @@ SE_DEV_PR_ATTR_RO(res_type);
static ssize_t target_core_dev_pr_show_attr_res_aptpl_active(
struct se_device *dev, char *page)
{
if (dev->transport->transport_type == TRANSPORT_PLUGIN_PHBA_PDEV)
if (dev->transport->transport_flags & TRANSPORT_FLAG_PASSTHROUGH)
return 0;

return sprintf(page, "APTPL Bit Status: %s\n",
Expand All @@ -988,7 +990,7 @@ SE_DEV_PR_ATTR_RO(res_aptpl_active);
static ssize_t target_core_dev_pr_show_attr_res_aptpl_metadata(
struct se_device *dev, char *page)
{
if (dev->transport->transport_type == TRANSPORT_PLUGIN_PHBA_PDEV)
if (dev->transport->transport_flags & TRANSPORT_FLAG_PASSTHROUGH)
return 0;

return sprintf(page, "Ready to process PR APTPL metadata..\n");
Expand Down Expand Up @@ -1035,7 +1037,7 @@ static ssize_t target_core_dev_pr_store_attr_res_aptpl_metadata(
u16 port_rpti = 0, tpgt = 0;
u8 type = 0, scope;

if (dev->transport->transport_type == TRANSPORT_PLUGIN_PHBA_PDEV)
if (dev->transport->transport_flags & TRANSPORT_FLAG_PASSTHROUGH)
return 0;
if (dev->dev_reservation_flags & DRF_SPC2_RESERVATIONS)
return 0;
Expand Down Expand Up @@ -2870,15 +2872,14 @@ static int __init target_core_init_configfs(void)
{
struct config_group *target_cg, *hba_cg = NULL, *alua_cg = NULL;
struct config_group *lu_gp_cg = NULL;
struct configfs_subsystem *subsys;
struct configfs_subsystem *subsys = &target_core_fabrics;
struct t10_alua_lu_gp *lu_gp;
int ret;

pr_debug("TARGET_CORE[0]: Loading Generic Kernel Storage"
" Engine: %s on %s/%s on "UTS_RELEASE"\n",
TARGET_CORE_VERSION, utsname()->sysname, utsname()->machine);

subsys = target_core_subsystem[0];
config_group_init(&subsys->su_group);
mutex_init(&subsys->su_mutex);

Expand Down Expand Up @@ -3008,13 +3009,10 @@ static int __init target_core_init_configfs(void)

static void __exit target_core_exit_configfs(void)
{
struct configfs_subsystem *subsys;
struct config_group *hba_cg, *alua_cg, *lu_gp_cg;
struct config_item *item;
int i;

subsys = target_core_subsystem[0];

lu_gp_cg = &alua_lu_gps_group;
for (i = 0; lu_gp_cg->default_groups[i]; i++) {
item = &lu_gp_cg->default_groups[i]->cg_item;
Expand Down Expand Up @@ -3045,8 +3043,8 @@ static void __exit target_core_exit_configfs(void)
* We expect subsys->su_group.default_groups to be released
* by configfs subsystem provider logic..
*/
configfs_unregister_subsystem(subsys);
kfree(subsys->su_group.default_groups);
configfs_unregister_subsystem(&target_core_fabrics);
kfree(target_core_fabrics.su_group.default_groups);

core_alua_free_lu_gp(default_lu_gp);
default_lu_gp = NULL;
Expand Down
78 changes: 76 additions & 2 deletions drivers/target/target_core_device.c
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@
#include <linux/kthread.h>
#include <linux/in.h>
#include <linux/export.h>
#include <asm/unaligned.h>
#include <net/sock.h>
#include <net/tcp.h>
#include <scsi/scsi.h>
Expand Down Expand Up @@ -527,7 +528,7 @@ static void core_export_port(
list_add_tail(&port->sep_list, &dev->dev_sep_list);
spin_unlock(&dev->se_port_lock);

if (dev->transport->transport_type != TRANSPORT_PLUGIN_PHBA_PDEV &&
if (!(dev->transport->transport_flags & TRANSPORT_FLAG_PASSTHROUGH) &&
!(dev->se_hba->hba_flags & HBA_FLAGS_INTERNAL_USE)) {
tg_pt_gp_mem = core_alua_allocate_tg_pt_gp_mem(port);
if (IS_ERR(tg_pt_gp_mem) || !tg_pt_gp_mem) {
Expand Down Expand Up @@ -1603,7 +1604,7 @@ int target_configure_device(struct se_device *dev)
* anything virtual (IBLOCK, FILEIO, RAMDISK), but not for TCM/pSCSI
* passthrough because this is being provided by the backend LLD.
*/
if (dev->transport->transport_type != TRANSPORT_PLUGIN_PHBA_PDEV) {
if (!(dev->transport->transport_flags & TRANSPORT_FLAG_PASSTHROUGH)) {
strncpy(&dev->t10_wwn.vendor[0], "LIO-ORG", 8);
strncpy(&dev->t10_wwn.model[0],
dev->transport->inquiry_prod, 16);
Expand Down Expand Up @@ -1707,3 +1708,76 @@ void core_dev_release_virtual_lun0(void)
target_free_device(g_lun0_dev);
core_delete_hba(hba);
}

/*
* Common CDB parsing for kernel and user passthrough.
*/
sense_reason_t
passthrough_parse_cdb(struct se_cmd *cmd,
sense_reason_t (*exec_cmd)(struct se_cmd *cmd))
{
unsigned char *cdb = cmd->t_task_cdb;

/*
* Clear a lun set in the cdb if the initiator talking to use spoke
* and old standards version, as we can't assume the underlying device
* won't choke up on it.
*/
switch (cdb[0]) {
case READ_10: /* SBC - RDProtect */
case READ_12: /* SBC - RDProtect */
case READ_16: /* SBC - RDProtect */
case SEND_DIAGNOSTIC: /* SPC - SELF-TEST Code */
case VERIFY: /* SBC - VRProtect */
case VERIFY_16: /* SBC - VRProtect */
case WRITE_VERIFY: /* SBC - VRProtect */
case WRITE_VERIFY_12: /* SBC - VRProtect */
case MAINTENANCE_IN: /* SPC - Parameter Data Format for SA RTPG */
break;
default:
cdb[1] &= 0x1f; /* clear logical unit number */
break;
}

/*
* For REPORT LUNS we always need to emulate the response, for everything
* else, pass it up.
*/
if (cdb[0] == REPORT_LUNS) {
cmd->execute_cmd = spc_emulate_report_luns;
return TCM_NO_SENSE;
}

/* Set DATA_CDB flag for ops that should have it */
switch (cdb[0]) {
case READ_6:
case READ_10:
case READ_12:
case READ_16:
case WRITE_6:
case WRITE_10:
case WRITE_12:
case WRITE_16:
case WRITE_VERIFY:
case WRITE_VERIFY_12:
case 0x8e: /* WRITE_VERIFY_16 */
case COMPARE_AND_WRITE:
case XDWRITEREAD_10:
cmd->se_cmd_flags |= SCF_SCSI_DATA_CDB;
break;
case VARIABLE_LENGTH_CMD:
switch (get_unaligned_be16(&cdb[8])) {
case READ_32:
case WRITE_32:
case 0x0c: /* WRITE_VERIFY_32 */
case XDWRITEREAD_32:
cmd->se_cmd_flags |= SCF_SCSI_DATA_CDB;
break;
}
}

cmd->execute_cmd = exec_cmd;

return TCM_NO_SENSE;
}
EXPORT_SYMBOL(passthrough_parse_cdb);
1 change: 0 additions & 1 deletion drivers/target/target_core_file.c
Original file line number Diff line number Diff line change
Expand Up @@ -958,7 +958,6 @@ static struct se_subsystem_api fileio_template = {
.inquiry_prod = "FILEIO",
.inquiry_rev = FD_VERSION,
.owner = THIS_MODULE,
.transport_type = TRANSPORT_PLUGIN_VHBA_PDEV,
.attach_hba = fd_attach_hba,
.detach_hba = fd_detach_hba,
.alloc_device = fd_alloc_device,
Expand Down
1 change: 0 additions & 1 deletion drivers/target/target_core_iblock.c
Original file line number Diff line number Diff line change
Expand Up @@ -904,7 +904,6 @@ static struct se_subsystem_api iblock_template = {
.inquiry_prod = "IBLOCK",
.inquiry_rev = IBLOCK_VERSION,
.owner = THIS_MODULE,
.transport_type = TRANSPORT_PLUGIN_VHBA_PDEV,
.attach_hba = iblock_attach_hba,
.detach_hba = iblock_detach_hba,
.alloc_device = iblock_alloc_device,
Expand Down
Loading

0 comments on commit dae8f28

Please sign in to comment.