diff --git a/headers/private/userlandfs/fuse/fuse.h b/headers/private/userlandfs/fuse/fuse.h index b7708c761e..0758babcd9 100644 --- a/headers/private/userlandfs/fuse/fuse.h +++ b/headers/private/userlandfs/fuse/fuse.h @@ -36,6 +36,11 @@ extern "C" { #endif +#ifdef HAS_FUSE_HAIKU_EXTENSIONS +struct fs_info; +extern int gHasHaikuFuseExtensions; +#endif + /* ----------------------------------------------------------- * * Basic FUSE API * * ----------------------------------------------------------- */ @@ -423,6 +428,10 @@ struct fuse_operations { * Introduced in version 2.6 */ int (*bmap) (const char *, size_t blocksize, uint64_t *idx); + +#ifdef HAS_FUSE_HAIKU_EXTENSIONS + int (*get_fs_info) (struct fs_info*); +#endif }; /** Extra context that may be needed by some filesystems @@ -658,6 +667,10 @@ int fuse_fs_bmap(struct fuse_fs *fs, const char *path, size_t blocksize, void fuse_fs_init(struct fuse_fs *fs, struct fuse_conn_info *conn); void fuse_fs_destroy(struct fuse_fs *fs); +#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/src/add-ons/kernel/file_systems/userlandfs/server/fuse/FUSEVolume.cpp b/src/add-ons/kernel/file_systems/userlandfs/server/fuse/FUSEVolume.cpp index 570afaedc7..ea9cc42c69 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 @@ -783,6 +783,15 @@ 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 (fuseError != 0) + return fuseError; + return B_OK; + } + + // No Haiku FUSE extensions, so our knowledge is limited: use some values + // from statfs and make reasonable guesses for the rest of them. if (fFS->ops.statfs == NULL) return B_UNSUPPORTED; @@ -791,6 +800,7 @@ FUSEVolume::ReadFSInfo(fs_info* info) if (fuseError != 0) return fuseError; + memset(info, 0, sizeof(*info)); info->flags = B_FS_IS_PERSISTENT; // assume the FS is persistent info->block_size = st.f_bsize; info->io_size = 64 * 1024; // some value diff --git a/src/add-ons/kernel/file_systems/userlandfs/server/fuse/fuse_api.h b/src/add-ons/kernel/file_systems/userlandfs/server/fuse/fuse_api.h index dca679f081..750e43ec33 100644 --- a/src/add-ons/kernel/file_systems/userlandfs/server/fuse/fuse_api.h +++ b/src/add-ons/kernel/file_systems/userlandfs/server/fuse/fuse_api.h @@ -7,6 +7,8 @@ #define FUSE_USE_VERSION FUSE_VERSION +#define HAS_FUSE_HAIKU_EXTENSIONS + #include #include #include 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 62831b171c..d0959fac31 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 @@ -380,3 +380,12 @@ 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 7dc318d812..2633970169 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,6 +17,11 @@ #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)