[v3,7/9] mem: add external API to retrieve page fd from EAL
Checks
Commit Message
Now that we can retrieve page fd's internally, we can expose it
as an external API. This will add two flavors of API - thread-safe
and non-thread-safe. Fix up internal API's to return values we need
without modifying rte_errno internally if called from within EAL.
We do not want calling code to accidentally close an internal fd, so
we make a duplicate of it before we return it to the user. Caller is
therefore responsible for closing this fd.
Signed-off-by: Anatoly Burakov <anatoly.burakov@intel.com>
---
lib/librte_eal/bsdapp/eal/eal_memalloc.c | 5 ++-
lib/librte_eal/common/eal_common_memory.c | 49 ++++++++++++++++++++++
lib/librte_eal/common/eal_memalloc.h | 2 +
lib/librte_eal/common/include/rte_memory.h | 48 +++++++++++++++++++++
lib/librte_eal/linuxapp/eal/eal_memalloc.c | 21 ++++++----
lib/librte_eal/rte_eal_version.map | 2 +
6 files changed, 118 insertions(+), 9 deletions(-)
Comments
On 09/04/2018 05:15 PM, Anatoly Burakov wrote:
> Now that we can retrieve page fd's internally, we can expose it
> as an external API. This will add two flavors of API - thread-safe
> and non-thread-safe. Fix up internal API's to return values we need
> without modifying rte_errno internally if called from within EAL.
>
> We do not want calling code to accidentally close an internal fd, so
> we make a duplicate of it before we return it to the user. Caller is
> therefore responsible for closing this fd.
>
> Signed-off-by: Anatoly Burakov <anatoly.burakov@intel.com>
> ---
> lib/librte_eal/bsdapp/eal/eal_memalloc.c | 5 ++-
> lib/librte_eal/common/eal_common_memory.c | 49 ++++++++++++++++++++++
> lib/librte_eal/common/eal_memalloc.h | 2 +
> lib/librte_eal/common/include/rte_memory.h | 48 +++++++++++++++++++++
> lib/librte_eal/linuxapp/eal/eal_memalloc.c | 21 ++++++----
> lib/librte_eal/rte_eal_version.map | 2 +
> 6 files changed, 118 insertions(+), 9 deletions(-)
>
Reviewed-by: Maxime Coquelin <maxime.coquelin@redhat.com>
@@ -4,6 +4,7 @@
#include <inttypes.h>
+#include <rte_errno.h>
#include <rte_log.h>
#include <rte_memory.h>
@@ -50,13 +51,13 @@ eal_memalloc_sync_with_primary(void)
int
eal_memalloc_get_seg_fd(int list_idx, int seg_idx)
{
- return -1;
+ return -ENOTSUP;
}
int
eal_memalloc_set_seg_fd(int list_idx, int seg_idx, int fd)
{
- return -1;
+ return -ENOTSUP;
}
int
@@ -550,6 +550,55 @@ rte_memseg_list_walk(rte_memseg_list_walk_t func, void *arg)
return ret;
}
+int __rte_experimental
+rte_memseg_get_fd_thread_unsafe(const struct rte_memseg *ms)
+{
+ struct rte_mem_config *mcfg = rte_eal_get_configuration()->mem_config;
+ struct rte_memseg_list *msl;
+ struct rte_fbarray *arr;
+ int msl_idx, seg_idx, ret;
+
+ if (ms == NULL) {
+ rte_errno = EINVAL;
+ return -1;
+ }
+
+ msl = rte_mem_virt2memseg_list(ms->addr);
+ if (msl == NULL) {
+ rte_errno = EINVAL;
+ return -1;
+ }
+ arr = &msl->memseg_arr;
+
+ msl_idx = msl - mcfg->memsegs;
+ seg_idx = rte_fbarray_find_idx(arr, ms);
+
+ if (!rte_fbarray_is_used(arr, seg_idx)) {
+ rte_errno = ENOENT;
+ return -1;
+ }
+
+ ret = eal_memalloc_get_seg_fd(msl_idx, seg_idx);
+ if (ret < 0) {
+ rte_errno = -ret;
+ ret = -1;
+ }
+ return ret;
+}
+
+int __rte_experimental
+rte_memseg_get_fd(const struct rte_memseg *ms)
+{
+ struct rte_mem_config *mcfg = rte_eal_get_configuration()->mem_config;
+ int ret;
+
+ rte_rwlock_read_lock(&mcfg->memory_hotplug_lock);
+ ret = rte_memseg_get_fd_thread_unsafe(ms);
+ rte_rwlock_read_unlock(&mcfg->memory_hotplug_lock);
+
+ return ret;
+}
+
/* init memory subsystem */
int
rte_eal_memory_init(void)
@@ -76,9 +76,11 @@ eal_memalloc_mem_alloc_validator_unregister(const char *name, int socket_id);
int
eal_memalloc_mem_alloc_validate(int socket_id, size_t new_len);
+/* returns fd or -errno */
int
eal_memalloc_get_seg_fd(int list_idx, int seg_idx);
+/* returns 0 or -errno */
int
eal_memalloc_set_seg_fd(int list_idx, int seg_idx, int fd);
@@ -317,6 +317,54 @@ rte_memseg_contig_walk_thread_unsafe(rte_memseg_contig_walk_t func, void *arg);
int __rte_experimental
rte_memseg_list_walk_thread_unsafe(rte_memseg_list_walk_t func, void *arg);
+/**
+ * Return file descriptor associated with a particular memseg (if available).
+ *
+ * @note This function read-locks the memory hotplug subsystem, and thus cannot
+ * be used within memory-related callback functions.
+ *
+ * @note This returns an internal file descriptor. Performing any operations on
+ * this file descriptor is inherently dangerous, so it should be treated
+ * as read-only for all intents and purposes.
+ *
+ * @param ms
+ * A pointer to memseg for which to get file descriptor.
+ *
+ * @return
+ * Valid file descriptor in case of success.
+ * -1 in case of error, with ``rte_errno`` set to the following values:
+ * - EINVAL - ``ms`` pointer was NULL or did not point to a valid memseg
+ * - ENODEV - ``ms`` fd is not available
+ * - ENOENT - ``ms`` is an unused segment
+ * - ENOTSUP - segment fd's are not supported
+ */
+int __rte_experimental
+rte_memseg_get_fd(const struct rte_memseg *ms);
+
+/**
+ * Return file descriptor associated with a particular memseg (if available).
+ *
+ * @note This function does not perform any locking, and is only safe to call
+ * from within memory-related callback functions.
+ *
+ * @note This returns an internal file descriptor. Performing any operations on
+ * this file descriptor is inherently dangerous, so it should be treated
+ * as read-only for all intents and purposes.
+ *
+ * @param ms
+ * A pointer to memseg for which to get file descriptor.
+ *
+ * @return
+ * Valid file descriptor in case of success.
+ * -1 in case of error, with ``rte_errno`` set to the following values:
+ * - EINVAL - ``ms`` pointer was NULL or did not point to a valid memseg
+ * - ENODEV - ``ms`` fd is not available
+ * - ENOENT - ``ms`` is an unused segment
+ * - ENOTSUP - segment fd's are not supported
+ */
+int __rte_experimental
+rte_memseg_get_fd_thread_unsafe(const struct rte_memseg *ms);
+
/**
* Dump the physical memory layout to a file.
*
@@ -34,6 +34,7 @@
#include <rte_log.h>
#include <rte_eal_memconfig.h>
#include <rte_eal.h>
+#include <rte_errno.h>
#include <rte_memory.h>
#include <rte_spinlock.h>
@@ -1381,7 +1382,7 @@ eal_memalloc_set_seg_fd(int list_idx, int seg_idx, int fd)
int len = mcfg->memsegs[list_idx].memseg_arr.len;
if (alloc_list(list_idx, len) < 0)
- return -1;
+ return -ENOMEM;
}
fd_list[list_idx].fds[seg_idx] = fd;
@@ -1391,12 +1392,18 @@ eal_memalloc_set_seg_fd(int list_idx, int seg_idx, int fd)
int
eal_memalloc_get_seg_fd(int list_idx, int seg_idx)
{
- if (internal_config.single_file_segments)
- return fd_list[list_idx].memseg_list_fd;
- /* list not initialized */
- if (fd_list[list_idx].len == 0)
- return -1;
- return fd_list[list_idx].fds[seg_idx];
+ int fd;
+ if (internal_config.single_file_segments) {
+ fd = fd_list[list_idx].memseg_list_fd;
+ } else if (fd_list[list_idx].len == 0) {
+ /* list not initialized */
+ fd = -1;
+ } else {
+ fd = fd_list[list_idx].fds[seg_idx];
+ }
+ if (fd < 0)
+ return -ENODEV;
+ return fd;
}
int
@@ -320,6 +320,8 @@ EXPERIMENTAL {
rte_mem_virt2memseg_list;
rte_memseg_contig_walk;
rte_memseg_contig_walk_thread_unsafe;
+ rte_memseg_get_fd;
+ rte_memseg_get_fd_thread_unsafe;
rte_memseg_list_walk;
rte_memseg_list_walk_thread_unsafe;
rte_memseg_walk;