From: "Eric DeCosta via GitGitGadget" <gitgitgadget@gmail.com>
To: git@vger.kernel.org
Cc: "Eric Sunshine [ ]" <sunshine@sunshineco.com>,
"Ævar Arnfjörð Bjarmason [ ]" <avarab@gmail.com>,
"Glen Choo [ ]" <chooglen@google.com>,
"Johannes Schindelin [ ]" <Johannes.Schindelin@gmx.de>,
"Taylor Blau [ ]" <me@ttaylorr.com>, marzi <m.ispare63@gmail.com>,
"Eric DeCosta" <edecosta@mathworks.com>
Subject: [PATCH 2/7] fsmonitor: determine if filesystem is local or remote
Date: Thu, 15 Feb 2024 10:29:33 +0000 [thread overview]
Message-ID: <d26de10866662a5bcd16d562cd1063dedd21cf02.1707992978.git.gitgitgadget@gmail.com> (raw)
In-Reply-To: <pull.1667.git.git.1707992978.gitgitgadget@gmail.com>
From: Eric DeCosta <edecosta@mathworks.com>
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 <edecosta@mathworks.com>
---
Makefile | 4 +
compat/fsmonitor/fsm-path-utils-linux.c | 195 ++++++++++++++++++++++++
compat/fsmonitor/fsm-path-utils-linux.h | 91 +++++++++++
config.mak.uname | 11 ++
4 files changed, 301 insertions(+)
create mode 100644 compat/fsmonitor/fsm-path-utils-linux.c
create mode 100644 compat/fsmonitor/fsm-path-utils-linux.h
diff --git a/Makefile b/Makefile
index 78e874099d9..0f36a0fd83a 100644
--- a/Makefile
+++ b/Makefile
@@ -2088,6 +2088,10 @@ ifdef HAVE_CLOCK_GETTIME
BASIC_CFLAGS += -DHAVE_CLOCK_GETTIME
endif
+ifdef HAVE_LINUX_MAGIC_H
+ BASIC_CFLAGS += -DHAVE_LINUX_MAGIC_H
+endif
+
ifdef HAVE_CLOCK_MONOTONIC
BASIC_CFLAGS += -DHAVE_CLOCK_MONOTONIC
endif
diff --git a/compat/fsmonitor/fsm-path-utils-linux.c b/compat/fsmonitor/fsm-path-utils-linux.c
new file mode 100644
index 00000000000..c21d1349532
--- /dev/null
+++ b/compat/fsmonitor/fsm-path-utils-linux.c
@@ -0,0 +1,195 @@
+#include "git-compat-util.h"
+#include "abspath.h"
+#include "fsmonitor.h"
+#include "fsmonitor-path-utils.h"
+#include "fsm-path-utils-linux.h"
+#include <errno.h>
+#include <mntent.h>
+#include <sys/mount.h>
+#include <sys/vfs.h>
+#include <sys/statvfs.h>
+
+static int is_remote_fs(const char *path)
+{
+ struct statfs fs;
+
+ if (statfs(path, &fs))
+ return error_errno(_("statfs('%s') failed"), path);
+
+ switch (fs.f_type) {
+ case ACFS_SUPER_MAGIC:
+ case AFS_SUPER_MAGIC:
+ case CEPH_SUPER_MAGIC:
+ case CIFS_SUPER_MAGIC:
+ case CODA_SUPER_MAGIC:
+ case FHGFS_SUPER_MAGIC:
+ case GFS_SUPER_MAGIC:
+ case GPFS_SUPER_MAGIC:
+ case IBRIX_SUPER_MAGIC:
+ case KAFS_SUPER_MAGIC:
+ case LUSTRE_SUPER_MAGIC:
+ case NCP_SUPER_MAGIC:
+ case NFS_SUPER_MAGIC:
+ case NFSD_SUPER_MAGIC:
+ case OCFS2_SUPER_MAGIC:
+ case PANFS_SUPER_MAGIC:
+ case SMB_SUPER_MAGIC:
+ case SMB2_SUPER_MAGIC:
+ case SNFS_SUPER_MAGIC:
+ case VMHGFS_SUPER_MAGIC:
+ case VXFS_SUPER_MAGIC:
+ return 1;
+ default:
+ return 0;
+ }
+}
+
+static int find_mount(const char *path, const struct statvfs *fs,
+ struct mntent *entry)
+{
+ const char *const mounts = "/proc/mounts";
+ char *rp = real_pathdup(path, 1);
+ struct mntent *ment = NULL;
+ struct statvfs mntfs;
+ FILE *fp;
+ int found = 0;
+ int ret = 0;
+ size_t dlen, plen, flen = 0;
+
+ entry->mnt_fsname = NULL;
+ entry->mnt_dir = NULL;
+ entry->mnt_type = NULL;
+
+ fp = setmntent(mounts, "r");
+ if (!fp) {
+ free(rp);
+ return error_errno(_("setmntent('%s') failed"), mounts);
+ }
+
+ plen = strlen(rp);
+
+ /* read all the mount information and compare to path */
+ while ((ment = getmntent(fp))) {
+ if (statvfs(ment->mnt_dir, &mntfs)) {
+ switch (errno) {
+ case EPERM:
+ case ESRCH:
+ case EACCES:
+ continue;
+ default:
+ error_errno(_("statvfs('%s') failed"), ment->mnt_dir);
+ ret = -1;
+ goto done;
+ }
+ }
+
+ /* is mount on the same filesystem and is a prefix of the path */
+ if ((fs->f_fsid == mntfs.f_fsid) &&
+ !strncmp(ment->mnt_dir, rp, strlen(ment->mnt_dir))) {
+ dlen = strlen(ment->mnt_dir);
+ if (dlen > plen)
+ continue;
+ /*
+ * look for the longest prefix (including root)
+ */
+ if (dlen > flen &&
+ ((dlen == 1 && ment->mnt_dir[0] == '/') ||
+ (!rp[dlen] || rp[dlen] == '/'))) {
+ flen = dlen;
+ found = 1;
+
+ /*
+ * https://man7.org/linux/man-pages/man3/getmntent.3.html
+ *
+ * The pointer points to a static area of memory which is
+ * overwritten by subsequent calls to getmntent().
+ */
+ free(entry->mnt_fsname);
+ free(entry->mnt_dir);
+ free(entry->mnt_type);
+ entry->mnt_fsname = xstrdup(ment->mnt_fsname);
+ entry->mnt_dir = xstrdup(ment->mnt_dir);
+ entry->mnt_type = xstrdup(ment->mnt_type);
+ }
+ }
+ }
+
+done:
+ free(rp);
+ endmntent(fp);
+
+ if (!found)
+ return -1;
+
+ return ret;
+}
+
+int fsmonitor__get_fs_info(const char *path, struct fs_info *fs_info)
+{
+ int ret = 0;
+ struct mntent entry;
+ struct statvfs fs;
+
+ fs_info->is_remote = -1;
+ fs_info->typename = NULL;
+
+ if (statvfs(path, &fs))
+ return error_errno(_("statvfs('%s') failed"), path);
+
+ if (find_mount(path, &fs, &entry) < 0) {
+ ret = -1;
+ goto done;
+ }
+
+ trace_printf_key(&trace_fsmonitor,
+ "statvfs('%s') [flags 0x%08lx] '%s' '%s'",
+ path, fs.f_flag, entry.mnt_type, entry.mnt_fsname);
+
+ fs_info->is_remote = is_remote_fs(entry.mnt_dir);
+ fs_info->typename = xstrdup(entry.mnt_fsname);
+
+ if (fs_info->is_remote < 0)
+ ret = -1;
+
+ trace_printf_key(&trace_fsmonitor,
+ "'%s' is_remote: %d",
+ path, fs_info->is_remote);
+
+done:
+ free(entry.mnt_fsname);
+ free(entry.mnt_dir);
+ free(entry.mnt_type);
+ return ret;
+}
+
+int fsmonitor__is_fs_remote(const char *path)
+{
+ int ret = 0;
+ struct fs_info fs;
+
+ if (fsmonitor__get_fs_info(path, &fs))
+ ret = -1;
+ else
+ ret = fs.is_remote;
+
+ free(fs.typename);
+
+ return ret;
+}
+
+/*
+ * No-op for now.
+ */
+int fsmonitor__get_alias(const char *path, struct alias_info *info)
+{
+ return 0;
+}
+
+/*
+ * No-op for now.
+ */
+char *fsmonitor__resolve_alias(const char *path,
+ const struct alias_info *info)
+{
+ return NULL;
+}
diff --git a/compat/fsmonitor/fsm-path-utils-linux.h b/compat/fsmonitor/fsm-path-utils-linux.h
new file mode 100644
index 00000000000..49bdb3c4728
--- /dev/null
+++ b/compat/fsmonitor/fsm-path-utils-linux.h
@@ -0,0 +1,91 @@
+#ifndef FSM_PATH_UTILS_LINUX_H
+#define FSM_PATH_UTILS_LINUX_H
+#endif
+
+#ifdef HAVE_LINUX_MAGIC_H
+#include <linux/magic.h>
+#endif
+
+#ifndef ACFS_SUPER_MAGIC
+#define ACFS_SUPER_MAGIC 0x61636673
+#endif
+
+#ifndef AFS_SUPER_MAGIC
+#define AFS_SUPER_MAGIC 0x5346414f
+#endif
+
+#ifndef CEPH_SUPER_MAGIC
+#define CEPH_SUPER_MAGIC 0x00c36400
+#endif
+
+#ifndef CIFS_SUPER_MAGIC
+#define CIFS_SUPER_MAGIC 0xff534d42
+#endif
+
+#ifndef CODA_SUPER_MAGIC
+#define CODA_SUPER_MAGIC 0x73757245
+#endif
+
+#ifndef FHGFS_SUPER_MAGIC
+#define FHGFS_SUPER_MAGIC 0x19830326
+#endif
+
+#ifndef GFS_SUPER_MAGIC
+#define GFS_SUPER_MAGIC 0x1161970
+#endif
+
+#ifndef GPFS_SUPER_MAGIC
+#define GPFS_SUPER_MAGIC 0x47504653
+#endif
+
+#ifndef IBRIX_SUPER_MAGIC
+#define IBRIX_SUPER_MAGIC 0x013111a8
+#endif
+
+#ifndef KAFS_SUPER_MAGIC
+#define KAFS_SUPER_MAGIC 0x6b414653
+#endif
+
+#ifndef LUSTRE_SUPER_MAGIC
+#define LUSTRE_SUPER_MAGIC 0x0bd00bd0
+#endif
+
+#ifndef NCP_SUPER_MAGIC
+#define NCP_SUPER_MAGIC 0x564c
+#endif
+
+#ifndef NFS_SUPER_MAGIC
+#define NFS_SUPER_MAGIC 0x6969
+#endif
+
+#ifndef NFSD_SUPER_MAGIC
+#define NFSD_SUPER_MAGIC 0x6e667364
+#endif
+
+#ifndef OCFS2_SUPER_MAGIC
+#define OCFS2_SUPER_MAGIC 0x7461636f
+#endif
+
+#ifndef PANFS_SUPER_MAGIC
+#define PANFS_SUPER_MAGIC 0xaad7aaea
+#endif
+
+#ifndef SMB_SUPER_MAGIC
+#define SMB_SUPER_MAGIC 0x517b
+#endif
+
+#ifndef SMB2_SUPER_MAGIC
+#define SMB2_SUPER_MAGIC 0xfe534d42
+#endif
+
+#ifndef SNFS_SUPER_MAGIC
+#define SNFS_SUPER_MAGIC 0xbeefdead
+#endif
+
+#ifndef VMHGFS_SUPER_MAGIC
+#define VMHGFS_SUPER_MAGIC 0xbacbacbc
+#endif
+
+#ifndef VXFS_SUPER_MAGIC
+#define VXFS_SUPER_MAGIC 0xa501fcf5
+#endif
diff --git a/config.mak.uname b/config.mak.uname
index dacc95172dc..80d7e2a2e68 100644
--- a/config.mak.uname
+++ b/config.mak.uname
@@ -68,6 +68,17 @@ ifeq ($(uname_S),Linux)
ifneq ($(findstring .el7.,$(uname_R)),)
BASIC_CFLAGS += -std=c99
endif
+ ifeq ($(shell test -f /usr/include/linux/magic.h && echo y),y)
+ HAVE_LINUX_MAGIC_H = YesPlease
+ endif
+ # The builtin FSMonitor on Linux builds upon Simple-IPC. Both require
+ # Unix domain sockets and PThreads.
+ ifndef NO_PTHREADS
+ ifndef NO_UNIX_SOCKETS
+ FSMONITOR_DAEMON_BACKEND = linux
+ FSMONITOR_OS_SETTINGS = linux
+ endif
+ endif
endif
ifeq ($(uname_S),GNU/kFreeBSD)
HAVE_ALLOCA_H = YesPlease
--
gitgitgadget
next prev parent reply other threads:[~2024-02-15 10:29 UTC|newest]
Thread overview: 14+ messages / expand[flat|nested] mbox.gz Atom feed top
2024-02-15 10:29 [PATCH 0/7] fsmonitor: completing a stale patch that Implements fsmonitor for Linux marzi via GitGitGadget
2024-02-15 10:29 ` [PATCH 1/7] fsmonitor: rebase with master Eric DeCosta via GitGitGadget
2024-02-15 13:49 ` Patrick Steinhardt
2024-02-15 10:29 ` Eric DeCosta via GitGitGadget [this message]
2024-02-15 11:24 ` [PATCH 2/7] fsmonitor: determine if filesystem is local or remote Jean-Noël Avila
2024-02-15 13:49 ` Patrick Steinhardt
2024-02-15 10:29 ` [PATCH 3/7] fsmonitor: implement filesystem change listener for Linux Eric DeCosta via GitGitGadget
2024-02-15 13:49 ` Patrick Steinhardt
2024-02-15 10:29 ` [PATCH 4/7] fsmonitor: enable fsmonitor " Eric DeCosta via GitGitGadget
2024-02-15 10:29 ` [PATCH 5/7] fsmonitor: test updates Eric DeCosta via GitGitGadget
2024-02-15 10:29 ` [PATCH 6/7] fsmonitor: update doc for Linux Eric DeCosta via GitGitGadget
2024-02-15 10:29 ` [PATCH 7/7] fsmonitor: addressed comments for patch 1352 marzi.esipreh via GitGitGadget
2024-02-15 13:49 ` Patrick Steinhardt
2025-01-31 3:28 ` [PATCH 0/7] fsmonitor: completing a stale patch that Implements fsmonitor for Linux Manoraj K
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=d26de10866662a5bcd16d562cd1063dedd21cf02.1707992978.git.gitgitgadget@gmail.com \
--to=gitgitgadget@gmail.com \
--cc=Johannes.Schindelin@gmx.de \
--cc=avarab@gmail.com \
--cc=chooglen@google.com \
--cc=edecosta@mathworks.com \
--cc=git@vger.kernel.org \
--cc=m.ispare63@gmail.com \
--cc=me@ttaylorr.com \
--cc=sunshine@sunshineco.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).