From patchwork Thu Feb 15 10:29:32 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Eric DeCosta X-Patchwork-Id: 13557870 Received: from mail-lf1-f47.google.com (mail-lf1-f47.google.com [209.85.167.47]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 928B167E8B for ; Thu, 15 Feb 2024 10:29:43 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.167.47 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1707992985; cv=none; b=rb1AUkcG2wsgs1hTEYL+qmnECu79bchKiBRDkuV2UxLHTz6x0vyz6Ta8ctURw48UEN+5wlU+5pYqOV6f4ugF3qAOppJXkoEXaIUaUdMiJbZaN3/iwNKBfNKhPI88CigTRZOHshzQDGK24LP1ks66IukbWRXJ2kZZqv+l7uidemI= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1707992985; c=relaxed/simple; bh=t8KWApBpQqCyUO351NTSTy0SVWndYeQKS63dUZxx9Oc=; h=Message-ID:In-Reply-To:References:From:Date:Subject:Content-Type: MIME-Version:To:Cc; b=X5IdMPhDrymsNDoF2RoEb7Jnk0z2AJ7pZukD9y0FNxXuC9t6cTOxxfvQGG0wIEuZdx8naD/u81c9cwVksxop/b08VWG8LEinww+7UZzQ1TnY7UGt3hIrzsAUH9mUSZe67F+YlawmKN9iJoVctIM0d7WKvAaAnkEQALCCKRRiNbE= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=gmail.com; spf=pass smtp.mailfrom=gmail.com; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b=hfRGFwu4; arc=none smtp.client-ip=209.85.167.47 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=gmail.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=gmail.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b="hfRGFwu4" Received: by mail-lf1-f47.google.com with SMTP id 2adb3069b0e04-511ac32fe38so1097822e87.1 for ; Thu, 15 Feb 2024 02:29:43 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20230601; t=1707992981; x=1708597781; darn=vger.kernel.org; h=cc:to:mime-version:content-transfer-encoding:fcc:subject:date:from :references:in-reply-to:message-id:from:to:cc:subject:date :message-id:reply-to; bh=3WOZYu1ABQvI0PZXp/i2IDZ9BkIUgU3t3A1/nH+ofTY=; b=hfRGFwu4ns1E+52wLLT/M4jtWvg2Rhd+Ah7oQmCqn8rluAjRN35xg+0DyDCF8oNmsu RxNzoBTRgMpVb5H54UD3wT67zLB/nitDFTJMDhluUkSfPvkoYqGZfwJbAZiBaE2ZaePQ vtC+ivt+XIfLtMU7K9jjrRzncGHNk6sGEPn5D5COnYTOnPnBiblsCPGPyt6JLS2oBeaP WtfZqVA/UgdBFZzd3qqTDv7ItZr4iCVpHLvKIBQMV7SeT5jpUwNHuswWMhs187ojlaf0 OTJYhvwnLL450ZUYEdtjgTABSLENJGLJdMvSJcj0ffPNATKCKxQQE7JVliML5goYlyg2 FhGg== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1707992981; x=1708597781; h=cc:to:mime-version:content-transfer-encoding:fcc:subject:date:from :references:in-reply-to:message-id:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=3WOZYu1ABQvI0PZXp/i2IDZ9BkIUgU3t3A1/nH+ofTY=; b=OlPwq5lsLOzEOOyiGwWeFuQQprIIncysf++HTolcVdOl72j6O+qMiRdlK1cuUZVJVg u1oHrH++m79+yc6tp2BGhFyyPoRMGYDGiB0IIIBf2gNHeFO1CWzefbRu0PqD2kgw5bnk sPxMKwnS2xRwBENrT8eccE3V3fLqj++DLCeveIgU8RneUoWk+fLeV1/kzBQNKdcoNe54 LFr2LScXUcpWK8Xp83JCmtw9LeMsiUdfARQYsMUEVgGpkaCZwnF6+VBKHA+rfuR9TId+ WMgQdvh+s40qspnHsyRS9tZe5OxUcj7yWbLZCbNvpgZqcdgW5Ry+3U/tgKBUfSiIWkUc UMtA== X-Gm-Message-State: AOJu0YzuQEVtpAjoxoUpP3vGdkEnM4bhiRlEM5A7Mhvyo9/dH1AWK96D tvlekbWYiRcaWMddX/neUEKNmcKJAIKIknOcUzbwHDEIBaNWHN8gs0aB/+Ez X-Google-Smtp-Source: AGHT+IGASUNnChhOj+iYzErwY/2RD2EFBRWppn1M4D9gZt1g71tQM+VozLAGDCLUYRqvJy8//3HEFg== X-Received: by 2002:a05:6512:312c:b0:511:ab37:b2ae with SMTP id p12-20020a056512312c00b00511ab37b2aemr1109909lfd.20.1707992980588; Thu, 15 Feb 2024 02:29:40 -0800 (PST) Received: from [127.0.0.1] ([13.74.141.28]) by smtp.gmail.com with ESMTPSA id b20-20020a05600c4e1400b00411a595d56bsm1596966wmq.14.2024.02.15.02.29.40 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Thu, 15 Feb 2024 02:29:40 -0800 (PST) Message-ID: <5973bbe18aeecf486d8256cc402285665c45e66a.1707992978.git.gitgitgadget@gmail.com> In-Reply-To: References: Date: Thu, 15 Feb 2024 10:29:32 +0000 Subject: [PATCH 1/7] fsmonitor: rebase with master Fcc: Sent Precedence: bulk X-Mailing-List: git@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 To: git@vger.kernel.org Cc: "Eric Sunshine [ ]" , " =?utf-8?b?w4Z2YXIgQXJu?= =?utf-8?b?ZmrDtnLDsA==?= Bjarmason [ ]" , "Glen Choo [ ]" , "Johannes Schindelin [ ]" , "Taylor Blau [ ]" , marzi , Eric DeCosta From: Eric DeCosta From: Eric DeCosta rebased with master, and resolved conflicts Signed-off-by: Eric DeCosta Signed-off-by: Eric DeCosta Signed-off-by: Marzieh Esipreh --- compat/fsmonitor/fsm-health-linux.c | 24 ++++++++++ compat/fsmonitor/fsm-ipc-darwin.c | 57 +---------------------- compat/fsmonitor/fsm-ipc-linux.c | 1 + compat/fsmonitor/fsm-ipc-unix.c | 53 +++++++++++++++++++++ compat/fsmonitor/fsm-settings-darwin.c | 64 +------------------------- compat/fsmonitor/fsm-settings-linux.c | 1 + compat/fsmonitor/fsm-settings-unix.c | 61 ++++++++++++++++++++++++ 7 files changed, 142 insertions(+), 119 deletions(-) create mode 100644 compat/fsmonitor/fsm-health-linux.c create mode 100644 compat/fsmonitor/fsm-ipc-linux.c create mode 100644 compat/fsmonitor/fsm-ipc-unix.c create mode 100644 compat/fsmonitor/fsm-settings-linux.c create mode 100644 compat/fsmonitor/fsm-settings-unix.c diff --git a/compat/fsmonitor/fsm-health-linux.c b/compat/fsmonitor/fsm-health-linux.c new file mode 100644 index 00000000000..b9f709e8548 --- /dev/null +++ b/compat/fsmonitor/fsm-health-linux.c @@ -0,0 +1,24 @@ +#include "cache.h" +#include "config.h" +#include "fsmonitor.h" +#include "fsm-health.h" +#include "fsmonitor--daemon.h" + +int fsm_health__ctor(struct fsmonitor_daemon_state *state) +{ + return 0; +} + +void fsm_health__dtor(struct fsmonitor_daemon_state *state) +{ + return; +} + +void fsm_health__loop(struct fsmonitor_daemon_state *state) +{ + return; +} + +void fsm_health__stop_async(struct fsmonitor_daemon_state *state) +{ +} diff --git a/compat/fsmonitor/fsm-ipc-darwin.c b/compat/fsmonitor/fsm-ipc-darwin.c index 6f3a95410cc..4c3c92081ee 100644 --- a/compat/fsmonitor/fsm-ipc-darwin.c +++ b/compat/fsmonitor/fsm-ipc-darwin.c @@ -1,56 +1 @@ -#include "git-compat-util.h" -#include "config.h" -#include "gettext.h" -#include "hex.h" -#include "path.h" -#include "repository.h" -#include "strbuf.h" -#include "fsmonitor-ll.h" -#include "fsmonitor-ipc.h" -#include "fsmonitor-path-utils.h" - -static GIT_PATH_FUNC(fsmonitor_ipc__get_default_path, "fsmonitor--daemon.ipc") - -const char *fsmonitor_ipc__get_path(struct repository *r) -{ - static const char *ipc_path = NULL; - git_SHA_CTX sha1ctx; - char *sock_dir = NULL; - struct strbuf ipc_file = STRBUF_INIT; - unsigned char hash[GIT_MAX_RAWSZ]; - - if (!r) - BUG("No repository passed into fsmonitor_ipc__get_path"); - - if (ipc_path) - return ipc_path; - - - /* By default the socket file is created in the .git directory */ - if (fsmonitor__is_fs_remote(r->gitdir) < 1) { - ipc_path = fsmonitor_ipc__get_default_path(); - return ipc_path; - } - - git_SHA1_Init(&sha1ctx); - git_SHA1_Update(&sha1ctx, r->worktree, strlen(r->worktree)); - git_SHA1_Final(hash, &sha1ctx); - - repo_config_get_string(r, "fsmonitor.socketdir", &sock_dir); - - /* Create the socket file in either socketDir or $HOME */ - if (sock_dir && *sock_dir) { - strbuf_addf(&ipc_file, "%s/.git-fsmonitor-%s", - sock_dir, hash_to_hex(hash)); - } else { - strbuf_addf(&ipc_file, "~/.git-fsmonitor-%s", hash_to_hex(hash)); - } - free(sock_dir); - - ipc_path = interpolate_path(ipc_file.buf, 1); - if (!ipc_path) - die(_("Invalid path: %s"), ipc_file.buf); - - strbuf_release(&ipc_file); - return ipc_path; -} +#include "fsm-ipc-unix.c" diff --git a/compat/fsmonitor/fsm-ipc-linux.c b/compat/fsmonitor/fsm-ipc-linux.c new file mode 100644 index 00000000000..4c3c92081ee --- /dev/null +++ b/compat/fsmonitor/fsm-ipc-linux.c @@ -0,0 +1 @@ +#include "fsm-ipc-unix.c" diff --git a/compat/fsmonitor/fsm-ipc-unix.c b/compat/fsmonitor/fsm-ipc-unix.c new file mode 100644 index 00000000000..eb25123fa12 --- /dev/null +++ b/compat/fsmonitor/fsm-ipc-unix.c @@ -0,0 +1,53 @@ +#include "cache.h" +#include "config.h" +#include "hex.h" +#include "strbuf.h" +#include "fsmonitor.h" +#include "fsmonitor-ipc.h" +#include "fsmonitor-path-utils.h" + +static GIT_PATH_FUNC(fsmonitor_ipc__get_default_path, "fsmonitor--daemon.ipc") + +const char *fsmonitor_ipc__get_path(struct repository *r) +{ + static const char *ipc_path = NULL; + git_SHA_CTX sha1ctx; + char *sock_dir = NULL; + struct strbuf ipc_file = STRBUF_INIT; + unsigned char hash[GIT_MAX_RAWSZ]; + + if (!r) + BUG("No repository passed into fsmonitor_ipc__get_path"); + + if (ipc_path) + return ipc_path; + + + /* By default the socket file is created in the .git directory */ + if (fsmonitor__is_fs_remote(r->gitdir) < 1) { + ipc_path = fsmonitor_ipc__get_default_path(); + return ipc_path; + } + + git_SHA1_Init(&sha1ctx); + git_SHA1_Update(&sha1ctx, r->worktree, strlen(r->worktree)); + git_SHA1_Final(hash, &sha1ctx); + + repo_config_get_string(r, "fsmonitor.socketdir", &sock_dir); + + /* Create the socket file in either socketDir or $HOME */ + if (sock_dir && *sock_dir) { + strbuf_addf(&ipc_file, "%s/.git-fsmonitor-%s", + sock_dir, hash_to_hex(hash)); + } else { + strbuf_addf(&ipc_file, "~/.git-fsmonitor-%s", hash_to_hex(hash)); + } + free(sock_dir); + + ipc_path = interpolate_path(ipc_file.buf, 1); + if (!ipc_path) + die(_("Invalid path: %s"), ipc_file.buf); + + strbuf_release(&ipc_file); + return ipc_path; +} diff --git a/compat/fsmonitor/fsm-settings-darwin.c b/compat/fsmonitor/fsm-settings-darwin.c index a3825906351..14baf9f0603 100644 --- a/compat/fsmonitor/fsm-settings-darwin.c +++ b/compat/fsmonitor/fsm-settings-darwin.c @@ -1,63 +1 @@ -#include "git-compat-util.h" -#include "config.h" -#include "fsmonitor-ll.h" -#include "fsmonitor-ipc.h" -#include "fsmonitor-settings.h" -#include "fsmonitor-path-utils.h" - - /* - * For the builtin FSMonitor, we create the Unix domain socket for the - * IPC in the .git directory. If the working directory is remote, - * then the socket will be created on the remote file system. This - * can fail if the remote file system does not support UDS file types - * (e.g. smbfs to a Windows server) or if the remote kernel does not - * allow a non-local process to bind() the socket. (These problems - * could be fixed by moving the UDS out of the .git directory and to a - * well-known local directory on the client machine, but care should - * be taken to ensure that $HOME is actually local and not a managed - * file share.) - * - * FAT32 and NTFS working directories are problematic too. - * - * The builtin FSMonitor uses a Unix domain socket in the .git - * directory for IPC. These Windows drive formats do not support - * Unix domain sockets, so mark them as incompatible for the daemon. - * - */ -static enum fsmonitor_reason check_uds_volume(struct repository *r) -{ - struct fs_info fs; - const char *ipc_path = fsmonitor_ipc__get_path(r); - struct strbuf path = STRBUF_INIT; - strbuf_add(&path, ipc_path, strlen(ipc_path)); - - if (fsmonitor__get_fs_info(dirname(path.buf), &fs) == -1) { - strbuf_release(&path); - return FSMONITOR_REASON_ERROR; - } - - strbuf_release(&path); - - if (fs.is_remote || - !strcmp(fs.typename, "msdos") || - !strcmp(fs.typename, "ntfs")) { - free(fs.typename); - return FSMONITOR_REASON_NOSOCKETS; - } - - free(fs.typename); - return FSMONITOR_REASON_OK; -} - -enum fsmonitor_reason fsm_os__incompatible(struct repository *r, int ipc) -{ - enum fsmonitor_reason reason; - - if (ipc) { - reason = check_uds_volume(r); - if (reason != FSMONITOR_REASON_OK) - return reason; - } - - return FSMONITOR_REASON_OK; -} +#include "fsm-settings-unix.c" diff --git a/compat/fsmonitor/fsm-settings-linux.c b/compat/fsmonitor/fsm-settings-linux.c new file mode 100644 index 00000000000..14baf9f0603 --- /dev/null +++ b/compat/fsmonitor/fsm-settings-linux.c @@ -0,0 +1 @@ +#include "fsm-settings-unix.c" diff --git a/compat/fsmonitor/fsm-settings-unix.c b/compat/fsmonitor/fsm-settings-unix.c new file mode 100644 index 00000000000..d16dca89416 --- /dev/null +++ b/compat/fsmonitor/fsm-settings-unix.c @@ -0,0 +1,61 @@ +#include "fsmonitor.h" +#include "fsmonitor-ipc.h" +#include "fsmonitor-path-utils.h" + + /* + * For the builtin FSMonitor, we create the Unix domain socket for the + * IPC in the .git directory. If the working directory is remote, + * then the socket will be created on the remote file system. This + * can fail if the remote file system does not support UDS file types + * (e.g. smbfs to a Windows server) or if the remote kernel does not + * allow a non-local process to bind() the socket. (These problems + * could be fixed by moving the UDS out of the .git directory and to a + * well-known local directory on the client machine, but care should + * be taken to ensure that $HOME is actually local and not a managed + * file share.) + * + * FAT32 and NTFS working directories are problematic too. + * + * The builtin FSMonitor uses a Unix domain socket in the .git + * directory for IPC. These Windows drive formats do not support + * Unix domain sockets, so mark them as incompatible for the daemon. + * + */ +static enum fsmonitor_reason check_uds_volume(struct repository *r) +{ + struct fs_info fs; + const char *ipc_path = fsmonitor_ipc__get_path(r); + struct strbuf path = STRBUF_INIT; + strbuf_addstr(&path, ipc_path); + + if (fsmonitor__get_fs_info(dirname(path.buf), &fs) == -1) { + free(fs.typename); + strbuf_release(&path); + return FSMONITOR_REASON_ERROR; + } + + strbuf_release(&path); + + if (fs.is_remote || + !strcmp(fs.typename, "msdos") || + !strcmp(fs.typename, "ntfs")) { + free(fs.typename); + return FSMONITOR_REASON_NOSOCKETS; + } + + free(fs.typename); + return FSMONITOR_REASON_OK; +} + +enum fsmonitor_reason fsm_os__incompatible(struct repository *r, int ipc) +{ + enum fsmonitor_reason reason; + + if (ipc) { + reason = check_uds_volume(r); + if (reason != FSMONITOR_REASON_OK) + return reason; + } + + return FSMONITOR_REASON_OK; +} From patchwork Thu Feb 15 10:29:33 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Eric DeCosta X-Patchwork-Id: 13557871 Received: from mail-wr1-f42.google.com (mail-wr1-f42.google.com [209.85.221.42]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id E85736994E for ; Thu, 15 Feb 2024 10:29:44 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.221.42 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1707992987; cv=none; b=DXEwR0mbjOp474kcFodNyv6hWHb5dmX94IHtVGIpEUjrrFD3whbfvfoxCMhXsj3Fm6jSxWLSbpusCoPVIs30a54go0iczRs2+Tv1sroUxUCPQvYW+xcGuQwdkWecHc5Q/Lrlo+1vYseL9M4ggxpvityrAU2UE0UHa2ynx/2USpE= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1707992987; c=relaxed/simple; bh=DYZSLOpxSIEvCpSwGORyOFXDTIvbE33cxKTEN+w6Amc=; h=Message-ID:In-Reply-To:References:From:Date:Subject:Content-Type: MIME-Version:To:Cc; b=M6mJ63XnjcXABLROjPFwduWntR4Nyxq4rYfW4QaP8Pd0JTRoj/bRKjq94avmIx0Th1E+Kp/qAPVlCou5g6pG8Xrb3JUggFyisGD8uZgENV+FAfxnegr7EVlsN2Xz3hiVcGibEGPY1eq5LTKs2VLP4W3Ti00cwtPG0Leqk/i6A88= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=gmail.com; spf=pass smtp.mailfrom=gmail.com; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b=OYQmJ1m+; arc=none smtp.client-ip=209.85.221.42 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=gmail.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=gmail.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b="OYQmJ1m+" Received: by mail-wr1-f42.google.com with SMTP id ffacd0b85a97d-33b66a7f859so199526f8f.3 for ; Thu, 15 Feb 2024 02:29:44 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20230601; t=1707992982; x=1708597782; darn=vger.kernel.org; h=cc:to:mime-version:content-transfer-encoding:fcc:subject:date:from :references:in-reply-to:message-id:from:to:cc:subject:date :message-id:reply-to; bh=/1jAhoRlRsCqkRqgq7RZ8OT6pU79N2PhXbptllXA09A=; b=OYQmJ1m+AhGApgS4rdtcOxC6WF18g50WMaPyl56WrPTH/FHFLwVS6Rm76i0iHnP9dK QG94w04jx6W/SOYRfpNo0aoWaX3QaxY7SWHdeu0s3B3li5c/na0a/ZxRdf86o/NeDXdd yslKDgii6hCk8HiqBe1oDmPy43LXiCecdaf0eyL712ApKzTnpTJthgZ9CumaMU/8kVFS GDqq/z/5Shwn2vjhkyhnVeTyX8vinjDbFl+FZJu2vbbxux/NiDdofSy+Wfr0EUmWrJJp 0pjX7Zb0VG3edzvU38ggjuG13XmAGPXNJL9QC+jYH8XD/SYnPpUjMTy/xO6Nw4dDTvOZ VXpQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1707992982; x=1708597782; h=cc:to:mime-version:content-transfer-encoding:fcc:subject:date:from :references:in-reply-to:message-id:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=/1jAhoRlRsCqkRqgq7RZ8OT6pU79N2PhXbptllXA09A=; b=DjYdYU2uwE/7KWDDMiyZp63lLrGyXxnsfXNF7/aiyQhFXyGyFayHiakcm6ovZ7Zo43 bNrQdeqcv/I50TpOBfVRgD82rgxq9xkJRXrEYICCA7T8RvglrJKfe32pnZV6FKfNBLKt nFEgHqZjTu1PZ9N7cJBAb0bdD4quv1j97OEpJvrIsiIB6733O2QRStcSiB1pdcqcB1DF JV1JqY9NHVxvW4K2mo3OGsGtpYJWNonBRuqDxW66mb13jHcpZx10+2KhTAwcIrgVNQCH aEtFXO6P5Q+4D2sggCCd00BOaJn7MybAza5suTw1IS8dN4LhhkpmCaLoUdYwlG7VsEoV bgAw== X-Gm-Message-State: AOJu0YxVeM8EPGtvjM6/p/rWdBn9UNdOOzwBUD+OgXtq9D/7TCN/GhvB /irjXAvThKT1lAf0ECg3Zc73avwb4YsFgaHtBjOMf97XTApXTX/wGuFf6wls X-Google-Smtp-Source: AGHT+IFYkpz3Liu+o6AIDwoYRwVvX7yrW47zQotIPOjMTK64t6pTBvkfIjgwoiEDV6y9d3bMI1BERA== X-Received: by 2002:adf:db4a:0:b0:33b:179d:d9aa with SMTP id f10-20020adfdb4a000000b0033b179dd9aamr1123301wrj.26.1707992982168; Thu, 15 Feb 2024 02:29:42 -0800 (PST) Received: from [127.0.0.1] ([13.74.141.28]) by smtp.gmail.com with ESMTPSA id l13-20020a5d4bcd000000b0033b784c2775sm1353835wrt.43.2024.02.15.02.29.40 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Thu, 15 Feb 2024 02:29:40 -0800 (PST) Message-ID: In-Reply-To: References: Date: Thu, 15 Feb 2024 10:29:33 +0000 Subject: [PATCH 2/7] fsmonitor: determine if filesystem is local or remote Fcc: Sent Precedence: bulk X-Mailing-List: git@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 To: git@vger.kernel.org Cc: "Eric Sunshine [ ]" , " =?utf-8?b?w4Z2YXIgQXJu?= =?utf-8?b?ZmrDtnLDsA==?= Bjarmason [ ]" , "Glen Choo [ ]" , "Johannes Schindelin [ ]" , "Taylor Blau [ ]" , marzi , Eric DeCosta From: Eric DeCosta From: Eric DeCosta Compare the given path to the mounted filesystems. Find the mount that is the longest prefix of the path (if any) and determine if that mount is on a local or remote filesystem. Signed-off-by: Eric DeCosta --- Makefile | 4 + compat/fsmonitor/fsm-path-utils-linux.c | 195 ++++++++++++++++++++++++ compat/fsmonitor/fsm-path-utils-linux.h | 91 +++++++++++ config.mak.uname | 11 ++ 4 files changed, 301 insertions(+) create mode 100644 compat/fsmonitor/fsm-path-utils-linux.c create mode 100644 compat/fsmonitor/fsm-path-utils-linux.h diff --git a/Makefile b/Makefile index 78e874099d9..0f36a0fd83a 100644 --- a/Makefile +++ b/Makefile @@ -2088,6 +2088,10 @@ ifdef HAVE_CLOCK_GETTIME BASIC_CFLAGS += -DHAVE_CLOCK_GETTIME endif +ifdef HAVE_LINUX_MAGIC_H + BASIC_CFLAGS += -DHAVE_LINUX_MAGIC_H +endif + ifdef HAVE_CLOCK_MONOTONIC BASIC_CFLAGS += -DHAVE_CLOCK_MONOTONIC endif diff --git a/compat/fsmonitor/fsm-path-utils-linux.c b/compat/fsmonitor/fsm-path-utils-linux.c new file mode 100644 index 00000000000..c21d1349532 --- /dev/null +++ b/compat/fsmonitor/fsm-path-utils-linux.c @@ -0,0 +1,195 @@ +#include "git-compat-util.h" +#include "abspath.h" +#include "fsmonitor.h" +#include "fsmonitor-path-utils.h" +#include "fsm-path-utils-linux.h" +#include +#include +#include +#include +#include + +static int is_remote_fs(const char *path) +{ + struct statfs fs; + + if (statfs(path, &fs)) + return error_errno(_("statfs('%s') failed"), path); + + switch (fs.f_type) { + case ACFS_SUPER_MAGIC: + case AFS_SUPER_MAGIC: + case CEPH_SUPER_MAGIC: + case CIFS_SUPER_MAGIC: + case CODA_SUPER_MAGIC: + case FHGFS_SUPER_MAGIC: + case GFS_SUPER_MAGIC: + case GPFS_SUPER_MAGIC: + case IBRIX_SUPER_MAGIC: + case KAFS_SUPER_MAGIC: + case LUSTRE_SUPER_MAGIC: + case NCP_SUPER_MAGIC: + case NFS_SUPER_MAGIC: + case NFSD_SUPER_MAGIC: + case OCFS2_SUPER_MAGIC: + case PANFS_SUPER_MAGIC: + case SMB_SUPER_MAGIC: + case SMB2_SUPER_MAGIC: + case SNFS_SUPER_MAGIC: + case VMHGFS_SUPER_MAGIC: + case VXFS_SUPER_MAGIC: + return 1; + default: + return 0; + } +} + +static int find_mount(const char *path, const struct statvfs *fs, + struct mntent *entry) +{ + const char *const mounts = "/proc/mounts"; + char *rp = real_pathdup(path, 1); + struct mntent *ment = NULL; + struct statvfs mntfs; + FILE *fp; + int found = 0; + int ret = 0; + size_t dlen, plen, flen = 0; + + entry->mnt_fsname = NULL; + entry->mnt_dir = NULL; + entry->mnt_type = NULL; + + fp = setmntent(mounts, "r"); + if (!fp) { + free(rp); + return error_errno(_("setmntent('%s') failed"), mounts); + } + + plen = strlen(rp); + + /* read all the mount information and compare to path */ + while ((ment = getmntent(fp))) { + if (statvfs(ment->mnt_dir, &mntfs)) { + switch (errno) { + case EPERM: + case ESRCH: + case EACCES: + continue; + default: + error_errno(_("statvfs('%s') failed"), ment->mnt_dir); + ret = -1; + goto done; + } + } + + /* is mount on the same filesystem and is a prefix of the path */ + if ((fs->f_fsid == mntfs.f_fsid) && + !strncmp(ment->mnt_dir, rp, strlen(ment->mnt_dir))) { + dlen = strlen(ment->mnt_dir); + if (dlen > plen) + continue; + /* + * look for the longest prefix (including root) + */ + if (dlen > flen && + ((dlen == 1 && ment->mnt_dir[0] == '/') || + (!rp[dlen] || rp[dlen] == '/'))) { + flen = dlen; + found = 1; + + /* + * https://man7.org/linux/man-pages/man3/getmntent.3.html + * + * The pointer points to a static area of memory which is + * overwritten by subsequent calls to getmntent(). + */ + free(entry->mnt_fsname); + free(entry->mnt_dir); + free(entry->mnt_type); + entry->mnt_fsname = xstrdup(ment->mnt_fsname); + entry->mnt_dir = xstrdup(ment->mnt_dir); + entry->mnt_type = xstrdup(ment->mnt_type); + } + } + } + +done: + free(rp); + endmntent(fp); + + if (!found) + return -1; + + return ret; +} + +int fsmonitor__get_fs_info(const char *path, struct fs_info *fs_info) +{ + int ret = 0; + struct mntent entry; + struct statvfs fs; + + fs_info->is_remote = -1; + fs_info->typename = NULL; + + if (statvfs(path, &fs)) + return error_errno(_("statvfs('%s') failed"), path); + + if (find_mount(path, &fs, &entry) < 0) { + ret = -1; + goto done; + } + + trace_printf_key(&trace_fsmonitor, + "statvfs('%s') [flags 0x%08lx] '%s' '%s'", + path, fs.f_flag, entry.mnt_type, entry.mnt_fsname); + + fs_info->is_remote = is_remote_fs(entry.mnt_dir); + fs_info->typename = xstrdup(entry.mnt_fsname); + + if (fs_info->is_remote < 0) + ret = -1; + + trace_printf_key(&trace_fsmonitor, + "'%s' is_remote: %d", + path, fs_info->is_remote); + +done: + free(entry.mnt_fsname); + free(entry.mnt_dir); + free(entry.mnt_type); + return ret; +} + +int fsmonitor__is_fs_remote(const char *path) +{ + int ret = 0; + struct fs_info fs; + + if (fsmonitor__get_fs_info(path, &fs)) + ret = -1; + else + ret = fs.is_remote; + + free(fs.typename); + + return ret; +} + +/* + * No-op for now. + */ +int fsmonitor__get_alias(const char *path, struct alias_info *info) +{ + return 0; +} + +/* + * No-op for now. + */ +char *fsmonitor__resolve_alias(const char *path, + const struct alias_info *info) +{ + return NULL; +} diff --git a/compat/fsmonitor/fsm-path-utils-linux.h b/compat/fsmonitor/fsm-path-utils-linux.h new file mode 100644 index 00000000000..49bdb3c4728 --- /dev/null +++ b/compat/fsmonitor/fsm-path-utils-linux.h @@ -0,0 +1,91 @@ +#ifndef FSM_PATH_UTILS_LINUX_H +#define FSM_PATH_UTILS_LINUX_H +#endif + +#ifdef HAVE_LINUX_MAGIC_H +#include +#endif + +#ifndef ACFS_SUPER_MAGIC +#define ACFS_SUPER_MAGIC 0x61636673 +#endif + +#ifndef AFS_SUPER_MAGIC +#define AFS_SUPER_MAGIC 0x5346414f +#endif + +#ifndef CEPH_SUPER_MAGIC +#define CEPH_SUPER_MAGIC 0x00c36400 +#endif + +#ifndef CIFS_SUPER_MAGIC +#define CIFS_SUPER_MAGIC 0xff534d42 +#endif + +#ifndef CODA_SUPER_MAGIC +#define CODA_SUPER_MAGIC 0x73757245 +#endif + +#ifndef FHGFS_SUPER_MAGIC +#define FHGFS_SUPER_MAGIC 0x19830326 +#endif + +#ifndef GFS_SUPER_MAGIC +#define GFS_SUPER_MAGIC 0x1161970 +#endif + +#ifndef GPFS_SUPER_MAGIC +#define GPFS_SUPER_MAGIC 0x47504653 +#endif + +#ifndef IBRIX_SUPER_MAGIC +#define IBRIX_SUPER_MAGIC 0x013111a8 +#endif + +#ifndef KAFS_SUPER_MAGIC +#define KAFS_SUPER_MAGIC 0x6b414653 +#endif + +#ifndef LUSTRE_SUPER_MAGIC +#define LUSTRE_SUPER_MAGIC 0x0bd00bd0 +#endif + +#ifndef NCP_SUPER_MAGIC +#define NCP_SUPER_MAGIC 0x564c +#endif + +#ifndef NFS_SUPER_MAGIC +#define NFS_SUPER_MAGIC 0x6969 +#endif + +#ifndef NFSD_SUPER_MAGIC +#define NFSD_SUPER_MAGIC 0x6e667364 +#endif + +#ifndef OCFS2_SUPER_MAGIC +#define OCFS2_SUPER_MAGIC 0x7461636f +#endif + +#ifndef PANFS_SUPER_MAGIC +#define PANFS_SUPER_MAGIC 0xaad7aaea +#endif + +#ifndef SMB_SUPER_MAGIC +#define SMB_SUPER_MAGIC 0x517b +#endif + +#ifndef SMB2_SUPER_MAGIC +#define SMB2_SUPER_MAGIC 0xfe534d42 +#endif + +#ifndef SNFS_SUPER_MAGIC +#define SNFS_SUPER_MAGIC 0xbeefdead +#endif + +#ifndef VMHGFS_SUPER_MAGIC +#define VMHGFS_SUPER_MAGIC 0xbacbacbc +#endif + +#ifndef VXFS_SUPER_MAGIC +#define VXFS_SUPER_MAGIC 0xa501fcf5 +#endif diff --git a/config.mak.uname b/config.mak.uname index dacc95172dc..80d7e2a2e68 100644 --- a/config.mak.uname +++ b/config.mak.uname @@ -68,6 +68,17 @@ ifeq ($(uname_S),Linux) ifneq ($(findstring .el7.,$(uname_R)),) BASIC_CFLAGS += -std=c99 endif + ifeq ($(shell test -f /usr/include/linux/magic.h && echo y),y) + HAVE_LINUX_MAGIC_H = YesPlease + endif + # The builtin FSMonitor on Linux builds upon Simple-IPC. Both require + # Unix domain sockets and PThreads. + ifndef NO_PTHREADS + ifndef NO_UNIX_SOCKETS + FSMONITOR_DAEMON_BACKEND = linux + FSMONITOR_OS_SETTINGS = linux + endif + endif endif ifeq ($(uname_S),GNU/kFreeBSD) HAVE_ALLOCA_H = YesPlease From patchwork Thu Feb 15 10:29:34 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Eric DeCosta X-Patchwork-Id: 13557872 Received: from mail-wr1-f43.google.com (mail-wr1-f43.google.com [209.85.221.43]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id A33DE69977 for ; Thu, 15 Feb 2024 10:29:45 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.221.43 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1707992988; cv=none; b=lGk2TdEJozCxcMVx4xgB1ONbQ0ayo5EL8fx64aczLpdQVOJnkM4CzCyEjXE/z0SsphSSMSpWESrf3iqebPBQ0J0+bo6jb9YZCHcTYphFC7RxqBSGjMYyCS2rrP4+FWERSfTNSjT4jqkVYKcCZO/9H9E2cD9l5Rx8m26aYmhxpW8= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1707992988; c=relaxed/simple; bh=n0DBkcg/yq71CZjjrmWo4SdXYLA2vZaVQyH0SMB7W2M=; h=Message-ID:In-Reply-To:References:From:Date:Subject:Content-Type: MIME-Version:To:Cc; b=rv4ynJKB+gB2ioykQJawEcK6O7/9qxWWb2phzCiirGLz94YZ6UUK/8zN+CEPijPfBZ+y+XbBoGtFpW0hQFTX+raysvBwt11W6v/pTaJYYkUjEKx0YAhrbH/TF6/KFcrvk1rj/IcqK7/o8iinPXaKP53aksenYUyKp2Sw5hFIksM= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=gmail.com; spf=pass smtp.mailfrom=gmail.com; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b=Y7wen5zm; arc=none smtp.client-ip=209.85.221.43 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=gmail.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=gmail.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b="Y7wen5zm" Received: by mail-wr1-f43.google.com with SMTP id ffacd0b85a97d-3394b892691so465217f8f.1 for ; Thu, 15 Feb 2024 02:29:45 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20230601; t=1707992983; x=1708597783; darn=vger.kernel.org; h=cc:to:mime-version:content-transfer-encoding:fcc:subject:date:from :references:in-reply-to:message-id:from:to:cc:subject:date :message-id:reply-to; bh=NWVyY03VyOHrfSqJa6fkgcP3t9WmHSfFLgDykLbO4hQ=; b=Y7wen5zmjuJH+oMgKXW4RMsXrPYxx4x1NlvdCmzgvNj0wfa2h1IjWFvtezCzin4JSa rEXMCvfx5WDW2SwhAhwoTOLVlVMPG/vJmugSeYsUOJBqdNsjMR6zAHSPpy79+638M9E/ mjjzCZob+sWjiyLexiBCiFDDqj0AQXUSn8E4GPefWiGjv6kq3l70BA6o0CNzxabDZiST P8eZRIe7Dsfi1gWFKMnMOUzSYEvMTTma1avMBPEyFKQPiPGEWOtvRlzOv9V/OjntnXT+ kskCqi/OfeNWGr1xjK0axQw/tdJwfO7QdDWgCtU4AAkDLi6PTD0EE/+VYIbm2ET7/HB+ Dm1w== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1707992983; x=1708597783; h=cc:to:mime-version:content-transfer-encoding:fcc:subject:date:from :references:in-reply-to:message-id:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=NWVyY03VyOHrfSqJa6fkgcP3t9WmHSfFLgDykLbO4hQ=; b=UgrhJh3ioD6+i6x+DyE8t6pkUjC8YwFZ+FgdGUt6JHtoCa498NNu7YDin91wkqEPky 059ocH9DKHkOsHscDcYryNuc0nN3/FKbwCXXL62t9Qq/hdmT4zi50rYhKlzlC2o+/ZQH YsTJtshtvvqapg5hyjOrp5STIHeYPZWYDlwbweIL9i6EAIH2nYVn8flH3jI5qI3RniT+ 5+84G+yd3Yhoioi5bY83s/5tL7dxQKNhNGCzqIhOdi1HbCxyXTIIOcl9+bsHSP2ZPQlp lF26kj6jSy1ZzoxVwKP7guysOa/sjDp0LNdTjom+GWsFLTJAOnwJvNZB14514qNi2bdG 2HMg== X-Gm-Message-State: AOJu0Yx57ELEhhM5eqOUhw/9hDCP1BRiLx5bTmq/MOT2Gk1RxsbNOMwW b523+ZNUPh/CEWMXXaVtTR7W+L72E2YcIinLCJfoSCwEej+wolnY4IwfqrlN X-Google-Smtp-Source: AGHT+IFOXDmjZWXUr3359qzGHfNiS0oDfcbLN0dZfGN79gRsCzAqLXiFw+bwp7QQ0PlfZeyb6r5DQg== X-Received: by 2002:adf:f9c6:0:b0:33a:d28c:222c with SMTP id w6-20020adff9c6000000b0033ad28c222cmr3980426wrr.11.1707992982900; Thu, 15 Feb 2024 02:29:42 -0800 (PST) Received: from [127.0.0.1] ([13.74.141.28]) by smtp.gmail.com with ESMTPSA id d26-20020adfa41a000000b0033905a60689sm1349590wra.45.2024.02.15.02.29.42 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Thu, 15 Feb 2024 02:29:42 -0800 (PST) Message-ID: <5fad429b4d53dee4eb509f0db98ef860762436fc.1707992978.git.gitgitgadget@gmail.com> In-Reply-To: References: Date: Thu, 15 Feb 2024 10:29:34 +0000 Subject: [PATCH 3/7] fsmonitor: implement filesystem change listener for Linux Fcc: Sent Precedence: bulk X-Mailing-List: git@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 To: git@vger.kernel.org Cc: "Eric Sunshine [ ]" , " =?utf-8?b?w4Z2YXIgQXJu?= =?utf-8?b?ZmrDtnLDsA==?= Bjarmason [ ]" , "Glen Choo [ ]" , "Johannes Schindelin [ ]" , "Taylor Blau [ ]" , marzi , Eric DeCosta From: Eric DeCosta From: Eric DeCosta Implement a filesystem change listener for Linux based on the inotify API: https://man7.org/linux/man-pages/man7/inotify.7.html inotify requires registering a watch on every directory in the worktree and special handling of moves/renames. Signed-off-by: Eric DeCosta --- compat/fsmonitor/fsm-listen-linux.c | 676 ++++++++++++++++++++++++++++ 1 file changed, 676 insertions(+) create mode 100644 compat/fsmonitor/fsm-listen-linux.c diff --git a/compat/fsmonitor/fsm-listen-linux.c b/compat/fsmonitor/fsm-listen-linux.c new file mode 100644 index 00000000000..e8548e4e009 --- /dev/null +++ b/compat/fsmonitor/fsm-listen-linux.c @@ -0,0 +1,676 @@ +#include "cache.h" +#include "fsmonitor.h" +#include "fsm-listen.h" +#include "fsmonitor--daemon.h" +#include +#include +#include +#include + +/* + * Safe value to bitwise OR with rest of mask for + * kernels that do not support IN_MASK_CREATE + */ +#ifndef IN_MASK_CREATE +#define IN_MASK_CREATE 0x00000000 +#endif + +enum shutdown_reason { + SHUTDOWN_CONTINUE = 0, + SHUTDOWN_STOP, + SHUTDOWN_ERROR, + SHUTDOWN_FORCE +}; + +struct watch_entry { + struct hashmap_entry ent; + int wd; + uint32_t cookie; + const char *dir; +}; + +struct rename_entry { + struct hashmap_entry ent; + time_t whence; + uint32_t cookie; + const char *dir; +}; + +struct fsm_listen_data { + int fd_inotify; + enum shutdown_reason shutdown; + struct hashmap watches; + struct hashmap renames; + struct hashmap revwatches; +}; + +static int watch_entry_cmp(const void *cmp_data, + const struct hashmap_entry *eptr, + const struct hashmap_entry *entry_or_key, + const void *keydata) +{ + const struct watch_entry *e1, *e2; + + e1 = container_of(eptr, const struct watch_entry, ent); + e2 = container_of(eptr, const struct watch_entry, ent); + return e1->wd != e2->wd; +} + +static int revwatches_entry_cmp(const void *cmp_data, + const struct hashmap_entry *eptr, + const struct hashmap_entry *entry_or_key, + const void *keydata) +{ + const struct watch_entry *e1, *e2; + + e1 = container_of(eptr, const struct watch_entry, ent); + e2 = container_of(eptr, const struct watch_entry, ent); + return strcmp(e1->dir, e2->dir); +} + +static int rename_entry_cmp(const void *cmp_data, + const struct hashmap_entry *eptr, + const struct hashmap_entry *entry_or_key, + const void *keydata) +{ + const struct rename_entry *e1, *e2; + + e1 = container_of(eptr, const struct rename_entry, ent); + e2 = container_of(eptr, const struct rename_entry, ent); + return e1->cookie != e2->cookie; +} + +/* + * Register an inotify watch, add watch descriptor to path mapping + * and the reverse mapping. + */ +static int add_watch(const char *path, struct fsm_listen_data *data) +{ + const char *interned = strintern(path); + struct watch_entry *w1, *w2; + + /* add the inotify watch, don't allow watches to be modified */ + int wd = inotify_add_watch(data->fd_inotify, interned, + (IN_ALL_EVENTS | IN_ONLYDIR | IN_MASK_CREATE) + ^ IN_ACCESS ^ IN_CLOSE ^ IN_OPEN); + if (wd < 0) + return error_errno("inotify_add_watch('%s') failed", interned); + + /* add watch descriptor -> directory mapping */ + CALLOC_ARRAY(w1, 1); + w1->wd = wd; + w1->dir = interned; + hashmap_entry_init(&w1->ent, memhash(&w1->wd, sizeof(int))); + hashmap_add(&data->watches, &w1->ent); + + /* add directory -> watch descriptor mapping */ + CALLOC_ARRAY(w2, 1); + w2->wd = wd; + w2->dir = interned; + hashmap_entry_init(&w2->ent, memhash(w2->dir, strlen(w2->dir))); + hashmap_add(&data->revwatches, &w2->ent); + + return 0; +} + +/* + * Remove the inotify watch, the watch descriptor to path mapping + * and the reverse mapping. + */ +static void remove_watch(struct watch_entry *w, + struct fsm_listen_data *data) +{ + struct watch_entry k1, k2, *w1, *w2; + + /* remove watch, ignore error if kernel already did it */ + if (inotify_rm_watch(data->fd_inotify, w->wd) && errno != EINVAL) + error_errno("inotify_rm_watch() failed"); + + hashmap_entry_init(&k1.ent, memhash(&w->wd, sizeof(int))); + w1 = hashmap_remove_entry(&data->watches, &k1, ent, NULL); + if (!w1) + BUG("Double remove of watch for '%s'", w->dir); + + if (w1->cookie) + BUG("Removing watch for '%s' which has a pending rename", w1->dir); + + hashmap_entry_init(&k2.ent, memhash(w->dir, strlen(w->dir))); + w2 = hashmap_remove_entry(&data->revwatches, &k2, ent, NULL); + if (!w2) + BUG("Double remove of reverse watch for '%s'", w->dir); + + /* w1->dir and w2->dir are interned strings, we don't own them */ + free(w1); + free(w2); +} + +/* + * Check for stale directory renames. + * + * https://man7.org/linux/man-pages/man7/inotify.7.html + * + * Allow for some small timeout to account for the fact that insertion of the + * IN_MOVED_FROM+IN_MOVED_TO event pair is not atomic, and the possibility that + * there may not be any IN_MOVED_TO event. + * + * If the IN_MOVED_TO event is not received within the timeout then events have + * been missed and the monitor is in an inconsistent state with respect to the + * filesystem. + */ +static int check_stale_dir_renames(struct hashmap *renames, time_t max_age) +{ + struct rename_entry *re; + struct hashmap_iter iter; + + hashmap_for_each_entry(renames, &iter, re, ent) { + if (re->whence <= max_age) + return -1; + } + return 0; +} + +/* + * Track pending renames. + * + * Tracking is done via a event cookie to watch descriptor mapping. + * + * A rename is not complete until matching a IN_MOVED_TO event is received + * for a corresponding IN_MOVED_FROM event. + */ +static void add_dir_rename(uint32_t cookie, const char *path, + struct fsm_listen_data *data) +{ + struct watch_entry k, *w; + struct rename_entry *re; + + /* lookup the watch descriptor for the given path */ + hashmap_entry_init(&k.ent, memhash(path, strlen(path))); + w = hashmap_get_entry(&data->revwatches, &k, ent, NULL); + if (!w) /* should never happen */ + BUG("No watch for '%s'", path); + w->cookie = cookie; + + /* add the pending rename to match against later */ + CALLOC_ARRAY(re, 1); + re->dir = w->dir; + re->cookie = w->cookie; + re->whence = time(NULL); + hashmap_entry_init(&re->ent, memhash(&re->cookie, sizeof(uint32_t))); + hashmap_add(&data->renames, &re->ent); +} + +/* + * Handle directory renames + * + * Once a IN_MOVED_TO event is received, lookup the rename tracking information + * via the event cookie and use this information to update the watch. + */ +static void rename_dir(uint32_t cookie, const char *path, + struct fsm_listen_data *data) +{ + struct rename_entry rek, *re; + struct watch_entry k, *w; + + /* lookup a pending rename to match */ + rek.cookie = cookie; + hashmap_entry_init(&rek.ent, memhash(&rek.cookie, sizeof(uint32_t))); + re = hashmap_get_entry(&data->renames, &rek, ent, NULL); + if (re) { + k.dir = re->dir; + hashmap_entry_init(&k.ent, memhash(k.dir, strlen(k.dir))); + w = hashmap_get_entry(&data->revwatches, &k, ent, NULL); + if (w) { + w->cookie = 0; /* rename handled */ + remove_watch(w, data); + add_watch(path, data); + } else { + BUG("No matching watch"); + } + } else { + BUG("No matching cookie"); + } +} + +/* + * Recursively add watches to every directory under path + */ +static int register_inotify(const char *path, + struct fsmonitor_daemon_state *state, + struct fsmonitor_batch *batch) +{ + DIR *dir; + const char *rel; + struct strbuf current = STRBUF_INIT; + struct dirent *de; + struct stat fs; + int ret = -1; + + dir = opendir(path); + if (!dir) + return error_errno("opendir('%s') failed", path); + + while ((de = readdir_skip_dot_and_dotdot(dir)) != NULL) { + strbuf_reset(¤t); + strbuf_addf(¤t, "%s/%s", path, de->d_name); + if (lstat(current.buf, &fs)) { + error_errno("lstat('%s') failed", current.buf); + goto failed; + } + + /* recurse into directory */ + if (S_ISDIR(fs.st_mode)) { + if (add_watch(current.buf, state->listen_data)) + goto failed; + if (register_inotify(current.buf, state, batch)) + goto failed; + } else if (batch) { + rel = current.buf + state->path_worktree_watch.len + 1; + trace_printf_key(&trace_fsmonitor, "explicitly adding '%s'", rel); + fsmonitor_batch__add_path(batch, rel); + } + } + ret = 0; + +failed: + strbuf_release(¤t); + if (closedir(dir) < 0) + return error_errno("closedir('%s') failed", path); + return ret; +} + +static int em_rename_dir_from(u_int32_t mask) +{ + return ((mask & IN_ISDIR) && (mask & IN_MOVED_FROM)); +} + +static int em_rename_dir_to(u_int32_t mask) +{ + return ((mask & IN_ISDIR) && (mask & IN_MOVED_TO)); +} + +static int em_remove_watch(u_int32_t mask) +{ + return (mask & IN_DELETE_SELF); +} + +static int em_dir_renamed(u_int32_t mask) +{ + return ((mask & IN_ISDIR) && (mask & IN_MOVE)); +} + +static int em_dir_created(u_int32_t mask) +{ + return ((mask & IN_ISDIR) && (mask & IN_CREATE)); +} + +static int em_dir_deleted(uint32_t mask) +{ + return ((mask & IN_ISDIR) && (mask & IN_DELETE)); +} + +static int em_force_shutdown(u_int32_t mask) +{ + return (mask & IN_UNMOUNT) || (mask & IN_Q_OVERFLOW); +} + +static int em_ignore(u_int32_t mask) +{ + return (mask & IN_IGNORED) || (mask & IN_MOVE_SELF); +} + +static void log_mask_set(const char *path, u_int32_t mask) +{ + struct strbuf msg = STRBUF_INIT; + + if (mask & IN_ACCESS) + strbuf_addstr(&msg, "IN_ACCESS|"); + if (mask & IN_MODIFY) + strbuf_addstr(&msg, "IN_MODIFY|"); + if (mask & IN_ATTRIB) + strbuf_addstr(&msg, "IN_ATTRIB|"); + if (mask & IN_CLOSE_WRITE) + strbuf_addstr(&msg, "IN_CLOSE_WRITE|"); + if (mask & IN_CLOSE_NOWRITE) + strbuf_addstr(&msg, "IN_CLOSE_NOWRITE|"); + if (mask & IN_OPEN) + strbuf_addstr(&msg, "IN_OPEN|"); + if (mask & IN_MOVED_FROM) + strbuf_addstr(&msg, "IN_MOVED_FROM|"); + if (mask & IN_MOVED_TO) + strbuf_addstr(&msg, "IN_MOVED_TO|"); + if (mask & IN_CREATE) + strbuf_addstr(&msg, "IN_CREATE|"); + if (mask & IN_DELETE) + strbuf_addstr(&msg, "IN_DELETE|"); + if (mask & IN_DELETE_SELF) + strbuf_addstr(&msg, "IN_DELETE_SELF|"); + if (mask & IN_MOVE_SELF) + strbuf_addstr(&msg, "IN_MOVE_SELF|"); + if (mask & IN_UNMOUNT) + strbuf_addstr(&msg, "IN_UNMOUNT|"); + if (mask & IN_Q_OVERFLOW) + strbuf_addstr(&msg, "IN_Q_OVERFLOW|"); + if (mask & IN_IGNORED) + strbuf_addstr(&msg, "IN_IGNORED|"); + if (mask & IN_ISDIR) + strbuf_addstr(&msg, "IN_ISDIR|"); + + trace_printf_key(&trace_fsmonitor, "inotify_event: '%s', mask=%#8.8x %s", + path, mask, msg.buf); + + strbuf_release(&msg); +} + +int fsm_listen__ctor(struct fsmonitor_daemon_state *state) +{ + int fd; + int ret = 0; + struct fsm_listen_data *data; + + CALLOC_ARRAY(data, 1); + state->listen_data = data; + state->listen_error_code = -1; + data->shutdown = SHUTDOWN_ERROR; + + fd = inotify_init1(O_NONBLOCK); + if (fd < 0) + return error_errno("inotify_init1() failed"); + + data->fd_inotify = fd; + + hashmap_init(&data->watches, watch_entry_cmp, NULL, 0); + hashmap_init(&data->renames, rename_entry_cmp, NULL, 0); + hashmap_init(&data->revwatches, revwatches_entry_cmp, NULL, 0); + + if (add_watch(state->path_worktree_watch.buf, data)) + ret = -1; + else if (register_inotify(state->path_worktree_watch.buf, state, NULL)) + ret = -1; + else if (state->nr_paths_watching > 1) { + if (add_watch(state->path_gitdir_watch.buf, data)) + ret = -1; + else if (register_inotify(state->path_gitdir_watch.buf, state, NULL)) + ret = -1; + } + + if (!ret) { + state->listen_error_code = 0; + data->shutdown = SHUTDOWN_CONTINUE; + } + + return ret; +} + +void fsm_listen__dtor(struct fsmonitor_daemon_state *state) +{ + struct fsm_listen_data *data; + struct hashmap_iter iter; + struct watch_entry *w; + int fd; + + if (!state || !state->listen_data) + return; + + data = state->listen_data; + fd = data->fd_inotify; + + hashmap_for_each_entry(&data->watches, &iter, w, ent) { + w->cookie = 0; /* ignore any pending renames */ + remove_watch(w, data); + } + hashmap_clear(&data->watches); + + hashmap_clear(&data->revwatches); /* remove_watch freed the entries */ + + hashmap_clear_and_free(&data->renames, struct rename_entry, ent); + + FREE_AND_NULL(state->listen_data); + + if (fd && (close(fd) < 0)) + error_errno(_("closing inotify file descriptor failed")); +} + +void fsm_listen__stop_async(struct fsmonitor_daemon_state *state) +{ + if (!state->listen_data->shutdown) + state->listen_data->shutdown = SHUTDOWN_STOP; +} + +/* + * Process a single inotify event and queue for publication. + */ +static int process_event(const char *path, + const struct inotify_event *event, + struct fsmonitor_batch *batch, + struct string_list *cookie_list, + struct fsmonitor_daemon_state *state) +{ + const char *rel; + const char *last_sep; + + switch (fsmonitor_classify_path_absolute(state, path)) { + case IS_INSIDE_DOT_GIT_WITH_COOKIE_PREFIX: + case IS_INSIDE_GITDIR_WITH_COOKIE_PREFIX: + /* Use just the filename of the cookie file. */ + last_sep = find_last_dir_sep(path); + string_list_append(cookie_list, + last_sep ? last_sep + 1 : path); + break; + case IS_INSIDE_DOT_GIT: + case IS_INSIDE_GITDIR: + break; + case IS_DOT_GIT: + case IS_GITDIR: + /* + * If .git directory is deleted or renamed away, + * we have to quit. + */ + if (em_dir_deleted(event->mask)) { + trace_printf_key(&trace_fsmonitor, + "event: gitdir removed"); + state->listen_data->shutdown = SHUTDOWN_FORCE; + goto done; + } + + if (em_dir_renamed(event->mask)) { + trace_printf_key(&trace_fsmonitor, + "event: gitdir renamed"); + state->listen_data->shutdown = SHUTDOWN_FORCE; + goto done; + } + break; + case IS_WORKDIR_PATH: + /* normal events in the working directory */ + if (trace_pass_fl(&trace_fsmonitor)) + log_mask_set(path, event->mask); + + rel = path + state->path_worktree_watch.len + 1; + fsmonitor_batch__add_path(batch, rel); + + if (em_dir_deleted(event->mask)) + break; + + /* received IN_MOVE_FROM, add tracking for expected IN_MOVE_TO */ + if (em_rename_dir_from(event->mask)) + add_dir_rename(event->cookie, path, state->listen_data); + + /* received IN_MOVE_TO, update watch to reflect new path */ + if (em_rename_dir_to(event->mask)) { + rename_dir(event->cookie, path, state->listen_data); + if (register_inotify(path, state, batch)) { + state->listen_data->shutdown = SHUTDOWN_ERROR; + goto done; + } + } + + if (em_dir_created(event->mask)) { + if (add_watch(path, state->listen_data)) { + state->listen_data->shutdown = SHUTDOWN_ERROR; + goto done; + } + if (register_inotify(path, state, batch)) { + state->listen_data->shutdown = SHUTDOWN_ERROR; + goto done; + } + } + break; + case IS_OUTSIDE_CONE: + default: + trace_printf_key(&trace_fsmonitor, + "ignoring '%s'", path); + break; + } + return 0; +done: + return -1; +} + +/* + * Read the inotify event stream and pre-process events before further + * processing and eventual publishing. + */ +static void handle_events(struct fsmonitor_daemon_state *state) +{ + /* See https://man7.org/linux/man-pages/man7/inotify.7.html */ + char buf[4096] + __attribute__ ((aligned(__alignof__(struct inotify_event)))); + + struct hashmap watches = state->listen_data->watches; + struct fsmonitor_batch *batch = NULL; + struct string_list cookie_list = STRING_LIST_INIT_DUP; + struct watch_entry k, *w; + struct strbuf path; + const struct inotify_event *event; + int fd = state->listen_data->fd_inotify; + ssize_t len; + char *ptr, *p; + + strbuf_init(&path, PATH_MAX); + + for(;;) { + len = read(fd, buf, sizeof(buf)); + if (len == -1 && errno != EAGAIN) { + error_errno(_("reading inotify message stream failed")); + state->listen_data->shutdown = SHUTDOWN_ERROR; + goto done; + } + + /* nothing to read */ + if (len <= 0) + goto done; + + /* Loop over all events in the buffer. */ + for (ptr = buf; ptr < buf + len; + ptr += sizeof(struct inotify_event) + event->len) { + + event = (const struct inotify_event *) ptr; + + if (em_ignore(event->mask)) + continue; + + /* File system was unmounted or event queue overflowed */ + if (em_force_shutdown(event->mask)) { + if (trace_pass_fl(&trace_fsmonitor)) + log_mask_set("Forcing shutdown", event->mask); + state->listen_data->shutdown = SHUTDOWN_FORCE; + goto done; + } + + hashmap_entry_init(&k.ent, memhash(&event->wd, sizeof(int))); + k.wd = event->wd; + + w = hashmap_get_entry(&watches, &k, ent, NULL); + if (!w) /* should never happen */ + BUG("No watch for '%s'", event->name); + + /* directory watch was removed */ + if (em_remove_watch(event->mask)) { + remove_watch(w, state->listen_data); + continue; + } + + strbuf_reset(&path); + strbuf_add(&path, w->dir, strlen(w->dir)); + strbuf_addch(&path, '/'); + strbuf_addstr(&path, event->name); + + p = fsmonitor__resolve_alias(path.buf, &state->alias); + if (!p) + p = strbuf_detach(&path, NULL); + + if (!batch) + batch = fsmonitor_batch__new(); + + if (process_event(p, event, batch, &cookie_list, state)) { + free(p); + goto done; + } + free(p); + } + strbuf_reset(&path); + fsmonitor_publish(state, batch, &cookie_list); + string_list_clear(&cookie_list, 0); + batch = NULL; + } +done: + strbuf_release(&path); + fsmonitor_batch__free_list(batch); + string_list_clear(&cookie_list, 0); +} + +/* + * Non-blocking read of the inotify events stream. The inotify fd is polled + * frequently to help minimize the number of queue overflows. + */ +void fsm_listen__loop(struct fsmonitor_daemon_state *state) +{ + int poll_num; + const int interval = 1000; + time_t checked = time(NULL); + struct pollfd fds[1]; + fds[0].fd = state->listen_data->fd_inotify; + fds[0].events = POLLIN; + + for(;;) { + switch (state->listen_data->shutdown) { + case SHUTDOWN_CONTINUE: + poll_num = poll(fds, 1, 1); + if (poll_num == -1) { + if (errno == EINTR) + continue; + error_errno(_("polling inotify message stream failed")); + state->listen_data->shutdown = SHUTDOWN_ERROR; + continue; + } + + if ((time(NULL) - checked) >= interval) { + checked = time(NULL); + if (check_stale_dir_renames(&state->listen_data->renames, + checked - interval)) { + trace_printf_key(&trace_fsmonitor, + "Missed IN_MOVED_TO events, forcing shutdown"); + state->listen_data->shutdown = SHUTDOWN_FORCE; + continue; + } + } + + if (poll_num > 0 && (fds[0].revents & POLLIN)) + handle_events(state); + + continue; + case SHUTDOWN_ERROR: + state->listen_error_code = -1; + ipc_server_stop_async(state->ipc_server_data); + break; + case SHUTDOWN_FORCE: + state->listen_error_code = 0; + ipc_server_stop_async(state->ipc_server_data); + break; + case SHUTDOWN_STOP: + default: + state->listen_error_code = 0; + break; + } + return; + } +} From patchwork Thu Feb 15 10:29:35 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Eric DeCosta X-Patchwork-Id: 13557873 Received: from mail-lj1-f179.google.com (mail-lj1-f179.google.com [209.85.208.179]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 5857867E8B for ; Thu, 15 Feb 2024 10:29:47 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.208.179 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1707992989; cv=none; b=qLaPEXC1AqukkcCHIYccHb1PO+aihyrCl7C/yaSbOXXYWgOc08g4vECx8Qbefbxx2EaIw2iHdrRtEGkCJxMLLVZmaW8LM9qEbzyjdhlehhEUyY/k+5Qu+wknv/B9FZTWUFEEz54yhtTDtAKSYM13M02wwcO37YFjDfEvo2RxD/Y= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1707992989; c=relaxed/simple; bh=48ZWlc/Yda+cZzB3XEMcFzvr4+7U1E5c2U8R097Wizw=; h=Message-ID:In-Reply-To:References:From:Date:Subject:Content-Type: MIME-Version:To:Cc; b=MAUAqLjKv5eBUjaSRgIMOvRjE8UgHRVuHFLw3uXH5ELE12Ch3kL+Tugb9q1bhPmWZl+vq695DxQLroaGLqxikTsRHK8qg87pTyNvcPQQMt4JxpM0+DuN/ko4hZKazjyKs+WiX5nsy8R8IzaO5NoK5pAVCdQqo+LDCae9usQr8jc= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=gmail.com; spf=pass smtp.mailfrom=gmail.com; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b=RrtnLLfF; arc=none smtp.client-ip=209.85.208.179 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=gmail.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=gmail.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b="RrtnLLfF" Received: by mail-lj1-f179.google.com with SMTP id 38308e7fff4ca-2d0d95e8133so8471261fa.1 for ; Thu, 15 Feb 2024 02:29:47 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20230601; t=1707992985; x=1708597785; darn=vger.kernel.org; h=cc:to:mime-version:content-transfer-encoding:fcc:subject:date:from :references:in-reply-to:message-id:from:to:cc:subject:date :message-id:reply-to; bh=woNBiHr5qG8RxFN4DSTN/Cs6jhn2/eAzflaZYKpV0Zo=; b=RrtnLLfFa2fzg6CYSE47haifIdiVQgPpoiBMlnpfj/cb1mosE/UMDBtPoGFhe1a1e5 UvBkGakqPpkeqt013OY7mtV3BV8gPPdPrFLpUx8WhS+GuzJW9v/4ade/z4HM8W/VP6te QOepjX7WyaEzltt7+sArLiR3cx0MxYW9Txu9QtzhEACeVBZ/tRo65Atscwy3kKSmOIGT 67jv0mGkMSsABDuHLzRgF39CvVuWZZLgCoYgZ3F1eGFMO903FcujgdGllG7L1xJdwqK/ 4uxyP0wuyEpnL/NX+8rLFqmAlWTl0xmJjrYxsM+uP4IZjnNoY1Bg+i2z74Ayz+AFaZK8 m9Ig== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1707992985; x=1708597785; h=cc:to:mime-version:content-transfer-encoding:fcc:subject:date:from :references:in-reply-to:message-id:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=woNBiHr5qG8RxFN4DSTN/Cs6jhn2/eAzflaZYKpV0Zo=; b=jnFc/9DUy5soQqms68JyEYP8AgVP/AYqfvIIG19FqAJf2GvOROTm/p021vqakt4SlJ UbemDVm1Hy9BhkSlLJ8nrBnFb7O2nwrgy8hT02pZncu3x6+ma6ZYCrRTWSbW290+ghLH ApCHlFgdmCPxPs3FFjbw4yVZWPgmuz5y7EjHStSnRRCI06MvXb5q5MNRNtBlr/rE2nnq oHa9cPeJ50f8LaGjmnUyUnsib1lIS9YvqxWauYm/mOoy/hqu8BgGg6C88I+ApU4VHvxu izskerom6GIyEIHcICca0EDmG03oNMYCuorYK8kqd1otBak+ga9OxT5Aly2S0UQTRHMh ArzA== X-Gm-Message-State: AOJu0YzuyNBuGdBU9+QT+BHDf4MTJJzHEfko4xXXH5RSLVnXrRI9Lz3D 18tz7/abcy0aVerRgbl4+5splz+cuz8XlHXxnros5/Xr9dCC9cL27appw3AM X-Google-Smtp-Source: AGHT+IG6UHw75Gscz6PilpRBs4kOH1wGakWmbe7POxn85uko5XPliwWQr/6sc+oJx8j4UdX3fwq9Uw== X-Received: by 2002:a05:6512:1289:b0:512:88a9:5d0c with SMTP id u9-20020a056512128900b0051288a95d0cmr874746lfs.15.1707992984520; Thu, 15 Feb 2024 02:29:44 -0800 (PST) Received: from [127.0.0.1] ([13.74.141.28]) by smtp.gmail.com with ESMTPSA id u22-20020a05600c211600b0040fddaf9ff4sm4602009wml.40.2024.02.15.02.29.43 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Thu, 15 Feb 2024 02:29:44 -0800 (PST) Message-ID: <8c10bf49b2537ea01035b21ffc1a011a7110d823.1707992978.git.gitgitgadget@gmail.com> In-Reply-To: References: Date: Thu, 15 Feb 2024 10:29:35 +0000 Subject: [PATCH 4/7] fsmonitor: enable fsmonitor for Linux Fcc: Sent Precedence: bulk X-Mailing-List: git@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 To: git@vger.kernel.org Cc: "Eric Sunshine [ ]" , " =?utf-8?b?w4Z2YXIgQXJu?= =?utf-8?b?ZmrDtnLDsA==?= Bjarmason [ ]" , "Glen Choo [ ]" , "Johannes Schindelin [ ]" , "Taylor Blau [ ]" , marzi , Eric DeCosta From: Eric DeCosta From: Eric DeCosta Update build to enable fsmonitor for Linux. Signed-off-by: Eric DeCosta --- contrib/buildsystems/CMakeLists.txt | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/contrib/buildsystems/CMakeLists.txt b/contrib/buildsystems/CMakeLists.txt index 804629c525b..61ec95c8507 100644 --- a/contrib/buildsystems/CMakeLists.txt +++ b/contrib/buildsystems/CMakeLists.txt @@ -304,7 +304,16 @@ else() endif() if(SUPPORTS_SIMPLE_IPC) - if(CMAKE_SYSTEM_NAME STREQUAL "Windows") + if(CMAKE_SYSTEM_NAME STREQUAL "Linux") + add_compile_definitions(HAVE_FSMONITOR_DAEMON_BACKEND) + list(APPEND compat_SOURCES compat/fsmonitor/fsm-listen-linux.c) + list(APPEND compat_SOURCES compat/fsmonitor/fsm-health-linux.c) + list(APPEND compat_SOURCES compat/fsmonitor/fsm-ipc-linux.c) + list(APPEND compat_SOURCES compat/fsmonitor/fsm-path-utils-linux.c) + + add_compile_definitions(HAVE_FSMONITOR_OS_SETTINGS) + list(APPEND compat_SOURCES compat/fsmonitor/fsm-settings-linux.c) + elseif(CMAKE_SYSTEM_NAME STREQUAL "Windows") add_compile_definitions(HAVE_FSMONITOR_DAEMON_BACKEND) list(APPEND compat_SOURCES compat/fsmonitor/fsm-listen-win32.c) list(APPEND compat_SOURCES compat/fsmonitor/fsm-health-win32.c) From patchwork Thu Feb 15 10:29:36 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Eric DeCosta X-Patchwork-Id: 13557874 Received: from mail-wr1-f52.google.com (mail-wr1-f52.google.com [209.85.221.52]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id BE18769D0C for ; Thu, 15 Feb 2024 10:29:47 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.221.52 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1707992989; cv=none; b=g6O7wSAwl2X/n/dzHS9dhxmx6HbMQsQyUTIuW0eRP+/c/EXI81w94nOXNM17EHx33W/KIVNAosRxoXyh76bEKgI9767ln3kW9Hl/fpsQEWVrlLPB8tKbJxO8UmNxzeEkVRst4JmXqalRbzlpPBO92wvnqwkcFwk+hyG4NLX2Zlo= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1707992989; c=relaxed/simple; bh=jPXFang1srJw4bZQSVknjo7OMOpzQSB7SbkHK3M3VwM=; h=Message-ID:In-Reply-To:References:From:Date:Subject:Content-Type: MIME-Version:To:Cc; b=OjFt3ztFP/Slt9g4a71wr0oI+STuVVv1EtSj2blNu3JSyMO1DzKJ1gn0szb4nO2k/A0e82wWxaqhpzdfUZAGJqT8G2Or5J9AWs2KHCp0Sxg753Njn45e4GNCLuYnDMZ3pWdDMLbbTxbXmoFtHK8VT4tplSZdy6OD8O6V5jFp3ho= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=gmail.com; spf=pass smtp.mailfrom=gmail.com; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b=b/p4bL6p; arc=none smtp.client-ip=209.85.221.52 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=gmail.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=gmail.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b="b/p4bL6p" Received: by mail-wr1-f52.google.com with SMTP id ffacd0b85a97d-33d118a181fso9705f8f.1 for ; Thu, 15 Feb 2024 02:29:47 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20230601; t=1707992986; x=1708597786; darn=vger.kernel.org; h=cc:to:mime-version:content-transfer-encoding:fcc:subject:date:from :references:in-reply-to:message-id:from:to:cc:subject:date :message-id:reply-to; bh=eFFlXaXhSVzkM+vKU3wWW4HNf9XxRFU91f9yeZk+K6g=; b=b/p4bL6pLQ/DAIH8su6m3EsrPTiGPgIq2LYQIXSx0Ltc7Qd8N+X5t5aV0vWQfJpYl8 uzgcpvl+qvBLtZXy1yLPbjZnup9irQTzgVEzCX+NwpkgioW54W81mDhPudWMt4Qj8xdN MDdOBxfmcARyseRh5l7/DVs8ssf3MouQUnxyOYzvk1qgl8LMFX+LmbO5e51TrSyGcMQQ eBNL0ZNP07nBpdgRX8nPOSKWgEKLaS55DFBAbBN3iRH+AHCPFCqX08VF22SoU3BbMSp3 xuL4OHIrbOShVM88GqZMz0AAT1r1/qRfNNXGzYuJ9W12wESRSqEtwxHMWH5P4qM20PKl f3EQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1707992986; x=1708597786; h=cc:to:mime-version:content-transfer-encoding:fcc:subject:date:from :references:in-reply-to:message-id:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=eFFlXaXhSVzkM+vKU3wWW4HNf9XxRFU91f9yeZk+K6g=; b=sDvVjbmhrjiaqGj19PGIINg8cSBQZWMuD4MyFKsWKvm5ZBD+7t6K0AAo2+1UY5qDgU rGBBFxPI1mvazTgDTMXMP5LHo4SgFIYPA3WC0U6DBrvujggQVju3eiyDYoOpRXjwfGff W/StfFFk+iF89wmpKA7O6RgDPTD+79Agbo1fWTJ3+M11GVMgQalbQ5JuMMcA0WolKFP9 D4j1ttZLoV1TMIBQwcHsJ9if+5HXR9zxbj9HeLoczGq4Qni+pZBFIrLqc25WKoZ/N2q1 YOgy/IsT+s2P5uq8o6PBc3yyMZmGsFb/eKe5NpOqPukrb98/mnXunrD9k1pMkU37E8Be 2+0Q== X-Gm-Message-State: AOJu0YysHHENsb9iaCOMIWBiQ3NMMssmV2I+nJnsbgQmkuxy9aOmfjkk h15xxjb9vXHgG+FK+mcyjBYcFLbL/XBFVVvVGKysA9H2cjvt9wk5TCdC1Y4V X-Google-Smtp-Source: AGHT+IETMSaVfRiQUX3n6xAl5dzRxqBXKeknq5lYZd/iQVEjdt6UMGF+VHCKizndLQ7RSOnZCP9WQQ== X-Received: by 2002:a5d:6a8b:0:b0:33b:4d13:3e91 with SMTP id s11-20020a5d6a8b000000b0033b4d133e91mr945618wru.45.1707992985877; Thu, 15 Feb 2024 02:29:45 -0800 (PST) Received: from [127.0.0.1] ([13.74.141.28]) by smtp.gmail.com with ESMTPSA id k2-20020adff282000000b0033b8808355fsm1345545wro.28.2024.02.15.02.29.44 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Thu, 15 Feb 2024 02:29:45 -0800 (PST) Message-ID: <2550a7824832ab4f570b82ec452bd12e315ea7f5.1707992978.git.gitgitgadget@gmail.com> In-Reply-To: References: Date: Thu, 15 Feb 2024 10:29:36 +0000 Subject: [PATCH 5/7] fsmonitor: test updates Fcc: Sent Precedence: bulk X-Mailing-List: git@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 To: git@vger.kernel.org Cc: "Eric Sunshine [ ]" , " =?utf-8?b?w4Z2YXIgQXJu?= =?utf-8?b?ZmrDtnLDsA==?= Bjarmason [ ]" , "Glen Choo [ ]" , "Johannes Schindelin [ ]" , "Taylor Blau [ ]" , marzi , Eric DeCosta From: Eric DeCosta From: Eric DeCosta t7527-builtin-fsmonitor was leaking fsmonitor--daemon processes in some cases. Accomodate slight difference in the number of events generated on Linux. On lower-powered systems, spin a little to give the daemon time to respond to and log filesystem events. Signed-off-by: Eric DeCosta --- t/t7527-builtin-fsmonitor.sh | 138 +++++++++++++++++++++++++++-------- 1 file changed, 106 insertions(+), 32 deletions(-) diff --git a/t/t7527-builtin-fsmonitor.sh b/t/t7527-builtin-fsmonitor.sh index 363f9dc0e41..1d33e418015 100755 --- a/t/t7527-builtin-fsmonitor.sh +++ b/t/t7527-builtin-fsmonitor.sh @@ -13,7 +13,7 @@ fi stop_daemon_delete_repo () { r=$1 && test_might_fail git -C $r fsmonitor--daemon stop && - rm -rf $1 + rm -rf $r } start_daemon () { @@ -72,6 +72,34 @@ start_daemon () { ) } +IMPLICIT_TIMEOUT=5 + +wait_for_update () { + func=$1 && + file=$2 && + sz=$(wc -c < "$file") && + last=0 && + $func && + k=0 && + while test "$k" -lt $IMPLICIT_TIMEOUT + do + nsz=$(wc -c < "$file") + if test "$nsz" -gt "$sz" + then + if test "$last" -eq "$nsz" + then + cat "$file" && + return 0 + fi + last=$nsz + fi + sleep 1 + k=$(( $k + 1 )) + done && + cat "$file" && + return 0 +} + # Is a Trace2 data event present with the given catetory and key? # We do not care what the value is. # @@ -137,7 +165,6 @@ test_expect_success 'implicit daemon start' ' # machines (where it might take a moment to wake and reschedule the # daemon process) to avoid false alarms during test runs.) # -IMPLICIT_TIMEOUT=5 verify_implicit_shutdown () { r=$1 && @@ -373,6 +400,15 @@ create_files () { echo 3 >dir2/new } +rename_directory () { + mv dirtorename dirrenamed +} + +rename_directory_file () { + mv dirtorename dirrenamed && + echo 1 > dirrenamed/new +} + rename_files () { mv rename renamed && mv dir1/rename dir1/renamed && @@ -427,10 +463,12 @@ test_expect_success 'edit some files' ' start_daemon --tf "$PWD/.git/trace" && - edit_files && + wait_for_update edit_files "$PWD/.git/trace" && test-tool fsmonitor-client query --token 0 && + test_might_fail git fsmonitor--daemon stop && + grep "^event: dir1/modified$" .git/trace && grep "^event: dir2/modified$" .git/trace && grep "^event: modified$" .git/trace && @@ -442,10 +480,12 @@ test_expect_success 'create some files' ' start_daemon --tf "$PWD/.git/trace" && - create_files && + wait_for_update create_files "$PWD/.git/trace" && test-tool fsmonitor-client query --token 0 && + test_might_fail git fsmonitor--daemon stop && + grep "^event: dir1/new$" .git/trace && grep "^event: dir2/new$" .git/trace && grep "^event: new$" .git/trace @@ -456,10 +496,12 @@ test_expect_success 'delete some files' ' start_daemon --tf "$PWD/.git/trace" && - delete_files && + wait_for_update delete_files "$PWD/.git/trace" && test-tool fsmonitor-client query --token 0 && + test_might_fail git fsmonitor--daemon stop && + grep "^event: dir1/delete$" .git/trace && grep "^event: dir2/delete$" .git/trace && grep "^event: delete$" .git/trace @@ -470,10 +512,12 @@ test_expect_success 'rename some files' ' start_daemon --tf "$PWD/.git/trace" && - rename_files && + wait_for_update rename_files "$PWD/.git/trace" && test-tool fsmonitor-client query --token 0 && + test_might_fail git fsmonitor--daemon stop && + grep "^event: dir1/rename$" .git/trace && grep "^event: dir2/rename$" .git/trace && grep "^event: rename$" .git/trace && @@ -487,23 +531,42 @@ test_expect_success 'rename directory' ' start_daemon --tf "$PWD/.git/trace" && - mv dirtorename dirrenamed && + wait_for_update rename_directory "$PWD/.git/trace" && test-tool fsmonitor-client query --token 0 && + test_might_fail git fsmonitor--daemon stop && + grep "^event: dirtorename/*$" .git/trace && grep "^event: dirrenamed/*$" .git/trace ' +test_expect_success 'rename directory file' ' + test_when_finished clean_up_repo_and_stop_daemon && + + start_daemon --tf "$PWD/.git/trace" && + + wait_for_update rename_directory_file "$PWD/.git/trace" && + + test-tool fsmonitor-client query --token 0 && + + test_might_fail git fsmonitor--daemon stop && + + grep "^event: dirtorename/*$" .git/trace && + grep "^event: dirrenamed/*$" .git/trace && + grep "^event: dirrenamed/new$" .git/trace +' test_expect_success 'file changes to directory' ' test_when_finished clean_up_repo_and_stop_daemon && start_daemon --tf "$PWD/.git/trace" && - file_to_directory && + wait_for_update file_to_directory "$PWD/.git/trace" && test-tool fsmonitor-client query --token 0 && + test_might_fail git fsmonitor--daemon stop && + grep "^event: delete$" .git/trace && grep "^event: delete/new$" .git/trace ' @@ -513,10 +576,12 @@ test_expect_success 'directory changes to a file' ' start_daemon --tf "$PWD/.git/trace" && - directory_to_file && + wait_for_update directory_to_file "$PWD/.git/trace" && test-tool fsmonitor-client query --token 0 && + test_might_fail git fsmonitor--daemon stop && + grep "^event: dir1$" .git/trace ' @@ -561,7 +626,7 @@ test_expect_success 'flush cached data' ' test-tool -C test_flush fsmonitor-client query --token "builtin:test_00000002:0" >actual_2 && nul_to_q actual_q2 && - grep "^builtin:test_00000002:0Q$" actual_q2 && + grep "^builtin:test_00000002:[0-1]Q$" actual_q2 && >test_flush/file_3 && @@ -732,7 +797,8 @@ u_values="$u1 $u2" for u in $u_values do test_expect_success "unicode in repo root path: $u" ' - test_when_finished "stop_daemon_delete_repo $u" && + test_when_finished \ + "stop_daemon_delete_repo `echo "$u" | sed 's:x:\\\\\\\\\\\\\\x:g'`" && git init "$u" && echo 1 >"$u"/file1 && @@ -823,8 +889,7 @@ test_expect_success 'submodule setup' ' ' test_expect_success 'submodule always visited' ' - test_when_finished "git -C super fsmonitor--daemon stop; \ - rm -rf super; \ + test_when_finished "rm -rf super; \ rm -rf sub" && create_super super && @@ -871,10 +936,29 @@ test_expect_success 'submodule always visited' ' # the submodule, and someone does a `git submodule absorbgitdirs` # in the super, Git will recursively invoke `git submodule--helper` # to do the work and this may try to read the index. This will -# try to start the daemon in the submodule. +# try to start the daemon in the submodule *and* pass (either +# directly or via inheritance) the `--super-prefix` arg to the +# `git fsmonitor--daemon start` command inside the submodule. +# This causes a warning because fsmonitor--daemon does take that +# global arg (see the table in git.c) +# +# This causes a warning when trying to start the daemon that is +# somewhat confusing. It does not seem to hurt anything because +# the fsmonitor code maps the query failure into a trivial response +# and does the work anyway. +# +# It would be nice to silence the warning, however. -test_expect_success "submodule absorbgitdirs implicitly starts daemon" ' - test_when_finished "rm -rf super; \ +have_t2_error_event () { + log=$1 + msg="fsmonitor--daemon doesnQt support --super-prefix" && + + tr '\047' Q <$1 | grep -e "$msg" +} + +test_expect_success "stray submodule super-prefix warning" ' + test_when_finished "git -C super/dir_1/dir_2/sub fsmonitor--daemon stop; \ + rm -rf super; \ rm -rf sub; \ rm super-sub.trace" && @@ -891,31 +975,21 @@ test_expect_success "submodule absorbgitdirs implicitly starts daemon" ' test_path_is_dir super/dir_1/dir_2/sub/.git && - cwd="$(cd super && pwd)" && - cat >expect <<-EOF && - Migrating git directory of '\''dir_1/dir_2/sub'\'' from - '\''$cwd/dir_1/dir_2/sub/.git'\'' to - '\''$cwd/.git/modules/dir_1/dir_2/sub'\'' - EOF GIT_TRACE2_EVENT="$PWD/super-sub.trace" \ - git -C super submodule absorbgitdirs >out 2>actual && - test_cmp expect actual && - test_must_be_empty out && + git -C super submodule absorbgitdirs && - # Confirm that the trace2 log contains a record of the - # daemon starting. - test_subcommand git fsmonitor--daemon start X-Patchwork-Id: 13557876 Received: from mail-wr1-f50.google.com (mail-wr1-f50.google.com [209.85.221.50]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id D2C0869D39 for ; Thu, 15 Feb 2024 10:29:48 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.221.50 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1707992991; cv=none; b=nidPK/D3MNrq7t12E54IlHDCYFDgsPS9n4VY4LXgumWK+tf6/ospf7qmEX5eWq95R2MBHh7f/Heo+c7bcfTJVjH+xvPtCAd4XiT8jaw/3rqnHeLUIAVl7gv+uFwPqqysipciNPxG05Wh5D6CJg7OT8PVOxscapjsZMHJATYB9lA= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1707992991; c=relaxed/simple; bh=8pHLxVwWfAKIVN+fYTYk15Ex0JhwyVUgbaNDr/IqWH8=; h=Message-ID:In-Reply-To:References:From:Date:Subject:Content-Type: MIME-Version:To:Cc; b=ush9usFUZA3REX1EP0KiCaoHZ4GNyG6ComcOsGkjT7EB+xov1psJVW3kXIzSLI1HcAwLSU9KkrPdKMlxRsNWmYELJji/4twqtsQ+cJ2qV28E2mLLREaKmPT/DuvoFmDBQqgf1HFcKHnOhpWqq3KNXbFy06jrzZMfIALVCY0YUF0= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=gmail.com; spf=pass smtp.mailfrom=gmail.com; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b=NeOHjSP9; arc=none smtp.client-ip=209.85.221.50 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=gmail.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=gmail.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b="NeOHjSP9" Received: by mail-wr1-f50.google.com with SMTP id ffacd0b85a97d-337d05b8942so442492f8f.3 for ; Thu, 15 Feb 2024 02:29:48 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20230601; t=1707992987; x=1708597787; darn=vger.kernel.org; h=cc:to:mime-version:content-transfer-encoding:fcc:subject:date:from :references:in-reply-to:message-id:from:to:cc:subject:date :message-id:reply-to; bh=e61PsnXiBlPenJ5EHXw7RgYMWWV8uQLSlMKi3SdABuM=; b=NeOHjSP9TFMGEHs29jF6/1/PzB7wrlA2EgsvJLBKNyvOtLO03YdfzmpdQ1lm9EOl/6 fllUzhcqR8Qq4de9P8UylfHXXMgYZibLndZTVyxLcWqrWwESnRGfxdYgZYjUzO5mUf4h 6ONzxTUnNzWhop60fLPCkx19LqxuHZyRDBuG8bNV5KIsZG+ewbJMKhyXGDXwvn65nmpq 0FHKqTaovTlP94K93Z/D39XjpUTai7MOZOTmAQ0oLa0R344a4OZugaWkDWWllKuNJcHP t0zCTqCnwDBBeIZHICC4E3bFvXvWhZeNaep8sSa1z0uuN1wHF6DgVF1b7tbQ3eYfC5FA 97gQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1707992987; x=1708597787; h=cc:to:mime-version:content-transfer-encoding:fcc:subject:date:from :references:in-reply-to:message-id:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=e61PsnXiBlPenJ5EHXw7RgYMWWV8uQLSlMKi3SdABuM=; b=bWguG4rqrCfz+wqVh3XqFFSxZ/KVUsHEXxv0U65q/36nN8GwHHOjcAV2rcQKXzfUSQ 7qGbPkPvgAGAtozE8sUvzdfN4h7idgTHBSGOk5Gcj7jAyzL2tQ7siluXHVNDa84P0m4r tyuo3N+GFxCbjgpjBSX/EXxkWfsQJxO3rTBArMZRp658JJR/gXU9Vv10dFjlfi4mXCjW xKecwrx/lo+udGQjSZMNoVqfS+qAS0nK5w6PXK9YdvOhSUPijMVnkVB6QBVqe1xhYzhv eQj28y+76vihTtuKH7zhAkyqu7UoMWaHk1ZIQ9ZwOl2+Qj4/8lu+pKh4OUCYtFb0NAFC 4Bjg== X-Gm-Message-State: AOJu0Yz94atLD687S5UlLdBZoR6tQsgKQJxHWK9nkv2OpMUTn2nGvFYj RaK+ug5g4pQn9r71JtUx/ho7gwhDW9Pi1r8gTMblDSiC6gMUIx9ETAfV/aMA X-Google-Smtp-Source: AGHT+IENKmCOV/A759SaBrhFtxwREKpCqs0ENMiwbA6FLB1gqraNZF0k3Xo2ULrQsP2xhSfny0/SzQ== X-Received: by 2002:adf:f50d:0:b0:33b:4649:a1e0 with SMTP id q13-20020adff50d000000b0033b4649a1e0mr1010265wro.15.1707992986673; Thu, 15 Feb 2024 02:29:46 -0800 (PST) Received: from [127.0.0.1] ([13.74.141.28]) by smtp.gmail.com with ESMTPSA id bs22-20020a056000071600b0033cfb525bf4sm1377408wrb.82.2024.02.15.02.29.46 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Thu, 15 Feb 2024 02:29:46 -0800 (PST) Message-ID: <02aee716a0ed83bef55eadc04ed5d8f9c0ac2c03.1707992978.git.gitgitgadget@gmail.com> In-Reply-To: References: Date: Thu, 15 Feb 2024 10:29:37 +0000 Subject: [PATCH 6/7] fsmonitor: update doc for Linux Fcc: Sent Precedence: bulk X-Mailing-List: git@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 To: git@vger.kernel.org Cc: "Eric Sunshine [ ]" , " =?utf-8?b?w4Z2YXIgQXJu?= =?utf-8?b?ZmrDtnLDsA==?= Bjarmason [ ]" , "Glen Choo [ ]" , "Johannes Schindelin [ ]" , "Taylor Blau [ ]" , marzi , Eric DeCosta From: Eric DeCosta From: Eric DeCosta Update the documentation for Linux. Signed-off-by: Eric DeCosta --- Documentation/config/fsmonitor--daemon.txt | 4 ++-- Documentation/git-fsmonitor--daemon.txt | 26 ++++++++++++++-------- 2 files changed, 19 insertions(+), 11 deletions(-) diff --git a/Documentation/config/fsmonitor--daemon.txt b/Documentation/config/fsmonitor--daemon.txt index 671f9b94628..4ca92536286 100644 --- a/Documentation/config/fsmonitor--daemon.txt +++ b/Documentation/config/fsmonitor--daemon.txt @@ -4,8 +4,8 @@ fsmonitor.allowRemote:: behavior. Only respected when `core.fsmonitor` is set to `true`. fsmonitor.socketDir:: - This Mac OS-specific option, if set, specifies the directory in + Mac OS and Linux-specific option. If set, specifies the directory in which to create the Unix domain socket used for communication between the fsmonitor daemon and various Git commands. The directory must - reside on a native Mac OS filesystem. Only respected when `core.fsmonitor` + reside on a native filesystem. Only respected when `core.fsmonitor` is set to `true`. diff --git a/Documentation/git-fsmonitor--daemon.txt b/Documentation/git-fsmonitor--daemon.txt index 8585d19f4d8..ebdc4aec3c0 100644 --- a/Documentation/git-fsmonitor--daemon.txt +++ b/Documentation/git-fsmonitor--daemon.txt @@ -76,23 +76,31 @@ repositories; this may be overridden by setting `fsmonitor.allowRemote` to correctly with all network-mounted repositories, so such use is considered experimental. -On Mac OS, the inter-process communication (IPC) between various Git +On Linux and Mac OS, the inter-process communication (IPC) between various Git commands and the fsmonitor daemon is done via a Unix domain socket (UDS) -- a -special type of file -- which is supported by native Mac OS filesystems, -but not on network-mounted filesystems, NTFS, or FAT32. Other filesystems -may or may not have the needed support; the fsmonitor daemon is not guaranteed -to work with these filesystems and such use is considered experimental. +special type of file -- which is supported by many native Linux and Mac OS +filesystems, but not on network-mounted filesystems, NTFS, or FAT32. Other +filesystems may or may not have the needed support; the fsmonitor daemon is not +guaranteed to work with these filesystems and such use is considered +experimental. By default, the socket is created in the `.git` directory. However, if the `.git` directory is on a network-mounted filesystem, it will instead be created at `$HOME/.git-fsmonitor-*` unless `$HOME` itself is on a -network-mounted filesystem, in which case you must set the configuration -variable `fsmonitor.socketDir` to the path of a directory on a Mac OS native +network-mounted filesystem in which case you must set the configuration +variable `fsmonitor.socketDir` to the path of a directory on a native filesystem in which to create the socket file. If none of the above directories (`.git`, `$HOME`, or `fsmonitor.socketDir`) -is on a native Mac OS file filesystem the fsmonitor daemon will report an -error that will cause the daemon and the currently running command to exit. +is on a native Linux or Mac OS filesystem the fsmonitor daemon will report +an error that will cause the daemon to exit and the currently running command +to issue a warning. + +On Linux, the fsmonitor daemon registers a watch for each directory in the +repository. The default per-user limit for the number of watches on most Linux +systems is 8192. This may not be sufficient for large repositories or if +multiple instances of the fsmonitor daemon are running. +See https://watchexec.github.io/docs/inotify-limits.html[Linux inotify limits] for more information. CONFIGURATION ------------- From patchwork Thu Feb 15 10:29:38 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: "marzi.esipreh" X-Patchwork-Id: 13557875 Received: from mail-wm1-f46.google.com (mail-wm1-f46.google.com [209.85.128.46]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 7FE3569D34 for ; Thu, 15 Feb 2024 10:29:49 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.128.46 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1707992991; cv=none; b=MDQOUa+5zD7jevpONL5XTWpX1D24uQA3zqkuQTQ1CDFf+qOuITWU/ycAAaWzu+dsl8eCFnyp8DSCiMo77kcbTNStREQOuacad7C1Knj2uObvkLA1Q7JvJrJvCZWkG9OqyZMDBzkRPnL8w2nO8B8XI9g0jQds7cFhuyy1hXhU3RI= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1707992991; c=relaxed/simple; bh=nXQ9VvGpqjK3Uc7GAGaSN5daE5jlPhL1iIQuhanR8Ew=; h=Message-ID:In-Reply-To:References:From:Date:Subject:Content-Type: MIME-Version:To:Cc; b=K8RXntmY681r3MkAQg+u8Vf4ugFaV/nUbOYZrPIlh96fNwOehlIyoaA+muEmSCnTQjfGyFQXw6POE+i7R4naTPZ7oopln8INrbUCga+p+6iHphaKuRIDKI8KBwTpuJiFmibkUWHd3WRQMI95llWtysAE7d71B32IY2LA2U0TD0M= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=gmail.com; spf=pass smtp.mailfrom=gmail.com; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b=JQJ6ekh0; arc=none smtp.client-ip=209.85.128.46 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=gmail.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=gmail.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b="JQJ6ekh0" Received: by mail-wm1-f46.google.com with SMTP id 5b1f17b1804b1-40fd72f7125so5867365e9.1 for ; Thu, 15 Feb 2024 02:29:49 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20230601; t=1707992987; x=1708597787; darn=vger.kernel.org; h=cc:to:mime-version:content-transfer-encoding:fcc:subject:date:from :references:in-reply-to:message-id:from:to:cc:subject:date :message-id:reply-to; bh=PpwII30pFsHq6LzWmfSIj9WqnFhvkGsh+DhS9dmzDIo=; b=JQJ6ekh02Vsn7wI3jkLnIvhzEZ1S7CyXQHyXyno9YU2hNJv3bZMErspQaxTB8bMmC3 6PM8jpTfJ1PW5wc7+MgqBCSeQPV9xO2emDY21en8y/7PTbhrAxaThc9fLhgiBJN+/9H7 0RgSysd7EmBiuFVgrfJ2qEFw1mHZfRhVyReexBu/i4owyKP0oq3FTjnj5uwPOm079LHK rk7URb7k+ixp+mkFwDM2Y4YiiNYZQjqZH3LsogAmtWlkxAcz6a6v4fgPDdHptHQpmkgk dMM5gbiGxIpHIVkiYSOpP+2qiMqvsmp5A5EkroMWCdCMe4Yz6FG/D6AQ4YeRWz5jwHbD 2kTA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1707992987; x=1708597787; h=cc:to:mime-version:content-transfer-encoding:fcc:subject:date:from :references:in-reply-to:message-id:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=PpwII30pFsHq6LzWmfSIj9WqnFhvkGsh+DhS9dmzDIo=; b=LqtzWarx18yAupLdwzCtooQd3ugOinrNdD2SjFk5TCi3csAmq3CbSLbV4BqlOMcZ7v BtnKQNMTz6gQWJlkmuTHpwZBZbb26nClZBkg97T8zLbDVArk8k1VC66eWRc+lQY4cXkB gcVyQVjH5PFbXwAP50g9gQ8LyYwkgwGCzKJNt684aArsx6NeKNgqRn4m05erg0+5QErK myPBxk0MzshgyiIwfUTthPhg2DIGcpWH9ZIDJ+CLT9j3QfwVeUYcEEkm6bTQ2m9Fd3BB IErzoPdgzqQVcVvFC1wVO5VAxntVJVzyf/iZXVnm0ETH3O/1rzqtBDbf9T9qinWZ4rsV 0cew== X-Gm-Message-State: AOJu0YxLzFmXAktlY1HGL/axw5rtLN1ENQsgCigW+svH4jY+iImIeCiX s3xc2moW0oOGqVw7Hs3/G+TxyCvoi0ykdWOPnq+wSCfXYesweOuA1ZOMD3Yn X-Google-Smtp-Source: AGHT+IGMb1uwR7YoQug9cvFmPZI6ud2g0TQRq5f9eFslPtfKnlAZ2mtEvVGY8LJhWMwq1whHs4o0+Q== X-Received: by 2002:a05:600c:1d26:b0:411:da90:89c0 with SMTP id l38-20020a05600c1d2600b00411da9089c0mr1071537wms.10.1707992987226; Thu, 15 Feb 2024 02:29:47 -0800 (PST) Received: from [127.0.0.1] ([13.74.141.28]) by smtp.gmail.com with ESMTPSA id n2-20020a05600c3b8200b00410c449f25asm4938615wms.6.2024.02.15.02.29.46 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Thu, 15 Feb 2024 02:29:47 -0800 (PST) Message-ID: <74a4fa335a7c2014a35be8556887170169360b36.1707992978.git.gitgitgadget@gmail.com> In-Reply-To: References: Date: Thu, 15 Feb 2024 10:29:38 +0000 Subject: [PATCH 7/7] fsmonitor: addressed comments for patch 1352 Fcc: Sent Precedence: bulk X-Mailing-List: git@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 To: git@vger.kernel.org Cc: "Eric Sunshine [ ]" , " =?utf-8?b?w4Z2YXIgQXJu?= =?utf-8?b?ZmrDtnLDsA==?= Bjarmason [ ]" , "Glen Choo [ ]" , "Johannes Schindelin [ ]" , "Taylor Blau [ ]" , marzi , "marzi.esipreh" From: "marzi.esipreh" From: "marzi.esipreh" addressed comments on 1352, rebased, resolved conflicts Signed-off-by: Marzieh Esipreh --- compat/fsmonitor/fsm-health-linux.c | 2 +- compat/fsmonitor/fsm-ipc-unix.c | 6 +- compat/fsmonitor/fsm-listen-linux.c | 170 ++++++++++++------------ compat/fsmonitor/fsm-path-utils-linux.c | 1 + compat/fsmonitor/fsm-settings-unix.c | 3 + 5 files changed, 95 insertions(+), 87 deletions(-) diff --git a/compat/fsmonitor/fsm-health-linux.c b/compat/fsmonitor/fsm-health-linux.c index b9f709e8548..4c291f8a066 100644 --- a/compat/fsmonitor/fsm-health-linux.c +++ b/compat/fsmonitor/fsm-health-linux.c @@ -1,4 +1,4 @@ -#include "cache.h" +#include "git-compat-util.h" #include "config.h" #include "fsmonitor.h" #include "fsm-health.h" diff --git a/compat/fsmonitor/fsm-ipc-unix.c b/compat/fsmonitor/fsm-ipc-unix.c index eb25123fa12..70afddfd298 100644 --- a/compat/fsmonitor/fsm-ipc-unix.c +++ b/compat/fsmonitor/fsm-ipc-unix.c @@ -1,10 +1,12 @@ -#include "cache.h" +#include "git-compat-util.h" #include "config.h" #include "hex.h" #include "strbuf.h" #include "fsmonitor.h" #include "fsmonitor-ipc.h" #include "fsmonitor-path-utils.h" +#include "gettext.h" +#include "path.h" static GIT_PATH_FUNC(fsmonitor_ipc__get_default_path, "fsmonitor--daemon.ipc") @@ -17,7 +19,7 @@ const char *fsmonitor_ipc__get_path(struct repository *r) unsigned char hash[GIT_MAX_RAWSZ]; if (!r) - BUG("No repository passed into fsmonitor_ipc__get_path"); + BUG("no repository passed into fsmonitor_ipc__get_path"); if (ipc_path) return ipc_path; diff --git a/compat/fsmonitor/fsm-listen-linux.c b/compat/fsmonitor/fsm-listen-linux.c index e8548e4e009..84d8fb28d5d 100644 --- a/compat/fsmonitor/fsm-listen-linux.c +++ b/compat/fsmonitor/fsm-listen-linux.c @@ -1,7 +1,10 @@ -#include "cache.h" +#include "git-compat-util.h" +#include "config.h" #include "fsmonitor.h" #include "fsm-listen.h" #include "fsmonitor--daemon.h" +#include "gettext.h" +#include "simple-ipc.h" #include #include #include @@ -129,15 +132,15 @@ static void remove_watch(struct watch_entry *w, hashmap_entry_init(&k1.ent, memhash(&w->wd, sizeof(int))); w1 = hashmap_remove_entry(&data->watches, &k1, ent, NULL); if (!w1) - BUG("Double remove of watch for '%s'", w->dir); + BUG("double remove of watch for '%s'", w->dir); if (w1->cookie) - BUG("Removing watch for '%s' which has a pending rename", w1->dir); + BUG("removing watch for '%s' which has a pending rename", w1->dir); hashmap_entry_init(&k2.ent, memhash(w->dir, strlen(w->dir))); w2 = hashmap_remove_entry(&data->revwatches, &k2, ent, NULL); if (!w2) - BUG("Double remove of reverse watch for '%s'", w->dir); + BUG("double remove of reverse watch for '%s'", w->dir); /* w1->dir and w2->dir are interned strings, we don't own them */ free(w1); @@ -187,7 +190,7 @@ static void add_dir_rename(uint32_t cookie, const char *path, hashmap_entry_init(&k.ent, memhash(path, strlen(path))); w = hashmap_get_entry(&data->revwatches, &k, ent, NULL); if (!w) /* should never happen */ - BUG("No watch for '%s'", path); + BUG("no watch for '%s'", path); w->cookie = cookie; /* add the pending rename to match against later */ @@ -224,10 +227,10 @@ static void rename_dir(uint32_t cookie, const char *path, remove_watch(w, data); add_watch(path, data); } else { - BUG("No matching watch"); + BUG("no matching watch"); } } else { - BUG("No matching cookie"); + BUG("no matching cookie"); } } @@ -249,7 +252,7 @@ static int register_inotify(const char *path, if (!dir) return error_errno("opendir('%s') failed", path); - while ((de = readdir_skip_dot_and_dotdot(dir)) != NULL) { + while ((de = readdir_skip_dot_and_dotdot(dir))) { strbuf_reset(¤t); strbuf_addf(¤t, "%s/%s", path, de->d_name); if (lstat(current.buf, &fs)) { @@ -353,7 +356,7 @@ static void log_mask_set(const char *path, u_int32_t mask) if (mask & IN_IGNORED) strbuf_addstr(&msg, "IN_IGNORED|"); if (mask & IN_ISDIR) - strbuf_addstr(&msg, "IN_ISDIR|"); + strbuf_addstr(&msg, "IN_ISDIR"); trace_printf_key(&trace_fsmonitor, "inotify_event: '%s', mask=%#8.8x %s", path, mask, msg.buf); @@ -373,8 +376,10 @@ int fsm_listen__ctor(struct fsmonitor_daemon_state *state) data->shutdown = SHUTDOWN_ERROR; fd = inotify_init1(O_NONBLOCK); - if (fd < 0) + if (fd < 0) { + FREE_AND_NULL(data); return error_errno("inotify_init1() failed"); + } data->fd_inotify = fd; @@ -386,12 +391,10 @@ int fsm_listen__ctor(struct fsmonitor_daemon_state *state) ret = -1; else if (register_inotify(state->path_worktree_watch.buf, state, NULL)) ret = -1; - else if (state->nr_paths_watching > 1) { - if (add_watch(state->path_gitdir_watch.buf, data)) - ret = -1; - else if (register_inotify(state->path_gitdir_watch.buf, state, NULL)) - ret = -1; - } + else if (state->nr_paths_watching > 1 && + (add_watch(state->path_gitdir_watch.buf, data) || + register_inotify(state->path_gitdir_watch.buf, state, NULL))) + ret = -1; if (!ret) { state->listen_error_code = 0; @@ -449,80 +452,80 @@ static int process_event(const char *path, const char *last_sep; switch (fsmonitor_classify_path_absolute(state, path)) { - case IS_INSIDE_DOT_GIT_WITH_COOKIE_PREFIX: - case IS_INSIDE_GITDIR_WITH_COOKIE_PREFIX: - /* Use just the filename of the cookie file. */ - last_sep = find_last_dir_sep(path); - string_list_append(cookie_list, - last_sep ? last_sep + 1 : path); - break; - case IS_INSIDE_DOT_GIT: - case IS_INSIDE_GITDIR: - break; - case IS_DOT_GIT: - case IS_GITDIR: - /* - * If .git directory is deleted or renamed away, - * we have to quit. - */ - if (em_dir_deleted(event->mask)) { - trace_printf_key(&trace_fsmonitor, - "event: gitdir removed"); - state->listen_data->shutdown = SHUTDOWN_FORCE; - goto done; - } + case IS_INSIDE_DOT_GIT_WITH_COOKIE_PREFIX: + case IS_INSIDE_GITDIR_WITH_COOKIE_PREFIX: + /* Use just the filename of the cookie file. */ + last_sep = find_last_dir_sep(path); + string_list_append(cookie_list, + last_sep ? last_sep + 1 : path); + break; + case IS_INSIDE_DOT_GIT: + case IS_INSIDE_GITDIR: + break; + case IS_DOT_GIT: + case IS_GITDIR: + /* + * If .git directory is deleted or renamed away, + * we have to quit. + */ + if (em_dir_deleted(event->mask)) { + trace_printf_key(&trace_fsmonitor, + "event: gitdir removed"); + state->listen_data->shutdown = SHUTDOWN_FORCE; + goto done; + } - if (em_dir_renamed(event->mask)) { - trace_printf_key(&trace_fsmonitor, - "event: gitdir renamed"); - state->listen_data->shutdown = SHUTDOWN_FORCE; - goto done; - } - break; - case IS_WORKDIR_PATH: - /* normal events in the working directory */ - if (trace_pass_fl(&trace_fsmonitor)) - log_mask_set(path, event->mask); + if (em_dir_renamed(event->mask)) { + trace_printf_key(&trace_fsmonitor, + "event: gitdir renamed"); + state->listen_data->shutdown = SHUTDOWN_FORCE; + goto done; + } + break; + case IS_WORKDIR_PATH: + /* normal events in the working directory */ + if (trace_pass_fl(&trace_fsmonitor)) + log_mask_set(path, event->mask); - rel = path + state->path_worktree_watch.len + 1; - fsmonitor_batch__add_path(batch, rel); + rel = path + state->path_worktree_watch.len + 1; + fsmonitor_batch__add_path(batch, rel); - if (em_dir_deleted(event->mask)) - break; + if (em_dir_deleted(event->mask)) + break; - /* received IN_MOVE_FROM, add tracking for expected IN_MOVE_TO */ - if (em_rename_dir_from(event->mask)) - add_dir_rename(event->cookie, path, state->listen_data); + /* received IN_MOVE_FROM, add tracking for expected IN_MOVE_TO */ + if (em_rename_dir_from(event->mask)) + add_dir_rename(event->cookie, path, state->listen_data); - /* received IN_MOVE_TO, update watch to reflect new path */ - if (em_rename_dir_to(event->mask)) { - rename_dir(event->cookie, path, state->listen_data); - if (register_inotify(path, state, batch)) { - state->listen_data->shutdown = SHUTDOWN_ERROR; - goto done; - } + /* received IN_MOVE_TO, update watch to reflect new path */ + if (em_rename_dir_to(event->mask)) { + rename_dir(event->cookie, path, state->listen_data); + if (register_inotify(path, state, batch)) { + state->listen_data->shutdown = SHUTDOWN_ERROR; + goto done; } + } - if (em_dir_created(event->mask)) { - if (add_watch(path, state->listen_data)) { - state->listen_data->shutdown = SHUTDOWN_ERROR; - goto done; - } - if (register_inotify(path, state, batch)) { - state->listen_data->shutdown = SHUTDOWN_ERROR; - goto done; - } + if (em_dir_created(event->mask)) { + if (add_watch(path, state->listen_data)) { + state->listen_data->shutdown = SHUTDOWN_ERROR; + goto done; } - break; - case IS_OUTSIDE_CONE: - default: - trace_printf_key(&trace_fsmonitor, - "ignoring '%s'", path); - break; + if (register_inotify(path, state, batch)) { + state->listen_data->shutdown = SHUTDOWN_ERROR; + goto done; + } + } + break; + case IS_OUTSIDE_CONE: + default: + trace_printf_key(&trace_fsmonitor, + "ignoring '%s'", path); + break; } return 0; -done: - return -1; + done: + return -1; } /* @@ -531,7 +534,7 @@ static int process_event(const char *path, */ static void handle_events(struct fsmonitor_daemon_state *state) { - /* See https://man7.org/linux/man-pages/man7/inotify.7.html */ + /* See https://man7.org/linux/man-pages/man7/inotify.7.html */ char buf[4096] __attribute__ ((aligned(__alignof__(struct inotify_event)))); @@ -539,13 +542,12 @@ static void handle_events(struct fsmonitor_daemon_state *state) struct fsmonitor_batch *batch = NULL; struct string_list cookie_list = STRING_LIST_INIT_DUP; struct watch_entry k, *w; - struct strbuf path; const struct inotify_event *event; int fd = state->listen_data->fd_inotify; ssize_t len; char *ptr, *p; - strbuf_init(&path, PATH_MAX); + struct strbuf path = STRBUF_INIT; for(;;) { len = read(fd, buf, sizeof(buf)); @@ -581,7 +583,7 @@ static void handle_events(struct fsmonitor_daemon_state *state) w = hashmap_get_entry(&watches, &k, ent, NULL); if (!w) /* should never happen */ - BUG("No watch for '%s'", event->name); + BUG("no watch for '%s'", event->name); /* directory watch was removed */ if (em_remove_watch(event->mask)) { diff --git a/compat/fsmonitor/fsm-path-utils-linux.c b/compat/fsmonitor/fsm-path-utils-linux.c index c21d1349532..0e3b33ffa48 100644 --- a/compat/fsmonitor/fsm-path-utils-linux.c +++ b/compat/fsmonitor/fsm-path-utils-linux.c @@ -3,6 +3,7 @@ #include "fsmonitor.h" #include "fsmonitor-path-utils.h" #include "fsm-path-utils-linux.h" +#include "gettext.h" #include #include #include diff --git a/compat/fsmonitor/fsm-settings-unix.c b/compat/fsmonitor/fsm-settings-unix.c index d16dca89416..c9b75aa44fe 100644 --- a/compat/fsmonitor/fsm-settings-unix.c +++ b/compat/fsmonitor/fsm-settings-unix.c @@ -1,6 +1,9 @@ +#include "git-compat-util.h" +#include "config.h" #include "fsmonitor.h" #include "fsmonitor-ipc.h" #include "fsmonitor-path-utils.h" +#include /* * For the builtin FSMonitor, we create the Unix domain socket for the