Skip to content

Commit

Permalink
Merge branch 'for-next' of git://git.kernel.org/pub/scm/linux/kernel/…
Browse files Browse the repository at this point in the history
…git/nab/target-pending

Pull scsi target updates from Nicholas Bellinger:
 "The highlights in this series include:

   - Improve sg_table lookup scalability in RAMDISK_MCP (martin)

   - Add device attribute to expose config name for INQUIRY model (tregaron)

   - Convert tcm_vhost to use lock-less list for cmd completion (asias)

   - Add tcm_vhost support for multiple target's per endpoint (asias)

   - Add tcm_vhost support for multiple queues per vhost (asias)

   - Add missing mapped_lun bounds checking during make_mappedlun setup
     in generic fabric configfs code (jan engelhardt + nab)

   - Enforce individual iscsi-target network portal export once per
     TargetName endpoint (grover + nab)

   - Add WRITE_SAME w/ UNMAP=0 emulation to FILEIO backend (nab)

  Things have been mostly quiet this round, with majority of the work
  being done on the iser-target WIP driver + associated iscsi-target
  refactoring patches currently in flight for v3.10 code.

  At this point there is one patch series left outstanding from Asias to
  add support for UNMAP + WRITE_SAME w/ UNMAP=1 to FILEIO awaiting
  feedback from hch & Co, that will likely be included in a post
  v3.9-rc1 PULL request if there are no objections.

  Also, there is a regression bug recently reported off-list that seems
  to be effecting v3.5 and v3.6 kernels with MSFT iSCSI initiators that
  is still being tracked down.  No word if this effects >= v3.7 just
  yet, but if so there will likely another PULL request coming your
  way.."

* 'for-next' of git://git.kernel.org/pub/scm/linux/kernel/git/nab/target-pending: (26 commits)
  target: Rename spc_get_write_same_sectors -> sbc_get_write_same_sectors
  target/file: Add WRITE_SAME w/ UNMAP=0 emulation support
  iscsi-target: Enforce individual network portal export once per TargetName
  iscsi-target: Refactor iscsit_get_np sockaddr matching into iscsit_check_np_match
  target: Add missing mapped_lun bounds checking during make_mappedlun setup
  target: Fix lookup of dynamic NodeACLs during cached demo-mode operation
  target: Fix parameter list length checking in MODE SELECT
  target: Fix error checking for UNMAP commands
  target: Fix sense data for out-of-bounds IO operations
  target_core_rd: break out unterminated loop during copy
  tcm_vhost: Multi-queue support
  tcm_vhost: Multi-target support
  target: Add device attribute to expose config_item_name for INQUIRY model
  target: don't truncate the fail intr address
  target: don't always say "ipv6" as address type
  target/iblock: Use backend REQ_FLUSH hint for WriteCacheEnabled status
  iscsi-target: make some temporary buffers larger
  tcm_vhost: Optimize gup in vhost_scsi_map_to_sgl
  tcm_vhost: Use iov_num_pages to calculate sgl_count
  tcm_vhost: Introduce iov_num_pages
  ...
  • Loading branch information
torvalds committed Feb 26, 2013
2 parents 70a3a06 + 972b29c commit ecc88ef
Show file tree
Hide file tree
Showing 21 changed files with 563 additions and 229 deletions.
65 changes: 39 additions & 26 deletions drivers/target/iscsi/iscsi_target.c
Original file line number Diff line number Diff line change
Expand Up @@ -264,16 +264,50 @@ int iscsit_deaccess_np(struct iscsi_np *np, struct iscsi_portal_group *tpg)
return 0;
}

static struct iscsi_np *iscsit_get_np(
bool iscsit_check_np_match(
struct __kernel_sockaddr_storage *sockaddr,
struct iscsi_np *np,
int network_transport)
{
struct sockaddr_in *sock_in, *sock_in_e;
struct sockaddr_in6 *sock_in6, *sock_in6_e;
struct iscsi_np *np;
int ip_match = 0;
bool ip_match = false;
u16 port;

if (sockaddr->ss_family == AF_INET6) {
sock_in6 = (struct sockaddr_in6 *)sockaddr;
sock_in6_e = (struct sockaddr_in6 *)&np->np_sockaddr;

if (!memcmp(&sock_in6->sin6_addr.in6_u,
&sock_in6_e->sin6_addr.in6_u,
sizeof(struct in6_addr)))
ip_match = true;

port = ntohs(sock_in6->sin6_port);
} else {
sock_in = (struct sockaddr_in *)sockaddr;
sock_in_e = (struct sockaddr_in *)&np->np_sockaddr;

if (sock_in->sin_addr.s_addr == sock_in_e->sin_addr.s_addr)
ip_match = true;

port = ntohs(sock_in->sin_port);
}

if ((ip_match == true) && (np->np_port == port) &&
(np->np_network_transport == network_transport))
return true;

return false;
}

static struct iscsi_np *iscsit_get_np(
struct __kernel_sockaddr_storage *sockaddr,
int network_transport)
{
struct iscsi_np *np;
bool match;

spin_lock_bh(&np_lock);
list_for_each_entry(np, &g_np_list, np_list) {
spin_lock(&np->np_thread_lock);
Expand All @@ -282,29 +316,8 @@ static struct iscsi_np *iscsit_get_np(
continue;
}

if (sockaddr->ss_family == AF_INET6) {
sock_in6 = (struct sockaddr_in6 *)sockaddr;
sock_in6_e = (struct sockaddr_in6 *)&np->np_sockaddr;

if (!memcmp(&sock_in6->sin6_addr.in6_u,
&sock_in6_e->sin6_addr.in6_u,
sizeof(struct in6_addr)))
ip_match = 1;

port = ntohs(sock_in6->sin6_port);
} else {
sock_in = (struct sockaddr_in *)sockaddr;
sock_in_e = (struct sockaddr_in *)&np->np_sockaddr;

if (sock_in->sin_addr.s_addr ==
sock_in_e->sin_addr.s_addr)
ip_match = 1;

port = ntohs(sock_in->sin_port);
}

if ((ip_match == 1) && (np->np_port == port) &&
(np->np_network_transport == network_transport)) {
match = iscsit_check_np_match(sockaddr, np, network_transport);
if (match == true) {
/*
* Increment the np_exports reference count now to
* prevent iscsit_del_np() below from being called
Expand Down
2 changes: 2 additions & 0 deletions drivers/target/iscsi/iscsi_target.h
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,8 @@ extern struct iscsi_tiqn *iscsit_add_tiqn(unsigned char *);
extern void iscsit_del_tiqn(struct iscsi_tiqn *);
extern int iscsit_access_np(struct iscsi_np *, struct iscsi_portal_group *);
extern int iscsit_deaccess_np(struct iscsi_np *, struct iscsi_portal_group *);
extern bool iscsit_check_np_match(struct __kernel_sockaddr_storage *,
struct iscsi_np *, int);
extern struct iscsi_np *iscsit_add_np(struct __kernel_sockaddr_storage *,
char *, int);
extern int iscsit_reset_np_thread(struct iscsi_np *, struct iscsi_tpg_np *,
Expand Down
8 changes: 4 additions & 4 deletions drivers/target/iscsi/iscsi_target_parameters.c
Original file line number Diff line number Diff line change
Expand Up @@ -1095,11 +1095,11 @@ static int iscsi_check_acceptor_state(struct iscsi_param *param, char *value,
SET_PSTATE_REPLY_OPTIONAL(param);
}
} else if (IS_TYPE_NUMBER(param)) {
char *tmpptr, buf[10];
char *tmpptr, buf[11];
u32 acceptor_value = simple_strtoul(param->value, &tmpptr, 0);
u32 proposer_value = simple_strtoul(value, &tmpptr, 0);

memset(buf, 0, 10);
memset(buf, 0, sizeof(buf));

if (!strcmp(param->name, MAXCONNECTIONS) ||
!strcmp(param->name, MAXBURSTLENGTH) ||
Expand Down Expand Up @@ -1503,8 +1503,8 @@ static int iscsi_enforce_integrity_rules(
FirstBurstLength = simple_strtoul(param->value,
&tmpptr, 0);
if (FirstBurstLength > MaxBurstLength) {
char tmpbuf[10];
memset(tmpbuf, 0, 10);
char tmpbuf[11];
memset(tmpbuf, 0, sizeof(tmpbuf));
sprintf(tmpbuf, "%u", MaxBurstLength);
if (iscsi_update_param_value(param, tmpbuf))
return -1;
Expand Down
25 changes: 15 additions & 10 deletions drivers/target/iscsi/iscsi_target_stat.c
Original file line number Diff line number Diff line change
Expand Up @@ -410,14 +410,16 @@ static ssize_t iscsi_stat_tgt_attr_show_attr_fail_intr_addr_type(
struct iscsi_tiqn *tiqn = container_of(igrps,
struct iscsi_tiqn, tiqn_stat_grps);
struct iscsi_login_stats *lstat = &tiqn->login_stats;
unsigned char buf[8];
int ret;

spin_lock(&lstat->lock);
snprintf(buf, 8, "%s", (lstat->last_intr_fail_ip_addr != NULL) ?
"ipv6" : "ipv4");
if (lstat->last_intr_fail_ip_family == AF_INET6)
ret = snprintf(page, PAGE_SIZE, "ipv6\n");
else
ret = snprintf(page, PAGE_SIZE, "ipv4\n");
spin_unlock(&lstat->lock);

return snprintf(page, PAGE_SIZE, "%s\n", buf);
return ret;
}
ISCSI_STAT_TGT_ATTR_RO(fail_intr_addr_type);

Expand All @@ -427,16 +429,19 @@ static ssize_t iscsi_stat_tgt_attr_show_attr_fail_intr_addr(
struct iscsi_tiqn *tiqn = container_of(igrps,
struct iscsi_tiqn, tiqn_stat_grps);
struct iscsi_login_stats *lstat = &tiqn->login_stats;
unsigned char buf[32];
int ret;

spin_lock(&lstat->lock);
if (lstat->last_intr_fail_ip_family == AF_INET6)
snprintf(buf, 32, "[%s]", lstat->last_intr_fail_ip_addr);
else
snprintf(buf, 32, "%s", lstat->last_intr_fail_ip_addr);
if (lstat->last_intr_fail_ip_family == AF_INET6) {
ret = snprintf(page, PAGE_SIZE, "[%s]\n",
lstat->last_intr_fail_ip_addr);
} else {
ret = snprintf(page, PAGE_SIZE, "%s\n",
lstat->last_intr_fail_ip_addr);
}
spin_unlock(&lstat->lock);

return snprintf(page, PAGE_SIZE, "%s\n", buf);
return ret;
}
ISCSI_STAT_TGT_ATTR_RO(fail_intr_addr);

Expand Down
39 changes: 39 additions & 0 deletions drivers/target/iscsi/iscsi_target_tpg.c
Original file line number Diff line number Diff line change
Expand Up @@ -422,6 +422,35 @@ struct iscsi_tpg_np *iscsit_tpg_locate_child_np(
return NULL;
}

static bool iscsit_tpg_check_network_portal(
struct iscsi_tiqn *tiqn,
struct __kernel_sockaddr_storage *sockaddr,
int network_transport)
{
struct iscsi_portal_group *tpg;
struct iscsi_tpg_np *tpg_np;
struct iscsi_np *np;
bool match = false;

spin_lock(&tiqn->tiqn_tpg_lock);
list_for_each_entry(tpg, &tiqn->tiqn_tpg_list, tpg_list) {

spin_lock(&tpg->tpg_np_lock);
list_for_each_entry(tpg_np, &tpg->tpg_gnp_list, tpg_np_list) {
np = tpg_np->tpg_np;

match = iscsit_check_np_match(sockaddr, np,
network_transport);
if (match == true)
break;
}
spin_unlock(&tpg->tpg_np_lock);
}
spin_unlock(&tiqn->tiqn_tpg_lock);

return match;
}

struct iscsi_tpg_np *iscsit_tpg_add_network_portal(
struct iscsi_portal_group *tpg,
struct __kernel_sockaddr_storage *sockaddr,
Expand All @@ -432,6 +461,16 @@ struct iscsi_tpg_np *iscsit_tpg_add_network_portal(
struct iscsi_np *np;
struct iscsi_tpg_np *tpg_np;

if (!tpg_np_parent) {
if (iscsit_tpg_check_network_portal(tpg->tpg_tiqn, sockaddr,
network_transport) == true) {
pr_err("Network Portal: %s already exists on a"
" different TPG on %s\n", ip_str,
tpg->tpg_tiqn->tiqn);
return ERR_PTR(-EEXIST);
}
}

tpg_np = kzalloc(sizeof(struct iscsi_tpg_np), GFP_KERNEL);
if (!tpg_np) {
pr_err("Unable to allocate memory for"
Expand Down
4 changes: 4 additions & 0 deletions drivers/target/target_core_configfs.c
Original file line number Diff line number Diff line change
Expand Up @@ -609,6 +609,9 @@ static struct target_core_dev_attrib_attribute \
__CONFIGFS_EATTR_RO(_name, \
target_core_dev_show_attr_##_name);

DEF_DEV_ATTRIB(emulate_model_alias);
SE_DEV_ATTR(emulate_model_alias, S_IRUGO | S_IWUSR);

DEF_DEV_ATTRIB(emulate_dpo);
SE_DEV_ATTR(emulate_dpo, S_IRUGO | S_IWUSR);

Expand Down Expand Up @@ -681,6 +684,7 @@ SE_DEV_ATTR(max_write_same_len, S_IRUGO | S_IWUSR);
CONFIGFS_EATTR_OPS(target_core_dev_attrib, se_dev_attrib, da_group);

static struct configfs_attribute *target_core_dev_attrib_attrs[] = {
&target_core_dev_attrib_emulate_model_alias.attr,
&target_core_dev_attrib_emulate_dpo.attr,
&target_core_dev_attrib_emulate_fua_write.attr,
&target_core_dev_attrib_emulate_fua_read.attr,
Expand Down
58 changes: 49 additions & 9 deletions drivers/target/target_core_device.c
Original file line number Diff line number Diff line change
Expand Up @@ -713,6 +713,44 @@ int se_dev_set_max_write_same_len(
return 0;
}

static void dev_set_t10_wwn_model_alias(struct se_device *dev)
{
const char *configname;

configname = config_item_name(&dev->dev_group.cg_item);
if (strlen(configname) >= 16) {
pr_warn("dev[%p]: Backstore name '%s' is too long for "
"INQUIRY_MODEL, truncating to 16 bytes\n", dev,
configname);
}
snprintf(&dev->t10_wwn.model[0], 16, "%s", configname);
}

int se_dev_set_emulate_model_alias(struct se_device *dev, int flag)
{
if (dev->export_count) {
pr_err("dev[%p]: Unable to change model alias"
" while export_count is %d\n",
dev, dev->export_count);
return -EINVAL;
}

if (flag != 0 && flag != 1) {
pr_err("Illegal value %d\n", flag);
return -EINVAL;
}

if (flag) {
dev_set_t10_wwn_model_alias(dev);
} else {
strncpy(&dev->t10_wwn.model[0],
dev->transport->inquiry_prod, 16);
}
dev->dev_attrib.emulate_model_alias = flag;

return 0;
}

int se_dev_set_emulate_dpo(struct se_device *dev, int flag)
{
if (flag != 0 && flag != 1) {
Expand Down Expand Up @@ -772,6 +810,12 @@ int se_dev_set_emulate_write_cache(struct se_device *dev, int flag)
pr_err("emulate_write_cache not supported for pSCSI\n");
return -EINVAL;
}
if (dev->transport->get_write_cache) {
pr_warn("emulate_write_cache cannot be changed when underlying"
" HW reports WriteCacheEnabled, ignoring request\n");
return 0;
}

dev->dev_attrib.emulate_write_cache = flag;
pr_debug("dev[%p]: SE Device WRITE_CACHE_EMULATION flag: %d\n",
dev, dev->dev_attrib.emulate_write_cache);
Expand Down Expand Up @@ -1182,24 +1226,18 @@ static struct se_lun *core_dev_get_lun(struct se_portal_group *tpg, u32 unpacked

struct se_lun_acl *core_dev_init_initiator_node_lun_acl(
struct se_portal_group *tpg,
struct se_node_acl *nacl,
u32 mapped_lun,
char *initiatorname,
int *ret)
{
struct se_lun_acl *lacl;
struct se_node_acl *nacl;

if (strlen(initiatorname) >= TRANSPORT_IQN_LEN) {
if (strlen(nacl->initiatorname) >= TRANSPORT_IQN_LEN) {
pr_err("%s InitiatorName exceeds maximum size.\n",
tpg->se_tpg_tfo->get_fabric_name());
*ret = -EOVERFLOW;
return NULL;
}
nacl = core_tpg_get_initiator_node_acl(tpg, initiatorname);
if (!nacl) {
*ret = -EINVAL;
return NULL;
}
lacl = kzalloc(sizeof(struct se_lun_acl), GFP_KERNEL);
if (!lacl) {
pr_err("Unable to allocate memory for struct se_lun_acl.\n");
Expand All @@ -1210,7 +1248,8 @@ struct se_lun_acl *core_dev_init_initiator_node_lun_acl(
INIT_LIST_HEAD(&lacl->lacl_list);
lacl->mapped_lun = mapped_lun;
lacl->se_lun_nacl = nacl;
snprintf(lacl->initiatorname, TRANSPORT_IQN_LEN, "%s", initiatorname);
snprintf(lacl->initiatorname, TRANSPORT_IQN_LEN, "%s",
nacl->initiatorname);

return lacl;
}
Expand Down Expand Up @@ -1390,6 +1429,7 @@ struct se_device *target_alloc_device(struct se_hba *hba, const char *name)
dev->t10_alua.t10_dev = dev;

dev->dev_attrib.da_dev = dev;
dev->dev_attrib.emulate_model_alias = DA_EMULATE_MODEL_ALIAS;
dev->dev_attrib.emulate_dpo = DA_EMULATE_DPO;
dev->dev_attrib.emulate_fua_write = DA_EMULATE_FUA_WRITE;
dev->dev_attrib.emulate_fua_read = DA_EMULATE_FUA_READ;
Expand Down
12 changes: 10 additions & 2 deletions drivers/target/target_core_fabric_configfs.c
Original file line number Diff line number Diff line change
Expand Up @@ -354,9 +354,17 @@ static struct config_group *target_fabric_make_mappedlun(
ret = -EINVAL;
goto out;
}
if (mapped_lun > (TRANSPORT_MAX_LUNS_PER_TPG-1)) {
pr_err("Mapped LUN: %lu exceeds TRANSPORT_MAX_LUNS_PER_TPG"
"-1: %u for Target Portal Group: %u\n", mapped_lun,
TRANSPORT_MAX_LUNS_PER_TPG-1,
se_tpg->se_tpg_tfo->tpg_get_tag(se_tpg));
ret = -EINVAL;
goto out;
}

lacl = core_dev_init_initiator_node_lun_acl(se_tpg, mapped_lun,
config_item_name(acl_ci), &ret);
lacl = core_dev_init_initiator_node_lun_acl(se_tpg, se_nacl,
mapped_lun, &ret);
if (!lacl) {
ret = -EINVAL;
goto out;
Expand Down
Loading

0 comments on commit ecc88ef

Please sign in to comment.