iser-target: Handle ADDR_CHANGE event for listener cm_id
The np listener cm_id will also get ADDR_CHANGE event upcall (in case it is bound to a specific IP). Handle it correctly by creating a new cm_id and implicitly destroy the old one. Since this is the second event a listener np cm_id may encounter, we move the np cm_id event handling to a routine. Squashed: iser-target: Move cma_id setup to a function Reported-by: Slava Shwartsman <valyushash@gmail.com> Signed-off-by: Sagi Grimberg <sagig@mellanox.com> Cc: <stable@vger.kernel.org> # v3.10+ Signed-off-by: Nicholas Bellinger <nab@linux-iscsi.org>
This commit is contained in:
parent
19e2090fb2
commit
ca6c1d82d1
2 changed files with 78 additions and 32 deletions
|
@ -58,6 +58,7 @@ static int
|
||||||
isert_rdma_post_recvl(struct isert_conn *isert_conn);
|
isert_rdma_post_recvl(struct isert_conn *isert_conn);
|
||||||
static int
|
static int
|
||||||
isert_rdma_accept(struct isert_conn *isert_conn);
|
isert_rdma_accept(struct isert_conn *isert_conn);
|
||||||
|
struct rdma_cm_id *isert_setup_id(struct isert_np *isert_np);
|
||||||
|
|
||||||
static void
|
static void
|
||||||
isert_qp_event_callback(struct ib_event *e, void *context)
|
isert_qp_event_callback(struct ib_event *e, void *context)
|
||||||
|
@ -573,8 +574,8 @@ err:
|
||||||
static int
|
static int
|
||||||
isert_connect_request(struct rdma_cm_id *cma_id, struct rdma_cm_event *event)
|
isert_connect_request(struct rdma_cm_id *cma_id, struct rdma_cm_event *event)
|
||||||
{
|
{
|
||||||
struct iscsi_np *np = cma_id->context;
|
struct isert_np *isert_np = cma_id->context;
|
||||||
struct isert_np *isert_np = np->np_context;
|
struct iscsi_np *np = isert_np->np;
|
||||||
struct isert_conn *isert_conn;
|
struct isert_conn *isert_conn;
|
||||||
struct isert_device *device;
|
struct isert_device *device;
|
||||||
struct ib_device *ib_dev = cma_id->device;
|
struct ib_device *ib_dev = cma_id->device;
|
||||||
|
@ -851,17 +852,41 @@ isert_conn_terminate(struct isert_conn *isert_conn)
|
||||||
}
|
}
|
||||||
|
|
||||||
static int
|
static int
|
||||||
isert_disconnected_handler(struct rdma_cm_id *cma_id)
|
isert_np_cma_handler(struct isert_np *isert_np,
|
||||||
|
enum rdma_cm_event_type event)
|
||||||
{
|
{
|
||||||
struct iscsi_np *np = cma_id->context;
|
pr_debug("isert np %p, handling event %d\n", isert_np, event);
|
||||||
struct isert_np *isert_np = np->np_context;
|
|
||||||
struct isert_conn *isert_conn;
|
|
||||||
|
|
||||||
if (isert_np->np_cm_id == cma_id) {
|
switch (event) {
|
||||||
|
case RDMA_CM_EVENT_DEVICE_REMOVAL:
|
||||||
isert_np->np_cm_id = NULL;
|
isert_np->np_cm_id = NULL;
|
||||||
|
break;
|
||||||
|
case RDMA_CM_EVENT_ADDR_CHANGE:
|
||||||
|
isert_np->np_cm_id = isert_setup_id(isert_np);
|
||||||
|
if (IS_ERR(isert_np->np_cm_id)) {
|
||||||
|
pr_err("isert np %p setup id failed: %ld\n",
|
||||||
|
isert_np, PTR_ERR(isert_np->np_cm_id));
|
||||||
|
isert_np->np_cm_id = NULL;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
pr_err("isert np %p Unexpected event %d\n",
|
||||||
|
isert_np, event);
|
||||||
|
}
|
||||||
|
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
isert_disconnected_handler(struct rdma_cm_id *cma_id,
|
||||||
|
enum rdma_cm_event_type event)
|
||||||
|
{
|
||||||
|
struct isert_np *isert_np = cma_id->context;
|
||||||
|
struct isert_conn *isert_conn;
|
||||||
|
|
||||||
|
if (isert_np->np_cm_id == cma_id)
|
||||||
|
return isert_np_cma_handler(cma_id->context, event);
|
||||||
|
|
||||||
isert_conn = cma_id->qp->qp_context;
|
isert_conn = cma_id->qp->qp_context;
|
||||||
|
|
||||||
mutex_lock(&isert_conn->conn_mutex);
|
mutex_lock(&isert_conn->conn_mutex);
|
||||||
|
@ -904,7 +929,7 @@ isert_cma_handler(struct rdma_cm_id *cma_id, struct rdma_cm_event *event)
|
||||||
case RDMA_CM_EVENT_DISCONNECTED: /* FALLTHRU */
|
case RDMA_CM_EVENT_DISCONNECTED: /* FALLTHRU */
|
||||||
case RDMA_CM_EVENT_DEVICE_REMOVAL: /* FALLTHRU */
|
case RDMA_CM_EVENT_DEVICE_REMOVAL: /* FALLTHRU */
|
||||||
case RDMA_CM_EVENT_TIMEWAIT_EXIT: /* FALLTHRU */
|
case RDMA_CM_EVENT_TIMEWAIT_EXIT: /* FALLTHRU */
|
||||||
ret = isert_disconnected_handler(cma_id);
|
ret = isert_disconnected_handler(cma_id, event->event);
|
||||||
break;
|
break;
|
||||||
case RDMA_CM_EVENT_REJECTED: /* FALLTHRU */
|
case RDMA_CM_EVENT_REJECTED: /* FALLTHRU */
|
||||||
case RDMA_CM_EVENT_UNREACHABLE: /* FALLTHRU */
|
case RDMA_CM_EVENT_UNREACHABLE: /* FALLTHRU */
|
||||||
|
@ -3065,13 +3090,51 @@ isert_response_queue(struct iscsi_conn *conn, struct iscsi_cmd *cmd, int state)
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
struct rdma_cm_id *
|
||||||
|
isert_setup_id(struct isert_np *isert_np)
|
||||||
|
{
|
||||||
|
struct iscsi_np *np = isert_np->np;
|
||||||
|
struct rdma_cm_id *id;
|
||||||
|
struct sockaddr *sa;
|
||||||
|
int ret;
|
||||||
|
|
||||||
|
sa = (struct sockaddr *)&np->np_sockaddr;
|
||||||
|
pr_debug("ksockaddr: %p, sa: %p\n", &np->np_sockaddr, sa);
|
||||||
|
|
||||||
|
id = rdma_create_id(isert_cma_handler, isert_np,
|
||||||
|
RDMA_PS_TCP, IB_QPT_RC);
|
||||||
|
if (IS_ERR(id)) {
|
||||||
|
pr_err("rdma_create_id() failed: %ld\n", PTR_ERR(id));
|
||||||
|
ret = PTR_ERR(id);
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
pr_debug("id %p context %p\n", id, id->context);
|
||||||
|
|
||||||
|
ret = rdma_bind_addr(id, sa);
|
||||||
|
if (ret) {
|
||||||
|
pr_err("rdma_bind_addr() failed: %d\n", ret);
|
||||||
|
goto out_id;
|
||||||
|
}
|
||||||
|
|
||||||
|
ret = rdma_listen(id, ISERT_RDMA_LISTEN_BACKLOG);
|
||||||
|
if (ret) {
|
||||||
|
pr_err("rdma_listen() failed: %d\n", ret);
|
||||||
|
goto out_id;
|
||||||
|
}
|
||||||
|
|
||||||
|
return id;
|
||||||
|
out_id:
|
||||||
|
rdma_destroy_id(id);
|
||||||
|
out:
|
||||||
|
return ERR_PTR(ret);
|
||||||
|
}
|
||||||
|
|
||||||
static int
|
static int
|
||||||
isert_setup_np(struct iscsi_np *np,
|
isert_setup_np(struct iscsi_np *np,
|
||||||
struct __kernel_sockaddr_storage *ksockaddr)
|
struct __kernel_sockaddr_storage *ksockaddr)
|
||||||
{
|
{
|
||||||
struct isert_np *isert_np;
|
struct isert_np *isert_np;
|
||||||
struct rdma_cm_id *isert_lid;
|
struct rdma_cm_id *isert_lid;
|
||||||
struct sockaddr *sa;
|
|
||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
isert_np = kzalloc(sizeof(struct isert_np), GFP_KERNEL);
|
isert_np = kzalloc(sizeof(struct isert_np), GFP_KERNEL);
|
||||||
|
@ -3083,9 +3146,8 @@ isert_setup_np(struct iscsi_np *np,
|
||||||
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);
|
||||||
|
isert_np->np = np;
|
||||||
|
|
||||||
sa = (struct sockaddr *)ksockaddr;
|
|
||||||
pr_debug("ksockaddr: %p, sa: %p\n", ksockaddr, sa);
|
|
||||||
/*
|
/*
|
||||||
* Setup the np->np_sockaddr from the passed sockaddr setup
|
* Setup the np->np_sockaddr from the passed sockaddr setup
|
||||||
* in iscsi_target_configfs.c code..
|
* in iscsi_target_configfs.c code..
|
||||||
|
@ -3093,37 +3155,20 @@ isert_setup_np(struct iscsi_np *np,
|
||||||
memcpy(&np->np_sockaddr, ksockaddr,
|
memcpy(&np->np_sockaddr, ksockaddr,
|
||||||
sizeof(struct __kernel_sockaddr_storage));
|
sizeof(struct __kernel_sockaddr_storage));
|
||||||
|
|
||||||
isert_lid = rdma_create_id(isert_cma_handler, np, RDMA_PS_TCP,
|
isert_lid = isert_setup_id(isert_np);
|
||||||
IB_QPT_RC);
|
|
||||||
if (IS_ERR(isert_lid)) {
|
if (IS_ERR(isert_lid)) {
|
||||||
pr_err("rdma_create_id() for isert_listen_handler failed: %ld\n",
|
|
||||||
PTR_ERR(isert_lid));
|
|
||||||
ret = PTR_ERR(isert_lid);
|
ret = PTR_ERR(isert_lid);
|
||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
|
|
||||||
ret = rdma_bind_addr(isert_lid, sa);
|
|
||||||
if (ret) {
|
|
||||||
pr_err("rdma_bind_addr() for isert_lid failed: %d\n", ret);
|
|
||||||
goto out_lid;
|
|
||||||
}
|
|
||||||
|
|
||||||
ret = rdma_listen(isert_lid, ISERT_RDMA_LISTEN_BACKLOG);
|
|
||||||
if (ret) {
|
|
||||||
pr_err("rdma_listen() for isert_lid failed: %d\n", ret);
|
|
||||||
goto out_lid;
|
|
||||||
}
|
|
||||||
|
|
||||||
isert_np->np_cm_id = isert_lid;
|
isert_np->np_cm_id = isert_lid;
|
||||||
np->np_context = isert_np;
|
np->np_context = isert_np;
|
||||||
pr_debug("Setup isert_lid->context: %p\n", isert_lid->context);
|
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
out_lid:
|
|
||||||
rdma_destroy_id(isert_lid);
|
|
||||||
out:
|
out:
|
||||||
kfree(isert_np);
|
kfree(isert_np);
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -183,6 +183,7 @@ struct isert_device {
|
||||||
};
|
};
|
||||||
|
|
||||||
struct isert_np {
|
struct isert_np {
|
||||||
|
struct iscsi_np *np;
|
||||||
struct semaphore np_sem;
|
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;
|
||||||
|
|
Loading…
Reference in a new issue