From mboxrd@z Thu Jan 1 00:00:00 1970 Authentication-Results: passt.top; dmarc=none (p=none dis=none) header.from=gibson.dropbear.id.au Authentication-Results: passt.top; dkim=pass (2048-bit key; secure) header.d=gibson.dropbear.id.au header.i=@gibson.dropbear.id.au header.a=rsa-sha256 header.s=202502 header.b=ilkaLR9k; dkim-atps=neutral Received: from mail.ozlabs.org (gandalf.ozlabs.org [150.107.74.76]) by passt.top (Postfix) with ESMTPS id 604B25A026F for ; Fri, 28 Mar 2025 01:40:18 +0100 (CET) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gibson.dropbear.id.au; s=202502; t=1743122401; bh=ddWzNryL0CwyQg1LuacqTyMZJlBlnJNKowENrNEGnK8=; h=From:To:Cc:Subject:Date:From; b=ilkaLR9kq7IFJxjV5KgbpSJiTnrCMy/5bz31TgK1dS7kdWBBn33X5DSDfRL72GX+X AvavMua6VTn1ppl47BDVSCyZajPxDrf2CUkQFm7N0iubePPqVHUgcNChAeIc5OyU+K VlIApwCu5MIykJf9dJMd/J5g+lIWrWFxDYzsVD/42Q9nayYuvLymghFl3ceVQpnnXc L/c6ep+M0fiD2I/vol1akINOsBFYVkpBv/yA5qP7m8DfRz1AE/b8cC77SbZVcHN0Gu qNpW03B1qelWESHimYHqf6Cu4SGGDmWAQW7xcuKNs0fuOBGZE+j6LUSI7qmLNSanRm 1EX9tr/Z4Na1Q== Received: by gandalf.ozlabs.org (Postfix, from userid 1007) id 4ZP1rd3Bncz4xD9; Fri, 28 Mar 2025 11:40:01 +1100 (AEDT) From: David Gibson To: passt-dev@passt.top, Stefano Brivio Subject: [PATCH v2] pasta, passt-repair: Support multiple events per read() in inotify handlers Date: Fri, 28 Mar 2025 11:39:58 +1100 Message-ID: <20250328003958.3570775-1-david@gibson.dropbear.id.au> X-Mailer: git-send-email 2.49.0 MIME-Version: 1.0 Content-Transfer-Encoding: 8bit Message-ID-Hash: SOZXJ3LPR7PNUBDT4IYPLCFGJ24GNOZ2 X-Message-ID-Hash: SOZXJ3LPR7PNUBDT4IYPLCFGJ24GNOZ2 X-MailFrom: dgibson@gandalf.ozlabs.org X-Mailman-Rule-Misses: dmarc-mitigation; no-senders; approved; emergency; loop; banned-address; member-moderation; nonmember-moderation; administrivia; implicit-dest; max-recipients; max-size; news-moderation; no-subject; digests; suspicious-header CC: David Gibson X-Mailman-Version: 3.3.8 Precedence: list List-Id: Development discussion and patches for passt Archived-At: Archived-At: List-Archive: List-Archive: List-Help: List-Owner: List-Post: List-Subscribe: List-Unsubscribe: From: Stefano Brivio The current code assumes that we'll get one event per read() on inotify descriptors, but that's not the case, not from documentation, and not from reports. Add loops in the two inotify handlers we have, in pasta-specific code and passt-repair, to go through all the events we receive. Link: https://bugs.passt.top/show_bug.cgi?id=119 Signed-off-by: Stefano Brivio [dwg: Remove unnecessary buffer expansion, use strnlen instead of strlen to make Coverity happier] Signed-off-by: David Gibson --- passt-repair.c | 27 ++++++++++++++++++++------- pasta.c | 20 +++++++++++++------- 2 files changed, 33 insertions(+), 14 deletions(-) diff --git a/passt-repair.c b/passt-repair.c index 120f7aa7..d36c9c94 100644 --- a/passt-repair.c +++ b/passt-repair.c @@ -111,14 +111,14 @@ int main(int argc, char **argv) } if ((sb.st_mode & S_IFMT) == S_IFDIR) { - char buf[sizeof(struct inotify_event) + NAME_MAX + 1]; + char buf[sizeof(struct inotify_event) + NAME_MAX + 1] + __attribute__ ((aligned(__alignof__(struct inotify_event)))); const struct inotify_event *ev; char path[PATH_MAX + 1]; + bool found = false; ssize_t n; int fd; - ev = (struct inotify_event *)buf; - if ((fd = inotify_init1(IN_CLOEXEC)) < 0) { fprintf(stderr, "inotify_init1: %i\n", errno); _exit(1); @@ -130,6 +130,8 @@ int main(int argc, char **argv) } do { + char *p; + n = read(fd, buf, sizeof(buf)); if (n < 0) { fprintf(stderr, "inotify read: %i", errno); @@ -138,11 +140,22 @@ int main(int argc, char **argv) if (n < (ssize_t)sizeof(*ev)) { fprintf(stderr, "Short inotify read: %zi", n); - _exit(1); + continue; + } + + for (p = buf; p < buf + n; p += sizeof(*ev) + ev->len) { + ev = (const struct inotify_event *)p; + + if (ev->len >= REPAIR_EXT_LEN && + !memcmp(ev->name + + strnlen(ev->name, ev->len) - + REPAIR_EXT_LEN, + REPAIR_EXT, REPAIR_EXT_LEN)) { + found = true; + break; + } } - } while (ev->len < REPAIR_EXT_LEN || - memcmp(ev->name + strlen(ev->name) - REPAIR_EXT_LEN, - REPAIR_EXT, REPAIR_EXT_LEN)); + } while (!found); snprintf(path, sizeof(path), "%s/%s", argv[1], ev->name); if ((stat(path, &sb))) { diff --git a/pasta.c b/pasta.c index fa3e7de5..017fa322 100644 --- a/pasta.c +++ b/pasta.c @@ -498,17 +498,23 @@ void pasta_netns_quit_init(const struct ctx *c) */ void pasta_netns_quit_inotify_handler(struct ctx *c, int inotify_fd) { - char buf[sizeof(struct inotify_event) + NAME_MAX + 1]; - const struct inotify_event *in_ev = (struct inotify_event *)buf; + char buf[sizeof(struct inotify_event) + NAME_MAX + 1] + __attribute__ ((aligned(__alignof__(struct inotify_event)))); + const struct inotify_event *ev; + ssize_t n; + char *p; - if (read(inotify_fd, buf, sizeof(buf)) < (ssize_t)sizeof(*in_ev)) + if ((n = read(inotify_fd, buf, sizeof(buf))) < (ssize_t)sizeof(*ev)) return; - if (strncmp(in_ev->name, c->netns_base, sizeof(c->netns_base))) - return; + for (p = buf; p < buf + n; p += sizeof(*ev) + ev->len) { + ev = (const struct inotify_event *)p; - info("Namespace %s is gone, exiting", c->netns_base); - _exit(EXIT_SUCCESS); + if (!strncmp(ev->name, c->netns_base, sizeof(c->netns_base))) { + info("Namespace %s is gone, exiting", c->netns_base); + _exit(EXIT_SUCCESS); + } + } } /** -- 2.49.0