get:
Show a patch.

patch:
Update a patch.

put:
Update a patch.

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

{
    "id": 35363,
    "url": "http://patches.dpdk.org/api/patches/35363/?format=api",
    "web_url": "http://patches.dpdk.org/project/dpdk/patch/df64cdb071cef1002de60c963701a49e1bc3f155.1519322682.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": "<df64cdb071cef1002de60c963701a49e1bc3f155.1519322682.git.anatoly.burakov@intel.com>",
    "list_archive_url": "https://inbox.dpdk.org/dev/df64cdb071cef1002de60c963701a49e1bc3f155.1519322682.git.anatoly.burakov@intel.com",
    "date": "2018-02-22T18:21:15",
    "name": "[dpdk-dev,3/3] eal: use locks to determine if secondary process is active",
    "commit_ref": null,
    "pull_url": null,
    "state": "superseded",
    "archived": true,
    "hash": "de64d8af7bd8a714dcda7a897435fb2694785025",
    "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/df64cdb071cef1002de60c963701a49e1bc3f155.1519322682.git.anatoly.burakov@intel.com/mbox/",
    "series": [],
    "comments": "http://patches.dpdk.org/api/patches/35363/comments/",
    "check": "fail",
    "checks": "http://patches.dpdk.org/api/patches/35363/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 57E571B2A5;\n\tThu, 22 Feb 2018 19:21:24 +0100 (CET)",
            "from mga06.intel.com (mga06.intel.com [134.134.136.31])\n\tby dpdk.org (Postfix) with ESMTP id CF132A493\n\tfor <dev@dpdk.org>; Thu, 22 Feb 2018 19:21:18 +0100 (CET)",
            "from fmsmga007.fm.intel.com ([10.253.24.52])\n\tby orsmga104.jf.intel.com with ESMTP/TLS/DHE-RSA-AES256-GCM-SHA384;\n\t22 Feb 2018 10:21:17 -0800",
            "from irvmail001.ir.intel.com ([163.33.26.43])\n\tby fmsmga007.fm.intel.com with ESMTP; 22 Feb 2018 10:21:16 -0800",
            "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\tw1MILGf4013693 for <dev@dpdk.org>; Thu, 22 Feb 2018 18:21:16 GMT",
            "from sivswdev01.ir.intel.com (localhost [127.0.0.1])\n\tby sivswdev01.ir.intel.com with ESMTP id w1MILGIc022612\n\tfor <dev@dpdk.org>; Thu, 22 Feb 2018 18:21:16 GMT",
            "(from aburakov@localhost)\n\tby sivswdev01.ir.intel.com with LOCAL id w1MILGuB022607\n\tfor dev@dpdk.org; Thu, 22 Feb 2018 18:21:16 GMT"
        ],
        "X-Amp-Result": "SKIPPED(no attachment in message)",
        "X-Amp-File-Uploaded": "False",
        "X-ExtLoop1": "1",
        "X-IronPort-AV": "E=Sophos;i=\"5.47,378,1515484800\"; d=\"scan'208\";a=\"19517163\"",
        "From": "Anatoly Burakov <anatoly.burakov@intel.com>",
        "To": "dev@dpdk.org",
        "Date": "Thu, 22 Feb 2018 18:21:15 +0000",
        "Message-Id": "<df64cdb071cef1002de60c963701a49e1bc3f155.1519322682.git.anatoly.burakov@intel.com>",
        "X-Mailer": "git-send-email 1.7.0.7",
        "In-Reply-To": [
            "<31f6d9ef676fb1eb0a664c06d62d66f32876dcb6.1519322682.git.anatoly.burakov@intel.com>",
            "<31f6d9ef676fb1eb0a664c06d62d66f32876dcb6.1519322682.git.anatoly.burakov@intel.com>"
        ],
        "References": [
            "<31f6d9ef676fb1eb0a664c06d62d66f32876dcb6.1519322682.git.anatoly.burakov@intel.com>",
            "<31f6d9ef676fb1eb0a664c06d62d66f32876dcb6.1519322682.git.anatoly.burakov@intel.com>"
        ],
        "Subject": "[dpdk-dev] [PATCH 3/3] eal: use locks to determine if secondary\n\tprocess is active",
        "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": "Previously, IPC would remove sockets it considers to be \"inactive\"\nbased on whether they have responded. Change this to create lock\nfiles in addition to socket files, so that we can determine if\nsecondary process is active before attempting to communicate with\nit. That way, we can distinguish secondaries that are alive but\nare not responding, from those that have already died.\n\nSigned-off-by: Anatoly Burakov <anatoly.burakov@intel.com>\n---\n lib/librte_eal/common/eal_common_proc.c | 204 +++++++++++++++++++++++++++-----\n 1 file changed, 175 insertions(+), 29 deletions(-)",
    "diff": "diff --git a/lib/librte_eal/common/eal_common_proc.c b/lib/librte_eal/common/eal_common_proc.c\nindex b4d00c3..17fded7 100644\n--- a/lib/librte_eal/common/eal_common_proc.c\n+++ b/lib/librte_eal/common/eal_common_proc.c\n@@ -13,6 +13,7 @@\n #include <stdio.h>\n #include <stdlib.h>\n #include <string.h>\n+#include <sys/file.h>\n #include <sys/time.h>\n #include <sys/types.h>\n #include <sys/socket.h>\n@@ -32,6 +33,7 @@\n #include \"eal_internal_cfg.h\"\n \n static int mp_fd = -1;\n+static int lock_fd = -1;\n static char mp_filter[PATH_MAX];   /* Filter for secondary process sockets */\n static char mp_dir_path[PATH_MAX]; /* The directory path for all mp sockets */\n static pthread_mutex_t mp_mutex_action = PTHREAD_MUTEX_INITIALIZER;\n@@ -104,6 +106,46 @@ find_sync_request(const char *dst, const char *act_name)\n \treturn r;\n }\n \n+static void\n+create_socket_path(const char *name, char *buf, int len)\n+{\n+\tconst char *prefix = eal_mp_socket_path();\n+\tif (strlen(name) > 0)\n+\t\tsnprintf(buf, len, \"%s_%s\", prefix, name);\n+\telse\n+\t\tsnprintf(buf, len, \"%s\", prefix);\n+}\n+\n+static void\n+create_lockfile_path(const char *name, char *buf, int len)\n+{\n+\tconst char *prefix = eal_mp_socket_path();\n+\tif (strlen(name) > 1)\n+\t\tsnprintf(buf, len, \"%slock_%s\", prefix, name);\n+\telse\n+\t\tsnprintf(buf, len, \"%slock\", prefix);\n+}\n+\n+static const char *\n+get_peer_name(const char *socket_full_path)\n+{\n+\tchar buf[PATH_MAX] = {0};\n+\tint len;\n+\n+\t/* primary process has no peer name */\n+\tif (strcmp(socket_full_path, eal_mp_socket_path()) == 0)\n+\t\treturn NULL;\n+\n+\t/* construct dummy socket file name - make it one character long so that\n+\t * we hit the code path where underscores are added\n+\t */\n+\tcreate_socket_path(\"a\", buf, sizeof(buf));\n+\n+\t/* we want to get everything after /path/.rte_unix_, so discard 'a' */\n+\tlen = strlen(buf) - 1;\n+\treturn &socket_full_path[len];\n+}\n+\n int\n rte_eal_primary_proc_alive(const char *config_file_path)\n {\n@@ -330,8 +372,29 @@ mp_handle(void *arg __rte_unused)\n static int\n open_socket_fd(void)\n {\n+\tchar peer_name[PATH_MAX] = {0};\n+\tchar lockfile[PATH_MAX] = {0};\n \tstruct sockaddr_un un;\n-\tconst char *prefix = eal_mp_socket_path();\n+\n+\tif (rte_eal_process_type() == RTE_PROC_SECONDARY)\n+\t\tsnprintf(peer_name, sizeof(peer_name), \"%d_%\"PRIx64,\n+\t\t\t getpid(), rte_rdtsc());\n+\n+\t/* try to create lockfile */\n+\tcreate_lockfile_path(peer_name, lockfile, sizeof(lockfile));\n+\n+\tlock_fd = open(lockfile, O_CREAT | O_RDWR);\n+\tif (lock_fd < 0) {\n+\t\tRTE_LOG(ERR, EAL, \"failed to open '%s': %s\\n\", lockfile,\n+\t\t\tstrerror(errno));\n+\t\treturn -1;\n+\t}\n+\tif (flock(lock_fd, LOCK_EX | LOCK_NB)) {\n+\t\tRTE_LOG(ERR, EAL, \"failed to lock '%s': %s\\n\", lockfile,\n+\t\t\tstrerror(errno));\n+\t\treturn -1;\n+\t}\n+\t/* no need to downgrade to shared lock */\n \n \tmp_fd = socket(AF_UNIX, SOCK_DGRAM, 0);\n \tif (mp_fd < 0) {\n@@ -341,13 +404,11 @@ open_socket_fd(void)\n \n \tmemset(&un, 0, sizeof(un));\n \tun.sun_family = AF_UNIX;\n-\tif (rte_eal_process_type() == RTE_PROC_PRIMARY)\n-\t\tsnprintf(un.sun_path, sizeof(un.sun_path), \"%s\", prefix);\n-\telse {\n-\t\tsnprintf(un.sun_path, sizeof(un.sun_path), \"%s_%d_%\"PRIx64,\n-\t\t\t prefix, getpid(), rte_rdtsc());\n-\t}\n+\n+\tcreate_socket_path(peer_name, un.sun_path, sizeof(un.sun_path));\n+\n \tunlink(un.sun_path); /* May still exist since last run */\n+\n \tif (bind(mp_fd, (struct sockaddr *)&un, sizeof(un)) < 0) {\n \t\tRTE_LOG(ERR, EAL, \"failed to bind %s: %s\\n\",\n \t\t\tun.sun_path, strerror(errno));\n@@ -359,6 +420,44 @@ open_socket_fd(void)\n \treturn mp_fd;\n }\n \n+/* find corresponding lock file and try to lock it */\n+static int\n+socket_is_active(const char *peer_name)\n+{\n+\tchar lockfile[PATH_MAX] = {0};\n+\tint fd, ret = -1;\n+\n+\t/* construct lockfile filename */\n+\tcreate_lockfile_path(peer_name, lockfile, sizeof(lockfile));\n+\n+\t/* try to lock it */\n+\tfd = open(lockfile, O_CREAT | O_RDWR);\n+\tif (fd < 0) {\n+\t\tRTE_LOG(ERR, EAL, \"Cannot open '%s': %s\\n\", lockfile,\n+\t\t\tstrerror(errno));\n+\t\treturn -1;\n+\t}\n+\tret = flock(fd, LOCK_EX | LOCK_NB);\n+\tif (ret < 0) {\n+\t\tif (errno == EWOULDBLOCK) {\n+\t\t\t/* file is locked */\n+\t\t\tret = 1;\n+\t\t} else {\n+\t\t\tRTE_LOG(ERR, EAL, \"Cannot lock '%s': %s\\n\", lockfile,\n+\t\t\t\tstrerror(errno));\n+\t\t\tret = -1;\n+\t\t}\n+\t} else {\n+\t\tret = 0;\n+\t\t/* unlink lockfile automatically */\n+\t\tunlink(lockfile);\n+\t\tflock(fd, LOCK_UN);\n+\t}\n+\tclose(fd);\n+\n+\treturn ret;\n+}\n+\n static int\n unlink_sockets(const char *filter)\n {\n@@ -374,28 +473,33 @@ unlink_sockets(const char *filter)\n \tdir_fd = dirfd(mp_dir);\n \n \twhile ((ent = readdir(mp_dir))) {\n-\t\tif (fnmatch(filter, ent->d_name, 0) == 0)\n+\t\tif (fnmatch(filter, ent->d_name, 0) == 0) {\n+\t\t\tconst char *peer_name;\n+\t\t\tchar path[PATH_MAX];\n+\t\t\tint ret;\n+\n+\t\t\tsnprintf(path, sizeof(path), \"%s/%s\", mp_dir_path,\n+\t\t\t\t ent->d_name);\n+\t\t\tpeer_name = get_peer_name(path);\n+\n+\t\t\tret = socket_is_active(peer_name);\n+\t\t\tif (ret < 0) {\n+\t\t\t\tRTE_LOG(ERR, EAL, \"Error getting socket active status\\n\");\n+\t\t\t\treturn -1;\n+\t\t\t} else if (ret == 1) {\n+\t\t\t\tRTE_LOG(ERR, EAL, \"Socket is active (old secondary process still running?)\\n\");\n+\t\t\t\treturn -1;\n+\t\t\t}\n+\t\t\tRTE_LOG(DEBUG, EAL, \"Removing stale socket file '%s'\\n\",\n+\t\t\t\t\tent->d_name);\n \t\t\tunlinkat(dir_fd, ent->d_name, 0);\n+\t\t}\n \t}\n \n \tclosedir(mp_dir);\n \treturn 0;\n }\n \n-static void\n-unlink_socket_by_path(const char *path)\n-{\n-\tchar *filename;\n-\tchar *fullpath = strdup(path);\n-\n-\tif (!fullpath)\n-\t\treturn;\n-\tfilename = basename(fullpath);\n-\tunlink_sockets(filename);\n-\tfree(fullpath);\n-\tRTE_LOG(INFO, EAL, \"Remove socket %s\\n\", path);\n-}\n-\n int\n rte_mp_channel_init(void)\n {\n@@ -485,10 +589,25 @@ send_msg(const char *dst_path, struct rte_mp_msg *msg, int type)\n \t\trte_errno = errno;\n \t\t/* Check if it caused by peer process exits */\n \t\tif (errno == ECONNREFUSED) {\n-\t\t\t/* We don't unlink the primary's socket here */\n-\t\t\tif (rte_eal_process_type() == RTE_PROC_PRIMARY)\n-\t\t\t\tunlink_socket_by_path(dst_path);\n-\t\t\treturn 0;\n+\t\t\tconst char *peer_name = get_peer_name(dst_path);\n+\t\t\tint active, ret = 0;\n+\n+\t\t\tactive = rte_eal_process_type() == RTE_PROC_PRIMARY ?\n+\t\t\t\t\tsocket_is_active(peer_name) :\n+\t\t\t\t\trte_eal_primary_proc_alive(NULL);\n+\n+\t\t\tif (active > 0) {\n+\t\t\t\tRTE_LOG(ERR, EAL, \"Couldn't communicate with active peer\\n\");\n+\t\t\t} else if (active < 0) {\n+\t\t\t\tRTE_LOG(ERR, EAL, \"Couldn't get peer status\\n\");\n+\t\t\t\tret = -1;\n+\t\t\t} else if (rte_eal_process_type() == RTE_PROC_PRIMARY) {\n+\t\t\t\t/* peer isn't active anymore, so unlink its\n+\t\t\t\t * socket.\n+\t\t\t\t */\n+\t\t\t\tunlink(dst_path);\n+\t\t\t}\n+\t\t\treturn ret;\n \t\t}\n \t\tif (errno == ENOBUFS) {\n \t\t\tRTE_LOG(ERR, EAL, \"Peer cannot receive message %s\\n\",\n@@ -506,7 +625,7 @@ send_msg(const char *dst_path, struct rte_mp_msg *msg, int type)\n static int\n mp_send(struct rte_mp_msg *msg, const char *peer, int type)\n {\n-\tint ret = 0;\n+\tint dir_fd, ret = 0;\n \tDIR *mp_dir;\n \tstruct dirent *ent;\n \n@@ -528,15 +647,28 @@ mp_send(struct rte_mp_msg *msg, const char *peer, int type)\n \t\trte_errno = errno;\n \t\treturn -1;\n \t}\n+\tdir_fd = dirfd(mp_dir);\n \twhile ((ent = readdir(mp_dir))) {\n \t\tchar path[PATH_MAX];\n+\t\tconst char *peer_name;\n+\t\tint active;\n \n \t\tif (fnmatch(mp_filter, ent->d_name, 0) != 0)\n \t\t\tcontinue;\n \n \t\tsnprintf(path, sizeof(path), \"%s/%s\", mp_dir_path,\n \t\t\t ent->d_name);\n-\t\tif (send_msg(path, msg, type) < 0)\n+\t\tpeer_name = get_peer_name(path);\n+\n+\t\t/* only send if we can expect to receive a reply, otherwise\n+\t\t * remove the socket.\n+\t\t */\n+\t\tactive = socket_is_active(peer_name);\n+\t\tif (active < 0)\n+\t\t\tret = -1;\n+\t\telse if (active == 0)\n+\t\t\tunlinkat(dir_fd, ent->d_name, 0);\n+\t\telse if (active > 0 && send_msg(path, msg, type) < 0)\n \t\t\tret = -1;\n \t}\n \n@@ -661,7 +793,7 @@ int __rte_experimental\n rte_mp_request(struct rte_mp_msg *req, struct rte_mp_reply *reply,\n \t\tconst struct timespec *ts)\n {\n-\tint ret = 0;\n+\tint dir_fd, ret = 0;\n \tDIR *mp_dir;\n \tstruct dirent *ent;\n \tstruct timeval now;\n@@ -696,15 +828,29 @@ rte_mp_request(struct rte_mp_msg *req, struct rte_mp_reply *reply,\n \t\trte_errno = errno;\n \t\treturn -1;\n \t}\n+\tdir_fd = dirfd(mp_dir);\n \n \twhile ((ent = readdir(mp_dir))) {\n+\t\tconst char *peer_name;\n \t\tchar path[PATH_MAX];\n+\t\tint active;\n \n \t\tif (fnmatch(mp_filter, ent->d_name, 0) != 0)\n \t\t\tcontinue;\n \n \t\tsnprintf(path, sizeof(path), \"%s/%s\", mp_dir_path,\n \t\t\t ent->d_name);\n+\t\tpeer_name = get_peer_name(path);\n+\n+\t\tactive = socket_is_active(peer_name);\n+\n+\t\tif (active < 0) {\n+\t\t\tret = -1;\n+\t\t\tbreak;\n+\t\t} else if (active == 0) {\n+\t\t\tunlinkat(dir_fd, ent->d_name, 0);\n+\t\t\tcontinue;\n+\t\t}\n \n \t\tif (mp_request_one(path, req, reply, &end))\n \t\t\tret = -1;\n",
    "prefixes": [
        "dpdk-dev",
        "3/3"
    ]
}