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