[v3,8/9] mem: allow querying offset into segment fd

Message ID 155676c123bd8b8770dcd966c7aa347177a70660.1536073997.git.anatoly.burakov@intel.com (mailing list archive)
State Accepted, archived
Delegated to: Thomas Monjalon
Headers
Series Improve running DPDK without hugetlbfs mounpoint |

Checks

Context Check Description
ci/checkpatch success coding style OK
ci/Intel-compilation success Compilation OK

Commit Message

Burakov, Anatoly Sept. 4, 2018, 3:15 p.m. UTC
  In a few cases, user may need to query offset into fd for a
particular memory segment (for example, to selectively map
pages). This commit adds a new API to do that.

Signed-off-by: Anatoly Burakov <anatoly.burakov@intel.com>
---

Notes:
    v3:
    - Fix single file segments mode not working

 lib/librte_eal/bsdapp/eal/eal_memalloc.c   |  6 +++
 lib/librte_eal/common/eal_common_memory.c  | 50 ++++++++++++++++++++++
 lib/librte_eal/common/eal_memalloc.h       |  3 ++
 lib/librte_eal/common/include/rte_memory.h | 49 +++++++++++++++++++++
 lib/librte_eal/linuxapp/eal/eal_memalloc.c | 24 +++++++++++
 lib/librte_eal/rte_eal_version.map         |  2 +
 6 files changed, 134 insertions(+)
  

Comments

Maxime Coquelin Sept. 14, 2018, 7:57 a.m. UTC | #1
On 09/04/2018 05:15 PM, Anatoly Burakov wrote:
> In a few cases, user may need to query offset into fd for a
> particular memory segment (for example, to selectively map
> pages). This commit adds a new API to do that.
> 
> Signed-off-by: Anatoly Burakov <anatoly.burakov@intel.com>
> ---
> 
> Notes:
>      v3:
>      - Fix single file segments mode not working
> 
>   lib/librte_eal/bsdapp/eal/eal_memalloc.c   |  6 +++
>   lib/librte_eal/common/eal_common_memory.c  | 50 ++++++++++++++++++++++
>   lib/librte_eal/common/eal_memalloc.h       |  3 ++
>   lib/librte_eal/common/include/rte_memory.h | 49 +++++++++++++++++++++
>   lib/librte_eal/linuxapp/eal/eal_memalloc.c | 24 +++++++++++
>   lib/librte_eal/rte_eal_version.map         |  2 +
>   6 files changed, 134 insertions(+)
> 

Reviewed-by: Maxime Coquelin <maxime.coquelin@redhat.com>

Thanks,
Maxime
  

Patch

diff --git a/lib/librte_eal/bsdapp/eal/eal_memalloc.c b/lib/librte_eal/bsdapp/eal/eal_memalloc.c
index 80e4c3d4f..06afbcc99 100644
--- a/lib/librte_eal/bsdapp/eal/eal_memalloc.c
+++ b/lib/librte_eal/bsdapp/eal/eal_memalloc.c
@@ -60,6 +60,12 @@  eal_memalloc_set_seg_fd(int list_idx, int seg_idx, int fd)
 	return -ENOTSUP;
 }
 
+int
+eal_memalloc_get_seg_fd_offset(int list_idx, int seg_idx, size_t *offset)
+{
+	return -ENOTSUP;
+}
+
 int
 eal_memalloc_init(void)
 {
diff --git a/lib/librte_eal/common/eal_common_memory.c b/lib/librte_eal/common/eal_common_memory.c
index 4a80deaf5..0b69804ff 100644
--- a/lib/librte_eal/common/eal_common_memory.c
+++ b/lib/librte_eal/common/eal_common_memory.c
@@ -599,6 +599,56 @@  rte_memseg_get_fd(const struct rte_memseg *ms)
 	return ret;
 }
 
+int __rte_experimental
+rte_memseg_get_fd_offset_thread_unsafe(const struct rte_memseg *ms,
+		size_t *offset)
+{
+	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 || offset == 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_offset(msl_idx, seg_idx, offset);
+	if (ret < 0) {
+		rte_errno = -ret;
+		ret = -1;
+	}
+	return ret;
+}
+
+int __rte_experimental
+rte_memseg_get_fd_offset(const struct rte_memseg *ms, size_t *offset)
+{
+	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_offset_thread_unsafe(ms, offset);
+	rte_rwlock_read_unlock(&mcfg->memory_hotplug_lock);
+
+	return ret;
+}
+
 /* init memory subsystem */
 int
 rte_eal_memory_init(void)
diff --git a/lib/librte_eal/common/eal_memalloc.h b/lib/librte_eal/common/eal_memalloc.h
index 70a214de4..af917c2f9 100644
--- a/lib/librte_eal/common/eal_memalloc.h
+++ b/lib/librte_eal/common/eal_memalloc.h
@@ -84,6 +84,9 @@  eal_memalloc_get_seg_fd(int list_idx, int seg_idx);
 int
 eal_memalloc_set_seg_fd(int list_idx, int seg_idx, int fd);
 
+int
+eal_memalloc_get_seg_fd_offset(int list_idx, int seg_idx, size_t *offset);
+
 int
 eal_memalloc_init(void);
 
diff --git a/lib/librte_eal/common/include/rte_memory.h b/lib/librte_eal/common/include/rte_memory.h
index 0d2a30056..14bd277a4 100644
--- a/lib/librte_eal/common/include/rte_memory.h
+++ b/lib/librte_eal/common/include/rte_memory.h
@@ -365,6 +365,55 @@  rte_memseg_get_fd(const struct rte_memseg *ms);
 int __rte_experimental
 rte_memseg_get_fd_thread_unsafe(const struct rte_memseg *ms);
 
+/**
+ * Get offset into segment 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.
+ *
+ * @param ms
+ *   A pointer to memseg for which to get file descriptor.
+ * @param offset
+ *   A pointer to offset value where the result will be stored.
+ *
+ * @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
+ *     - EINVAL  - ``offset`` pointer was NULL
+ *     - 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_offset(const struct rte_memseg *ms, size_t *offset);
+
+/**
+ * Get offset into segment 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.
+ *
+ * @param ms
+ *   A pointer to memseg for which to get file descriptor.
+ * @param offset
+ *   A pointer to offset value where the result will be stored.
+ *
+ * @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
+ *     - EINVAL  - ``offset`` pointer was NULL
+ *     - 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_offset_thread_unsafe(const struct rte_memseg *ms,
+		size_t *offset);
+
 /**
  * Dump the physical memory layout to a file.
  *
diff --git a/lib/librte_eal/linuxapp/eal/eal_memalloc.c b/lib/librte_eal/linuxapp/eal/eal_memalloc.c
index 21f842753..6fc9dc0ca 100644
--- a/lib/librte_eal/linuxapp/eal/eal_memalloc.c
+++ b/lib/librte_eal/linuxapp/eal/eal_memalloc.c
@@ -1406,6 +1406,30 @@  eal_memalloc_get_seg_fd(int list_idx, int seg_idx)
 	return fd;
 }
 
+int
+eal_memalloc_get_seg_fd_offset(int list_idx, int seg_idx, size_t *offset)
+{
+	struct rte_mem_config *mcfg = rte_eal_get_configuration()->mem_config;
+
+	/* fd_list not initialized? */
+	if (fd_list[list_idx].len == 0)
+		return -ENODEV;
+	if (internal_config.single_file_segments) {
+		size_t pgsz = mcfg->memsegs[list_idx].page_sz;
+
+		/* segment not active? */
+		if (fd_list[list_idx].memseg_list_fd < 0)
+			return -ENOENT;
+		*offset = pgsz * seg_idx;
+	} else {
+		/* segment not active? */
+		if (fd_list[list_idx].fds[seg_idx] < 0)
+			return -ENOENT;
+		*offset = 0;
+	}
+	return 0;
+}
+
 int
 eal_memalloc_init(void)
 {
diff --git a/lib/librte_eal/rte_eal_version.map b/lib/librte_eal/rte_eal_version.map
index e659e19d6..ba159f7cd 100644
--- a/lib/librte_eal/rte_eal_version.map
+++ b/lib/librte_eal/rte_eal_version.map
@@ -321,7 +321,9 @@  EXPERIMENTAL {
 	rte_memseg_contig_walk;
 	rte_memseg_contig_walk_thread_unsafe;
 	rte_memseg_get_fd;
+	rte_memseg_get_fd_offset;
 	rte_memseg_get_fd_thread_unsafe;
+	rte_memseg_get_fd_offset_thread_unsafe;
 	rte_memseg_list_walk;
 	rte_memseg_list_walk_thread_unsafe;
 	rte_memseg_walk;