get:
Show a patch.

patch:
Update a patch.

put:
Update a patch.

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

{
    "id": 53530,
    "url": "http://patches.dpdk.org/api/patches/53530/?format=api",
    "web_url": "http://patches.dpdk.org/project/dpdk/patch/20190517150613.13310-2-maxime.coquelin@redhat.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": "<20190517150613.13310-2-maxime.coquelin@redhat.com>",
    "list_archive_url": "https://inbox.dpdk.org/dev/20190517150613.13310-2-maxime.coquelin@redhat.com",
    "date": "2019-05-17T15:06:09",
    "name": "[v2,1/5] vhost: un-inline dirty pages logging functions",
    "commit_ref": null,
    "pull_url": null,
    "state": "superseded",
    "archived": true,
    "hash": "59015946a191a1224b389a21b4fa047de697a6a0",
    "submitter": {
        "id": 512,
        "url": "http://patches.dpdk.org/api/people/512/?format=api",
        "name": "Maxime Coquelin",
        "email": "maxime.coquelin@redhat.com"
    },
    "delegate": {
        "id": 2642,
        "url": "http://patches.dpdk.org/api/users/2642/?format=api",
        "username": "mcoquelin",
        "first_name": "Maxime",
        "last_name": "Coquelin",
        "email": "maxime.coquelin@redhat.com"
    },
    "mbox": "http://patches.dpdk.org/project/dpdk/patch/20190517150613.13310-2-maxime.coquelin@redhat.com/mbox/",
    "series": [
        {
            "id": 4710,
            "url": "http://patches.dpdk.org/api/series/4710/?format=api",
            "web_url": "http://patches.dpdk.org/project/dpdk/list/?series=4710",
            "date": "2019-05-17T15:06:08",
            "name": "vhost: I-cache pressure optimizations",
            "version": 2,
            "mbox": "http://patches.dpdk.org/series/4710/mbox/"
        }
    ],
    "comments": "http://patches.dpdk.org/api/patches/53530/comments/",
    "check": "fail",
    "checks": "http://patches.dpdk.org/api/patches/53530/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 A27A4ABEF;\n\tFri, 17 May 2019 17:06:32 +0200 (CEST)",
            "from mx1.redhat.com (mx1.redhat.com [209.132.183.28])\n\tby dpdk.org (Postfix) with ESMTP id 72A5F7D4A\n\tfor <dev@dpdk.org>; Fri, 17 May 2019 17:06:30 +0200 (CEST)",
            "from smtp.corp.redhat.com\n\t(int-mx06.intmail.prod.int.phx2.redhat.com [10.5.11.16])\n\t(using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits))\n\t(No client certificate requested)\n\tby mx1.redhat.com (Postfix) with ESMTPS id 8294CC0AD28F;\n\tFri, 17 May 2019 15:06:29 +0000 (UTC)",
            "from localhost.localdomain (ovpn-112-59.ams2.redhat.com\n\t[10.36.112.59])\n\tby smtp.corp.redhat.com (Postfix) with ESMTP id 70F0A71442;\n\tFri, 17 May 2019 15:06:26 +0000 (UTC)"
        ],
        "From": "Maxime Coquelin <maxime.coquelin@redhat.com>",
        "To": "dev@dpdk.org, tiwei.bie@intel.com, jfreimann@redhat.com,\n\tzhihong.wang@intel.com, bruce.richardson@intel.com,\n\tkonstantin.ananyev@intel.com, david.marchand@redhat.com",
        "Cc": "Maxime Coquelin <maxime.coquelin@redhat.com>",
        "Date": "Fri, 17 May 2019 17:06:09 +0200",
        "Message-Id": "<20190517150613.13310-2-maxime.coquelin@redhat.com>",
        "In-Reply-To": "<20190517150613.13310-1-maxime.coquelin@redhat.com>",
        "References": "<20190517150613.13310-1-maxime.coquelin@redhat.com>",
        "MIME-Version": "1.0",
        "Content-Transfer-Encoding": "8bit",
        "X-Scanned-By": "MIMEDefang 2.79 on 10.5.11.16",
        "X-Greylist": "Sender IP whitelisted, not delayed by milter-greylist-4.5.16\n\t(mx1.redhat.com [10.5.110.32]); Fri, 17 May 2019 15:06:29 +0000 (UTC)",
        "Subject": "[dpdk-dev] [PATCH v2 1/5] vhost: un-inline dirty pages logging\n\tfunctions",
        "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": "In order to reduce the I-cache pressure, this patch removes\nthe inlining of the dirty pages logging functions, that we\ncan consider as cold path.\n\nIndeed, these functions are only called while doing live\nmigration, so not called most of the time.\n\nSigned-off-by: Maxime Coquelin <maxime.coquelin@redhat.com>\n---\n lib/librte_vhost/vhost.c | 132 +++++++++++++++++++++++++++++++++++++++\n lib/librte_vhost/vhost.h | 129 ++++----------------------------------\n 2 files changed, 144 insertions(+), 117 deletions(-)",
    "diff": "diff --git a/lib/librte_vhost/vhost.c b/lib/librte_vhost/vhost.c\nindex 163f4595ef..4a54ad6bd1 100644\n--- a/lib/librte_vhost/vhost.c\n+++ b/lib/librte_vhost/vhost.c\n@@ -69,6 +69,138 @@ __vhost_iova_to_vva(struct virtio_net *dev, struct vhost_virtqueue *vq,\n \treturn 0;\n }\n \n+#define VHOST_LOG_PAGE\t4096\n+\n+/*\n+ * Atomically set a bit in memory.\n+ */\n+static __rte_always_inline void\n+vhost_set_bit(unsigned int nr, volatile uint8_t *addr)\n+{\n+#if defined(RTE_TOOLCHAIN_GCC) && (GCC_VERSION < 70100)\n+\t/*\n+\t * __sync_ built-ins are deprecated, but __atomic_ ones\n+\t * are sub-optimized in older GCC versions.\n+\t */\n+\t__sync_fetch_and_or_1(addr, (1U << nr));\n+#else\n+\t__atomic_fetch_or(addr, (1U << nr), __ATOMIC_RELAXED);\n+#endif\n+}\n+\n+static __rte_always_inline void\n+vhost_log_page(uint8_t *log_base, uint64_t page)\n+{\n+\tvhost_set_bit(page % 8, &log_base[page / 8]);\n+}\n+\n+void\n+__vhost_log_write(struct virtio_net *dev, uint64_t addr, uint64_t len)\n+{\n+\tuint64_t page;\n+\n+\tif (unlikely(!dev->log_base || !len))\n+\t\treturn;\n+\n+\tif (unlikely(dev->log_size <= ((addr + len - 1) / VHOST_LOG_PAGE / 8)))\n+\t\treturn;\n+\n+\t/* To make sure guest memory updates are committed before logging */\n+\trte_smp_wmb();\n+\n+\tpage = addr / VHOST_LOG_PAGE;\n+\twhile (page * VHOST_LOG_PAGE < addr + len) {\n+\t\tvhost_log_page((uint8_t *)(uintptr_t)dev->log_base, page);\n+\t\tpage += 1;\n+\t}\n+}\n+\n+void\n+__vhost_log_cache_sync(struct virtio_net *dev, struct vhost_virtqueue *vq)\n+{\n+\tunsigned long *log_base;\n+\tint i;\n+\n+\tif (unlikely(!dev->log_base))\n+\t\treturn;\n+\n+\trte_smp_wmb();\n+\n+\tlog_base = (unsigned long *)(uintptr_t)dev->log_base;\n+\n+\tfor (i = 0; i < vq->log_cache_nb_elem; i++) {\n+\t\tstruct log_cache_entry *elem = vq->log_cache + i;\n+\n+#if defined(RTE_TOOLCHAIN_GCC) && (GCC_VERSION < 70100)\n+\t\t/*\n+\t\t * '__sync' builtins are deprecated, but '__atomic' ones\n+\t\t * are sub-optimized in older GCC versions.\n+\t\t */\n+\t\t__sync_fetch_and_or(log_base + elem->offset, elem->val);\n+#else\n+\t\t__atomic_fetch_or(log_base + elem->offset, elem->val,\n+\t\t\t\t__ATOMIC_RELAXED);\n+#endif\n+\t}\n+\n+\trte_smp_wmb();\n+\n+\tvq->log_cache_nb_elem = 0;\n+}\n+\n+static __rte_always_inline void\n+vhost_log_cache_page(struct virtio_net *dev, struct vhost_virtqueue *vq,\n+\t\t\tuint64_t page)\n+{\n+\tuint32_t bit_nr = page % (sizeof(unsigned long) << 3);\n+\tuint32_t offset = page / (sizeof(unsigned long) << 3);\n+\tint i;\n+\n+\tfor (i = 0; i < vq->log_cache_nb_elem; i++) {\n+\t\tstruct log_cache_entry *elem = vq->log_cache + i;\n+\n+\t\tif (elem->offset == offset) {\n+\t\t\telem->val |= (1UL << bit_nr);\n+\t\t\treturn;\n+\t\t}\n+\t}\n+\n+\tif (unlikely(i >= VHOST_LOG_CACHE_NR)) {\n+\t\t/*\n+\t\t * No more room for a new log cache entry,\n+\t\t * so write the dirty log map directly.\n+\t\t */\n+\t\trte_smp_wmb();\n+\t\tvhost_log_page((uint8_t *)(uintptr_t)dev->log_base, page);\n+\n+\t\treturn;\n+\t}\n+\n+\tvq->log_cache[i].offset = offset;\n+\tvq->log_cache[i].val = (1UL << bit_nr);\n+\tvq->log_cache_nb_elem++;\n+}\n+\n+void\n+__vhost_log_cache_write(struct virtio_net *dev, struct vhost_virtqueue *vq,\n+\t\t\tuint64_t addr, uint64_t len)\n+{\n+\tuint64_t page;\n+\n+\tif (unlikely(!dev->log_base || !len))\n+\t\treturn;\n+\n+\tif (unlikely(dev->log_size <= ((addr + len - 1) / VHOST_LOG_PAGE / 8)))\n+\t\treturn;\n+\n+\tpage = addr / VHOST_LOG_PAGE;\n+\twhile (page * VHOST_LOG_PAGE < addr + len) {\n+\t\tvhost_log_cache_page(dev, vq, page);\n+\t\tpage += 1;\n+\t}\n+}\n+\n+\n void\n cleanup_vq(struct vhost_virtqueue *vq, int destroy)\n {\ndiff --git a/lib/librte_vhost/vhost.h b/lib/librte_vhost/vhost.h\nindex e9138dfab4..3ab7b4950f 100644\n--- a/lib/librte_vhost/vhost.h\n+++ b/lib/librte_vhost/vhost.h\n@@ -350,138 +350,33 @@ desc_is_avail(struct vring_packed_desc *desc, bool wrap_counter)\n \t\twrap_counter != !!(flags & VRING_DESC_F_USED);\n }\n \n-#define VHOST_LOG_PAGE\t4096\n-\n-/*\n- * Atomically set a bit in memory.\n- */\n-static __rte_always_inline void\n-vhost_set_bit(unsigned int nr, volatile uint8_t *addr)\n-{\n-#if defined(RTE_TOOLCHAIN_GCC) && (GCC_VERSION < 70100)\n-\t/*\n-\t * __sync_ built-ins are deprecated, but __atomic_ ones\n-\t * are sub-optimized in older GCC versions.\n-\t */\n-\t__sync_fetch_and_or_1(addr, (1U << nr));\n-#else\n-\t__atomic_fetch_or(addr, (1U << nr), __ATOMIC_RELAXED);\n-#endif\n-}\n-\n-static __rte_always_inline void\n-vhost_log_page(uint8_t *log_base, uint64_t page)\n-{\n-\tvhost_set_bit(page % 8, &log_base[page / 8]);\n-}\n+void __vhost_log_cache_write(struct virtio_net *dev,\n+\t\tstruct vhost_virtqueue *vq,\n+\t\tuint64_t addr, uint64_t len);\n+void __vhost_log_cache_sync(struct virtio_net *dev,\n+\t\tstruct vhost_virtqueue *vq);\n+void __vhost_log_write(struct virtio_net *dev, uint64_t addr, uint64_t len);\n \n static __rte_always_inline void\n vhost_log_write(struct virtio_net *dev, uint64_t addr, uint64_t len)\n {\n-\tuint64_t page;\n-\n-\tif (likely(((dev->features & (1ULL << VHOST_F_LOG_ALL)) == 0) ||\n-\t\t   !dev->log_base || !len))\n-\t\treturn;\n-\n-\tif (unlikely(dev->log_size <= ((addr + len - 1) / VHOST_LOG_PAGE / 8)))\n-\t\treturn;\n-\n-\t/* To make sure guest memory updates are committed before logging */\n-\trte_smp_wmb();\n-\n-\tpage = addr / VHOST_LOG_PAGE;\n-\twhile (page * VHOST_LOG_PAGE < addr + len) {\n-\t\tvhost_log_page((uint8_t *)(uintptr_t)dev->log_base, page);\n-\t\tpage += 1;\n-\t}\n+\tif (unlikely(dev->features & (1ULL << VHOST_F_LOG_ALL)))\n+\t\t__vhost_log_write(dev, addr, len);\n }\n \n static __rte_always_inline void\n vhost_log_cache_sync(struct virtio_net *dev, struct vhost_virtqueue *vq)\n {\n-\tunsigned long *log_base;\n-\tint i;\n-\n-\tif (likely(((dev->features & (1ULL << VHOST_F_LOG_ALL)) == 0) ||\n-\t\t   !dev->log_base))\n-\t\treturn;\n-\n-\trte_smp_wmb();\n-\n-\tlog_base = (unsigned long *)(uintptr_t)dev->log_base;\n-\n-\tfor (i = 0; i < vq->log_cache_nb_elem; i++) {\n-\t\tstruct log_cache_entry *elem = vq->log_cache + i;\n-\n-#if defined(RTE_TOOLCHAIN_GCC) && (GCC_VERSION < 70100)\n-\t\t/*\n-\t\t * '__sync' builtins are deprecated, but '__atomic' ones\n-\t\t * are sub-optimized in older GCC versions.\n-\t\t */\n-\t\t__sync_fetch_and_or(log_base + elem->offset, elem->val);\n-#else\n-\t\t__atomic_fetch_or(log_base + elem->offset, elem->val,\n-\t\t\t\t__ATOMIC_RELAXED);\n-#endif\n-\t}\n-\n-\trte_smp_wmb();\n-\n-\tvq->log_cache_nb_elem = 0;\n-}\n-\n-static __rte_always_inline void\n-vhost_log_cache_page(struct virtio_net *dev, struct vhost_virtqueue *vq,\n-\t\t\tuint64_t page)\n-{\n-\tuint32_t bit_nr = page % (sizeof(unsigned long) << 3);\n-\tuint32_t offset = page / (sizeof(unsigned long) << 3);\n-\tint i;\n-\n-\tfor (i = 0; i < vq->log_cache_nb_elem; i++) {\n-\t\tstruct log_cache_entry *elem = vq->log_cache + i;\n-\n-\t\tif (elem->offset == offset) {\n-\t\t\telem->val |= (1UL << bit_nr);\n-\t\t\treturn;\n-\t\t}\n-\t}\n-\n-\tif (unlikely(i >= VHOST_LOG_CACHE_NR)) {\n-\t\t/*\n-\t\t * No more room for a new log cache entry,\n-\t\t * so write the dirty log map directly.\n-\t\t */\n-\t\trte_smp_wmb();\n-\t\tvhost_log_page((uint8_t *)(uintptr_t)dev->log_base, page);\n-\n-\t\treturn;\n-\t}\n-\n-\tvq->log_cache[i].offset = offset;\n-\tvq->log_cache[i].val = (1UL << bit_nr);\n-\tvq->log_cache_nb_elem++;\n+\tif (unlikely(dev->features & (1ULL << VHOST_F_LOG_ALL)))\n+\t\t__vhost_log_cache_sync(dev, vq);\n }\n \n static __rte_always_inline void\n vhost_log_cache_write(struct virtio_net *dev, struct vhost_virtqueue *vq,\n \t\t\tuint64_t addr, uint64_t len)\n {\n-\tuint64_t page;\n-\n-\tif (likely(((dev->features & (1ULL << VHOST_F_LOG_ALL)) == 0) ||\n-\t\t   !dev->log_base || !len))\n-\t\treturn;\n-\n-\tif (unlikely(dev->log_size <= ((addr + len - 1) / VHOST_LOG_PAGE / 8)))\n-\t\treturn;\n-\n-\tpage = addr / VHOST_LOG_PAGE;\n-\twhile (page * VHOST_LOG_PAGE < addr + len) {\n-\t\tvhost_log_cache_page(dev, vq, page);\n-\t\tpage += 1;\n-\t}\n+\tif (unlikely(dev->features & (1ULL << VHOST_F_LOG_ALL)))\n+\t\t__vhost_log_cache_write(dev, vq, addr, len);\n }\n \n static __rte_always_inline void\n",
    "prefixes": [
        "v2",
        "1/5"
    ]
}