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:
@@ -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)
|
||||
|
||||
Reference in New Issue
Block a user