Merge branch 'for-next' of git://git.kernel.org/pub/scm/linux/kernel/git/nab/target-pending
Pull SCSI target updates from Nicholas Bellinger: "The highlights this round include: - Introduce configfs support for unlocked configfs_depend_item() (krzysztof + andrezej) - Conversion of usb-gadget target driver to new function registration interface (andrzej + sebastian) - Enable qla2xxx FC target mode support for Extended Logins (himansu + giridhar) - Enable qla2xxx FC target mode support for Exchange Offload (himansu + giridhar) - Add qla2xxx FC target mode irq affinity notification + selective command queuing. (quinn + himanshu) - Fix iscsi-target deadlock in se_node_acl configfs deletion (sagi + nab) - Convert se_node_acl configfs deletion + se_node_acl->queue_depth to proper se_session->sess_kref + target_get_session() usage. (hch + sagi + nab) - Fix long-standing race between se_node_acl->acl_kref get and get_initiator_node_acl() lookup. (hch + nab) - Fix target/user block-size handling, and make sure netlink reaches all network namespaces (sheng + andy) Note there is an outstanding bug-fix series for remote I_T nexus port TMR LUN_RESET has been posted and still being tested, and will likely become post -rc1 material at this point" * 'for-next' of git://git.kernel.org/pub/scm/linux/kernel/git/nab/target-pending: (56 commits) scsi: qla2xxxx: avoid type mismatch in comparison target/user: Make sure netlink would reach all network namespaces target: Obtain se_node_acl->acl_kref during get_initiator_node_acl target: Convert ACL change queue_depth se_session reference usage iscsi-target: Fix potential dead-lock during node acl delete ib_srpt: Convert acl lookup to modern get_initiator_node_acl usage tcm_fc: Convert acl lookup to modern get_initiator_node_acl usage tcm_fc: Wait for command completion before freeing a session target: Fix a memory leak in target_dev_lba_map_store() target: Support aborting tasks with a 64-bit tag usb/gadget: Remove set-but-not-used variables target: Remove an unused variable target: Fix indentation in target_core_configfs.c target/user: Allow user to set block size before enabling device iser-target: Fix non negative ERR_PTR isert_device_get usage target/fcoe: Add tag support to tcm_fc qla2xxx: Check for online flag instead of active reset when transmitting responses qla2xxx: Set all queues to 4k qla2xxx: Disable ZIO at start time. qla2xxx: Move atioq to a different lock to reduce lock contention ...
This commit is contained in:
@@ -1333,7 +1333,7 @@ iscsit_check_dataout_hdr(struct iscsi_conn *conn, unsigned char *buf,
|
||||
/*
|
||||
* Check if a delayed TASK_ABORTED status needs to
|
||||
* be sent now if the ISCSI_FLAG_CMD_FINAL has been
|
||||
* received with the unsolicitied data out.
|
||||
* received with the unsolicited data out.
|
||||
*/
|
||||
if (hdr->flags & ISCSI_FLAG_CMD_FINAL)
|
||||
iscsit_stop_dataout_timer(cmd);
|
||||
@@ -3435,7 +3435,7 @@ iscsit_build_sendtargets_response(struct iscsi_cmd *cmd,
|
||||
|
||||
if ((tpg->tpg_attrib.generate_node_acls == 0) &&
|
||||
(tpg->tpg_attrib.demo_mode_discovery == 0) &&
|
||||
(!core_tpg_get_initiator_node_acl(&tpg->tpg_se_tpg,
|
||||
(!target_tpg_has_node_acl(&tpg->tpg_se_tpg,
|
||||
cmd->conn->sess->sess_ops->InitiatorName))) {
|
||||
continue;
|
||||
}
|
||||
@@ -4459,9 +4459,6 @@ int iscsit_close_connection(
|
||||
|
||||
return 0;
|
||||
}
|
||||
spin_unlock_bh(&sess->conn_lock);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int iscsit_close_session(struct iscsi_session *sess)
|
||||
|
@@ -725,11 +725,8 @@ static ssize_t lio_target_nacl_cmdsn_depth_store(struct config_item *item,
|
||||
|
||||
if (iscsit_get_tpg(tpg) < 0)
|
||||
return -EINVAL;
|
||||
/*
|
||||
* iscsit_tpg_set_initiator_node_queue_depth() assumes force=1
|
||||
*/
|
||||
ret = iscsit_tpg_set_initiator_node_queue_depth(tpg,
|
||||
config_item_name(acl_ci), cmdsn_depth, 1);
|
||||
|
||||
ret = core_tpg_set_initiator_node_queue_depth(se_nacl, cmdsn_depth);
|
||||
|
||||
pr_debug("LIO_Target_ConfigFS: %s/%s Set CmdSN Window: %u for"
|
||||
"InitiatorName: %s\n", config_item_name(wwn_ci),
|
||||
@@ -1593,28 +1590,30 @@ static int lio_tpg_check_prot_fabric_only(
|
||||
}
|
||||
|
||||
/*
|
||||
* Called with spin_lock_bh(struct se_portal_group->session_lock) held..
|
||||
*
|
||||
* Also, this function calls iscsit_inc_session_usage_count() on the
|
||||
* This function calls iscsit_inc_session_usage_count() on the
|
||||
* struct iscsi_session in question.
|
||||
*/
|
||||
static int lio_tpg_shutdown_session(struct se_session *se_sess)
|
||||
{
|
||||
struct iscsi_session *sess = se_sess->fabric_sess_ptr;
|
||||
struct se_portal_group *se_tpg = &sess->tpg->tpg_se_tpg;
|
||||
|
||||
spin_lock_bh(&se_tpg->session_lock);
|
||||
spin_lock(&sess->conn_lock);
|
||||
if (atomic_read(&sess->session_fall_back_to_erl0) ||
|
||||
atomic_read(&sess->session_logout) ||
|
||||
(sess->time2retain_timer_flags & ISCSI_TF_EXPIRED)) {
|
||||
spin_unlock(&sess->conn_lock);
|
||||
spin_unlock_bh(&se_tpg->session_lock);
|
||||
return 0;
|
||||
}
|
||||
atomic_set(&sess->session_reinstatement, 1);
|
||||
spin_unlock(&sess->conn_lock);
|
||||
|
||||
iscsit_stop_time2retain_timer(sess);
|
||||
iscsit_stop_session(sess, 1, 1);
|
||||
spin_unlock_bh(&se_tpg->session_lock);
|
||||
|
||||
iscsit_stop_session(sess, 1, 1);
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
@@ -160,8 +160,7 @@ static int iscsit_handle_r2t_snack(
|
||||
" protocol error.\n", cmd->init_task_tag, begrun,
|
||||
(begrun + runlength), cmd->acked_data_sn);
|
||||
|
||||
return iscsit_reject_cmd(cmd,
|
||||
ISCSI_REASON_PROTOCOL_ERROR, buf);
|
||||
return iscsit_reject_cmd(cmd, ISCSI_REASON_PROTOCOL_ERROR, buf);
|
||||
}
|
||||
|
||||
if (runlength) {
|
||||
@@ -628,8 +627,8 @@ int iscsit_dataout_datapduinorder_no_fbit(
|
||||
if (cmd->pdu_list[i].seq_no == pdu->seq_no) {
|
||||
if (!first_pdu)
|
||||
first_pdu = &cmd->pdu_list[i];
|
||||
xfer_len += cmd->pdu_list[i].length;
|
||||
pdu_count++;
|
||||
xfer_len += cmd->pdu_list[i].length;
|
||||
pdu_count++;
|
||||
} else if (pdu_count)
|
||||
break;
|
||||
}
|
||||
|
@@ -1668,7 +1668,7 @@ void iscsi_set_session_parameters(
|
||||
param->value);
|
||||
} else if (!strcmp(param->name, INITIALR2T)) {
|
||||
ops->InitialR2T = !strcmp(param->value, YES);
|
||||
pr_debug("InitialR2T: %s\n",
|
||||
pr_debug("InitialR2T: %s\n",
|
||||
param->value);
|
||||
} else if (!strcmp(param->name, IMMEDIATEDATA)) {
|
||||
ops->ImmediateData = !strcmp(param->value, YES);
|
||||
|
@@ -82,7 +82,7 @@ int iscsit_tmr_task_warm_reset(
|
||||
pr_err("TMR Opcode TARGET_WARM_RESET authorization"
|
||||
" failed for Initiator Node: %s\n",
|
||||
sess->se_sess->se_node_acl->initiatorname);
|
||||
return -1;
|
||||
return -1;
|
||||
}
|
||||
/*
|
||||
* Do the real work in transport_generic_do_tmr().
|
||||
|
@@ -590,16 +590,6 @@ int iscsit_tpg_del_network_portal(
|
||||
return iscsit_tpg_release_np(tpg_np, tpg, np);
|
||||
}
|
||||
|
||||
int iscsit_tpg_set_initiator_node_queue_depth(
|
||||
struct iscsi_portal_group *tpg,
|
||||
unsigned char *initiatorname,
|
||||
u32 queue_depth,
|
||||
int force)
|
||||
{
|
||||
return core_tpg_set_initiator_node_queue_depth(&tpg->tpg_se_tpg,
|
||||
initiatorname, queue_depth, force);
|
||||
}
|
||||
|
||||
int iscsit_ta_authentication(struct iscsi_portal_group *tpg, u32 authentication)
|
||||
{
|
||||
unsigned char buf1[256], buf2[256], *none = NULL;
|
||||
|
@@ -26,8 +26,6 @@ extern struct iscsi_tpg_np *iscsit_tpg_add_network_portal(struct iscsi_portal_gr
|
||||
int);
|
||||
extern int iscsit_tpg_del_network_portal(struct iscsi_portal_group *,
|
||||
struct iscsi_tpg_np *);
|
||||
extern int iscsit_tpg_set_initiator_node_queue_depth(struct iscsi_portal_group *,
|
||||
unsigned char *, u32, int);
|
||||
extern int iscsit_ta_authentication(struct iscsi_portal_group *, u32);
|
||||
extern int iscsit_ta_login_timeout(struct iscsi_portal_group *, u32);
|
||||
extern int iscsit_ta_netif_timeout(struct iscsi_portal_group *, u32);
|
||||
|
@@ -1036,12 +1036,26 @@ static ssize_t tcm_loop_tpg_transport_status_store(struct config_item *item,
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
static ssize_t tcm_loop_tpg_address_show(struct config_item *item,
|
||||
char *page)
|
||||
{
|
||||
struct se_portal_group *se_tpg = to_tpg(item);
|
||||
struct tcm_loop_tpg *tl_tpg = container_of(se_tpg,
|
||||
struct tcm_loop_tpg, tl_se_tpg);
|
||||
struct tcm_loop_hba *tl_hba = tl_tpg->tl_hba;
|
||||
|
||||
return snprintf(page, PAGE_SIZE, "%d:0:%d\n",
|
||||
tl_hba->sh->host_no, tl_tpg->tl_tpgt);
|
||||
}
|
||||
|
||||
CONFIGFS_ATTR(tcm_loop_tpg_, nexus);
|
||||
CONFIGFS_ATTR(tcm_loop_tpg_, transport_status);
|
||||
CONFIGFS_ATTR_RO(tcm_loop_tpg_, address);
|
||||
|
||||
static struct configfs_attribute *tcm_loop_tpg_attrs[] = {
|
||||
&tcm_loop_tpg_attr_nexus,
|
||||
&tcm_loop_tpg_attr_transport_status,
|
||||
&tcm_loop_tpg_attr_address,
|
||||
NULL,
|
||||
};
|
||||
|
||||
|
@@ -39,8 +39,6 @@
|
||||
|
||||
#include "sbp_target.h"
|
||||
|
||||
static const struct target_core_fabric_ops sbp_ops;
|
||||
|
||||
/* FireWire address region for management and command block address handlers */
|
||||
static const struct fw_address_region sbp_register_region = {
|
||||
.start = CSR_REGISTER_BASE + 0x10000,
|
||||
|
@@ -278,7 +278,7 @@ EXPORT_SYMBOL(target_depend_item);
|
||||
|
||||
void target_undepend_item(struct config_item *item)
|
||||
{
|
||||
return configfs_undepend_item(&target_core_fabrics, item);
|
||||
return configfs_undepend_item(item);
|
||||
}
|
||||
EXPORT_SYMBOL(target_undepend_item);
|
||||
|
||||
@@ -499,6 +499,7 @@ DEF_CONFIGFS_ATTRIB_SHOW(max_unmap_lba_count);
|
||||
DEF_CONFIGFS_ATTRIB_SHOW(max_unmap_block_desc_count);
|
||||
DEF_CONFIGFS_ATTRIB_SHOW(unmap_granularity);
|
||||
DEF_CONFIGFS_ATTRIB_SHOW(unmap_granularity_alignment);
|
||||
DEF_CONFIGFS_ATTRIB_SHOW(unmap_zeroes_data);
|
||||
DEF_CONFIGFS_ATTRIB_SHOW(max_write_same_len);
|
||||
|
||||
#define DEF_CONFIGFS_ATTRIB_STORE_U32(_name) \
|
||||
@@ -548,7 +549,8 @@ static ssize_t _name##_store(struct config_item *item, const char *page,\
|
||||
size_t count) \
|
||||
{ \
|
||||
printk_once(KERN_WARNING \
|
||||
"ignoring deprecated ##_name## attribute\n"); \
|
||||
"ignoring deprecated %s attribute\n", \
|
||||
__stringify(_name)); \
|
||||
return count; \
|
||||
}
|
||||
|
||||
@@ -866,6 +868,39 @@ static ssize_t emulate_rest_reord_store(struct config_item *item,
|
||||
return count;
|
||||
}
|
||||
|
||||
static ssize_t unmap_zeroes_data_store(struct config_item *item,
|
||||
const char *page, size_t count)
|
||||
{
|
||||
struct se_dev_attrib *da = to_attrib(item);
|
||||
bool flag;
|
||||
int ret;
|
||||
|
||||
ret = strtobool(page, &flag);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
if (da->da_dev->export_count) {
|
||||
pr_err("dev[%p]: Unable to change SE Device"
|
||||
" unmap_zeroes_data while export_count is %d\n",
|
||||
da->da_dev, da->da_dev->export_count);
|
||||
return -EINVAL;
|
||||
}
|
||||
/*
|
||||
* We expect this value to be non-zero when generic Block Layer
|
||||
* Discard supported is detected iblock_configure_device().
|
||||
*/
|
||||
if (flag && !da->max_unmap_block_desc_count) {
|
||||
pr_err("dev[%p]: Thin Provisioning LBPRZ will not be set"
|
||||
" because max_unmap_block_desc_count is zero\n",
|
||||
da->da_dev);
|
||||
return -ENOSYS;
|
||||
}
|
||||
da->unmap_zeroes_data = flag;
|
||||
pr_debug("dev[%p]: SE Device Thin Provisioning LBPRZ bit: %d\n",
|
||||
da->da_dev, flag);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Note, this can only be called on unexported SE Device Object.
|
||||
*/
|
||||
@@ -998,6 +1033,7 @@ CONFIGFS_ATTR(, max_unmap_lba_count);
|
||||
CONFIGFS_ATTR(, max_unmap_block_desc_count);
|
||||
CONFIGFS_ATTR(, unmap_granularity);
|
||||
CONFIGFS_ATTR(, unmap_granularity_alignment);
|
||||
CONFIGFS_ATTR(, unmap_zeroes_data);
|
||||
CONFIGFS_ATTR(, max_write_same_len);
|
||||
|
||||
/*
|
||||
@@ -1034,6 +1070,7 @@ struct configfs_attribute *sbc_attrib_attrs[] = {
|
||||
&attr_max_unmap_block_desc_count,
|
||||
&attr_unmap_granularity,
|
||||
&attr_unmap_granularity_alignment,
|
||||
&attr_unmap_zeroes_data,
|
||||
&attr_max_write_same_len,
|
||||
NULL,
|
||||
};
|
||||
@@ -1980,14 +2017,14 @@ static ssize_t target_dev_lba_map_store(struct config_item *item,
|
||||
struct se_device *dev = to_device(item);
|
||||
struct t10_alua_lba_map *lba_map = NULL;
|
||||
struct list_head lba_list;
|
||||
char *map_entries, *ptr;
|
||||
char *map_entries, *orig, *ptr;
|
||||
char state;
|
||||
int pg_num = -1, pg;
|
||||
int ret = 0, num = 0, pg_id, alua_state;
|
||||
unsigned long start_lba = -1, end_lba = -1;
|
||||
unsigned long segment_size = -1, segment_mult = -1;
|
||||
|
||||
map_entries = kstrdup(page, GFP_KERNEL);
|
||||
orig = map_entries = kstrdup(page, GFP_KERNEL);
|
||||
if (!map_entries)
|
||||
return -ENOMEM;
|
||||
|
||||
@@ -2085,7 +2122,7 @@ out:
|
||||
} else
|
||||
core_alua_set_lba_map(dev, &lba_list,
|
||||
segment_size, segment_mult);
|
||||
kfree(map_entries);
|
||||
kfree(orig);
|
||||
return count;
|
||||
}
|
||||
|
||||
|
@@ -813,6 +813,8 @@ struct se_device *target_alloc_device(struct se_hba *hba, const char *name)
|
||||
dev->dev_attrib.unmap_granularity = DA_UNMAP_GRANULARITY_DEFAULT;
|
||||
dev->dev_attrib.unmap_granularity_alignment =
|
||||
DA_UNMAP_GRANULARITY_ALIGNMENT_DEFAULT;
|
||||
dev->dev_attrib.unmap_zeroes_data =
|
||||
DA_UNMAP_ZEROES_DATA_DEFAULT;
|
||||
dev->dev_attrib.max_write_same_len = DA_MAX_WRITE_SAME_LEN;
|
||||
|
||||
xcopy_lun = &dev->xcopy_lun;
|
||||
|
@@ -138,6 +138,8 @@ static int iblock_configure_device(struct se_device *dev)
|
||||
q->limits.discard_granularity >> 9;
|
||||
dev->dev_attrib.unmap_granularity_alignment =
|
||||
q->limits.discard_alignment;
|
||||
dev->dev_attrib.unmap_zeroes_data =
|
||||
q->limits.discard_zeroes_data;
|
||||
|
||||
pr_debug("IBLOCK: BLOCK Discard support available,"
|
||||
" disabled by default\n");
|
||||
|
@@ -1457,8 +1457,7 @@ static void core_scsi3_nodeacl_undepend_item(struct se_node_acl *nacl)
|
||||
static int core_scsi3_lunacl_depend_item(struct se_dev_entry *se_deve)
|
||||
{
|
||||
struct se_lun_acl *lun_acl;
|
||||
struct se_node_acl *nacl;
|
||||
struct se_portal_group *tpg;
|
||||
|
||||
/*
|
||||
* For nacl->dynamic_node_acl=1
|
||||
*/
|
||||
@@ -1467,17 +1466,13 @@ static int core_scsi3_lunacl_depend_item(struct se_dev_entry *se_deve)
|
||||
if (!lun_acl)
|
||||
return 0;
|
||||
|
||||
nacl = lun_acl->se_lun_nacl;
|
||||
tpg = nacl->se_tpg;
|
||||
|
||||
return target_depend_item(&lun_acl->se_lun_group.cg_item);
|
||||
}
|
||||
|
||||
static void core_scsi3_lunacl_undepend_item(struct se_dev_entry *se_deve)
|
||||
{
|
||||
struct se_lun_acl *lun_acl;
|
||||
struct se_node_acl *nacl;
|
||||
struct se_portal_group *tpg;
|
||||
|
||||
/*
|
||||
* For nacl->dynamic_node_acl=1
|
||||
*/
|
||||
@@ -1487,8 +1482,6 @@ static void core_scsi3_lunacl_undepend_item(struct se_dev_entry *se_deve)
|
||||
kref_put(&se_deve->pr_kref, target_pr_kref_release);
|
||||
return;
|
||||
}
|
||||
nacl = lun_acl->se_lun_nacl;
|
||||
tpg = nacl->se_tpg;
|
||||
|
||||
target_undepend_item(&lun_acl->se_lun_group.cg_item);
|
||||
kref_put(&se_deve->pr_kref, target_pr_kref_release);
|
||||
|
@@ -141,9 +141,17 @@ sbc_emulate_readcapacity_16(struct se_cmd *cmd)
|
||||
* Set Thin Provisioning Enable bit following sbc3r22 in section
|
||||
* READ CAPACITY (16) byte 14 if emulate_tpu or emulate_tpws is enabled.
|
||||
*/
|
||||
if (dev->dev_attrib.emulate_tpu || dev->dev_attrib.emulate_tpws)
|
||||
if (dev->dev_attrib.emulate_tpu || dev->dev_attrib.emulate_tpws) {
|
||||
buf[14] |= 0x80;
|
||||
|
||||
/*
|
||||
* LBPRZ signifies that zeroes will be read back from an LBA after
|
||||
* an UNMAP or WRITE SAME w/ unmap bit (sbc3r36 5.16.2)
|
||||
*/
|
||||
if (dev->dev_attrib.unmap_zeroes_data)
|
||||
buf[14] |= 0x40;
|
||||
}
|
||||
|
||||
rbuf = transport_kmap_data_sg(cmd);
|
||||
if (rbuf) {
|
||||
memcpy(rbuf, buf, min_t(u32, sizeof(buf), cmd->data_length));
|
||||
|
@@ -635,6 +635,18 @@ spc_emulate_evpd_b2(struct se_cmd *cmd, unsigned char *buf)
|
||||
if (dev->dev_attrib.emulate_tpws != 0)
|
||||
buf[5] |= 0x40 | 0x20;
|
||||
|
||||
/*
|
||||
* The unmap_zeroes_data set means that the underlying device supports
|
||||
* REQ_DISCARD and has the discard_zeroes_data bit set. This satisfies
|
||||
* the SBC requirements for LBPRZ, meaning that a subsequent read
|
||||
* will return zeroes after an UNMAP or WRITE SAME (16) to an LBA
|
||||
* See sbc4r36 6.6.4.
|
||||
*/
|
||||
if (((dev->dev_attrib.emulate_tpu != 0) ||
|
||||
(dev->dev_attrib.emulate_tpws != 0)) &&
|
||||
(dev->dev_attrib.unmap_zeroes_data != 0))
|
||||
buf[5] |= 0x04;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@@ -201,7 +201,7 @@ static void core_tmr_drain_tmr_list(
|
||||
/*
|
||||
* If this function was called with a valid pr_res_key
|
||||
* parameter (eg: for PROUT PREEMPT_AND_ABORT service action
|
||||
* skip non regisration key matching TMRs.
|
||||
* skip non registration key matching TMRs.
|
||||
*/
|
||||
if (target_check_cdb_and_preempt(preempt_and_abort_list, cmd))
|
||||
continue;
|
||||
|
@@ -75,9 +75,21 @@ struct se_node_acl *core_tpg_get_initiator_node_acl(
|
||||
unsigned char *initiatorname)
|
||||
{
|
||||
struct se_node_acl *acl;
|
||||
|
||||
/*
|
||||
* Obtain se_node_acl->acl_kref using fabric driver provided
|
||||
* initiatorname[] during node acl endpoint lookup driven by
|
||||
* new se_session login.
|
||||
*
|
||||
* The reference is held until se_session shutdown -> release
|
||||
* occurs via fabric driver invoked transport_deregister_session()
|
||||
* or transport_free_session() code.
|
||||
*/
|
||||
mutex_lock(&tpg->acl_node_mutex);
|
||||
acl = __core_tpg_get_initiator_node_acl(tpg, initiatorname);
|
||||
if (acl) {
|
||||
if (!kref_get_unless_zero(&acl->acl_kref))
|
||||
acl = NULL;
|
||||
}
|
||||
mutex_unlock(&tpg->acl_node_mutex);
|
||||
|
||||
return acl;
|
||||
@@ -157,28 +169,25 @@ void core_tpg_add_node_to_devs(
|
||||
mutex_unlock(&tpg->tpg_lun_mutex);
|
||||
}
|
||||
|
||||
/* core_set_queue_depth_for_node():
|
||||
*
|
||||
*
|
||||
*/
|
||||
static int core_set_queue_depth_for_node(
|
||||
struct se_portal_group *tpg,
|
||||
struct se_node_acl *acl)
|
||||
static void
|
||||
target_set_nacl_queue_depth(struct se_portal_group *tpg,
|
||||
struct se_node_acl *acl, u32 queue_depth)
|
||||
{
|
||||
acl->queue_depth = queue_depth;
|
||||
|
||||
if (!acl->queue_depth) {
|
||||
pr_err("Queue depth for %s Initiator Node: %s is 0,"
|
||||
pr_warn("Queue depth for %s Initiator Node: %s is 0,"
|
||||
"defaulting to 1.\n", tpg->se_tpg_tfo->get_fabric_name(),
|
||||
acl->initiatorname);
|
||||
acl->queue_depth = 1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static struct se_node_acl *target_alloc_node_acl(struct se_portal_group *tpg,
|
||||
const unsigned char *initiatorname)
|
||||
{
|
||||
struct se_node_acl *acl;
|
||||
u32 queue_depth;
|
||||
|
||||
acl = kzalloc(max(sizeof(*acl), tpg->se_tpg_tfo->node_acl_size),
|
||||
GFP_KERNEL);
|
||||
@@ -193,24 +202,20 @@ static struct se_node_acl *target_alloc_node_acl(struct se_portal_group *tpg,
|
||||
spin_lock_init(&acl->nacl_sess_lock);
|
||||
mutex_init(&acl->lun_entry_mutex);
|
||||
atomic_set(&acl->acl_pr_ref_count, 0);
|
||||
|
||||
if (tpg->se_tpg_tfo->tpg_get_default_depth)
|
||||
acl->queue_depth = tpg->se_tpg_tfo->tpg_get_default_depth(tpg);
|
||||
queue_depth = tpg->se_tpg_tfo->tpg_get_default_depth(tpg);
|
||||
else
|
||||
acl->queue_depth = 1;
|
||||
queue_depth = 1;
|
||||
target_set_nacl_queue_depth(tpg, acl, queue_depth);
|
||||
|
||||
snprintf(acl->initiatorname, TRANSPORT_IQN_LEN, "%s", initiatorname);
|
||||
acl->se_tpg = tpg;
|
||||
acl->acl_index = scsi_get_new_index(SCSI_AUTH_INTR_INDEX);
|
||||
|
||||
tpg->se_tpg_tfo->set_default_node_attributes(acl);
|
||||
|
||||
if (core_set_queue_depth_for_node(tpg, acl) < 0)
|
||||
goto out_free_acl;
|
||||
|
||||
return acl;
|
||||
|
||||
out_free_acl:
|
||||
kfree(acl);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static void target_add_node_acl(struct se_node_acl *acl)
|
||||
@@ -219,7 +224,6 @@ static void target_add_node_acl(struct se_node_acl *acl)
|
||||
|
||||
mutex_lock(&tpg->acl_node_mutex);
|
||||
list_add_tail(&acl->acl_list, &tpg->acl_node_list);
|
||||
tpg->num_node_acls++;
|
||||
mutex_unlock(&tpg->acl_node_mutex);
|
||||
|
||||
pr_debug("%s_TPG[%hu] - Added %s ACL with TCQ Depth: %d for %s"
|
||||
@@ -232,6 +236,25 @@ static void target_add_node_acl(struct se_node_acl *acl)
|
||||
acl->initiatorname);
|
||||
}
|
||||
|
||||
bool target_tpg_has_node_acl(struct se_portal_group *tpg,
|
||||
const char *initiatorname)
|
||||
{
|
||||
struct se_node_acl *acl;
|
||||
bool found = false;
|
||||
|
||||
mutex_lock(&tpg->acl_node_mutex);
|
||||
list_for_each_entry(acl, &tpg->acl_node_list, acl_list) {
|
||||
if (!strcmp(acl->initiatorname, initiatorname)) {
|
||||
found = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
mutex_unlock(&tpg->acl_node_mutex);
|
||||
|
||||
return found;
|
||||
}
|
||||
EXPORT_SYMBOL(target_tpg_has_node_acl);
|
||||
|
||||
struct se_node_acl *core_tpg_check_initiator_node_acl(
|
||||
struct se_portal_group *tpg,
|
||||
unsigned char *initiatorname)
|
||||
@@ -248,6 +271,15 @@ struct se_node_acl *core_tpg_check_initiator_node_acl(
|
||||
acl = target_alloc_node_acl(tpg, initiatorname);
|
||||
if (!acl)
|
||||
return NULL;
|
||||
/*
|
||||
* When allocating a dynamically generated node_acl, go ahead
|
||||
* and take the extra kref now before returning to the fabric
|
||||
* driver caller.
|
||||
*
|
||||
* Note this reference will be released at session shutdown
|
||||
* time within transport_free_session() code.
|
||||
*/
|
||||
kref_get(&acl->acl_kref);
|
||||
acl->dynamic_node_acl = 1;
|
||||
|
||||
/*
|
||||
@@ -318,7 +350,6 @@ void core_tpg_del_initiator_node_acl(struct se_node_acl *acl)
|
||||
acl->dynamic_node_acl = 0;
|
||||
}
|
||||
list_del(&acl->acl_list);
|
||||
tpg->num_node_acls--;
|
||||
mutex_unlock(&tpg->acl_node_mutex);
|
||||
|
||||
spin_lock_irqsave(&acl->nacl_sess_lock, flags);
|
||||
@@ -329,7 +360,8 @@ void core_tpg_del_initiator_node_acl(struct se_node_acl *acl)
|
||||
if (sess->sess_tearing_down != 0)
|
||||
continue;
|
||||
|
||||
target_get_session(sess);
|
||||
if (!target_get_session(sess))
|
||||
continue;
|
||||
list_move(&sess->sess_acl_list, &sess_list);
|
||||
}
|
||||
spin_unlock_irqrestore(&acl->nacl_sess_lock, flags);
|
||||
@@ -366,108 +398,52 @@ void core_tpg_del_initiator_node_acl(struct se_node_acl *acl)
|
||||
*
|
||||
*/
|
||||
int core_tpg_set_initiator_node_queue_depth(
|
||||
struct se_portal_group *tpg,
|
||||
unsigned char *initiatorname,
|
||||
u32 queue_depth,
|
||||
int force)
|
||||
struct se_node_acl *acl,
|
||||
u32 queue_depth)
|
||||
{
|
||||
struct se_session *sess, *init_sess = NULL;
|
||||
struct se_node_acl *acl;
|
||||
LIST_HEAD(sess_list);
|
||||
struct se_portal_group *tpg = acl->se_tpg;
|
||||
struct se_session *sess, *sess_tmp;
|
||||
unsigned long flags;
|
||||
int dynamic_acl = 0;
|
||||
|
||||
mutex_lock(&tpg->acl_node_mutex);
|
||||
acl = __core_tpg_get_initiator_node_acl(tpg, initiatorname);
|
||||
if (!acl) {
|
||||
pr_err("Access Control List entry for %s Initiator"
|
||||
" Node %s does not exists for TPG %hu, ignoring"
|
||||
" request.\n", tpg->se_tpg_tfo->get_fabric_name(),
|
||||
initiatorname, tpg->se_tpg_tfo->tpg_get_tag(tpg));
|
||||
mutex_unlock(&tpg->acl_node_mutex);
|
||||
return -ENODEV;
|
||||
}
|
||||
if (acl->dynamic_node_acl) {
|
||||
acl->dynamic_node_acl = 0;
|
||||
dynamic_acl = 1;
|
||||
}
|
||||
mutex_unlock(&tpg->acl_node_mutex);
|
||||
|
||||
spin_lock_irqsave(&tpg->session_lock, flags);
|
||||
list_for_each_entry(sess, &tpg->tpg_sess_list, sess_list) {
|
||||
if (sess->se_node_acl != acl)
|
||||
continue;
|
||||
|
||||
if (!force) {
|
||||
pr_err("Unable to change queue depth for %s"
|
||||
" Initiator Node: %s while session is"
|
||||
" operational. To forcefully change the queue"
|
||||
" depth and force session reinstatement"
|
||||
" use the \"force=1\" parameter.\n",
|
||||
tpg->se_tpg_tfo->get_fabric_name(), initiatorname);
|
||||
spin_unlock_irqrestore(&tpg->session_lock, flags);
|
||||
|
||||
mutex_lock(&tpg->acl_node_mutex);
|
||||
if (dynamic_acl)
|
||||
acl->dynamic_node_acl = 1;
|
||||
mutex_unlock(&tpg->acl_node_mutex);
|
||||
return -EEXIST;
|
||||
}
|
||||
/*
|
||||
* Determine if the session needs to be closed by our context.
|
||||
*/
|
||||
if (!tpg->se_tpg_tfo->shutdown_session(sess))
|
||||
continue;
|
||||
|
||||
init_sess = sess;
|
||||
break;
|
||||
}
|
||||
int rc;
|
||||
|
||||
/*
|
||||
* User has requested to change the queue depth for a Initiator Node.
|
||||
* Change the value in the Node's struct se_node_acl, and call
|
||||
* core_set_queue_depth_for_node() to add the requested queue depth.
|
||||
*
|
||||
* Finally call tpg->se_tpg_tfo->close_session() to force session
|
||||
* reinstatement to occur if there is an active session for the
|
||||
* $FABRIC_MOD Initiator Node in question.
|
||||
* target_set_nacl_queue_depth() to set the new queue depth.
|
||||
*/
|
||||
acl->queue_depth = queue_depth;
|
||||
target_set_nacl_queue_depth(tpg, acl, queue_depth);
|
||||
|
||||
spin_lock_irqsave(&acl->nacl_sess_lock, flags);
|
||||
list_for_each_entry_safe(sess, sess_tmp, &acl->acl_sess_list,
|
||||
sess_acl_list) {
|
||||
if (sess->sess_tearing_down != 0)
|
||||
continue;
|
||||
if (!target_get_session(sess))
|
||||
continue;
|
||||
spin_unlock_irqrestore(&acl->nacl_sess_lock, flags);
|
||||
|
||||
if (core_set_queue_depth_for_node(tpg, acl) < 0) {
|
||||
spin_unlock_irqrestore(&tpg->session_lock, flags);
|
||||
/*
|
||||
* Force session reinstatement if
|
||||
* core_set_queue_depth_for_node() failed, because we assume
|
||||
* the $FABRIC_MOD has already the set session reinstatement
|
||||
* bit from tpg->se_tpg_tfo->shutdown_session() called above.
|
||||
* Finally call tpg->se_tpg_tfo->close_session() to force session
|
||||
* reinstatement to occur if there is an active session for the
|
||||
* $FABRIC_MOD Initiator Node in question.
|
||||
*/
|
||||
if (init_sess)
|
||||
tpg->se_tpg_tfo->close_session(init_sess);
|
||||
|
||||
mutex_lock(&tpg->acl_node_mutex);
|
||||
if (dynamic_acl)
|
||||
acl->dynamic_node_acl = 1;
|
||||
mutex_unlock(&tpg->acl_node_mutex);
|
||||
return -EINVAL;
|
||||
rc = tpg->se_tpg_tfo->shutdown_session(sess);
|
||||
target_put_session(sess);
|
||||
if (!rc) {
|
||||
spin_lock_irqsave(&acl->nacl_sess_lock, flags);
|
||||
continue;
|
||||
}
|
||||
target_put_session(sess);
|
||||
spin_lock_irqsave(&acl->nacl_sess_lock, flags);
|
||||
}
|
||||
spin_unlock_irqrestore(&tpg->session_lock, flags);
|
||||
/*
|
||||
* If the $FABRIC_MOD session for the Initiator Node ACL exists,
|
||||
* forcefully shutdown the $FABRIC_MOD session/nexus.
|
||||
*/
|
||||
if (init_sess)
|
||||
tpg->se_tpg_tfo->close_session(init_sess);
|
||||
spin_unlock_irqrestore(&acl->nacl_sess_lock, flags);
|
||||
|
||||
pr_debug("Successfully changed queue depth to: %d for Initiator"
|
||||
" Node: %s on %s Target Portal Group: %u\n", queue_depth,
|
||||
initiatorname, tpg->se_tpg_tfo->get_fabric_name(),
|
||||
" Node: %s on %s Target Portal Group: %u\n", acl->queue_depth,
|
||||
acl->initiatorname, tpg->se_tpg_tfo->get_fabric_name(),
|
||||
tpg->se_tpg_tfo->tpg_get_tag(tpg));
|
||||
|
||||
mutex_lock(&tpg->acl_node_mutex);
|
||||
if (dynamic_acl)
|
||||
acl->dynamic_node_acl = 1;
|
||||
mutex_unlock(&tpg->acl_node_mutex);
|
||||
|
||||
return 0;
|
||||
}
|
||||
EXPORT_SYMBOL(core_tpg_set_initiator_node_queue_depth);
|
||||
@@ -595,7 +571,6 @@ int core_tpg_deregister(struct se_portal_group *se_tpg)
|
||||
*/
|
||||
list_for_each_entry_safe(nacl, nacl_tmp, &node_list, acl_list) {
|
||||
list_del(&nacl->acl_list);
|
||||
se_tpg->num_node_acls--;
|
||||
|
||||
core_tpg_wait_for_nacl_pr_ref(nacl);
|
||||
core_free_device_list_for_node(nacl, se_tpg);
|
||||
|
@@ -341,7 +341,6 @@ void __transport_register_session(
|
||||
&buf[0], PR_REG_ISID_LEN);
|
||||
se_sess->sess_bin_isid = get_unaligned_be64(&buf[0]);
|
||||
}
|
||||
kref_get(&se_nacl->acl_kref);
|
||||
|
||||
spin_lock_irq(&se_nacl->nacl_sess_lock);
|
||||
/*
|
||||
@@ -384,9 +383,9 @@ static void target_release_session(struct kref *kref)
|
||||
se_tpg->se_tpg_tfo->close_session(se_sess);
|
||||
}
|
||||
|
||||
void target_get_session(struct se_session *se_sess)
|
||||
int target_get_session(struct se_session *se_sess)
|
||||
{
|
||||
kref_get(&se_sess->sess_kref);
|
||||
return kref_get_unless_zero(&se_sess->sess_kref);
|
||||
}
|
||||
EXPORT_SYMBOL(target_get_session);
|
||||
|
||||
@@ -432,6 +431,7 @@ void target_put_nacl(struct se_node_acl *nacl)
|
||||
{
|
||||
kref_put(&nacl->acl_kref, target_complete_nacl);
|
||||
}
|
||||
EXPORT_SYMBOL(target_put_nacl);
|
||||
|
||||
void transport_deregister_session_configfs(struct se_session *se_sess)
|
||||
{
|
||||
@@ -464,6 +464,15 @@ EXPORT_SYMBOL(transport_deregister_session_configfs);
|
||||
|
||||
void transport_free_session(struct se_session *se_sess)
|
||||
{
|
||||
struct se_node_acl *se_nacl = se_sess->se_node_acl;
|
||||
/*
|
||||
* Drop the se_node_acl->nacl_kref obtained from within
|
||||
* core_tpg_get_initiator_node_acl().
|
||||
*/
|
||||
if (se_nacl) {
|
||||
se_sess->se_node_acl = NULL;
|
||||
target_put_nacl(se_nacl);
|
||||
}
|
||||
if (se_sess->sess_cmd_map) {
|
||||
percpu_ida_destroy(&se_sess->sess_tag_pool);
|
||||
kvfree(se_sess->sess_cmd_map);
|
||||
@@ -478,7 +487,7 @@ void transport_deregister_session(struct se_session *se_sess)
|
||||
const struct target_core_fabric_ops *se_tfo;
|
||||
struct se_node_acl *se_nacl;
|
||||
unsigned long flags;
|
||||
bool comp_nacl = true, drop_nacl = false;
|
||||
bool drop_nacl = false;
|
||||
|
||||
if (!se_tpg) {
|
||||
transport_free_session(se_sess);
|
||||
@@ -502,7 +511,6 @@ void transport_deregister_session(struct se_session *se_sess)
|
||||
if (se_nacl && se_nacl->dynamic_node_acl) {
|
||||
if (!se_tfo->tpg_check_demo_mode_cache(se_tpg)) {
|
||||
list_del(&se_nacl->acl_list);
|
||||
se_tpg->num_node_acls--;
|
||||
drop_nacl = true;
|
||||
}
|
||||
}
|
||||
@@ -511,18 +519,16 @@ void transport_deregister_session(struct se_session *se_sess)
|
||||
if (drop_nacl) {
|
||||
core_tpg_wait_for_nacl_pr_ref(se_nacl);
|
||||
core_free_device_list_for_node(se_nacl, se_tpg);
|
||||
se_sess->se_node_acl = NULL;
|
||||
kfree(se_nacl);
|
||||
comp_nacl = false;
|
||||
}
|
||||
pr_debug("TARGET_CORE[%s]: Deregistered fabric_sess\n",
|
||||
se_tpg->se_tpg_tfo->get_fabric_name());
|
||||
/*
|
||||
* If last kref is dropping now for an explicit NodeACL, awake sleeping
|
||||
* ->acl_free_comp caller to wakeup configfs se_node_acl->acl_group
|
||||
* removal context.
|
||||
* removal context from within transport_free_session() code.
|
||||
*/
|
||||
if (se_nacl && comp_nacl)
|
||||
target_put_nacl(se_nacl);
|
||||
|
||||
transport_free_session(se_sess);
|
||||
}
|
||||
@@ -715,7 +721,10 @@ void target_complete_cmd(struct se_cmd *cmd, u8 scsi_status)
|
||||
cmd->transport_state |= (CMD_T_COMPLETE | CMD_T_ACTIVE);
|
||||
spin_unlock_irqrestore(&cmd->t_state_lock, flags);
|
||||
|
||||
queue_work(target_completion_wq, &cmd->work);
|
||||
if (cmd->cpuid == -1)
|
||||
queue_work(target_completion_wq, &cmd->work);
|
||||
else
|
||||
queue_work_on(cmd->cpuid, target_completion_wq, &cmd->work);
|
||||
}
|
||||
EXPORT_SYMBOL(target_complete_cmd);
|
||||
|
||||
@@ -1309,7 +1318,7 @@ EXPORT_SYMBOL(target_setup_cmd_from_cdb);
|
||||
|
||||
/*
|
||||
* Used by fabric module frontends to queue tasks directly.
|
||||
* Many only be used from process context only
|
||||
* May only be used from process context.
|
||||
*/
|
||||
int transport_handle_cdb_direct(
|
||||
struct se_cmd *cmd)
|
||||
@@ -1582,7 +1591,7 @@ static void target_complete_tmr_failure(struct work_struct *work)
|
||||
int target_submit_tmr(struct se_cmd *se_cmd, struct se_session *se_sess,
|
||||
unsigned char *sense, u64 unpacked_lun,
|
||||
void *fabric_tmr_ptr, unsigned char tm_type,
|
||||
gfp_t gfp, unsigned int tag, int flags)
|
||||
gfp_t gfp, u64 tag, int flags)
|
||||
{
|
||||
struct se_portal_group *se_tpg;
|
||||
int ret;
|
||||
|
@@ -152,6 +152,7 @@ static struct genl_family tcmu_genl_family = {
|
||||
.maxattr = TCMU_ATTR_MAX,
|
||||
.mcgrps = tcmu_mcgrps,
|
||||
.n_mcgrps = ARRAY_SIZE(tcmu_mcgrps),
|
||||
.netnsok = true,
|
||||
};
|
||||
|
||||
static struct tcmu_cmd *tcmu_alloc_cmd(struct se_cmd *se_cmd)
|
||||
@@ -194,7 +195,7 @@ static struct tcmu_cmd *tcmu_alloc_cmd(struct se_cmd *se_cmd)
|
||||
|
||||
static inline void tcmu_flush_dcache_range(void *vaddr, size_t size)
|
||||
{
|
||||
unsigned long offset = (unsigned long) vaddr & ~PAGE_MASK;
|
||||
unsigned long offset = offset_in_page(vaddr);
|
||||
|
||||
size = round_up(size+offset, PAGE_SIZE);
|
||||
vaddr -= offset;
|
||||
@@ -840,7 +841,7 @@ static int tcmu_netlink_event(enum tcmu_genl_cmd cmd, const char *name, int mino
|
||||
|
||||
genlmsg_end(skb, msg_header);
|
||||
|
||||
ret = genlmsg_multicast(&tcmu_genl_family, skb, 0,
|
||||
ret = genlmsg_multicast_allns(&tcmu_genl_family, skb, 0,
|
||||
TCMU_MCGRP_CONFIG, GFP_KERNEL);
|
||||
|
||||
/* We don't care if no one is listening */
|
||||
@@ -917,8 +918,10 @@ static int tcmu_configure_device(struct se_device *dev)
|
||||
if (ret)
|
||||
goto err_register;
|
||||
|
||||
/* User can set hw_block_size before enable the device */
|
||||
if (dev->dev_attrib.hw_block_size == 0)
|
||||
dev->dev_attrib.hw_block_size = 512;
|
||||
/* Other attributes can be configured in userspace */
|
||||
dev->dev_attrib.hw_block_size = 512;
|
||||
dev->dev_attrib.hw_max_sectors = 128;
|
||||
dev->dev_attrib.hw_queue_depth = 128;
|
||||
|
||||
|
@@ -166,7 +166,6 @@ void ft_aborted_task(struct se_cmd *);
|
||||
*/
|
||||
void ft_recv_req(struct ft_sess *, struct fc_frame *);
|
||||
struct ft_tpg *ft_lport_find_tpg(struct fc_lport *);
|
||||
struct ft_node_acl *ft_acl_get(struct ft_tpg *, struct fc_rport_priv *);
|
||||
|
||||
void ft_recv_write_data(struct ft_cmd *, struct fc_frame *);
|
||||
void ft_dump_cmd(struct ft_cmd *, const char *caller);
|
||||
|
@@ -171,9 +171,31 @@ static ssize_t ft_nacl_node_name_store(struct config_item *item,
|
||||
CONFIGFS_ATTR(ft_nacl_, node_name);
|
||||
CONFIGFS_ATTR(ft_nacl_, port_name);
|
||||
|
||||
static ssize_t ft_nacl_tag_show(struct config_item *item,
|
||||
char *page)
|
||||
{
|
||||
return snprintf(page, PAGE_SIZE, "%s", acl_to_nacl(item)->acl_tag);
|
||||
}
|
||||
|
||||
static ssize_t ft_nacl_tag_store(struct config_item *item,
|
||||
const char *page, size_t count)
|
||||
{
|
||||
struct se_node_acl *se_nacl = acl_to_nacl(item);
|
||||
int ret;
|
||||
|
||||
ret = core_tpg_set_initiator_node_tag(se_nacl->se_tpg, se_nacl, page);
|
||||
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
return count;
|
||||
}
|
||||
|
||||
CONFIGFS_ATTR(ft_nacl_, tag);
|
||||
|
||||
static struct configfs_attribute *ft_nacl_base_attrs[] = {
|
||||
&ft_nacl_attr_port_name,
|
||||
&ft_nacl_attr_node_name,
|
||||
&ft_nacl_attr_tag,
|
||||
NULL,
|
||||
};
|
||||
|
||||
@@ -198,31 +220,6 @@ static int ft_init_nodeacl(struct se_node_acl *nacl, const char *name)
|
||||
return 0;
|
||||
}
|
||||
|
||||
struct ft_node_acl *ft_acl_get(struct ft_tpg *tpg, struct fc_rport_priv *rdata)
|
||||
{
|
||||
struct ft_node_acl *found = NULL;
|
||||
struct ft_node_acl *acl;
|
||||
struct se_portal_group *se_tpg = &tpg->se_tpg;
|
||||
struct se_node_acl *se_acl;
|
||||
|
||||
mutex_lock(&se_tpg->acl_node_mutex);
|
||||
list_for_each_entry(se_acl, &se_tpg->acl_node_list, acl_list) {
|
||||
acl = container_of(se_acl, struct ft_node_acl, se_node_acl);
|
||||
pr_debug("acl %p port_name %llx\n",
|
||||
acl, (unsigned long long)acl->node_auth.port_name);
|
||||
if (acl->node_auth.port_name == rdata->ids.port_name ||
|
||||
acl->node_auth.node_name == rdata->ids.node_name) {
|
||||
pr_debug("acl %p port_name %llx matched\n", acl,
|
||||
(unsigned long long)rdata->ids.port_name);
|
||||
found = acl;
|
||||
/* XXX need to hold onto ACL */
|
||||
break;
|
||||
}
|
||||
}
|
||||
mutex_unlock(&se_tpg->acl_node_mutex);
|
||||
return found;
|
||||
}
|
||||
|
||||
/*
|
||||
* local_port port_group (tpg) ops.
|
||||
*/
|
||||
|
@@ -154,9 +154,9 @@ int ft_queue_data_in(struct se_cmd *se_cmd)
|
||||
BUG_ON(!page);
|
||||
from = kmap_atomic(page + (mem_off >> PAGE_SHIFT));
|
||||
page_addr = from;
|
||||
from += mem_off & ~PAGE_MASK;
|
||||
from += offset_in_page(mem_off);
|
||||
tlen = min(tlen, (size_t)(PAGE_SIZE -
|
||||
(mem_off & ~PAGE_MASK)));
|
||||
offset_in_page(mem_off)));
|
||||
memcpy(to, from, tlen);
|
||||
kunmap_atomic(page_addr);
|
||||
to += tlen;
|
||||
@@ -314,9 +314,9 @@ void ft_recv_write_data(struct ft_cmd *cmd, struct fc_frame *fp)
|
||||
|
||||
to = kmap_atomic(page + (mem_off >> PAGE_SHIFT));
|
||||
page_addr = to;
|
||||
to += mem_off & ~PAGE_MASK;
|
||||
to += offset_in_page(mem_off);
|
||||
tlen = min(tlen, (size_t)(PAGE_SIZE -
|
||||
(mem_off & ~PAGE_MASK)));
|
||||
offset_in_page(mem_off)));
|
||||
memcpy(to, from, tlen);
|
||||
kunmap_atomic(page_addr);
|
||||
|
||||
|
@@ -191,10 +191,15 @@ out:
|
||||
* Caller holds ft_lport_lock.
|
||||
*/
|
||||
static struct ft_sess *ft_sess_create(struct ft_tport *tport, u32 port_id,
|
||||
struct ft_node_acl *acl)
|
||||
struct fc_rport_priv *rdata)
|
||||
{
|
||||
struct se_portal_group *se_tpg = &tport->tpg->se_tpg;
|
||||
struct se_node_acl *se_acl;
|
||||
struct ft_sess *sess;
|
||||
struct hlist_head *head;
|
||||
unsigned char initiatorname[TRANSPORT_IQN_LEN];
|
||||
|
||||
ft_format_wwn(&initiatorname[0], TRANSPORT_IQN_LEN, rdata->ids.port_name);
|
||||
|
||||
head = &tport->hash[ft_sess_hash(port_id)];
|
||||
hlist_for_each_entry_rcu(sess, head, hash)
|
||||
@@ -212,7 +217,14 @@ static struct ft_sess *ft_sess_create(struct ft_tport *tport, u32 port_id,
|
||||
kfree(sess);
|
||||
return NULL;
|
||||
}
|
||||
sess->se_sess->se_node_acl = &acl->se_node_acl;
|
||||
|
||||
se_acl = core_tpg_get_initiator_node_acl(se_tpg, &initiatorname[0]);
|
||||
if (!se_acl) {
|
||||
transport_free_session(sess->se_sess);
|
||||
kfree(sess);
|
||||
return NULL;
|
||||
}
|
||||
sess->se_sess->se_node_acl = se_acl;
|
||||
sess->tport = tport;
|
||||
sess->port_id = port_id;
|
||||
kref_init(&sess->kref); /* ref for table entry */
|
||||
@@ -221,7 +233,7 @@ static struct ft_sess *ft_sess_create(struct ft_tport *tport, u32 port_id,
|
||||
|
||||
pr_debug("port_id %x sess %p\n", port_id, sess);
|
||||
|
||||
transport_register_session(&tport->tpg->se_tpg, &acl->se_node_acl,
|
||||
transport_register_session(&tport->tpg->se_tpg, se_acl,
|
||||
sess->se_sess, sess);
|
||||
return sess;
|
||||
}
|
||||
@@ -260,6 +272,14 @@ static struct ft_sess *ft_sess_delete(struct ft_tport *tport, u32 port_id)
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static void ft_close_sess(struct ft_sess *sess)
|
||||
{
|
||||
transport_deregister_session_configfs(sess->se_sess);
|
||||
target_sess_cmd_list_set_waiting(sess->se_sess);
|
||||
target_wait_for_sess_cmds(sess->se_sess);
|
||||
ft_sess_put(sess);
|
||||
}
|
||||
|
||||
/*
|
||||
* Delete all sessions from tport.
|
||||
* Caller holds ft_lport_lock.
|
||||
@@ -273,8 +293,7 @@ static void ft_sess_delete_all(struct ft_tport *tport)
|
||||
head < &tport->hash[FT_SESS_HASH_SIZE]; head++) {
|
||||
hlist_for_each_entry_rcu(sess, head, hash) {
|
||||
ft_sess_unhash(sess);
|
||||
transport_deregister_session_configfs(sess->se_sess);
|
||||
ft_sess_put(sess); /* release from table */
|
||||
ft_close_sess(sess); /* release from table */
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -313,8 +332,7 @@ void ft_sess_close(struct se_session *se_sess)
|
||||
pr_debug("port_id %x\n", port_id);
|
||||
ft_sess_unhash(sess);
|
||||
mutex_unlock(&ft_lport_lock);
|
||||
transport_deregister_session_configfs(se_sess);
|
||||
ft_sess_put(sess);
|
||||
ft_close_sess(sess);
|
||||
/* XXX Send LOGO or PRLO */
|
||||
synchronize_rcu(); /* let transport deregister happen */
|
||||
}
|
||||
@@ -343,17 +361,12 @@ static int ft_prli_locked(struct fc_rport_priv *rdata, u32 spp_len,
|
||||
{
|
||||
struct ft_tport *tport;
|
||||
struct ft_sess *sess;
|
||||
struct ft_node_acl *acl;
|
||||
u32 fcp_parm;
|
||||
|
||||
tport = ft_tport_get(rdata->local_port);
|
||||
if (!tport)
|
||||
goto not_target; /* not a target for this local port */
|
||||
|
||||
acl = ft_acl_get(tport->tpg, rdata);
|
||||
if (!acl)
|
||||
goto not_target; /* no target for this remote */
|
||||
|
||||
if (!rspp)
|
||||
goto fill;
|
||||
|
||||
@@ -375,7 +388,7 @@ static int ft_prli_locked(struct fc_rport_priv *rdata, u32 spp_len,
|
||||
spp->spp_flags |= FC_SPP_EST_IMG_PAIR;
|
||||
if (!(fcp_parm & FCP_SPPF_INIT_FCN))
|
||||
return FC_SPP_RESP_CONF;
|
||||
sess = ft_sess_create(tport, rdata->ids.port_id, acl);
|
||||
sess = ft_sess_create(tport, rdata->ids.port_id, rdata);
|
||||
if (!sess)
|
||||
return FC_SPP_RESP_RES;
|
||||
if (!sess->params)
|
||||
@@ -460,8 +473,7 @@ static void ft_prlo(struct fc_rport_priv *rdata)
|
||||
return;
|
||||
}
|
||||
mutex_unlock(&ft_lport_lock);
|
||||
transport_deregister_session_configfs(sess->se_sess);
|
||||
ft_sess_put(sess); /* release from table */
|
||||
ft_close_sess(sess); /* release from table */
|
||||
rdata->prli_count--;
|
||||
/* XXX TBD - clearing actions. unit attn, see 4.10 */
|
||||
}
|
||||
|
Reference in New Issue
Block a user