Skip to content

Commit

Permalink
[PATCH] fuse: more flexible caching
Browse files Browse the repository at this point in the history
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: Miklos Szeredi <[email protected]>
Signed-off-by: Andrew Morton <[email protected]>
Signed-off-by: Linus Torvalds <[email protected]>
  • Loading branch information
szmi authored and Linus Torvalds committed Sep 9, 2005
1 parent 04730fe commit 45323fb
Show file tree
Hide file tree
Showing 5 changed files with 18 additions and 59 deletions.
26 changes: 0 additions & 26 deletions Documentation/filesystems/fuse.txt
Original file line number Diff line number Diff line change
Expand Up @@ -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.
Expand Down
18 changes: 8 additions & 10 deletions fs/fuse/file.c
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down Expand Up @@ -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;
}
Expand Down Expand Up @@ -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;
}
6 changes: 0 additions & 6 deletions fs/fuse/fuse_i.h
Original file line number Diff line number Diff line change
Expand Up @@ -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 {
Expand Down
16 changes: 0 additions & 16 deletions fs/fuse/inode.c
Original file line number Diff line number Diff line change
Expand Up @@ -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
};
Expand All @@ -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}
};
Expand Down Expand Up @@ -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;
Expand Down Expand Up @@ -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;
Expand Down
11 changes: 10 additions & 1 deletion include/linux/fuse.h
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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 */
Expand Down

0 comments on commit 45323fb

Please sign in to comment.