integrated 2.6 kernel support
diff --git a/kernel/.cvsignore b/kernel/.cvsignore
index e440faf..bd5fe06 100644
--- a/kernel/.cvsignore
+++ b/kernel/.cvsignore
@@ -1,3 +1,2 @@
-Makefile.in
Makefile
.deps
diff --git a/kernel/Makefile.am b/kernel/Makefile.am
deleted file mode 100644
index 89b1018..0000000
--- a/kernel/Makefile.am
+++ /dev/null
@@ -1,43 +0,0 @@
-## Process this file with automake to produce Makefile.in
-
-EXTRA_DIST = dev.c dir.c file.c inode.c util.c fuse_i.h
-
-CC = @CC@
-LD = @LD@
-CFLAGS = -O2 -Wall -Wstrict-prototypes -fno-strict-aliasing -pipe
-CPPFLAGS = -I@KERNINCLUDE@ -I../include -D__KERNEL__ -DMODULE -D_LOOSE_KERNEL_NAMES
-INSTALL = @INSTALL@
-fusemoduledir = @kmoduledir@/kernel/fs/fuse
-
-SUFFIXES = .c .o .s
-
-
-all-local: fuse.o
-
-install-exec-local: fuse.o
- $(mkinstalldirs) $(DESTDIR)$(fusemoduledir)
- $(INSTALL) -m 644 fuse.o $(DESTDIR)$(fusemoduledir)/fuse.o
- -/sbin/depmod -a
-
-uninstall-local:
- rm -f $(DESTDIR)$(fusemoduledir)/fuse.o
- -/sbin/depmod -a
-
-clean-local:
- rm -f *.o *.s
-
-.c.o:
- $(CC) $(CFLAGS) $(CPPFLAGS) -c $<
-
-fuse_objs = dev.o dir.o file.o inode.o util.o
-
-fuse.o: $(fuse_objs)
- $(LD) -r -o fuse.o $(fuse_objs)
-
-fuse_headers = fuse_i.h ../include/linux/fuse.h
-
-dev.o: $(fuse_headers)
-dir.o: $(fuse_headers)
-file.o: $(fuse_headers)
-inode.o: $(fuse_headers)
-util.o: $(fuse_headers)
diff --git a/kernel/Makefile.in b/kernel/Makefile.in
new file mode 100644
index 0000000..f1bf8a1
--- /dev/null
+++ b/kernel/Makefile.in
@@ -0,0 +1,80 @@
+# Makefile.in for kernel module
+
+SHELL = /bin/sh
+INSTALL = @INSTALL@
+mkinstalldirs = $(SHELL) ../mkinstalldirs
+majver = @majver@
+
+EXTRA_CFLAGS := -I$(PWD)/../include
+DISTFILES = Makefile.in dev.c dir.c file.c inode.c util.c fuse_i.h
+
+fusemoduledir = @kmoduledir@/kernel/fs/fuse
+
+ifeq ($(majver), 2.4)
+fusemodule := fuse.o
+else
+fusemodule := fuse.ko
+endif
+
+all: all-spec
+
+install: all
+ @$(mkinstalldirs) $(DESTDIR)$(fusemoduledir)
+ $(INSTALL) -m 644 $(fusemodule) $(DESTDIR)$(fusemoduledir)/$(fusemodule)
+ -/sbin/depmod -a
+
+uninstall:
+ rm -f $(DESTDIR)$(fusemoduledir)/$(fusemodule)
+ -/sbin/depmod -a
+
+clean:
+ -rm -f $(fusemodule) *.o .*.cmd *.mod.c *.ko *.s
+
+distclean: clean
+ rm -f Makefile
+
+maintainer-clean: distclean
+
+distdir: $(DISTFILES)
+ cp -p $(DISTFILES) $(distdir)
+
+
+ifeq ($(majver), 2.4)
+
+CC = @CC@
+LD = @LD@
+CFLAGS = -O2 -Wall -Wstrict-prototypes -fno-strict-aliasing -pipe
+CPPFLAGS = -I@kernelsrc@/include -I../include -D__KERNEL__ -DMODULE -D_LOOSE_KERNEL_NAMES
+
+fuse_objs = dev.o dir.o file.o inode.o util.o
+
+SUFFIXES = .c .o .s
+
+all-spec: fuse.o
+
+.c.o:
+ $(CC) $(CFLAGS) $(CPPFLAGS) -c $<
+
+fuse.o: $(fuse_objs)
+ $(LD) -r -o fuse.o $(fuse_objs)
+
+fuse_headers = fuse_i.h ../include/linux/fuse.h
+
+dev.o: $(fuse_headers)
+dir.o: $(fuse_headers)
+file.o: $(fuse_headers)
+inode.o: $(fuse_headers)
+util.o: $(fuse_headers)
+
+else
+
+obj-m := fuse.o
+fuse-objs := dev.o dir.o file.o inode.o util.o
+
+all-spec:
+ $(MAKE) -C @kernelsrc@ SUBDIRS=$(PWD) modules
+endif
+
+
+
+
diff --git a/kernel/dev.c b/kernel/dev.c
index e34bee5..8b9b3fb 100644
--- a/kernel/dev.c
+++ b/kernel/dev.c
@@ -368,7 +368,12 @@
if (!inode)
return -ENOENT;
+#ifdef KERNEL_2_6
+ invalidate_inode_pages(inode->i_mapping);
+#else
invalidate_inode_pages(inode);
+#endif
+
iput(inode);
return 0;
}
diff --git a/kernel/dir.c b/kernel/dir.c
index d4210b5..23d1f01 100644
--- a/kernel/dir.c
+++ b/kernel/dir.c
@@ -25,8 +25,13 @@
static void change_attributes(struct inode *inode, struct fuse_attr *attr)
{
- if(S_ISREG(inode->i_mode) && inode->i_size != attr->size)
+ if(S_ISREG(inode->i_mode) && inode->i_size != attr->size) {
+#ifdef KERNEL_2_6
+ invalidate_inode_pages(inode->i_mapping);
+#else
invalidate_inode_pages(inode);
+#endif
+ }
inode->i_mode = (inode->i_mode & S_IFMT) + (attr->mode & 07777);
inode->i_nlink = attr->nlink;
@@ -35,9 +40,18 @@
inode->i_size = attr->size;
inode->i_blksize = PAGE_CACHE_SIZE;
inode->i_blocks = attr->blocks;
+#ifdef KERNEL_2_6
+ inode->i_atime.tv_sec = attr->atime;
+ inode->i_atime.tv_nsec = 0;
+ inode->i_mtime.tv_sec = attr->mtime;
+ inode->i_mtime.tv_nsec = 0;
+ inode->i_ctime.tv_sec = attr->ctime;
+ inode->i_ctime.tv_nsec = 0;
+#else
inode->i_atime = attr->atime;
inode->i_mtime = attr->mtime;
inode->i_ctime = attr->ctime;
+#endif
}
static void fuse_init_inode(struct inode *inode, struct fuse_attr *attr)
@@ -114,7 +128,7 @@
return out.h.error;
}
-static struct dentry *fuse_lookup(struct inode *dir, struct dentry *entry)
+static struct dentry *_fuse_lookup(struct inode *dir, struct dentry *entry)
{
int ret;
struct fuse_lookup_out outarg;
@@ -150,8 +164,8 @@
/* create needs to return a positive entry, so this is actually an
mknod+lookup */
-static int fuse_mknod(struct inode *dir, struct dentry *entry, int mode,
- int rdev)
+static int _fuse_mknod(struct inode *dir, struct dentry *entry, int mode,
+ dev_t rdev)
{
struct fuse_conn *fc = INO_FC(dir);
struct fuse_in in = FUSE_IN_INIT;
@@ -199,10 +213,9 @@
return 0;
}
-
-static int fuse_create(struct inode *dir, struct dentry *entry, int mode)
+static int _fuse_create(struct inode *dir, struct dentry *entry, int mode)
{
- return fuse_mknod(dir, entry, mode, 0);
+ return _fuse_mknod(dir, entry, mode, 0);
}
static int fuse_mkdir(struct inode *dir, struct dentry *entry, int mode)
@@ -323,7 +336,7 @@
}
-int fuse_getattr(struct inode *inode)
+int fuse_do_getattr(struct inode *inode)
{
struct fuse_conn *fc = INO_FC(inode);
struct fuse_in in = FUSE_IN_INIT;
@@ -349,17 +362,16 @@
struct fuse_conn *fc = INO_FC(inode);
if(inode->i_ino == FUSE_ROOT_INO) {
- if(!(fc->flags & FUSE_ALLOW_OTHER)
- && current->fsuid != fc->uid)
+ if(!(fc->flags & FUSE_ALLOW_OTHER) &&
+ current->fsuid != fc->uid)
return -EACCES;
- }
- else if(time_before_eq(jiffies, entry->d_time + FUSE_REVALIDATE_TIME))
+ } else if(time_before_eq(jiffies, entry->d_time + FUSE_REVALIDATE_TIME))
return 0;
- return fuse_getattr(inode);
+ return fuse_do_getattr(inode);
}
-static int fuse_permission(struct inode *inode, int mask)
+static int _fuse_permission(struct inode *inode, int mask)
{
struct fuse_conn *fc = INO_FC(inode);
@@ -373,7 +385,7 @@
node will at first have no permissions */
if(err == -EACCES) {
- err = fuse_getattr(inode);
+ err = fuse_do_getattr(inode);
if(!err)
err = vfs_permission(inode, mask);
}
@@ -393,7 +405,6 @@
return 0;
}
-
static int parse_dirfile(char *buf, size_t nbytes, struct file *file,
void *dstbuf, filldir_t filldir)
{
@@ -563,8 +574,13 @@
/* You can only _set_ these together (they may change by themselves) */
if((ivalid & (ATTR_ATIME | ATTR_MTIME)) == (ATTR_ATIME | ATTR_MTIME)) {
fvalid |= FATTR_UTIME;
+#ifdef KERNEL_2_6
+ fattr->atime = iattr->ia_atime.tv_sec;
+ fattr->mtime = iattr->ia_mtime.tv_sec;
+#else
fattr->atime = iattr->ia_atime;
fattr->mtime = iattr->ia_mtime;
+#endif
}
return fvalid;
@@ -602,7 +618,7 @@
return out.h.error;
}
-static int fuse_dentry_revalidate(struct dentry *entry, int flags)
+static int _fuse_dentry_revalidate(struct dentry *entry)
{
if(!entry->d_inode)
return 0;
@@ -627,6 +643,62 @@
return 1;
}
+#ifdef KERNEL_2_6
+
+#define fuse_mknod _fuse_mknod
+
+static int fuse_getattr(struct vfsmount *mnt, struct dentry *entry,
+ struct kstat *stat)
+{
+ struct inode *inode = entry->d_inode;
+ int err = fuse_revalidate(entry);
+ if(!err)
+ generic_fillattr(inode, stat);
+
+ return err;
+}
+
+static struct dentry *fuse_lookup(struct inode *dir, struct dentry *entry,
+ struct nameidata *nd)
+{
+ return _fuse_lookup(dir, entry);
+}
+
+static int fuse_create(struct inode *dir, struct dentry *entry, int mode,
+ struct nameidata *nd)
+{
+ return _fuse_create(dir, entry, mode);
+}
+
+static int fuse_permission(struct inode *inode, int mask,
+ struct nameidata *nd)
+{
+ return _fuse_permission(inode, mask);
+}
+
+static int fuse_dentry_revalidate(struct dentry *entry, struct nameidata *nd)
+{
+ return _fuse_dentry_revalidate(entry);
+}
+#else /* KERNEL_2_6 */
+
+#define fuse_lookup _fuse_lookup
+#define fuse_create _fuse_create
+#define fuse_permission _fuse_permission
+
+static int fuse_mknod(struct inode *dir, struct dentry *entry, int mode,
+ int rdev)
+{
+ return fuse_mknod(dir, entry, mode, rdev);
+}
+
+static int fuse_dentry_revalidate(struct dentry *entry, int flags)
+{
+ return _fuse_dentry_revalidate(entry);
+}
+#endif /* KERNEL_2_6 */
+
+
static struct inode_operations fuse_dir_inode_operations =
{
lookup: fuse_lookup,
@@ -640,7 +712,11 @@
link: fuse_link,
setattr: fuse_setattr,
permission: fuse_permission,
+#ifdef KERNEL_2_6
+ getattr: fuse_getattr,
+#else
revalidate: fuse_revalidate,
+#endif
};
static struct file_operations fuse_dir_operations = {
@@ -653,7 +729,11 @@
static struct inode_operations fuse_file_inode_operations = {
setattr: fuse_setattr,
permission: fuse_permission,
+#ifdef KERNEL_2_6
+ getattr: fuse_getattr,
+#else
revalidate: fuse_revalidate,
+#endif
};
static struct inode_operations fuse_symlink_inode_operations =
@@ -661,7 +741,11 @@
setattr: fuse_setattr,
readlink: fuse_readlink,
follow_link: fuse_follow_link,
+#ifdef KERNEL_2_6
+ getattr: fuse_getattr,
+#else
revalidate: fuse_revalidate,
+#endif
};
static struct dentry_operations fuse_dentry_opertations = {
diff --git a/kernel/file.c b/kernel/file.c
index 11e7bc0..184f938 100644
--- a/kernel/file.c
+++ b/kernel/file.c
@@ -9,6 +9,13 @@
#include <linux/pagemap.h>
#include <linux/slab.h>
+#ifdef KERNEL_2_6
+#include <linux/backing-dev.h>
+#endif
+
+#ifndef KERNEL_2_6
+#define PageUptodate(page) Page_Uptodate(page)
+#endif
static int fuse_open(struct inode *inode, struct file *file)
{
@@ -20,7 +27,7 @@
/* If opening the root node, no lookup has been performed on
it, so the attributes must be refreshed */
if(inode->i_ino == FUSE_ROOT_INO) {
- int err = fuse_getattr(inode);
+ int err = fuse_do_getattr(inode);
if(err)
return err;
}
@@ -34,8 +41,13 @@
in.args[0].size = sizeof(inarg);
in.args[0].value = &inarg;
request_send(fc, &in, &out);
- if(!out.h.error && !(fc->flags & FUSE_KERNEL_CACHE))
+ if(!out.h.error && !(fc->flags & FUSE_KERNEL_CACHE)) {
+#ifdef KERNEL_2_6
+ invalidate_inode_pages(inode->i_mapping);
+#else
invalidate_inode_pages(inode);
+#endif
+ }
return out.h.error;
}
@@ -126,7 +138,7 @@
}
kunmap(page);
- UnlockPage(page);
+ unlock_page(page);
return out.h.error;
}
@@ -147,7 +159,7 @@
if (!page)
return 0;
- if (!Page_Uptodate(page)) {
+ if (!PageUptodate(page)) {
page_cache_release(page);
return 0;
}
@@ -182,7 +194,7 @@
if (!page)
return -1;
- if (!Page_Uptodate(page)) {
+ if (!PageUptodate(page)) {
buffer = kmap(page);
memcpy(buffer, bl_buf + i * PAGE_CACHE_SIZE,
PAGE_CACHE_SIZE);
@@ -190,7 +202,7 @@
kunmap(page);
}
- UnlockPage(page);
+ unlock_page(page);
page_cache_release(page);
}
@@ -296,8 +308,11 @@
return out.h.error;
}
-
+#ifdef KERNEL_2_6
+static int fuse_writepage(struct page *page, struct writeback_control *wbc)
+#else
static int fuse_writepage(struct page *page)
+#endif
{
struct inode *inode = page->mapping->host;
unsigned count;
@@ -316,7 +331,7 @@
}
err = write_buffer(inode, page, 0, count);
out:
- UnlockPage(page);
+ unlock_page(page);
return 0;
}
@@ -363,6 +378,9 @@
{
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;
+#endif
}
/*
diff --git a/kernel/fuse_i.h b/kernel/fuse_i.h
index 5a4a8b7..a667176 100644
--- a/kernel/fuse_i.h
+++ b/kernel/fuse_i.h
@@ -16,13 +16,26 @@
#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>
+/** Read combining parameters */
+#define FUSE_BLOCK_SHIFT 16
+#define FUSE_BLOCK_SIZE 65536
+#define FUSE_BLOCK_MASK 0xffff0000
+
#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.
@@ -122,8 +135,12 @@
wait_queue_head_t waitq;
};
-
-#define INO_FC(inode) ((struct fuse_conn *) (inode)->i_sb->u.generic_sbp)
+#ifdef KERNEL_2_6
+#define SB_FC(sb) ((struct fuse_conn *) (sb)->s_fs_info)
+#else
+#define SB_FC(sb) ((struct fuse_conn *) (sb)->u.generic_sbp)
+#endif
+#define INO_FC(inode) SB_FC((inode)->i_sb)
#define DEV_FC(file) ((struct fuse_conn *) (file)->private_data)
@@ -191,7 +208,7 @@
/**
* Get the attributes of a file
*/
-int fuse_getattr(struct inode *inode);
+int fuse_do_getattr(struct inode *inode);
/*
* Local Variables:
diff --git a/kernel/inode.c b/kernel/inode.c
index cd7fbc4..55d381c 100644
--- a/kernel/inode.c
+++ b/kernel/inode.c
@@ -13,9 +13,16 @@
#include <linux/slab.h>
#include <linux/file.h>
#include <linux/proc_fs.h>
+#ifdef KERNEL_2_6
+#include <linux/statfs.h>
+#endif
#define FUSE_SUPER_MAGIC 0x65735546
+#ifndef KERNEL_2_6
+#define kstatfs statfs
+#endif
+
static void fuse_read_inode(struct inode *inode)
{
/* No op */
@@ -58,7 +65,7 @@
static void fuse_put_super(struct super_block *sb)
{
- struct fuse_conn *fc = sb->u.generic_sbp;
+ struct fuse_conn *fc = SB_FC(sb);
spin_lock(&fuse_lock);
fc->sb = NULL;
@@ -67,11 +74,11 @@
/* Flush all readers on this fs */
wake_up_all(&fc->waitq);
fuse_release_conn(fc);
- sb->u.generic_sbp = NULL;
+ SB_FC(sb) = NULL;
spin_unlock(&fuse_lock);
}
-static void convert_fuse_statfs(struct statfs *stbuf, struct fuse_kstatfs *attr)
+static void convert_fuse_statfs(struct kstatfs *stbuf, struct fuse_kstatfs *attr)
{
stbuf->f_type = FUSE_SUPER_MAGIC;
stbuf->f_bsize = attr->block_size;
@@ -85,9 +92,9 @@
stbuf->f_namelen = attr->namelen;
}
-static int fuse_statfs(struct super_block *sb, struct statfs *st)
+static int fuse_statfs(struct super_block *sb, struct kstatfs *buf)
{
- struct fuse_conn *fc = sb->u.generic_sbp;
+ struct fuse_conn *fc = SB_FC(sb);
struct fuse_in in = FUSE_IN_INIT;
struct fuse_out out = FUSE_OUT_INIT;
struct fuse_statfs_out outarg;
@@ -99,7 +106,7 @@
out.args[0].value = &outarg;
request_send(fc, &in, &out);
if(!out.h.error)
- convert_fuse_statfs(st,&outarg.st);
+ convert_fuse_statfs(buf, &outarg.st);
return out.h.error;
}
@@ -155,8 +162,7 @@
return fuse_iget(sb, 1, &attr, 0);
}
-static struct super_block *fuse_read_super(struct super_block *sb,
- void *data, int silent)
+static int fuse_read_super(struct super_block *sb, void *data, int silent)
{
struct fuse_conn *fc;
struct inode *root;
@@ -170,7 +176,7 @@
root = get_root_inode(sb, d->rootmode);
if(root == NULL) {
printk("fuse_read_super: failed to get root inode\n");
- return NULL;
+ return -EINVAL;
}
spin_lock(&fuse_lock);
@@ -183,7 +189,7 @@
goto err;
}
- sb->u.generic_sbp = fc;
+ SB_FC(sb) = fc;
sb->s_root = d_alloc_root(root);
if(!sb->s_root)
goto err;
@@ -193,16 +199,41 @@
fc->uid = d->uid;
spin_unlock(&fuse_lock);
- return sb;
+ return 0;
err:
spin_unlock(&fuse_lock);
iput(root);
- return NULL;
+ return -EINVAL;
}
+#ifdef KERNEL_2_6
+static struct super_block *fuse_get_sb(struct file_system_type *fs_type,
+ int flags, const char *dev_name, void *raw_data)
+{
+ return get_sb_nodev(fs_type, flags, raw_data, fuse_read_super);
+}
-static DECLARE_FSTYPE(fuse_fs_type, "fuse", fuse_read_super, 0);
+static struct file_system_type fuse_fs_type = {
+ .owner = THIS_MODULE,
+ .name = "fuse",
+ .get_sb = fuse_get_sb,
+ .kill_sb = kill_anon_super,
+ .fs_flags = 0
+};
+#else
+static struct super_block *fuse_read_super_compat(struct super_block *sb,
+ void *data, int silent)
+{
+ int err = fuse_read_super(sb, data, silent);
+ if(err)
+ return NULL;
+ else
+ return sb;
+}
+
+static DECLARE_FSTYPE(fuse_fs_type, "fuse", fuse_read_super_compat, 0);
+#endif
int fuse_fs_init()
{
diff --git a/kernel/util.c b/kernel/util.c
index ecf23ce..7296517 100644
--- a/kernel/util.c
+++ b/kernel/util.c
@@ -8,11 +8,11 @@
#include "fuse_i.h"
+#include <linux/init.h>
#include <linux/slab.h>
MODULE_AUTHOR("Miklos Szeredi <mszeredi@inf.bme.hu>");
MODULE_DESCRIPTION("Filesystem in Userspace");
-
#ifdef MODULE_LICENSE
MODULE_LICENSE("GPL");
#endif
@@ -27,7 +27,7 @@
}
}
-int init_module(void)
+int __init fuse_init(void)
{
int res;
@@ -49,14 +49,17 @@
return res;
}
-void cleanup_module(void)
+void __exit fuse_exit(void)
{
- printk(KERN_DEBUG "fuse cleanup\n");
+ printk(KERN_DEBUG "fuse exit\n");
fuse_fs_cleanup();
fuse_dev_cleanup();
}
+module_init(fuse_init);
+module_exit(fuse_exit);
+
/*
* Local Variables:
* indent-tabs-mode: t