aboutsummaryrefslogtreecommitdiffstats
path: root/kernel
diff options
context:
space:
mode:
Diffstat (limited to 'kernel')
-rw-r--r--kernel/dev.c3
-rw-r--r--kernel/dir.c6
-rw-r--r--kernel/file.c46
-rw-r--r--kernel/fuse_i.h21
-rw-r--r--kernel/inode.c39
5 files changed, 60 insertions, 55 deletions
diff --git a/kernel/dev.c b/kernel/dev.c
index d3c56a6..9851327 100644
--- a/kernel/dev.c
+++ b/kernel/dev.c
@@ -298,8 +298,7 @@ static ssize_t fuse_dev_read(struct file *file, char *buf, size_t nbytes,
if(ret < 0) {
req->out->h.error = -EPROTO;
req->finished = 1;
- }
- else {
+ } else {
list_add_tail(&req->list, &fc->processing);
req->sent = 1;
}
diff --git a/kernel/dir.c b/kernel/dir.c
index 7e91639..608de2d 100644
--- a/kernel/dir.c
+++ b/kernel/dir.c
@@ -18,7 +18,7 @@ static struct inode_operations fuse_symlink_inode_operations;
static struct file_operations fuse_dir_operations;
-static struct dentry_operations fuse_dentry_opertations;
+static struct dentry_operations fuse_dentry_operations;
/* FIXME: This should be user configurable */
#define FUSE_REVALIDATE_TIME (1 * HZ)
@@ -137,7 +137,7 @@ static int fuse_lookup_iget(struct inode *dir, struct dentry *entry,
return err;
entry->d_time = jiffies;
- entry->d_op = &fuse_dentry_opertations;
+ entry->d_op = &fuse_dentry_operations;
*inodep = inode;
return 0;
}
@@ -769,7 +769,7 @@ static struct inode_operations fuse_symlink_inode_operations =
#endif
};
-static struct dentry_operations fuse_dentry_opertations = {
+static struct dentry_operations fuse_dentry_operations = {
.d_revalidate = fuse_dentry_revalidate,
};
diff --git a/kernel/file.c b/kernel/file.c
index 0752943..04eb729 100644
--- a/kernel/file.c
+++ b/kernel/file.c
@@ -60,6 +60,9 @@ static int fuse_release(struct inode *inode, struct file *file)
struct fuse_open_in *inarg = NULL;
unsigned int s = sizeof(struct fuse_in) + sizeof(struct fuse_open_in);
+ if(file->f_mode & FMODE_WRITE)
+ filemap_fdatawrite(inode->i_mapping);
+
in = kmalloc(s, GFP_NOFS);
if(!in)
return -ENOMEM;
@@ -189,7 +192,6 @@ static int fuse_cache_block(struct address_space *mapping,
char *buffer;
page = grab_cache_page(mapping, index);
-
if (!page)
return -1;
@@ -241,38 +243,40 @@ static int fuse_file_read_block(struct inode *inode, char *bl_buf,
return out.h.error;
}
-static ssize_t fuse_file_read(struct file *filp, char *buf,
- size_t count, loff_t * ppos)
+static void fuse_file_bigread(struct address_space *mapping,
+ struct inode *inode, loff_t pos, size_t count)
{
- struct address_space *mapping = filp->f_dentry->d_inode->i_mapping;
- struct inode *inode = mapping->host;
-
- size_t bl_index = *ppos >> FUSE_BLOCK_SHIFT;
- size_t bl_end_index = (*ppos + count) >> FUSE_BLOCK_SHIFT;
+ size_t bl_index = pos >> FUSE_BLOCK_SHIFT;
+ size_t bl_end_index = (pos + count) >> FUSE_BLOCK_SHIFT;
size_t bl_file_end_index = inode->i_size >> FUSE_BLOCK_SHIFT;
-
+
if (bl_end_index > bl_file_end_index)
bl_end_index = bl_file_end_index;
-
+
while (bl_index <= bl_end_index) {
int res;
char *bl_buf = kmalloc(FUSE_BLOCK_SIZE, GFP_NOFS);
-
if (!bl_buf)
break;
-
res = fuse_is_block_uptodate(mapping, inode, bl_index);
-
if (!res)
res = fuse_file_read_block(inode, bl_buf, bl_index);
-
if (!res)
fuse_cache_block(mapping, inode, bl_buf, bl_index);
-
kfree(bl_buf);
-
bl_index++;
}
+}
+
+static ssize_t fuse_file_read(struct file *filp, char *buf,
+ size_t count, loff_t * ppos)
+{
+ struct address_space *mapping = filp->f_dentry->d_inode->i_mapping;
+ struct inode *inode = mapping->host;
+ struct fuse_conn *fc = INO_FC(inode);
+
+ if(fc->flags & FUSE_LARGE_READ)
+ fuse_file_bigread(mapping, inode, *ppos, count);
return generic_file_read(filp, buf, count, ppos);
}
@@ -466,11 +470,15 @@ static struct address_space_operations fuse_file_aops = {
void fuse_init_file_inode(struct inode *inode)
{
- inode->i_fop = &fuse_file_operations;
- inode->i_data.a_ops = &fuse_file_aops;
#ifdef KERNEL_2_6
- inode->i_mapping->backing_dev_info->ra_pages = 0;
+ struct fuse_conn *fc = INO_FC(inode);
+ /* Readahead somehow defeats big reads on 2.6 (says Michael
+ Grigoriev) */
+ if(fc->flags & FUSE_LARGE_READ)
+ inode->i_mapping->backing_dev_info->ra_pages = 0;
#endif
+ inode->i_fop = &fuse_file_operations;
+ inode->i_data.a_ops = &fuse_file_aops;
}
/*
diff --git a/kernel/fuse_i.h b/kernel/fuse_i.h
index f2e55d4..cc386ac 100644
--- a/kernel/fuse_i.h
+++ b/kernel/fuse_i.h
@@ -8,15 +8,25 @@
#include <linux/fuse.h>
+#include <linux/version.h>
+
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,0) && LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,0)
+#error Kernel version 2.5.* not supported
+#endif
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0)
+#define KERNEL_2_6
+#endif
+
+#ifndef KERNEL_2_6
#include <linux/config.h>
#ifdef CONFIG_MODVERSIONS
#define MODVERSIONS
#include <linux/modversions.h>
#endif
+#endif
#include <linux/kernel.h>
#include <linux/module.h>
-#include <linux/version.h>
#include <linux/fs.h>
#include <linux/list.h>
#include <linux/spinlock.h>
@@ -28,15 +38,6 @@
#define FUSE_BLOCK_PAGE_SHIFT (FUSE_BLOCK_SHIFT - PAGE_CACHE_SHIFT)
-#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,0) && LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,0)
-#error Kernel version 2.5.* not supported
-#endif
-
-#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0)
-#define KERNEL_2_6
-#endif
-
-
/**
* A Fuse connection.
*
diff --git a/kernel/inode.c b/kernel/inode.c
index 4a16051..f5c3a97 100644
--- a/kernel/inode.c
+++ b/kernel/inode.c
@@ -201,38 +201,35 @@ static int fuse_read_super(struct super_block *sb, void *data, int silent)
sb->s_export_op = &fuse_export_operations;
#endif
- root = get_root_inode(sb, d->rootmode);
- if(root == NULL) {
- printk("fuse_read_super: failed to get root inode\n");
- return -EINVAL;
- }
-
- spin_lock(&fuse_lock);
fc = get_conn(d);
if(fc == NULL)
- goto err;
-
+ return -EINVAL;
+ spin_lock(&fuse_lock);
if(fc->sb != NULL) {
printk("fuse_read_super: connection already mounted\n");
- goto err;
+ spin_unlock(&fuse_lock);
+ return -EINVAL;
}
-
- SB_FC(sb) = fc;
- sb->s_root = d_alloc_root(root);
- if(!sb->s_root)
- goto err;
-
fc->sb = sb;
fc->flags = d->flags;
fc->uid = d->uid;
spin_unlock(&fuse_lock);
- return 0;
+ /* fc is needed in fuse_init_file_inode which could be called
+ from get_root_inode */
+ SB_FC(sb) = fc;
- err:
- spin_unlock(&fuse_lock);
- iput(root);
- return -EINVAL;
+ root = get_root_inode(sb, d->rootmode);
+ if(root == NULL) {
+ printk("fuse_read_super: failed to get root inode\n");
+ return -EINVAL;
+ }
+
+ sb->s_root = d_alloc_root(root);
+ if(!sb->s_root)
+ return -EINVAL;
+
+ return 0;
}
#ifdef KERNEL_2_6