Commit 45323fb7 authored by Miklos Szeredi's avatar Miklos Szeredi Committed by Linus Torvalds

[PATCH] fuse: more flexible caching

Make data caching behavior selectable on a per-open basis instead of
per-mount.  Compatibility for the old mount options 'kernel_cache' and
'direct_io' is retained in the userspace library (version 2.4.0-pre1 or
later).
Signed-off-by: default avatarMiklos Szeredi <miklos@szeredi.hu>
Signed-off-by: default avatarAndrew Morton <akpm@osdl.org>
Signed-off-by: default avatarLinus Torvalds <torvalds@osdl.org>
parent 04730fef
......@@ -80,32 +80,6 @@ Mount options
allowed to root, but this restriction can be removed with a
(userspace) configuration option.
'kernel_cache'
This option disables flushing the cache of the file contents on
every open(). 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(), so a read() system call will not
always initiate a read operation.
'direct_io'
This option disables the use of page cache (file content cache) in
the kernel for this filesystem. This has several affects:
- Each read() or write() system call will initiate one or more
read or write operations, data will not be cached in the
kernel.
- 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).
'max_read=N'
With this option the maximum size of read operations can be set.
......
......@@ -12,6 +12,8 @@
#include <linux/slab.h>
#include <linux/kernel.h>
static struct file_operations fuse_direct_io_file_operations;
int fuse_open_common(struct inode *inode, struct file *file, int isdir)
{
struct fuse_conn *fc = get_fuse_conn(inode);
......@@ -70,12 +72,14 @@ int fuse_open_common(struct inode *inode, struct file *file, int isdir)
else
request_send(fc, req);
err = req->out.h.error;
if (!err && !(fc->flags & FUSE_KERNEL_CACHE))
invalidate_inode_pages(inode->i_mapping);
if (err) {
fuse_request_free(ff->release_req);
kfree(ff);
} else {
if (!isdir && (outarg.open_flags & FOPEN_DIRECT_IO))
file->f_op = &fuse_direct_io_file_operations;
if (!(outarg.open_flags & FOPEN_KEEP_CACHE))
invalidate_inode_pages(inode->i_mapping);
ff->fh = outarg.fh;
file->private_data = ff;
}
......@@ -544,12 +548,6 @@ static struct address_space_operations fuse_file_aops = {
void fuse_init_file_inode(struct inode *inode)
{
struct fuse_conn *fc = get_fuse_conn(inode);
if (fc->flags & FUSE_DIRECT_IO)
inode->i_fop = &fuse_direct_io_file_operations;
else {
inode->i_fop = &fuse_file_operations;
inode->i_data.a_ops = &fuse_file_aops;
}
inode->i_fop = &fuse_file_operations;
inode->i_data.a_ops = &fuse_file_aops;
}
......@@ -30,12 +30,6 @@
doing the mount will be allowed to access the filesystem */
#define FUSE_ALLOW_OTHER (1 << 1)
/** If the FUSE_KERNEL_CACHE flag is given, then cached data will not
be flushed on open */
#define FUSE_KERNEL_CACHE (1 << 2)
/** Bypass the page cache for read and write operations */
#define FUSE_DIRECT_IO (1 << 3)
/** FUSE inode */
struct fuse_inode {
......
......@@ -257,8 +257,6 @@ enum {
OPT_GROUP_ID,
OPT_DEFAULT_PERMISSIONS,
OPT_ALLOW_OTHER,
OPT_KERNEL_CACHE,
OPT_DIRECT_IO,
OPT_MAX_READ,
OPT_ERR
};
......@@ -270,8 +268,6 @@ static match_table_t tokens = {
{OPT_GROUP_ID, "group_id=%u"},
{OPT_DEFAULT_PERMISSIONS, "default_permissions"},
{OPT_ALLOW_OTHER, "allow_other"},
{OPT_KERNEL_CACHE, "kernel_cache"},
{OPT_DIRECT_IO, "direct_io"},
{OPT_MAX_READ, "max_read=%u"},
{OPT_ERR, NULL}
};
......@@ -327,14 +323,6 @@ static int parse_fuse_opt(char *opt, struct fuse_mount_data *d)
d->flags |= FUSE_ALLOW_OTHER;
break;
case OPT_KERNEL_CACHE:
d->flags |= FUSE_KERNEL_CACHE;
break;
case OPT_DIRECT_IO:
d->flags |= FUSE_DIRECT_IO;
break;
case OPT_MAX_READ:
if (match_int(&args[0], &value))
return 0;
......@@ -363,10 +351,6 @@ static int fuse_show_options(struct seq_file *m, struct vfsmount *mnt)
seq_puts(m, ",default_permissions");
if (fc->flags & FUSE_ALLOW_OTHER)
seq_puts(m, ",allow_other");
if (fc->flags & FUSE_KERNEL_CACHE)
seq_puts(m, ",kernel_cache");
if (fc->flags & FUSE_DIRECT_IO)
seq_puts(m, ",direct_io");
if (fc->max_read != ~0)
seq_printf(m, ",max_read=%u", fc->max_read);
return 0;
......
......@@ -14,7 +14,7 @@
#define FUSE_KERNEL_VERSION 7
/** Minor version number of this interface */
#define FUSE_KERNEL_MINOR_VERSION 1
#define FUSE_KERNEL_MINOR_VERSION 2
/** The node ID of the root inode */
#define FUSE_ROOT_ID 1
......@@ -63,6 +63,15 @@ struct fuse_kstatfs {
#define FATTR_MTIME (1 << 5)
#define FATTR_CTIME (1 << 6)
/**
* Flags returned by the OPEN request
*
* FOPEN_DIRECT_IO: bypass page cache for this open file
* FOPEN_KEEP_CACHE: don't invalidate the data cache on open
*/
#define FOPEN_DIRECT_IO (1 << 0)
#define FOPEN_KEEP_CACHE (1 << 1)
enum fuse_opcode {
FUSE_LOOKUP = 1,
FUSE_FORGET = 2, /* no reply */
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment