Commit 19e75ed4 authored by Linus Torvalds's avatar Linus Torvalds
Browse files

Merge branch '3.3-rc-fixes' of git://git.kernel.org/pub/scm/linux/kernel/git/nab/target-pending

This series contains pending target bug-fixes and cleanups for v3.3-rc3
that have been addressed the past weeks in lio-core.git.

Some of the highlights include:

 - Fix handling for control CDBs with data greater than PAGE_SIZE (andy)
 - Use IP_FREEBIND for iscsi-target to address network portal creation
   issues with systemd (dax)
 - Allow PERSISTENT RESERVE IN for non-reservation holder (marco)
 - Fix iblock se_dev_attrib.unmap_granularity (marco)
 - Fix unsupported WRITE_SAME sense payload handling (martin)
 - Add workaround for zero-length control CDB handling (nab)
 - Fix discovery with INADDR_ANY and IN6ADDR_ANY_INIT (nab)
 - Fix target_submit_cmd() exception handling (nab)
 - Return correct ASC for unimplemented VPD pages (roland)
 - Don't zero pages used for data buffers (roland)
 - Fix return code of core_tpg_.*_lun (sebastian)

* '3.3-rc-fixes' of git://git.kernel.org/pub/scm/linux/kernel/git/nab/target-pending: (26 commits)
  target: Fix unsupported WRITE_SAME sense payload
  iscsi: use IP_FREEBIND socket option
  iblock: fix handling of large requests
  target: handle empty string writes in sysfs
  iscsi_target: in_aton needs linux/inet.h
  target: Fix iblock se_dev_attrib.unmap_granularity
  target: Fix target_submit_cmd() exception handling
  target: Change target_submit_cmd() to return void
  target: accept REQUEST_SENSE with 18bytes
  target: Fail INQUIRY commands with EVPD==0 but PAGE CODE!=0
  target: Return correct ASC for unimplemented VPD pages
  iscsi-target: Fix discovery with INADDR_ANY and IN6ADDR_ANY_INIT
  target: Allow control CDBs with data > 1 page
  iscsi-target: Fix up a few assignments
  iscsi-target: make one-bit bitfields unsigned
  iscsi-target: Fix double list_add with iscsit_alloc_buffs reject
  iscsi-target: Fix reject release handling in iscsit_free_cmd()
  target: fix return code of core_tpg_.*_lun
  target: use save/restore lock primitive in core_dec_lacl_count()
  target: avoid multiple outputs in scsi_dump_inquiry()
  ...
parents 4d39aa1b 67236c44
......@@ -1061,7 +1061,7 @@ attach_cmd:
if (ret < 0)
return iscsit_add_reject_from_cmd(
ISCSI_REASON_BOOKMARK_NO_RESOURCES,
1, 1, buf, cmd);
1, 0, buf, cmd);
/*
* Check the CmdSN against ExpCmdSN/MaxCmdSN here if
* the Immediate Bit is not set, and no Immediate
......@@ -3164,6 +3164,30 @@ static int iscsit_send_task_mgt_rsp(
return 0;
}
static bool iscsit_check_inaddr_any(struct iscsi_np *np)
{
bool ret = false;
if (np->np_sockaddr.ss_family == AF_INET6) {
const struct sockaddr_in6 sin6 = {
.sin6_addr = IN6ADDR_ANY_INIT };
struct sockaddr_in6 *sock_in6 =
(struct sockaddr_in6 *)&np->np_sockaddr;
if (!memcmp(sock_in6->sin6_addr.s6_addr,
sin6.sin6_addr.s6_addr, 16))
ret = true;
} else {
struct sockaddr_in * sock_in =
(struct sockaddr_in *)&np->np_sockaddr;
if (sock_in->sin_addr.s_addr == INADDR_ANY)
ret = true;
}
return ret;
}
static int iscsit_build_sendtargets_response(struct iscsi_cmd *cmd)
{
char *payload = NULL;
......@@ -3213,12 +3237,17 @@ static int iscsit_build_sendtargets_response(struct iscsi_cmd *cmd)
spin_lock(&tpg->tpg_np_lock);
list_for_each_entry(tpg_np, &tpg->tpg_gnp_list,
tpg_np_list) {
struct iscsi_np *np = tpg_np->tpg_np;
bool inaddr_any = iscsit_check_inaddr_any(np);
len = sprintf(buf, "TargetAddress="
"%s%s%s:%hu,%hu",
(tpg_np->tpg_np->np_sockaddr.ss_family == AF_INET6) ?
"[" : "", tpg_np->tpg_np->np_ip,
(tpg_np->tpg_np->np_sockaddr.ss_family == AF_INET6) ?
"]" : "", tpg_np->tpg_np->np_port,
(np->np_sockaddr.ss_family == AF_INET6) ?
"[" : "", (inaddr_any == false) ?
np->np_ip : conn->local_ip,
(np->np_sockaddr.ss_family == AF_INET6) ?
"]" : "", (inaddr_any == false) ?
np->np_port : conn->local_port,
tpg->tpgt);
len += 1;
......
......@@ -21,6 +21,7 @@
#include <linux/configfs.h>
#include <linux/export.h>
#include <linux/inet.h>
#include <target/target_core_base.h>
#include <target/target_core_fabric.h>
#include <target/target_core_fabric_configfs.h>
......
......@@ -508,6 +508,7 @@ struct iscsi_conn {
u16 cid;
/* Remote TCP Port */
u16 login_port;
u16 local_port;
int net_size;
u32 auth_id;
#define CONNFLAG_SCTP_STRUCT_FILE 0x01
......@@ -527,6 +528,7 @@ struct iscsi_conn {
unsigned char bad_hdr[ISCSI_HDR_LEN];
#define IPV6_ADDRESS_SPACE 48
unsigned char login_ip[IPV6_ADDRESS_SPACE];
unsigned char local_ip[IPV6_ADDRESS_SPACE];
int conn_usage_count;
int conn_waiting_on_uc;
atomic_t check_immediate_queue;
......@@ -561,8 +563,8 @@ struct iscsi_conn {
struct hash_desc conn_tx_hash;
/* Used for scheduling TX and RX connection kthreads */
cpumask_var_t conn_cpumask;
int conn_rx_reset_cpumask:1;
int conn_tx_reset_cpumask:1;
unsigned int conn_rx_reset_cpumask:1;
unsigned int conn_tx_reset_cpumask:1;
/* list_head of struct iscsi_cmd for this connection */
struct list_head conn_cmd_list;
struct list_head immed_queue_list;
......
......@@ -1238,7 +1238,7 @@ void iscsit_mod_dataout_timer(struct iscsi_cmd *cmd)
{
struct iscsi_conn *conn = cmd->conn;
struct iscsi_session *sess = conn->sess;
struct iscsi_node_attrib *na = na = iscsit_tpg_get_node_attrib(sess);
struct iscsi_node_attrib *na = iscsit_tpg_get_node_attrib(sess);
spin_lock_bh(&cmd->dataout_timeout_lock);
if (!(cmd->dataout_timer_flags & ISCSI_TF_RUNNING)) {
......@@ -1261,7 +1261,7 @@ void iscsit_start_dataout_timer(
struct iscsi_conn *conn)
{
struct iscsi_session *sess = conn->sess;
struct iscsi_node_attrib *na = na = iscsit_tpg_get_node_attrib(sess);
struct iscsi_node_attrib *na = iscsit_tpg_get_node_attrib(sess);
if (cmd->dataout_timer_flags & ISCSI_TF_RUNNING)
return;
......
......@@ -615,8 +615,8 @@ static int iscsi_post_login_handler(
}
pr_debug("iSCSI Login successful on CID: %hu from %s to"
" %s:%hu,%hu\n", conn->cid, conn->login_ip, np->np_ip,
np->np_port, tpg->tpgt);
" %s:%hu,%hu\n", conn->cid, conn->login_ip,
conn->local_ip, conn->local_port, tpg->tpgt);
list_add_tail(&conn->conn_list, &sess->sess_conn_list);
atomic_inc(&sess->nconn);
......@@ -658,7 +658,8 @@ static int iscsi_post_login_handler(
sess->session_state = TARG_SESS_STATE_LOGGED_IN;
pr_debug("iSCSI Login successful on CID: %hu from %s to %s:%hu,%hu\n",
conn->cid, conn->login_ip, np->np_ip, np->np_port, tpg->tpgt);
conn->cid, conn->login_ip, conn->local_ip, conn->local_port,
tpg->tpgt);
spin_lock_bh(&sess->conn_lock);
list_add_tail(&conn->conn_list, &sess->sess_conn_list);
......@@ -841,6 +842,14 @@ int iscsi_target_setup_login_socket(
goto fail;
}
ret = kernel_setsockopt(sock, IPPROTO_IP, IP_FREEBIND,
(char *)&opt, sizeof(opt));
if (ret < 0) {
pr_err("kernel_setsockopt() for IP_FREEBIND"
" failed\n");
goto fail;
}
ret = kernel_bind(sock, (struct sockaddr *)&np->np_sockaddr, len);
if (ret < 0) {
pr_err("kernel_bind() failed: %d\n", ret);
......@@ -1020,6 +1029,18 @@ static int __iscsi_target_login_thread(struct iscsi_np *np)
snprintf(conn->login_ip, sizeof(conn->login_ip), "%pI6c",
&sock_in6.sin6_addr.in6_u);
conn->login_port = ntohs(sock_in6.sin6_port);
if (conn->sock->ops->getname(conn->sock,
(struct sockaddr *)&sock_in6, &err, 0) < 0) {
pr_err("sock_ops->getname() failed.\n");
iscsit_tx_login_rsp(conn, ISCSI_STATUS_CLS_TARGET_ERR,
ISCSI_LOGIN_STATUS_TARGET_ERROR);
goto new_sess_out;
}
snprintf(conn->local_ip, sizeof(conn->local_ip), "%pI6c",
&sock_in6.sin6_addr.in6_u);
conn->local_port = ntohs(sock_in6.sin6_port);
} else {
memset(&sock_in, 0, sizeof(struct sockaddr_in));
......@@ -1032,6 +1053,16 @@ static int __iscsi_target_login_thread(struct iscsi_np *np)
}
sprintf(conn->login_ip, "%pI4", &sock_in.sin_addr.s_addr);
conn->login_port = ntohs(sock_in.sin_port);
if (conn->sock->ops->getname(conn->sock,
(struct sockaddr *)&sock_in, &err, 0) < 0) {
pr_err("sock_ops->getname() failed.\n");
iscsit_tx_login_rsp(conn, ISCSI_STATUS_CLS_TARGET_ERR,
ISCSI_LOGIN_STATUS_TARGET_ERROR);
goto new_sess_out;
}
sprintf(conn->local_ip, "%pI4", &sock_in.sin_addr.s_addr);
conn->local_port = ntohs(sock_in.sin_port);
}
conn->network_transport = np->np_network_transport;
......@@ -1039,7 +1070,7 @@ static int __iscsi_target_login_thread(struct iscsi_np *np)
pr_debug("Received iSCSI login request from %s on %s Network"
" Portal %s:%hu\n", conn->login_ip,
(conn->network_transport == ISCSI_TCP) ? "TCP" : "SCTP",
np->np_ip, np->np_port);
conn->local_ip, conn->local_port);
pr_debug("Moving to TARG_CONN_STATE_IN_LOGIN.\n");
conn->conn_state = TARG_CONN_STATE_IN_LOGIN;
......
......@@ -849,6 +849,17 @@ void iscsit_free_cmd(struct iscsi_cmd *cmd)
case ISCSI_OP_SCSI_TMFUNC:
transport_generic_free_cmd(&cmd->se_cmd, 1);
break;
case ISCSI_OP_REJECT:
/*
* Handle special case for REJECT when iscsi_add_reject*() has
* overwritten the original iscsi_opcode assignment, and the
* associated cmd->se_cmd needs to be released.
*/
if (cmd->se_cmd.se_tfo != NULL) {
transport_generic_free_cmd(&cmd->se_cmd, 1);
break;
}
/* Fall-through */
default:
iscsit_release_cmd(cmd);
break;
......
......@@ -78,7 +78,7 @@ int target_emulate_report_target_port_groups(struct se_task *task)
return -EINVAL;
}
buf = transport_kmap_first_data_page(cmd);
buf = transport_kmap_data_sg(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,
......@@ -163,7 +163,7 @@ int target_emulate_report_target_port_groups(struct se_task *task)
buf[2] = ((rd_len >> 8) & 0xff);
buf[3] = (rd_len & 0xff);
transport_kunmap_first_data_page(cmd);
transport_kunmap_data_sg(cmd);
task->task_scsi_status = GOOD;
transport_complete_task(task, 1);
......@@ -194,7 +194,7 @@ int target_emulate_set_target_port_groups(struct se_task *task)
cmd->scsi_sense_reason = TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE;
return -EINVAL;
}
buf = transport_kmap_first_data_page(cmd);
buf = transport_kmap_data_sg(cmd);
/*
* Determine if explict ALUA via SET_TARGET_PORT_GROUPS is allowed
......@@ -351,7 +351,7 @@ int target_emulate_set_target_port_groups(struct se_task *task)
}
out:
transport_kunmap_first_data_page(cmd);
transport_kunmap_data_sg(cmd);
task->task_scsi_status = GOOD;
transport_complete_task(task, 1);
return 0;
......
......@@ -83,7 +83,7 @@ target_emulate_inquiry_std(struct se_cmd *cmd)
return -EINVAL;
}
buf = transport_kmap_first_data_page(cmd);
buf = transport_kmap_data_sg(cmd);
if (dev == tpg->tpg_virt_lun0.lun_se_dev) {
buf[0] = 0x3f; /* Not connected */
......@@ -134,7 +134,7 @@ target_emulate_inquiry_std(struct se_cmd *cmd)
buf[4] = 31; /* Set additional length to 31 */
out:
transport_kunmap_first_data_page(cmd);
transport_kunmap_data_sg(cmd);
return 0;
}
......@@ -698,6 +698,13 @@ int target_emulate_inquiry(struct se_task *task)
int p, ret;
if (!(cdb[1] & 0x1)) {
if (cdb[2]) {
pr_err("INQUIRY with EVPD==0 but PAGE CODE=%02x\n",
cdb[2]);
cmd->scsi_sense_reason = TCM_INVALID_CDB_FIELD;
return -EINVAL;
}
ret = target_emulate_inquiry_std(cmd);
goto out;
}
......@@ -716,7 +723,7 @@ int target_emulate_inquiry(struct se_task *task)
return -EINVAL;
}
buf = transport_kmap_first_data_page(cmd);
buf = transport_kmap_data_sg(cmd);
buf[0] = dev->transport->get_device_type(dev);
......@@ -729,11 +736,11 @@ int target_emulate_inquiry(struct se_task *task)
}
pr_err("Unknown VPD Code: 0x%02x\n", cdb[2]);
cmd->scsi_sense_reason = TCM_UNSUPPORTED_SCSI_OPCODE;
cmd->scsi_sense_reason = TCM_INVALID_CDB_FIELD;
ret = -EINVAL;
out_unmap:
transport_kunmap_first_data_page(cmd);
transport_kunmap_data_sg(cmd);
out:
if (!ret) {
task->task_scsi_status = GOOD;
......@@ -755,7 +762,7 @@ int target_emulate_readcapacity(struct se_task *task)
else
blocks = (u32)blocks_long;
buf = transport_kmap_first_data_page(cmd);
buf = transport_kmap_data_sg(cmd);
buf[0] = (blocks >> 24) & 0xff;
buf[1] = (blocks >> 16) & 0xff;
......@@ -771,7 +778,7 @@ int target_emulate_readcapacity(struct se_task *task)
if (dev->se_sub_dev->se_dev_attrib.emulate_tpu || dev->se_sub_dev->se_dev_attrib.emulate_tpws)
put_unaligned_be32(0xFFFFFFFF, &buf[0]);
transport_kunmap_first_data_page(cmd);
transport_kunmap_data_sg(cmd);
task->task_scsi_status = GOOD;
transport_complete_task(task, 1);
......@@ -785,7 +792,7 @@ int target_emulate_readcapacity_16(struct se_task *task)
unsigned char *buf;
unsigned long long blocks = dev->transport->get_blocks(dev);
buf = transport_kmap_first_data_page(cmd);
buf = transport_kmap_data_sg(cmd);
buf[0] = (blocks >> 56) & 0xff;
buf[1] = (blocks >> 48) & 0xff;
......@@ -806,7 +813,7 @@ int target_emulate_readcapacity_16(struct se_task *task)
if (dev->se_sub_dev->se_dev_attrib.emulate_tpu || dev->se_sub_dev->se_dev_attrib.emulate_tpws)
buf[14] = 0x80;
transport_kunmap_first_data_page(cmd);
transport_kunmap_data_sg(cmd);
task->task_scsi_status = GOOD;
transport_complete_task(task, 1);
......@@ -1019,9 +1026,9 @@ int target_emulate_modesense(struct se_task *task)
offset = cmd->data_length;
}
rbuf = transport_kmap_first_data_page(cmd);
rbuf = transport_kmap_data_sg(cmd);
memcpy(rbuf, buf, offset);
transport_kunmap_first_data_page(cmd);
transport_kunmap_data_sg(cmd);
task->task_scsi_status = GOOD;
transport_complete_task(task, 1);
......@@ -1043,7 +1050,7 @@ int target_emulate_request_sense(struct se_task *task)
return -ENOSYS;
}
buf = transport_kmap_first_data_page(cmd);
buf = transport_kmap_data_sg(cmd);
if (!core_scsi3_ua_clear_for_request_sense(cmd, &ua_asc, &ua_ascq)) {
/*
......@@ -1051,11 +1058,8 @@ int target_emulate_request_sense(struct se_task *task)
*/
buf[0] = 0x70;
buf[SPC_SENSE_KEY_OFFSET] = UNIT_ATTENTION;
/*
* Make sure request data length is enough for additional
* sense data.
*/
if (cmd->data_length <= 18) {
if (cmd->data_length < 18) {
buf[7] = 0x00;
err = -EINVAL;
goto end;
......@@ -1072,11 +1076,8 @@ int target_emulate_request_sense(struct se_task *task)
*/
buf[0] = 0x70;
buf[SPC_SENSE_KEY_OFFSET] = NO_SENSE;
/*
* Make sure request data length is enough for additional
* sense data.
*/
if (cmd->data_length <= 18) {
if (cmd->data_length < 18) {
buf[7] = 0x00;
err = -EINVAL;
goto end;
......@@ -1089,7 +1090,7 @@ int target_emulate_request_sense(struct se_task *task)
}
end:
transport_kunmap_first_data_page(cmd);
transport_kunmap_data_sg(cmd);
task->task_scsi_status = GOOD;
transport_complete_task(task, 1);
return 0;
......@@ -1123,7 +1124,7 @@ int target_emulate_unmap(struct se_task *task)
dl = get_unaligned_be16(&cdb[0]);
bd_dl = get_unaligned_be16(&cdb[2]);
buf = transport_kmap_first_data_page(cmd);
buf = transport_kmap_data_sg(cmd);
ptr = &buf[offset];
pr_debug("UNMAP: Sub: %s Using dl: %hu bd_dl: %hu size: %hu"
......@@ -1147,7 +1148,7 @@ int target_emulate_unmap(struct se_task *task)
}
err:
transport_kunmap_first_data_page(cmd);
transport_kunmap_data_sg(cmd);
if (!ret) {
task->task_scsi_status = GOOD;
transport_complete_task(task, 1);
......
......@@ -1704,13 +1704,15 @@ static ssize_t target_core_store_dev_alias(
return -EINVAL;
}
se_dev->su_dev_flags |= SDF_USING_ALIAS;
read_bytes = snprintf(&se_dev->se_dev_alias[0], SE_DEV_ALIAS_LEN,
"%s", page);
if (!read_bytes)
return -EINVAL;
if (se_dev->se_dev_alias[read_bytes - 1] == '\n')
se_dev->se_dev_alias[read_bytes - 1] = '\0';
se_dev->su_dev_flags |= SDF_USING_ALIAS;
pr_debug("Target_Core_ConfigFS: %s/%s set alias: %s\n",
config_item_name(&hba->hba_group.cg_item),
config_item_name(&se_dev->se_dev_group.cg_item),
......@@ -1753,13 +1755,15 @@ static ssize_t target_core_store_dev_udev_path(
return -EINVAL;
}
se_dev->su_dev_flags |= SDF_USING_UDEV_PATH;
read_bytes = snprintf(&se_dev->se_dev_udev_path[0], SE_UDEV_PATH_LEN,
"%s", page);
if (!read_bytes)
return -EINVAL;
if (se_dev->se_dev_udev_path[read_bytes - 1] == '\n')
se_dev->se_dev_udev_path[read_bytes - 1] = '\0';
se_dev->su_dev_flags |= SDF_USING_UDEV_PATH;
pr_debug("Target_Core_ConfigFS: %s/%s set udev_path: %s\n",
config_item_name(&hba->hba_group.cg_item),
config_item_name(&se_dev->se_dev_group.cg_item),
......
......@@ -320,11 +320,12 @@ int core_free_device_list_for_node(
void core_dec_lacl_count(struct se_node_acl *se_nacl, struct se_cmd *se_cmd)
{
struct se_dev_entry *deve;
unsigned long flags;
spin_lock_irq(&se_nacl->device_list_lock);
spin_lock_irqsave(&se_nacl->device_list_lock, flags);
deve = &se_nacl->device_list[se_cmd->orig_fe_lun];
deve->deve_cmds--;
spin_unlock_irq(&se_nacl->device_list_lock);
spin_unlock_irqrestore(&se_nacl->device_list_lock, flags);
}
void core_update_device_list_access(
......@@ -656,7 +657,7 @@ int target_report_luns(struct se_task *se_task)
unsigned char *buf;
u32 cdb_offset = 0, lun_count = 0, offset = 8, i;
buf = transport_kmap_first_data_page(se_cmd);
buf = (unsigned char *) transport_kmap_data_sg(se_cmd);
/*
* If no struct se_session pointer is present, this struct se_cmd is
......@@ -694,7 +695,7 @@ int target_report_luns(struct se_task *se_task)
* See SPC3 r07, page 159.
*/
done:
transport_kunmap_first_data_page(se_cmd);
transport_kunmap_data_sg(se_cmd);
lun_count *= 8;
buf[0] = ((lun_count >> 24) & 0xff);
buf[1] = ((lun_count >> 16) & 0xff);
......@@ -1294,24 +1295,26 @@ struct se_lun *core_dev_add_lun(
{
struct se_lun *lun_p;
u32 lun_access = 0;
int rc;
if (atomic_read(&dev->dev_access_obj.obj_access_count) != 0) {
pr_err("Unable to export struct se_device while dev_access_obj: %d\n",
atomic_read(&dev->dev_access_obj.obj_access_count));
return NULL;
return ERR_PTR(-EACCES);
}
lun_p = core_tpg_pre_addlun(tpg, lun);
if ((IS_ERR(lun_p)) || !lun_p)
return NULL;
if (IS_ERR(lun_p))
return lun_p;
if (dev->dev_flags & DF_READ_ONLY)
lun_access = TRANSPORT_LUNFLAGS_READ_ONLY;
else
lun_access = TRANSPORT_LUNFLAGS_READ_WRITE;
if (core_tpg_post_addlun(tpg, lun_p, lun_access, dev) < 0)
return NULL;
rc = core_tpg_post_addlun(tpg, lun_p, lun_access, dev);
if (rc < 0)
return ERR_PTR(rc);
pr_debug("%s_TPG[%u]_LUN[%u] - Activated %s Logical Unit from"
" CORE HBA: %u\n", tpg->se_tpg_tfo->get_fabric_name(),
......@@ -1348,11 +1351,10 @@ int core_dev_del_lun(
u32 unpacked_lun)
{
struct se_lun *lun;
int ret = 0;
lun = core_tpg_pre_dellun(tpg, unpacked_lun, &ret);
if (!lun)
return ret;
lun = core_tpg_pre_dellun(tpg, unpacked_lun);
if (IS_ERR(lun))
return PTR_ERR(lun);
core_tpg_post_dellun(tpg, lun);
......
......@@ -766,9 +766,9 @@ static int target_fabric_port_link(
lun_p = core_dev_add_lun(se_tpg, dev->se_hba, dev,
lun->unpacked_lun);
if (IS_ERR(lun_p) || !lun_p) {
if (IS_ERR(lun_p)) {
pr_err("core_dev_add_lun() failed\n");
ret = -EINVAL;
ret = PTR_ERR(lun_p);
goto out;
}
......
......@@ -129,7 +129,7 @@ static struct se_device *iblock_create_virtdevice(
/*
* These settings need to be made tunable..
*/
ib_dev->ibd_bio_set = bioset_create(32, 64);
ib_dev->ibd_bio_set = bioset_create(32, 0);
if (!ib_dev->ibd_bio_set) {
pr_err("IBLOCK: Unable to create bioset()\n");
return ERR_PTR(-ENOMEM);
......@@ -181,7 +181,7 @@ static struct se_device *iblock_create_virtdevice(
*/
dev->se_sub_dev->se_dev_attrib.max_unmap_block_desc_count = 1;
dev->se_sub_dev->se_dev_attrib.unmap_granularity =
q->limits.discard_granularity;
q->limits.discard_granularity >> 9;
dev->se_sub_dev->se_dev_attrib.unmap_granularity_alignment =
q->limits.discard_alignment;
......@@ -488,6 +488,13 @@ iblock_get_bio(struct se_task *task, sector_t lba, u32 sg_num)
struct iblock_req *ib_req = IBLOCK_REQ(task);
struct bio *bio;
/*
* Only allocate as many vector entries as the bio code allows us to,
* we'll loop later on until we have handled the whole request.
*/
if (sg_num > BIO_MAX_PAGES)
sg_num = BIO_MAX_PAGES;
bio = bio_alloc_bioset(GFP_NOIO, sg_num, ib_dev->ibd_bio_set);
if (!bio) {
pr_err("Unable to allocate memory for bio\n");
......
......@@ -90,7 +90,7 @@ void core_tpg_wait_for_nacl_pr_ref(struct se_node_acl *);
struct se_lun *core_tpg_pre_addlun(struct se_portal_group *, u32);
int core_tpg_post_addlun(struct se_portal_group *, struct se_lun *,
u32, void *);
struct se_lun *core_tpg_pre_dellun(struct se_portal_group *, u32, int *);
struct se_lun *core_tpg_pre_dellun(struct se_portal_group *, u32 unpacked_lun);
int core_tpg_post_dellun(struct se_portal_group *, struct se_lun *);
/* target_core_transport.c */
......
......@@ -478,6 +478,7 @@ static int core_scsi3_pr_seq_non_holder(
case READ_MEDIA_SERIAL_NUMBER:
case REPORT_LUNS:
case REQUEST_SENSE:
case PERSISTENT_RESERVE_IN:
ret = 0; /*/ Allowed CDBs */
break;
default:
......@@ -1534,7 +1535,7 @@ static int core_scsi3_decode_spec_i_port(
tidh_new->dest_local_nexus = 1;
list_add_tail(&tidh_new->dest_list, &tid_dest_list);
buf = transport_kmap_first_data_page(cmd);
buf = transport_kmap_data_sg(cmd);
/*
* For a PERSISTENT RESERVE OUT specify initiator ports payload,
* first extract TransportID Parameter Data Length, and make sure
......@@ -1785,7 +1786,7 @@ static int core_scsi3_decode_spec_i_port(
}
transport_kunmap_first_data_page(cmd);
transport_kunmap_data_sg(cmd);
/*