fsmonitor: refactor filesystem checks to common interface
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 <edecosta@mathworks.com> Signed-off-by: Junio C Hamano <gitster@pobox.com>
This commit is contained in:

committed by
Junio C Hamano

parent
85dc0da6dc
commit
508c1a572d
@ -1,32 +1,10 @@
|
||||
#include "cache.h"
|
||||
#include "config.h"
|
||||
#include "repository.h"
|
||||
#include "fsmonitor-settings.h"
|
||||
#include "fsmonitor.h"
|
||||
#include <sys/param.h>
|
||||
#include <sys/mount.h>
|
||||
#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);
|
||||
strbuf_release(&path);
|
||||
|
||||
if (!(fs.f_flags & MNT_LOCAL))
|
||||
return FSMONITOR_REASON_REMOTE;
|
||||
|
||||
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;
|
||||
|
||||
|
Reference in New Issue
Block a user