get:
Show a patch.

patch:
Update a patch.

put:
Update a patch.

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

{
    "id": 25934,
    "url": "http://patches.dpdk.org/api/patches/25934/?format=api",
    "web_url": "http://patches.dpdk.org/project/dpdk/patch/1498712510-44217-2-git-send-email-jia.guo@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": "<1498712510-44217-2-git-send-email-jia.guo@intel.com>",
    "list_archive_url": "https://inbox.dpdk.org/dev/1498712510-44217-2-git-send-email-jia.guo@intel.com",
    "date": "2017-06-29T05:01:49",
    "name": "[dpdk-dev,v3,1/2] eal: add uevent api for hot plug",
    "commit_ref": null,
    "pull_url": null,
    "state": "superseded",
    "archived": true,
    "hash": "23501f9352e0147520b88bc90f0cdc1dc76051ce",
    "submitter": {
        "id": 507,
        "url": "http://patches.dpdk.org/api/people/507/?format=api",
        "name": "Guo, Jia",
        "email": "jia.guo@intel.com"
    },
    "delegate": {
        "id": 1,
        "url": "http://patches.dpdk.org/api/users/1/?format=api",
        "username": "tmonjalo",
        "first_name": "Thomas",
        "last_name": "Monjalon",
        "email": "thomas@monjalon.net"
    },
    "mbox": "http://patches.dpdk.org/project/dpdk/patch/1498712510-44217-2-git-send-email-jia.guo@intel.com/mbox/",
    "series": [],
    "comments": "http://patches.dpdk.org/api/patches/25934/comments/",
    "check": "fail",
    "checks": "http://patches.dpdk.org/api/patches/25934/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 [IPv6:::1])\n\tby dpdk.org (Postfix) with ESMTP id E2063377E;\n\tThu, 29 Jun 2017 07:05:41 +0200 (CEST)",
            "from mga05.intel.com (mga05.intel.com [192.55.52.43])\n\tby dpdk.org (Postfix) with ESMTP id 952F829CA\n\tfor <dev@dpdk.org>; Thu, 29 Jun 2017 07:05:36 +0200 (CEST)",
            "from orsmga001.jf.intel.com ([10.7.209.18])\n\tby fmsmga105.fm.intel.com with ESMTP; 28 Jun 2017 22:05:36 -0700",
            "from dpdk-py-purley.sh.intel.com ([10.239.129.223])\n\tby orsmga001.jf.intel.com with ESMTP; 28 Jun 2017 22:05:34 -0700"
        ],
        "X-ExtLoop1": "1",
        "X-IronPort-AV": "E=Sophos; i=\"5.40,278,1496127600\"; d=\"scan'208\";\n\ta=\"1145923624\"",
        "From": "Jeff Guo <jia.guo@intel.com>",
        "To": "helin.zhang@intel.com,\n\tjingjing.wu@intel.com",
        "Cc": "dev@dpdk.org, jia.guo@intel.com, bruce.richardson@intel.com,\n\tkonstantin.ananyev@intel.com, gaetan.rivet@6wind.com,\n\tthomas.monjalon@6wind.com, ferruh.yigit@intel.com",
        "Date": "Thu, 29 Jun 2017 13:01:49 +0800",
        "Message-Id": "<1498712510-44217-2-git-send-email-jia.guo@intel.com>",
        "X-Mailer": "git-send-email 1.8.3.1",
        "In-Reply-To": "<1498712510-44217-1-git-send-email-jia.guo@intel.com>",
        "References": "<1498648044-57541-2-git-send-email-jia.guo@intel.com>\n\t<1498712510-44217-1-git-send-email-jia.guo@intel.com>",
        "MIME-Version": "1.0",
        "Content-Type": "text/plain; charset=UTF-8",
        "Content-Transfer-Encoding": "8bit",
        "Subject": "[dpdk-dev] [PATCH v3 1/2] eal: add uevent api for hot plug",
        "X-BeenThere": "dev@dpdk.org",
        "X-Mailman-Version": "2.1.15",
        "Precedence": "list",
        "List-Id": "DPDK patches and discussions <dev.dpdk.org>",
        "List-Unsubscribe": "<http://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": "<http://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": "From: \"Guo, Jia\" <jia.guo@intel.com>\n\nThis patch aim to add a variable \"uevent_fd\" in structure\n\"rte_intr_handle\" for enable kernel object uevent monitoring,\nand add some uevent API in rte eal interrupt, that is\n“rte_uevent_connect” and “rte_uevent_get”, so that all driver\ncould use these API to monitor and read out the uevent, then\ncorresponding to handle these uevent, such as detach or attach\nthe device.\n\nSigned-off-by: Guo, Jia <jia.guo@intel.com>\n---\nv3->v2: refine some return error\n\trefine the string searching logic to aviod memory issue\n---\n lib/librte_eal/common/eal_common_pci_uio.c         |   6 +-\n lib/librte_eal/linuxapp/eal/eal_interrupts.c       | 136 ++++++++++++++++++++-\n lib/librte_eal/linuxapp/eal/eal_pci_uio.c          |   6 +\n .../linuxapp/eal/include/exec-env/rte_interrupts.h |  37 ++++++\n 4 files changed, 182 insertions(+), 3 deletions(-)",
    "diff": "diff --git a/lib/librte_eal/common/eal_common_pci_uio.c b/lib/librte_eal/common/eal_common_pci_uio.c\nindex 367a681..5b62f70 100644\n--- a/lib/librte_eal/common/eal_common_pci_uio.c\n+++ b/lib/librte_eal/common/eal_common_pci_uio.c\n@@ -117,6 +117,7 @@\n \n \tdev->intr_handle.fd = -1;\n \tdev->intr_handle.uio_cfg_fd = -1;\n+\tdev->intr_handle.uevent_fd = -1;\n \tdev->intr_handle.type = RTE_INTR_HANDLE_UNKNOWN;\n \n \t/* secondary processes - use already recorded details */\n@@ -227,7 +228,10 @@\n \t\tclose(dev->intr_handle.uio_cfg_fd);\n \t\tdev->intr_handle.uio_cfg_fd = -1;\n \t}\n-\n+\tif (dev->intr_handle.uevent_fd >= 0) {\n+\t\tclose(dev->intr_handle.uevent_fd);\n+\t\tdev->intr_handle.uevent_fd = -1;\n+\t}\n \tdev->intr_handle.fd = -1;\n \tdev->intr_handle.type = RTE_INTR_HANDLE_UNKNOWN;\n }\ndiff --git a/lib/librte_eal/linuxapp/eal/eal_interrupts.c b/lib/librte_eal/linuxapp/eal/eal_interrupts.c\nindex 2e3bd12..2c4a3fb 100644\n--- a/lib/librte_eal/linuxapp/eal/eal_interrupts.c\n+++ b/lib/librte_eal/linuxapp/eal/eal_interrupts.c\n@@ -65,6 +65,10 @@\n #include <rte_errno.h>\n #include <rte_spinlock.h>\n \n+#include <sys/socket.h>\n+#include <linux/netlink.h>\n+#include <sys/epoll.h>\n+\n #include \"eal_private.h\"\n #include \"eal_vfio.h\"\n #include \"eal_thread.h\"\n@@ -669,10 +673,13 @@ struct rte_intr_source {\n \t\t\tRTE_SET_USED(r);\n \t\t\treturn -1;\n \t\t}\n+\n \t\trte_spinlock_lock(&intr_lock);\n \t\tTAILQ_FOREACH(src, &intr_sources, next)\n-\t\t\tif (src->intr_handle.fd ==\n-\t\t\t\t\tevents[n].data.fd)\n+\t\t\tif ((src->intr_handle.fd ==\n+\t\t\t\t\tevents[n].data.fd) ||\n+\t\t\t\t(src->intr_handle.uevent_fd ==\n+\t\t\t\t\tevents[n].data.fd))\n \t\t\t\tbreak;\n \t\tif (src == NULL){\n \t\t\trte_spinlock_unlock(&intr_lock);\n@@ -858,7 +865,24 @@ static __attribute__((noreturn)) void *\n \t\t\t}\n \t\t\telse\n \t\t\t\tnumfds++;\n+\n+\t\t\t/**\n+\t\t\t * add device uevent file descriptor\n+\t\t\t * into wait list for uevent monitoring.\n+\t\t\t */\n+\t\t\tev.events = EPOLLIN | EPOLLPRI | EPOLLRDHUP | EPOLLHUP;\n+\t\t\tev.data.fd = src->intr_handle.uevent_fd;\n+\t\t\tif (epoll_ctl(pfd, EPOLL_CTL_ADD,\n+\t\t\t\t\tsrc->intr_handle.uevent_fd, &ev) < 0){\n+\t\t\t\trte_panic(\"Error adding uevent_fd %d epoll_ctl\"\n+\t\t\t\t\t\", %s\\n\",\n+\t\t\t\t\tsrc->intr_handle.uevent_fd,\n+\t\t\t\t\tstrerror(errno));\n+\t\t\t} else\n+\t\t\t\tnumfds++;\n \t\t}\n+\n+\n \t\trte_spinlock_unlock(&intr_lock);\n \t\t/* serve the interrupt */\n \t\teal_intr_handle_interrupts(pfd, numfds);\n@@ -1255,3 +1279,111 @@ static __attribute__((noreturn)) void *\n \n \treturn 0;\n }\n+\n+int\n+rte_uevent_connect(void)\n+{\n+\tstruct sockaddr_nl addr;\n+\tint ret;\n+\tint netlink_fd = -1;\n+\tint size = 64 * 1024;\n+\tint nonblock = 1;\n+\tmemset(&addr, 0, sizeof(addr));\n+\taddr.nl_family = AF_NETLINK;\n+\taddr.nl_pid = 0;\n+\taddr.nl_groups = 0xffffffff;\n+\n+\tnetlink_fd = socket(PF_NETLINK, SOCK_DGRAM, NETLINK_KOBJECT_UEVENT);\n+\tif (netlink_fd < 0)\n+\t\treturn -1;\n+\n+\tsetsockopt(netlink_fd, SOL_SOCKET, SO_RCVBUFFORCE, &size, sizeof(size));\n+\n+\tret = ioctl(netlink_fd, FIONBIO, &nonblock);\n+\tif (ret != 0) {\n+\t\tRTE_LOG(ERR, EAL,\n+\t\t\"ioctl(FIONBIO) failed\\n\");\n+\t\tclose(netlink_fd);\n+\t\treturn -1;\n+\t}\n+\n+\tif (bind(netlink_fd, (struct sockaddr *) &addr, sizeof(addr)) < 0) {\n+\t\tclose(netlink_fd);\n+\t\treturn -1;\n+\t}\n+\n+\treturn netlink_fd;\n+}\n+\n+static int\n+parse_event(const char *buf, struct rte_uevent *event)\n+{\n+\tchar action[RTE_UEVENT_MSG_LEN];\n+\tchar subsystem[RTE_UEVENT_MSG_LEN];\n+\tchar dev_path[RTE_UEVENT_MSG_LEN];\n+\tint i = 0;\n+\n+\tmemset(action, 0, RTE_UEVENT_MSG_LEN);\n+\tmemset(subsystem, 0, RTE_UEVENT_MSG_LEN);\n+\tmemset(dev_path, 0, RTE_UEVENT_MSG_LEN);\n+\n+\twhile (i < RTE_UEVENT_MSG_LEN) {\n+\t\tfor (; i < RTE_UEVENT_MSG_LEN; i++) {\n+\t\t\tif (*buf)\n+\t\t\t\tbreak;\n+\t\t\tbuf++;\n+\t\t}\n+\t\tif (!strncmp(buf, \"ACTION=\", 7)) {\n+\t\t\tbuf += 7;\n+\t\t\ti += 7;\n+\t\t\tsnprintf(action, sizeof(action), \"%s\", buf);\n+\t\t} else if (!strncmp(buf, \"DEVPATH=\", 8)) {\n+\t\t\tbuf += 8;\n+\t\t\ti += 8;\n+\t\t\tsnprintf(dev_path, sizeof(dev_path), \"%s\", buf);\n+\t\t} else if (!strncmp(buf, \"SUBSYSTEM=\", 10)) {\n+\t\t\tbuf += 10;\n+\t\t\ti += 10;\n+\t\t\tsnprintf(subsystem, sizeof(subsystem), \"%s\", buf);\n+\t\t}\n+\t\tfor (; i < RTE_UEVENT_MSG_LEN; i++) {\n+\t\t\tif (*buf == '\\0')\n+\t\t\t\tbreak;\n+\t\t\tbuf++;\n+\t\t}\n+\t}\n+\n+\tif (!strncmp(subsystem, \"uio\", 3)) {\n+\n+\t\tevent->subsystem = RTE_UEVENT_SUBSYSTEM_UIO;\n+\t\tif (!strncmp(action, \"add\", 3))\n+\t\t\tevent->action = RTE_UEVENT_ADD;\n+\t\tif (!strncmp(action, \"remove\", 6))\n+\t\t\tevent->action = RTE_UEVENT_REMOVE;\n+\t\treturn 0;\n+\t}\n+\n+\treturn -1;\n+}\n+\n+int\n+rte_uevent_get(int fd, struct rte_uevent *uevent)\n+{\n+\tint ret;\n+\tchar buf[RTE_UEVENT_MSG_LEN];\n+\n+\tmemset(uevent, 0, sizeof(struct rte_uevent));\n+\tmemset(buf, 0, RTE_UEVENT_MSG_LEN);\n+\n+\tret = recv(fd, buf, RTE_UEVENT_MSG_LEN - 1, MSG_DONTWAIT);\n+\tif (ret > 0)\n+\t\treturn parse_event(buf, uevent);\n+\telse if (ret < 0) {\n+\t\tRTE_LOG(ERR, EAL,\n+\t\t\"Socket read error(%d): %s\\n\",\n+\t\terrno, strerror(errno));\n+\t\treturn -1;\n+\t} else\n+\t\t/* connection closed */\n+\t\treturn -1;\n+}\ndiff --git a/lib/librte_eal/linuxapp/eal/eal_pci_uio.c b/lib/librte_eal/linuxapp/eal/eal_pci_uio.c\nindex fa10329..eae9cd5 100644\n--- a/lib/librte_eal/linuxapp/eal/eal_pci_uio.c\n+++ b/lib/librte_eal/linuxapp/eal/eal_pci_uio.c\n@@ -231,6 +231,10 @@\n \t\tclose(dev->intr_handle.uio_cfg_fd);\n \t\tdev->intr_handle.uio_cfg_fd = -1;\n \t}\n+\tif (dev->intr_handle.uevent_fd >= 0) {\n+\t\tclose(dev->intr_handle.uevent_fd);\n+\t\tdev->intr_handle.uevent_fd = -1;\n+\t}\n \tif (dev->intr_handle.fd >= 0) {\n \t\tclose(dev->intr_handle.fd);\n \t\tdev->intr_handle.fd = -1;\n@@ -276,6 +280,8 @@\n \t\tgoto error;\n \t}\n \n+\tdev->intr_handle.uevent_fd = rte_uevent_connect();\n+\n \tif (dev->kdrv == RTE_KDRV_IGB_UIO)\n \t\tdev->intr_handle.type = RTE_INTR_HANDLE_UIO;\n \telse {\ndiff --git a/lib/librte_eal/linuxapp/eal/include/exec-env/rte_interrupts.h b/lib/librte_eal/linuxapp/eal/include/exec-env/rte_interrupts.h\nindex 6daffeb..0b31a22 100644\n--- a/lib/librte_eal/linuxapp/eal/include/exec-env/rte_interrupts.h\n+++ b/lib/librte_eal/linuxapp/eal/include/exec-env/rte_interrupts.h\n@@ -90,6 +90,7 @@ struct rte_intr_handle {\n \t\t\t\t\tfor uio_pci_generic */\n \t};\n \tint fd;\t /**< interrupt event file descriptor */\n+\tint uevent_fd;\t /**< uevent file descriptor */\n \tenum rte_intr_handle_type type;  /**< handle type */\n \tuint32_t max_intr;             /**< max interrupt requested */\n \tuint32_t nb_efd;               /**< number of available efd(event fd) */\n@@ -99,6 +100,19 @@ struct rte_intr_handle {\n \tint *intr_vec;                 /**< intr vector number array */\n };\n \n+#define RTE_UEVENT_MSG_LEN 4096\n+#define RTE_UEVENT_SUBSYSTEM_UIO 1\n+\n+enum rte_uevent_action {\n+\tRTE_UEVENT_ADD = 0,\t\t/**< uevent type of device add */\n+\tRTE_UEVENT_REMOVE = 1,\t/**< uevent type of device remove*/\n+};\n+\n+struct rte_uevent {\n+\tenum rte_uevent_action action;\t/**< uevent action type */\n+\tint subsystem;\t\t\t\t/**< subsystem id */\n+};\n+\n #define RTE_EPOLL_PER_THREAD        -1  /**< to hint using per thread epfd */\n \n /**\n@@ -236,4 +250,27 @@ struct rte_intr_handle {\n int\n rte_intr_cap_multiple(struct rte_intr_handle *intr_handle);\n \n+/**\n+ * It read out the uevent from the specific file descriptor.\n+ *\n+ * @param fd\n+ *   The fd which the uevent associated to\n+ * @param uevent\n+ *   Pointer to the uevent which read from the monitoring fd.\n+ * @return\n+ *   - On success, zero.\n+ *   - On failure, a negative value.\n+ */\n+int\n+rte_uevent_get(int fd, struct rte_uevent *uevent);\n+\n+/**\n+ * Connect to the device uevent file descriptor.\n+ * @return\n+ *   - On success, the connected uevent fd.\n+ *   - On failure, a negative value.\n+ */\n+int\n+rte_uevent_connect(void);\n+\n #endif /* _RTE_LINUXAPP_INTERRUPTS_H_ */\n",
    "prefixes": [
        "dpdk-dev",
        "v3",
        "1/2"
    ]
}