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 <[email protected]>
Reviewed-by: waddlesplash <[email protected]>
Tested-by: Commit checker robot <[email protected]>
This commit is contained in:
PulkoMandy
2022-09-13 18:51:12 +00:00
committed by waddlesplash
parent 750afaef94
commit 49a00a128a
7 changed files with 27 additions and 28 deletions
-13
View File
@@ -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
*
@@ -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
*
@@ -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);
@@ -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);
@@ -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;
@@ -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);
}
@@ -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)