get:
Show a patch.

patch:
Update a patch.

put:
Update a patch.

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

{
    "id": 46112,
    "url": "http://patchwork.dpdk.org/api/patches/46112/?format=api",
    "web_url": "http://patchwork.dpdk.org/project/dpdk/patch/5e545d6548f62a8fddfca18f8cc0901654e1e403.1538728009.git.anatoly.burakov@intel.com/",
    "project": {
        "id": 1,
        "url": "http://patchwork.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": "<5e545d6548f62a8fddfca18f8cc0901654e1e403.1538728009.git.anatoly.burakov@intel.com>",
    "list_archive_url": "https://inbox.dpdk.org/dev/5e545d6548f62a8fddfca18f8cc0901654e1e403.1538728009.git.anatoly.burakov@intel.com",
    "date": "2018-10-05T08:29:44",
    "name": "[v2] eal/linuxapp: improve segment list preallocation",
    "commit_ref": null,
    "pull_url": null,
    "state": "accepted",
    "archived": true,
    "hash": "bf139fe4d00836292ba971f892aed44d886b0021",
    "submitter": {
        "id": 4,
        "url": "http://patchwork.dpdk.org/api/people/4/?format=api",
        "name": "Anatoly Burakov",
        "email": "anatoly.burakov@intel.com"
    },
    "delegate": {
        "id": 1,
        "url": "http://patchwork.dpdk.org/api/users/1/?format=api",
        "username": "tmonjalo",
        "first_name": "Thomas",
        "last_name": "Monjalon",
        "email": "thomas@monjalon.net"
    },
    "mbox": "http://patchwork.dpdk.org/project/dpdk/patch/5e545d6548f62a8fddfca18f8cc0901654e1e403.1538728009.git.anatoly.burakov@intel.com/mbox/",
    "series": [
        {
            "id": 1707,
            "url": "http://patchwork.dpdk.org/api/series/1707/?format=api",
            "web_url": "http://patchwork.dpdk.org/project/dpdk/list/?series=1707",
            "date": "2018-10-05T08:29:44",
            "name": "[v2] eal/linuxapp: improve segment list preallocation",
            "version": 2,
            "mbox": "http://patchwork.dpdk.org/series/1707/mbox/"
        }
    ],
    "comments": "http://patchwork.dpdk.org/api/patches/46112/comments/",
    "check": "success",
    "checks": "http://patchwork.dpdk.org/api/patches/46112/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 2CF474C90;\n\tFri,  5 Oct 2018 10:29:49 +0200 (CEST)",
            "from mga05.intel.com (mga05.intel.com [192.55.52.43])\n\tby dpdk.org (Postfix) with ESMTP id 962A93195;\n\tFri,  5 Oct 2018 10:29:47 +0200 (CEST)",
            "from orsmga008.jf.intel.com ([10.7.209.65])\n\tby fmsmga105.fm.intel.com with ESMTP/TLS/DHE-RSA-AES256-GCM-SHA384;\n\t05 Oct 2018 01:29:46 -0700",
            "from irvmail001.ir.intel.com ([163.33.26.43])\n\tby orsmga008.jf.intel.com with ESMTP; 05 Oct 2018 01:29:45 -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\tw958Tian014439; Fri, 5 Oct 2018 09:29:44 +0100",
            "from sivswdev01.ir.intel.com (localhost [127.0.0.1])\n\tby sivswdev01.ir.intel.com with ESMTP id w958Tigw006247;\n\tFri, 5 Oct 2018 09:29:44 +0100",
            "(from aburakov@localhost)\n\tby sivswdev01.ir.intel.com with LOCAL id w958Ti4h006239;\n\tFri, 5 Oct 2018 09:29:44 +0100"
        ],
        "X-Amp-Result": "SKIPPED(no attachment in message)",
        "X-Amp-File-Uploaded": "False",
        "X-ExtLoop1": "1",
        "X-IronPort-AV": "E=Sophos;i=\"5.54,343,1534834800\"; d=\"scan'208\";a=\"78936758\"",
        "From": "Anatoly Burakov <anatoly.burakov@intel.com>",
        "To": "dev@dpdk.org",
        "Cc": "Ravi1.Kumar@amd.com, stable@dpdk.org",
        "Date": "Fri,  5 Oct 2018 09:29:44 +0100",
        "Message-Id": "<5e545d6548f62a8fddfca18f8cc0901654e1e403.1538728009.git.anatoly.burakov@intel.com>",
        "X-Mailer": "git-send-email 1.7.0.7",
        "In-Reply-To": "<ea99abb9ad539e0817fff5280c8103e5ad51bfc8.1538669431.git.anatoly.burakov@intel.com>",
        "References": "<ea99abb9ad539e0817fff5280c8103e5ad51bfc8.1538669431.git.anatoly.burakov@intel.com>",
        "Subject": "[dpdk-dev] [PATCH v2] eal/linuxapp: improve segment list\n\tpreallocation",
        "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://mails.dpdk.org/options/dev>,\n\t<mailto:dev-request@dpdk.org?subject=unsubscribe>",
        "List-Archive": "<http://mails.dpdk.org/archives/dev/>",
        "List-Post": "<mailto:dev@dpdk.org>",
        "List-Help": "<mailto:dev-request@dpdk.org?subject=help>",
        "List-Subscribe": "<https://mails.dpdk.org/listinfo/dev>,\n\t<mailto:dev-request@dpdk.org?subject=subscribe>",
        "Errors-To": "dev-bounces@dpdk.org",
        "Sender": "\"dev\" <dev-bounces@dpdk.org>"
    },
    "content": "Current code to preallocate segment lists is trying to do\neverything in one go, and thus ends up being convoluted,\nhard to understand, and, most importantly, does not scale beyond\ninitial assumptions about number of NUMA nodes and number of\npage sizes, and therefore has issues on some configurations.\n\nInstead of fixing these issues in the existing code, simply\nrewrite it to be slightly less clever but much more logical, and\nprovide ample comments to explain exactly what is going on.\n\nWe cannot use the same approach for 32-bit code because the\nlimitations of the target dictate current socket-centric\napproach rather than type-centric approach we use on 64-bit\ntarget, so 32-bit code is left unmodified. FreeBSD doesn't\nsupport NUMA so there's no complexity involved there, and thus\nits code is much more readable and not worth changing.\n\nFixes: 1d406458db47 (\"mem: make segment preallocation OS-specific\")\nCc: stable@dpdk.org\n\nSigned-off-by: Anatoly Burakov <anatoly.burakov@intel.com>\n---\n\nNotes:\n    v2:\n    - Fix max mem amount calculation from relying on total number of\n      sockets to total number of mem types\n\n lib/librte_eal/linuxapp/eal/eal_memory.c | 179 +++++++++++++++++------\n 1 file changed, 137 insertions(+), 42 deletions(-)",
    "diff": "diff --git a/lib/librte_eal/linuxapp/eal/eal_memory.c b/lib/librte_eal/linuxapp/eal/eal_memory.c\nindex 78bfa2241..047d0a869 100644\n--- a/lib/librte_eal/linuxapp/eal/eal_memory.c\n+++ b/lib/librte_eal/linuxapp/eal/eal_memory.c\n@@ -2128,18 +2128,65 @@ static int __rte_unused\n memseg_primary_init(void)\n {\n \tstruct rte_mem_config *mcfg = rte_eal_get_configuration()->mem_config;\n-\tint i, socket_id, hpi_idx, msl_idx = 0;\n+\tstruct memtype {\n+\t\tuint64_t page_sz;\n+\t\tint socket_id;\n+\t} *memtypes = NULL;\n+\tint i, hpi_idx, msl_idx;\n \tstruct rte_memseg_list *msl;\n-\tuint64_t max_mem, total_mem;\n+\tuint64_t max_mem, max_mem_per_type;\n+\tunsigned int max_seglists_per_type;\n+\tunsigned int n_memtypes, cur_type;\n \n \t/* no-huge does not need this at all */\n \tif (internal_config.no_hugetlbfs)\n \t\treturn 0;\n \n-\tmax_mem = (uint64_t)RTE_MAX_MEM_MB << 20;\n-\ttotal_mem = 0;\n+\t/*\n+\t * figuring out amount of memory we're going to have is a long and very\n+\t * involved process. the basic element we're operating with is a memory\n+\t * type, defined as a combination of NUMA node ID and page size (so that\n+\t * e.g. 2 sockets with 2 page sizes yield 4 memory types in total).\n+\t *\n+\t * deciding amount of memory going towards each memory type is a\n+\t * balancing act between maximum segments per type, maximum memory per\n+\t * type, and number of detected NUMA nodes. the goal is to make sure\n+\t * each memory type gets at least one memseg list.\n+\t *\n+\t * the total amount of memory is limited by RTE_MAX_MEM_MB value.\n+\t *\n+\t * the total amount of memory per type is limited by either\n+\t * RTE_MAX_MEM_MB_PER_TYPE, or by RTE_MAX_MEM_MB divided by the number\n+\t * of detected NUMA nodes. additionally, maximum number of segments per\n+\t * type is also limited by RTE_MAX_MEMSEG_PER_TYPE. this is because for\n+\t * smaller page sizes, it can take hundreds of thousands of segments to\n+\t * reach the above specified per-type memory limits.\n+\t *\n+\t * additionally, each type may have multiple memseg lists associated\n+\t * with it, each limited by either RTE_MAX_MEM_MB_PER_LIST for bigger\n+\t * page sizes, or RTE_MAX_MEMSEG_PER_LIST segments for smaller ones.\n+\t *\n+\t * the number of memseg lists per type is decided based on the above\n+\t * limits, and also taking number of detected NUMA nodes, to make sure\n+\t * that we don't run out of memseg lists before we populate all NUMA\n+\t * nodes with memory.\n+\t *\n+\t * we do this in three stages. first, we collect the number of types.\n+\t * then, we figure out memory constraints and populate the list of\n+\t * would-be memseg lists. then, we go ahead and allocate the memseg\n+\t * lists.\n+\t */\n \n-\t/* create memseg lists */\n+\t/* create space for mem types */\n+\tn_memtypes = internal_config.num_hugepage_sizes * rte_socket_count();\n+\tmemtypes = calloc(n_memtypes, sizeof(*memtypes));\n+\tif (memtypes == NULL) {\n+\t\tRTE_LOG(ERR, EAL, \"Cannot allocate space for memory types\\n\");\n+\t\treturn -1;\n+\t}\n+\n+\t/* populate mem types */\n+\tcur_type = 0;\n \tfor (hpi_idx = 0; hpi_idx < (int) internal_config.num_hugepage_sizes;\n \t\t\thpi_idx++) {\n \t\tstruct hugepage_info *hpi;\n@@ -2148,59 +2195,107 @@ memseg_primary_init(void)\n \t\thpi = &internal_config.hugepage_info[hpi_idx];\n \t\thugepage_sz = hpi->hugepage_sz;\n \n-\t\tfor (i = 0; i < (int) rte_socket_count(); i++) {\n-\t\t\tuint64_t max_type_mem, total_type_mem = 0;\n-\t\t\tint type_msl_idx, max_segs, total_segs = 0;\n-\n-\t\t\tsocket_id = rte_socket_id_by_idx(i);\n+\t\tfor (i = 0; i < (int) rte_socket_count(); i++, cur_type++) {\n+\t\t\tint socket_id = rte_socket_id_by_idx(i);\n \n #ifndef RTE_EAL_NUMA_AWARE_HUGEPAGES\n \t\t\tif (socket_id > 0)\n \t\t\t\tbreak;\n #endif\n+\t\t\tmemtypes[cur_type].page_sz = hugepage_sz;\n+\t\t\tmemtypes[cur_type].socket_id = socket_id;\n \n-\t\t\tif (total_mem >= max_mem)\n-\t\t\t\tbreak;\n+\t\t\tRTE_LOG(DEBUG, EAL, \"Detected memory type: \"\n+\t\t\t\t\"socket_id:%u hugepage_sz:%\" PRIu64 \"\\n\",\n+\t\t\t\tsocket_id, hugepage_sz);\n+\t\t}\n+\t}\n \n-\t\t\tmax_type_mem = RTE_MIN(max_mem - total_mem,\n-\t\t\t\t(uint64_t)RTE_MAX_MEM_MB_PER_TYPE << 20);\n-\t\t\tmax_segs = RTE_MAX_MEMSEG_PER_TYPE;\n+\t/* set up limits for types */\n+\tmax_mem = (uint64_t)RTE_MAX_MEM_MB << 20;\n+\tmax_mem_per_type = RTE_MIN((uint64_t)RTE_MAX_MEM_MB_PER_TYPE << 20,\n+\t\t\tmax_mem / n_memtypes);\n+\t/*\n+\t * limit maximum number of segment lists per type to ensure there's\n+\t * space for memseg lists for all NUMA nodes with all page sizes\n+\t */\n+\tmax_seglists_per_type = RTE_MAX_MEMSEG_LISTS / n_memtypes;\n \n-\t\t\ttype_msl_idx = 0;\n-\t\t\twhile (total_type_mem < max_type_mem &&\n-\t\t\t\t\ttotal_segs < max_segs) {\n-\t\t\t\tuint64_t cur_max_mem, cur_mem;\n-\t\t\t\tunsigned int n_segs;\n+\tif (max_seglists_per_type == 0) {\n+\t\tRTE_LOG(ERR, EAL, \"Cannot accommodate all memory types, please increase %s\\n\",\n+\t\t\tRTE_STR(CONFIG_RTE_MAX_MEMSEG_LISTS));\n+\t\treturn -1;\n+\t}\n \n-\t\t\t\tif (msl_idx >= RTE_MAX_MEMSEG_LISTS) {\n-\t\t\t\t\tRTE_LOG(ERR, EAL,\n-\t\t\t\t\t\t\"No more space in memseg lists, please increase %s\\n\",\n-\t\t\t\t\t\tRTE_STR(CONFIG_RTE_MAX_MEMSEG_LISTS));\n-\t\t\t\t\treturn -1;\n-\t\t\t\t}\n+\t/* go through all mem types and create segment lists */\n+\tmsl_idx = 0;\n+\tfor (cur_type = 0; cur_type < n_memtypes; cur_type++) {\n+\t\tunsigned int cur_seglist, n_seglists, n_segs;\n+\t\tunsigned int max_segs_per_type, max_segs_per_list;\n+\t\tstruct memtype *type = &memtypes[cur_type];\n+\t\tuint64_t max_mem_per_list, pagesz;\n+\t\tint socket_id;\n \n-\t\t\t\tmsl = &mcfg->memsegs[msl_idx++];\n+\t\tpagesz = type->page_sz;\n+\t\tsocket_id = type->socket_id;\n \n-\t\t\t\tcur_max_mem = max_type_mem - total_type_mem;\n+\t\t/*\n+\t\t * we need to create segment lists for this type. we must take\n+\t\t * into account the following things:\n+\t\t *\n+\t\t * 1. total amount of memory we can use for this memory type\n+\t\t * 2. total amount of memory per memseg list allowed\n+\t\t * 3. number of segments needed to fit the amount of memory\n+\t\t * 4. number of segments allowed per type\n+\t\t * 5. number of segments allowed per memseg list\n+\t\t * 6. number of memseg lists we are allowed to take up\n+\t\t */\n \n-\t\t\t\tcur_mem = get_mem_amount(hugepage_sz,\n-\t\t\t\t\t\tcur_max_mem);\n-\t\t\t\tn_segs = cur_mem / hugepage_sz;\n+\t\t/* calculate how much segments we will need in total */\n+\t\tmax_segs_per_type = max_mem_per_type / pagesz;\n+\t\t/* limit number of segments to maximum allowed per type */\n+\t\tmax_segs_per_type = RTE_MIN(max_segs_per_type,\n+\t\t\t\t(unsigned int)RTE_MAX_MEMSEG_PER_TYPE);\n+\t\t/* limit number of segments to maximum allowed per list */\n+\t\tmax_segs_per_list = RTE_MIN(max_segs_per_type,\n+\t\t\t\t(unsigned int)RTE_MAX_MEMSEG_PER_LIST);\n \n-\t\t\t\tif (alloc_memseg_list(msl, hugepage_sz, n_segs,\n-\t\t\t\t\t\tsocket_id, type_msl_idx))\n-\t\t\t\t\treturn -1;\n+\t\t/* calculate how much memory we can have per segment list */\n+\t\tmax_mem_per_list = RTE_MIN(max_segs_per_list * pagesz,\n+\t\t\t\t(uint64_t)RTE_MAX_MEM_MB_PER_LIST << 20);\n \n-\t\t\t\ttotal_segs += msl->memseg_arr.len;\n-\t\t\t\ttotal_type_mem = total_segs * hugepage_sz;\n-\t\t\t\ttype_msl_idx++;\n+\t\t/* calculate how many segments each segment list will have */\n+\t\tn_segs = RTE_MIN(max_segs_per_list, max_mem_per_list / pagesz);\n \n-\t\t\t\tif (alloc_va_space(msl)) {\n-\t\t\t\t\tRTE_LOG(ERR, EAL, \"Cannot allocate VA space for memseg list\\n\");\n-\t\t\t\t\treturn -1;\n-\t\t\t\t}\n+\t\t/* calculate how many segment lists we can have */\n+\t\tn_seglists = RTE_MIN(max_segs_per_type / n_segs,\n+\t\t\t\tmax_mem_per_type / max_mem_per_list);\n+\n+\t\t/* limit number of segment lists according to our maximum */\n+\t\tn_seglists = RTE_MIN(n_seglists, max_seglists_per_type);\n+\n+\t\tRTE_LOG(DEBUG, EAL, \"Creating %i segment lists: \"\n+\t\t\t\t\"n_segs:%i socket_id:%i hugepage_sz:%\" PRIu64 \"\\n\",\n+\t\t\tn_seglists, n_segs, socket_id, pagesz);\n+\n+\t\t/* create all segment lists */\n+\t\tfor (cur_seglist = 0; cur_seglist < n_seglists; cur_seglist++) {\n+\t\t\tif (msl_idx >= RTE_MAX_MEMSEG_LISTS) {\n+\t\t\t\tRTE_LOG(ERR, EAL,\n+\t\t\t\t\t\"No more space in memseg lists, please increase %s\\n\",\n+\t\t\t\t\tRTE_STR(CONFIG_RTE_MAX_MEMSEG_LISTS));\n+\t\t\t\treturn -1;\n+\t\t\t}\n+\t\t\tmsl = &mcfg->memsegs[msl_idx++];\n+\n+\t\t\tif (alloc_memseg_list(msl, pagesz, n_segs,\n+\t\t\t\t\tsocket_id, cur_seglist))\n+\t\t\t\treturn -1;\n+\n+\t\t\tif (alloc_va_space(msl)) {\n+\t\t\t\tRTE_LOG(ERR, EAL, \"Cannot allocate VA space for memseg list\\n\");\n+\t\t\t\treturn -1;\n \t\t\t}\n-\t\t\ttotal_mem += total_type_mem;\n \t\t}\n \t}\n \treturn 0;\n",
    "prefixes": [
        "v2"
    ]
}