sock: add function spdk_sock_get_optimal_sock_group

Also add the mapping table and the operations between placement_id and
sock_group

Change-Id: I31868e241fdd20252c2d79792ff1239e6d23afb8
Signed-off-by: Ziye Yang <ziye.yang@intel.com>
Reviewed-on: https://review.gerrithub.io/c/spdk/spdk/+/454537
Reviewed-by: Changpeng Liu <changpeng.liu@intel.com>
Reviewed-by: Darek Stojaczyk <dariusz.stojaczyk@intel.com>
Tested-by: SPDK CI Jenkins <sys_sgci@intel.com>
This commit is contained in:
Ziye Yang 2019-05-14 20:50:15 +08:00 committed by Darek Stojaczyk
parent bdb90726ee
commit 8bb174f87d
3 changed files with 151 additions and 2 deletions

View File

@ -69,6 +69,14 @@ the ring.
A new API `spdk_mempool_lookup` has been added to lookup the memory pool created
by the primary process.
### sock
Add spdk_sock_get_optimal_sock_group(), which returns the optimal sock group for
this socket. When a socket is created, it is often assigned to a sock group using
spdk_sock_group_add_sock so that a set of sockets can be polled more efficiently.
For some network devices, it is optimal to assign particular sockets to specific
sock groups. This API is intended to provide the user with that information.
## v19.04:
### nvme

View File

@ -252,6 +252,16 @@ int spdk_sock_group_poll_count(struct spdk_sock_group *group, int max_events);
*/
int spdk_sock_group_close(struct spdk_sock_group **group);
/**
* Get the optimal sock group for this sock.
*
* \param sock The socket
* \param group Returns the optimal sock group. If there is no optimal sock group, returns NULL.
*
* \return 0 on success. Negated errno on failure.
*/
int spdk_sock_get_optimal_sock_group(struct spdk_sock *sock, struct spdk_sock_group **group);
#ifdef __cplusplus
}
#endif

View File

@ -40,6 +40,123 @@
static STAILQ_HEAD(, spdk_net_impl) g_net_impls = STAILQ_HEAD_INITIALIZER(g_net_impls);
struct spdk_sock_placement_id_entry {
int placement_id;
uint32_t ref;
struct spdk_sock_group *group;
STAILQ_ENTRY(spdk_sock_placement_id_entry) link;
};
static STAILQ_HEAD(, spdk_sock_placement_id_entry) g_placement_id_map = STAILQ_HEAD_INITIALIZER(
g_placement_id_map);
static pthread_mutex_t g_map_table_mutex = PTHREAD_MUTEX_INITIALIZER;
/* Insert a group into the placement map.
* If the group is already in the map, take a reference.
*/
static int
spdk_sock_map_insert(int placement_id, struct spdk_sock_group *group)
{
struct spdk_sock_placement_id_entry *entry;
pthread_mutex_lock(&g_map_table_mutex);
STAILQ_FOREACH(entry, &g_placement_id_map, link) {
if (placement_id == entry->placement_id) {
/* The mapping already exists, it means that different sockets have
* the same placement_ids.
*/
entry->ref++;
pthread_mutex_unlock(&g_map_table_mutex);
return 0;
}
}
entry = calloc(1, sizeof(*entry));
if (!entry) {
SPDK_ERRLOG("Cannot allocate an entry for placement_id=%u\n", placement_id);
pthread_mutex_unlock(&g_map_table_mutex);
return -ENOMEM;
}
entry->placement_id = placement_id;
entry->group = group;
entry->ref++;
STAILQ_INSERT_TAIL(&g_placement_id_map, entry, link);
pthread_mutex_unlock(&g_map_table_mutex);
return 0;
}
/* Release a reference to the group for a given placement_id.
* If the reference count is 0, remove the group.
*/
static void
spdk_sock_map_release(int placement_id)
{
struct spdk_sock_placement_id_entry *entry;
pthread_mutex_lock(&g_map_table_mutex);
STAILQ_FOREACH(entry, &g_placement_id_map, link) {
if (placement_id == entry->placement_id) {
assert(entry->ref > 0);
entry->ref--;
if (!entry->ref) {
STAILQ_REMOVE(&g_placement_id_map, entry, spdk_sock_placement_id_entry, link);
}
break;
}
}
pthread_mutex_unlock(&g_map_table_mutex);
}
/* Look up the group for a placement_id. */
static void
spdk_sock_map_lookup(int placement_id, struct spdk_sock_group **group)
{
struct spdk_sock_placement_id_entry *entry;
*group = NULL;
pthread_mutex_lock(&g_map_table_mutex);
STAILQ_FOREACH(entry, &g_placement_id_map, link) {
if (placement_id == entry->placement_id) {
assert(entry->group != NULL);
*group = entry->group;
break;
}
}
pthread_mutex_unlock(&g_map_table_mutex);
}
/* Remove the socket group from the map table */
static void
spdk_sock_remove_sock_group_from_map_table(struct spdk_sock_group *group)
{
struct spdk_sock_placement_id_entry *entry;
pthread_mutex_lock(&g_map_table_mutex);
STAILQ_FOREACH(entry, &g_placement_id_map, link) {
STAILQ_REMOVE(&g_placement_id_map, entry, spdk_sock_placement_id_entry, link);
}
pthread_mutex_unlock(&g_map_table_mutex);
}
int
spdk_sock_get_optimal_sock_group(struct spdk_sock *sock, struct spdk_sock_group **group)
{
int placement_id = 0, rc;
rc = sock->net_impl->get_placement_id(sock, &placement_id);
if (!rc && (placement_id != 0)) {
spdk_sock_map_lookup(placement_id, group);
return 0;
} else {
return -1;
}
}
int
spdk_sock_getaddr(struct spdk_sock *sock, char *saddr, int slen, uint16_t *sport,
char *caddr, int clen, uint16_t *cport)
@ -212,7 +329,7 @@ spdk_sock_group_add_sock(struct spdk_sock_group *group, struct spdk_sock *sock,
spdk_sock_cb cb_fn, void *cb_arg)
{
struct spdk_sock_group_impl *group_impl = NULL;
int rc;
int rc, placement_id = 0;
if (cb_fn == NULL) {
errno = EINVAL;
@ -228,6 +345,14 @@ spdk_sock_group_add_sock(struct spdk_sock_group *group, struct spdk_sock *sock,
return -1;
}
rc = sock->net_impl->get_placement_id(sock, &placement_id);
if (!rc && (placement_id != 0)) {
rc = spdk_sock_map_insert(placement_id, group);
if (rc < 0) {
return -1;
}
}
STAILQ_FOREACH_FROM(group_impl, &group->group_impls, link) {
if (sock->net_impl == group_impl->net_impl) {
break;
@ -253,7 +378,7 @@ int
spdk_sock_group_remove_sock(struct spdk_sock_group *group, struct spdk_sock *sock)
{
struct spdk_sock_group_impl *group_impl = NULL;
int rc;
int rc, placement_id = 0;
STAILQ_FOREACH_FROM(group_impl, &group->group_impls, link) {
if (sock->net_impl == group_impl->net_impl) {
@ -266,6 +391,11 @@ spdk_sock_group_remove_sock(struct spdk_sock_group *group, struct spdk_sock *soc
return -1;
}
rc = sock->net_impl->get_placement_id(sock, &placement_id);
if (!rc && (placement_id != 0)) {
spdk_sock_map_release(placement_id);
}
rc = group_impl->net_impl->group_impl_remove_sock(group_impl, sock);
if (rc == 0) {
TAILQ_REMOVE(&group_impl->socks, sock, link);
@ -366,6 +496,7 @@ spdk_sock_group_close(struct spdk_sock_group **group)
free(group_impl);
}
spdk_sock_remove_sock_group_from_map_table(*group);
free(*group);
*group = NULL;