Imported Upstream version 16.11
[deb_dpdk.git] / lib / librte_ivshmem / rte_ivshmem.c
diff --git a/lib/librte_ivshmem/rte_ivshmem.c b/lib/librte_ivshmem/rte_ivshmem.c
deleted file mode 100644 (file)
index c26edb6..0000000
+++ /dev/null
@@ -1,919 +0,0 @@
-/*-
- *   BSD LICENSE
- *
- *   Copyright(c) 2010-2014 Intel Corporation. All rights reserved.
- *   All rights reserved.
- *
- *   Redistribution and use in source and binary forms, with or without
- *   modification, are permitted provided that the following conditions
- *   are met:
- *
- *     * Redistributions of source code must retain the above copyright
- *       notice, this list of conditions and the following disclaimer.
- *     * Redistributions in binary form must reproduce the above copyright
- *       notice, this list of conditions and the following disclaimer in
- *       the documentation and/or other materials provided with the
- *       distribution.
- *     * Neither the name of Intel Corporation nor the names of its
- *       contributors may be used to endorse or promote products derived
- *       from this software without specific prior written permission.
- *
- *   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- *   "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- *   LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- *   A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- *   OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- *   SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- *   LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- *   DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- *   THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- *   (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- *   OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-#include <fcntl.h>
-#include <limits.h>
-#include <unistd.h>
-#include <sys/mman.h>
-#include <string.h>
-#include <stdio.h>
-
-#include <rte_eal_memconfig.h>
-#include <rte_memory.h>
-#include <rte_ivshmem.h>
-#include <rte_string_fns.h>
-#include <rte_common.h>
-#include <rte_log.h>
-#include <rte_debug.h>
-#include <rte_spinlock.h>
-#include <rte_common.h>
-#include <rte_malloc.h>
-
-#include "rte_ivshmem.h"
-
-#define IVSHMEM_CONFIG_FILE_FMT "/var/run/.dpdk_ivshmem_metadata_%s"
-#define IVSHMEM_QEMU_CMD_LINE_HEADER_FMT "-device ivshmem,size=%" PRIu64 "M,shm=fd%s"
-#define IVSHMEM_QEMU_CMD_FD_FMT ":%s:0x%" PRIx64 ":0x%" PRIx64
-#define IVSHMEM_QEMU_CMDLINE_BUFSIZE 1024
-#define IVSHMEM_MAX_PAGES (1 << 12)
-#define adjacent(x,y) (((x).phys_addr+(x).len)==(y).phys_addr)
-#define METADATA_SIZE_ALIGNED \
-       (RTE_ALIGN_CEIL(sizeof(struct rte_ivshmem_metadata),pagesz))
-
-#define GET_PAGEMAP_ADDR(in,addr,dlm,err)    \
-{                                      \
-       char *end;                         \
-       errno = 0;                         \
-       addr = strtoull((in), &end, 16);   \
-       if (errno != 0 || *end != (dlm)) { \
-               RTE_LOG(ERR, EAL, err);        \
-               goto error;                    \
-       }                                  \
-       (in) = end + 1;                    \
-}
-
-static int pagesz;
-
-struct memseg_cache_entry {
-       char filepath[PATH_MAX];
-       uint64_t offset;
-       uint64_t len;
-};
-
-struct ivshmem_config {
-       struct rte_ivshmem_metadata * metadata;
-       struct memseg_cache_entry memseg_cache[IVSHMEM_MAX_PAGES];
-               /**< account for multiple files per segment case */
-       struct flock lock;
-       rte_spinlock_t sl;
-};
-
-static struct ivshmem_config
-ivshmem_global_config[RTE_LIBRTE_IVSHMEM_MAX_METADATA_FILES];
-
-static rte_spinlock_t global_cfg_sl;
-
-static struct ivshmem_config *
-get_config_by_name(const char * name)
-{
-       struct rte_ivshmem_metadata * config;
-       unsigned i;
-
-       for (i = 0; i < RTE_DIM(ivshmem_global_config); i++) {
-               config = ivshmem_global_config[i].metadata;
-               if (config == NULL)
-                       return NULL;
-               if (strncmp(name, config->name, IVSHMEM_NAME_LEN) == 0)
-                       return &ivshmem_global_config[i];
-       }
-
-       return NULL;
-}
-
-static int
-overlap(const struct rte_memzone * s1, const struct rte_memzone * s2)
-{
-       uint64_t start1, end1, start2, end2;
-
-       start1 = s1->addr_64;
-       end1 = s1->addr_64 + s1->len;
-       start2 = s2->addr_64;
-       end2 = s2->addr_64 + s2->len;
-
-       if (start1 >= start2 && start1 < end2)
-               return 1;
-       if (start2 >= start1 && start2 < end1)
-               return 1;
-
-       return 0;
-}
-
-static struct rte_memzone *
-get_memzone_by_addr(const void * addr)
-{
-       struct rte_memzone * tmp, * mz;
-       struct rte_mem_config * mcfg;
-       int i;
-
-       mcfg = rte_eal_get_configuration()->mem_config;
-       mz = NULL;
-
-       /* find memzone for the ring */
-       for (i = 0; i < RTE_MAX_MEMZONE; i++) {
-               tmp = &mcfg->memzone[i];
-
-               if (tmp->addr_64 == (uint64_t) addr) {
-                       mz = tmp;
-                       break;
-               }
-       }
-
-       return mz;
-}
-
-static int
-entry_compare(const void * a, const void * b)
-{
-       const struct rte_ivshmem_metadata_entry * e1 =
-                       (const struct rte_ivshmem_metadata_entry*) a;
-       const struct rte_ivshmem_metadata_entry * e2 =
-                       (const struct rte_ivshmem_metadata_entry*) b;
-
-       /* move unallocated zones to the end */
-       if (e1->mz.addr == NULL && e2->mz.addr == NULL)
-               return 0;
-       if (e1->mz.addr == 0)
-               return 1;
-       if (e2->mz.addr == 0)
-               return -1;
-
-       return e1->mz.phys_addr > e2->mz.phys_addr;
-}
-
-/* fills hugepage cache entry for a given start virt_addr */
-static int
-get_hugefile_by_virt_addr(uint64_t virt_addr, struct memseg_cache_entry * e)
-{
-       uint64_t start_addr, end_addr;
-       char *start,*path_end;
-       char buf[PATH_MAX*2];
-       FILE *f;
-
-       start = NULL;
-       path_end = NULL;
-       start_addr = 0;
-
-       memset(e->filepath, 0, sizeof(e->filepath));
-
-       /* open /proc/self/maps */
-       f = fopen("/proc/self/maps", "r");
-       if (f == NULL) {
-               RTE_LOG(ERR, EAL, "cannot open /proc/self/maps!\n");
-               return -1;
-       }
-
-       /* parse maps */
-       while (fgets(buf, sizeof(buf), f) != NULL) {
-
-               /* get endptr to end of start addr */
-               start = buf;
-
-               GET_PAGEMAP_ADDR(start,start_addr,'-',
-                               "Cannot find start address in maps!\n");
-
-               /* if start address is bigger than our address, skip */
-               if (start_addr > virt_addr)
-                       continue;
-
-               GET_PAGEMAP_ADDR(start,end_addr,' ',
-                               "Cannot find end address in maps!\n");
-
-               /* if end address is less than our address, skip */
-               if (end_addr <= virt_addr)
-                       continue;
-
-               /* find where the path starts */
-               start = strstr(start, "/");
-
-               if (start == NULL)
-                       continue;
-
-               /* at this point, we know that this is our map.
-                * now let's find the file */
-               path_end = strstr(start, "\n");
-               break;
-       }
-
-       if (path_end == NULL) {
-               RTE_LOG(ERR, EAL, "Hugefile path not found!\n");
-               goto error;
-       }
-
-       /* calculate offset and copy the file path */
-       snprintf(e->filepath, RTE_PTR_DIFF(path_end, start) + 1, "%s", start);
-
-       e->offset = virt_addr - start_addr;
-
-       fclose(f);
-
-       return 0;
-error:
-       fclose(f);
-       return -1;
-}
-
-/*
- * This is a complex function. What it does is the following:
- *  1. Goes through metadata and gets list of hugepages involved
- *  2. Sorts the hugepages by size (1G first)
- *  3. Goes through metadata again and writes correct offsets
- *  4. Goes through pages and finds out their filenames, offsets etc.
- */
-static int
-build_config(struct rte_ivshmem_metadata * metadata)
-{
-       struct rte_ivshmem_metadata_entry * e_local;
-       struct memseg_cache_entry * ms_local;
-       struct rte_memseg pages[IVSHMEM_MAX_PAGES];
-       struct rte_ivshmem_metadata_entry *entry;
-       struct memseg_cache_entry * c_entry, * prev_entry;
-       struct ivshmem_config * config;
-       unsigned i, j, mz_iter, ms_iter;
-       uint64_t biggest_len;
-       int biggest_idx;
-
-       /* return error if we try to use an unknown config file */
-       config = get_config_by_name(metadata->name);
-       if (config == NULL) {
-               RTE_LOG(ERR, EAL, "Cannot find IVSHMEM config %s!\n", metadata->name);
-               goto fail_e;
-       }
-
-       memset(pages, 0, sizeof(pages));
-
-       e_local = malloc(sizeof(config->metadata->entry));
-       if (e_local == NULL)
-               goto fail_e;
-       ms_local = malloc(sizeof(config->memseg_cache));
-       if (ms_local == NULL)
-               goto fail_ms;
-
-
-       /* make local copies before doing anything */
-       memcpy(e_local, config->metadata->entry, sizeof(config->metadata->entry));
-       memcpy(ms_local, config->memseg_cache, sizeof(config->memseg_cache));
-
-       qsort(e_local, RTE_DIM(config->metadata->entry), sizeof(struct rte_ivshmem_metadata_entry),
-                       entry_compare);
-
-       /* first pass - collect all huge pages */
-       for (mz_iter = 0; mz_iter < RTE_DIM(config->metadata->entry); mz_iter++) {
-
-               entry = &e_local[mz_iter];
-
-               uint64_t start_addr = RTE_ALIGN_FLOOR(entry->mz.addr_64,
-                               entry->mz.hugepage_sz);
-               uint64_t offset = entry->mz.addr_64 - start_addr;
-               uint64_t len = RTE_ALIGN_CEIL(entry->mz.len + offset,
-                               entry->mz.hugepage_sz);
-
-               if (entry->mz.addr_64 == 0 || start_addr == 0 || len == 0)
-                       continue;
-
-               int start_page;
-
-               /* find first unused page - mz are phys_addr sorted so we don't have to
-                * look out for holes */
-               for (i = 0; i < RTE_DIM(pages); i++) {
-
-                       /* skip if we already have this page */
-                       if (pages[i].addr_64 == start_addr) {
-                               start_addr += entry->mz.hugepage_sz;
-                               len -= entry->mz.hugepage_sz;
-                               continue;
-                       }
-                       /* we found a new page */
-                       else if (pages[i].addr_64 == 0) {
-                               start_page = i;
-                               break;
-                       }
-               }
-               if (i == RTE_DIM(pages)) {
-                       RTE_LOG(ERR, EAL, "Cannot find unused page!\n");
-                       goto fail;
-               }
-
-               /* populate however many pages the memzone has */
-               for (i = start_page; i < RTE_DIM(pages) && len != 0; i++) {
-
-                       pages[i].addr_64 = start_addr;
-                       pages[i].len = entry->mz.hugepage_sz;
-                       start_addr += entry->mz.hugepage_sz;
-                       len -= entry->mz.hugepage_sz;
-               }
-               /* if there's still length left */
-               if (len != 0) {
-                       RTE_LOG(ERR, EAL, "Not enough space for pages!\n");
-                       goto fail;
-               }
-       }
-
-       /* second pass - sort pages by size */
-       for (i = 0; i < RTE_DIM(pages); i++) {
-
-               if (pages[i].addr == NULL)
-                       break;
-
-               biggest_len = 0;
-               biggest_idx = -1;
-
-               /*
-                * browse all entries starting at 'i', and find the
-                * entry with the smallest addr
-                */
-               for (j=i; j< RTE_DIM(pages); j++) {
-                       if (pages[j].addr == NULL)
-                                       break;
-                       if (biggest_len == 0 ||
-                               pages[j].len > biggest_len) {
-                               biggest_len = pages[j].len;
-                               biggest_idx = j;
-                       }
-               }
-
-               /* should not happen */
-               if (biggest_idx == -1) {
-                       RTE_LOG(ERR, EAL, "Error sorting by size!\n");
-                       goto fail;
-               }
-               if (i != (unsigned) biggest_idx) {
-                       struct rte_memseg tmp;
-
-                       memcpy(&tmp, &pages[biggest_idx], sizeof(struct rte_memseg));
-
-                       /* we don't want to break contiguousness, so instead of just
-                        * swapping segments, we move all the preceding segments to the
-                        * right and then put the old segment @ biggest_idx in place of
-                        * segment @ i */
-                       for (j = biggest_idx - 1; j >= i; j--) {
-                               memcpy(&pages[j+1], &pages[j], sizeof(struct rte_memseg));
-                               memset(&pages[j], 0, sizeof(struct rte_memseg));
-                               if (j == 0)
-                                       break;
-                       }
-
-                       /* put old biggest segment to its new place */
-                       memcpy(&pages[i], &tmp, sizeof(struct rte_memseg));
-               }
-       }
-
-       /* third pass - write correct offsets */
-       for (mz_iter = 0; mz_iter < RTE_DIM(config->metadata->entry); mz_iter++) {
-
-               uint64_t offset = 0;
-
-               entry = &e_local[mz_iter];
-
-               if (entry->mz.addr_64 == 0)
-                       break;
-
-               /* find page for current memzone */
-               for (i = 0; i < RTE_DIM(pages); i++) {
-                       /* we found our page */
-                       if (entry->mz.addr_64 >= pages[i].addr_64 &&
-                                       entry->mz.addr_64 < pages[i].addr_64 + pages[i].len) {
-                               entry->offset = (entry->mz.addr_64 - pages[i].addr_64) +
-                                               offset;
-                               break;
-                       }
-                       offset += pages[i].len;
-               }
-               if (i == RTE_DIM(pages)) {
-                       RTE_LOG(ERR, EAL, "Page not found!\n");
-                       goto fail;
-               }
-       }
-
-       ms_iter = 0;
-       prev_entry = NULL;
-
-       /* fourth pass - create proper memseg cache */
-       for (i = 0; i < RTE_DIM(pages) &&
-                       ms_iter <= RTE_DIM(config->memseg_cache); i++) {
-               if (pages[i].addr_64 == 0)
-                       break;
-
-
-               if (ms_iter == RTE_DIM(pages)) {
-                       RTE_LOG(ERR, EAL, "The universe has collapsed!\n");
-                       goto fail;
-               }
-
-               c_entry = &ms_local[ms_iter];
-               c_entry->len = pages[i].len;
-
-               if (get_hugefile_by_virt_addr(pages[i].addr_64, c_entry) < 0)
-                       goto fail;
-
-               /* if previous entry has the same filename and is contiguous,
-                * clear current entry and increase previous entry's length
-                */
-               if (prev_entry != NULL &&
-                               strncmp(c_entry->filepath, prev_entry->filepath,
-                               sizeof(c_entry->filepath)) == 0 &&
-                               prev_entry->offset + prev_entry->len == c_entry->offset) {
-                       prev_entry->len += pages[i].len;
-                       memset(c_entry, 0, sizeof(struct memseg_cache_entry));
-               }
-               else {
-                       prev_entry = c_entry;
-                       ms_iter++;
-               }
-       }
-
-       /* update current configuration with new valid data */
-       memcpy(config->metadata->entry, e_local, sizeof(config->metadata->entry));
-       memcpy(config->memseg_cache, ms_local, sizeof(config->memseg_cache));
-
-       free(ms_local);
-       free(e_local);
-
-       return 0;
-fail:
-       free(ms_local);
-fail_ms:
-       free(e_local);
-fail_e:
-       return -1;
-}
-
-static int
-add_memzone_to_metadata(const struct rte_memzone * mz,
-               struct ivshmem_config * config)
-{
-       struct rte_ivshmem_metadata_entry * entry;
-       unsigned i, idx;
-       struct rte_mem_config *mcfg;
-
-       if (mz->len == 0) {
-               RTE_LOG(ERR, EAL, "Trying to add an empty memzone\n");
-               return -1;
-       }
-
-       rte_spinlock_lock(&config->sl);
-
-       mcfg = rte_eal_get_configuration()->mem_config;
-
-       /* it prevents the memzone being freed while we add it to the metadata */
-       rte_rwlock_write_lock(&mcfg->mlock);
-
-       /* find free slot in this config */
-       for (i = 0; i < RTE_DIM(config->metadata->entry); i++) {
-               entry = &config->metadata->entry[i];
-
-               if (&entry->mz.addr_64 != 0 && overlap(mz, &entry->mz)) {
-                       RTE_LOG(ERR, EAL, "Overlapping memzones!\n");
-                       goto fail;
-               }
-
-               /* if addr is zero, the memzone is probably free */
-               if (entry->mz.addr_64 == 0) {
-                       RTE_LOG(DEBUG, EAL, "Adding memzone '%s' at %p to metadata %s\n",
-                                       mz->name, mz->addr, config->metadata->name);
-                       memcpy(&entry->mz, mz, sizeof(struct rte_memzone));
-
-                       /* run config file parser */
-                       if (build_config(config->metadata) < 0)
-                               goto fail;
-
-                       break;
-               }
-       }
-
-       /* if we reached the maximum, that means we have no place in config */
-       if (i == RTE_DIM(config->metadata->entry)) {
-               RTE_LOG(ERR, EAL, "No space left in IVSHMEM metadata %s!\n",
-                               config->metadata->name);
-               goto fail;
-       }
-
-       idx = ((uintptr_t)mz - (uintptr_t)mcfg->memzone);
-       idx = idx / sizeof(struct rte_memzone);
-
-       /* mark the memzone not freeable */
-       mcfg->memzone[idx].ioremap_addr = mz->phys_addr;
-
-       rte_rwlock_write_unlock(&mcfg->mlock);
-       rte_spinlock_unlock(&config->sl);
-       return 0;
-fail:
-       rte_rwlock_write_unlock(&mcfg->mlock);
-       rte_spinlock_unlock(&config->sl);
-       return -1;
-}
-
-static int
-add_ring_to_metadata(const struct rte_ring * r,
-               struct ivshmem_config * config)
-{
-       struct rte_memzone * mz;
-
-       mz = get_memzone_by_addr(r);
-
-       if (!mz) {
-               RTE_LOG(ERR, EAL, "Cannot find memzone for ring!\n");
-               return -1;
-       }
-
-       return add_memzone_to_metadata(mz, config);
-}
-
-static int
-add_mempool_memzone_to_metadata(const void *addr,
-               struct ivshmem_config *config)
-{
-       struct rte_memzone *mz;
-
-       mz = get_memzone_by_addr(addr);
-
-       if (!mz) {
-               RTE_LOG(ERR, EAL, "Cannot find memzone for mempool!\n");
-               return -1;
-       }
-
-       return add_memzone_to_metadata(mz, config);
-}
-
-static int
-add_mempool_to_metadata(const struct rte_mempool *mp,
-               struct ivshmem_config *config)
-{
-       struct rte_mempool_memhdr *memhdr;
-       int ret;
-
-       ret = add_mempool_memzone_to_metadata(mp, config);
-       if (ret < 0)
-               return -1;
-
-       STAILQ_FOREACH(memhdr, &mp->mem_list, next) {
-               ret = add_mempool_memzone_to_metadata(memhdr->addr, config);
-               if (ret < 0)
-                       return -1;
-       }
-
-       /* mempool consists of memzone and ring */
-       return add_ring_to_metadata(mp->pool_data, config);
-}
-
-int
-rte_ivshmem_metadata_add_ring(const struct rte_ring * r, const char * name)
-{
-       struct ivshmem_config * config;
-
-       if (name == NULL || r == NULL)
-               return -1;
-
-       config = get_config_by_name(name);
-
-       if (config == NULL) {
-               RTE_LOG(ERR, EAL, "Cannot find IVSHMEM config %s!\n", name);
-               return -1;
-       }
-
-       return add_ring_to_metadata(r, config);
-}
-
-int
-rte_ivshmem_metadata_add_memzone(const struct rte_memzone * mz, const char * name)
-{
-       struct ivshmem_config * config;
-
-       if (name == NULL || mz == NULL)
-               return -1;
-
-       config = get_config_by_name(name);
-
-       if (config == NULL) {
-               RTE_LOG(ERR, EAL, "Cannot find IVSHMEM config %s!\n", name);
-               return -1;
-       }
-
-       return add_memzone_to_metadata(mz, config);
-}
-
-int
-rte_ivshmem_metadata_add_mempool(const struct rte_mempool * mp, const char * name)
-{
-       struct ivshmem_config * config;
-
-       if (name == NULL || mp == NULL)
-               return -1;
-
-       config = get_config_by_name(name);
-
-       if (config == NULL) {
-               RTE_LOG(ERR, EAL, "Cannot find IVSHMEM config %s!\n", name);
-               return -1;
-       }
-
-       return add_mempool_to_metadata(mp, config);
-}
-
-static inline void
-ivshmem_config_path(char *buffer, size_t bufflen, const char *name)
-{
-       snprintf(buffer, bufflen, IVSHMEM_CONFIG_FILE_FMT, name);
-}
-
-
-
-static inline
-void *ivshmem_metadata_create(const char *name, size_t size,
-               struct flock *lock)
-{
-       int retval, fd;
-       void *metadata_addr;
-       char pathname[PATH_MAX];
-
-       ivshmem_config_path(pathname, sizeof(pathname), name);
-
-       fd = open(pathname, O_RDWR | O_CREAT, 0660);
-       if (fd < 0) {
-               RTE_LOG(ERR, EAL, "Cannot open '%s'\n", pathname);
-               return NULL;
-       }
-
-       size = METADATA_SIZE_ALIGNED;
-
-       retval = fcntl(fd, F_SETLK, lock);
-       if (retval < 0){
-               close(fd);
-               RTE_LOG(ERR, EAL, "Cannot create lock on '%s'. Is another "
-                               "process using it?\n", pathname);
-               return NULL;
-       }
-
-       retval = ftruncate(fd, size);
-       if (retval < 0){
-               close(fd);
-               RTE_LOG(ERR, EAL, "Cannot resize '%s'\n", pathname);
-               return NULL;
-       }
-
-       metadata_addr = mmap(NULL, size,
-                               PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);
-
-       if (metadata_addr == MAP_FAILED){
-               RTE_LOG(ERR, EAL, "Cannot mmap memory for '%s'\n", pathname);
-
-               /* we don't care if we can't unlock */
-               fcntl(fd, F_UNLCK, lock);
-               close(fd);
-
-               return NULL;
-       }
-
-       return metadata_addr;
-}
-
-int rte_ivshmem_metadata_create(const char *name)
-{
-       struct ivshmem_config * ivshmem_config;
-       unsigned index;
-
-       if (pagesz == 0)
-               pagesz = getpagesize();
-
-       if (name == NULL)
-               return -1;
-
-       rte_spinlock_lock(&global_cfg_sl);
-
-       for (index = 0; index < RTE_DIM(ivshmem_global_config); index++) {
-               if (ivshmem_global_config[index].metadata == NULL) {
-                       ivshmem_config = &ivshmem_global_config[index];
-                       break;
-               }
-       }
-
-       if (index == RTE_DIM(ivshmem_global_config)) {
-               RTE_LOG(ERR, EAL, "Cannot create more ivshmem config files. "
-               "Maximum has been reached\n");
-               rte_spinlock_unlock(&global_cfg_sl);
-               return -1;
-       }
-
-       ivshmem_config->lock.l_type = F_WRLCK;
-       ivshmem_config->lock.l_whence = SEEK_SET;
-
-       ivshmem_config->lock.l_start = 0;
-       ivshmem_config->lock.l_len = METADATA_SIZE_ALIGNED;
-
-       ivshmem_global_config[index].metadata = ((struct rte_ivshmem_metadata *)
-                       ivshmem_metadata_create(
-                                       name,
-                                       sizeof(struct rte_ivshmem_metadata),
-                                       &ivshmem_config->lock));
-
-       if (ivshmem_global_config[index].metadata == NULL) {
-               rte_spinlock_unlock(&global_cfg_sl);
-               return -1;
-       }
-
-       /* Metadata setup */
-       memset(ivshmem_config->metadata, 0, sizeof(struct rte_ivshmem_metadata));
-       ivshmem_config->metadata->magic_number = IVSHMEM_MAGIC;
-       snprintf(ivshmem_config->metadata->name,
-                       sizeof(ivshmem_config->metadata->name), "%s", name);
-
-       rte_spinlock_unlock(&global_cfg_sl);
-
-       return 0;
-}
-
-int
-rte_ivshmem_metadata_cmdline_generate(char *buffer, unsigned size, const char *name)
-{
-       const struct memseg_cache_entry * ms_cache, *entry;
-       struct ivshmem_config * config;
-       char cmdline[IVSHMEM_QEMU_CMDLINE_BUFSIZE], *cmdline_ptr;
-       char cfg_file_path[PATH_MAX];
-       unsigned remaining_len, tmplen, iter;
-       uint64_t shared_mem_size, zero_size, total_size;
-
-       if (buffer == NULL || name == NULL)
-               return -1;
-
-       config = get_config_by_name(name);
-
-       if (config == NULL) {
-               RTE_LOG(ERR, EAL, "Config %s not found!\n", name);
-               return -1;
-       }
-
-       rte_spinlock_lock(&config->sl);
-
-       /* prepare metadata file path */
-       snprintf(cfg_file_path, sizeof(cfg_file_path), IVSHMEM_CONFIG_FILE_FMT,
-                       config->metadata->name);
-
-       ms_cache = config->memseg_cache;
-
-       cmdline_ptr = cmdline;
-       remaining_len = sizeof(cmdline);
-
-       shared_mem_size = 0;
-       iter = 0;
-
-       while ((ms_cache[iter].len != 0) && (iter < RTE_DIM(config->metadata->entry))) {
-
-               entry = &ms_cache[iter];
-
-               /* Offset and sizes within the current pathname */
-               tmplen = snprintf(cmdline_ptr, remaining_len, IVSHMEM_QEMU_CMD_FD_FMT,
-                               entry->filepath, entry->offset, entry->len);
-
-               shared_mem_size += entry->len;
-
-               cmdline_ptr = RTE_PTR_ADD(cmdline_ptr, tmplen);
-               remaining_len -= tmplen;
-
-               if (remaining_len == 0) {
-                       RTE_LOG(ERR, EAL, "Command line too long!\n");
-                       rte_spinlock_unlock(&config->sl);
-                       return -1;
-               }
-
-               iter++;
-       }
-
-       total_size = rte_align64pow2(shared_mem_size + METADATA_SIZE_ALIGNED);
-       zero_size = total_size - shared_mem_size - METADATA_SIZE_ALIGNED;
-
-       /* add /dev/zero to command-line to fill the space */
-       tmplen = snprintf(cmdline_ptr, remaining_len, IVSHMEM_QEMU_CMD_FD_FMT,
-                       "/dev/zero",
-                       (uint64_t)0x0,
-                       zero_size);
-
-       cmdline_ptr = RTE_PTR_ADD(cmdline_ptr, tmplen);
-       remaining_len -= tmplen;
-
-       if (remaining_len == 0) {
-               RTE_LOG(ERR, EAL, "Command line too long!\n");
-               rte_spinlock_unlock(&config->sl);
-               return -1;
-       }
-
-       /* add metadata file to the end of command-line */
-       tmplen = snprintf(cmdline_ptr, remaining_len, IVSHMEM_QEMU_CMD_FD_FMT,
-                       cfg_file_path,
-                       (uint64_t)0x0,
-                       METADATA_SIZE_ALIGNED);
-
-       cmdline_ptr = RTE_PTR_ADD(cmdline_ptr, tmplen);
-       remaining_len -= tmplen;
-
-       if (remaining_len == 0) {
-               RTE_LOG(ERR, EAL, "Command line too long!\n");
-               rte_spinlock_unlock(&config->sl);
-               return -1;
-       }
-
-       /* if current length of the command line is bigger than the buffer supplied
-        * by the user, or if command-line is bigger than what IVSHMEM accepts */
-       if ((sizeof(cmdline) - remaining_len) > size) {
-               RTE_LOG(ERR, EAL, "Buffer is too short!\n");
-               rte_spinlock_unlock(&config->sl);
-               return -1;
-       }
-       /* complete the command-line */
-       snprintf(buffer, size,
-                       IVSHMEM_QEMU_CMD_LINE_HEADER_FMT,
-                       total_size >> 20,
-                       cmdline);
-
-       rte_spinlock_unlock(&config->sl);
-
-       return 0;
-}
-
-void
-rte_ivshmem_metadata_dump(FILE *f, const char *name)
-{
-       unsigned i = 0;
-       struct ivshmem_config * config;
-       struct rte_ivshmem_metadata_entry *entry;
-#ifdef RTE_LIBRTE_IVSHMEM_DEBUG
-       uint64_t addr;
-       uint64_t end, hugepage_sz;
-       struct memseg_cache_entry e;
-#endif
-
-       if (name == NULL)
-               return;
-
-       /* return error if we try to use an unknown config file */
-       config = get_config_by_name(name);
-       if (config == NULL) {
-               RTE_LOG(ERR, EAL, "Cannot find IVSHMEM config %s!\n", name);
-               return;
-       }
-
-       rte_spinlock_lock(&config->sl);
-
-       entry = &config->metadata->entry[0];
-
-       while (entry->mz.addr != NULL && i < RTE_DIM(config->metadata->entry)) {
-
-               fprintf(f, "Entry %u: name:<%-20s>, phys:0x%-15lx, len:0x%-15lx, "
-                       "virt:%-15p, off:0x%-15lx\n",
-                       i,
-                       entry->mz.name,
-                       entry->mz.phys_addr,
-                       entry->mz.len,
-                       entry->mz.addr,
-                       entry->offset);
-               i++;
-
-#ifdef RTE_LIBRTE_IVSHMEM_DEBUG
-               fprintf(f, "\tHugepage files:\n");
-
-               hugepage_sz = entry->mz.hugepage_sz;
-               addr = RTE_ALIGN_FLOOR(entry->mz.addr_64, hugepage_sz);
-               end = addr + RTE_ALIGN_CEIL(entry->mz.len + (entry->mz.addr_64 - addr),
-                               hugepage_sz);
-
-               for (; addr < end; addr += hugepage_sz) {
-                       memset(&e, 0, sizeof(e));
-
-                       get_hugefile_by_virt_addr(addr, &e);
-
-                       fprintf(f, "\t0x%"PRIx64 "-0x%" PRIx64 " offset: 0x%" PRIx64 " %s\n",
-                                       addr, addr + hugepage_sz, e.offset, e.filepath);
-               }
-#endif
-               entry++;
-       }
-
-       rte_spinlock_unlock(&config->sl);
-}