Using pread to replace lseek + read.
And add new APIs to reduce open/close/lseek system call frequency when the
user needs to convert a large range of virtual address space.
- rte_mem_virt2iova_with_fd
- rte_mem_virt2phy_with_fd
Currently it will be used by spdk in spdk_mem_register.
Signed-off-by: Li Feng <[email protected]>
---
lib/librte_eal/freebsd/eal_memory.c | 18 ++++++++++++++
lib/librte_eal/include/rte_memory.h | 36 +++++++++++++++++++++++++++
lib/librte_eal/linux/eal_memory.c | 49 +++++++++++++++++++++++--------------
lib/librte_eal/rte_eal_version.map | 3 +++
4 files changed, 88 insertions(+), 18 deletions(-)
diff --git a/lib/librte_eal/freebsd/eal_memory.c
b/lib/librte_eal/freebsd/eal_memory.c
index a97d8f0f0..fc0debf23 100644
--- a/lib/librte_eal/freebsd/eal_memory.c
+++ b/lib/librte_eal/freebsd/eal_memory.c
@@ -44,12 +44,30 @@ rte_mem_virt2phy(const void *virtaddr)
(void)virtaddr;
return RTE_BAD_IOVA;
}
+
rte_iova_t
rte_mem_virt2iova(const void *virtaddr)
{
return rte_mem_virt2phy(virtaddr);
}
+phys_addr_t
+rte_mem_virt2phy_with_fd(int fd, const void *virtaddr)
+{
+ /*
+ * XXX not implemented. This function is only used by
+ * rte_mempool_virt2iova_with_fd() when hugepages are disabled.
+ */
+ (void)virtaddr;
+ return RTE_BAD_IOVA;
+}
+
+rte_iova_t
+rte_mem_virt2iova_with_fd(int fd, const void *virtaddr)
+{
+ return rte_mem_virt2phy_with_fd(fd, virtaddr);
+}
+
int
rte_eal_hugepage_init(void)
{
diff --git a/lib/librte_eal/include/rte_memory.h
b/lib/librte_eal/include/rte_memory.h
index 3d8d0bd69..c75782fa7 100644
--- a/lib/librte_eal/include/rte_memory.h
+++ b/lib/librte_eal/include/rte_memory.h
@@ -108,6 +108,23 @@ int rte_mem_lock_page(const void *virt);
phys_addr_t rte_mem_virt2phy(const void *virt);
/**
+ * Get physical address of any mapped virtual address in the current process.
+ * It is found by reading fd which is the opened /proc/self/pagemap special
file
+ * descriptor. This is a optimization of rte_mem_virt2phy when the
+ * rte_mem_virt2phy is needed to be called many times.
+ * The page must be locked.
+ *
+ * @param fd
+ * The opened fd of /proc/self/pagemap.
+ * @param virt
+ * The virtual address.
+ * @return
+ * The physical address or RTE_BAD_IOVA on error.
+ */
+__rte_experimental
+phys_addr_t rte_mem_virt2phy_with_fd(int fd, const void *virt);
+
+/**
* Get IO virtual address of any mapped virtual address in the current process.
*
* @note This function will not check internal page table. Instead, in IOVA as
@@ -123,6 +140,25 @@ phys_addr_t rte_mem_virt2phy(const void *virt);
rte_iova_t rte_mem_virt2iova(const void *virt);
/**
+ * Get IO virtual address of any mapped virtual address in the current process.
+ *
+ * @note This function will not check internal page table. Instead, in IOVA as
+ * PA mode, it will fall back to getting real physical address (which may
+ * not match the expected IOVA, such as what was specified for external
+ * memory).
+ *
+ * @param virt
+ * The virtual address.
+ * @param fd
+ * The opened fd of /proc/self/pagemap.
+ * @return
+ * The IO address or RTE_BAD_IOVA on error.
+ */
+__rte_experimental
+rte_iova_t rte_mem_virt2iova_with_fd(int fd, const void *virt);
+
+
+/**
* Get virtual memory address corresponding to iova address.
*
* @note This function read-locks the memory hotplug subsystem, and thus cannot
diff --git a/lib/librte_eal/linux/eal_memory.c
b/lib/librte_eal/linux/eal_memory.c
index 7a9c97ff8..918796700 100644
--- a/lib/librte_eal/linux/eal_memory.c
+++ b/lib/librte_eal/linux/eal_memory.c
@@ -91,11 +91,11 @@ uint64_t eal_get_baseaddr(void)
/*
* Get physical address of any mapped virtual address in the current process.
+ * fd is used to avoid open/close pagemap repeatly.
*/
phys_addr_t
-rte_mem_virt2phy(const void *virtaddr)
-{
- int fd, retval;
+rte_mem_virt2phy_with_fd(int fd, const void *virtaddr) {
+ int retval;
uint64_t page, physaddr;
unsigned long virt_pfn;
int page_size;
@@ -107,24 +107,10 @@ rte_mem_virt2phy(const void *virtaddr)
/* standard page size */
page_size = getpagesize();
- fd = open("/proc/self/pagemap", O_RDONLY);
- if (fd < 0) {
- RTE_LOG(INFO, EAL, "%s(): cannot open /proc/self/pagemap: %s\n",
- __func__, strerror(errno));
- return RTE_BAD_IOVA;
- }
-
virt_pfn = (unsigned long)virtaddr / page_size;
offset = sizeof(uint64_t) * virt_pfn;
- if (lseek(fd, offset, SEEK_SET) == (off_t) -1) {
- RTE_LOG(INFO, EAL, "%s(): seek error in /proc/self/pagemap:
%s\n",
- __func__, strerror(errno));
- close(fd);
- return RTE_BAD_IOVA;
- }
- retval = read(fd, &page, PFN_MASK_SIZE);
- close(fd);
+ retval = pread(fd, &page, PFN_MASK_SIZE, offset);
if (retval < 0) {
RTE_LOG(INFO, EAL, "%s(): cannot read /proc/self/pagemap: %s\n",
__func__, strerror(errno));
@@ -149,6 +135,33 @@ rte_mem_virt2phy(const void *virtaddr)
return physaddr;
}
+/*
+ * Get physical address of any mapped virtual address in the current process.
+ */
+phys_addr_t
+rte_mem_virt2phy(const void *virtaddr)
+{
+ uint64_t physaddr;
+ int fd;
+ fd = open("/proc/self/pagemap", O_RDONLY);
+ if (fd < 0) {
+ RTE_LOG(INFO, EAL, "%s(): cannot open /proc/self/pagemap: %s\n",
+ __func__, strerror(errno));
+ return RTE_BAD_IOVA;
+ }
+ physaddr = rte_mem_virt2phy_with_fd(fd, virtaddr);
+ close(fd);
+ return physaddr;
+}
+
+rte_iova_t
+rte_mem_virt2iova_with_fd(int fd, const void *virtaddr)
+{
+ if (rte_eal_iova_mode() == RTE_IOVA_VA)
+ return (uintptr_t)virtaddr;
+ return rte_mem_virt2phy_with_fd(fd, virtaddr);
+}
+
rte_iova_t
rte_mem_virt2iova(const void *virtaddr)
{
diff --git a/lib/librte_eal/rte_eal_version.map
b/lib/librte_eal/rte_eal_version.map
index f9ede5b41..fc3a436e7 100644
--- a/lib/librte_eal/rte_eal_version.map
+++ b/lib/librte_eal/rte_eal_version.map
@@ -338,4 +338,7 @@ EXPERIMENTAL {
# added in 20.05
rte_log_can_log;
+
+ rte_mem_virt2iova_with_fd;
+ rte_mem_virt2phy_with_fd;
};
--
2.11.0
--
The SmartX email address is only for business purpose. Any sent message
that is not related to the business is not authorized or permitted by
SmartX.
本邮箱为北京志凌海纳科技有限公司(SmartX)工作邮箱. 如本邮箱发出的邮件与工作无关,该邮件未得到本公司任何的明示或默示的授权.