Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit ca6c1d82 authored by Sagi Grimberg's avatar Sagi Grimberg Committed by Nicholas Bellinger
Browse files

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: default avatarSlava Shwartsman <valyushash@gmail.com>
Signed-off-by: default avatarSagi Grimberg <sagig@mellanox.com>
Cc: <stable@vger.kernel.org> # v3.10+
Signed-off-by: default avatarNicholas Bellinger <nab@linux-iscsi.org>
parent 19e2090f
Loading
Loading
Loading
Loading
+76 −31
Original line number Diff line number Diff line
@@ -58,6 +58,7 @@ static int
isert_rdma_post_recvl(struct isert_conn *isert_conn);
static int
isert_rdma_accept(struct isert_conn *isert_conn);
struct rdma_cm_id *isert_setup_id(struct isert_np *isert_np);

static void
isert_qp_event_callback(struct ib_event *e, void *context)
@@ -573,8 +574,8 @@ isert_conn_create_fastreg_pool(struct isert_conn *isert_conn, u8 pi_support)
static int
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 = np->np_context;
	struct isert_np *isert_np = cma_id->context;
	struct iscsi_np *np = isert_np->np;
	struct isert_conn *isert_conn;
	struct isert_device *device;
	struct ib_device *ib_dev = cma_id->device;
@@ -851,17 +852,41 @@ isert_conn_terminate(struct isert_conn *isert_conn)
}

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;
	struct isert_np *isert_np = np->np_context;
	struct isert_conn *isert_conn;
	pr_debug("isert np %p, handling event %d\n", isert_np, event);

	if (isert_np->np_cm_id == cma_id) {
	switch (event) {
	case RDMA_CM_EVENT_DEVICE_REMOVAL:
		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;
}

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;

	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_DEVICE_REMOVAL: /* FALLTHRU */
	case RDMA_CM_EVENT_TIMEWAIT_EXIT:  /* FALLTHRU */
		ret = isert_disconnected_handler(cma_id);
		ret = isert_disconnected_handler(cma_id, event->event);
		break;
	case RDMA_CM_EVENT_REJECTED:       /* 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;
}

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
isert_setup_np(struct iscsi_np *np,
	       struct __kernel_sockaddr_storage *ksockaddr)
{
	struct isert_np *isert_np;
	struct rdma_cm_id *isert_lid;
	struct sockaddr *sa;
	int ret;

	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);
	INIT_LIST_HEAD(&isert_np->np_accept_list);
	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
	 * in iscsi_target_configfs.c code..
@@ -3093,37 +3155,20 @@ isert_setup_np(struct iscsi_np *np,
	memcpy(&np->np_sockaddr, ksockaddr,
	       sizeof(struct __kernel_sockaddr_storage));

	isert_lid = rdma_create_id(isert_cma_handler, np, RDMA_PS_TCP,
				IB_QPT_RC);
	isert_lid = isert_setup_id(isert_np);
	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);
		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;
	np->np_context = isert_np;
	pr_debug("Setup isert_lid->context: %p\n", isert_lid->context);

	return 0;

out_lid:
	rdma_destroy_id(isert_lid);
out:
	kfree(isert_np);

	return ret;
}

+1 −0
Original line number Diff line number Diff line
@@ -183,6 +183,7 @@ struct isert_device {
};

struct isert_np {
	struct iscsi_np         *np;
	struct semaphore	np_sem;
	struct rdma_cm_id	*np_cm_id;
	struct mutex		np_accept_mutex;