get:
Show a patch.

patch:
Update a patch.

put:
Update a patch.

GET /api/patches/37929/?format=api
HTTP 200 OK
Allow: GET, PUT, PATCH, HEAD, OPTIONS
Content-Type: application/json
Vary: Accept

{
    "id": 37929,
    "url": "http://patches.dpdk.org/api/patches/37929/?format=api",
    "web_url": "http://patches.dpdk.org/project/dpdk/patch/5ddc20d447039673d50c7f263157341969ba2142.1523448978.git.anatoly.burakov@intel.com/",
    "project": {
        "id": 1,
        "url": "http://patches.dpdk.org/api/projects/1/?format=api",
        "name": "DPDK",
        "link_name": "dpdk",
        "list_id": "dev.dpdk.org",
        "list_email": "dev@dpdk.org",
        "web_url": "http://core.dpdk.org",
        "scm_url": "git://dpdk.org/dpdk",
        "webscm_url": "http://git.dpdk.org/dpdk",
        "list_archive_url": "https://inbox.dpdk.org/dev",
        "list_archive_url_format": "https://inbox.dpdk.org/dev/{}",
        "commit_url_format": ""
    },
    "msgid": "<5ddc20d447039673d50c7f263157341969ba2142.1523448978.git.anatoly.burakov@intel.com>",
    "list_archive_url": "https://inbox.dpdk.org/dev/5ddc20d447039673d50c7f263157341969ba2142.1523448978.git.anatoly.burakov@intel.com",
    "date": "2018-04-11T12:30:28",
    "name": "[dpdk-dev,v6,53/70] eal: add single file segments command-line option",
    "commit_ref": null,
    "pull_url": null,
    "state": "accepted",
    "archived": true,
    "hash": "329f3c95ec15ba85bfa5666fd2247c48bf2e2f72",
    "submitter": {
        "id": 4,
        "url": "http://patches.dpdk.org/api/people/4/?format=api",
        "name": "Burakov, Anatoly",
        "email": "anatoly.burakov@intel.com"
    },
    "delegate": null,
    "mbox": "http://patches.dpdk.org/project/dpdk/patch/5ddc20d447039673d50c7f263157341969ba2142.1523448978.git.anatoly.burakov@intel.com/mbox/",
    "series": [],
    "comments": "http://patches.dpdk.org/api/patches/37929/comments/",
    "check": "success",
    "checks": "http://patches.dpdk.org/api/patches/37929/checks/",
    "tags": {},
    "related": [],
    "headers": {
        "Return-Path": "<dev-bounces@dpdk.org>",
        "X-Original-To": "patchwork@dpdk.org",
        "Delivered-To": "patchwork@dpdk.org",
        "Received": [
            "from [92.243.14.124] (localhost [127.0.0.1])\n\tby dpdk.org (Postfix) with ESMTP id 451BD1C0A5;\n\tWed, 11 Apr 2018 14:33:05 +0200 (CEST)",
            "from mga02.intel.com (mga02.intel.com [134.134.136.20])\n\tby dpdk.org (Postfix) with ESMTP id D2C3B1BBAD\n\tfor <dev@dpdk.org>; Wed, 11 Apr 2018 14:31:06 +0200 (CEST)",
            "from orsmga004.jf.intel.com ([10.7.209.38])\n\tby orsmga101.jf.intel.com with ESMTP/TLS/DHE-RSA-AES256-GCM-SHA384;\n\t11 Apr 2018 05:31:05 -0700",
            "from irvmail001.ir.intel.com ([163.33.26.43])\n\tby orsmga004.jf.intel.com with ESMTP; 11 Apr 2018 05:31:01 -0700",
            "from sivswdev01.ir.intel.com (sivswdev01.ir.intel.com\n\t[10.237.217.45])\n\tby irvmail001.ir.intel.com (8.14.3/8.13.6/MailSET/Hub) with ESMTP id\n\tw3BCV08j012534; Wed, 11 Apr 2018 13:31:00 +0100",
            "from sivswdev01.ir.intel.com (localhost [127.0.0.1])\n\tby sivswdev01.ir.intel.com with ESMTP id w3BCV0xN013930;\n\tWed, 11 Apr 2018 13:31:00 +0100",
            "(from aburakov@localhost)\n\tby sivswdev01.ir.intel.com with LOCAL id w3BCV0cR013924;\n\tWed, 11 Apr 2018 13:31:00 +0100"
        ],
        "X-Amp-Result": "SKIPPED(no attachment in message)",
        "X-Amp-File-Uploaded": "False",
        "X-ExtLoop1": "1",
        "X-IronPort-AV": "E=Sophos;i=\"5.48,436,1517904000\"; d=\"scan'208\";a=\"190642338\"",
        "From": "Anatoly Burakov <anatoly.burakov@intel.com>",
        "To": "dev@dpdk.org",
        "Cc": "keith.wiles@intel.com, jianfeng.tan@intel.com, andras.kovacs@ericsson.com,\n\tlaszlo.vadkeri@ericsson.com, benjamin.walker@intel.com,\n\tbruce.richardson@intel.com, thomas@monjalon.net,\n\tkonstantin.ananyev@intel.com, kuralamudhan.ramakrishnan@intel.com,\n\tlouise.m.daly@intel.com, nelio.laranjeiro@6wind.com,\n\tyskoh@mellanox.com, pepperjo@japf.ch, jerin.jacob@caviumnetworks.com, \n\themant.agrawal@nxp.com, olivier.matz@6wind.com, shreyansh.jain@nxp.com,\n\tgowrishankar.m@linux.vnet.ibm.com",
        "Date": "Wed, 11 Apr 2018 13:30:28 +0100",
        "Message-Id": "<5ddc20d447039673d50c7f263157341969ba2142.1523448978.git.anatoly.burakov@intel.com>",
        "X-Mailer": "git-send-email 1.7.0.7",
        "In-Reply-To": [
            "<cover.1523448978.git.anatoly.burakov@intel.com>",
            "<cover.1523448978.git.anatoly.burakov@intel.com>"
        ],
        "References": [
            "<cover.1523448978.git.anatoly.burakov@intel.com>",
            "<cover.1523296700.git.anatoly.burakov@intel.com>\n\t<cover.1523448978.git.anatoly.burakov@intel.com>"
        ],
        "Subject": "[dpdk-dev] [PATCH v6 53/70] eal: add single file segments\n\tcommand-line option",
        "X-BeenThere": "dev@dpdk.org",
        "X-Mailman-Version": "2.1.15",
        "Precedence": "list",
        "List-Id": "DPDK patches and discussions <dev.dpdk.org>",
        "List-Unsubscribe": "<https://dpdk.org/ml/options/dev>,\n\t<mailto:dev-request@dpdk.org?subject=unsubscribe>",
        "List-Archive": "<http://dpdk.org/ml/archives/dev/>",
        "List-Post": "<mailto:dev@dpdk.org>",
        "List-Help": "<mailto:dev-request@dpdk.org?subject=help>",
        "List-Subscribe": "<https://dpdk.org/ml/listinfo/dev>,\n\t<mailto:dev-request@dpdk.org?subject=subscribe>",
        "Errors-To": "dev-bounces@dpdk.org",
        "Sender": "\"dev\" <dev-bounces@dpdk.org>"
    },
    "content": "Currently, DPDK stores all pages as separate files in hugetlbfs.\nThis option will allow storing all pages in one file (one file\nper memseg list).\n\nWe do this by using fallocate() calls on FreeBSD, however this is\nonly supported on fairly recent (4.3+) kernels, so ftruncate()\nfallback is provided to grow (but not shrink) hugepage files.\nNaming scheme is deterministic, so both primary and secondary\nprocesses will be able to easily map needed files and offsets.\n\nFor multi-file segments, we can close fd's right away. For\nsingle-file segments, we can reuse the same fd and reduce the\namount of fd's needed to map/use hugepages. However, we need to\nstore the fd's somewhere, so we add a tailq.\n\nSigned-off-by: Anatoly Burakov <anatoly.burakov@intel.com>\nTested-by: Santosh Shukla <santosh.shukla@caviumnetworks.com>\nTested-by: Hemant Agrawal <hemant.agrawal@nxp.com>\nTested-by: Gowrishankar Muthukrishnan <gowrishankar.m@linux.vnet.ibm.com>\n---\n lib/librte_eal/common/eal_common_options.c |   4 +\n lib/librte_eal/common/eal_internal_cfg.h   |   4 +\n lib/librte_eal/common/eal_options.h        |   2 +\n lib/librte_eal/linuxapp/eal/eal.c          |   1 +\n lib/librte_eal/linuxapp/eal/eal_memalloc.c | 337 ++++++++++++++++++++++++-----\n 5 files changed, 297 insertions(+), 51 deletions(-)",
    "diff": "diff --git a/lib/librte_eal/common/eal_common_options.c b/lib/librte_eal/common/eal_common_options.c\nindex 5cc5a8a..e764e43 100644\n--- a/lib/librte_eal/common/eal_common_options.c\n+++ b/lib/librte_eal/common/eal_common_options.c\n@@ -74,6 +74,7 @@ eal_long_options[] = {\n \t{OPT_VFIO_INTR,         1, NULL, OPT_VFIO_INTR_NUM        },\n \t{OPT_VMWARE_TSC_MAP,    0, NULL, OPT_VMWARE_TSC_MAP_NUM   },\n \t{OPT_LEGACY_MEM,        0, NULL, OPT_LEGACY_MEM_NUM       },\n+\t{OPT_SINGLE_FILE_SEGMENTS, 0, NULL, OPT_SINGLE_FILE_SEGMENTS_NUM},\n \t{0,                     0, NULL, 0                        }\n };\n \n@@ -1190,6 +1191,9 @@ eal_parse_common_option(int opt, const char *optarg,\n \tcase OPT_LEGACY_MEM_NUM:\n \t\tconf->legacy_mem = 1;\n \t\tbreak;\n+\tcase OPT_SINGLE_FILE_SEGMENTS_NUM:\n+\t\tconf->single_file_segments = 1;\n+\t\tbreak;\n \n \t/* don't know what to do, leave this to caller */\n \tdefault:\ndiff --git a/lib/librte_eal/common/eal_internal_cfg.h b/lib/librte_eal/common/eal_internal_cfg.h\nindex 5cf7102..9d33cf4 100644\n--- a/lib/librte_eal/common/eal_internal_cfg.h\n+++ b/lib/librte_eal/common/eal_internal_cfg.h\n@@ -51,6 +51,10 @@ struct internal_config {\n \t/**< true to enable legacy memory behavior (no dynamic allocation,\n \t * IOVA-contiguous segments).\n \t */\n+\tvolatile unsigned single_file_segments;\n+\t/**< true if storing all pages within single files (per-page-size,\n+\t * per-node) non-legacy mode only.\n+\t */\n \tvolatile int syslog_facility;\t  /**< facility passed to openlog() */\n \t/** default interrupt mode for VFIO */\n \tvolatile enum rte_intr_mode vfio_intr_mode;\ndiff --git a/lib/librte_eal/common/eal_options.h b/lib/librte_eal/common/eal_options.h\nindex d301d0b..211ae06 100644\n--- a/lib/librte_eal/common/eal_options.h\n+++ b/lib/librte_eal/common/eal_options.h\n@@ -57,6 +57,8 @@ enum {\n \tOPT_VMWARE_TSC_MAP_NUM,\n #define OPT_LEGACY_MEM    \"legacy-mem\"\n \tOPT_LEGACY_MEM_NUM,\n+#define OPT_SINGLE_FILE_SEGMENTS    \"single-file-segments\"\n+\tOPT_SINGLE_FILE_SEGMENTS_NUM,\n \tOPT_LONG_MAX_NUM\n };\n \ndiff --git a/lib/librte_eal/linuxapp/eal/eal.c b/lib/librte_eal/linuxapp/eal/eal.c\nindex 9832551..2c12811 100644\n--- a/lib/librte_eal/linuxapp/eal/eal.c\n+++ b/lib/librte_eal/linuxapp/eal/eal.c\n@@ -349,6 +349,7 @@ eal_usage(const char *prgname)\n \t       \"  --\"OPT_CREATE_UIO_DEV\"    Create /dev/uioX (usually done by hotplug)\\n\"\n \t       \"  --\"OPT_VFIO_INTR\"         Interrupt mode for VFIO (legacy|msi|msix)\\n\"\n \t       \"  --\"OPT_LEGACY_MEM\"        Legacy memory mode (no dynamic allocation, contiguous segments)\\n\"\n+\t       \"  --\"OPT_SINGLE_FILE_SEGMENTS\" Put all hugepage memory in single files\\n\"\n \t       \"\\n\");\n \t/* Allow the application to print its usage message too if hook is set */\n \tif ( rte_application_usage_hook ) {\ndiff --git a/lib/librte_eal/linuxapp/eal/eal_memalloc.c b/lib/librte_eal/linuxapp/eal/eal_memalloc.c\nindex 11ef742..46b71e3 100644\n--- a/lib/librte_eal/linuxapp/eal/eal_memalloc.c\n+++ b/lib/librte_eal/linuxapp/eal/eal_memalloc.c\n@@ -39,6 +39,31 @@\n #include \"eal_internal_cfg.h\"\n #include \"eal_memalloc.h\"\n \n+/*\n+ * not all kernel version support fallocate on hugetlbfs, so fall back to\n+ * ftruncate and disallow deallocation if fallocate is not supported.\n+ */\n+static int fallocate_supported = -1; /* unknown */\n+\n+/*\n+ * If each page is in a separate file, we can close fd's since we need each fd\n+ * only once. However, in single file segments mode, we can get away with using\n+ * a single fd for entire segments, but we need to store them somewhere. Each\n+ * fd is different within each process, so we'll store them in a local tailq.\n+ */\n+struct msl_entry {\n+\tTAILQ_ENTRY(msl_entry) next;\n+\tunsigned int msl_idx;\n+\tint fd;\n+};\n+\n+/** Double linked list of memseg list fd's. */\n+TAILQ_HEAD(msl_entry_list, msl_entry);\n+\n+static struct msl_entry_list msl_entry_list =\n+\t\tTAILQ_HEAD_INITIALIZER(msl_entry_list);\n+static rte_spinlock_t tailq_lock = RTE_SPINLOCK_INITIALIZER;\n+\n static sigjmp_buf huge_jmpenv;\n \n static void __rte_unused huge_sigbus_handler(int signo __rte_unused)\n@@ -129,18 +154,100 @@ resotre_numa(int *oldpolicy, struct bitmask *oldmask)\n }\n #endif\n \n+static struct msl_entry *\n+get_msl_entry_by_idx(unsigned int list_idx)\n+{\n+\tstruct msl_entry *te;\n+\n+\trte_spinlock_lock(&tailq_lock);\n+\n+\tTAILQ_FOREACH(te, &msl_entry_list, next) {\n+\t\tif (te->msl_idx == list_idx)\n+\t\t\tbreak;\n+\t}\n+\tif (te == NULL) {\n+\t\t/* doesn't exist, so create it and set fd to -1 */\n+\n+\t\tte = malloc(sizeof(*te));\n+\t\tif (te == NULL) {\n+\t\t\tRTE_LOG(ERR, EAL, \"%s(): cannot allocate tailq entry for memseg list\\n\",\n+\t\t\t\t__func__);\n+\t\t\tgoto unlock;\n+\t\t}\n+\t\tte->msl_idx = list_idx;\n+\t\tte->fd = -1;\n+\t\tTAILQ_INSERT_TAIL(&msl_entry_list, te, next);\n+\t}\n+unlock:\n+\trte_spinlock_unlock(&tailq_lock);\n+\treturn te;\n+}\n+\n+/*\n+ * uses fstat to report the size of a file on disk\n+ */\n+static off_t\n+get_file_size(int fd)\n+{\n+\tstruct stat st;\n+\tif (fstat(fd, &st) < 0)\n+\t\treturn 0;\n+\treturn st.st_size;\n+}\n+\n+/*\n+ * uses fstat to check if file size on disk is zero (regular fstat won't show\n+ * true file size due to how fallocate works)\n+ */\n+static bool\n+is_zero_length(int fd)\n+{\n+\tstruct stat st;\n+\tif (fstat(fd, &st) < 0)\n+\t\treturn false;\n+\treturn st.st_blocks == 0;\n+}\n+\n static int\n get_seg_fd(char *path, int buflen, struct hugepage_info *hi,\n \t\tunsigned int list_idx, unsigned int seg_idx)\n {\n \tint fd;\n-\teal_get_hugefile_path(path, buflen, hi->hugedir,\n-\t\t\tlist_idx * RTE_MAX_MEMSEG_PER_LIST + seg_idx);\n-\tfd = open(path, O_CREAT | O_RDWR, 0600);\n-\tif (fd < 0) {\n-\t\tRTE_LOG(DEBUG, EAL, \"%s(): open failed: %s\\n\", __func__,\n-\t\t\t\tstrerror(errno));\n-\t\treturn -1;\n+\n+\tif (internal_config.single_file_segments) {\n+\t\t/*\n+\t\t * try to find a tailq entry, for this memseg list, or create\n+\t\t * one if it doesn't exist.\n+\t\t */\n+\t\tstruct msl_entry *te = get_msl_entry_by_idx(list_idx);\n+\t\tif (te == NULL) {\n+\t\t\tRTE_LOG(ERR, EAL, \"%s(): cannot allocate tailq entry for memseg list\\n\",\n+\t\t\t\t__func__);\n+\t\t\treturn -1;\n+\t\t} else if (te->fd < 0) {\n+\t\t\t/* create a hugepage file */\n+\t\t\teal_get_hugefile_path(path, buflen, hi->hugedir,\n+\t\t\t\t\tlist_idx);\n+\t\t\tfd = open(path, O_CREAT | O_RDWR, 0600);\n+\t\t\tif (fd < 0) {\n+\t\t\t\tRTE_LOG(DEBUG, EAL, \"%s(): open failed: %s\\n\",\n+\t\t\t\t\t__func__, strerror(errno));\n+\t\t\t\treturn -1;\n+\t\t\t}\n+\t\t\tte->fd = fd;\n+\t\t} else {\n+\t\t\tfd = te->fd;\n+\t\t}\n+\t} else {\n+\t\t/* one file per page, just create it */\n+\t\teal_get_hugefile_path(path, buflen, hi->hugedir,\n+\t\t\t\tlist_idx * RTE_MAX_MEMSEG_PER_LIST + seg_idx);\n+\t\tfd = open(path, O_CREAT | O_RDWR, 0600);\n+\t\tif (fd < 0) {\n+\t\t\tRTE_LOG(DEBUG, EAL, \"%s(): open failed: %s\\n\", __func__,\n+\t\t\t\t\tstrerror(errno));\n+\t\t\treturn -1;\n+\t\t}\n \t}\n \treturn fd;\n }\n@@ -173,6 +280,94 @@ static int lock(int fd, uint64_t offset, uint64_t len, int type)\n }\n \n static int\n+resize_hugefile(int fd, uint64_t fa_offset, uint64_t page_sz,\n+\t\tbool grow)\n+{\n+\tbool again = false;\n+\tdo {\n+\t\tif (fallocate_supported == 0) {\n+\t\t\t/* we cannot deallocate memory if fallocate() is not\n+\t\t\t * supported, but locks are still needed to prevent\n+\t\t\t * primary process' initialization from clearing out\n+\t\t\t * huge pages used by this process.\n+\t\t\t */\n+\n+\t\t\tif (!grow) {\n+\t\t\t\tRTE_LOG(DEBUG, EAL, \"%s(): fallocate not supported, not freeing page back to the system\\n\",\n+\t\t\t\t\t__func__);\n+\t\t\t\treturn -1;\n+\t\t\t}\n+\t\t\tuint64_t new_size = fa_offset + page_sz;\n+\t\t\tuint64_t cur_size = get_file_size(fd);\n+\n+\t\t\t/* fallocate isn't supported, fall back to ftruncate */\n+\t\t\tif (new_size > cur_size &&\n+\t\t\t\t\tftruncate(fd, new_size) < 0) {\n+\t\t\t\tRTE_LOG(DEBUG, EAL, \"%s(): ftruncate() failed: %s\\n\",\n+\t\t\t\t\t__func__, strerror(errno));\n+\t\t\t\treturn -1;\n+\t\t\t}\n+\t\t\t/* not being able to take out a read lock is an error */\n+\t\t\tif (lock(fd, fa_offset, page_sz, F_RDLCK) != 1)\n+\t\t\t\treturn -1;\n+\t\t} else {\n+\t\t\tint flags = grow ? 0 : FALLOC_FL_PUNCH_HOLE |\n+\t\t\t\t\tFALLOC_FL_KEEP_SIZE;\n+\t\t\tint ret;\n+\n+\t\t\t/* if fallocate() is supported, we need to take out a\n+\t\t\t * read lock on allocate (to prevent other processes\n+\t\t\t * from deallocating this page), and take out a write\n+\t\t\t * lock on deallocate (to ensure nobody else is using\n+\t\t\t * this page).\n+\t\t\t *\n+\t\t\t * we can't use flock() for this, as we actually need to\n+\t\t\t * lock part of the file, not the entire file.\n+\t\t\t */\n+\n+\t\t\tif (!grow) {\n+\t\t\t\tret = lock(fd, fa_offset, page_sz, F_WRLCK);\n+\n+\t\t\t\tif (ret < 0)\n+\t\t\t\t\treturn -1;\n+\t\t\t\telse if (ret == 0)\n+\t\t\t\t\t/* failed to lock, not an error */\n+\t\t\t\t\treturn 0;\n+\t\t\t}\n+\t\t\tif (fallocate(fd, flags, fa_offset, page_sz) < 0) {\n+\t\t\t\tif (fallocate_supported == -1 &&\n+\t\t\t\t\t\terrno == ENOTSUP) {\n+\t\t\t\t\tRTE_LOG(ERR, EAL, \"%s(): fallocate() not supported, hugepage deallocation will be disabled\\n\",\n+\t\t\t\t\t\t__func__);\n+\t\t\t\t\tagain = true;\n+\t\t\t\t\tfallocate_supported = 0;\n+\t\t\t\t} else {\n+\t\t\t\t\tRTE_LOG(DEBUG, EAL, \"%s(): fallocate() failed: %s\\n\",\n+\t\t\t\t\t\t__func__,\n+\t\t\t\t\t\tstrerror(errno));\n+\t\t\t\t\treturn -1;\n+\t\t\t\t}\n+\t\t\t} else {\n+\t\t\t\tfallocate_supported = 1;\n+\n+\t\t\t\tif (grow) {\n+\t\t\t\t\t/* if can't read lock, it's an error */\n+\t\t\t\t\tif (lock(fd, fa_offset, page_sz,\n+\t\t\t\t\t\t\tF_RDLCK) != 1)\n+\t\t\t\t\t\treturn -1;\n+\t\t\t\t} else {\n+\t\t\t\t\t/* if can't unlock, it's an error */\n+\t\t\t\t\tif (lock(fd, fa_offset, page_sz,\n+\t\t\t\t\t\t\tF_UNLCK) != 1)\n+\t\t\t\t\t\treturn -1;\n+\t\t\t\t}\n+\t\t\t}\n+\t\t}\n+\t} while (again);\n+\treturn 0;\n+}\n+\n+static int\n alloc_seg(struct rte_memseg *ms, void *addr, int socket_id,\n \t\tstruct hugepage_info *hi, unsigned int list_idx,\n \t\tunsigned int seg_idx)\n@@ -191,34 +386,40 @@ alloc_seg(struct rte_memseg *ms, void *addr, int socket_id,\n \t\treturn -1;\n \n \talloc_sz = hi->hugepage_sz;\n-\n-\tmap_offset = 0;\n-\tif (ftruncate(fd, alloc_sz) < 0) {\n-\t\tRTE_LOG(DEBUG, EAL, \"%s(): ftruncate() failed: %s\\n\",\n-\t\t\t__func__, strerror(errno));\n-\t\tgoto resized;\n-\t}\n-\t/* we've allocated a page - take out a read lock. we're using fcntl()\n-\t * locks rather than flock() here because doing that gives us one huge\n-\t * advantage - fcntl() locks are per-process, not per-file descriptor,\n-\t * which means that we don't have to keep the original fd's around to\n-\t * keep a lock on the file.\n-\t *\n-\t * this is useful, because when it comes to unmapping pages, we will\n-\t * have to take out a write lock (to figure out if another process still\n-\t * has this page mapped), and to do itwith flock() we'll have to use\n-\t * original fd, as lock is associated with that particular fd. with\n-\t * fcntl(), this is not necessary - we can open a new fd and use fcntl()\n-\t * on that.\n-\t */\n-\tret = lock(fd, map_offset, alloc_sz, F_RDLCK);\n-\n-\t/* this should not fail */\n-\tif (ret != 1) {\n-\t\tRTE_LOG(ERR, EAL, \"%s(): error locking file: %s\\n\",\n-\t\t\t__func__,\n-\t\t\tstrerror(errno));\n-\t\tgoto resized;\n+\tif (internal_config.single_file_segments) {\n+\t\tmap_offset = seg_idx * alloc_sz;\n+\t\tret = resize_hugefile(fd, map_offset, alloc_sz, true);\n+\t\tif (ret < 1)\n+\t\t\tgoto resized;\n+\t} else {\n+\t\tmap_offset = 0;\n+\t\tif (ftruncate(fd, alloc_sz) < 0) {\n+\t\t\tRTE_LOG(DEBUG, EAL, \"%s(): ftruncate() failed: %s\\n\",\n+\t\t\t\t__func__, strerror(errno));\n+\t\t\tgoto resized;\n+\t\t}\n+\t\t/* we've allocated a page - take out a read lock. we're using\n+\t\t * fcntl() locks rather than flock() here because doing that\n+\t\t * gives us one huge advantage - fcntl() locks are per-process,\n+\t\t * not per-file descriptor, which means that we don't have to\n+\t\t * keep the original fd's around to keep a lock on the file.\n+\t\t *\n+\t\t * this is useful, because when it comes to unmapping pages, we\n+\t\t * will have to take out a write lock (to figure out if another\n+\t\t * process still has this page mapped), and to do itwith flock()\n+\t\t * we'll have to use original fd, as lock is associated with\n+\t\t * that particular fd. with fcntl(), this is not necessary - we\n+\t\t * can open a new fd and use fcntl() on that.\n+\t\t */\n+\t\tret = lock(fd, map_offset, alloc_sz, F_RDLCK);\n+\n+\t\t/* this should not fail */\n+\t\tif (ret != 1) {\n+\t\t\tRTE_LOG(ERR, EAL, \"%s(): error locking file: %s\\n\",\n+\t\t\t\t__func__,\n+\t\t\t\tstrerror(errno));\n+\t\t\tgoto resized;\n+\t\t}\n \t}\n \n \t/*\n@@ -227,7 +428,9 @@ alloc_seg(struct rte_memseg *ms, void *addr, int socket_id,\n \t */\n \tvoid *va = mmap(addr, alloc_sz, PROT_READ | PROT_WRITE,\n \t\t\tMAP_SHARED | MAP_POPULATE | MAP_FIXED, fd, map_offset);\n-\tclose(fd);\n+\t/* for non-single file segments, we can close fd here */\n+\tif (!internal_config.single_file_segments)\n+\t\tclose(fd);\n \n \tif (va == MAP_FAILED) {\n \t\tRTE_LOG(DEBUG, EAL, \"%s(): mmap() failed: %s\\n\", __func__,\n@@ -284,8 +487,21 @@ alloc_seg(struct rte_memseg *ms, void *addr, int socket_id,\n mapped:\n \tmunmap(addr, alloc_sz);\n resized:\n-\tclose(fd);\n-\tunlink(path);\n+\tif (internal_config.single_file_segments) {\n+\t\tresize_hugefile(fd, map_offset, alloc_sz, false);\n+\t\tif (is_zero_length(fd)) {\n+\t\t\tstruct msl_entry *te = get_msl_entry_by_idx(list_idx);\n+\t\t\tif (te != NULL && te->fd >= 0) {\n+\t\t\t\tclose(te->fd);\n+\t\t\t\tte->fd = -1;\n+\t\t\t}\n+\t\t\t/* ignore errors, can't make it any worse */\n+\t\t\tunlink(path);\n+\t\t}\n+\t} else {\n+\t\tclose(fd);\n+\t\tunlink(path);\n+\t}\n \treturn -1;\n }\n \n@@ -293,6 +509,7 @@ static int\n free_seg(struct rte_memseg *ms, struct hugepage_info *hi,\n \t\tunsigned int list_idx, unsigned int seg_idx)\n {\n+\tuint64_t map_offset;\n \tchar path[PATH_MAX];\n \tint fd, ret;\n \n@@ -310,21 +527,39 @@ free_seg(struct rte_memseg *ms, struct hugepage_info *hi,\n \tif (fd < 0)\n \t\treturn -1;\n \n-\t/* if we're able to take out a write lock, we're the last one\n-\t * holding onto this page.\n-\t */\n-\n-\tret = lock(fd, 0, ms->len, F_WRLCK);\n-\tif (ret >= 0) {\n-\t\t/* no one else is using this page */\n-\t\tif (ret == 1)\n+\tif (internal_config.single_file_segments) {\n+\t\tmap_offset = seg_idx * ms->len;\n+\t\tif (resize_hugefile(fd, map_offset, ms->len, false))\n+\t\t\treturn -1;\n+\t\t/* if file is zero-length, we've already shrunk it, so it's\n+\t\t * safe to remove.\n+\t\t */\n+\t\tif (is_zero_length(fd)) {\n+\t\t\tstruct msl_entry *te = get_msl_entry_by_idx(list_idx);\n+\t\t\tif (te != NULL && te->fd >= 0) {\n+\t\t\t\tclose(te->fd);\n+\t\t\t\tte->fd = -1;\n+\t\t\t}\n \t\t\tunlink(path);\n-\t\tret = lock(fd, 0, ms->len, F_UNLCK);\n-\t\tif (ret != 1)\n-\t\t\tRTE_LOG(ERR, EAL, \"%s(): unable to unlock file %s\\n\",\n-\t\t\t\t__func__, path);\n+\t\t}\n+\t\tret = 0;\n+\t} else {\n+\t\t/* if we're able to take out a write lock, we're the last one\n+\t\t * holding onto this page.\n+\t\t */\n+\n+\t\tret = lock(fd, 0, ms->len, F_WRLCK);\n+\t\tif (ret >= 0) {\n+\t\t\t/* no one else is using this page */\n+\t\t\tif (ret == 1)\n+\t\t\t\tunlink(path);\n+\t\t\tret = lock(fd, 0, ms->len, F_UNLCK);\n+\t\t\tif (ret != 1)\n+\t\t\t\tRTE_LOG(ERR, EAL, \"%s(): unable to unlock file %s\\n\",\n+\t\t\t\t\t__func__, path);\n+\t\t}\n+\t\tclose(fd);\n \t}\n-\tclose(fd);\n \n \tmemset(ms, 0, sizeof(*ms));\n \n",
    "prefixes": [
        "dpdk-dev",
        "v6",
        "53/70"
    ]
}