Commit 6301f891 authored by Tomasz Zawadzki's avatar Tomasz Zawadzki
Browse files

lib/sock: provide a hint to picking optimal poll group



The process of matching qpair to poll group is split into
two distinct parts that occur on different threads.
See spdk_nvmf_tgt_new_qpair().

This results in a race condition for TCP between spdk_sock_map_lookup()
and spdk_sock_map_insert(), which are called in spdk_nvmf_get_optimal_poll_group()
and spdk_nvmf_poll_group_add() respectively.

Fixes #2113

This patch picks a hint from nvmf_tcp for next poll group,
which is then passed down to spdk_sock_map_lookup().

When matching placement_id exists, but does not have
a poll group assigned - the hint will be used.

Signed-off-by: default avatarTomasz Zawadzki <tomasz.zawadzki@intel.com>
Change-Id: I4abde2bc9c39225c9f5dd7c3654fa2639bb0a27f
Reviewed-on: https://review.spdk.io/gerrit/c/spdk/spdk/+/10271


Tested-by: default avatarSPDK CI Jenkins <sys_sgci@intel.com>
Reviewed-by: default avatarJim Harris <james.r.harris@intel.com>
Reviewed-by: default avatarChangpeng Liu <changpeng.liu@intel.com>
parent 0db0c443
Loading
Loading
Loading
Loading
+5 −0
Original line number Diff line number Diff line
@@ -199,6 +199,11 @@ individual traces.
Added `spdk_ioviter_first` and `spdk_ioviter_next` to iterate over two iovecs and
yield pointers to common length segments.

### sock

A new parameter `hint` is added to `spdk_sock_get_optimal_sock_group`. It allows to suggest
a poll group when no optimal poll group is found.

## v21.10

Structure `spdk_nvmf_target_opts` has been extended with new member `discovery_filter` which allows to specify
+3 −1
Original line number Diff line number Diff line
@@ -467,10 +467,12 @@ int spdk_sock_group_close(struct spdk_sock_group **group);
 *
 * \param sock The socket
 * \param group Returns the optimal sock group. If there is no optimal sock group, returns NULL.
 * \param hint When return is 0 and group is set to NULL, hint is used to set optimal sock group for the socket.
 *
 * \return 0 on success. Negated errno on failure.
 */
int spdk_sock_get_optimal_sock_group(struct spdk_sock *sock, struct spdk_sock_group **group);
int spdk_sock_get_optimal_sock_group(struct spdk_sock *sock, struct spdk_sock_group **group,
				     struct spdk_sock_group *hint);

/**
 * Get current socket implementation options.
+3 −2
Original line number Diff line number Diff line
@@ -114,7 +114,8 @@ struct spdk_net_impl {
	bool (*is_ipv4)(struct spdk_sock *sock);
	bool (*is_connected)(struct spdk_sock *sock);

	struct spdk_sock_group_impl *(*group_impl_get_optimal)(struct spdk_sock *sock);
	struct spdk_sock_group_impl *(*group_impl_get_optimal)(struct spdk_sock *sock,
			struct spdk_sock_group_impl *hint);
	struct spdk_sock_group_impl *(*group_impl_create)(void);
	int (*group_impl_add_sock)(struct spdk_sock_group_impl *group, struct spdk_sock *sock);
	int (*group_impl_remove_sock)(struct spdk_sock_group_impl *group, struct spdk_sock *sock);
@@ -323,7 +324,7 @@ void spdk_sock_map_release(struct spdk_sock_map *map, int placement_id);
 * Look up the group for the given placement_id.
 */
int spdk_sock_map_lookup(struct spdk_sock_map *map, int placement_id,
			 struct spdk_sock_group_impl **group_impl);
			 struct spdk_sock_group_impl **group_impl, struct spdk_sock_group_impl *hint);

/**
 * Find a placement id with no associated group
+1 −1
Original line number Diff line number Diff line
@@ -2235,7 +2235,7 @@ nvme_tcp_qpair_get_optimal_poll_group(struct spdk_nvme_qpair *qpair)
	struct spdk_sock_group *group = NULL;
	int rc;

	rc = spdk_sock_get_optimal_sock_group(tqpair->sock, &group);
	rc = spdk_sock_get_optimal_sock_group(tqpair->sock, &group, NULL);
	if (!rc && group != NULL) {
		return spdk_sock_group_get_ctx(group);
	}
+14 −10
Original line number Diff line number Diff line
@@ -1290,18 +1290,11 @@ static struct spdk_nvmf_transport_poll_group *
nvmf_tcp_get_optimal_poll_group(struct spdk_nvmf_qpair *qpair)
{
	struct spdk_nvmf_tcp_transport *ttransport;
	struct spdk_nvmf_transport_poll_group *result;
	struct spdk_nvmf_tcp_poll_group **pg;
	struct spdk_nvmf_tcp_qpair *tqpair;
	struct spdk_sock_group *group = NULL;
	struct spdk_sock_group *group = NULL, *hint = NULL;
	int rc;

	tqpair = SPDK_CONTAINEROF(qpair, struct spdk_nvmf_tcp_qpair, qpair);
	rc = spdk_sock_get_optimal_sock_group(tqpair->sock, &group);
	if (!rc && group != NULL) {
		return spdk_sock_group_get_ctx(group);
	}

	ttransport = SPDK_CONTAINEROF(qpair->transport, struct spdk_nvmf_tcp_transport, transport);

	pthread_mutex_lock(&ttransport->lock);
@@ -1313,16 +1306,27 @@ nvmf_tcp_get_optimal_poll_group(struct spdk_nvmf_qpair *qpair)

	pg = &ttransport->next_pg;
	assert(*pg != NULL);
	hint = (*pg)->sock_group;

	result = &(*pg)->group;
	tqpair = SPDK_CONTAINEROF(qpair, struct spdk_nvmf_tcp_qpair, qpair);
	rc = spdk_sock_get_optimal_sock_group(tqpair->sock, &group, hint);
	if (rc != 0) {
		pthread_mutex_unlock(&ttransport->lock);
		return NULL;
	} else if (group != NULL) {
		/* Optimal poll group was found */
		pthread_mutex_unlock(&ttransport->lock);
		return spdk_sock_group_get_ctx(group);
	}

	/* The hint was used for optimal poll group, advance next_pg. */
	*pg = TAILQ_NEXT(*pg, link);
	if (*pg == NULL) {
		*pg = TAILQ_FIRST(&ttransport->poll_groups);
	}

	pthread_mutex_unlock(&ttransport->lock);
	return result;
	return spdk_sock_group_get_ctx(hint);
}

static void
Loading