Commit a7aa96a9 authored by Linus Torvalds's avatar Linus Torvalds

Merge git://git.kernel.org/pub/scm/linux/kernel/git/nab/target-pending

Pull scsi target fixes from Nicholas Bellinger:
 "This series include:

   - Close race between iser-target network portal shutdown + accepting
     new connection logins (sagi)
   - Fix free-after-use regression in tcm_fc post conversion to
     percpu-ida pre-allocation (nab)
   - Explicitly disable Immediate + Unsolicited Data for iser-target
     connections when T10-PI is enabled (sagi + nab)
   - Allow pi_prot_type + emulate_write_cache attributes to be set to
     zero regardless of backend support (andy)
   - memory leak fix (mikulas)"

* git://git.kernel.org/pub/scm/linux/kernel/git/nab/target-pending:
  target: fix memory leak on XCOPY
  target: Don't allow setting WC emulation if device doesn't support
  iscsi-target: Disable Immediate + Unsolicited Data with ISER Protection
  tcm_fc: Fix free-after-use regression in ft_free_cmd
  iscsi-target: Change BUG_ON to REJECT in iscsit_process_nop_out
  Target/iscsi,iser: Avoid accepting transport connections during stop stage
  Target/iser: Fix iscsit_accept_np and rdma_cm racy flow
  Target/iser: Fix wrong connection requests list addition
  target: Allow non-supporting backends to set pi_prot_type to 0
parents b1400276 1e1110c4
...@@ -28,6 +28,7 @@ ...@@ -28,6 +28,7 @@
#include <target/target_core_base.h> #include <target/target_core_base.h>
#include <target/target_core_fabric.h> #include <target/target_core_fabric.h>
#include <target/iscsi/iscsi_transport.h> #include <target/iscsi/iscsi_transport.h>
#include <linux/semaphore.h>
#include "isert_proto.h" #include "isert_proto.h"
#include "ib_isert.h" #include "ib_isert.h"
...@@ -561,7 +562,15 @@ isert_connect_request(struct rdma_cm_id *cma_id, struct rdma_cm_event *event) ...@@ -561,7 +562,15 @@ isert_connect_request(struct rdma_cm_id *cma_id, struct rdma_cm_event *event)
struct isert_device *device; struct isert_device *device;
struct ib_device *ib_dev = cma_id->device; struct ib_device *ib_dev = cma_id->device;
int ret = 0; int ret = 0;
u8 pi_support = np->tpg_np->tpg->tpg_attrib.t10_pi; u8 pi_support;
spin_lock_bh(&np->np_thread_lock);
if (!np->enabled) {
spin_unlock_bh(&np->np_thread_lock);
pr_debug("iscsi_np is not enabled, reject connect request\n");
return rdma_reject(cma_id, NULL, 0);
}
spin_unlock_bh(&np->np_thread_lock);
pr_debug("Entering isert_connect_request cma_id: %p, context: %p\n", pr_debug("Entering isert_connect_request cma_id: %p, context: %p\n",
cma_id, cma_id->context); cma_id, cma_id->context);
...@@ -652,6 +661,7 @@ isert_connect_request(struct rdma_cm_id *cma_id, struct rdma_cm_event *event) ...@@ -652,6 +661,7 @@ isert_connect_request(struct rdma_cm_id *cma_id, struct rdma_cm_event *event)
goto out_mr; goto out_mr;
} }
pi_support = np->tpg_np->tpg->tpg_attrib.t10_pi;
if (pi_support && !device->pi_capable) { if (pi_support && !device->pi_capable) {
pr_err("Protection information requested but not supported\n"); pr_err("Protection information requested but not supported\n");
ret = -EINVAL; ret = -EINVAL;
...@@ -663,11 +673,11 @@ isert_connect_request(struct rdma_cm_id *cma_id, struct rdma_cm_event *event) ...@@ -663,11 +673,11 @@ isert_connect_request(struct rdma_cm_id *cma_id, struct rdma_cm_event *event)
goto out_conn_dev; goto out_conn_dev;
mutex_lock(&isert_np->np_accept_mutex); mutex_lock(&isert_np->np_accept_mutex);
list_add_tail(&isert_np->np_accept_list, &isert_conn->conn_accept_node); list_add_tail(&isert_conn->conn_accept_node, &isert_np->np_accept_list);
mutex_unlock(&isert_np->np_accept_mutex); mutex_unlock(&isert_np->np_accept_mutex);
pr_debug("isert_connect_request() waking up np_accept_wq: %p\n", np); pr_debug("isert_connect_request() up np_sem np: %p\n", np);
wake_up(&isert_np->np_accept_wq); up(&isert_np->np_sem);
return 0; return 0;
out_conn_dev: out_conn_dev:
...@@ -2999,7 +3009,7 @@ isert_setup_np(struct iscsi_np *np, ...@@ -2999,7 +3009,7 @@ isert_setup_np(struct iscsi_np *np,
pr_err("Unable to allocate struct isert_np\n"); pr_err("Unable to allocate struct isert_np\n");
return -ENOMEM; return -ENOMEM;
} }
init_waitqueue_head(&isert_np->np_accept_wq); sema_init(&isert_np->np_sem, 0);
mutex_init(&isert_np->np_accept_mutex); mutex_init(&isert_np->np_accept_mutex);
INIT_LIST_HEAD(&isert_np->np_accept_list); INIT_LIST_HEAD(&isert_np->np_accept_list);
init_completion(&isert_np->np_login_comp); init_completion(&isert_np->np_login_comp);
...@@ -3047,18 +3057,6 @@ isert_setup_np(struct iscsi_np *np, ...@@ -3047,18 +3057,6 @@ isert_setup_np(struct iscsi_np *np,
return ret; return ret;
} }
static int
isert_check_accept_queue(struct isert_np *isert_np)
{
int empty;
mutex_lock(&isert_np->np_accept_mutex);
empty = list_empty(&isert_np->np_accept_list);
mutex_unlock(&isert_np->np_accept_mutex);
return empty;
}
static int static int
isert_rdma_accept(struct isert_conn *isert_conn) isert_rdma_accept(struct isert_conn *isert_conn)
{ {
...@@ -3151,16 +3149,14 @@ isert_accept_np(struct iscsi_np *np, struct iscsi_conn *conn) ...@@ -3151,16 +3149,14 @@ isert_accept_np(struct iscsi_np *np, struct iscsi_conn *conn)
int max_accept = 0, ret; int max_accept = 0, ret;
accept_wait: accept_wait:
ret = wait_event_interruptible(isert_np->np_accept_wq, ret = down_interruptible(&isert_np->np_sem);
!isert_check_accept_queue(isert_np) ||
np->np_thread_state == ISCSI_NP_THREAD_RESET);
if (max_accept > 5) if (max_accept > 5)
return -ENODEV; return -ENODEV;
spin_lock_bh(&np->np_thread_lock); spin_lock_bh(&np->np_thread_lock);
if (np->np_thread_state == ISCSI_NP_THREAD_RESET) { if (np->np_thread_state == ISCSI_NP_THREAD_RESET) {
spin_unlock_bh(&np->np_thread_lock); spin_unlock_bh(&np->np_thread_lock);
pr_err("ISCSI_NP_THREAD_RESET for isert_accept_np\n"); pr_debug("ISCSI_NP_THREAD_RESET for isert_accept_np\n");
return -ENODEV; return -ENODEV;
} }
spin_unlock_bh(&np->np_thread_lock); spin_unlock_bh(&np->np_thread_lock);
......
...@@ -182,7 +182,7 @@ struct isert_device { ...@@ -182,7 +182,7 @@ struct isert_device {
}; };
struct isert_np { struct isert_np {
wait_queue_head_t np_accept_wq; struct semaphore np_sem;
struct rdma_cm_id *np_cm_id; struct rdma_cm_id *np_cm_id;
struct mutex np_accept_mutex; struct mutex np_accept_mutex;
struct list_head np_accept_list; struct list_head np_accept_list;
......
...@@ -1593,7 +1593,9 @@ int iscsit_process_nop_out(struct iscsi_conn *conn, struct iscsi_cmd *cmd, ...@@ -1593,7 +1593,9 @@ int iscsit_process_nop_out(struct iscsi_conn *conn, struct iscsi_cmd *cmd,
* Initiator is expecting a NopIN ping reply.. * Initiator is expecting a NopIN ping reply..
*/ */
if (hdr->itt != RESERVED_ITT) { if (hdr->itt != RESERVED_ITT) {
BUG_ON(!cmd); if (!cmd)
return iscsit_add_reject(conn, ISCSI_REASON_PROTOCOL_ERROR,
(unsigned char *)hdr);
spin_lock_bh(&conn->cmd_lock); spin_lock_bh(&conn->cmd_lock);
list_add_tail(&cmd->i_conn_node, &conn->conn_cmd_list); list_add_tail(&cmd->i_conn_node, &conn->conn_cmd_list);
......
...@@ -775,6 +775,7 @@ struct iscsi_np { ...@@ -775,6 +775,7 @@ struct iscsi_np {
int np_ip_proto; int np_ip_proto;
int np_sock_type; int np_sock_type;
enum np_thread_state_table np_thread_state; enum np_thread_state_table np_thread_state;
bool enabled;
enum iscsi_timer_flags_table np_login_timer_flags; enum iscsi_timer_flags_table np_login_timer_flags;
u32 np_exports; u32 np_exports;
enum np_flags_table np_flags; enum np_flags_table np_flags;
......
...@@ -436,7 +436,7 @@ static int iscsi_login_zero_tsih_s2( ...@@ -436,7 +436,7 @@ static int iscsi_login_zero_tsih_s2(
} }
off = mrdsl % PAGE_SIZE; off = mrdsl % PAGE_SIZE;
if (!off) if (!off)
return 0; goto check_prot;
if (mrdsl < PAGE_SIZE) if (mrdsl < PAGE_SIZE)
mrdsl = PAGE_SIZE; mrdsl = PAGE_SIZE;
...@@ -452,6 +452,31 @@ static int iscsi_login_zero_tsih_s2( ...@@ -452,6 +452,31 @@ static int iscsi_login_zero_tsih_s2(
ISCSI_LOGIN_STATUS_NO_RESOURCES); ISCSI_LOGIN_STATUS_NO_RESOURCES);
return -1; return -1;
} }
/*
* ISER currently requires that ImmediateData + Unsolicited
* Data be disabled when protection / signature MRs are enabled.
*/
check_prot:
if (sess->se_sess->sup_prot_ops &
(TARGET_PROT_DOUT_STRIP | TARGET_PROT_DOUT_PASS |
TARGET_PROT_DOUT_INSERT)) {
sprintf(buf, "ImmediateData=No");
if (iscsi_change_param_value(buf, conn->param_list, 0) < 0) {
iscsit_tx_login_rsp(conn, ISCSI_STATUS_CLS_TARGET_ERR,
ISCSI_LOGIN_STATUS_NO_RESOURCES);
return -1;
}
sprintf(buf, "InitialR2T=Yes");
if (iscsi_change_param_value(buf, conn->param_list, 0) < 0) {
iscsit_tx_login_rsp(conn, ISCSI_STATUS_CLS_TARGET_ERR,
ISCSI_LOGIN_STATUS_NO_RESOURCES);
return -1;
}
pr_debug("Forcing ImmediateData=No + InitialR2T=Yes for"
" T10-PI enabled ISER session\n");
}
} }
return 0; return 0;
...@@ -984,6 +1009,7 @@ int iscsi_target_setup_login_socket( ...@@ -984,6 +1009,7 @@ int iscsi_target_setup_login_socket(
} }
np->np_transport = t; np->np_transport = t;
np->enabled = true;
return 0; return 0;
} }
......
...@@ -184,6 +184,7 @@ static void iscsit_clear_tpg_np_login_thread( ...@@ -184,6 +184,7 @@ static void iscsit_clear_tpg_np_login_thread(
return; return;
} }
tpg_np->tpg_np->enabled = false;
iscsit_reset_np_thread(tpg_np->tpg_np, tpg_np, tpg, shutdown); iscsit_reset_np_thread(tpg_np->tpg_np, tpg_np, tpg, shutdown);
} }
......
...@@ -798,10 +798,10 @@ int se_dev_set_emulate_write_cache(struct se_device *dev, int flag) ...@@ -798,10 +798,10 @@ int se_dev_set_emulate_write_cache(struct se_device *dev, int flag)
pr_err("emulate_write_cache not supported for pSCSI\n"); pr_err("emulate_write_cache not supported for pSCSI\n");
return -EINVAL; return -EINVAL;
} }
if (dev->transport->get_write_cache) { if (flag &&
pr_warn("emulate_write_cache cannot be changed when underlying" dev->transport->get_write_cache) {
" HW reports WriteCacheEnabled, ignoring request\n"); pr_err("emulate_write_cache not supported for this device\n");
return 0; return -EINVAL;
} }
dev->dev_attrib.emulate_write_cache = flag; dev->dev_attrib.emulate_write_cache = flag;
...@@ -936,6 +936,10 @@ int se_dev_set_pi_prot_type(struct se_device *dev, int flag) ...@@ -936,6 +936,10 @@ int se_dev_set_pi_prot_type(struct se_device *dev, int flag)
return 0; return 0;
} }
if (!dev->transport->init_prot || !dev->transport->free_prot) { if (!dev->transport->init_prot || !dev->transport->free_prot) {
/* 0 is only allowed value for non-supporting backends */
if (flag == 0)
return 0;
pr_err("DIF protection not supported by backend: %s\n", pr_err("DIF protection not supported by backend: %s\n",
dev->transport->name); dev->transport->name);
return -ENOSYS; return -ENOSYS;
......
...@@ -1113,6 +1113,7 @@ void transport_init_se_cmd( ...@@ -1113,6 +1113,7 @@ void transport_init_se_cmd(
init_completion(&cmd->cmd_wait_comp); init_completion(&cmd->cmd_wait_comp);
init_completion(&cmd->task_stop_comp); init_completion(&cmd->task_stop_comp);
spin_lock_init(&cmd->t_state_lock); spin_lock_init(&cmd->t_state_lock);
kref_init(&cmd->cmd_kref);
cmd->transport_state = CMD_T_DEV_ACTIVE; cmd->transport_state = CMD_T_DEV_ACTIVE;
cmd->se_tfo = tfo; cmd->se_tfo = tfo;
...@@ -2357,7 +2358,6 @@ int target_get_sess_cmd(struct se_session *se_sess, struct se_cmd *se_cmd, ...@@ -2357,7 +2358,6 @@ int target_get_sess_cmd(struct se_session *se_sess, struct se_cmd *se_cmd,
unsigned long flags; unsigned long flags;
int ret = 0; int ret = 0;
kref_init(&se_cmd->cmd_kref);
/* /*
* Add a second kref if the fabric caller is expecting to handle * Add a second kref if the fabric caller is expecting to handle
* fabric acknowledgement that requires two target_put_sess_cmd() * fabric acknowledgement that requires two target_put_sess_cmd()
......
...@@ -90,18 +90,18 @@ static void ft_free_cmd(struct ft_cmd *cmd) ...@@ -90,18 +90,18 @@ static void ft_free_cmd(struct ft_cmd *cmd)
{ {
struct fc_frame *fp; struct fc_frame *fp;
struct fc_lport *lport; struct fc_lport *lport;
struct se_session *se_sess; struct ft_sess *sess;
if (!cmd) if (!cmd)
return; return;
se_sess = cmd->sess->se_sess; sess = cmd->sess;
fp = cmd->req_frame; fp = cmd->req_frame;
lport = fr_dev(fp); lport = fr_dev(fp);
if (fr_seq(fp)) if (fr_seq(fp))
lport->tt.seq_release(fr_seq(fp)); lport->tt.seq_release(fr_seq(fp));
fc_frame_free(fp); fc_frame_free(fp);
percpu_ida_free(&se_sess->sess_tag_pool, cmd->se_cmd.map_tag); percpu_ida_free(&sess->se_sess->sess_tag_pool, cmd->se_cmd.map_tag);
ft_sess_put(cmd->sess); /* undo get from lookup at recv */ ft_sess_put(sess); /* undo get from lookup at recv */
} }
void ft_release_cmd(struct se_cmd *se_cmd) void ft_release_cmd(struct se_cmd *se_cmd)
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment