From patchwork Fri Oct 14 21:45:33 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Eric DeCosta X-Patchwork-Id: 13007365 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id DE925C433FE for ; Fri, 14 Oct 2022 21:45:57 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S229783AbiJNVp4 (ORCPT ); Fri, 14 Oct 2022 17:45:56 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:36006 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S229542AbiJNVpy (ORCPT ); Fri, 14 Oct 2022 17:45:54 -0400 Received: from mail-wm1-x32e.google.com (mail-wm1-x32e.google.com [IPv6:2a00:1450:4864:20::32e]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 01F5A53A7C for ; Fri, 14 Oct 2022 14:45:49 -0700 (PDT) Received: by mail-wm1-x32e.google.com with SMTP id y10so4021098wma.0 for ; Fri, 14 Oct 2022 14:45:49 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20210112; 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=/UUex0cY0K6feHq8tu7IWFSwvIPxLCCgjSfeFT2OfB8=; b=RNz/V0jv8VE1VL1pT2fdEkDIr92tUtfP59mkTDUQIPo1couu5MqmkW2QK0sY/i2xJp k5NzNFScp5wpkQEliVu0Q2Wng7z1I9EzE+m/L9/tpcsFtKiVeSC3xVUpSJ4xevdCxAXN icJ0QYPVi3mxY9bfsdqOmKQICssZXmT5MQuMIhDsIKd8k4MQuM5QBQXcypZk3svAkd09 lTGgy4kUaOK9ygDF0WIzK5buzbUw+YeVCqju9IBz69+klJWa8fORDZbN0ino/CM9EWkt ajK4i3QgYP/BsjFVtAl+Ha5kfCHqSdx9nJ2HaGj2/R4zJUhYvuDKGbCaPyHKNNrS/NZk pWhQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; 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=/UUex0cY0K6feHq8tu7IWFSwvIPxLCCgjSfeFT2OfB8=; b=woZf5QFuHCe+uIZZO3nCYMBJqESds4WdR2+BqUm42ttrAkbbwCojc6/UXJX27/HDUG l4balWK1FLBkgi9VMitAik8vXP+XjBIf+FhsZ2Xm1eckSaU+3Ut0tLZAmSnRix5YSzXl M8fC5UtnKDEbVLC0TbQgvCOsymAUf7D8UnprlvdbwWTVXwP6dqdwrOpcugTLYq6N1sc9 gWTJ64uxiNqwA7srSRhOMk0cp2+B5ghWCWtYTQ0J1Zwqd6QdO5mZmuBoMdQCfydBRG2F g2jwwJAOWAiywfLFE/uJrF8mjwYEkFAAIJf8z3ZJgycSgC1jWOh3hffsCwSmOBLks+3H /nJQ== X-Gm-Message-State: ACrzQf1esG+U6wBv7SMGBjIcFvmoGGKVm4P3BwppvF6WQkxt2sV6MUrC DyA8+8VPiWsmxEwTzwfYVJVxVz4jdX8= X-Google-Smtp-Source: AMsMyM7H/gfDnQBupo9+jwEk3zTfMwGOtBRi/fG5AMCmstyDkmd7r2GlJrE7a0aC1h3ckdXldyQ1lA== X-Received: by 2002:a05:600c:35ce:b0:3c6:809a:b5c3 with SMTP id r14-20020a05600c35ce00b003c6809ab5c3mr4937830wmq.206.1665783947609; Fri, 14 Oct 2022 14:45:47 -0700 (PDT) Received: from [127.0.0.1] ([13.74.141.28]) by smtp.gmail.com with ESMTPSA id t15-20020a5d49cf000000b0022e32f4c06asm2756343wrs.11.2022.10.14.14.45.46 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Fri, 14 Oct 2022 14:45:46 -0700 (PDT) Message-Id: In-Reply-To: References: Date: Fri, 14 Oct 2022 21:45:33 +0000 Subject: [PATCH v2 01/12] fsmonitor: refactor filesystem checks to common interface Fcc: Sent MIME-Version: 1.0 To: git@vger.kernel.org Cc: Eric Sunshine , =?utf-8?b?w4Z2YXIgQXJuZmrDtnI=?= =?utf-8?b?w7A=?= Bjarmason , Eric DeCosta , Eric DeCosta Precedence: bulk List-ID: X-Mailing-List: git@vger.kernel.org From: Eric DeCosta From: Eric DeCosta Provide a common interface for getting basic filesystem information including filesystem type and whether the filesystem is remote. Refactor existing code for getting basic filesystem info and detecting remote file systems to the new interface. Refactor filesystem checks to leverage new interface. For macOS, error-out if the Unix Domain socket (UDS) file is on a remote filesystem. Signed-off-by: Eric DeCosta --- Makefile | 1 + compat/fsmonitor/fsm-path-utils-darwin.c | 43 ++++++ compat/fsmonitor/fsm-path-utils-win32.c | 128 +++++++++++++++++ compat/fsmonitor/fsm-settings-darwin.c | 69 +++------ compat/fsmonitor/fsm-settings-win32.c | 172 +---------------------- contrib/buildsystems/CMakeLists.txt | 2 + fsmonitor-path-utils.h | 26 ++++ fsmonitor-settings.c | 50 +++++++ 8 files changed, 272 insertions(+), 219 deletions(-) create mode 100644 compat/fsmonitor/fsm-path-utils-darwin.c create mode 100644 compat/fsmonitor/fsm-path-utils-win32.c create mode 100644 fsmonitor-path-utils.h diff --git a/Makefile b/Makefile index 6bfb62cbe94..99a3d9e6322 100644 --- a/Makefile +++ b/Makefile @@ -2043,6 +2043,7 @@ endif ifdef FSMONITOR_OS_SETTINGS COMPAT_CFLAGS += -DHAVE_FSMONITOR_OS_SETTINGS COMPAT_OBJS += compat/fsmonitor/fsm-settings-$(FSMONITOR_OS_SETTINGS).o + COMPAT_OBJS += compat/fsmonitor/fsm-path-utils-$(FSMONITOR_OS_SETTINGS).o endif ifeq ($(TCLTK_PATH),) diff --git a/compat/fsmonitor/fsm-path-utils-darwin.c b/compat/fsmonitor/fsm-path-utils-darwin.c new file mode 100644 index 00000000000..d46d7f13538 --- /dev/null +++ b/compat/fsmonitor/fsm-path-utils-darwin.c @@ -0,0 +1,43 @@ +#include "fsmonitor.h" +#include "fsmonitor-path-utils.h" +#include +#include + +int fsmonitor__get_fs_info(const char *path, struct fs_info *fs_info) +{ + struct statfs fs; + if (statfs(path, &fs) == -1) { + int saved_errno = errno; + trace_printf_key(&trace_fsmonitor, "statfs('%s') failed: %s", + path, strerror(saved_errno)); + errno = saved_errno; + return -1; + } + + trace_printf_key(&trace_fsmonitor, + "statfs('%s') [type 0x%08x][flags 0x%08x] '%s'", + path, fs.f_type, fs.f_flags, fs.f_fstypename); + + if (!(fs.f_flags & MNT_LOCAL)) + fs_info->is_remote = 1; + else + fs_info->is_remote = 0; + + fs_info->typename = xstrdup(fs.f_fstypename); + + trace_printf_key(&trace_fsmonitor, + "'%s' is_remote: %d", + path, fs_info->is_remote); + return 0; +} + +int fsmonitor__is_fs_remote(const char *path) +{ + struct fs_info fs; + if (fsmonitor__get_fs_info(path, &fs)) + return -1; + + free(fs.typename); + + return fs.is_remote; +} diff --git a/compat/fsmonitor/fsm-path-utils-win32.c b/compat/fsmonitor/fsm-path-utils-win32.c new file mode 100644 index 00000000000..a90b8f7925b --- /dev/null +++ b/compat/fsmonitor/fsm-path-utils-win32.c @@ -0,0 +1,128 @@ +#include "cache.h" +#include "fsmonitor.h" +#include "fsmonitor-path-utils.h" + +/* + * Check remote working directory protocol. + * + * Return -1 if client machine cannot get remote protocol information. + */ +static int check_remote_protocol(wchar_t *wpath) +{ + HANDLE h; + FILE_REMOTE_PROTOCOL_INFO proto_info; + + h = CreateFileW(wpath, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, + FILE_FLAG_BACKUP_SEMANTICS, NULL); + + if (h == INVALID_HANDLE_VALUE) { + error(_("[GLE %ld] unable to open for read '%ls'"), + GetLastError(), wpath); + return -1; + } + + if (!GetFileInformationByHandleEx(h, FileRemoteProtocolInfo, + &proto_info, sizeof(proto_info))) { + error(_("[GLE %ld] unable to get protocol information for '%ls'"), + GetLastError(), wpath); + CloseHandle(h); + return -1; + } + + CloseHandle(h); + + trace_printf_key(&trace_fsmonitor, + "check_remote_protocol('%ls') remote protocol %#8.8lx", + wpath, proto_info.Protocol); + + return 0; +} + +/* + * Notes for testing: + * + * (a) Windows allows a network share to be mapped to a drive letter. + * (This is the normal method to access it.) + * + * $ NET USE Z: \\server\share + * $ git -C Z:/repo status + * + * (b) Windows allows a network share to be referenced WITHOUT mapping + * it to drive letter. + * + * $ NET USE \\server\share\dir + * $ git -C //server/share/repo status + * + * (c) Windows allows "SUBST" to create a fake drive mapping to an + * arbitrary path (which may be remote) + * + * $ SUBST Q: Z:\repo + * $ git -C Q:/ status + * + * (d) Windows allows a directory symlink to be created on a local + * file system that points to a remote repo. + * + * $ mklink /d ./link //server/share/repo + * $ git -C ./link status + */ +int fsmonitor__get_fs_info(const char *path, struct fs_info *fs_info) +{ + wchar_t wpath[MAX_PATH]; + wchar_t wfullpath[MAX_PATH]; + size_t wlen; + UINT driveType; + + /* + * Do everything in wide chars because the drive letter might be + * a multi-byte sequence. See win32_has_dos_drive_prefix(). + */ + if (xutftowcs_path(wpath, path) < 0) { + return -1; + } + + /* + * GetDriveTypeW() requires a final slash. We assume that the + * worktree pathname points to an actual directory. + */ + wlen = wcslen(wpath); + if (wpath[wlen - 1] != L'\\' && wpath[wlen - 1] != L'/') { + wpath[wlen++] = L'\\'; + wpath[wlen] = 0; + } + + /* + * Normalize the path. If nothing else, this converts forward + * slashes to backslashes. This is essential to get GetDriveTypeW() + * correctly handle some UNC "\\server\share\..." paths. + */ + if (!GetFullPathNameW(wpath, MAX_PATH, wfullpath, NULL)) { + return -1; + } + + driveType = GetDriveTypeW(wfullpath); + trace_printf_key(&trace_fsmonitor, + "DriveType '%s' L'%ls' (%u)", + path, wfullpath, driveType); + + if (driveType == DRIVE_REMOTE) { + fs_info->is_remote = 1; + if (check_remote_protocol(wfullpath) < 0) + return -1; + } else { + fs_info->is_remote = 0; + } + + trace_printf_key(&trace_fsmonitor, + "'%s' is_remote: %d", + path, fs_info->is_remote); + + return 0; +} + +int fsmonitor__is_fs_remote(const char *path) +{ + struct fs_info fs; + if (fsmonitor__get_fs_info(path, &fs)) + return -1; + return fs.is_remote; +} diff --git a/compat/fsmonitor/fsm-settings-darwin.c b/compat/fsmonitor/fsm-settings-darwin.c index efc732c0f31..699f0b272e6 100644 --- a/compat/fsmonitor/fsm-settings-darwin.c +++ b/compat/fsmonitor/fsm-settings-darwin.c @@ -1,32 +1,10 @@ -#include "cache.h" #include "config.h" -#include "repository.h" -#include "fsmonitor-settings.h" #include "fsmonitor.h" -#include -#include +#include "fsmonitor-ipc.h" +#include "fsmonitor-settings.h" +#include "fsmonitor-path-utils.h" -/* - * [1] Remote working directories are problematic for FSMonitor. - * - * The underlying file system on the server machine and/or the remote - * mount type (NFS, SAMBA, etc.) dictates whether notification events - * are available at all to remote client machines. - * - * Kernel differences between the server and client machines also - * dictate the how (buffering, frequency, de-dup) the events are - * delivered to client machine processes. - * - * A client machine (such as a laptop) may choose to suspend/resume - * and it is unclear (without lots of testing) whether the watcher can - * resync after a resume. We might be able to treat this as a normal - * "events were dropped by the kernel" event and do our normal "flush - * and resync" --or-- we might need to close the existing (zombie?) - * notification fd and create a new one. - * - * In theory, the above issues need to be addressed whether we are - * using the Hook or IPC API. - * + /* * 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 @@ -38,42 +16,35 @@ * be taken to ensure that $HOME is actually local and not a managed * file share.) * - * So (for now at least), mark remote working directories as - * incompatible. - * - * - * [2] FAT32 and NTFS working directories are problematic too. + * 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_volume(struct repository *r) +static enum fsmonitor_reason check_uds_volume(struct repository *r) { - struct statfs fs; + struct fs_info fs; + const char *ipc_path = fsmonitor_ipc__get_path(); + struct strbuf path = STRBUF_INIT; + strbuf_add(&path, ipc_path, strlen(ipc_path)); - if (statfs(r->worktree, &fs) == -1) { - int saved_errno = errno; - trace_printf_key(&trace_fsmonitor, "statfs('%s') failed: %s", - r->worktree, strerror(saved_errno)); - errno = saved_errno; + if (fsmonitor__get_fs_info(dirname(path.buf), &fs) == -1) { + strbuf_release(&path); return FSMONITOR_REASON_ERROR; } - trace_printf_key(&trace_fsmonitor, - "statfs('%s') [type 0x%08x][flags 0x%08x] '%s'", - r->worktree, fs.f_type, fs.f_flags, fs.f_fstypename); - - if (!(fs.f_flags & MNT_LOCAL)) - return FSMONITOR_REASON_REMOTE; + strbuf_release(&path); - if (!strcmp(fs.f_fstypename, "msdos")) /* aka FAT32 */ - return FSMONITOR_REASON_NOSOCKETS; - - if (!strcmp(fs.f_fstypename, "ntfs")) + 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; } @@ -81,7 +52,7 @@ enum fsmonitor_reason fsm_os__incompatible(struct repository *r) { enum fsmonitor_reason reason; - reason = check_volume(r); + reason = check_uds_volume(r); if (reason != FSMONITOR_REASON_OK) return reason; diff --git a/compat/fsmonitor/fsm-settings-win32.c b/compat/fsmonitor/fsm-settings-win32.c index e5ec5b0a9f7..d88b06ae610 100644 --- a/compat/fsmonitor/fsm-settings-win32.c +++ b/compat/fsmonitor/fsm-settings-win32.c @@ -1,8 +1,9 @@ #include "cache.h" #include "config.h" #include "repository.h" -#include "fsmonitor-settings.h" #include "fsmonitor.h" +#include "fsmonitor-settings.h" +#include "fsmonitor-path-utils.h" /* * VFS for Git is incompatible with FSMonitor. @@ -24,171 +25,6 @@ static enum fsmonitor_reason check_vfs4git(struct repository *r) return FSMONITOR_REASON_OK; } -/* - * Check if monitoring remote working directories is allowed. - * - * By default, monitoring remote working directories is - * disabled. Users may override this behavior in enviroments where - * they have proper support. - */ -static int check_config_allowremote(struct repository *r) -{ - int allow; - - if (!repo_config_get_bool(r, "fsmonitor.allowremote", &allow)) - return allow; - - return -1; /* fsmonitor.allowremote not set */ -} - -/* - * Check remote working directory protocol. - * - * Error if client machine cannot get remote protocol information. - */ -static int check_remote_protocol(wchar_t *wpath) -{ - HANDLE h; - FILE_REMOTE_PROTOCOL_INFO proto_info; - - h = CreateFileW(wpath, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, - FILE_FLAG_BACKUP_SEMANTICS, NULL); - - if (h == INVALID_HANDLE_VALUE) { - error(_("[GLE %ld] unable to open for read '%ls'"), - GetLastError(), wpath); - return -1; - } - - if (!GetFileInformationByHandleEx(h, FileRemoteProtocolInfo, - &proto_info, sizeof(proto_info))) { - error(_("[GLE %ld] unable to get protocol information for '%ls'"), - GetLastError(), wpath); - CloseHandle(h); - return -1; - } - - CloseHandle(h); - - trace_printf_key(&trace_fsmonitor, - "check_remote_protocol('%ls') remote protocol %#8.8lx", - wpath, proto_info.Protocol); - - return 0; -} - -/* - * Remote working directories are problematic for FSMonitor. - * - * The underlying file system on the server machine and/or the remote - * mount type dictates whether notification events are available at - * all to remote client machines. - * - * Kernel differences between the server and client machines also - * dictate the how (buffering, frequency, de-dup) the events are - * delivered to client machine processes. - * - * A client machine (such as a laptop) may choose to suspend/resume - * and it is unclear (without lots of testing) whether the watcher can - * resync after a resume. We might be able to treat this as a normal - * "events were dropped by the kernel" event and do our normal "flush - * and resync" --or-- we might need to close the existing (zombie?) - * notification fd and create a new one. - * - * In theory, the above issues need to be addressed whether we are - * using the Hook or IPC API. - * - * So (for now at least), mark remote working directories as - * incompatible. - * - * Notes for testing: - * - * (a) Windows allows a network share to be mapped to a drive letter. - * (This is the normal method to access it.) - * - * $ NET USE Z: \\server\share - * $ git -C Z:/repo status - * - * (b) Windows allows a network share to be referenced WITHOUT mapping - * it to drive letter. - * - * $ NET USE \\server\share\dir - * $ git -C //server/share/repo status - * - * (c) Windows allows "SUBST" to create a fake drive mapping to an - * arbitrary path (which may be remote) - * - * $ SUBST Q: Z:\repo - * $ git -C Q:/ status - * - * (d) Windows allows a directory symlink to be created on a local - * file system that points to a remote repo. - * - * $ mklink /d ./link //server/share/repo - * $ git -C ./link status - */ -static enum fsmonitor_reason check_remote(struct repository *r) -{ - int ret; - wchar_t wpath[MAX_PATH]; - wchar_t wfullpath[MAX_PATH]; - size_t wlen; - UINT driveType; - - /* - * Do everything in wide chars because the drive letter might be - * a multi-byte sequence. See win32_has_dos_drive_prefix(). - */ - if (xutftowcs_path(wpath, r->worktree) < 0) - return FSMONITOR_REASON_ERROR; - - /* - * GetDriveTypeW() requires a final slash. We assume that the - * worktree pathname points to an actual directory. - */ - wlen = wcslen(wpath); - if (wpath[wlen - 1] != L'\\' && wpath[wlen - 1] != L'/') { - wpath[wlen++] = L'\\'; - wpath[wlen] = 0; - } - - /* - * Normalize the path. If nothing else, this converts forward - * slashes to backslashes. This is essential to get GetDriveTypeW() - * correctly handle some UNC "\\server\share\..." paths. - */ - if (!GetFullPathNameW(wpath, MAX_PATH, wfullpath, NULL)) - return FSMONITOR_REASON_ERROR; - - driveType = GetDriveTypeW(wfullpath); - trace_printf_key(&trace_fsmonitor, - "DriveType '%s' L'%ls' (%u)", - r->worktree, wfullpath, driveType); - - if (driveType == DRIVE_REMOTE) { - trace_printf_key(&trace_fsmonitor, - "check_remote('%s') true", - r->worktree); - - ret = check_remote_protocol(wfullpath); - if (ret < 0) - return FSMONITOR_REASON_ERROR; - - switch (check_config_allowremote(r)) { - case 0: /* config overrides and disables */ - return FSMONITOR_REASON_REMOTE; - case 1: /* config overrides and enables */ - return FSMONITOR_REASON_OK; - default: - break; /* config has no opinion */ - } - - return FSMONITOR_REASON_REMOTE; - } - - return FSMONITOR_REASON_OK; -} - enum fsmonitor_reason fsm_os__incompatible(struct repository *r) { enum fsmonitor_reason reason; @@ -197,9 +33,5 @@ enum fsmonitor_reason fsm_os__incompatible(struct repository *r) if (reason != FSMONITOR_REASON_OK) return reason; - reason = check_remote(r); - if (reason != FSMONITOR_REASON_OK) - return reason; - return FSMONITOR_REASON_OK; } diff --git a/contrib/buildsystems/CMakeLists.txt b/contrib/buildsystems/CMakeLists.txt index ea2a531be87..5482a04b3ce 100644 --- a/contrib/buildsystems/CMakeLists.txt +++ b/contrib/buildsystems/CMakeLists.txt @@ -308,6 +308,7 @@ if(SUPPORTS_SIMPLE_IPC) 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) + list(APPEND compat_SOURCES compat/fsmonitor/fsm-path-utils-win32.c) add_compile_definitions(HAVE_FSMONITOR_OS_SETTINGS) list(APPEND compat_SOURCES compat/fsmonitor/fsm-settings-win32.c) @@ -315,6 +316,7 @@ if(SUPPORTS_SIMPLE_IPC) add_compile_definitions(HAVE_FSMONITOR_DAEMON_BACKEND) list(APPEND compat_SOURCES compat/fsmonitor/fsm-listen-darwin.c) list(APPEND compat_SOURCES compat/fsmonitor/fsm-health-darwin.c) + list(APPEND compat_SOURCES compat/fsmonitor/fsm-path-utils-darwin.c) add_compile_definitions(HAVE_FSMONITOR_OS_SETTINGS) list(APPEND compat_SOURCES compat/fsmonitor/fsm-settings-darwin.c) diff --git a/fsmonitor-path-utils.h b/fsmonitor-path-utils.h new file mode 100644 index 00000000000..41edf5b934f --- /dev/null +++ b/fsmonitor-path-utils.h @@ -0,0 +1,26 @@ +#ifndef FSM_PATH_UTILS_H +#define FSM_PATH_UTILS_H + +struct fs_info { + int is_remote; + char *typename; +}; + +/* + * Get some basic filesystem informtion for the given path + * + * The caller owns the storage that is occupied by fs_info and + * is responsible for releasing it. + * + * Returns -1 on error, zero otherwise. + */ +int fsmonitor__get_fs_info(const char *path, struct fs_info *fs_info); + +/* + * Determines if the filesystem that path resides on is remote. + * + * Returns -1 on error, 0 if not remote, 1 if remote. + */ +int fsmonitor__is_fs_remote(const char *path); + +#endif diff --git a/fsmonitor-settings.c b/fsmonitor-settings.c index 464424a1e92..d288cbad479 100644 --- a/fsmonitor-settings.c +++ b/fsmonitor-settings.c @@ -2,6 +2,7 @@ #include "config.h" #include "repository.h" #include "fsmonitor-settings.h" +#include "fsmonitor-path-utils.h" /* * We keep this structure defintion private and have getters @@ -13,6 +14,52 @@ struct fsmonitor_settings { char *hook_path; }; +/* + * Remote working directories are problematic for FSMonitor. + * + * The underlying file system on the server machine and/or the remote + * mount type dictates whether notification events are available at + * all to remote client machines. + * + * Kernel differences between the server and client machines also + * dictate the how (buffering, frequency, de-dup) the events are + * delivered to client machine processes. + * + * A client machine (such as a laptop) may choose to suspend/resume + * and it is unclear (without lots of testing) whether the watcher can + * resync after a resume. We might be able to treat this as a normal + * "events were dropped by the kernel" event and do our normal "flush + * and resync" --or-- we might need to close the existing (zombie?) + * notification fd and create a new one. + * + * In theory, the above issues need to be addressed whether we are + * using the Hook or IPC API. + * + * So (for now at least), mark remote working directories as + * incompatible unless 'fsmonitor.allowRemote' is true. + * + */ +#ifdef HAVE_FSMONITOR_OS_SETTINGS +static enum fsmonitor_reason check_remote(struct repository *r) +{ + int allow_remote = -1; /* -1 unset, 0 not allowed, 1 allowed */ + int is_remote = fsmonitor__is_fs_remote(r->worktree); + + switch (is_remote) { + case 0: + return FSMONITOR_REASON_OK; + case 1: + repo_config_get_bool(r, "fsmonitor.allowremote", &allow_remote); + if (allow_remote < 1) + return FSMONITOR_REASON_REMOTE; + else + return FSMONITOR_REASON_OK; + default: + return FSMONITOR_REASON_ERROR; + } +} +#endif + static enum fsmonitor_reason check_for_incompatible(struct repository *r) { if (!r->worktree) { @@ -27,6 +74,9 @@ static enum fsmonitor_reason check_for_incompatible(struct repository *r) { enum fsmonitor_reason reason; + reason = check_remote(r); + if (reason != FSMONITOR_REASON_OK) + return reason; reason = fsm_os__incompatible(r); if (reason != FSMONITOR_REASON_OK) return reason; From patchwork Fri Oct 14 21:45:34 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Eric DeCosta X-Patchwork-Id: 13007366 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id D0A73C4332F for ; Fri, 14 Oct 2022 21:45:59 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S229672AbiJNVp7 (ORCPT ); Fri, 14 Oct 2022 17:45:59 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:36014 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S229607AbiJNVpy (ORCPT ); Fri, 14 Oct 2022 17:45:54 -0400 Received: from mail-wr1-x432.google.com (mail-wr1-x432.google.com [IPv6:2a00:1450:4864:20::432]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 1B4355FDC2 for ; Fri, 14 Oct 2022 14:45:50 -0700 (PDT) Received: by mail-wr1-x432.google.com with SMTP id j7so9571243wrr.3 for ; Fri, 14 Oct 2022 14:45:50 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20210112; 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=SKWiRKw+pE4bAIjbr7RdfgLWN24DhrcCIKvw4qxruKM=; b=pcySvTH8POc8zTJRTrWpxerdyKE4e5FhA7AiCZ7mYrJzvdWkh69P+I2MheTQ4xucCt HGZmBC0gQD1n3Aygbf0dpJDxySl8O5SWHGi4glXXM4Ymb5YtaBnj4sCkTmlc6qQJhpVp /rzsIyqjsdMZoQlK/KmhjVtPdtml9Bp5FeAAotw8qo225o0VNdvnpSjMeoe3xxkqmOG0 CDbgr7AxP6i50EaWKxZFVqpBK71/xZ+manV11gfnKq79fRUnFdVQqycboRp5wBfipmuM EwHJ8aGRBqMYCoWAbHj+uecIsW3YW1Qe7c9ZZIZ6eGXeB0n2EVmPMrrwza4IqO246ihY deFQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; 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=SKWiRKw+pE4bAIjbr7RdfgLWN24DhrcCIKvw4qxruKM=; b=EnMZUNJSnqD9fWE/0MDIE1gCBuQsSrq4DdrEdlIUNYREpn9CnGMm8TflQFw5ax/kxT S5b/t+MCUTpkKQ7oMlwggBJXGqTUn8Z0snjljC2XzGTjvZgnAP42NWelWga/m5F8xQ5/ imXu+V1+Ocivv9U4n/oUNdijWi+oisTJxDmQXebiTze6HlScRwJzVzgbX+wYDuyPGvhc 9BHaTGEqjU5Q4e/ZQcyQf338Gs/Iars3Z3t4cGnGjXf0Fg/ieRx9SMi30qEEf1gTR5sj hRhixqzuQnGJpRisFUPFQi1b89oBe69180tV8VljC1TK8cS5bH5nROIZVPCfuGMqsrhh BLKA== X-Gm-Message-State: ACrzQf2c/5O8JeqfxOji+vJOkylpwjjp/Cz2UTFOmbLorCwPZ3bmyWdv 1ywTudhBDEJbhwDudD14ODPB/t+cwag= X-Google-Smtp-Source: AMsMyM4zsx41yBYQdZuqFh5WicCdgtEDWiHbjFi2DtP4J2yzFWwsw6OwdqwflGIP3nkvw+UX3aA6Tw== X-Received: by 2002:a05:6000:1541:b0:231:115e:9bb8 with SMTP id 1-20020a056000154100b00231115e9bb8mr4910482wry.51.1665783948983; Fri, 14 Oct 2022 14:45:48 -0700 (PDT) Received: from [127.0.0.1] ([13.74.141.28]) by smtp.gmail.com with ESMTPSA id k13-20020a5d6d4d000000b0022ac38fb20asm2690550wri.111.2022.10.14.14.45.47 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Fri, 14 Oct 2022 14:45:48 -0700 (PDT) Message-Id: <21d114bda4b515170ae43f01f9bb14befec611f2.1665783944.git.gitgitgadget@gmail.com> In-Reply-To: References: Date: Fri, 14 Oct 2022 21:45:34 +0000 Subject: [PATCH v2 02/12] fsmonitor: relocate socket file if .git directory is remote Fcc: Sent MIME-Version: 1.0 To: git@vger.kernel.org Cc: Eric Sunshine , =?utf-8?b?w4Z2YXIgQXJuZmrDtnI=?= =?utf-8?b?w7A=?= Bjarmason , Eric DeCosta , Eric DeCosta Precedence: bulk List-ID: X-Mailing-List: git@vger.kernel.org From: Eric DeCosta From: Eric DeCosta If the .git directory is on a remote filesystem, create the socket file in 'fsmonitor.socketDir' if it is defined, else create it in $HOME. Signed-off-by: Eric DeCosta --- Makefile | 1 + builtin/fsmonitor--daemon.c | 3 +- compat/fsmonitor/fsm-ipc-darwin.c | 52 ++++++++++++++++++++++++++ compat/fsmonitor/fsm-ipc-win32.c | 9 +++++ compat/fsmonitor/fsm-settings-darwin.c | 2 +- contrib/buildsystems/CMakeLists.txt | 2 + fsmonitor-ipc.c | 18 ++++----- fsmonitor-ipc.h | 4 +- 8 files changed, 78 insertions(+), 13 deletions(-) create mode 100644 compat/fsmonitor/fsm-ipc-darwin.c create mode 100644 compat/fsmonitor/fsm-ipc-win32.c diff --git a/Makefile b/Makefile index 99a3d9e6322..9553d590824 100644 --- a/Makefile +++ b/Makefile @@ -2038,6 +2038,7 @@ ifdef FSMONITOR_DAEMON_BACKEND COMPAT_CFLAGS += -DHAVE_FSMONITOR_DAEMON_BACKEND COMPAT_OBJS += compat/fsmonitor/fsm-listen-$(FSMONITOR_DAEMON_BACKEND).o COMPAT_OBJS += compat/fsmonitor/fsm-health-$(FSMONITOR_DAEMON_BACKEND).o + COMPAT_OBJS += compat/fsmonitor/fsm-ipc-$(FSMONITOR_DAEMON_BACKEND).o endif ifdef FSMONITOR_OS_SETTINGS diff --git a/builtin/fsmonitor--daemon.c b/builtin/fsmonitor--daemon.c index c69da93eceb..6e417846d8b 100644 --- a/builtin/fsmonitor--daemon.c +++ b/builtin/fsmonitor--daemon.c @@ -1343,7 +1343,8 @@ static int fsmonitor_run_daemon(void) * directory.) */ strbuf_init(&state.path_ipc, 0); - strbuf_addstr(&state.path_ipc, absolute_path(fsmonitor_ipc__get_path())); + strbuf_addstr(&state.path_ipc, + absolute_path(fsmonitor_ipc__get_path(the_repository))); /* * Confirm that we can create platform-specific resources for the diff --git a/compat/fsmonitor/fsm-ipc-darwin.c b/compat/fsmonitor/fsm-ipc-darwin.c new file mode 100644 index 00000000000..ce843d63348 --- /dev/null +++ b/compat/fsmonitor/fsm-ipc-darwin.c @@ -0,0 +1,52 @@ +#include "cache.h" +#include "config.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; + SHA_CTX sha1ctx; + char *sock_dir = NULL; + struct strbuf ipc_file = STRBUF_INIT; + unsigned char hash[SHA_DIGEST_LENGTH]; + + 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; + } + + SHA1_Init(&sha1ctx); + SHA1_Update(&sha1ctx, r->worktree, strlen(r->worktree)); + 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-ipc-win32.c b/compat/fsmonitor/fsm-ipc-win32.c new file mode 100644 index 00000000000..e08c505c148 --- /dev/null +++ b/compat/fsmonitor/fsm-ipc-win32.c @@ -0,0 +1,9 @@ +#include "config.h" +#include "fsmonitor-ipc.h" + +const char *fsmonitor_ipc__get_path(struct repository *r) { + static char *ret; + if (!ret) + ret = git_pathdup("fsmonitor--daemon.ipc"); + return ret; +} diff --git a/compat/fsmonitor/fsm-settings-darwin.c b/compat/fsmonitor/fsm-settings-darwin.c index 699f0b272e6..7241c4c22c9 100644 --- a/compat/fsmonitor/fsm-settings-darwin.c +++ b/compat/fsmonitor/fsm-settings-darwin.c @@ -26,7 +26,7 @@ static enum fsmonitor_reason check_uds_volume(struct repository *r) { struct fs_info fs; - const char *ipc_path = fsmonitor_ipc__get_path(); + const char *ipc_path = fsmonitor_ipc__get_path(r); struct strbuf path = STRBUF_INIT; strbuf_add(&path, ipc_path, strlen(ipc_path)); diff --git a/contrib/buildsystems/CMakeLists.txt b/contrib/buildsystems/CMakeLists.txt index 5482a04b3ce..787738e6fa3 100644 --- a/contrib/buildsystems/CMakeLists.txt +++ b/contrib/buildsystems/CMakeLists.txt @@ -308,6 +308,7 @@ if(SUPPORTS_SIMPLE_IPC) 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) + list(APPEND compat_SOURCES compat/fsmonitor/fsm-ipc-win32.c) list(APPEND compat_SOURCES compat/fsmonitor/fsm-path-utils-win32.c) add_compile_definitions(HAVE_FSMONITOR_OS_SETTINGS) @@ -316,6 +317,7 @@ if(SUPPORTS_SIMPLE_IPC) add_compile_definitions(HAVE_FSMONITOR_DAEMON_BACKEND) list(APPEND compat_SOURCES compat/fsmonitor/fsm-listen-darwin.c) list(APPEND compat_SOURCES compat/fsmonitor/fsm-health-darwin.c) + list(APPEND compat_SOURCES compat/fsmonitor/fsm-ipc-darwin.c) list(APPEND compat_SOURCES compat/fsmonitor/fsm-path-utils-darwin.c) add_compile_definitions(HAVE_FSMONITOR_OS_SETTINGS) diff --git a/fsmonitor-ipc.c b/fsmonitor-ipc.c index 789e7397baa..c0f42301c84 100644 --- a/fsmonitor-ipc.c +++ b/fsmonitor-ipc.c @@ -18,7 +18,7 @@ int fsmonitor_ipc__is_supported(void) return 0; } -const char *fsmonitor_ipc__get_path(void) +const char *fsmonitor_ipc__get_path(struct repository *r) { return NULL; } @@ -47,11 +47,9 @@ int fsmonitor_ipc__is_supported(void) return 1; } -GIT_PATH_FUNC(fsmonitor_ipc__get_path, "fsmonitor--daemon.ipc") - enum ipc_active_state fsmonitor_ipc__get_state(void) { - return ipc_get_active_state(fsmonitor_ipc__get_path()); + return ipc_get_active_state(fsmonitor_ipc__get_path(the_repository)); } static int spawn_daemon(void) @@ -81,8 +79,8 @@ int fsmonitor_ipc__send_query(const char *since_token, trace2_data_string("fsm_client", NULL, "query/command", tok); try_again: - state = ipc_client_try_connect(fsmonitor_ipc__get_path(), &options, - &connection); + state = ipc_client_try_connect(fsmonitor_ipc__get_path(the_repository), + &options, &connection); switch (state) { case IPC_STATE__LISTENING: @@ -117,13 +115,13 @@ try_again: case IPC_STATE__INVALID_PATH: ret = error(_("fsmonitor_ipc__send_query: invalid path '%s'"), - fsmonitor_ipc__get_path()); + fsmonitor_ipc__get_path(the_repository)); goto done; case IPC_STATE__OTHER_ERROR: default: ret = error(_("fsmonitor_ipc__send_query: unspecified error on '%s'"), - fsmonitor_ipc__get_path()); + fsmonitor_ipc__get_path(the_repository)); goto done; } @@ -149,8 +147,8 @@ int fsmonitor_ipc__send_command(const char *command, options.wait_if_busy = 1; options.wait_if_not_found = 0; - state = ipc_client_try_connect(fsmonitor_ipc__get_path(), &options, - &connection); + state = ipc_client_try_connect(fsmonitor_ipc__get_path(the_repository), + &options, &connection); if (state != IPC_STATE__LISTENING) { die(_("fsmonitor--daemon is not running")); return -1; diff --git a/fsmonitor-ipc.h b/fsmonitor-ipc.h index b6a7067c3af..8b489da762b 100644 --- a/fsmonitor-ipc.h +++ b/fsmonitor-ipc.h @@ -3,6 +3,8 @@ #include "simple-ipc.h" +struct repository; + /* * Returns true if built-in file system monitor daemon is defined * for this platform. @@ -16,7 +18,7 @@ int fsmonitor_ipc__is_supported(void); * * Returns NULL if the daemon is not supported on this platform. */ -const char *fsmonitor_ipc__get_path(void); +const char *fsmonitor_ipc__get_path(struct repository *r); /* * Try to determine whether there is a `git-fsmonitor--daemon` process From patchwork Fri Oct 14 21:45:35 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Eric DeCosta X-Patchwork-Id: 13007369 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id EFB66C4332F for ; Fri, 14 Oct 2022 21:46:11 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S229921AbiJNVqK (ORCPT ); Fri, 14 Oct 2022 17:46:10 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:36256 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S229726AbiJNVp4 (ORCPT ); Fri, 14 Oct 2022 17:45:56 -0400 Received: from mail-wr1-x42c.google.com (mail-wr1-x42c.google.com [IPv6:2a00:1450:4864:20::42c]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 27B7963843 for ; Fri, 14 Oct 2022 14:45:51 -0700 (PDT) Received: by mail-wr1-x42c.google.com with SMTP id u10so9578697wrq.2 for ; Fri, 14 Oct 2022 14:45:51 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20210112; 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=Wcm8qpzJovNixZr4FfekgJCx0i3cU8b+4aQdred0fgg=; b=Ey85Ze5eJeiO4QUAKWWiwg5jepBHJs6Pu0k+Ml7NLqw3UETCuEDB6nwAWVs7lFNWtC qNFJNQQwhi2Sul2SGOnTHZI5zNFvzMeadmvd0KUao8ODAcWYVRj22hmE7wknlsXvR4RK KFqbREuN5Oje3EsLLHXNwwBFykYpEWZhggBSngDU1PPlu/cWXdbyuvYnyGnCepjiec+1 +SPNjKTRvhTrNHJkXQK7X3RFwRHNDyPG9DBWmjykKxGoaSzdhTV+Nx4fDIe6kcjO5vEn +OGrYbeUO6/nGN27h7o1VI2ceNipBIQMRXDYNggNl5wMYoKX50lPRFvlgTqNDi304Xpj tSTA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; 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=Wcm8qpzJovNixZr4FfekgJCx0i3cU8b+4aQdred0fgg=; b=y4h95A2s4MaVh0WdbO4O8K1eHjA9g5cfpo0blxCs+9+38eCNnXeRNrkOYOGMhWFjKe OoqukIdZ8uvHhbdhXFvIMIEhayJuok5MZcLGUxM4+0gZg2OKtTOxjkUQxWdLC6AnZ3a9 QpTB1I9ry07cu5W2hp/yVhhZw6G2aGwC/z+8BFo5/IebII0PBJ1kuIL165aZm6XTdzC+ OTiUuCEk6LPXhocG7zY7BVtVzDYOocZ+LQmObBqJsDiJt5iUKMY04P6/ZrO0ZPh68CSg l3Q99EHab17sLAuEDIV3sfymXmTuVK8RhZuG7lEIwwUxY9sMvkVjychoB8c+owR1DU6L V03Q== X-Gm-Message-State: ACrzQf035Yj3B0cdMA41jh/yUp8Zvq1xgWuZCK6tEjC02W8RXVa+iKFG KS4g97gVAZd2Sv3YpvNrtSOIg0wLwAI= X-Google-Smtp-Source: AMsMyM72rQnKuvtoqB5kPeffd6w3LcsOAFd1eK46SKW/gAhyYcGr0r9k2K3VyCtbxZyBYLR+NwwDeA== X-Received: by 2002:a5d:4687:0:b0:22f:21c6:4b66 with SMTP id u7-20020a5d4687000000b0022f21c64b66mr4524900wrq.154.1665783950107; Fri, 14 Oct 2022 14:45:50 -0700 (PDT) Received: from [127.0.0.1] ([13.74.141.28]) by smtp.gmail.com with ESMTPSA id p8-20020a05600c358800b003a541d893desm3229186wmq.38.2022.10.14.14.45.49 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Fri, 14 Oct 2022 14:45:49 -0700 (PDT) Message-Id: <664259ed57a3b39af295ba87ce668cab4d364a9e.1665783944.git.gitgitgadget@gmail.com> In-Reply-To: References: Date: Fri, 14 Oct 2022 21:45:35 +0000 Subject: [PATCH v2 03/12] fsmonitor: avoid socket location check if using hook Fcc: Sent MIME-Version: 1.0 To: git@vger.kernel.org Cc: Eric Sunshine , =?utf-8?b?w4Z2YXIgQXJuZmrDtnI=?= =?utf-8?b?w7A=?= Bjarmason , Eric DeCosta , Eric DeCosta Precedence: bulk List-ID: X-Mailing-List: git@vger.kernel.org From: Eric DeCosta From: Eric DeCosta If monitoring is done via fsmonitor hook rather than IPC there is no need to check if the location of the Unix Domain socket (UDS) file is on a remote filesystem. Signed-off-by: Eric DeCosta --- compat/fsmonitor/fsm-settings-darwin.c | 10 ++++++---- compat/fsmonitor/fsm-settings-win32.c | 2 +- fsmonitor-settings.c | 8 ++++---- fsmonitor-settings.h | 2 +- 4 files changed, 12 insertions(+), 10 deletions(-) diff --git a/compat/fsmonitor/fsm-settings-darwin.c b/compat/fsmonitor/fsm-settings-darwin.c index 7241c4c22c9..6abbc7af3ab 100644 --- a/compat/fsmonitor/fsm-settings-darwin.c +++ b/compat/fsmonitor/fsm-settings-darwin.c @@ -48,13 +48,15 @@ static enum fsmonitor_reason check_uds_volume(struct repository *r) return FSMONITOR_REASON_OK; } -enum fsmonitor_reason fsm_os__incompatible(struct repository *r) +enum fsmonitor_reason fsm_os__incompatible(struct repository *r, int ipc) { enum fsmonitor_reason reason; - reason = check_uds_volume(r); - if (reason != FSMONITOR_REASON_OK) - return reason; + if (ipc) { + reason = check_uds_volume(r); + if (reason != FSMONITOR_REASON_OK) + return reason; + } return FSMONITOR_REASON_OK; } diff --git a/compat/fsmonitor/fsm-settings-win32.c b/compat/fsmonitor/fsm-settings-win32.c index d88b06ae610..a8af31b71de 100644 --- a/compat/fsmonitor/fsm-settings-win32.c +++ b/compat/fsmonitor/fsm-settings-win32.c @@ -25,7 +25,7 @@ static enum fsmonitor_reason check_vfs4git(struct repository *r) return FSMONITOR_REASON_OK; } -enum fsmonitor_reason fsm_os__incompatible(struct repository *r) +enum fsmonitor_reason fsm_os__incompatible(struct repository *r, int ipc) { enum fsmonitor_reason reason; diff --git a/fsmonitor-settings.c b/fsmonitor-settings.c index d288cbad479..531a1b6f956 100644 --- a/fsmonitor-settings.c +++ b/fsmonitor-settings.c @@ -60,7 +60,7 @@ static enum fsmonitor_reason check_remote(struct repository *r) } #endif -static enum fsmonitor_reason check_for_incompatible(struct repository *r) +static enum fsmonitor_reason check_for_incompatible(struct repository *r, int ipc) { if (!r->worktree) { /* @@ -77,7 +77,7 @@ static enum fsmonitor_reason check_for_incompatible(struct repository *r) reason = check_remote(r); if (reason != FSMONITOR_REASON_OK) return reason; - reason = fsm_os__incompatible(r); + reason = fsm_os__incompatible(r, ipc); if (reason != FSMONITOR_REASON_OK) return reason; } @@ -162,7 +162,7 @@ const char *fsm_settings__get_hook_path(struct repository *r) void fsm_settings__set_ipc(struct repository *r) { - enum fsmonitor_reason reason = check_for_incompatible(r); + enum fsmonitor_reason reason = check_for_incompatible(r, 1); if (reason != FSMONITOR_REASON_OK) { fsm_settings__set_incompatible(r, reason); @@ -185,7 +185,7 @@ void fsm_settings__set_ipc(struct repository *r) void fsm_settings__set_hook(struct repository *r, const char *path) { - enum fsmonitor_reason reason = check_for_incompatible(r); + enum fsmonitor_reason reason = check_for_incompatible(r, 0); if (reason != FSMONITOR_REASON_OK) { fsm_settings__set_incompatible(r, reason); diff --git a/fsmonitor-settings.h b/fsmonitor-settings.h index d9c2605197f..0721617b95a 100644 --- a/fsmonitor-settings.h +++ b/fsmonitor-settings.h @@ -48,7 +48,7 @@ struct fsmonitor_settings; * fsm_os__* routines should considered private to fsm_settings__ * routines. */ -enum fsmonitor_reason fsm_os__incompatible(struct repository *r); +enum fsmonitor_reason fsm_os__incompatible(struct repository *r, int ipc); #endif /* HAVE_FSMONITOR_OS_SETTINGS */ #endif /* FSMONITOR_SETTINGS_H */ From patchwork Fri Oct 14 21:45:36 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Eric DeCosta X-Patchwork-Id: 13007370 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id 8A71DC4332F for ; Fri, 14 Oct 2022 21:46:15 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S229977AbiJNVqM (ORCPT ); Fri, 14 Oct 2022 17:46:12 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:36330 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S229831AbiJNVp4 (ORCPT ); Fri, 14 Oct 2022 17:45:56 -0400 Received: from mail-wr1-x434.google.com (mail-wr1-x434.google.com [IPv6:2a00:1450:4864:20::434]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 7CB8363877 for ; Fri, 14 Oct 2022 14:45:53 -0700 (PDT) Received: by mail-wr1-x434.google.com with SMTP id bv10so9550443wrb.4 for ; Fri, 14 Oct 2022 14:45:53 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20210112; 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=ninSLfwK4PhPZWmT6P0TqP/TyJJ9jFipnqovDaaACaQ=; b=NVLSSxEsQqeOQ5+eDBL62xZzYEhjmsQ1tx5qdBYhznu7QsHb7NUC6sxVeBcywW31yN PBtlUaZVwG57U+zQIrj7AiPiJDhbJU504DHDZ3iAPIsclL8sZR4KG1CPc9vn7VWQe9FA imKkRPqJ4UASyxvQhAxRY/te4bPSMwPmol1HmuPpmh0fsaCOGf54g/PXdKdtG+pvV42A oku3F5uB+M0buZPfh8qEVsNDlSlmy9h6jDG5Di3MlrMbla8Lk4JPcCCb4dlp2PKEW6B/ aAfdhQCS0dgEUYHgm87KpH8SzNuvnvcvyNDoByKNFT/c+DAP5Slr0sX0YLEl5e7/Jzhe J8HQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; 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=ninSLfwK4PhPZWmT6P0TqP/TyJJ9jFipnqovDaaACaQ=; b=stUtr0cb5KGOdzetJJtln92UzSq61XMJyYVS7PKwjXQjKMkyYlW25WzjVu+YPhKVx/ uRAhA1OBABxkKVij4bfBINlra/K8uOZCK/zc+rS0Gvpb7va4KM8CyfybldDloDUtjBeZ o0tPu3K97Tn0/nXfeQVJxo1Y2Lar5lWXUOVuHmw2F3sM3PfONJ+2quaPuWvAJF6LA6MJ iWV1w82DcKoNT4Jo+NxfRG7PgMRprp+HM/mk+lexJqV9MEsbfLePOKY5WmwRu3JSLf68 yFpfLkpAUcv42/YjEZRnTy/vOrWltC7t09xE5vJViltBx65Uu588NMtV83nAK2pHjYwj qwaA== X-Gm-Message-State: ACrzQf2bTatxjZNgy/UO4lRkKZfK3hYwWOvxqfIUNy5C5H8Z9kopwd96 bLSg9r/Bz0K6Gm/3ucvtWnSFYNLq+Ic= X-Google-Smtp-Source: AMsMyM6mO2iMFHzoRRQXdHEmO6etiohJ5JAPmG5VrNcC1y+Psffa7DxYT7V8DR1yWIvZXE3ua8sryg== X-Received: by 2002:a05:6000:2cd:b0:22e:5cef:4332 with SMTP id o13-20020a05600002cd00b0022e5cef4332mr4533721wry.540.1665783950951; Fri, 14 Oct 2022 14:45:50 -0700 (PDT) Received: from [127.0.0.1] ([13.74.141.28]) by smtp.gmail.com with ESMTPSA id e9-20020adffc49000000b002206203ed3dsm2727027wrs.29.2022.10.14.14.45.50 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Fri, 14 Oct 2022 14:45:50 -0700 (PDT) Message-Id: In-Reply-To: References: Date: Fri, 14 Oct 2022 21:45:36 +0000 Subject: [PATCH v2 04/12] fsmonitor: deal with synthetic firmlinks on macOS Fcc: Sent MIME-Version: 1.0 To: git@vger.kernel.org Cc: Eric Sunshine , =?utf-8?b?w4Z2YXIgQXJuZmrDtnI=?= =?utf-8?b?w7A=?= Bjarmason , Eric DeCosta , Eric DeCosta Precedence: bulk List-ID: X-Mailing-List: git@vger.kernel.org From: Eric DeCosta From: Eric DeCosta Starting with macOS 10.15 (Catalina), Apple introduced a new feature called 'firmlinks' in order to separate the boot volume into two volumes, one read-only and one writable but still present them to the user as a single volume. Along with this change, Apple removed the ability to create symlinks in the root directory and replaced them with 'synthetic firmlinks'. See 'man synthetic.conf' When FSEevents reports the path of changed files, if the path involves a synthetic firmlink, the path is reported from the point of the synthetic firmlink and not the real path. For example: Real path: /System/Volumes/Data/network/working/directory/foo.txt Synthetic firmlink: /network -> /System/Volumes/Data/network FSEvents path: /network/working/directory/foo.txt This causes the FSEvents path to not match against the worktree directory. There are several ways in which synthetic firmlinks can be created: they can be defined in /etc/synthetic.conf, the automounter can create them, and there may be other means. Simply reading /etc/synthetic.conf is insufficient. No matter what process creates synthetic firmlinks, they all get created in the root directory. Therefore, in order to deal with synthetic firmlinks, the root directory is scanned and the first possible synthetic firmink that, when resolved, is a prefix of the worktree is used to map FSEvents paths to worktree paths. Signed-off-by: Eric DeCosta --- builtin/fsmonitor--daemon.c | 8 +++ compat/fsmonitor/fsm-listen-darwin.c | 14 +++- compat/fsmonitor/fsm-path-utils-darwin.c | 92 ++++++++++++++++++++++++ compat/fsmonitor/fsm-path-utils-win32.c | 17 +++++ fsmonitor--daemon.h | 3 + fsmonitor-path-utils.h | 36 +++++++++- 6 files changed, 167 insertions(+), 3 deletions(-) diff --git a/builtin/fsmonitor--daemon.c b/builtin/fsmonitor--daemon.c index 6e417846d8b..6f30a4f93a7 100644 --- a/builtin/fsmonitor--daemon.c +++ b/builtin/fsmonitor--daemon.c @@ -3,6 +3,7 @@ #include "parse-options.h" #include "fsmonitor.h" #include "fsmonitor-ipc.h" +#include "fsmonitor-path-utils.h" #include "compat/fsmonitor/fsm-health.h" #include "compat/fsmonitor/fsm-listen.h" #include "fsmonitor--daemon.h" @@ -1282,6 +1283,11 @@ static int fsmonitor_run_daemon(void) strbuf_addstr(&state.path_worktree_watch, absolute_path(get_git_work_tree())); state.nr_paths_watching = 1; + strbuf_init(&state.alias.alias, 0); + strbuf_init(&state.alias.points_to, 0); + if ((err = fsmonitor__get_alias(state.path_worktree_watch.buf, &state.alias))) + goto done; + /* * We create and delete cookie files somewhere inside the .git * directory to help us keep sync with the file system. If @@ -1391,6 +1397,8 @@ done: strbuf_release(&state.path_gitdir_watch); strbuf_release(&state.path_cookie_prefix); strbuf_release(&state.path_ipc); + strbuf_release(&state.alias.alias); + strbuf_release(&state.alias.points_to); return err; } diff --git a/compat/fsmonitor/fsm-listen-darwin.c b/compat/fsmonitor/fsm-listen-darwin.c index 8e208e8289e..daeee4e465c 100644 --- a/compat/fsmonitor/fsm-listen-darwin.c +++ b/compat/fsmonitor/fsm-listen-darwin.c @@ -26,6 +26,7 @@ #include "fsmonitor.h" #include "fsm-listen.h" #include "fsmonitor--daemon.h" +#include "fsmonitor-path-utils.h" struct fsm_listen_data { @@ -198,8 +199,9 @@ static void fsevent_callback(ConstFSEventStreamRef streamRef, struct string_list cookie_list = STRING_LIST_INIT_DUP; const char *path_k; const char *slash; - int k; + char *resolved = NULL; struct strbuf tmp = STRBUF_INIT; + int k; /* * Build a list of all filesystem changes into a private/local @@ -209,7 +211,12 @@ static void fsevent_callback(ConstFSEventStreamRef streamRef, /* * On Mac, we receive an array of absolute paths. */ - path_k = paths[k]; + free(resolved); + resolved = fsmonitor__resolve_alias(paths[k], &state->alias); + if (resolved) + path_k = resolved; + else + path_k = paths[k]; /* * If you want to debug FSEvents, log them to GIT_TRACE_FSMONITOR. @@ -238,6 +245,7 @@ static void fsevent_callback(ConstFSEventStreamRef streamRef, fsmonitor_force_resync(state); fsmonitor_batch__free_list(batch); string_list_clear(&cookie_list, 0); + batch = NULL; /* * We assume that any events that we received @@ -360,12 +368,14 @@ static void fsevent_callback(ConstFSEventStreamRef streamRef, } } + free(resolved); fsmonitor_publish(state, batch, &cookie_list); string_list_clear(&cookie_list, 0); strbuf_release(&tmp); return; force_shutdown: + free(resolved); fsmonitor_batch__free_list(batch); string_list_clear(&cookie_list, 0); diff --git a/compat/fsmonitor/fsm-path-utils-darwin.c b/compat/fsmonitor/fsm-path-utils-darwin.c index d46d7f13538..ce5a8febe09 100644 --- a/compat/fsmonitor/fsm-path-utils-darwin.c +++ b/compat/fsmonitor/fsm-path-utils-darwin.c @@ -1,5 +1,8 @@ #include "fsmonitor.h" #include "fsmonitor-path-utils.h" +#include +#include +#include #include #include @@ -41,3 +44,92 @@ int fsmonitor__is_fs_remote(const char *path) return fs.is_remote; } + +/* + * Scan the root directory for synthetic firmlinks that when resolved + * are a prefix of the path, stopping at the first one found. + * + * Some information about firmlinks and synthetic firmlinks: + * https://eclecticlight.co/2020/01/23/catalina-boot-volumes/ + * + * macOS no longer allows symlinks in the root directory; any link found + * there is therefore a synthetic firmlink. + * + * If this function gets called often, will want to cache all the firmlink + * information, but for now there is only one caller of this function. + * + * If there is more than one alias for the path, that is another + * matter altogether. + */ +int fsmonitor__get_alias(const char *path, struct alias_info *info) +{ + DIR *dir; + int retval = -1; + const char *const root = "/"; + struct stat st; + struct dirent *de; + struct strbuf alias; + struct strbuf points_to = STRBUF_INIT; + + dir = opendir(root); + if (!dir) + return error_errno(_("opendir('%s') failed"), root); + + strbuf_init(&alias, 256); + + while ((de = readdir(dir)) != NULL) { + strbuf_reset(&alias); + strbuf_addf(&alias, "%s%s", root, de->d_name); + + if (lstat(alias.buf, &st) < 0) { + error_errno(_("lstat('%s') failed"), alias.buf); + goto done; + } + + if (!S_ISLNK(st.st_mode)) + continue; + + if (strbuf_readlink(&points_to, alias.buf, st.st_size) < 0) { + error_errno(_("strbuf_readlink('%s') failed"), alias.buf); + goto done; + } + + if (!strncmp(points_to.buf, path, points_to.len) && + (path[points_to.len] == '/')) { + strbuf_addbuf(&info->alias, &alias); + strbuf_addbuf(&info->points_to, &points_to); + trace_printf_key(&trace_fsmonitor, + "Found alias for '%s' : '%s' -> '%s'", + path, info->alias.buf, info->points_to.buf); + retval = 0; + goto done; + } + } + retval = 0; /* no alias */ + +done: + strbuf_release(&alias); + strbuf_release(&points_to); + if (closedir(dir) < 0) + return error_errno(_("closedir('%s') failed"), root); + return retval; +} + +char *fsmonitor__resolve_alias(const char *path, + const struct alias_info *info) +{ + if (!info->alias.len) + return NULL; + + if ((!strncmp(info->alias.buf, path, info->alias.len)) + && path[info->alias.len] == '/') { + struct strbuf tmp = STRBUF_INIT; + const char *remainder = path + info->alias.len; + + strbuf_addbuf(&tmp, &info->points_to); + strbuf_add(&tmp, remainder, strlen(remainder)); + return strbuf_detach(&tmp, NULL); + } + + return NULL; +} diff --git a/compat/fsmonitor/fsm-path-utils-win32.c b/compat/fsmonitor/fsm-path-utils-win32.c index a90b8f7925b..0d95bbb416f 100644 --- a/compat/fsmonitor/fsm-path-utils-win32.c +++ b/compat/fsmonitor/fsm-path-utils-win32.c @@ -126,3 +126,20 @@ int fsmonitor__is_fs_remote(const char *path) return -1; return fs.is_remote; } + +/* + * 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/fsmonitor--daemon.h b/fsmonitor--daemon.h index 2102a5c9ff5..e24838f9a86 100644 --- a/fsmonitor--daemon.h +++ b/fsmonitor--daemon.h @@ -8,6 +8,7 @@ #include "run-command.h" #include "simple-ipc.h" #include "thread-utils.h" +#include "fsmonitor-path-utils.h" struct fsmonitor_batch; struct fsmonitor_token_data; @@ -43,6 +44,7 @@ struct fsmonitor_daemon_state { struct strbuf path_worktree_watch; struct strbuf path_gitdir_watch; + struct alias_info alias; int nr_paths_watching; struct fsmonitor_token_data *current_token_data; @@ -59,6 +61,7 @@ struct fsmonitor_daemon_state { struct ipc_server_data *ipc_server_data; struct strbuf path_ipc; + }; /* diff --git a/fsmonitor-path-utils.h b/fsmonitor-path-utils.h index 41edf5b934f..5bfdfb81c14 100644 --- a/fsmonitor-path-utils.h +++ b/fsmonitor-path-utils.h @@ -1,13 +1,21 @@ #ifndef FSM_PATH_UTILS_H #define FSM_PATH_UTILS_H +#include "strbuf.h" + +struct alias_info +{ + struct strbuf alias; + struct strbuf points_to; +}; + struct fs_info { int is_remote; char *typename; }; /* - * Get some basic filesystem informtion for the given path + * Get some basic filesystem information for the given path * * The caller owns the storage that is occupied by fs_info and * is responsible for releasing it. @@ -23,4 +31,30 @@ int fsmonitor__get_fs_info(const char *path, struct fs_info *fs_info); */ int fsmonitor__is_fs_remote(const char *path); +/* + * Get the alias in given path, if any. + * + * Sets alias to the first alias that matches any part of the path. + * + * If an alias is found, info.alias and info.points_to are set to the + * found mapping. + * + * Returns -1 on error, 0 otherwise. + * + * The caller owns the storage that is occupied by info.alias and + * info.points_to and is responsible for releasing it. + */ +int fsmonitor__get_alias(const char *path, struct alias_info *info); + +/* + * Resolve the path against the given alias. + * + * Returns the resolved path if there is one, NULL otherwise. + * + * The caller owns the storage that the returned string occupies and + * is responsible for releasing it. + */ +char *fsmonitor__resolve_alias(const char *path, + const struct alias_info *info); + #endif From patchwork Fri Oct 14 21:45:37 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Eric DeCosta X-Patchwork-Id: 13007368 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id B363AC433FE for ; Fri, 14 Oct 2022 21:46:09 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S229907AbiJNVqH (ORCPT ); Fri, 14 Oct 2022 17:46:07 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:36258 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S229742AbiJNVp4 (ORCPT ); Fri, 14 Oct 2022 17:45:56 -0400 Received: from mail-wr1-x434.google.com (mail-wr1-x434.google.com [IPv6:2a00:1450:4864:20::434]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id E87CD6715F for ; Fri, 14 Oct 2022 14:45:54 -0700 (PDT) Received: by mail-wr1-x434.google.com with SMTP id bu30so9544070wrb.8 for ; Fri, 14 Oct 2022 14:45:54 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20210112; 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=bGtbzq+IH2Ws4ChKWDCxefvQxY0NorgXVM+ffiB3Qi0=; b=F1az9wlsLSSnPp6N2T7Ijlv41Fxb9qOHwu33S3GqJWkVd5Xi7r7zO1p2OgjZbHn1Gs Vy1KQdovPKzelRFsIU89+x+Z/gXHSpAkuQSiGyTI1JvsPc9ykmBQkGwd1BSxCkn6xWn/ GJeUfnsM3VojZPt4QManGxLh3FZyjcxDrM0aNc0jVBDPeizEYNPLD1xuNx1dYW86snYM 6bByuA+Tjr0dAMSAkrXnXbFLRzPUY0uyMAm/qaLNivFkkjRPRZQTZ4N3nxYsTr3pWLm8 RqJm8Pfu2Qxgss8/PIDarLJMFSUemBZdK6BuqJNcdFx/n5V2sLON0wYXC/auw0IsF9ar MLfA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; 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=bGtbzq+IH2Ws4ChKWDCxefvQxY0NorgXVM+ffiB3Qi0=; b=QCovL6YTb+vMKLb4tsd7MjHKQIr7d2VS/Pj9z3qLaKw4erEs0qxk8Ko4NaZxjIdy0o moIlBpmDR6PtNJ89NEKhMi1MVvzfAuZwJu3O6AkK3r74rD4lY5QAwGGM0Wwu2GAdSDpG MbpPAJhyFAoqJCl5rMk3GbLwYgg78X4lLinm683e7eUQd7pDcTFU5uIJ1abEE4U8caWo 1p7PiNzJz8FvKaJKAHZFEwJFibXJxi/gjJQdATBFQmalOLywZGQUgI2v4tIRY2INLjpU C9sNbTGCqBrzacJIWRV9fktVpiapm6T/A5+XaEG89aGhoB0ZvU8e5i51/WN2c+uYemym sPlw== X-Gm-Message-State: ACrzQf1De8xBTiqFT18rqfVzLZmOe9pN60XOJgXdvRGYruoMHq/er/1P GTYWjBUiwadBh0yuAjluP8gZw5gneNw= X-Google-Smtp-Source: AMsMyM7utUc366AOv+gpY7fm+LuYG5YyKUL+83YHd9xKb9RX21/FSCC3YKXy434u/oSGwYEk0U30OQ== X-Received: by 2002:a5d:4a4e:0:b0:22e:64a6:7a52 with SMTP id v14-20020a5d4a4e000000b0022e64a67a52mr4625309wrs.333.1665783952253; Fri, 14 Oct 2022 14:45:52 -0700 (PDT) Received: from [127.0.0.1] ([13.74.141.28]) by smtp.gmail.com with ESMTPSA id e38-20020a5d5966000000b002252884cc91sm2736985wri.43.2022.10.14.14.45.51 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Fri, 14 Oct 2022 14:45:51 -0700 (PDT) Message-Id: In-Reply-To: References: Date: Fri, 14 Oct 2022 21:45:37 +0000 Subject: [PATCH v2 05/12] fsmonitor: check for compatability before communicating with fsmonitor Fcc: Sent MIME-Version: 1.0 To: git@vger.kernel.org Cc: Eric Sunshine , =?utf-8?b?w4Z2YXIgQXJuZmrDtnI=?= =?utf-8?b?w7A=?= Bjarmason , Eric DeCosta , Eric DeCosta Precedence: bulk List-ID: X-Mailing-List: git@vger.kernel.org From: Eric DeCosta From: Eric DeCosta If fsmonitor is not in a compatible state, warn with an appropriate message. Signed-off-by: Eric DeCosta --- fsmonitor-settings.c | 10 +++++++--- fsmonitor-settings.h | 2 +- fsmonitor.c | 7 +++++++ 3 files changed, 15 insertions(+), 4 deletions(-) diff --git a/fsmonitor-settings.c b/fsmonitor-settings.c index 531a1b6f956..ee63a97dc51 100644 --- a/fsmonitor-settings.c +++ b/fsmonitor-settings.c @@ -1,6 +1,7 @@ #include "cache.h" #include "config.h" #include "repository.h" +#include "fsmonitor-ipc.h" #include "fsmonitor-settings.h" #include "fsmonitor-path-utils.h" @@ -242,10 +243,11 @@ enum fsmonitor_reason fsm_settings__get_reason(struct repository *r) return r->settings.fsmonitor->reason; } -char *fsm_settings__get_incompatible_msg(const struct repository *r, +char *fsm_settings__get_incompatible_msg(struct repository *r, enum fsmonitor_reason reason) { struct strbuf msg = STRBUF_INIT; + const char *socket_dir; switch (reason) { case FSMONITOR_REASON_UNTESTED: @@ -281,9 +283,11 @@ char *fsm_settings__get_incompatible_msg(const struct repository *r, goto done; case FSMONITOR_REASON_NOSOCKETS: + socket_dir = dirname((char *)fsmonitor_ipc__get_path(r)); strbuf_addf(&msg, - _("repository '%s' is incompatible with fsmonitor due to lack of Unix sockets"), - r->worktree); + _("socket directory '%s' is incompatible with fsmonitor due" + " to lack of Unix sockets support"), + socket_dir); goto done; } diff --git a/fsmonitor-settings.h b/fsmonitor-settings.h index 0721617b95a..ab02e3995ee 100644 --- a/fsmonitor-settings.h +++ b/fsmonitor-settings.h @@ -33,7 +33,7 @@ enum fsmonitor_mode fsm_settings__get_mode(struct repository *r); const char *fsm_settings__get_hook_path(struct repository *r); enum fsmonitor_reason fsm_settings__get_reason(struct repository *r); -char *fsm_settings__get_incompatible_msg(const struct repository *r, +char *fsm_settings__get_incompatible_msg(struct repository *r, enum fsmonitor_reason reason); struct fsmonitor_settings; diff --git a/fsmonitor.c b/fsmonitor.c index 57d6a483bee..540736b39fd 100644 --- a/fsmonitor.c +++ b/fsmonitor.c @@ -295,6 +295,7 @@ static int fsmonitor_force_update_threshold = 100; void refresh_fsmonitor(struct index_state *istate) { + static int warn_once = 0; struct strbuf query_result = STRBUF_INIT; int query_success = 0, hook_version = -1; size_t bol = 0; /* beginning of line */ @@ -305,6 +306,12 @@ void refresh_fsmonitor(struct index_state *istate) int is_trivial = 0; struct repository *r = istate->repo ? istate->repo : the_repository; enum fsmonitor_mode fsm_mode = fsm_settings__get_mode(r); + enum fsmonitor_reason reason = fsm_settings__get_reason(r); + + if (!warn_once && reason > FSMONITOR_REASON_OK) { + warn_once = 1; + warning("%s", fsm_settings__get_incompatible_msg(r, reason)); + } if (fsm_mode <= FSMONITOR_MODE_DISABLED || istate->fsmonitor_has_run_once) From patchwork Fri Oct 14 21:45:38 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Eric DeCosta X-Patchwork-Id: 13007371 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id B8CC0C433FE for ; Fri, 14 Oct 2022 21:46:18 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S229590AbiJNVqR (ORCPT ); Fri, 14 Oct 2022 17:46:17 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:36330 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S229661AbiJNVp6 (ORCPT ); Fri, 14 Oct 2022 17:45:58 -0400 Received: from mail-wr1-x42d.google.com (mail-wr1-x42d.google.com [IPv6:2a00:1450:4864:20::42d]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 013F35FDC2 for ; Fri, 14 Oct 2022 14:45:55 -0700 (PDT) Received: by mail-wr1-x42d.google.com with SMTP id bu30so9544118wrb.8 for ; Fri, 14 Oct 2022 14:45:55 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20210112; 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=NZZ/jRI252DzMeVq+3yot+76+uTRZX0nJIDrWhlOFuE=; b=Od2uBJ6FRJy+1AZAouOF+wM/gZVGb2DeXZPbq4+/RbDcVWbrEd+PfeqLV7d2vONC8B pHbKE9cSw9wA5rXgB6c1mr+twuJGQfnqg3AxQr4n9voYxt+UT9zKZH0GB5Hb9ubPC2Gv e8ecZyRIt5aflvWDPdDiPq2sMx1gYhIN9NsarTPPN09pUK8hM29KqBG14c6NNxYD3Aby PNMxYsJL3kVznHb5fh8fs4uvjAuUmrL+2F19tYTZ0jmmcRkx2Kd1OmcQnXaoSkbSwpvv cOKIUXoic+ipLkTDDXoXuy58+OrUvcX8Y8oB1yiQhEie22muPPQm/a34b0/Oh5wDbJdZ DSEw== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; 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=NZZ/jRI252DzMeVq+3yot+76+uTRZX0nJIDrWhlOFuE=; b=DvBI31HLwnQL/ymZCmDAtWKzrXWlZ8s9/X1XKc48/PM6aWRllpIV5nnR5q8F8n9ss9 p8YXUGQylPXpo4hluRj7e0wmTftCwMnQOUFqpJmZPDzah7i/lWi5G9nIW6gDIVxZcXda 6dXGjxXEbj7e2embvOGGhkJINJTB5Gko8m0pKP+/tItF02wjxStIjsHyp7s1wEEbvnZQ GORpyAzyUcrAs2p03p5bVZ3uTrRKb4UtkiC5TDFmjF7a4FIxw8IhLiRyb6Y1tG2wFUSF oj0lTEIlSToJ4jgeqbjmztD0CRkAw4bQ2U244t3nWc2LSYyrarcJAboeyUL0NeBbfjwh Rj2A== X-Gm-Message-State: ACrzQf11WUPuANl2miAVA0COh+X5xTjGPC1xkWFnk4ehNfaB97LGva/Q AgPoqlRj0NBwNExzxOMapkRWMRumaJA= X-Google-Smtp-Source: AMsMyM739lY0EOSTPVlG8+WYE9h2ErH+KIEgXIT8h46Iic+ELCpfoWxCaUa59mxHxak6wBZVtkooqQ== X-Received: by 2002:a05:6000:1861:b0:232:2471:d405 with SMTP id d1-20020a056000186100b002322471d405mr4658469wri.130.1665783953804; Fri, 14 Oct 2022 14:45:53 -0700 (PDT) Received: from [127.0.0.1] ([13.74.141.28]) by smtp.gmail.com with ESMTPSA id z6-20020a1cf406000000b003c6deb5c1edsm2982925wma.45.2022.10.14.14.45.53 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Fri, 14 Oct 2022 14:45:53 -0700 (PDT) Message-Id: <9c552239b57fb181189d3c6bb84a648a272cba62.1665783945.git.gitgitgadget@gmail.com> In-Reply-To: References: Date: Fri, 14 Oct 2022 21:45:38 +0000 Subject: [PATCH v2 06/12] fsmonitor: add documentation for allowRemote and socketDir options Fcc: Sent MIME-Version: 1.0 To: git@vger.kernel.org Cc: Eric Sunshine , =?utf-8?b?w4Z2YXIgQXJuZmrDtnI=?= =?utf-8?b?w7A=?= Bjarmason , Eric DeCosta , Eric DeCosta Precedence: bulk List-ID: X-Mailing-List: git@vger.kernel.org From: Eric DeCosta From: Eric DeCosta Add documentation for 'fsmonitor.allowRemote' and 'fsmonitor.socketDir'. Call-out experimental nature of 'fsmonitor.allowRemote' and limited filesystem support for 'fsmonitor.socketDir'. Signed-off-by: Eric DeCosta --- Documentation/config.txt | 2 ++ Documentation/config/fsmonitor--daemon.txt | 11 +++++++ Documentation/git-fsmonitor--daemon.txt | 37 ++++++++++++++++++++-- 3 files changed, 47 insertions(+), 3 deletions(-) create mode 100644 Documentation/config/fsmonitor--daemon.txt diff --git a/Documentation/config.txt b/Documentation/config.txt index 5b5b9765699..1e205831656 100644 --- a/Documentation/config.txt +++ b/Documentation/config.txt @@ -423,6 +423,8 @@ include::config/filter.txt[] include::config/fsck.txt[] +include::config/fsmonitor--daemon.txt[] + include::config/gc.txt[] include::config/gitcvs.txt[] diff --git a/Documentation/config/fsmonitor--daemon.txt b/Documentation/config/fsmonitor--daemon.txt new file mode 100644 index 00000000000..c225c6c9e74 --- /dev/null +++ b/Documentation/config/fsmonitor--daemon.txt @@ -0,0 +1,11 @@ +fsmonitor.allowRemote:: + By default, the fsmonitor daemon refuses to work against network-mounted + repositories. Setting `fsmonitor.allowRemote` to `true` overrides this + behavior. Only respected when `core.fsmonitor` is set to `true`. + +fsmonitor.socketDir:: + This Mac OS-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` + is set to `true`. diff --git a/Documentation/git-fsmonitor--daemon.txt b/Documentation/git-fsmonitor--daemon.txt index cc142fb8612..8238eadb0e1 100644 --- a/Documentation/git-fsmonitor--daemon.txt +++ b/Documentation/git-fsmonitor--daemon.txt @@ -3,7 +3,7 @@ git-fsmonitor{litdd}daemon(1) NAME ---- -git-fsmonitor--daemon - A Built-in File System Monitor +git-fsmonitor--daemon - A Built-in Filesystem Monitor SYNOPSIS -------- @@ -17,7 +17,7 @@ DESCRIPTION ----------- A daemon to watch the working directory for file and directory -changes using platform-specific file system notification facilities. +changes using platform-specific filesystem notification facilities. This daemon communicates directly with commands like `git status` using the link:technical/api-simple-ipc.html[simple IPC] interface @@ -63,13 +63,44 @@ CAVEATS ------- The fsmonitor daemon does not currently know about submodules and does -not know to filter out file system events that happen within a +not know to filter out filesystem events that happen within a submodule. If fsmonitor daemon is watching a super repo and a file is modified within the working directory of a submodule, it will report the change (as happening against the super repo). However, the client will properly ignore these extra events, so performance may be affected but it will not cause an incorrect result. +By default, the fsmonitor daemon refuses to work against network-mounted +repositories; this may be overridden by setting `fsmonitor.allowRemote` to +`true`. Note, however, that the fsmonitor daemon is not guaranteed to work +correctly with all network-mounted repositories and such use is considered +experimental. + +On 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. + +By default, the socket is created in the `.git` directory, however, if the +`.git` directory is on a network-mounted filesystem, it will be 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 +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. + +CONFIGURATION +------------- + +include::includes/cmd-config-section-all.txt[] + +include::config/fsmonitor--daemon.txt[] + GIT --- Part of the linkgit:git[1] suite From patchwork Fri Oct 14 21:45:39 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Eric DeCosta X-Patchwork-Id: 13007372 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id 95A98C4332F for ; Fri, 14 Oct 2022 21:46:22 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S229739AbiJNVqU (ORCPT ); Fri, 14 Oct 2022 17:46:20 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:36444 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S229740AbiJNVp7 (ORCPT ); Fri, 14 Oct 2022 17:45:59 -0400 Received: from mail-wr1-x433.google.com (mail-wr1-x433.google.com [IPv6:2a00:1450:4864:20::433]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 021F16386E for ; Fri, 14 Oct 2022 14:45:56 -0700 (PDT) Received: by mail-wr1-x433.google.com with SMTP id u10so9578935wrq.2 for ; Fri, 14 Oct 2022 14:45:56 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20210112; 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=LckyfNVoYdL232Tax7sXGyYKzM8LJlSJVTs/P20Tba4=; b=nw08t7XAO+upe7zeHsli/Ql4LBQ7sK+QD48URIkPHYV+2urcp0MIyoHcIzdzSOj45N 8K1UoAYbuD19JQ5VHzgS7Ig0omTprKxAgE1n6IG1oe0WjMIGh10ArMN6ekOr1QnLu3Oo BwLVMDpdyR83lYai1E1yljrigNxkGhZw+pVrBlBj3fq8Pu2Ly/USDaQdX1WiC45mCE5W hTw9dy87ksGhAu2O6qSjkIucbQG9IGMnoMoCoYeGyHWhNKw/U4I7g4oovKxy/9OzKGy9 awHWUffnI7NRNltMhMP27Hzo7JovG+Kgq69Qcnp3mxxVdTy9O5eN6d9wzTBP9J+unnoT giqw== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; 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=LckyfNVoYdL232Tax7sXGyYKzM8LJlSJVTs/P20Tba4=; b=ulwSBR1xQnsfXeWuy8PBTUug0cEkZVV65mT3ESL+WJx9qubAjtZiCdC0YEEOOGTGHM Xvtu/e+b7EAEAwxd4KjUJ+XoCYYHkuegBn75I2rmuyL4+GFzm2EKN39zNxQNAtLETDnH YDcUacKSGZql4/zhHknZg/FWC20scoDeYuan+RoRLl7nvyNYFsb35okFLGjlrQue2d4b rWWI9XmKjsZIq0KP9R5Pu0aoEK9xVdiuXmTcRrdA+qbXkwSrTSYqvZO9hditiQUJ4eIW UC/cvA/ChxOlLV7wE8sRpZ2HJj2hunc2e0KC6+JVc2ENNVhz2xa06awYZY/SaEB7x1ng humw== X-Gm-Message-State: ACrzQf0hefXbOo2UyFNSjyYI9ikl4XWw8l2tmfGkRGXLEUC3Nm5PZuNS JqLVgqFqvM94mJo2QWQXVwFpaZ9ZcMI= X-Google-Smtp-Source: AMsMyM6tuXJAUhCYpWnys+zpbu/MdeGL3PBwYKSokFKgLcqrQ85tNnrRnWNmUa/XI6KOI5AmDsB0dw== X-Received: by 2002:a5d:52cb:0:b0:21a:3cc5:f5f4 with SMTP id r11-20020a5d52cb000000b0021a3cc5f5f4mr4779555wrv.367.1665783954727; Fri, 14 Oct 2022 14:45:54 -0700 (PDT) Received: from [127.0.0.1] ([13.74.141.28]) by smtp.gmail.com with ESMTPSA id c25-20020a7bc019000000b003c6b874a0dfsm3922084wmb.14.2022.10.14.14.45.54 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Fri, 14 Oct 2022 14:45:54 -0700 (PDT) Message-Id: <295beb89ab10f001724fb64fa55944d05ee29fc7.1665783945.git.gitgitgadget@gmail.com> In-Reply-To: References: Date: Fri, 14 Oct 2022 21:45:39 +0000 Subject: [PATCH v2 07/12] fsmonitor: prepare to share code between Mac OS and Linux Fcc: Sent MIME-Version: 1.0 To: git@vger.kernel.org Cc: Eric Sunshine , =?utf-8?b?w4Z2YXIgQXJuZmrDtnI=?= =?utf-8?b?w7A=?= Bjarmason , Eric DeCosta , Eric DeCosta Precedence: bulk List-ID: X-Mailing-List: git@vger.kernel.org From: Eric DeCosta From: Eric DeCosta Linux and Mac OS can share some of the code originally developed for Mac OS. Minor update to compat/fsmonitor/fsm-ipc-unix.c to make it cross-platform. Mac OS and Linux can share fsm-ipc-unix.c Both platforms can also share compat/fsmonitor/fsm-settings-unix.c but we will leave room for future, platform-specific checks by having the platform- specific implementations call into fsm-settings-unix. Signed-off-by: Eric DeCosta --- Makefile | 9 ++- compat/fsmonitor/fsm-health-linux.c | 24 +++++++ .../{fsm-ipc-darwin.c => fsm-ipc-unix.c} | 8 +-- compat/fsmonitor/fsm-settings-darwin.c | 57 +---------------- compat/fsmonitor/fsm-settings-linux.c | 11 ++++ compat/fsmonitor/fsm-settings-unix.c | 62 +++++++++++++++++++ compat/fsmonitor/fsm-settings-unix.h | 11 ++++ config.mak.uname | 1 + contrib/buildsystems/CMakeLists.txt | 17 ++++- 9 files changed, 138 insertions(+), 62 deletions(-) create mode 100644 compat/fsmonitor/fsm-health-linux.c rename compat/fsmonitor/{fsm-ipc-darwin.c => fsm-ipc-unix.c} (89%) create mode 100644 compat/fsmonitor/fsm-settings-linux.c create mode 100644 compat/fsmonitor/fsm-settings-unix.c create mode 100644 compat/fsmonitor/fsm-settings-unix.h diff --git a/Makefile b/Makefile index 9553d590824..bbbde00ce49 100644 --- a/Makefile +++ b/Makefile @@ -2036,13 +2036,20 @@ endif ifdef FSMONITOR_DAEMON_BACKEND COMPAT_CFLAGS += -DHAVE_FSMONITOR_DAEMON_BACKEND + ifdef FSMONITOR_DAEMON_COMMON + COMPAT_OBJS += compat/fsmonitor/fsm-ipc-$(FSMONITOR_DAEMON_COMMON).o + else + COMPAT_OBJS += compat/fsmonitor/fsm-ipc-$(FSMONITOR_DAEMON_BACKEND).o + endif COMPAT_OBJS += compat/fsmonitor/fsm-listen-$(FSMONITOR_DAEMON_BACKEND).o COMPAT_OBJS += compat/fsmonitor/fsm-health-$(FSMONITOR_DAEMON_BACKEND).o - COMPAT_OBJS += compat/fsmonitor/fsm-ipc-$(FSMONITOR_DAEMON_BACKEND).o endif ifdef FSMONITOR_OS_SETTINGS COMPAT_CFLAGS += -DHAVE_FSMONITOR_OS_SETTINGS + ifdef FSMONITOR_DAEMON_COMMON + COMPAT_OBJS += compat/fsmonitor/fsm-settings-$(FSMONITOR_DAEMON_COMMON).o + endif COMPAT_OBJS += compat/fsmonitor/fsm-settings-$(FSMONITOR_OS_SETTINGS).o COMPAT_OBJS += compat/fsmonitor/fsm-path-utils-$(FSMONITOR_OS_SETTINGS).o endif 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-unix.c similarity index 89% rename from compat/fsmonitor/fsm-ipc-darwin.c rename to compat/fsmonitor/fsm-ipc-unix.c index ce843d63348..3ba3b9e17ed 100644 --- a/compat/fsmonitor/fsm-ipc-darwin.c +++ b/compat/fsmonitor/fsm-ipc-unix.c @@ -10,7 +10,7 @@ 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; - SHA_CTX sha1ctx; + git_SHA_CTX sha1ctx; char *sock_dir = NULL; struct strbuf ipc_file = STRBUF_INIT; unsigned char hash[SHA_DIGEST_LENGTH]; @@ -28,9 +28,9 @@ const char *fsmonitor_ipc__get_path(struct repository *r) return ipc_path; } - SHA1_Init(&sha1ctx); - SHA1_Update(&sha1ctx, r->worktree, strlen(r->worktree)); - SHA1_Final(hash, &sha1ctx); + 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); diff --git a/compat/fsmonitor/fsm-settings-darwin.c b/compat/fsmonitor/fsm-settings-darwin.c index 6abbc7af3ab..2f5c6a88bf0 100644 --- a/compat/fsmonitor/fsm-settings-darwin.c +++ b/compat/fsmonitor/fsm-settings-darwin.c @@ -1,62 +1,11 @@ #include "config.h" #include "fsmonitor.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; -} +#include "fsmonitor-settings.h" +#include "fsm-settings-unix.h" 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; + return fsm_os__incompatible_unix(r, ipc); } diff --git a/compat/fsmonitor/fsm-settings-linux.c b/compat/fsmonitor/fsm-settings-linux.c new file mode 100644 index 00000000000..2f5c6a88bf0 --- /dev/null +++ b/compat/fsmonitor/fsm-settings-linux.c @@ -0,0 +1,11 @@ +#include "config.h" +#include "fsmonitor.h" +#include "fsmonitor-ipc.h" +#include "fsmonitor-path-utils.h" +#include "fsmonitor-settings.h" +#include "fsm-settings-unix.h" + +enum fsmonitor_reason fsm_os__incompatible(struct repository *r, int ipc) +{ + return fsm_os__incompatible_unix(r, ipc); +} diff --git a/compat/fsmonitor/fsm-settings-unix.c b/compat/fsmonitor/fsm-settings-unix.c new file mode 100644 index 00000000000..6b43e26720e --- /dev/null +++ b/compat/fsmonitor/fsm-settings-unix.c @@ -0,0 +1,62 @@ +#include "config.h" +#include "fsmonitor.h" +#include "fsmonitor-ipc.h" +#include "fsmonitor-path-utils.h" +#include "fsm-settings-unix.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_unix(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; +} diff --git a/compat/fsmonitor/fsm-settings-unix.h b/compat/fsmonitor/fsm-settings-unix.h new file mode 100644 index 00000000000..8a62971190b --- /dev/null +++ b/compat/fsmonitor/fsm-settings-unix.h @@ -0,0 +1,11 @@ +#ifndef FSM_SETTINGS_UNIX_H +#define FSM_SETTINGS_UNIX_H + +#ifdef HAVE_FSMONITOR_OS_SETTINGS +/* + * Check for compatibility on unix-like systems (e.g. Darwin and Linux) + */ +enum fsmonitor_reason fsm_os__incompatible_unix(struct repository *r, int ipc); +#endif /* HAVE_FSMONITOR_OS_SETTINGS */ + +#endif /* FSM_SETTINGS_UNIX_H */ diff --git a/config.mak.uname b/config.mak.uname index d63629fe807..9f716cfba81 100644 --- a/config.mak.uname +++ b/config.mak.uname @@ -165,6 +165,7 @@ ifeq ($(uname_S),Darwin) ifndef NO_UNIX_SOCKETS FSMONITOR_DAEMON_BACKEND = darwin FSMONITOR_OS_SETTINGS = darwin + FSMONITOR_DAEMON_COMMON = unix endif endif diff --git a/contrib/buildsystems/CMakeLists.txt b/contrib/buildsystems/CMakeLists.txt index 787738e6fa3..4c6e84da346 100644 --- a/contrib/buildsystems/CMakeLists.txt +++ b/contrib/buildsystems/CMakeLists.txt @@ -304,7 +304,17 @@ 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-ipc-unix.c) + list(APPEND compat_SOURCES compat/fsmonitor/fsm-health-linux.c) + list(APPEND compat_SOURCES compat/fsmonitor/fsm-listen-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-unix.c) + 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) @@ -315,12 +325,13 @@ if(SUPPORTS_SIMPLE_IPC) list(APPEND compat_SOURCES compat/fsmonitor/fsm-settings-win32.c) elseif(CMAKE_SYSTEM_NAME STREQUAL "Darwin") add_compile_definitions(HAVE_FSMONITOR_DAEMON_BACKEND) - list(APPEND compat_SOURCES compat/fsmonitor/fsm-listen-darwin.c) + list(APPEND compat_SOURCES compat/fsmonitor/fsm-ipc-unix.c) list(APPEND compat_SOURCES compat/fsmonitor/fsm-health-darwin.c) - list(APPEND compat_SOURCES compat/fsmonitor/fsm-ipc-darwin.c) + list(APPEND compat_SOURCES compat/fsmonitor/fsm-listen-darwin.c) list(APPEND compat_SOURCES compat/fsmonitor/fsm-path-utils-darwin.c) add_compile_definitions(HAVE_FSMONITOR_OS_SETTINGS) + list(APPEND compat_SOURCES compat/fsmonitor/fsm-settings-unix.c) list(APPEND compat_SOURCES compat/fsmonitor/fsm-settings-darwin.c) endif() endif() From patchwork Fri Oct 14 21:45:40 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Eric DeCosta X-Patchwork-Id: 13007376 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id A68BCC4332F for ; Fri, 14 Oct 2022 21:46:47 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S229995AbiJNVqp (ORCPT ); Fri, 14 Oct 2022 17:46:45 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:39822 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S229744AbiJNVqg (ORCPT ); Fri, 14 Oct 2022 17:46:36 -0400 Received: from mail-wm1-x332.google.com (mail-wm1-x332.google.com [IPv6:2a00:1450:4864:20::332]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 439CC4B4B6 for ; Fri, 14 Oct 2022 14:45:58 -0700 (PDT) Received: by mail-wm1-x332.google.com with SMTP id v130-20020a1cac88000000b003bcde03bd44so6540989wme.5 for ; Fri, 14 Oct 2022 14:45:58 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20210112; 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=JzsaAR0X8JQprc/ENUUg7TQxj4tsxrHAeMaKjdaTLuE=; b=qdHCeLiSUquabkOHe/wd+7avFaSo1xJuD//r72lAozdLtCBmDfH7lXCunn8IB4Fpmk fDdWZ/DUgObXIrMLqN0Doo8Lf/jJhfREnPIAzZzyEqQYI0WdIxuLS0EkIXtBtukKypES 2U01RXLT5feaIZSfumVBtdRk4rz4cpIDPXng9T9f/DD13oc9VHAYSce/fLU5DQu0ZbTr ZXczla/JiRtFyNWKOMprCcsN41a+e83Hv1pQK/JvAd/+Jq9M+o8X+7meKfUnklaWDmHY grM4x40v5h2ttOCnSWtqkoTHMbMxqFMuBBrIzl4FPs12CM271/42bV4bMuwGYB2ZNLd2 6l4A== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; 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=JzsaAR0X8JQprc/ENUUg7TQxj4tsxrHAeMaKjdaTLuE=; b=QyJpTtp6DYTJiB6AxLxtLNKZVbC87rZ3cYxIY/xuUj+eOYAOuAkqeGZ/drECmOb7fq T7kzka4zkQ39+EfD+BLKznVBqXhFd8NiqBmaqL+E01Jrz+37JyhzKoVul79w/Mig2Qpj rZG1BLr6dnfEf1bn8hxYNqQOtUfXz7bXe1kv/cXC1Xaf9aKZBkRjt7ZTURjNPr8RPDaW QymzOrfTa8KCEZpofoodUDbkW74knA4v7G6OM2KnCcleUFDWMqRkI1Sno6P0C6YEuv/u +4k/YmMyPlyMJxekkPBMEWFGGdG9klfB0f3nCqzN95gAIA/L5W/sCRXihi5Bo6apglu/ ljxA== X-Gm-Message-State: ACrzQf2m94+ZCWR+oUxneU3a12zL9dqCFNuaByIEmcJzj6kdLn9iIE0+ mXUHUK9hhyP0+Zz7w198WJJFFdMtABk= X-Google-Smtp-Source: AMsMyM675EajXu+oaZKhpYJxOuPYCkY0O30MfZjm2gx+1hbGr6ETigY+8/MmFeHTmYiPR/Y3cLqsYA== X-Received: by 2002:a05:600c:3b21:b0:3c6:172:9c5a with SMTP id m33-20020a05600c3b2100b003c601729c5amr5091967wms.129.1665783956077; Fri, 14 Oct 2022 14:45:56 -0700 (PDT) Received: from [127.0.0.1] ([13.74.141.28]) by smtp.gmail.com with ESMTPSA id g8-20020a7bc4c8000000b003c0d504a92csm7728903wmk.22.2022.10.14.14.45.54 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Fri, 14 Oct 2022 14:45:55 -0700 (PDT) Message-Id: <7d7ef78728f890db68166b3b5b6b7dd33f20e62c.1665783945.git.gitgitgadget@gmail.com> In-Reply-To: References: Date: Fri, 14 Oct 2022 21:45:40 +0000 Subject: [PATCH v2 08/12] fsmonitor: determine if filesystem is local or remote Fcc: Sent MIME-Version: 1.0 To: git@vger.kernel.org Cc: Eric Sunshine , =?utf-8?b?w4Z2YXIgQXJuZmrDtnI=?= =?utf-8?b?w7A=?= Bjarmason , Eric DeCosta , Eric DeCosta Precedence: bulk List-ID: X-Mailing-List: git@vger.kernel.org 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 --- compat/fsmonitor/fsm-path-utils-linux.c | 169 ++++++++++++++++++++++++ 1 file changed, 169 insertions(+) create mode 100644 compat/fsmonitor/fsm-path-utils-linux.c diff --git a/compat/fsmonitor/fsm-path-utils-linux.c b/compat/fsmonitor/fsm-path-utils-linux.c new file mode 100644 index 00000000000..039f044b670 --- /dev/null +++ b/compat/fsmonitor/fsm-path-utils-linux.c @@ -0,0 +1,169 @@ +#include "fsmonitor.h" +#include "fsmonitor-path-utils.h" +#include +#include +#include +#include + +/* + * https://github.com/coreutils/gnulib/blob/master/lib/mountlist.c + */ +#ifndef ME_REMOTE +/* A file system is "remote" if its Fs_name contains a ':' + or if (it is of type (smbfs or cifs) and its Fs_name starts with '//') + or if it is of any other of the listed types + or Fs_name is equal to "-hosts" (used by autofs to mount remote fs). + "VM" file systems like prl_fs or vboxsf are not considered remote here. */ +# define ME_REMOTE(Fs_name, Fs_type) \ + (strchr (Fs_name, ':') != NULL \ + || ((Fs_name)[0] == '/' \ + && (Fs_name)[1] == '/' \ + && (strcmp (Fs_type, "smbfs") == 0 \ + || strcmp (Fs_type, "smb3") == 0 \ + || strcmp (Fs_type, "cifs") == 0)) \ + || strcmp (Fs_type, "acfs") == 0 \ + || strcmp (Fs_type, "afs") == 0 \ + || strcmp (Fs_type, "coda") == 0 \ + || strcmp (Fs_type, "auristorfs") == 0 \ + || strcmp (Fs_type, "fhgfs") == 0 \ + || strcmp (Fs_type, "gpfs") == 0 \ + || strcmp (Fs_type, "ibrix") == 0 \ + || strcmp (Fs_type, "ocfs2") == 0 \ + || strcmp (Fs_type, "vxfs") == 0 \ + || strcmp ("-hosts", Fs_name) == 0) +#endif + +static int find_mount(const char *path, const struct statvfs *fs, + struct mntent *ent) +{ + const char *const mounts = "/proc/mounts"; + const char *rp = real_pathdup(path, 1); + struct mntent *ment = NULL; + struct statvfs mntfs; + FILE *fp; + int found = 0; + int dlen, plen, flen = 0; + + ent->mnt_fsname = NULL; + ent->mnt_dir = NULL; + ent->mnt_type = NULL; + + fp = setmntent(mounts, "r"); + if (!fp) { + error_errno(_("setmntent('%s') failed"), mounts); + return -1; + } + + plen = strlen(rp); + + /* read all the mount information and compare to path */ + while ((ment = getmntent(fp)) != NULL) { + if (statvfs(ment->mnt_dir, &mntfs)) { + switch (errno) { + case EPERM: + case ESRCH: + case EACCES: + continue; + default: + error_errno(_("statvfs('%s') failed"), ment->mnt_dir); + endmntent(fp); + return -1; + } + } + + /* 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; + /* + * root is always a potential match; otherwise look for + * directory prefix + */ + if ((dlen == 1 && ment->mnt_dir[0] == '/') || + (dlen > flen && (!rp[dlen] || rp[dlen] == '/'))) { + flen = dlen; + /* + * 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(). + */ + found = 1; + free(ent->mnt_fsname); + free(ent->mnt_dir); + free(ent->mnt_type); + ent->mnt_fsname = xstrdup(ment->mnt_fsname); + ent->mnt_dir = xstrdup(ment->mnt_dir); + ent->mnt_type = xstrdup(ment->mnt_type); + } + } + } + endmntent(fp); + + if (!found) + return -1; + + return 0; +} + +int fsmonitor__get_fs_info(const char *path, struct fs_info *fs_info) +{ + struct mntent ment; + struct statvfs fs; + + if (statvfs(path, &fs)) + return error_errno(_("statvfs('%s') failed"), path); + + + if (find_mount(path, &fs, &ment) < 0) { + free(ment.mnt_fsname); + free(ment.mnt_dir); + free(ment.mnt_type); + return -1; + } + + trace_printf_key(&trace_fsmonitor, + "statvfs('%s') [flags 0x%08lx] '%s' '%s'", + path, fs.f_flag, ment.mnt_type, ment.mnt_fsname); + + fs_info->is_remote = ME_REMOTE(ment.mnt_fsname, ment.mnt_type); + fs_info->typename = ment.mnt_fsname; + free(ment.mnt_dir); + free(ment.mnt_type); + + trace_printf_key(&trace_fsmonitor, + "'%s' is_remote: %d", + path, fs_info->is_remote); + return 0; +} + +int fsmonitor__is_fs_remote(const char *path) +{ + struct fs_info fs; + + if (fsmonitor__get_fs_info(path, &fs)) + return -1; + + free(fs.typename); + + return fs.is_remote; +} + +/* + * 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; +} From patchwork Fri Oct 14 21:45:41 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Eric DeCosta X-Patchwork-Id: 13007375 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id 6A002C43217 for ; Fri, 14 Oct 2022 21:46:45 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S229945AbiJNVqn (ORCPT ); Fri, 14 Oct 2022 17:46:43 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:36954 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S229740AbiJNVqg (ORCPT ); Fri, 14 Oct 2022 17:46:36 -0400 Received: from mail-wr1-x42b.google.com (mail-wr1-x42b.google.com [IPv6:2a00:1450:4864:20::42b]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 437E94A123 for ; Fri, 14 Oct 2022 14:45:59 -0700 (PDT) Received: by mail-wr1-x42b.google.com with SMTP id j16so9563976wrh.5 for ; Fri, 14 Oct 2022 14:45:59 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20210112; 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=Wx2fwswNmQdyPPAOyzEDKAYLTyC9b8TXZP60zg27Jmc=; b=igwbd6sOHIlml2IDyB7PQN26JkofMi5G2JfL/7bRVZNyW7Z0Gq6hxkS7LHHG+vjOSl E70JwEahVlM3iO8OfHIzlQMeakyYRk55OrQAZBFo48uHFLs2quqPajTgeuy37HgMohyX 4qfXKtwQPt4VjIwDT5957jEmxAuE0CQST7O+opssxrneQlF1/E6fsMTU+R+pAuvd85Hv GLXgVCyBYc0aFTDdkUe9G2h9kCEsWQyOHEzo7wJL11a1FFUQ7yzCcssfUpoLDJnDFsyV 3yBF/OqZ8If6oW6MDqjDjTu37wtTc72pYRwwIbdtFoJgRETYXTZAPRCBXupE63tC2Hdr CLng== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; 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=Wx2fwswNmQdyPPAOyzEDKAYLTyC9b8TXZP60zg27Jmc=; b=jHjjlyLjkk3CZyb1pcC1r8QbbNe47Tyj9iXLbwwX4ZyZ80iXRJkskMKE6kdXMTDAI2 wVQaOko/czyDUml6GO1pCuRJmUUuUqH47xefuWLuZsnYCUJfNrEbCxj4NH1aOpTU4aNt iKC6J620Zfn4136MqgNEB2txWS0MNbRMhMtW5hmUFXDTPX8l5o0uCZZ/yHkd/KKcrq5G 9KI8n2JA6wiv9U8D5HuhsiHD6ZMg/KcSImuo/FAgffUIt1Cu7QulWRjJfMhmR/j4ube3 RjHxufYp3dgFu/owanmGi315YN9zVzxWBfm/KfZADSOBKVCUIIYH3pMzS2JvHy3xAIHY Hs6A== X-Gm-Message-State: ACrzQf1xvfcqzl3t9lWH2GECHCQttEH7PQOdIYp8ST6qH8KPWyJJne0t JFzhtGdSplt/xdm+NRx9oPcDQ++52pw= X-Google-Smtp-Source: AMsMyM6X/BX+zkMe7hRFYrgZkK0zEXyYrbPFnKIE8G2kg6YfRFEIV0U/rTM8uF9JTgllplhJcKTIWw== X-Received: by 2002:a5d:5942:0:b0:225:7425:4e39 with SMTP id e2-20020a5d5942000000b0022574254e39mr4472063wri.566.1665783957000; Fri, 14 Oct 2022 14:45:57 -0700 (PDT) Received: from [127.0.0.1] ([13.74.141.28]) by smtp.gmail.com with ESMTPSA id e9-20020a5d5009000000b0022e3d7c9887sm2653961wrt.101.2022.10.14.14.45.56 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Fri, 14 Oct 2022 14:45:56 -0700 (PDT) Message-Id: <4f9c5358475867af75acd865505884f99801ca17.1665783945.git.gitgitgadget@gmail.com> In-Reply-To: References: Date: Fri, 14 Oct 2022 21:45:41 +0000 Subject: [PATCH v2 09/12] fsmonitor: implement filesystem change listener for Linux Fcc: Sent MIME-Version: 1.0 To: git@vger.kernel.org Cc: Eric Sunshine , =?utf-8?b?w4Z2YXIgQXJuZmrDtnI=?= =?utf-8?b?w7A=?= Bjarmason , Eric DeCosta , Eric DeCosta Precedence: bulk List-ID: X-Mailing-List: git@vger.kernel.org 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 | 664 ++++++++++++++++++++++++++++ 1 file changed, 664 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..0ac131a9497 --- /dev/null +++ b/compat/fsmonitor/fsm-listen-linux.c @@ -0,0 +1,664 @@ +#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 fsm_listen_data *data) +{ + DIR *dir; + 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, data)) + goto failed; + if (register_inotify(current.buf, data)) + goto failed; + } + } + 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, data)) + 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, data)) + 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 (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->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; + } + 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_add(&path, event->name, strlen(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 Fri Oct 14 21:45:42 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Eric DeCosta X-Patchwork-Id: 13007373 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id 96D0EC433FE for ; Fri, 14 Oct 2022 21:46:41 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S230023AbiJNVqk (ORCPT ); Fri, 14 Oct 2022 17:46:40 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:37866 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S229975AbiJNVqM (ORCPT ); Fri, 14 Oct 2022 17:46:12 -0400 Received: from mail-wm1-x336.google.com (mail-wm1-x336.google.com [IPv6:2a00:1450:4864:20::336]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 578FC94101 for ; Fri, 14 Oct 2022 14:45:59 -0700 (PDT) Received: by mail-wm1-x336.google.com with SMTP id v130-20020a1cac88000000b003bcde03bd44so6541085wme.5 for ; Fri, 14 Oct 2022 14:45:59 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20210112; 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=qeIJAFWxEsrz1YUq4p3vMlNyGEFg/vGTl2fx3fBK7IA=; b=idA8gMYns9xSnVs8jYZNh8nfTpbRGRWvkx6yJtgwWxZnZ/uqD07NT5h/ELzfHbtOru 2OLiSFTLnF9Lo0Pwb7Fpp+bVOnsk5eSwrqxU7zszTx8Q2/QFgpvz0wVW5TOBa+FE40K6 Dku+2VJb14KMJ41uatc/xJ7VOoh3lEgXKY7hY72Dde50FLhm/QZEOGtWOYr3ih5Ru4hy 7Sqp4VXaao57jFAEv5BImWRmSemcZRwzx6TddK83BFVAvfcH20hbxLjhOYs6954xUJz3 +uxI8g/UbePwVg76xEK0WCfkpCDH++Dm35ozJ9PDja/bj/lzN/lj49Te6OHiFBDx04QH zM+g== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; 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=qeIJAFWxEsrz1YUq4p3vMlNyGEFg/vGTl2fx3fBK7IA=; b=N1lJyQY56/Y/PwTdGmVQBQetRnRxdGrgKzOqoD14UURSL+gBpEOBy8mguuXYIfJuJA tbMeCayGLsH7hXpF4v+QTVcvq0+mdv6gccKsrY37gRtLMGS8wDnXtQMJ5Z7h9/rqQBf5 S7euPMvv0eDmJ7RbiZ5v45/+NKWdvroSiEfAwBTfxpVinhmfdsCsogQkvQeimCD2ZvUB jT27kKWdRIZwBYIT61hHvI+cIKHDaJ3Xr1jMb0AqLKtk6U1cCZ34AvGSYsdWZ5G1hxDC SYYdD2tnD7ksQ74wQjfANWMKZMY9Dh8EFHtVnH9o0X4QVsFQlMjdlsXhFIvwQBiHF/gt M4MA== X-Gm-Message-State: ACrzQf2OiXQjP9SdG4eDSFRW6/rNo/P9EtAeTCJTH4mqsqKiJzW3siNP p6jAYYV8qz62sVbvwhZy+oO7m3nQJLw= X-Google-Smtp-Source: AMsMyM5Z/Jt1wm0aZDvfeYjbcA0/8DsLID507qtouqRAa55BXCz4Mlw1BDDNP5Ngrj86DZ7wZvU3rA== X-Received: by 2002:a05:600c:490f:b0:3c6:2c21:97f6 with SMTP id f15-20020a05600c490f00b003c62c2197f6mr11581665wmp.177.1665783958000; Fri, 14 Oct 2022 14:45:58 -0700 (PDT) Received: from [127.0.0.1] ([13.74.141.28]) by smtp.gmail.com with ESMTPSA id b7-20020adfe307000000b0022cbf4cda62sm3435173wrj.27.2022.10.14.14.45.57 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Fri, 14 Oct 2022 14:45:57 -0700 (PDT) Message-Id: <07650ecd27b91d49a83427187a846c18424f9ab4.1665783945.git.gitgitgadget@gmail.com> In-Reply-To: References: Date: Fri, 14 Oct 2022 21:45:42 +0000 Subject: [PATCH v2 10/12] fsmonitor: enable fsmonitor for Linux Fcc: Sent MIME-Version: 1.0 To: git@vger.kernel.org Cc: Eric Sunshine , =?utf-8?b?w4Z2YXIgQXJuZmrDtnI=?= =?utf-8?b?w7A=?= Bjarmason , Eric DeCosta , Eric DeCosta Precedence: bulk List-ID: X-Mailing-List: git@vger.kernel.org From: Eric DeCosta From: Eric DeCosta Update build to enable fsmonitor for Linux. Signed-off-by: Eric DeCosta --- config.mak.uname | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/config.mak.uname b/config.mak.uname index 9f716cfba81..d8889f8570a 100644 --- a/config.mak.uname +++ b/config.mak.uname @@ -68,6 +68,15 @@ ifeq ($(uname_S),Linux) ifneq ($(findstring .el7.,$(uname_R)),) BASIC_CFLAGS += -std=c99 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 + FSMONITOR_DAEMON_COMMON = unix + endif + endif endif ifeq ($(uname_S),GNU/kFreeBSD) HAVE_ALLOCA_H = YesPlease From patchwork Fri Oct 14 21:45:43 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Eric DeCosta X-Patchwork-Id: 13007374 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id 7D58CC4332F for ; Fri, 14 Oct 2022 21:46:43 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S229655AbiJNVqm (ORCPT ); Fri, 14 Oct 2022 17:46:42 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:39798 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S229635AbiJNVqg (ORCPT ); Fri, 14 Oct 2022 17:46:36 -0400 Received: from mail-wr1-x432.google.com (mail-wr1-x432.google.com [IPv6:2a00:1450:4864:20::432]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 580D19AC30 for ; Fri, 14 Oct 2022 14:45:59 -0700 (PDT) Received: by mail-wr1-x432.google.com with SMTP id j7so9571679wrr.3 for ; Fri, 14 Oct 2022 14:45:59 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20210112; 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=ibpglQJIFgP9j6z8KDbCVZ6yZW73BVoxIeYg4BhjscE=; b=YL1F9OoxXsjG1+q8THV8o9N/a7K2PRceTDZLHkAjMtp6YT8wIAfchmNjgLmb6gMq8E EQ72ZZHf1x5GpYHtJaDl7lZmWIkWBEIy4q3XGjpd6rBCta9tSFE9WKemBIqINeb+qvDI 5IXdvrSwSxPLunZP0hrct9HdJnSj+U5jOJi4rwidvI81n9o81ONC5PzLwwKKeWD2DVu1 dld1a2eEqsrNkKdie98z0OpVqhOG8CCtW44h+GgxFQl2zraKAhYIzPrUXrMA5V8vpeTc 4Tomwcwn+QiEVFjWTnYV+DsKuM0PBor6myVRfQ7/MNw9MSsjuZqykFYrGK7odC4V9h7G pFzg== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; 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=ibpglQJIFgP9j6z8KDbCVZ6yZW73BVoxIeYg4BhjscE=; b=hfwC6JDMKejRWyn1yE9yAHGI3Quv9kpFLm1ihyOjCw+6155NUkPioHYfmPMoS8MMg2 pzl4q+Ls7dk7oFA5daCBxziKXi3sb6ZWptwxBppWQpCNfZ06oHQ0FRD2fpl7ZXjeCtQF RFO/ju2Snk49d64oCEcKcmp8EFSiAyEzLbMRlYim0oAr6wRwyEr9FMAcHiiU++AFmoQk k2TKiFfEiZJlEphkiWGymAun3mSNo1oUeXQiMudTMq+kIzDHhkoKKrPI2hIMj5RJR5XW PKVKqCdu522rMzhjLPk+1GzDE3PQuxhMJNHe90r8VR9c3NjgRvAgRlmicAw3ACMwqqcG Tz6g== X-Gm-Message-State: ACrzQf10rMhQPLtZN1MF2FqT6i7vNWW9uvD2Eqi/9le4wtsD1lQzT0Tg hxsLSyUNKnkFD+9ES7+/cI7GOT3NBQ8= X-Google-Smtp-Source: AMsMyM6xV7p0PreDSDgoZJEwVCSaYnDowJaOcPddwxhdvKuXrsIOBcq3Y/THZgRhtk+FLGM0YdL5AA== X-Received: by 2002:a5d:5988:0:b0:22e:58fe:28cf with SMTP id n8-20020a5d5988000000b0022e58fe28cfmr4605355wri.440.1665783959125; Fri, 14 Oct 2022 14:45:59 -0700 (PDT) Received: from [127.0.0.1] ([13.74.141.28]) by smtp.gmail.com with ESMTPSA id a3-20020a05600c224300b003b49bd61b19sm7684368wmm.15.2022.10.14.14.45.58 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Fri, 14 Oct 2022 14:45:58 -0700 (PDT) Message-Id: <6682938fff8a3bc7c0c4b08fdfd20effc4b2fc66.1665783945.git.gitgitgadget@gmail.com> In-Reply-To: References: Date: Fri, 14 Oct 2022 21:45:43 +0000 Subject: [PATCH v2 11/12] fsmonitor: test updates Fcc: Sent MIME-Version: 1.0 To: git@vger.kernel.org Cc: Eric Sunshine , =?utf-8?b?w4Z2YXIgQXJuZmrDtnI=?= =?utf-8?b?w7A=?= Bjarmason , Eric DeCosta , Eric DeCosta Precedence: bulk List-ID: X-Mailing-List: git@vger.kernel.org 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 | 72 +++++++++++++++++++++++++++++------- 1 file changed, 58 insertions(+), 14 deletions(-) diff --git a/t/t7527-builtin-fsmonitor.sh b/t/t7527-builtin-fsmonitor.sh index 1746d30cf6a..d27bd3662a7 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,32 @@ 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 + return 0 + fi + last=$nsz + fi + sleep 1 + k=$(( $k + 1 )) + done && + return 0 +} + # Is a Trace2 data event present with the given catetory and key? # We do not care what the value is. # @@ -137,7 +163,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 +398,10 @@ create_files () { echo 3 >dir2/new } +rename_directory () { + mv dirtorename dirrenamed +} + rename_files () { mv rename renamed && mv dir1/rename dir1/renamed && @@ -427,10 +456,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 +473,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 +489,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 +505,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,10 +524,12 @@ 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 ' @@ -500,10 +539,12 @@ test_expect_success 'file changes to directory' ' 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 +554,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 +604,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 +775,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 && @@ -814,8 +858,7 @@ my_match_and_clean () { } 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 && @@ -883,7 +926,8 @@ have_t2_error_event () { } test_expect_success "stray submodule super-prefix warning" ' - test_when_finished "rm -rf super; \ + test_when_finished "git -C super/dir_1/dir_2/sub fsmonitor--daemon stop; \ + rm -rf super; \ rm -rf sub; \ rm super-sub.trace" && From patchwork Fri Oct 14 21:45:44 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Eric DeCosta X-Patchwork-Id: 13007377 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id E9DAFC4332F for ; Fri, 14 Oct 2022 21:46:49 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S229751AbiJNVqs (ORCPT ); Fri, 14 Oct 2022 17:46:48 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:39858 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S229988AbiJNVqh (ORCPT ); Fri, 14 Oct 2022 17:46:37 -0400 Received: from mail-wr1-x42c.google.com (mail-wr1-x42c.google.com [IPv6:2a00:1450:4864:20::42c]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id CC9D44D4C8 for ; Fri, 14 Oct 2022 14:46:01 -0700 (PDT) Received: by mail-wr1-x42c.google.com with SMTP id a10so9508066wrm.12 for ; Fri, 14 Oct 2022 14:46:01 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20210112; 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=Oi1JhA2Y49B3vsv8LyQZ/nUzDuStw5WBLGMA8BZqLVA=; b=naZ4cg7tt4tUhw1MoOR/WMrw4TbLg6ZdwMVGI31B6LN1dkbB5Cgcfa8JEkgCyWEs6v qR7x3y5TqsrplKCO5GKWWPiCubss5HO9r4NnAhYoDBccyRnxdujWulx/q+M1tnUply0u c71Nao/qX+U/200f71mS90urDY/KLrT61IY7A6YZhlB1WihrcPvRVmxXsjQEFKVnCNEz byb72SKIVR2KsOm+YwLsVHs8VGWUyL/c/aaysl4+xMtDYUvyHbLq5WqZR+28rxq8+w9q hJEeHA+e7D8tDPuKD4j8ED2riVn3p0zgdIsGh3q0apyeHT/r02r4kid8ByPTdiSTQL9G mH0w== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; 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=Oi1JhA2Y49B3vsv8LyQZ/nUzDuStw5WBLGMA8BZqLVA=; b=2Msj8V0pR6w0bHHBYZuQf/Uw8F/W1Yd1zM2V10QMthnptSuoRbEatXPv7v3u3b5OwJ d4bV7n1+5v51m9ohOD5CD3vjkSFa9o6Q9yLrHZAk8O/qvIKwsXuFkeQjo1Xr5k09zDcz 1bk+hZGoWwUjqJtG2J+NLCMqoUJY3OUFtgLXMf1nhyhhJc3jK6p6UGG/JC7UJn8Sxfip vERNTNkpak8qJ9KZtynvK5X4u9lrZ3hUuWh3QL8n5LmA5w817/EvYuu/xmgg8Mz/1/9Q J7dsWBBvMscr/BvRsIAvDozpdJ+5IHci23/kN/9IhsJN9XhafVd8/pTW27O4rdsOvFGy /msA== X-Gm-Message-State: ACrzQf1WVqzaWn8teLCEs6penlym6PWp8MLo31ThQhX/iWXQkhmENC/R U4LNm0lyOoJ/++CCEJ6mA2PC+JZ4T2A= X-Google-Smtp-Source: AMsMyM73LkIOHMBaxNfXEqlWC7R3aoLAuLtF73zAGQHlpk70McifgrQiXAcTAkh3xuyNIwkK+r0B4w== X-Received: by 2002:a5d:64e3:0:b0:231:86ac:978a with SMTP id g3-20020a5d64e3000000b0023186ac978amr4382653wri.283.1665783960138; Fri, 14 Oct 2022 14:46:00 -0700 (PDT) Received: from [127.0.0.1] ([13.74.141.28]) by smtp.gmail.com with ESMTPSA id a13-20020a05600c348d00b003c6c76b43a1sm3050228wmq.13.2022.10.14.14.45.59 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Fri, 14 Oct 2022 14:45:59 -0700 (PDT) Message-Id: In-Reply-To: References: Date: Fri, 14 Oct 2022 21:45:44 +0000 Subject: [PATCH v2 12/12] fsmonitor: update doc for Linux Fcc: Sent MIME-Version: 1.0 To: git@vger.kernel.org Cc: Eric Sunshine , =?utf-8?b?w4Z2YXIgQXJuZmrDtnI=?= =?utf-8?b?w7A=?= Bjarmason , Eric DeCosta , Eric DeCosta Precedence: bulk List-ID: X-Mailing-List: git@vger.kernel.org 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 | 24 ++++++++++++++-------- 2 files changed, 18 insertions(+), 10 deletions(-) diff --git a/Documentation/config/fsmonitor--daemon.txt b/Documentation/config/fsmonitor--daemon.txt index c225c6c9e74..2cafb040d96 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 8238eadb0e1..c2b08229c74 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 and 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 be 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 +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 -------------