diff options
Diffstat (limited to 'kernel')
-rw-r--r-- | kernel/dev.c | 3 | ||||
-rw-r--r-- | kernel/dir.c | 6 | ||||
-rw-r--r-- | kernel/file.c | 46 | ||||
-rw-r--r-- | kernel/fuse_i.h | 21 | ||||
-rw-r--r-- | kernel/inode.c | 39 |
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 |