Support running DPDK without hugetlbfs mountpoint
cover Support running DPDK without hugetlbfs mountpoint
This patchset adds a new command-line option "--in-memory", which takes old debug options "--huge-unlink" and "--no-shconf", and enhances them with additional functionality. This will allow DPDK to reserve hugepages anonymously instead of using hugetlbfs mountpoints. Coupled with the fact that this option also effectively enables both "--no-shconf" and "--huge-unlink" modes, DPDK will be able to run entirely in memory and not create any shared files while running - neither hugepages nor any runtime data.
This will, of course, disable secondary processes, but for use-cases this is targeted at (containers etc.), this is not a problem.
Older revisions had kernel support at 4.14+ and also required a fairly new glibc, but now due to not using memfd and using mmap() instead, minimum supported kernel version has dropped to 3.8.
RFC->v1 changes:
- Dropped memfd, using anonymous mmap() instead
- Do not deprecate old command-line parameters, instead use them as they are, and add a deprecation notice to remove them in the next release.
Anatoly Burakov (9):
fbarray: support no-shconf mode
ipc: add support for no-shconf mode
eal: add support for no-shconf for hugepage info
eal: add support for no-shconf in hugepage data file
eal: do not create runtime dir in no-shconf mode
mem: add support for hugepage-unlink mode
eal: add --in-memory option
doc: add deprecation notice for EAL command line options
mem: support in-memory mode
doc/guides/rel_notes/deprecation.rst | 5 + lib/librte_eal/bsdapp/eal/eal.c | 3 +- lib/librte_eal/bsdapp/eal/eal_hugepage_info.c | 4 + lib/librte_eal/common/eal_common_fbarray.c | 71 +++++---- lib/librte_eal/common/eal_common_options.c | 21 ++- lib/librte_eal/common/eal_common_proc.c | 25 ++++ lib/librte_eal/common/eal_internal_cfg.h | 4 + lib/librte_eal/common/eal_options.h | 2 + lib/librte_eal/linuxapp/eal/eal.c | 3 +- .../linuxapp/eal/eal_hugepage_info.c | 95 ++++++++---- lib/librte_eal/linuxapp/eal/eal_memalloc.c | 140 ++++++++++++------ lib/librte_eal/linuxapp/eal/eal_memory.c | 16 +- 12 files changed, 272 insertions(+), 117 deletions(-)
Signature · 1 line
2.17.0
PATCH 1/9 fbarray: support no-shconf mode
When using --no-shconf option, the expectation is that no multiprocess will be supported as no shared files are created. However, fbarray still creates some shared files that prevent multiple processes with the same prefix from starting.
Fix this by avoiding creating shared files whenever noshconf option is specified. Since virtual areas we get from eal_get_virtual_area() are read-only, remap them as writable.
---
Notes:
RFC->v1:
- Use --no-shconf only
lib/librte_eal/common/eal_common_fbarray.c | 71 +++++++++++++--------- 1 file changed, 42 insertions(+), 29 deletions(-)
lib/librte_eal/common/eal_common_fbarray.c +42 -29
@@ -434,39 +434,52 @@ rte_fbarray_init(struct rte_fbarray *arr, const char *name, unsigned int len,if (data ==NULL ) goto fail; -eal_get_fbarray_path (path,sizeof (path), name); +if (internal_config.no_shconf) { +/* remap virtual area as writable */ +void *new_data =mmap (data, mmap_len,PROT_READ |PROT_WRITE , +MAP_FIXED |MAP_PRIVATE |MAP_ANONYMOUS ,-1 ,0 ); +if (new_data ==MAP_FAILED ) { +RTE_LOG (DEBUG ,EAL ,"%s(): couldn't remap anonymous memory: %s\n" , + __func__,strerror (errno)); + goto fail; + } + }else { +eal_get_fbarray_path (path,sizeof (path), name); -/* -* Each fbarray is unique to process namespace, i.e. the filename -* depends on process prefix. Try to take out a lock and see if we -* succeed. If we don't, someone else is using it already. -*/ - fd =open (path,O_CREAT |O_RDWR ,0600 ); -if (fd <0 ) { -RTE_LOG (DEBUG ,EAL ,"%s(): couldn't open %s: %s\n" , __func__, - path,strerror (errno)); - rte_errno = errno; - goto fail; - }else if (flock (fd,LOCK_EX |LOCK_NB )) { -RTE_LOG (DEBUG ,EAL ,"%s(): couldn't lock %s: %s\n" , __func__, - path,strerror (errno)); - rte_errno =EBUSY ; - goto fail; - } +/* +* Each fbarray is unique to process namespace, i.e. the +* filename depends on process prefix. Try to take out a lock +* and see if we succeed. If we don't, someone else is using it +* already. +*/ + fd =open (path,O_CREAT |O_RDWR ,0600 ); +if (fd <0 ) { +RTE_LOG (DEBUG ,EAL ,"%s(): couldn't open %s: %s\n" , + __func__, path,strerror (errno)); + rte_errno = errno; + goto fail; + }else if (flock (fd,LOCK_EX |LOCK_NB )) { +RTE_LOG (DEBUG ,EAL ,"%s(): couldn't lock %s: %s\n" , + __func__, path,strerror (errno)); + rte_errno =EBUSY ; + goto fail; + } -/* take out a non-exclusive lock, so that other processes could still -* attach to it, but no other process could reinitialize it. -*/ -if (flock (fd,LOCK_SH |LOCK_NB )) { - rte_errno = errno; - goto fail; - } +/* take out a non-exclusive lock, so that other processes could +* still attach to it, but no other process could reinitialize +* it. +*/ +if (flock (fd,LOCK_SH |LOCK_NB )) { + rte_errno = errno; + goto fail; + } -if (resize_and_map (fd, data, mmap_len)) - goto fail; +if (resize_and_map (fd, data, mmap_len)) + goto fail; -/* we've mmap'ed the file, we can now close the fd */ -close (fd); +/* we've mmap'ed the file, we can now close the fd */ +close (fd); + }/* initialize the data */ memset (data,0 , mmap_len);
Signature · 1 line
2.17.0
PATCH 2/9 ipc: add support for no-shconf mode
In reply to Anatoly BurakovIPC is an inter-process communication mechanism. Since no secondaries can ever be expected to run in no-shconf mode, IPC will be useless, so do not enable it in the first place. In the interests of API usage convenience, we will still allow registering callbacks, but obviously they won't ever be triggered.
---
Notes:
RFC->v1:
- Use --no-shconf only
lib/librte_eal/common/eal_common_proc.c | 25 +++++++++++++++++++++++++ 1 file changed, 25 insertions(+)
lib/librte_eal/common/eal_common_proc.c +25 -0
@@ -626,6 +626,14 @@ rte_mp_channel_init(void)int dir_fd;pthread_t mp_handle_tid, async_reply_handle_tid; +/* in no shared files mode, we do not have secondary processes support, +* so no need to initialize IPC. +*/ +if (internal_config.no_shconf) { +RTE_LOG (DEBUG ,EAL ,"No shared files mode enabled, IPC will be disabled\n" ); +return 0 ; + } +/* create filter path */ create_socket_path ("*" , path,sizeof (path));strlcpy (mp_filter,basename (path),sizeof (mp_filter));
@@ -988,6 +996,12 @@ rte_mp_request_sync(struct rte_mp_msg *req, struct rte_mp_reply *reply,if (check_input (req) == false)return -1 ; + +if (internal_config.no_shconf) { +RTE_LOG (DEBUG ,EAL ,"No shared files mode enabled, IPC is disabled\n" ); +return 0 ; + } +if (gettimeofday (&now,NULL ) <0 ) {RTE_LOG (ERR ,EAL ,"Faile to get current time\n" ); rte_errno = errno;
@@ -1072,6 +1086,12 @@ rte_mp_request_async(struct rte_mp_msg *req, const struct timespec *ts,if (check_input (req) == false)return -1 ; + +if (internal_config.no_shconf) { +RTE_LOG (DEBUG ,EAL ,"No shared files mode enabled, IPC is disabled\n" ); +return 0 ; + } +if (gettimeofday (&now,NULL ) <0 ) {RTE_LOG (ERR ,EAL ,"Faile to get current time\n" ); rte_errno = errno;
@@ -1213,5 +1233,10 @@ rte_mp_reply(struct rte_mp_msg *msg, const char *peer)return -1 ; } +if (internal_config.no_shconf) { +RTE_LOG (DEBUG ,EAL ,"No shared files mode enabled, IPC is disabled\n" ); +return 0 ; + } +return mp_send (msg, peer,MP_REP ); }
Signature · 1 line
2.17.0
PATCH 3/9 eal: add support for no-shconf for hugepage info
In reply to Anatoly BurakovDo not create any shared hugepage size info files if we were asked to not create any shared files.
---
Notes:
RFC->v1:
- Use --no-shconf only
lib/librte_eal/bsdapp/eal/eal_hugepage_info.c | 4 ++++ lib/librte_eal/linuxapp/eal/eal_hugepage_info.c | 4 ++++ 2 files changed, 8 insertions(+)
lib/librte_eal/bsdapp/eal/eal_hugepage_info.c +4 -0
@@ -101,6 +101,10 @@ eal_hugepage_info_init(void) hpi->num_pages[0 ] = num_buffers; hpi->lock_descriptor = fd; +/* for no shared files mode, do not create shared memory config */ +if (internal_config.no_shconf) +return 0 ; + tmp_hpi =create_shared_memory (eal_hugepage_info_path (),sizeof (internal_config.hugepage_info));if (tmp_hpi ==NULL ) {
lib/librte_eal/linuxapp/eal/eal_hugepage_info.c +4 -0
@@ -446,6 +446,10 @@ eal_hugepage_info_init(void)if (hugepage_info_init () <0 )return -1 ; +/* for no shared files mode, we're done */ +if (internal_config.no_shconf) +return 0 ; + hpi = &internal_config.hugepage_info[0 ]; tmp_hpi = create_shared_memory(eal_hugepage_info_path(),
Signature · 1 line
2.17.0
PATCH 4/9 eal: add support for no-shconf in hugepage data file
In reply to Anatoly BurakovDo not create a shared hugepage data file if we were asked to not create any shared files.
---
Notes:
RFC->v1:
- Use --no-shconf only
lib/librte_eal/linuxapp/eal/eal_memory.c | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-)
lib/librte_eal/linuxapp/eal/eal_memory.c +12 -1
@@ -521,7 +521,18 @@ static void * create_shared_memory(const char *filename, const size_t mem_size) { void *retval; -int fd =open (filename,O_CREAT |O_RDWR ,0666 ); +int fd; + +/* if no shared files mode is used, create anonymous memory instead */ +if (internal_config.no_shconf) { + retval =mmap (NULL , mem_size,PROT_READ |PROT_WRITE , +MAP_PRIVATE |MAP_ANONYMOUS ,-1 ,0 ); +if (retval ==MAP_FAILED ) +return NULL ; +return retval; + } + + fd =open (filename,O_CREAT |O_RDWR ,0666 );if (fd <0 )return NULL ;if (ftruncate (fd, mem_size) <0 ) {
Signature · 1 line
2.17.0
PATCH 5/9 eal: do not create runtime dir in no-shconf mode
In reply to Anatoly BurakovNow that the rest of the EAL is adjusted to not create any shared files, prevent runtime directory from ever being created.
---
Notes:
RFC->v1:
- Use --no-shconf only
lib/librte_eal/bsdapp/eal/eal.c | 3 ++- lib/librte_eal/linuxapp/eal/eal.c | 3 ++- 2 files changed, 4 insertions(+), 2 deletions(-)
lib/librte_eal/bsdapp/eal/eal.c +2 -1
@@ -601,7 +601,8 @@ rte_eal_init(int argc, char **argv) }/* create runtime data directory */ -if (eal_create_runtime_dir () <0 ) { +if (internal_config.no_shconf ==0 && +eal_create_runtime_dir () <0 ) {rte_eal_init_alert ("Cannot create runtime directory\n" ); rte_errno =EACCES ;return -1 ;
lib/librte_eal/linuxapp/eal/eal.c +2 -1
@@ -818,7 +818,8 @@ rte_eal_init(int argc, char **argv) }/* create runtime data directory */ -if (eal_create_runtime_dir () <0 ) { +if (internal_config.no_shconf ==0 && +eal_create_runtime_dir () <0 ) {rte_eal_init_alert ("Cannot create runtime directory\n" ); rte_errno =EACCES ;return -1 ;
Signature · 1 line
2.17.0
PATCH 6/9 mem: add support for hugepage-unlink mode
In reply to Anatoly BurakovUnlink hugepages after creating them, to honor the hugepage-unlink mode. We cannot resize non-existing files, so make single file segments explicitly unsupported.
---
Notes:
RFC->v1:
- Use --huge-unlink only
lib/librte_eal/linuxapp/eal/eal_memalloc.c | 16 +++++++++++++++- 1 file changed, 15 insertions(+), 1 deletion(-)
lib/librte_eal/linuxapp/eal/eal_memalloc.c +15 -1
@@ -512,6 +512,13 @@ alloc_seg(struct rte_memseg *ms, void *addr, int socket_id, __func__, strerror(errno)); goto resized; } +if (internal_config.hugepage_unlink) { +if (unlink (path)) { +RTE_LOG (DEBUG ,EAL ,"%s(): unlink() failed: %s\n" , + __func__,strerror (errno)); + goto resized; + } + } }/*
@@ -592,7 +599,8 @@ alloc_seg(struct rte_memseg *ms, void *addr, int socket_id,/* ignore failure, can't make it any worse */ }else {/* only remove file if we can take out a write lock */ -if (lock (fd,LOCK_EX ) ==1 ) +if (internal_config.hugepage_unlink ==0 && +lock (fd,LOCK_EX ) ==1 )unlink (path);close (fd); }
@@ -617,6 +625,12 @@ free_seg(struct rte_memseg *ms, struct hugepage_info *hi,return -1 ; } +/* if we've already unlinked the page, nothing needs to be done */ +if (internal_config.hugepage_unlink) { +memset (ms,0 ,sizeof (*ms)); +return 0 ; + } +/* if we are not in single file segments mode, we're going to unmap the * segment and thus drop the lock on original fd, but hugepage dir is * now locked so we can take out another one without races.
Signature · 1 line
2.17.0
PATCH 7/9 eal: add --in-memory option
In reply to Anatoly BurakovThis command-line option will cause DPDK to operate entirely in memory and not create any shared files at runtime, including any shared configuration or hugetlbfs files. This is useful for debug purposes, as well as for certain use cases like containers or automatic memory cleanup.
Currently, this option acts as a strict superset of --no-shconf and --huge-unlink commands.
---
Notes:
RFC->v1:
- Do not deprecate old options, instead just coopt them
lib/librte_eal/common/eal_common_options.c | 21 +++++++++++++++++++-- lib/librte_eal/common/eal_internal_cfg.h | 4 ++++ lib/librte_eal/common/eal_options.h | 2 ++ 3 files changed, 25 insertions(+), 2 deletions(-)
lib/librte_eal/common/eal_common_options.c +19 -2
@@ -66,6 +66,7 @@ eal_long_options[] = { {OPT_NO_HUGE, 0, NULL, OPT_NO_HUGE_NUM }, {OPT_NO_PCI, 0, NULL, OPT_NO_PCI_NUM }, {OPT_NO_SHCONF, 0, NULL, OPT_NO_SHCONF_NUM }, + {OPT_IN_MEMORY, 0, NULL, OPT_IN_MEMORY_NUM }, {OPT_PCI_BLACKLIST, 1, NULL, OPT_PCI_BLACKLIST_NUM }, {OPT_PCI_WHITELIST, 1, NULL, OPT_PCI_WHITELIST_NUM }, {OPT_PROC_TYPE, 1, NULL, OPT_PROC_TYPE_NUM },
@@ -1165,6 +1166,13 @@ eal_parse_common_option(int opt, const char *optarg, conf->no_shconf =1 ;break ; +case OPT_IN_MEMORY_NUM : + conf->in_memory =1 ; +/* in-memory is a superset of noshconf and huge-unlink */ + conf->no_shconf =1 ; + conf->hugepage_unlink =1 ; +break ; +case OPT_PROC_TYPE_NUM : conf->process_type =eal_parse_proc_type (optarg);break ;
@@ -1316,12 +1324,19 @@ eal_check_common_options(struct internal_config *internal_cfg) "be specified together with --"OPT_NO_HUGE"\n");return -1 ; } - -if (internal_cfg->no_hugetlbfs && internal_cfg->hugepage_unlink) { +if (internal_cfg->no_hugetlbfs && internal_cfg->hugepage_unlink && + !internal_cfg->in_memory) {RTE_LOG (ERR ,EAL ,"Option --" OPT_HUGE_UNLINK " cannot " "be specified together with --" OPT_NO_HUGE "\n" );return -1 ; } +if (internal_cfg->single_file_segments && + internal_cfg->hugepage_unlink) { +RTE_LOG (ERR ,EAL ,"Option --" OPT_SINGLE_FILE_SEGMENTS " is " +"not compatible with neither --" OPT_IN_MEMORY " nor " +"--" OPT_HUGE_UNLINK "\n" ); +return -1 ; + }return 0 ; }
@@ -1370,6 +1385,8 @@ eal_common_usage(void)" Set specific log level\n" " -v Display version information on startup\n" " -h, --help This help\n" +" --" OPT_IN_MEMORY " Operate entirely in memory. This will \n" +" disable secondary process support\n" "\nEAL options for DEBUG use only:\n" " --" OPT_HUGE_UNLINK " Unlink hugepage files after init\n" " --" OPT_NO_HUGE " Use malloc instead of hugetlbfs\n"
lib/librte_eal/common/eal_internal_cfg.h +4 -0
@@ -41,6 +41,10 @@ struct internal_config {volatile unsigned vmware_tsc_map;/**< true to use VMware TSC mapping * instead of native TSC */ volatile unsigned no_shconf;/**< true if there is no shared config */ +volatile unsigned in_memory; +/**< true if DPDK should operate entirely in-memory and not create any +* shared files or runtime data. +*/ volatile unsigned create_uio_dev;/**< true to create /dev/uioX devices */ volatile enum rte_proc_type_t process_type;/**< multi-process proc type */ /** true to try allocating memory on specific sockets */
lib/librte_eal/common/eal_options.h +2 -0
@@ -45,6 +45,8 @@ enum {OPT_NO_PCI_NUM , #define OPT_NO_SHCONF "no-shconf"OPT_NO_SHCONF_NUM , +#define OPT_IN_MEMORY "in-memory" +OPT_IN_MEMORY_NUM , #define OPT_SOCKET_MEM "socket-mem"OPT_SOCKET_MEM_NUM , #define OPT_SYSLOG "syslog"
Signature · 1 line
2.17.0
PATCH 8/9 doc: add deprecation notice for EAL command line options
In reply to Anatoly BurakovOptions --no-shconf and --huge-unlink will be removed, and replaced with --in-memory option, which will be a superset of these two, and an offially support method to run DPDK entirely in memory.
---
Notes:
RFC->v1:
- Add this patch
doc/guides/rel_notes/deprecation.rst | 5 +++++ 1 file changed, 5 insertions(+)
doc/guides/rel_notes/deprecation.rst +5 -0
@@ -8,6 +8,11 @@ API and ABI deprecation notices are to be posted here. Deprecation Notices ------------------- +* eal: command-line options ``--no-shconf`` and ``--huge-unlink`` will be + removed, and replaced with a single option ``--in-memory``, which will + enable DPDK to operate entirely in memory, without creating any files on any + filesystems. + * eal: DPDK runtime configuration file (located at ``/var/run/.<prefix>_config``) will be moved. The new path will be as follows:
Signature · 1 line
2.17.0
PATCH 9/9 mem: support in-memory mode
In reply to Anatoly BurakovImplement the final piece of the in-memory mode puzzle - enable running DPDK entirely in memory, without creating any files.
To do it, use mmap with MAP_HUGETLB and size flags to enable DPDK to work without hugetlbfs mountpoints. In order to enable this, a few things needed to be changed.
First of all, we need to allow empty hugetlbfs mountpoints in hugepage_info, and handle them correctly (by not trying to create any files and lock any directories).
Next, we need to reorder the mapping sequence, because the page is not really allocated until the page fault, and we cannot get its IOVA address before we trigger the page fault.
Finally, decide at compile time whether we are going to be supporting anonymous hugepages or not, because we cannot check for it at runtime.
---
Notes:
RFC->v1:
- Drop memfd and instead use mmap() with MAP_HUGETLB. This will drop the kernel requirements down to 3.8, and does not impose any restrictions glibc (as far as i known).
Unfortunately, there's a bit of an issue with this approach, because mmap() is stupid and will happily ignore unsupported arguments. This means that if the binary were to be compiled on a 3.8+ kernel but run on a pre-3.8 kernel (such as currently supported minimum of 3.2), then most likely the memory would be allocated using regular pages, causing unthinkable performance degradation. No solution to this problem is currently known to me.
.../linuxapp/eal/eal_hugepage_info.c | 91 +++++++----- lib/librte_eal/linuxapp/eal/eal_memalloc.c | 130 +++++++++++------- lib/librte_eal/linuxapp/eal/eal_memory.c | 3 +- 3 files changed, 139 insertions(+), 85 deletions(-)
lib/librte_eal/linuxapp/eal/eal_hugepage_info.c +59 -32
@@ -18,6 +18,8 @@#include <sys/queue.h> #include <sys/stat.h> +#include <linux/mman.h> /* for hugetlb-related flags */ +#include <rte_memory.h> #include <rte_eal.h> #include <rte_launch.h>
@@ -313,11 +315,49 @@ compare_hpi(const void *a, const void *b)return hpi_b->hugepage_sz - hpi_a->hugepage_sz; } +static void +calc_num_pages (struct hugepage_info *hpi,struct dirent *dirent) +{ +uint64_t total_pages =0 ; +unsigned int i; + +/* +* first, try to put all hugepages into relevant sockets, but +* if first attempts fails, fall back to collecting all pages +* in one socket and sorting them later +*/ + total_pages =0 ; +/* we also don't want to do this for legacy init */ +if (!internal_config.legacy_mem) +for (i =0 ; i <rte_socket_count (); i++) { +int socket =rte_socket_id_by_idx (i); +unsigned int num_pages = +get_num_hugepages_on_node ( + dirent->d_name, socket); + hpi->num_pages[socket] = num_pages; + total_pages += num_pages; + } +/* +* we failed to sort memory from the get go, so fall +* back to old way +*/ +if (total_pages ==0 ) { + hpi->num_pages[0 ] =get_num_hugepages (dirent->d_name); + +#ifndef RTE_ARCH_64 +/* for 32-bit systems, limit number of hugepages to +* 1GB per page size */ + hpi->num_pages[0 ] =RTE_MIN (hpi->num_pages[0 ], +RTE_PGSIZE_1G / hpi->hugepage_sz); +#endif + } +} +static int hugepage_info_init (void ) {const char dirent_start_text[] ="hugepages-" ;const size_t dirent_start_len =sizeof (dirent_start_text) -1 ; -unsigned int i, total_pages, num_sizes =0 ; +unsigned int i, num_sizes =0 ;DIR *dir;struct dirent *dirent;
@@ -355,6 +395,22 @@ hugepage_info_init(void)"%" PRIu64" reserved, but no mounted " "hugetlbfs found for that size\n" , num_pages, hpi->hugepage_sz); +/* if we have kernel support for reserving hugepages +* through mmap, and we're in in-memory mode, treat this +* page size as valid. we cannot be in legacy mode at +* this point because we've checked this earlier in the +* init process. +*/ +#ifdef MAP_HUGE_SHIFT +if (internal_config.in_memory) { +RTE_LOG (DEBUG ,EAL ,"In-memory mode enabled, " +"hugepages of size %" PRIu64" bytes " +"will be allocated anonymously\n" , + hpi->hugepage_sz); +calc_num_pages (hpi, dirent); + num_sizes++; + } +#endif continue ; }
@@ -371,35 +427,7 @@ hugepage_info_init(void)if (clear_hugedir (hpi->hugedir) ==-1 )break ; -/* -* first, try to put all hugepages into relevant sockets, but -* if first attempts fails, fall back to collecting all pages -* in one socket and sorting them later -*/ - total_pages =0 ; -/* we also don't want to do this for legacy init */ -if (!internal_config.legacy_mem) -for (i =0 ; i <rte_socket_count (); i++) { -int socket =rte_socket_id_by_idx (i); -unsigned int num_pages = -get_num_hugepages_on_node ( - dirent->d_name, socket); - hpi->num_pages[socket] = num_pages; - total_pages += num_pages; - } -/* -* we failed to sort memory from the get go, so fall -* back to old way -*/ -if (total_pages ==0 ) - hpi->num_pages[0 ] =get_num_hugepages (dirent->d_name); - -#ifndef RTE_ARCH_64 -/* for 32-bit systems, limit number of hugepages to -* 1GB per page size */ - hpi->num_pages[0 ] =RTE_MIN (hpi->num_pages[0 ], -RTE_PGSIZE_1G / hpi->hugepage_sz); -#endif +calc_num_pages (hpi, dirent); num_sizes++; }
@@ -423,8 +451,7 @@ hugepage_info_init(void)for (j =0 ; j <RTE_MAX_NUMA_NODES ; j++) num_pages += hpi->num_pages[j]; -if (strnlen (hpi->hugedir,sizeof (hpi->hugedir)) !=0 && - num_pages >0 ) +if (num_pages >0 )return 0 ; }
lib/librte_eal/linuxapp/eal/eal_memalloc.c +79 -51
197 lines not on this page · raw message
lib/librte_eal/linuxapp/eal/eal_memory.c +1 -2
@@ -1060,8 +1060,7 @@ get_socket_mem_size(int socket)for (i =0 ; i < internal_config.num_hugepage_sizes; i++){struct hugepage_info *hpi = &internal_config.hugepage_info[i]; -if (strnlen (hpi->hugedir,sizeof (hpi->hugedir)) !=0 ) - size += hpi->hugepage_sz * hpi->num_pages[socket]; + size += hpi->hugepage_sz * hpi->num_pages[socket]; }return size;
Signature · 1 line
2.17.0
v2 cover Support running DPDK without hugetlbfs mountpoint
In reply to Anatoly BurakovThis patchset adds a new command-line option "--in-memory", which takes old debug options "--huge-unlink" and "--no-shconf", and enhances them with additional functionality. This will allow DPDK to reserve hugepages anonymously instead of using hugetlbfs mountpoints. Coupled with the fact that this option also effectively enables both "--no-shconf" and "--huge-unlink" modes, DPDK will be able to run entirely in memory and not create any shared files while running - neither hugepages nor any runtime data.
This will, of course, disable secondary processes, but for use-cases this is targeted at (containers etc.), this is not a problem.
Older revisions had kernel support at 4.14+ and also required a fairly new glibc, but now due to not using memfd and using mmap() instead, minimum supported kernel version has dropped to 3.8.
v1->v2 changes:
- Rebase on latest master
- Fix patch 5 to include check from patch 6 as commit message states
RFC->v1 changes:
- Dropped memfd, using anonymous mmap() instead
- Do not deprecate old command-line parameters, instead use them as they are, and add a deprecation notice to remove them in the next release.
Anatoly Burakov (9):
fbarray: support no-shconf mode
ipc: add support for no-shconf mode
eal: add support for no-shconf for hugepage info
eal: add support for no-shconf in hugepage data file
eal: do not create runtime dir in no-shconf mode
mem: add support for hugepage-unlink mode
eal: add --in-memory option
doc: add deprecation notice for EAL command line options
mem: support in-memory mode
doc/guides/rel_notes/deprecation.rst | 5 + lib/librte_eal/bsdapp/eal/eal.c | 3 +- lib/librte_eal/bsdapp/eal/eal_hugepage_info.c | 4 + lib/librte_eal/common/eal_common_fbarray.c | 71 +++++---- lib/librte_eal/common/eal_common_options.c | 20 ++- lib/librte_eal/common/eal_common_proc.c | 25 ++++ lib/librte_eal/common/eal_internal_cfg.h | 4 + lib/librte_eal/common/eal_options.h | 2 + lib/librte_eal/linuxapp/eal/eal.c | 3 +- .../linuxapp/eal/eal_hugepage_info.c | 95 ++++++++---- lib/librte_eal/linuxapp/eal/eal_memalloc.c | 140 ++++++++++++------ lib/librte_eal/linuxapp/eal/eal_memory.c | 16 +- 12 files changed, 271 insertions(+), 117 deletions(-)
Signature · 1 line
2.17.1
PATCH v2 1/9 fbarray: support no-shconf mode
When using --no-shconf option, the expectation is that no multiprocess will be supported as no shared files are created. However, fbarray still creates some shared files that prevent multiple processes with the same prefix from starting.
Fix this by avoiding creating shared files whenever noshconf option is specified. Since virtual areas we get from eal_get_virtual_area() are read-only, remap them as writable.
---
Notes:
RFC->v1:
- Use --no-shconf only
lib/librte_eal/common/eal_common_fbarray.c | 71 +++++++++++++--------- 1 file changed, 42 insertions(+), 29 deletions(-)
lib/librte_eal/common/eal_common_fbarray.c +42 -29
@@ -705,39 +705,52 @@ rte_fbarray_init(struct rte_fbarray *arr, const char *name, unsigned int len,if (data ==NULL ) goto fail; -eal_get_fbarray_path (path,sizeof (path), name); +if (internal_config.no_shconf) { +/* remap virtual area as writable */ +void *new_data =mmap (data, mmap_len,PROT_READ |PROT_WRITE , +MAP_FIXED |MAP_PRIVATE |MAP_ANONYMOUS ,-1 ,0 ); +if (new_data ==MAP_FAILED ) { +RTE_LOG (DEBUG ,EAL ,"%s(): couldn't remap anonymous memory: %s\n" , + __func__,strerror (errno)); + goto fail; + } + }else { +eal_get_fbarray_path (path,sizeof (path), name); -/* -* Each fbarray is unique to process namespace, i.e. the filename -* depends on process prefix. Try to take out a lock and see if we -* succeed. If we don't, someone else is using it already. -*/ - fd =open (path,O_CREAT |O_RDWR ,0600 ); -if (fd <0 ) { -RTE_LOG (DEBUG ,EAL ,"%s(): couldn't open %s: %s\n" , __func__, - path,strerror (errno)); - rte_errno = errno; - goto fail; - }else if (flock (fd,LOCK_EX |LOCK_NB )) { -RTE_LOG (DEBUG ,EAL ,"%s(): couldn't lock %s: %s\n" , __func__, - path,strerror (errno)); - rte_errno =EBUSY ; - goto fail; - } +/* +* Each fbarray is unique to process namespace, i.e. the +* filename depends on process prefix. Try to take out a lock +* and see if we succeed. If we don't, someone else is using it +* already. +*/ + fd =open (path,O_CREAT |O_RDWR ,0600 ); +if (fd <0 ) { +RTE_LOG (DEBUG ,EAL ,"%s(): couldn't open %s: %s\n" , + __func__, path,strerror (errno)); + rte_errno = errno; + goto fail; + }else if (flock (fd,LOCK_EX |LOCK_NB )) { +RTE_LOG (DEBUG ,EAL ,"%s(): couldn't lock %s: %s\n" , + __func__, path,strerror (errno)); + rte_errno =EBUSY ; + goto fail; + } -/* take out a non-exclusive lock, so that other processes could still -* attach to it, but no other process could reinitialize it. -*/ -if (flock (fd,LOCK_SH |LOCK_NB )) { - rte_errno = errno; - goto fail; - } +/* take out a non-exclusive lock, so that other processes could +* still attach to it, but no other process could reinitialize +* it. +*/ +if (flock (fd,LOCK_SH |LOCK_NB )) { + rte_errno = errno; + goto fail; + } -if (resize_and_map (fd, data, mmap_len)) - goto fail; +if (resize_and_map (fd, data, mmap_len)) + goto fail; -/* we've mmap'ed the file, we can now close the fd */ -close (fd); +/* we've mmap'ed the file, we can now close the fd */ +close (fd); + }/* initialize the data */ memset (data,0 , mmap_len);
Signature · 1 line
2.17.1
PATCH v2 2/9 ipc: add support for no-shconf mode
In reply to Anatoly BurakovIPC is an inter-process communication mechanism. Since no secondaries can ever be expected to run in no-shconf mode, IPC will be useless, so do not enable it in the first place. In the interests of API usage convenience, we will still allow registering callbacks, but obviously they won't ever be triggered.
---
Notes:
RFC->v1:
- Use --no-shconf only
lib/librte_eal/common/eal_common_proc.c | 25 +++++++++++++++++++++++++ 1 file changed, 25 insertions(+)
lib/librte_eal/common/eal_common_proc.c +25 -0
@@ -626,6 +626,14 @@ rte_mp_channel_init(void)int dir_fd;pthread_t mp_handle_tid, async_reply_handle_tid; +/* in no shared files mode, we do not have secondary processes support, +* so no need to initialize IPC. +*/ +if (internal_config.no_shconf) { +RTE_LOG (DEBUG ,EAL ,"No shared files mode enabled, IPC will be disabled\n" ); +return 0 ; + } +/* create filter path */ create_socket_path ("*" , path,sizeof (path));strlcpy (mp_filter,basename (path),sizeof (mp_filter));
@@ -988,6 +996,12 @@ rte_mp_request_sync(struct rte_mp_msg *req, struct rte_mp_reply *reply,if (check_input (req) == false)return -1 ; + +if (internal_config.no_shconf) { +RTE_LOG (DEBUG ,EAL ,"No shared files mode enabled, IPC is disabled\n" ); +return 0 ; + } +if (gettimeofday (&now,NULL ) <0 ) {RTE_LOG (ERR ,EAL ,"Faile to get current time\n" ); rte_errno = errno;
@@ -1072,6 +1086,12 @@ rte_mp_request_async(struct rte_mp_msg *req, const struct timespec *ts,if (check_input (req) == false)return -1 ; + +if (internal_config.no_shconf) { +RTE_LOG (DEBUG ,EAL ,"No shared files mode enabled, IPC is disabled\n" ); +return 0 ; + } +if (gettimeofday (&now,NULL ) <0 ) {RTE_LOG (ERR ,EAL ,"Faile to get current time\n" ); rte_errno = errno;
@@ -1213,5 +1233,10 @@ rte_mp_reply(struct rte_mp_msg *msg, const char *peer)return -1 ; } +if (internal_config.no_shconf) { +RTE_LOG (DEBUG ,EAL ,"No shared files mode enabled, IPC is disabled\n" ); +return 0 ; + } +return mp_send (msg, peer,MP_REP ); }
Signature · 1 line
2.17.1
PATCH v2 3/9 eal: add support for no-shconf for hugepage info
In reply to Anatoly BurakovDo not create any shared hugepage size info files if we were asked to not create any shared files.
---
Notes:
RFC->v1:
- Use --no-shconf only
lib/librte_eal/bsdapp/eal/eal_hugepage_info.c | 4 ++++ lib/librte_eal/linuxapp/eal/eal_hugepage_info.c | 4 ++++ 2 files changed, 8 insertions(+)
lib/librte_eal/bsdapp/eal/eal_hugepage_info.c +4 -0
@@ -101,6 +101,10 @@ eal_hugepage_info_init(void) hpi->num_pages[0 ] = num_buffers; hpi->lock_descriptor = fd; +/* for no shared files mode, do not create shared memory config */ +if (internal_config.no_shconf) +return 0 ; + tmp_hpi =create_shared_memory (eal_hugepage_info_path (),sizeof (internal_config.hugepage_info));if (tmp_hpi ==NULL ) {
lib/librte_eal/linuxapp/eal/eal_hugepage_info.c +4 -0
@@ -446,6 +446,10 @@ eal_hugepage_info_init(void)if (hugepage_info_init () <0 )return -1 ; +/* for no shared files mode, we're done */ +if (internal_config.no_shconf) +return 0 ; + hpi = &internal_config.hugepage_info[0 ]; tmp_hpi = create_shared_memory(eal_hugepage_info_path(),
Signature · 1 line
2.17.1
PATCH v2 4/9 eal: add support for no-shconf in hugepage data file
In reply to Anatoly BurakovDo not create a shared hugepage data file if we were asked to not create any shared files.
---
Notes:
RFC->v1:
- Use --no-shconf only
lib/librte_eal/linuxapp/eal/eal_memory.c | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-)
lib/librte_eal/linuxapp/eal/eal_memory.c +12 -1
@@ -521,7 +521,18 @@ static void * create_shared_memory(const char *filename, const size_t mem_size) { void *retval; -int fd =open (filename,O_CREAT |O_RDWR ,0666 ); +int fd; + +/* if no shared files mode is used, create anonymous memory instead */ +if (internal_config.no_shconf) { + retval =mmap (NULL , mem_size,PROT_READ |PROT_WRITE , +MAP_PRIVATE |MAP_ANONYMOUS ,-1 ,0 ); +if (retval ==MAP_FAILED ) +return NULL ; +return retval; + } + + fd =open (filename,O_CREAT |O_RDWR ,0666 );if (fd <0 )return NULL ;if (ftruncate (fd, mem_size) <0 ) {
Signature · 1 line
2.17.1
PATCH v2 5/9 eal: do not create runtime dir in no-shconf mode
In reply to Anatoly BurakovNow that the rest of the EAL is adjusted to not create any shared files, prevent runtime directory from ever being created.
---
Notes:
RFC->v1:
- Use --no-shconf only
lib/librte_eal/bsdapp/eal/eal.c | 3 ++- lib/librte_eal/linuxapp/eal/eal.c | 3 ++- 2 files changed, 4 insertions(+), 2 deletions(-)
lib/librte_eal/bsdapp/eal/eal.c +2 -1
@@ -601,7 +601,8 @@ rte_eal_init(int argc, char **argv) }/* create runtime data directory */ -if (eal_create_runtime_dir () <0 ) { +if (internal_config.no_shconf ==0 && +eal_create_runtime_dir () <0 ) {rte_eal_init_alert ("Cannot create runtime directory\n" ); rte_errno =EACCES ;return -1 ;
lib/librte_eal/linuxapp/eal/eal.c +2 -1
@@ -832,7 +832,8 @@ rte_eal_init(int argc, char **argv) }/* create runtime data directory */ -if (eal_create_runtime_dir () <0 ) { +if (internal_config.no_shconf ==0 && +eal_create_runtime_dir () <0 ) {rte_eal_init_alert ("Cannot create runtime directory\n" ); rte_errno =EACCES ;return -1 ;
Signature · 1 line
2.17.1
PATCH v2 6/9 mem: add support for hugepage-unlink mode
In reply to Anatoly BurakovUnlink hugepages after creating them, to honor the hugepage-unlink mode. We cannot resize non-existing files, so make single file segments explicitly unsupported.
---
Notes:
v1->v2:
- Move check for hugepage unlink into this patch, to be consistent with commit message
RFC->v1:
- Use --huge-unlink only
RFC->v1:
- Use --huge-unlink only
lib/librte_eal/common/eal_common_options.c | 6 ++++++ lib/librte_eal/linuxapp/eal/eal_memalloc.c | 16 +++++++++++++++- 2 files changed, 21 insertions(+), 1 deletion(-)
lib/librte_eal/common/eal_common_options.c +6 -0
@@ -1332,6 +1332,12 @@ eal_check_common_options(struct internal_config *internal_cfg) " is only supported in non-legacy memory mode\n");return -1 ; } +if (internal_cfg->single_file_segments && + internal_cfg->hugepage_unlink) { +RTE_LOG (ERR ,EAL ,"Option --" OPT_SINGLE_FILE_SEGMENTS " is " +"not compatible with --" OPT_HUGE_UNLINK "\n" ); +return -1 ; + }return 0 ; }
lib/librte_eal/linuxapp/eal/eal_memalloc.c +15 -1
@@ -489,6 +489,13 @@ alloc_seg(struct rte_memseg *ms, void *addr, int socket_id, __func__, strerror(errno)); goto resized; } +if (internal_config.hugepage_unlink) { +if (unlink (path)) { +RTE_LOG (DEBUG ,EAL ,"%s(): unlink() failed: %s\n" , + __func__,strerror (errno)); + goto resized; + } + } }/*
@@ -587,7 +594,8 @@ alloc_seg(struct rte_memseg *ms, void *addr, int socket_id,/* ignore failure, can't make it any worse */ }else {/* only remove file if we can take out a write lock */ -if (lock (fd,LOCK_EX ) ==1 ) +if (internal_config.hugepage_unlink ==0 && +lock (fd,LOCK_EX ) ==1 )unlink (path);close (fd); }
@@ -612,6 +620,12 @@ free_seg(struct rte_memseg *ms, struct hugepage_info *hi,return -1 ; } +/* if we've already unlinked the page, nothing needs to be done */ +if (internal_config.hugepage_unlink) { +memset (ms,0 ,sizeof (*ms)); +return 0 ; + } +/* if we are not in single file segments mode, we're going to unmap the * segment and thus drop the lock on original fd, but hugepage dir is * now locked so we can take out another one without races.
Signature · 1 line
2.17.1
PATCH v2 7/9 eal: add --in-memory option
In reply to Anatoly BurakovThis command-line option will cause DPDK to operate entirely in memory and not create any shared files at runtime, including any shared configuration or hugetlbfs files. This is useful for debug purposes, as well as for certain use cases like containers or automatic memory cleanup.
Currently, this option acts as a strict superset of --no-shconf and --huge-unlink commands.
---
Notes:
RFC->v1:
- Do not deprecate old options, instead just coopt them
lib/librte_eal/common/eal_common_options.c | 18 ++++++++++++++---- lib/librte_eal/common/eal_internal_cfg.h | 4 ++++ lib/librte_eal/common/eal_options.h | 2 ++ 3 files changed, 20 insertions(+), 4 deletions(-)
lib/librte_eal/common/eal_common_options.c +14 -4
@@ -66,6 +66,7 @@ eal_long_options[] = { {OPT_NO_HUGE, 0, NULL, OPT_NO_HUGE_NUM }, {OPT_NO_PCI, 0, NULL, OPT_NO_PCI_NUM }, {OPT_NO_SHCONF, 0, NULL, OPT_NO_SHCONF_NUM }, + {OPT_IN_MEMORY, 0, NULL, OPT_IN_MEMORY_NUM }, {OPT_PCI_BLACKLIST, 1, NULL, OPT_PCI_BLACKLIST_NUM }, {OPT_PCI_WHITELIST, 1, NULL, OPT_PCI_WHITELIST_NUM }, {OPT_PROC_TYPE, 1, NULL, OPT_PROC_TYPE_NUM },
@@ -1170,6 +1171,13 @@ eal_parse_common_option(int opt, const char *optarg, conf->no_shconf =1 ;break ; +case OPT_IN_MEMORY_NUM : + conf->in_memory =1 ; +/* in-memory is a superset of noshconf and huge-unlink */ + conf->no_shconf =1 ; + conf->hugepage_unlink =1 ; +break ; +case OPT_PROC_TYPE_NUM : conf->process_type =eal_parse_proc_type (optarg);break ;
@@ -1321,8 +1329,8 @@ eal_check_common_options(struct internal_config *internal_cfg) "be specified together with --"OPT_NO_HUGE"\n");return -1 ; } - -if (internal_cfg->no_hugetlbfs && internal_cfg->hugepage_unlink) { +if (internal_cfg->no_hugetlbfs && internal_cfg->hugepage_unlink && + !internal_cfg->in_memory) {RTE_LOG (ERR ,EAL ,"Option --" OPT_HUGE_UNLINK " cannot " "be specified together with --" OPT_NO_HUGE "\n" );return -1 ;
@@ -1330,12 +1338,12 @@ eal_check_common_options(struct internal_config *internal_cfg)if (internal_config.force_socket_limits && internal_config.legacy_mem) {RTE_LOG (ERR ,EAL ,"Option --" OPT_SOCKET_LIMIT " is only supported in non-legacy memory mode\n" ); -return -1 ; }if (internal_cfg->single_file_segments && internal_cfg->hugepage_unlink) {RTE_LOG (ERR ,EAL ,"Option --" OPT_SINGLE_FILE_SEGMENTS " is " -"not compatible with --" OPT_HUGE_UNLINK "\n" ); +"not compatible with neither --" OPT_IN_MEMORY " nor " +"--" OPT_HUGE_UNLINK "\n" );return -1 ; }
@@ -1386,6 +1394,8 @@ eal_common_usage(void)" Set specific log level\n" " -v Display version information on startup\n" " -h, --help This help\n" +" --" OPT_IN_MEMORY " Operate entirely in memory. This will \n" +" disable secondary process support\n" "\nEAL options for DEBUG use only:\n" " --" OPT_HUGE_UNLINK " Unlink hugepage files after init\n" " --" OPT_NO_HUGE " Use malloc instead of hugetlbfs\n"
lib/librte_eal/common/eal_internal_cfg.h +4 -0
@@ -41,6 +41,10 @@ struct internal_config {volatile unsigned vmware_tsc_map;/**< true to use VMware TSC mapping * instead of native TSC */ volatile unsigned no_shconf;/**< true if there is no shared config */ +volatile unsigned in_memory; +/**< true if DPDK should operate entirely in-memory and not create any +* shared files or runtime data. +*/ volatile unsigned create_uio_dev;/**< true to create /dev/uioX devices */ volatile enum rte_proc_type_t process_type;/**< multi-process proc type */ /** true to try allocating memory on specific sockets */
lib/librte_eal/common/eal_options.h +2 -0
@@ -45,6 +45,8 @@ enum {OPT_NO_PCI_NUM , #define OPT_NO_SHCONF "no-shconf"OPT_NO_SHCONF_NUM , +#define OPT_IN_MEMORY "in-memory" +OPT_IN_MEMORY_NUM , #define OPT_SOCKET_MEM "socket-mem"OPT_SOCKET_MEM_NUM , #define OPT_SOCKET_LIMIT "socket-limit"
Signature · 1 line
2.17.1
Re: [PATCH v2 7/9] eal: add --in-memory option
13/07/2018 12:27, Anatoly Burakov:
Quoted 10 lines
This command-line option will cause DPDK to operate entirely in memory and not create any shared files at runtime, including any shared configuration or hugetlbfs files. This is useful for debug purposes, as well as for certain use cases like containers or automatic memory cleanup.
Currently, this option acts as a strict superset of --no-shconf and --huge-unlink commands.
Signed-off-by Anatoly Burakov <[email protected]>
I would like to see some support or review for this feature.
Re: [PATCH v2 7/9] eal: add --in-memory option
Quoted 7 lines · Thomas Monjalon
13/07/2018 12:27, Anatoly Burakov:
Quoted 6 lines
This command-line option will cause DPDK to operate entirely in memory and not create any shared files at runtime, including any shared configuration or hugetlbfs files. This is useful for debug purposes, as well as for certain use cases like containers or automatic memory cleanup.
Quoted 7 lines
Quoted 4 lines
Currently, this option acts as a strict superset of --no-shconf and --huge-unlink commands.
Signed-off-by Anatoly Burakov <[email protected]>I would like to see some support or review for this feature.
While the justification for it can be use-cases like running a DPDK process without worrying about cleaning up its hugepages afterwards (somewhat less of a concern since 18.05 but still a concern if primary crashes), it is really fixing the no-shconf/huge-unlink options to not be half-measures.
Both of these options effectively disable secondary processes, but don't do it in a consistent way - huge-unlink cleans up hugepages after allocating them, but leaves shared config on. No-shconf disables shared config, but leaves hugepages in place. Since 18.05, huge-unlink didn't work anyway (wasn't implemented, which was my omission), and due to EAL now relying on fbarray's to store some data, no-shconf wasn't working correctly either because even though shared config wasn't created, two primaries still couldn't share a prefix with --no-shconf (see the first patch).
So, this patchset is really an acknowledgement of the fact that both huge-unlink and no-shconf options are really there to disable secondary processes and stop leaving files on the file system. I just went one step further, and instead of allocating-and-then-removing hugepages we're not creating them in the first place, and map them anonymously instead.
Signature · 2 lines
Thanks, Anatoly
PATCH v2 8/9 doc: add deprecation notice for EAL command line options
In reply to Anatoly BurakovOptions --no-shconf and --huge-unlink will be removed, and replaced with --in-memory option, which will be a superset of these two, and an offially support method to run DPDK entirely in memory.
---
Notes:
RFC->v1:
- Add this patch
doc/guides/rel_notes/deprecation.rst | 5 +++++ 1 file changed, 5 insertions(+)
doc/guides/rel_notes/deprecation.rst +5 -0
@@ -8,6 +8,11 @@ API and ABI deprecation notices are to be posted here. Deprecation Notices ------------------- +* eal: command-line options ``--no-shconf`` and ``--huge-unlink`` will be + removed, and replaced with a single option ``--in-memory``, which will + enable DPDK to operate entirely in memory, without creating any files on any + filesystems. + * eal: DPDK runtime configuration file (located at ``/var/run/.<prefix>_config``) will be moved. The new path will be as follows:
Signature · 1 line
2.17.1
Re: [PATCH v2 8/9] doc: add deprecation notice for EAL command line options
13/07/2018 12:27, Anatoly Burakov:
Quoted 6 lines
Options --no-shconf and --huge-unlink will be removed, and replaced with --in-memory option, which will be a superset of these two, and an offially support method to run DPDK entirely in memory.
Signed-off-by Anatoly Burakov <[email protected]>
The deprecation notice should be sent separately in order to wait for enough agreement.
Re: [PATCH v2 8/9] doc: add deprecation notice for EAL command line options
Quoted 11 lines · Thomas Monjalon
13/07/2018 12:27, Anatoly Burakov:
Quoted 6 lines
Options --no-shconf and --huge-unlink will be removed, and replaced with --in-memory option, which will be a superset of these two, and an offially support method to run DPDK entirely in memory.
Signed-off-by Anatoly Burakov <[email protected]>The deprecation notice should be sent separately in order to wait for enough agreement.
Really, we don't have to deprecate old options. It would be nice to remove them as half-measures and replace them with a proper implementation, but it's not strictly necessary, so i'll make it a separate patch.
Signature · 2 lines
Thanks, Anatoly
PATCH v2 9/9 mem: support in-memory mode
In reply to Anatoly BurakovImplement the final piece of the in-memory mode puzzle - enable running DPDK entirely in memory, without creating any files.
To do it, use mmap with MAP_HUGETLB and size flags to enable DPDK to work without hugetlbfs mountpoints. In order to enable this, a few things needed to be changed.
First of all, we need to allow empty hugetlbfs mountpoints in hugepage_info, and handle them correctly (by not trying to create any files and lock any directories).
Next, we need to reorder the mapping sequence, because the page is not really allocated until the page fault, and we cannot get its IOVA address before we trigger the page fault.
Finally, decide at compile time whether we are going to be supporting anonymous hugepages or not, because we cannot check for it at runtime.
---
Notes:
RFC->v1:
- Drop memfd and instead use mmap() with MAP_HUGETLB. This will drop the kernel requirements down to 3.8, and does not impose any restrictions glibc (as far as i known).
Unfortunately, there's a bit of an issue with this approach, because mmap() is stupid and will happily ignore unsupported arguments. This means that if the binary were to be compiled on a 3.8+ kernel but run on a pre-3.8 kernel (such as currently supported minimum of 3.2), then most likely the memory would be allocated using regular pages, causing unthinkable performance degradation. No solution to this problem is currently known to me.
.../linuxapp/eal/eal_hugepage_info.c | 91 +++++++----- lib/librte_eal/linuxapp/eal/eal_memalloc.c | 130 +++++++++++------- lib/librte_eal/linuxapp/eal/eal_memory.c | 3 +- 3 files changed, 139 insertions(+), 85 deletions(-)
lib/librte_eal/linuxapp/eal/eal_hugepage_info.c +59 -32
@@ -18,6 +18,8 @@#include <sys/queue.h> #include <sys/stat.h> +#include <linux/mman.h> /* for hugetlb-related flags */ +#include <rte_memory.h> #include <rte_eal.h> #include <rte_launch.h>
@@ -313,11 +315,49 @@ compare_hpi(const void *a, const void *b)return hpi_b->hugepage_sz - hpi_a->hugepage_sz; } +static void +calc_num_pages (struct hugepage_info *hpi,struct dirent *dirent) +{ +uint64_t total_pages =0 ; +unsigned int i; + +/* +* first, try to put all hugepages into relevant sockets, but +* if first attempts fails, fall back to collecting all pages +* in one socket and sorting them later +*/ + total_pages =0 ; +/* we also don't want to do this for legacy init */ +if (!internal_config.legacy_mem) +for (i =0 ; i <rte_socket_count (); i++) { +int socket =rte_socket_id_by_idx (i); +unsigned int num_pages = +get_num_hugepages_on_node ( + dirent->d_name, socket); + hpi->num_pages[socket] = num_pages; + total_pages += num_pages; + } +/* +* we failed to sort memory from the get go, so fall +* back to old way +*/ +if (total_pages ==0 ) { + hpi->num_pages[0 ] =get_num_hugepages (dirent->d_name); + +#ifndef RTE_ARCH_64 +/* for 32-bit systems, limit number of hugepages to +* 1GB per page size */ + hpi->num_pages[0 ] =RTE_MIN (hpi->num_pages[0 ], +RTE_PGSIZE_1G / hpi->hugepage_sz); +#endif + } +} +static int hugepage_info_init (void ) {const char dirent_start_text[] ="hugepages-" ;const size_t dirent_start_len =sizeof (dirent_start_text) -1 ; -unsigned int i, total_pages, num_sizes =0 ; +unsigned int i, num_sizes =0 ;DIR *dir;struct dirent *dirent;
@@ -355,6 +395,22 @@ hugepage_info_init(void)"%" PRIu64" reserved, but no mounted " "hugetlbfs found for that size\n" , num_pages, hpi->hugepage_sz); +/* if we have kernel support for reserving hugepages +* through mmap, and we're in in-memory mode, treat this +* page size as valid. we cannot be in legacy mode at +* this point because we've checked this earlier in the +* init process. +*/ +#ifdef MAP_HUGE_SHIFT +if (internal_config.in_memory) { +RTE_LOG (DEBUG ,EAL ,"In-memory mode enabled, " +"hugepages of size %" PRIu64" bytes " +"will be allocated anonymously\n" , + hpi->hugepage_sz); +calc_num_pages (hpi, dirent); + num_sizes++; + } +#endif continue ; }
@@ -371,35 +427,7 @@ hugepage_info_init(void)if (clear_hugedir (hpi->hugedir) ==-1 )break ; -/* -* first, try to put all hugepages into relevant sockets, but -* if first attempts fails, fall back to collecting all pages -* in one socket and sorting them later -*/ - total_pages =0 ; -/* we also don't want to do this for legacy init */ -if (!internal_config.legacy_mem) -for (i =0 ; i <rte_socket_count (); i++) { -int socket =rte_socket_id_by_idx (i); -unsigned int num_pages = -get_num_hugepages_on_node ( - dirent->d_name, socket); - hpi->num_pages[socket] = num_pages; - total_pages += num_pages; - } -/* -* we failed to sort memory from the get go, so fall -* back to old way -*/ -if (total_pages ==0 ) - hpi->num_pages[0 ] =get_num_hugepages (dirent->d_name); - -#ifndef RTE_ARCH_64 -/* for 32-bit systems, limit number of hugepages to -* 1GB per page size */ - hpi->num_pages[0 ] =RTE_MIN (hpi->num_pages[0 ], -RTE_PGSIZE_1G / hpi->hugepage_sz); -#endif +calc_num_pages (hpi, dirent); num_sizes++; }
@@ -423,8 +451,7 @@ hugepage_info_init(void)for (j =0 ; j <RTE_MAX_NUMA_NODES ; j++) num_pages += hpi->num_pages[j]; -if (strnlen (hpi->hugedir,sizeof (hpi->hugedir)) !=0 && - num_pages >0 ) +if (num_pages >0 )return 0 ; }
lib/librte_eal/linuxapp/eal/eal_memalloc.c +79 -51
199 lines not on this page · raw message
lib/librte_eal/linuxapp/eal/eal_memory.c +1 -2
@@ -1088,8 +1088,7 @@ get_socket_mem_size(int socket)for (i =0 ; i < internal_config.num_hugepage_sizes; i++){struct hugepage_info *hpi = &internal_config.hugepage_info[i]; -if (strnlen (hpi->hugedir,sizeof (hpi->hugedir)) !=0 ) - size += hpi->hugepage_sz * hpi->num_pages[socket]; + size += hpi->hugepage_sz * hpi->num_pages[socket]; }return size;
Signature · 1 line
2.17.1
Re: [PATCH v2 9/9] mem: support in-memory mode
There is a compilation error:
../lib/librte_eal/linuxapp/eal/eal_memalloc.c: In function ‘alloc_seg’:../lib/librte_eal/linuxapp/eal/eal_memalloc.c:619:3: error:
‘map_offset’ may be used uninitialized in this function
13/07/2018 12:27, Anatoly Burakov:
Quoted 34 lines
Implement the final piece of the in-memory mode puzzle - enable running DPDK entirely in memory, without creating any files.
To do it, use mmap with
MAP_HUGETLBand size flags to enable DPDK to work without hugetlbfs mountpoints. In order to enable this, a few things needed to be changed.First of all, we need to allow empty hugetlbfs mountpoints in
hugepage_info, and handle them correctly (by not trying to create any files and lock any directories).Next, we need to reorder the mapping sequence, because the page is not really allocated until the page fault, and we cannot get its IOVA address before we trigger the page fault.
Finally, decide at compile time whether we are going to be supporting anonymous hugepages or not, because we cannot check for it at runtime.
Signed-off-by Anatoly Burakov <[email protected]>---
Notes:
RFC->v1:
- Drop memfd and instead usemmap()withMAP_HUGETLB. This will drop the kernel requirements down to 3.8, and does not impose any restrictions glibc (as far as i known).Unfortunately, there's a bit of an issue with this approach, because
mmap()is stupid and will happily ignore unsupported arguments. This means that if the binary were to be compiled on a 3.8+ kernel but run on a pre-3.8 kernel (such as currently supported minimum of 3.2), then most likely the memory would be allocated using regular pages, causing unthinkable performance degradation. No solution to this problem is currently known to me.
v3 cover Support running DPDK without hugetlbfs mountpoint
In reply to Anatoly BurakovThis patchset adds a new command-line option "--in-memory", which takes old debug options "--huge-unlink" and "--no-shconf", and enhances them with additional functionality. This will allow DPDK to reserve hugepages anonymously instead of using hugetlbfs mountpoints. Coupled with the fact that this option also effectively enables both "--no-shconf" and "--huge-unlink" modes, DPDK will be able to run entirely in memory and not create any shared files while running - neither hugepages nor any runtime data.
This will, of course, disable secondary processes, but for use-cases this is targeted at (containers etc.), this is not a problem.
Older revisions had kernel support at 4.14+ and also required a fairly new glibc, but now due to not using memfd and using mmap() instead, minimum supported kernel version has dropped to 3.8.
v2->v3 changes:
- Fix compile issue in patch 9 (now 8)
- Drop deprecation notice (will be sent separately)
v1->v2 changes:
- Rebase on latest master
- Fix patch 5 to include check from patch 6 as commit message states
RFC->v1 changes:
- Dropped memfd, using anonymous mmap() instead
- Do not deprecate old command-line parameters, instead use them as they are, and add a deprecation notice to remove them in the next release.
Anatoly Burakov (8):
fbarray: support no-shconf mode
ipc: add support for no-shconf mode
eal: add support for no-shconf for hugepage info
eal: add support for no-shconf in hugepage data file
eal: do not create runtime dir in no-shconf mode
mem: add support for hugepage-unlink mode
eal: add --in-memory option
mem: support in-memory mode
lib/librte_eal/bsdapp/eal/eal.c | 3 +- lib/librte_eal/bsdapp/eal/eal_hugepage_info.c | 4 + lib/librte_eal/common/eal_common_fbarray.c | 71 +++++---- lib/librte_eal/common/eal_common_options.c | 20 ++- lib/librte_eal/common/eal_common_proc.c | 25 +++ lib/librte_eal/common/eal_internal_cfg.h | 4 + lib/librte_eal/common/eal_options.h | 2 + lib/librte_eal/linuxapp/eal/eal.c | 3 +- .../linuxapp/eal/eal_hugepage_info.c | 95 +++++++---- lib/librte_eal/linuxapp/eal/eal_memalloc.c | 150 ++++++++++++------ lib/librte_eal/linuxapp/eal/eal_memory.c | 16 +- 11 files changed, 276 insertions(+), 117 deletions(-)
Signature · 1 line
2.17.1
PATCH v3 1/8 fbarray: support no-shconf mode
When using --no-shconf option, the expectation is that no multiprocess will be supported as no shared files are created. However, fbarray still creates some shared files that prevent multiple processes with the same prefix from starting.
Fix this by avoiding creating shared files whenever noshconf option is specified. Since virtual areas we get from eal_get_virtual_area() are read-only, remap them as writable.
---
Notes:
RFC->v1:
- Use --no-shconf only
lib/librte_eal/common/eal_common_fbarray.c | 71 +++++++++++++--------- 1 file changed, 42 insertions(+), 29 deletions(-)
lib/librte_eal/common/eal_common_fbarray.c +42 -29
@@ -705,39 +705,52 @@ rte_fbarray_init(struct rte_fbarray *arr, const char *name, unsigned int len,if (data ==NULL ) goto fail; -eal_get_fbarray_path (path,sizeof (path), name); +if (internal_config.no_shconf) { +/* remap virtual area as writable */ +void *new_data =mmap (data, mmap_len,PROT_READ |PROT_WRITE , +MAP_FIXED |MAP_PRIVATE |MAP_ANONYMOUS ,-1 ,0 ); +if (new_data ==MAP_FAILED ) { +RTE_LOG (DEBUG ,EAL ,"%s(): couldn't remap anonymous memory: %s\n" , + __func__,strerror (errno)); + goto fail; + } + }else { +eal_get_fbarray_path (path,sizeof (path), name); -/* -* Each fbarray is unique to process namespace, i.e. the filename -* depends on process prefix. Try to take out a lock and see if we -* succeed. If we don't, someone else is using it already. -*/ - fd =open (path,O_CREAT |O_RDWR ,0600 ); -if (fd <0 ) { -RTE_LOG (DEBUG ,EAL ,"%s(): couldn't open %s: %s\n" , __func__, - path,strerror (errno)); - rte_errno = errno; - goto fail; - }else if (flock (fd,LOCK_EX |LOCK_NB )) { -RTE_LOG (DEBUG ,EAL ,"%s(): couldn't lock %s: %s\n" , __func__, - path,strerror (errno)); - rte_errno =EBUSY ; - goto fail; - } +/* +* Each fbarray is unique to process namespace, i.e. the +* filename depends on process prefix. Try to take out a lock +* and see if we succeed. If we don't, someone else is using it +* already. +*/ + fd =open (path,O_CREAT |O_RDWR ,0600 ); +if (fd <0 ) { +RTE_LOG (DEBUG ,EAL ,"%s(): couldn't open %s: %s\n" , + __func__, path,strerror (errno)); + rte_errno = errno; + goto fail; + }else if (flock (fd,LOCK_EX |LOCK_NB )) { +RTE_LOG (DEBUG ,EAL ,"%s(): couldn't lock %s: %s\n" , + __func__, path,strerror (errno)); + rte_errno =EBUSY ; + goto fail; + } -/* take out a non-exclusive lock, so that other processes could still -* attach to it, but no other process could reinitialize it. -*/ -if (flock (fd,LOCK_SH |LOCK_NB )) { - rte_errno = errno; - goto fail; - } +/* take out a non-exclusive lock, so that other processes could +* still attach to it, but no other process could reinitialize +* it. +*/ +if (flock (fd,LOCK_SH |LOCK_NB )) { + rte_errno = errno; + goto fail; + } -if (resize_and_map (fd, data, mmap_len)) - goto fail; +if (resize_and_map (fd, data, mmap_len)) + goto fail; -/* we've mmap'ed the file, we can now close the fd */ -close (fd); +/* we've mmap'ed the file, we can now close the fd */ +close (fd); + }/* initialize the data */ memset (data,0 , mmap_len);
Signature · 1 line
2.17.1
PATCH v3 2/8 ipc: add support for no-shconf mode
In reply to Anatoly BurakovIPC is an inter-process communication mechanism. Since no secondaries can ever be expected to run in no-shconf mode, IPC will be useless, so do not enable it in the first place. In the interests of API usage convenience, we will still allow registering callbacks, but obviously they won't ever be triggered.
---
Notes:
RFC->v1:
- Use --no-shconf only
lib/librte_eal/common/eal_common_proc.c | 25 +++++++++++++++++++++++++ 1 file changed, 25 insertions(+)
lib/librte_eal/common/eal_common_proc.c +25 -0
@@ -626,6 +626,14 @@ rte_mp_channel_init(void)int dir_fd;pthread_t mp_handle_tid, async_reply_handle_tid; +/* in no shared files mode, we do not have secondary processes support, +* so no need to initialize IPC. +*/ +if (internal_config.no_shconf) { +RTE_LOG (DEBUG ,EAL ,"No shared files mode enabled, IPC will be disabled\n" ); +return 0 ; + } +/* create filter path */ create_socket_path ("*" , path,sizeof (path));strlcpy (mp_filter,basename (path),sizeof (mp_filter));
@@ -988,6 +996,12 @@ rte_mp_request_sync(struct rte_mp_msg *req, struct rte_mp_reply *reply,if (check_input (req) == false)return -1 ; + +if (internal_config.no_shconf) { +RTE_LOG (DEBUG ,EAL ,"No shared files mode enabled, IPC is disabled\n" ); +return 0 ; + } +if (gettimeofday (&now,NULL ) <0 ) {RTE_LOG (ERR ,EAL ,"Faile to get current time\n" ); rte_errno = errno;
@@ -1072,6 +1086,12 @@ rte_mp_request_async(struct rte_mp_msg *req, const struct timespec *ts,if (check_input (req) == false)return -1 ; + +if (internal_config.no_shconf) { +RTE_LOG (DEBUG ,EAL ,"No shared files mode enabled, IPC is disabled\n" ); +return 0 ; + } +if (gettimeofday (&now,NULL ) <0 ) {RTE_LOG (ERR ,EAL ,"Faile to get current time\n" ); rte_errno = errno;
@@ -1213,5 +1233,10 @@ rte_mp_reply(struct rte_mp_msg *msg, const char *peer)return -1 ; } +if (internal_config.no_shconf) { +RTE_LOG (DEBUG ,EAL ,"No shared files mode enabled, IPC is disabled\n" ); +return 0 ; + } +return mp_send (msg, peer,MP_REP ); }
Signature · 1 line
2.17.1
PATCH v3 3/8 eal: add support for no-shconf for hugepage info
In reply to Anatoly BurakovDo not create any shared hugepage size info files if we were asked to not create any shared files.
---
Notes:
RFC->v1:
- Use --no-shconf only
lib/librte_eal/bsdapp/eal/eal_hugepage_info.c | 4 ++++ lib/librte_eal/linuxapp/eal/eal_hugepage_info.c | 4 ++++ 2 files changed, 8 insertions(+)
lib/librte_eal/bsdapp/eal/eal_hugepage_info.c +4 -0
@@ -101,6 +101,10 @@ eal_hugepage_info_init(void) hpi->num_pages[0 ] = num_buffers; hpi->lock_descriptor = fd; +/* for no shared files mode, do not create shared memory config */ +if (internal_config.no_shconf) +return 0 ; + tmp_hpi =create_shared_memory (eal_hugepage_info_path (),sizeof (internal_config.hugepage_info));if (tmp_hpi ==NULL ) {
lib/librte_eal/linuxapp/eal/eal_hugepage_info.c +4 -0
@@ -446,6 +446,10 @@ eal_hugepage_info_init(void)if (hugepage_info_init () <0 )return -1 ; +/* for no shared files mode, we're done */ +if (internal_config.no_shconf) +return 0 ; + hpi = &internal_config.hugepage_info[0 ]; tmp_hpi = create_shared_memory(eal_hugepage_info_path(),
Signature · 1 line
2.17.1
PATCH v3 4/8 eal: add support for no-shconf in hugepage data file
In reply to Anatoly BurakovDo not create a shared hugepage data file if we were asked to not create any shared files.
---
Notes:
RFC->v1:
- Use --no-shconf only
lib/librte_eal/linuxapp/eal/eal_memory.c | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-)
lib/librte_eal/linuxapp/eal/eal_memory.c +12 -1
@@ -521,7 +521,18 @@ static void * create_shared_memory(const char *filename, const size_t mem_size) { void *retval; -int fd =open (filename,O_CREAT |O_RDWR ,0666 ); +int fd; + +/* if no shared files mode is used, create anonymous memory instead */ +if (internal_config.no_shconf) { + retval =mmap (NULL , mem_size,PROT_READ |PROT_WRITE , +MAP_PRIVATE |MAP_ANONYMOUS ,-1 ,0 ); +if (retval ==MAP_FAILED ) +return NULL ; +return retval; + } + + fd =open (filename,O_CREAT |O_RDWR ,0666 );if (fd <0 )return NULL ;if (ftruncate (fd, mem_size) <0 ) {
Signature · 1 line
2.17.1
PATCH v3 5/8 eal: do not create runtime dir in no-shconf mode
In reply to Anatoly BurakovNow that the rest of the EAL is adjusted to not create any shared files, prevent runtime directory from ever being created.
---
Notes:
RFC->v1:
- Use --no-shconf only
lib/librte_eal/bsdapp/eal/eal.c | 3 ++- lib/librte_eal/linuxapp/eal/eal.c | 3 ++- 2 files changed, 4 insertions(+), 2 deletions(-)
lib/librte_eal/bsdapp/eal/eal.c +2 -1
@@ -601,7 +601,8 @@ rte_eal_init(int argc, char **argv) }/* create runtime data directory */ -if (eal_create_runtime_dir () <0 ) { +if (internal_config.no_shconf ==0 && +eal_create_runtime_dir () <0 ) {rte_eal_init_alert ("Cannot create runtime directory\n" ); rte_errno =EACCES ;return -1 ;
lib/librte_eal/linuxapp/eal/eal.c +2 -1
@@ -832,7 +832,8 @@ rte_eal_init(int argc, char **argv) }/* create runtime data directory */ -if (eal_create_runtime_dir () <0 ) { +if (internal_config.no_shconf ==0 && +eal_create_runtime_dir () <0 ) {rte_eal_init_alert ("Cannot create runtime directory\n" ); rte_errno =EACCES ;return -1 ;
Signature · 1 line
2.17.1
PATCH v3 6/8 mem: add support for hugepage-unlink mode
In reply to Anatoly BurakovUnlink hugepages after creating them, to honor the hugepage-unlink mode. We cannot resize non-existing files, so make single file segments explicitly unsupported.
---
Notes:
v1->v2:
- Move check for hugepage unlink into this patch, to be consistent with commit message
RFC->v1:
- Use --huge-unlink only
RFC->v1:
- Use --huge-unlink only
lib/librte_eal/common/eal_common_options.c | 6 ++++++ lib/librte_eal/linuxapp/eal/eal_memalloc.c | 16 +++++++++++++++- 2 files changed, 21 insertions(+), 1 deletion(-)
lib/librte_eal/common/eal_common_options.c +6 -0
@@ -1332,6 +1332,12 @@ eal_check_common_options(struct internal_config *internal_cfg) " is only supported in non-legacy memory mode\n");return -1 ; } +if (internal_cfg->single_file_segments && + internal_cfg->hugepage_unlink) { +RTE_LOG (ERR ,EAL ,"Option --" OPT_SINGLE_FILE_SEGMENTS " is " +"not compatible with --" OPT_HUGE_UNLINK "\n" ); +return -1 ; + }return 0 ; }
lib/librte_eal/linuxapp/eal/eal_memalloc.c +15 -1
@@ -489,6 +489,13 @@ alloc_seg(struct rte_memseg *ms, void *addr, int socket_id, __func__, strerror(errno)); goto resized; } +if (internal_config.hugepage_unlink) { +if (unlink (path)) { +RTE_LOG (DEBUG ,EAL ,"%s(): unlink() failed: %s\n" , + __func__,strerror (errno)); + goto resized; + } + } }/*
@@ -587,7 +594,8 @@ alloc_seg(struct rte_memseg *ms, void *addr, int socket_id,/* ignore failure, can't make it any worse */ }else {/* only remove file if we can take out a write lock */ -if (lock (fd,LOCK_EX ) ==1 ) +if (internal_config.hugepage_unlink ==0 && +lock (fd,LOCK_EX ) ==1 )unlink (path);close (fd); }
@@ -612,6 +620,12 @@ free_seg(struct rte_memseg *ms, struct hugepage_info *hi,return -1 ; } +/* if we've already unlinked the page, nothing needs to be done */ +if (internal_config.hugepage_unlink) { +memset (ms,0 ,sizeof (*ms)); +return 0 ; + } +/* if we are not in single file segments mode, we're going to unmap the * segment and thus drop the lock on original fd, but hugepage dir is * now locked so we can take out another one without races.
Signature · 1 line
2.17.1
PATCH v3 7/8 eal: add --in-memory option
In reply to Anatoly BurakovThis command-line option will cause DPDK to operate entirely in memory and not create any shared files at runtime, including any shared configuration or hugetlbfs files. This is useful for debug purposes, as well as for certain use cases like containers or automatic memory cleanup.
Currently, this option acts as a strict superset of --no-shconf and --huge-unlink commands.
---
Notes:
RFC->v1:
- Do not deprecate old options, instead just coopt them
lib/librte_eal/common/eal_common_options.c | 18 ++++++++++++++---- lib/librte_eal/common/eal_internal_cfg.h | 4 ++++ lib/librte_eal/common/eal_options.h | 2 ++ 3 files changed, 20 insertions(+), 4 deletions(-)
lib/librte_eal/common/eal_common_options.c +14 -4
@@ -66,6 +66,7 @@ eal_long_options[] = { {OPT_NO_HUGE, 0, NULL, OPT_NO_HUGE_NUM }, {OPT_NO_PCI, 0, NULL, OPT_NO_PCI_NUM }, {OPT_NO_SHCONF, 0, NULL, OPT_NO_SHCONF_NUM }, + {OPT_IN_MEMORY, 0, NULL, OPT_IN_MEMORY_NUM }, {OPT_PCI_BLACKLIST, 1, NULL, OPT_PCI_BLACKLIST_NUM }, {OPT_PCI_WHITELIST, 1, NULL, OPT_PCI_WHITELIST_NUM }, {OPT_PROC_TYPE, 1, NULL, OPT_PROC_TYPE_NUM },
@@ -1170,6 +1171,13 @@ eal_parse_common_option(int opt, const char *optarg, conf->no_shconf =1 ;break ; +case OPT_IN_MEMORY_NUM : + conf->in_memory =1 ; +/* in-memory is a superset of noshconf and huge-unlink */ + conf->no_shconf =1 ; + conf->hugepage_unlink =1 ; +break ; +case OPT_PROC_TYPE_NUM : conf->process_type =eal_parse_proc_type (optarg);break ;
@@ -1321,8 +1329,8 @@ eal_check_common_options(struct internal_config *internal_cfg) "be specified together with --"OPT_NO_HUGE"\n");return -1 ; } - -if (internal_cfg->no_hugetlbfs && internal_cfg->hugepage_unlink) { +if (internal_cfg->no_hugetlbfs && internal_cfg->hugepage_unlink && + !internal_cfg->in_memory) {RTE_LOG (ERR ,EAL ,"Option --" OPT_HUGE_UNLINK " cannot " "be specified together with --" OPT_NO_HUGE "\n" );return -1 ;
@@ -1330,12 +1338,12 @@ eal_check_common_options(struct internal_config *internal_cfg)if (internal_config.force_socket_limits && internal_config.legacy_mem) {RTE_LOG (ERR ,EAL ,"Option --" OPT_SOCKET_LIMIT " is only supported in non-legacy memory mode\n" ); -return -1 ; }if (internal_cfg->single_file_segments && internal_cfg->hugepage_unlink) {RTE_LOG (ERR ,EAL ,"Option --" OPT_SINGLE_FILE_SEGMENTS " is " -"not compatible with --" OPT_HUGE_UNLINK "\n" ); +"not compatible with neither --" OPT_IN_MEMORY " nor " +"--" OPT_HUGE_UNLINK "\n" );return -1 ; }
@@ -1386,6 +1394,8 @@ eal_common_usage(void)" Set specific log level\n" " -v Display version information on startup\n" " -h, --help This help\n" +" --" OPT_IN_MEMORY " Operate entirely in memory. This will \n" +" disable secondary process support\n" "\nEAL options for DEBUG use only:\n" " --" OPT_HUGE_UNLINK " Unlink hugepage files after init\n" " --" OPT_NO_HUGE " Use malloc instead of hugetlbfs\n"
lib/librte_eal/common/eal_internal_cfg.h +4 -0
@@ -41,6 +41,10 @@ struct internal_config {volatile unsigned vmware_tsc_map;/**< true to use VMware TSC mapping * instead of native TSC */ volatile unsigned no_shconf;/**< true if there is no shared config */ +volatile unsigned in_memory; +/**< true if DPDK should operate entirely in-memory and not create any +* shared files or runtime data. +*/ volatile unsigned create_uio_dev;/**< true to create /dev/uioX devices */ volatile enum rte_proc_type_t process_type;/**< multi-process proc type */ /** true to try allocating memory on specific sockets */
lib/librte_eal/common/eal_options.h +2 -0
@@ -45,6 +45,8 @@ enum {OPT_NO_PCI_NUM , #define OPT_NO_SHCONF "no-shconf"OPT_NO_SHCONF_NUM , +#define OPT_IN_MEMORY "in-memory" +OPT_IN_MEMORY_NUM , #define OPT_SOCKET_MEM "socket-mem"OPT_SOCKET_MEM_NUM , #define OPT_SOCKET_LIMIT "socket-limit"
Signature · 1 line
2.17.1
PATCH v3 8/8 mem: support in-memory mode
In reply to Anatoly BurakovImplement the final piece of the in-memory mode puzzle - enable running DPDK entirely in memory, without creating any files.
To do it, use mmap with MAP_HUGETLB and size flags to enable DPDK to work without hugetlbfs mountpoints. In order to enable this, a few things needed to be changed.
First of all, we need to allow empty hugetlbfs mountpoints in hugepage_info, and handle them correctly (by not trying to create any files and lock any directories).
Next, we need to reorder the mapping sequence, because the page is not really allocated until the page fault, and we cannot get its IOVA address before we trigger the page fault.
Finally, decide at compile time whether we are going to be supporting anonymous hugepages or not, because we cannot check for it at runtime.
---
Notes:
RFC->v1:
- Drop memfd and instead use mmap() with MAP_HUGETLB. This will drop the kernel requirements down to 3.8, and does not impose any restrictions glibc (as far as i known).
Unfortunately, there's a bit of an issue with this approach, because mmap() is stupid and will happily ignore unsupported arguments. This means that if the binary were to be compiled on a 3.8+ kernel but run on a pre-3.8 kernel (such as currently supported minimum of 3.2), then most likely the memory would be allocated using regular pages, causing unthinkable performance degradation. No solution to this problem is currently known to me.
.../linuxapp/eal/eal_hugepage_info.c | 91 ++++++++---- lib/librte_eal/linuxapp/eal/eal_memalloc.c | 140 +++++++++++------- lib/librte_eal/linuxapp/eal/eal_memory.c | 3 +- 3 files changed, 149 insertions(+), 85 deletions(-)
lib/librte_eal/linuxapp/eal/eal_hugepage_info.c +59 -32
@@ -18,6 +18,8 @@#include <sys/queue.h> #include <sys/stat.h> +#include <linux/mman.h> /* for hugetlb-related flags */ +#include <rte_memory.h> #include <rte_eal.h> #include <rte_launch.h>
@@ -313,11 +315,49 @@ compare_hpi(const void *a, const void *b)return hpi_b->hugepage_sz - hpi_a->hugepage_sz; } +static void +calc_num_pages (struct hugepage_info *hpi,struct dirent *dirent) +{ +uint64_t total_pages =0 ; +unsigned int i; + +/* +* first, try to put all hugepages into relevant sockets, but +* if first attempts fails, fall back to collecting all pages +* in one socket and sorting them later +*/ + total_pages =0 ; +/* we also don't want to do this for legacy init */ +if (!internal_config.legacy_mem) +for (i =0 ; i <rte_socket_count (); i++) { +int socket =rte_socket_id_by_idx (i); +unsigned int num_pages = +get_num_hugepages_on_node ( + dirent->d_name, socket); + hpi->num_pages[socket] = num_pages; + total_pages += num_pages; + } +/* +* we failed to sort memory from the get go, so fall +* back to old way +*/ +if (total_pages ==0 ) { + hpi->num_pages[0 ] =get_num_hugepages (dirent->d_name); + +#ifndef RTE_ARCH_64 +/* for 32-bit systems, limit number of hugepages to +* 1GB per page size */ + hpi->num_pages[0 ] =RTE_MIN (hpi->num_pages[0 ], +RTE_PGSIZE_1G / hpi->hugepage_sz); +#endif + } +} +static int hugepage_info_init (void ) {const char dirent_start_text[] ="hugepages-" ;const size_t dirent_start_len =sizeof (dirent_start_text) -1 ; -unsigned int i, total_pages, num_sizes =0 ; +unsigned int i, num_sizes =0 ;DIR *dir;struct dirent *dirent;
@@ -355,6 +395,22 @@ hugepage_info_init(void)"%" PRIu64" reserved, but no mounted " "hugetlbfs found for that size\n" , num_pages, hpi->hugepage_sz); +/* if we have kernel support for reserving hugepages +* through mmap, and we're in in-memory mode, treat this +* page size as valid. we cannot be in legacy mode at +* this point because we've checked this earlier in the +* init process. +*/ +#ifdef MAP_HUGE_SHIFT +if (internal_config.in_memory) { +RTE_LOG (DEBUG ,EAL ,"In-memory mode enabled, " +"hugepages of size %" PRIu64" bytes " +"will be allocated anonymously\n" , + hpi->hugepage_sz); +calc_num_pages (hpi, dirent); + num_sizes++; + } +#endif continue ; }
@@ -371,35 +427,7 @@ hugepage_info_init(void)if (clear_hugedir (hpi->hugedir) ==-1 )break ; -/* -* first, try to put all hugepages into relevant sockets, but -* if first attempts fails, fall back to collecting all pages -* in one socket and sorting them later -*/ - total_pages =0 ; -/* we also don't want to do this for legacy init */ -if (!internal_config.legacy_mem) -for (i =0 ; i <rte_socket_count (); i++) { -int socket =rte_socket_id_by_idx (i); -unsigned int num_pages = -get_num_hugepages_on_node ( - dirent->d_name, socket); - hpi->num_pages[socket] = num_pages; - total_pages += num_pages; - } -/* -* we failed to sort memory from the get go, so fall -* back to old way -*/ -if (total_pages ==0 ) - hpi->num_pages[0 ] =get_num_hugepages (dirent->d_name); - -#ifndef RTE_ARCH_64 -/* for 32-bit systems, limit number of hugepages to -* 1GB per page size */ - hpi->num_pages[0 ] =RTE_MIN (hpi->num_pages[0 ], -RTE_PGSIZE_1G / hpi->hugepage_sz); -#endif +calc_num_pages (hpi, dirent); num_sizes++; }
@@ -423,8 +451,7 @@ hugepage_info_init(void)for (j =0 ; j <RTE_MAX_NUMA_NODES ; j++) num_pages += hpi->num_pages[j]; -if (strnlen (hpi->hugedir,sizeof (hpi->hugedir)) !=0 && - num_pages >0 ) +if (num_pages >0 )return 0 ; }
lib/librte_eal/linuxapp/eal/eal_memalloc.c +89 -51
215 lines not on this page · raw message
lib/librte_eal/linuxapp/eal/eal_memory.c +1 -2
@@ -1088,8 +1088,7 @@ get_socket_mem_size(int socket)for (i =0 ; i < internal_config.num_hugepage_sizes; i++){struct hugepage_info *hpi = &internal_config.hugepage_info[i]; -if (strnlen (hpi->hugedir,sizeof (hpi->hugedir)) !=0 ) - size += hpi->hugepage_sz * hpi->num_pages[socket]; + size += hpi->hugepage_sz * hpi->num_pages[socket]; }return size;
Signature · 1 line
2.17.1
Thomas Monjalon
AppliedQuoted 9 lines
Anatoly Burakov (8):
fbarray: support no-shconf mode
ipc: add support for no-shconf mode
eal: add support for no-shconf for hugepage info
eal: add support for no-shconf in hugepage data file
eal: do not create runtime dir in no-shconf mode
mem: add support for hugepage-unlink mode
eal: add --in-memory option
mem: support in-memory mode
Applied, thanks.