From 49a00a128add075bfc362bcdd53237832cebc618 Mon Sep 17 00:00:00 2001 From: PulkoMandy Date: Wed, 20 Jul 2022 22:13:26 +0200 Subject: [PATCH] userlandfs: implement get_fs_info using ioctl This avoids introducing an entirely custom hook in FUSE. It uses the ioctl hook in an unconventional way (calling it with no valid fuse_file_info) but this can be fixed if a filesystem requires it (by opening a file handle on /, doing the ioctl, then closing again). An updated version of fusesmb-haiku is available and confirmed working: https://github.com/haikuarchives/fusesmb-haiku Change-Id: If1268113874363fa035e5340be75e9f5198216d6 Reviewed-on: https://review.haiku-os.org/c/haiku/+/5199 Reviewed-by: Adrien Destugues Reviewed-by: waddlesplash Tested-by: Commit checker robot --- headers/private/userlandfs/fuse/fuse.h | 13 ------------- headers/private/userlandfs/fuse/fuse_common.h | 6 ++++++ .../userlandfs/server/fuse/FUSEFileSystem.cpp | 2 ++ .../userlandfs/server/fuse/FUSEFileSystem.h | 6 ++++++ .../userlandfs/server/fuse/FUSEVolume.cpp | 5 +++-- .../userlandfs/server/fuse/fuse_fs.cpp | 18 ++++++++++-------- .../userlandfs/server/fuse/fuse_main.cpp | 5 ----- 7 files changed, 27 insertions(+), 28 deletions(-) diff --git a/headers/private/userlandfs/fuse/fuse.h b/headers/private/userlandfs/fuse/fuse.h index e3a49317c2..affb46c7b0 100644 --- a/headers/private/userlandfs/fuse/fuse.h +++ b/headers/private/userlandfs/fuse/fuse.h @@ -37,11 +37,6 @@ extern "C" { #endif -#ifdef HAS_FUSE_HAIKU_EXTENSIONS -struct fs_info; -extern int gHasHaikuFuseExtensions; -#endif - /* ----------------------------------------------------------- * * Basic FUSE API * @@ -459,10 +454,6 @@ struct fuse_operations { */ int (*bmap) (const char *, size_t blocksize, uint64_t *idx); -#ifdef HAS_FUSE_HAIKU_EXTENSIONS - int (*get_fs_info) (struct fs_info*); -#endif - /** * Flag indicating that the filesystem can accept a NULL path * as the first argument for the following operations: @@ -903,10 +894,6 @@ void fuse_fs_destroy(struct fuse_fs *fs); int fuse_notify_poll(struct fuse_pollhandle *ph); -#ifdef HAS_FUSE_HAIKU_EXTENSIONS -int fuse_fs_get_fs_info(struct fuse_fs* fs, struct fs_info* info); -#endif - /** * Create a new fuse filesystem object * diff --git a/headers/private/userlandfs/fuse/fuse_common.h b/headers/private/userlandfs/fuse/fuse_common.h index 8b9a1ae935..87fca44159 100644 --- a/headers/private/userlandfs/fuse/fuse_common.h +++ b/headers/private/userlandfs/fuse/fuse_common.h @@ -113,6 +113,12 @@ struct fuse_file_info { #define FUSE_CAP_FLOCK_LOCKS (1 << 10) #define FUSE_CAP_IOCTL_DIR (1 << 11) +/* Indicate support for Haiku-specific extensions in struct fuse_operations and fuse_ll_ops */ +#define FUSE_CAP_HAIKU_FUSE_EXTENSIONS (1 << 31) + +#define FUSE_HAIKU_GET_DRIVE_INFO (((uint32_t)'H' << 24) | ((uint32_t)'G' << 16) \ + | ((uint32_t)'D' << 8) | (uint32_t)'I') + /** * Ioctl flags * diff --git a/src/add-ons/kernel/file_systems/userlandfs/server/fuse/FUSEFileSystem.cpp b/src/add-ons/kernel/file_systems/userlandfs/server/fuse/FUSEFileSystem.cpp index 0564992823..2e5c22e788 100644 --- a/src/add-ons/kernel/file_systems/userlandfs/server/fuse/FUSEFileSystem.cpp +++ b/src/add-ons/kernel/file_systems/userlandfs/server/fuse/FUSEFileSystem.cpp @@ -376,6 +376,8 @@ fNodeCapabilities.Dump(); fConnectionInfo.async_read = false; fConnectionInfo.max_write = 64 * 1024; fConnectionInfo.max_readahead = 64 * 1024; + fConnectionInfo.capable = FUSE_CAP_ATOMIC_O_TRUNC | FUSE_CAP_BIG_WRITES | FUSE_CAP_IOCTL_DIR + | FUSE_CAP_HAIKU_FUSE_EXTENSIONS; fuse_fs_init(fFS, &fConnectionInfo); diff --git a/src/add-ons/kernel/file_systems/userlandfs/server/fuse/FUSEFileSystem.h b/src/add-ons/kernel/file_systems/userlandfs/server/fuse/FUSEFileSystem.h index ad4dd84ae9..1997fd12d2 100644 --- a/src/add-ons/kernel/file_systems/userlandfs/server/fuse/FUSEFileSystem.h +++ b/src/add-ons/kernel/file_systems/userlandfs/server/fuse/FUSEFileSystem.h @@ -41,6 +41,12 @@ public: const fuse_config& GetFUSEConfig() const { return fFUSEConfig; } + bool HasHaikuFuseExtensions() const + { + return (fConnectionInfo.want + & FUSE_CAP_HAIKU_FUSE_EXTENSIONS) != 0; + } + virtual status_t CreateVolume(Volume** _volume, dev_t id); virtual status_t DeleteVolume(Volume* volume); diff --git a/src/add-ons/kernel/file_systems/userlandfs/server/fuse/FUSEVolume.cpp b/src/add-ons/kernel/file_systems/userlandfs/server/fuse/FUSEVolume.cpp index 575cbf1c7e..9709820791 100644 --- a/src/add-ons/kernel/file_systems/userlandfs/server/fuse/FUSEVolume.cpp +++ b/src/add-ons/kernel/file_systems/userlandfs/server/fuse/FUSEVolume.cpp @@ -882,8 +882,9 @@ FUSEVolume::Sync() status_t FUSEVolume::ReadFSInfo(fs_info* info) { - if (gHasHaikuFuseExtensions == 1 && fFS->ops.get_fs_info != NULL) { - int fuseError = fuse_fs_get_fs_info(fFS, info); + if (_FileSystem()->HasHaikuFuseExtensions() && fFS->ops.ioctl != NULL) { + int fuseError = fuse_fs_ioctl(fFS, "/", FUSE_HAIKU_GET_DRIVE_INFO, info, NULL, + sizeof(fs_info), NULL); if (fuseError != 0) return fuseError; return B_OK; diff --git a/src/add-ons/kernel/file_systems/userlandfs/server/fuse/fuse_fs.cpp b/src/add-ons/kernel/file_systems/userlandfs/server/fuse/fuse_fs.cpp index d0959fac31..21f531e368 100644 --- a/src/add-ons/kernel/file_systems/userlandfs/server/fuse/fuse_fs.cpp +++ b/src/add-ons/kernel/file_systems/userlandfs/server/fuse/fuse_fs.cpp @@ -342,6 +342,16 @@ fuse_fs_bmap(struct fuse_fs* fs, const char* path, size_t blocksize, } +int fuse_fs_ioctl(struct fuse_fs *fs, const char *path, int cmd, void *arg, + struct fuse_file_info *fi, unsigned int flags, void *data) +{ + if (fs->ops.ioctl == NULL) + return ENOSYS; + + return fs->ops.ioctl(path, cmd, arg, fi, flags, data); +} + + void fuse_fs_init(struct fuse_fs* fs, struct fuse_conn_info* conn) { @@ -381,11 +391,3 @@ fuse_fs_new(const struct fuse_operations* ops, size_t opSize, void* userData) return fs; } - -int -fuse_fs_get_fs_info(struct fuse_fs* fs, struct fs_info* info) -{ - if (fs->ops.get_fs_info == NULL) - return ENOSYS; - return fs->ops.get_fs_info(info); -} diff --git a/src/add-ons/kernel/file_systems/userlandfs/server/fuse/fuse_main.cpp b/src/add-ons/kernel/file_systems/userlandfs/server/fuse/fuse_main.cpp index 6ce9a52f65..321b9f3aed 100644 --- a/src/add-ons/kernel/file_systems/userlandfs/server/fuse/fuse_main.cpp +++ b/src/add-ons/kernel/file_systems/userlandfs/server/fuse/fuse_main.cpp @@ -17,11 +17,6 @@ #include "../RequestThread.h" -int gHasHaikuFuseExtensions = 0; - // This global can be set to 1 by a Haiku-aware FUSE add-on to signal - // that it implements the Haiku-specific functions in struct - // fuse_operations (those which are guarded by HAS_FUSE_HAIKU_EXTENSIONS). - int fuse_main_real(int argc, char* argv[], const struct fuse_operations* op, size_t opSize, void* userData)