From 6c66dac9f229d0035f83ae63d9033e4f51d9c5c8 Mon Sep 17 00:00:00 2001 From: Nikolaus Rath Date: Tue, 18 Oct 2016 21:02:32 -0700 Subject: [PATCH] Pass struct fuse_config to high-level init() handler. --- ChangeLog.rst | 4 + include/fuse.h | 183 ++++++++++++++++++++++++++++++++++++++++++- lib/fuse.c | 34 +------- lib/modules/iconv.c | 5 +- lib/modules/subdir.c | 5 +- 5 files changed, 195 insertions(+), 36 deletions(-) diff --git a/ChangeLog.rst b/ChangeLog.rst index a668d5f..7d32ba6 100644 --- a/ChangeLog.rst +++ b/ChangeLog.rst @@ -1,6 +1,10 @@ Unreleased Changes ================== +* The high-level init() handler now receives an additional struct + fuse_config pointer that can be used to adjust high-level API + specific configuration options. + * File systems that use the low-level API and support lookup requests for '.' and '..' should continue make sure to set the FUSE_CAP_EXPORT_SUPPORT bit in fuse_conn_info->want. diff --git a/include/fuse.h b/include/fuse.h index 52b8698..3c13c14 100644 --- a/include/fuse.h +++ b/include/fuse.h @@ -76,6 +76,183 @@ enum fuse_fill_dir_flags { typedef int (*fuse_fill_dir_t) (void *buf, const char *name, const struct stat *stbuf, off_t off, enum fuse_fill_dir_flags flags); +/** + * Configuration of the high-level API + * + * This structure is initialized from the arguments passed to + * fuse_new(), and then passed to the file system's init() handler + * which should ensure that the configuration is compatible with the + * file system implementation. + */ +struct fuse_config { + /** + * If `set_gid` is non-zero, the st_gid attribute of each file + * is overwritten with the value of `gid`. + */ + int set_gid; + unsigned int gid; + + /** + * If `set_uid` is non-zero, the st_uid attribute of each file + * is overwritten with the value of `uid`. + */ + int set_uid; + unsigned int uid; + + /** + * If `set_mode` is non-zero, the any permissions bits set in + * `umask` are unset in the st_mode attribute of each file. + */ + int set_mode; + unsigned int umask; + + /** + * The timeout in seconds for which name lookups will be + * cached. + */ + double entry_timeout; + + /** + * The timeout in seconds for which a negative lookup will be + * cached. This means, that if file did not exist (lookup + * retuned ENOENT), the lookup will only be redone after the + * timeout, and the file/directory will be assumed to not + * exist until then. A value of zero means that negative + * lookups are not cached. + */ + double negative_timeout; + + /** + * The timeout in seconds for which file/directory attributes + * (as returned by e.g. the `getattr` handler) are cached. + */ + double attr_timeout; + + /** + * Allow requests to be interrupted + */ + int intr; + + /** + * Specify which signal number to send to the filesystem when + * a request is interrupted. The default is hardcoded to + * USR1. + */ + int intr_signal; + + /** + * Normally, FUSE assigns inodes to paths only for as long as + * the kernel is aware of them. With this option inodes are + * instead remembered for at least this many seconds. This + * will require more memory, but may be necessary when using + * applications that make use of inode numbers. + * + * A number of -1 means that inodes will be remembered for the + * entire life-time of the file-system process. + */ + int remember; + + /** + * The default behavior is that if an open file is deleted, + * the file is renamed to a hidden file (.fuse_hiddenXXX), and + * only removed when the file is finally released. This + * relieves the filesystem implementation of having to deal + * with this problem. This option disables the hiding + * behavior, and files are removed immediately in an unlink + * operation (or in a rename operation which overwrites an + * existing file). + * + * It is recommended that you not use the hard_remove + * option. When hard_remove is set, the following libc + * functions fail on unlinked files (returning errno of + * ENOENT): read(2), write(2), fsync(2), close(2), f*xattr(2), + * ftruncate(2), fstat(2), fch‐ mod(2), fchown(2) + */ + int hard_remove; + + /** + * Honor the st_ino field in the functions getattr() and + * fill_dir(). This value is used to fill in the st_ino field + * in the stat(2), lstat(2), fstat(2) functions and the d_ino + * field in the readdir(2) function. The filesystem does not + * have to guarantee uniqueness, however some applications + * rely on this value being unique for the whole filesystem. + */ + int use_ino; + + /** + * If use_ino option is not given, still try to fill in the + * d_ino field in readdir(2). If the name was previously + * looked up, and is still in the cache, the inode number + * found there will be used. Otherwise it will be set to -1. + * If use_ino option is given, this option is ignored. + */ + int readdir_ino; + + /** + * This option disables the use of page cache (file content cache) + * in the kernel for this filesystem. This has several affects: + * + * 1. Each read(2) or write(2) system call will initiate one + * or more read or write operations, data will not be + * cached in the kernel. + * + * 2. The return value of the read() and write() system calls + * will correspond to the return values of the read and + * write operations. This is useful for example if the + * file size is not known in advance (before reading it). + * + * Internally, enabling this option causes fuse to set the + * `direct_io` field of `struct fuse_file_info` - overwriting + * any value that was put there by the file system. + */ + int direct_io; + + /** + * This option disables flushing the cache of the file + * contents on every open(2). This should only be enabled on + * filesystems, where the file data is never changed + * externally (not through the mounted FUSE filesystem). Thus + * it is not suitable for network filesystems and other + * intermediate filesystems. + * + * NOTE: if this option is not specified (and neither + * direct_io) data is still cached after the open(2), so a + * read(2) system call will not always initiate a read + * operation. + * + * Internally, enabling this option causes fuse to set the + * `keep_cache` field of `struct fuse_file_info` - overwriting + * any value that was put there by the file system. + */ + int kernel_cache; + + /** + * This option is an alternative to `kernel_cache`. Instead of + * unconditionally keeping cached data, the cached data is + * invalidated on open(2) if if the modification time or the + * size of the file has changed since it was last opened. + */ + int auto_cache; + + /** + * The timeout in seconds for which file attributes are cached + * for the purpose of checking if auto_cache should flush the + * file data on open. + */ + int ac_attr_timeout_set; + double ac_attr_timeout; + + /** + * The remaining options are used by libfuse internally and + * should not be touched. + */ + int show_help; + char *modules; + int debug; + int nopath; +}; + /** * The file system operations: @@ -354,7 +531,8 @@ struct fuse_operations { * fuse_context to all file operations and as a parameter to the * destroy() method. */ - void *(*init) (struct fuse_conn_info *conn); + void *(*init) (struct fuse_conn_info *conn, + struct fuse_config *cfg); /** * Clean up filesystem @@ -881,7 +1059,8 @@ int fuse_fs_poll(struct fuse_fs *fs, const char *path, unsigned *reventsp); int fuse_fs_fallocate(struct fuse_fs *fs, const char *path, int mode, off_t offset, off_t length, struct fuse_file_info *fi); -void fuse_fs_init(struct fuse_fs *fs, struct fuse_conn_info *conn); +void fuse_fs_init(struct fuse_fs *fs, struct fuse_conn_info *conn, + struct fuse_config *cfg); void fuse_fs_destroy(struct fuse_fs *fs); int fuse_notify_poll(struct fuse_pollhandle *ph); diff --git a/lib/fuse.c b/lib/fuse.c index 07e63d2..f469378 100644 --- a/lib/fuse.c +++ b/lib/fuse.c @@ -57,33 +57,6 @@ #define NODE_TABLE_MIN_SIZE 8192 -struct fuse_config { - unsigned int uid; - unsigned int gid; - unsigned int umask; - double entry_timeout; - double negative_timeout; - double attr_timeout; - double ac_attr_timeout; - int ac_attr_timeout_set; - int remember; - int nopath; - int debug; - int hard_remove; - int use_ino; - int readdir_ino; - int set_mode; - int set_uid; - int set_gid; - int direct_io; - int kernel_cache; - int auto_cache; - int intr; - int intr_signal; - int show_help; - char *modules; -}; - struct fuse_fs { struct fuse_operations op; struct fuse_module *m; @@ -2478,7 +2451,8 @@ static void reply_entry(fuse_req_t req, const struct fuse_entry_param *e, reply_err(req, err); } -void fuse_fs_init(struct fuse_fs *fs, struct fuse_conn_info *conn) +void fuse_fs_init(struct fuse_fs *fs, struct fuse_conn_info *conn, + struct fuse_config *cfg) { fuse_get_context()->private_data = fs->user_data; if (!fs->op.write_buf) @@ -2488,7 +2462,7 @@ void fuse_fs_init(struct fuse_fs *fs, struct fuse_conn_info *conn) if (!fs->op.flock) conn->want &= ~FUSE_CAP_FLOCK_LOCKS; if (fs->op.init) - fs->user_data = fs->op.init(conn); + fs->user_data = fs->op.init(conn, cfg); } static void fuse_lib_init(void *data, struct fuse_conn_info *conn) @@ -2497,7 +2471,7 @@ static void fuse_lib_init(void *data, struct fuse_conn_info *conn) fuse_create_context(f); conn->want |= FUSE_CAP_EXPORT_SUPPORT; - fuse_fs_init(f->fs, conn); + fuse_fs_init(f->fs, conn, &f->conf); } void fuse_fs_destroy(struct fuse_fs *fs) diff --git a/lib/modules/iconv.c b/lib/modules/iconv.c index 41a072c..b0453be 100644 --- a/lib/modules/iconv.c +++ b/lib/modules/iconv.c @@ -556,10 +556,11 @@ static int iconv_bmap(const char *path, size_t blocksize, uint64_t *idx) return err; } -static void *iconv_init(struct fuse_conn_info *conn) +static void *iconv_init(struct fuse_conn_info *conn, + struct fuse_config *cfg) { struct iconv *ic = iconv_get(); - fuse_fs_init(ic->next, conn); + fuse_fs_init(ic->next, conn, cfg); return ic; } diff --git a/lib/modules/subdir.c b/lib/modules/subdir.c index c264fb4..708edf3 100644 --- a/lib/modules/subdir.c +++ b/lib/modules/subdir.c @@ -542,10 +542,11 @@ static int subdir_bmap(const char *path, size_t blocksize, uint64_t *idx) return err; } -static void *subdir_init(struct fuse_conn_info *conn) +static void *subdir_init(struct fuse_conn_info *conn, + struct fuse_config *cfg) { struct subdir *d = subdir_get(); - fuse_fs_init(d->next, conn); + fuse_fs_init(d->next, conn, cfg); return d; } -- 2.30.2