diff -ruN linux-2.6.21.orig/fs/fuse/control.c linux-2.6.21/fs/fuse/control.c
--- linux-2.6.21.orig/fs/fuse/control.c	2007-04-30 20:31:05.000000000 +0200
+++ linux-2.6.21/fs/fuse/control.c	2007-04-30 21:55:38.000000000 +0200
@@ -59,12 +59,12 @@
 	return simple_read_from_buffer(buf, len, ppos, tmp, size);
 }
 
-static const struct file_operations fuse_ctl_abort_ops = {
+static struct file_operations fuse_ctl_abort_ops = {
 	.open = nonseekable_open,
 	.write = fuse_conn_abort_write,
 };
 
-static const struct file_operations fuse_ctl_waiting_ops = {
+static struct file_operations fuse_ctl_waiting_ops = {
 	.open = nonseekable_open,
 	.read = fuse_conn_waiting_read,
 };
diff -ruN linux-2.6.21.orig/fs/fuse/dev.c linux-2.6.21/fs/fuse/dev.c
--- linux-2.6.21.orig/fs/fuse/dev.c	2007-04-30 20:31:05.000000000 +0200
+++ linux-2.6.21/fs/fuse/dev.c	2007-04-30 21:55:38.000000000 +0200
@@ -17,7 +17,9 @@
 #include <linux/file.h>
 #include <linux/slab.h>
 
+#ifdef MODULE_ALIAS_MISCDEV
 MODULE_ALIAS_MISCDEV(FUSE_MINOR);
+#endif
 
 static struct kmem_cache *fuse_req_cachep;
 
@@ -212,7 +214,6 @@
  * Called with fc->lock, unlocks it
  */
 static void request_end(struct fuse_conn *fc, struct fuse_req *req)
-	__releases(fc->lock)
 {
 	void (*end) (struct fuse_conn *, struct fuse_req *) = req->end;
 	req->end = NULL;
@@ -482,6 +483,9 @@
 {
 	unsigned long offset;
 	int err;
+#ifdef DCACHE_BUG
+	struct vm_area_struct *vma;
+#endif
 
 	unlock_request(cs->fc, cs->req);
 	fuse_copy_finish(cs);
@@ -493,14 +497,22 @@
 		cs->nr_segs --;
 	}
 	down_read(&current->mm->mmap_sem);
+#ifndef DCACHE_BUG
 	err = get_user_pages(current, current->mm, cs->addr, 1, cs->write, 0,
 			     &cs->pg, NULL);
+#else
+	err = get_user_pages(current, current->mm, cs->addr, 1, cs->write, 0,
+			     &cs->pg, &vma);
+#endif
 	up_read(&current->mm->mmap_sem);
 	if (err < 0)
 		return err;
 	BUG_ON(err != 1);
 	offset = cs->addr % PAGE_SIZE;
 	cs->mapaddr = kmap_atomic(cs->pg, KM_USER0);
+#ifdef DCACHE_BUG
+	flush_cache_page(vma, cs->addr, page_to_pfn(cs->pg));
+#endif
 	cs->buf = cs->mapaddr + offset;
 	cs->len = min(PAGE_SIZE - offset, cs->seglen);
 	cs->seglen -= cs->len;
@@ -641,7 +653,6 @@
  */
 static int fuse_read_interrupt(struct fuse_conn *fc, struct fuse_req *req,
 			       const struct iovec *iov, unsigned long nr_segs)
-	__releases(fc->lock)
 {
 	struct fuse_copy_state cs;
 	struct fuse_in_header ih;
@@ -680,15 +691,14 @@
  * request_end().  Otherwise add it to the processing list, and set
  * the 'sent' flag.
  */
-static ssize_t fuse_dev_read(struct kiocb *iocb, const struct iovec *iov,
-			      unsigned long nr_segs, loff_t pos)
+static ssize_t fuse_dev_readv(struct file *file, const struct iovec *iov,
+			      unsigned long nr_segs, loff_t *off)
 {
 	int err;
 	struct fuse_req *req;
 	struct fuse_in *in;
 	struct fuse_copy_state cs;
 	unsigned reqsize;
-	struct file *file = iocb->ki_filp;
 	struct fuse_conn *fc = fuse_get_conn(file);
 	if (!fc)
 		return -EPERM;
@@ -762,6 +772,12 @@
 	return err;
 }
 
+static ssize_t fuse_dev_read(struct kiocb *iocb, const struct iovec *iov,
+			     unsigned long nr_segs, loff_t pos)
+{
+	return fuse_dev_readv(iocb->ki_filp, iov, nr_segs, &pos);
+}
+
 /* Look up request on processing list by unique ID */
 static struct fuse_req *request_find(struct fuse_conn *fc, u64 unique)
 {
@@ -806,15 +822,15 @@
  * it from the list and copy the rest of the buffer to the request.
  * The request is finished by calling request_end()
  */
-static ssize_t fuse_dev_write(struct kiocb *iocb, const struct iovec *iov,
-			       unsigned long nr_segs, loff_t pos)
+static ssize_t fuse_dev_writev(struct file *file, const struct iovec *iov,
+			       unsigned long nr_segs, loff_t *off)
 {
 	int err;
 	unsigned nbytes = iov_length(iov, nr_segs);
 	struct fuse_req *req;
 	struct fuse_out_header oh;
 	struct fuse_copy_state cs;
-	struct fuse_conn *fc = fuse_get_conn(iocb->ki_filp);
+	struct fuse_conn *fc = fuse_get_conn(file);
 	if (!fc)
 		return -EPERM;
 
@@ -890,6 +906,12 @@
 	return err;
 }
 
+static ssize_t fuse_dev_write(struct kiocb *iocb, const struct iovec *iov,
+			      unsigned long nr_segs, loff_t pos)
+{
+	return fuse_dev_writev(iocb->ki_filp, iov, nr_segs, &pos);
+}
+
 static unsigned fuse_dev_poll(struct file *file, poll_table *wait)
 {
 	unsigned mask = POLLOUT | POLLWRNORM;
@@ -1021,7 +1043,7 @@
 	return fasync_helper(fd, file, on, &fc->fasync);
 }
 
-const struct file_operations fuse_dev_operations = {
+struct file_operations fuse_dev_operations = {
 	.owner		= THIS_MODULE,
 	.llseek		= no_llseek,
 	.read		= do_sync_read,
diff -ruN linux-2.6.21.orig/fs/fuse/dir.c linux-2.6.21/fs/fuse/dir.c
--- linux-2.6.21.orig/fs/fuse/dir.c	2007-04-30 20:31:05.000000000 +0200
+++ linux-2.6.21/fs/fuse/dir.c	2007-04-30 21:55:38.000000000 +0200
@@ -195,7 +195,7 @@
 	.d_revalidate	= fuse_dentry_revalidate,
 };
 
-int fuse_valid_type(int m)
+static int valid_mode(int m)
 {
 	return S_ISREG(m) || S_ISDIR(m) || S_ISLNK(m) || S_ISCHR(m) ||
 		S_ISBLK(m) || S_ISFIFO(m) || S_ISSOCK(m);
@@ -205,18 +205,19 @@
  * Add a directory inode to a dentry, ensuring that no other dentry
  * refers to this inode.  Called with fc->inst_mutex.
  */
-static int fuse_d_add_directory(struct dentry *entry, struct inode *inode)
+static struct dentry *fuse_d_add_directory(struct dentry *entry,
+					   struct inode *inode)
 {
 	struct dentry *alias = d_find_alias(inode);
-	if (alias) {
+	if (alias && !(alias->d_flags & DCACHE_DISCONNECTED)) {
 		/* This tries to shrink the subtree below alias */
 		fuse_invalidate_entry(alias);
 		dput(alias);
 		if (!list_empty(&inode->i_dentry))
-			return -EBUSY;
-	}
-	d_add(entry, inode);
-	return 0;
+			return ERR_PTR(-EBUSY);
+	} else
+		dput(alias);
+	return d_splice_alias(inode, entry);
 }
 
 static struct dentry *fuse_lookup(struct inode *dir, struct dentry *entry,
@@ -225,6 +226,7 @@
 	int err;
 	struct fuse_entry_out outarg;
 	struct inode *inode = NULL;
+	struct dentry *newent;
 	struct fuse_conn *fc = get_fuse_conn(dir);
 	struct fuse_req *req;
 	struct fuse_req *forget_req;
@@ -248,8 +250,7 @@
 	fuse_put_request(fc, req);
 	/* Zero nodeid is same as -ENOENT, but with valid timeout */
 	if (!err && outarg.nodeid &&
-	    (invalid_nodeid(outarg.nodeid) ||
-	     !fuse_valid_type(outarg.attr.mode)))
+	    (invalid_nodeid(outarg.nodeid) || !valid_mode(outarg.attr.mode)))
 		err = -EIO;
 	if (!err && outarg.nodeid) {
 		inode = fuse_iget(dir->i_sb, outarg.nodeid, outarg.generation,
@@ -265,23 +266,25 @@
 
 	if (inode && S_ISDIR(inode->i_mode)) {
 		mutex_lock(&fc->inst_mutex);
-		err = fuse_d_add_directory(entry, inode);
+		newent = fuse_d_add_directory(entry, inode);
 		mutex_unlock(&fc->inst_mutex);
-		if (err) {
+		if (IS_ERR(newent)) {
 			iput(inode);
-			return ERR_PTR(err);
+			return newent;
 		}
 	} else
-		d_add(entry, inode);
+		newent = d_splice_alias(inode, entry);
 
+	entry = newent ? newent : entry;
 	entry->d_op = &fuse_dentry_operations;
 	if (!err)
 		fuse_change_timeout(entry, &outarg);
 	else
 		fuse_invalidate_entry_cache(entry);
-	return NULL;
+	return newent;
 }
 
+#ifdef HAVE_LOOKUP_INSTANTIATE_FILP
 /*
  * Synchronous release for the case when something goes wrong in CREATE_OPEN
  */
@@ -392,6 +395,7 @@
 	fuse_put_request(fc, forget_req);
 	return err;
 }
+#endif
 
 /*
  * Code shared between mknod, mkdir, symlink and link
@@ -485,12 +489,14 @@
 static int fuse_create(struct inode *dir, struct dentry *entry, int mode,
 		       struct nameidata *nd)
 {
+#ifdef HAVE_LOOKUP_INSTANTIATE_FILP
 	if (nd && (nd->flags & LOOKUP_OPEN)) {
 		int err = fuse_create_open(dir, entry, mode, nd);
 		if (err != -ENOSYS)
 			return err;
 		/* Fall back on mknod */
 	}
+#endif
 	return fuse_mknod(dir, entry, mode, 0);
 }
 
@@ -818,9 +824,13 @@
 		return err;
 	} else {
 		int mode = inode->i_mode;
+
 		if ((mask & MAY_EXEC) && !S_ISDIR(mode) && !(mode & S_IXUGO))
 			return -EACCES;
 
+#ifndef LOOKUP_CHDIR
+#define LOOKUP_CHDIR 0
+#endif
 		if (nd && (nd->flags & (LOOKUP_ACCESS | LOOKUP_CHDIR)))
 			return fuse_access(inode, mask);
 		return 0;
@@ -857,7 +867,7 @@
 	int err;
 	size_t nbytes;
 	struct page *page;
-	struct inode *inode = file->f_path.dentry->d_inode;
+	struct inode *inode = file->f_dentry->d_inode;
 	struct fuse_conn *fc = get_fuse_conn(inode);
 	struct fuse_req *req;
 
@@ -973,11 +983,13 @@
 		arg->atime = iattr->ia_atime.tv_sec;
 		arg->mtime = iattr->ia_mtime.tv_sec;
 	}
+#ifdef ATTR_FILE
 	if (ivalid & ATTR_FILE) {
 		struct fuse_file *ff = iattr->ia_file->private_data;
 		arg->valid |= FATTR_FH;
 		arg->fh = ff->fh;
 	}
+#endif
 }
 
 static void fuse_vmtruncate(struct inode *inode, loff_t offset)
@@ -1028,6 +1040,7 @@
 		if (IS_SWAPFILE(inode))
 			return -ETXTBSY;
 		limit = current->signal->rlim[RLIMIT_FSIZE].rlim_cur;
+
 		if (limit != RLIM_INFINITY && attr->ia_size > (loff_t) limit) {
 			send_sig(SIGXFSZ, current, 0);
 			return -EFBIG;
@@ -1040,6 +1053,9 @@
 
 	memset(&inarg, 0, sizeof(inarg));
 	iattr_to_fattr(attr, &inarg);
+	/* Defend against future expansion of ATTR_FILE use */
+	if (S_ISDIR(inode->i_mode))
+		inarg.valid &= ~FATTR_FH;
 	req->in.h.opcode = FUSE_SETATTR;
 	req->in.h.nodeid = get_node_id(inode);
 	req->in.numargs = 1;
@@ -1074,6 +1090,8 @@
 	struct inode *inode = entry->d_inode;
 	int err = fuse_revalidate(entry);
 	if (!err)
+		/* FIXME: may want specialized function because of
+		   st_blksize on block devices on 2.6.19+ */
 		generic_fillattr(inode, stat);
 
 	return err;
@@ -1243,7 +1261,7 @@
 	return err;
 }
 
-static const struct inode_operations fuse_dir_inode_operations = {
+static struct inode_operations fuse_dir_inode_operations = {
 	.lookup		= fuse_lookup,
 	.mkdir		= fuse_mkdir,
 	.symlink	= fuse_symlink,
@@ -1262,7 +1280,7 @@
 	.removexattr	= fuse_removexattr,
 };
 
-static const struct file_operations fuse_dir_operations = {
+static struct file_operations fuse_dir_operations = {
 	.llseek		= generic_file_llseek,
 	.read		= generic_read_dir,
 	.readdir	= fuse_readdir,
@@ -1271,7 +1289,7 @@
 	.fsync		= fuse_dir_fsync,
 };
 
-static const struct inode_operations fuse_common_inode_operations = {
+static struct inode_operations fuse_common_inode_operations = {
 	.setattr	= fuse_setattr,
 	.permission	= fuse_permission,
 	.getattr	= fuse_getattr,
@@ -1281,7 +1299,7 @@
 	.removexattr	= fuse_removexattr,
 };
 
-static const struct inode_operations fuse_symlink_inode_operations = {
+static struct inode_operations fuse_symlink_inode_operations = {
 	.setattr	= fuse_setattr,
 	.follow_link	= fuse_follow_link,
 	.put_link	= fuse_put_link,
diff -ruN linux-2.6.21.orig/fs/fuse/file.c linux-2.6.21/fs/fuse/file.c
--- linux-2.6.21.orig/fs/fuse/file.c	2007-04-30 20:31:05.000000000 +0200
+++ linux-2.6.21/fs/fuse/file.c	2007-04-30 21:55:38.000000000 +0200
@@ -12,7 +12,7 @@
 #include <linux/slab.h>
 #include <linux/kernel.h>
 
-static const struct file_operations fuse_direct_io_file_operations;
+static struct file_operations fuse_direct_io_file_operations;
 
 static int fuse_send_open(struct inode *inode, struct file *file, int isdir,
 			  struct fuse_open_out *outargp)
@@ -141,8 +141,8 @@
 					isdir ? FUSE_RELEASEDIR : FUSE_RELEASE);
 
 		/* Hold vfsmount and dentry until release is finished */
-		req->vfsmount = mntget(file->f_path.mnt);
-		req->dentry = dget(file->f_path.dentry);
+		req->vfsmount = mntget(file->f_vfsmnt);
+		req->dentry = dget(file->f_dentry);
 		request_send_background(fc, req);
 	}
 
@@ -184,7 +184,7 @@
 
 static int fuse_flush(struct file *file, fl_owner_t id)
 {
-	struct inode *inode = file->f_path.dentry->d_inode;
+	struct inode *inode = file->f_dentry->d_inode;
 	struct fuse_conn *fc = get_fuse_conn(inode);
 	struct fuse_file *ff = file->private_data;
 	struct fuse_req *req;
@@ -370,21 +370,32 @@
 	struct fuse_req *req = data->req;
 	struct inode *inode = data->inode;
 	struct fuse_conn *fc = get_fuse_conn(inode);
+	int err;
 
-	if (req->num_pages &&
+	if (req && req->num_pages &&
 	    (req->num_pages == FUSE_MAX_PAGES_PER_REQ ||
 	     (req->num_pages + 1) * PAGE_CACHE_SIZE > fc->max_read ||
 	     req->pages[req->num_pages - 1]->index + 1 != page->index)) {
 		fuse_send_readpages(req, data->file, inode);
+		req = NULL;
+	}
+	if (!req) {
+		err = -EIO;
+		if (is_bad_inode(inode))
+			goto out_unlock_page;
+
 		data->req = req = fuse_get_req(fc);
-		if (IS_ERR(req)) {
-			unlock_page(page);
-			return PTR_ERR(req);
-		}
+		err = PTR_ERR(req);
+		if (IS_ERR(req))
+			goto out_unlock_page;
 	}
 	req->pages[req->num_pages] = page;
 	req->num_pages ++;
 	return 0;
+
+ out_unlock_page:
+	unlock_page(page);
+	return err;
 }
 
 static int fuse_readpages(struct file *file, struct address_space *mapping,
@@ -395,25 +406,17 @@
 	struct fuse_readpages_data data;
 	int err;
 
-	err = -EIO;
-	if (is_bad_inode(inode))
-		goto out;
-
 	data.file = file;
 	data.inode = inode;
-	data.req = fuse_get_req(fc);
-	err = PTR_ERR(data.req);
-	if (IS_ERR(data.req))
-		goto out;
+	data.req = NULL;
 
 	err = read_cache_pages(mapping, pages, fuse_readpages_fill, &data);
-	if (!err) {
+	if (!err && data.req) {
 		if (data.req->num_pages)
 			fuse_send_readpages(data.req, file, inode);
 		else
 			fuse_put_request(fc, data.req);
 	}
-out:
 	return err;
 }
 
@@ -515,7 +518,8 @@
 
 	nbytes = min(nbytes, (unsigned) FUSE_MAX_PAGES_PER_REQ << PAGE_SHIFT);
 	npages = (nbytes + offset + PAGE_SIZE - 1) >> PAGE_SHIFT;
-	npages = min(max(npages, 1), FUSE_MAX_PAGES_PER_REQ);
+	npages = max(npages, 1);
+	npages = min(npages, FUSE_MAX_PAGES_PER_REQ);
 	down_read(&current->mm->mmap_sem);
 	npages = get_user_pages(current, current->mm, user_addr, npages, write,
 				0, req->pages, NULL);
@@ -531,7 +535,7 @@
 static ssize_t fuse_direct_io(struct file *file, const char __user *buf,
 			      size_t count, loff_t *ppos, int write)
 {
-	struct inode *inode = file->f_path.dentry->d_inode;
+	struct inode *inode = file->f_dentry->d_inode;
 	struct fuse_conn *fc = get_fuse_conn(inode);
 	size_t nmax = write ? fc->max_write : fc->max_read;
 	loff_t pos = *ppos;
@@ -605,7 +609,7 @@
 static ssize_t fuse_direct_write(struct file *file, const char __user *buf,
 				 size_t count, loff_t *ppos)
 {
-	struct inode *inode = file->f_path.dentry->d_inode;
+	struct inode *inode = file->f_dentry->d_inode;
 	ssize_t res;
 	/* Don't allow parallel writes to the same file */
 	mutex_lock(&inode->i_mutex);
@@ -660,7 +664,7 @@
 static void fuse_lk_fill(struct fuse_req *req, struct file *file,
 			 const struct file_lock *fl, int opcode, pid_t pid)
 {
-	struct inode *inode = file->f_path.dentry->d_inode;
+	struct inode *inode = file->f_dentry->d_inode;
 	struct fuse_conn *fc = get_fuse_conn(inode);
 	struct fuse_file *ff = file->private_data;
 	struct fuse_lk_in *arg = &req->misc.lk_in;
@@ -680,7 +684,7 @@
 
 static int fuse_getlk(struct file *file, struct file_lock *fl)
 {
-	struct inode *inode = file->f_path.dentry->d_inode;
+	struct inode *inode = file->f_dentry->d_inode;
 	struct fuse_conn *fc = get_fuse_conn(inode);
 	struct fuse_req *req;
 	struct fuse_lk_out outarg;
@@ -705,7 +709,7 @@
 
 static int fuse_setlk(struct file *file, struct file_lock *fl)
 {
-	struct inode *inode = file->f_path.dentry->d_inode;
+	struct inode *inode = file->f_dentry->d_inode;
 	struct fuse_conn *fc = get_fuse_conn(inode);
 	struct fuse_req *req;
 	int opcode = (fl->fl_flags & FL_SLEEP) ? FUSE_SETLKW : FUSE_SETLK;
@@ -717,6 +721,7 @@
 		return 0;
 
 	req = fuse_get_req(fc);
+
 	if (IS_ERR(req))
 		return PTR_ERR(req);
 
@@ -732,7 +737,7 @@
 
 static int fuse_file_lock(struct file *file, int cmd, struct file_lock *fl)
 {
-	struct inode *inode = file->f_path.dentry->d_inode;
+	struct inode *inode = file->f_dentry->d_inode;
 	struct fuse_conn *fc = get_fuse_conn(inode);
 	int err;
 
@@ -788,7 +794,7 @@
 	return err ? 0 : outarg.block;
 }
 
-static const struct file_operations fuse_file_operations = {
+static struct file_operations fuse_file_operations = {
 	.llseek		= generic_file_llseek,
 	.read		= do_sync_read,
 	.aio_read	= generic_file_aio_read,
@@ -803,7 +809,7 @@
 	.sendfile	= generic_file_sendfile,
 };
 
-static const struct file_operations fuse_direct_io_file_operations = {
+static struct file_operations fuse_direct_io_file_operations = {
 	.llseek		= generic_file_llseek,
 	.read		= fuse_direct_read,
 	.write		= fuse_direct_write,
@@ -815,7 +821,7 @@
 	/* no mmap and sendfile */
 };
 
-static const struct address_space_operations fuse_file_aops  = {
+static struct address_space_operations fuse_file_aops  = {
 	.readpage	= fuse_readpage,
 	.prepare_write	= fuse_prepare_write,
 	.commit_write	= fuse_commit_write,
diff -ruN linux-2.6.21.orig/fs/fuse/fuse_i.h linux-2.6.21/fs/fuse/fuse_i.h
--- linux-2.6.21.orig/fs/fuse/fuse_i.h	2007-04-30 20:31:05.000000000 +0200
+++ linux-2.6.21/fs/fuse/fuse_i.h	2007-04-30 21:55:38.000000000 +0200
@@ -397,7 +397,7 @@
 }
 
 /** Device operations */
-extern const struct file_operations fuse_dev_operations;
+extern struct file_operations fuse_dev_operations;
 
 /**
  * Get a filled in inode
@@ -552,8 +552,3 @@
  * Remove connection from control filesystem
  */
 void fuse_ctl_remove_conn(struct fuse_conn *fc);
-
-/**
- * Is file type valid?
- */
-int fuse_valid_type(int m);
diff -ruN linux-2.6.21.orig/fs/fuse/inode.c linux-2.6.21/fs/fuse/inode.c
--- linux-2.6.21.orig/fs/fuse/inode.c	2007-04-30 20:31:05.000000000 +0200
+++ linux-2.6.21/fs/fuse/inode.c	2007-04-30 21:55:38.000000000 +0200
@@ -20,7 +20,9 @@
 
 MODULE_AUTHOR("Miklos Szeredi <miklos@szeredi.hu>");
 MODULE_DESCRIPTION("Filesystem in Userspace");
+#ifdef MODULE_LICENSE
 MODULE_LICENSE("GPL");
+#endif
 
 static struct kmem_cache *fuse_inode_cachep;
 struct list_head fuse_conn_list;
@@ -28,6 +30,9 @@
 
 #define FUSE_SUPER_MAGIC 0x65735546
 
+#ifndef MAX_LFS_FILESIZE
+#define MAX_LFS_FILESIZE (((u64)PAGE_CACHE_SIZE << (BITS_PER_LONG-1))-1)
+#endif
 struct fuse_mount_data {
 	int fd;
 	unsigned rootmode;
@@ -122,6 +127,9 @@
 	spin_lock(&fc->lock);
 	i_size_write(inode, attr->size);
 	spin_unlock(&fc->lock);
+#ifdef HAVE_I_BLKSIZE
+	inode->i_blksize = PAGE_CACHE_SIZE;
+#endif
 	inode->i_blocks  = attr->blocks;
 	inode->i_atime.tv_sec   = attr->atime;
 	inode->i_atime.tv_nsec  = attr->atimensec;
@@ -330,8 +338,6 @@
 		case OPT_ROOTMODE:
 			if (match_octal(&args[0], &value))
 				return 0;
-			if (!fuse_valid_type(value))
-				return 0;
 			d->rootmode = value;
 			d->rootmode_present = 1;
 			break;
@@ -447,8 +453,70 @@
 	attr.ino = FUSE_ROOT_ID;
 	return fuse_iget(sb, 1, 0, &attr);
 }
+#ifndef FUSE_MAINLINE
+static struct dentry *fuse_get_dentry(struct super_block *sb, void *vobjp)
+{
+	__u32 *objp = vobjp;
+	unsigned long nodeid = objp[0];
+	__u32 generation = objp[1];
+	struct inode *inode;
+	struct dentry *entry;
+
+	if (nodeid == 0)
+		return ERR_PTR(-ESTALE);
+
+	inode = ilookup5(sb, nodeid, fuse_inode_eq, &nodeid);
+	if (!inode)
+		return ERR_PTR(-ESTALE);
+	if (inode->i_generation != generation) {
+		iput(inode);
+		return ERR_PTR(-ESTALE);
+	}
+
+	entry = d_alloc_anon(inode);
+	if (!entry) {
+		iput(inode);
+		return ERR_PTR(-ENOMEM);
+	}
+
+	return entry;
+}
 
-static const struct super_operations fuse_super_operations = {
+static int fuse_encode_fh(struct dentry *dentry, __u32 *fh, int *max_len,
+			  int connectable)
+{
+	struct inode *inode = dentry->d_inode;
+	int len = *max_len;
+	int type = 1;
+
+	if (len < 2 || (connectable && len < 4))
+		return 255;
+
+	len = 2;
+	fh[0] = get_fuse_inode(inode)->nodeid;
+	fh[1] = inode->i_generation;
+	if (connectable && !S_ISDIR(inode->i_mode)) {
+		struct inode *parent;
+
+		spin_lock(&dentry->d_lock);
+		parent = dentry->d_parent->d_inode;
+		fh[2] = get_fuse_inode(parent)->nodeid;
+		fh[3] = parent->i_generation;
+		spin_unlock(&dentry->d_lock);
+		len = 4;
+		type = 2;
+	}
+	*max_len = len;
+	return type;
+}
+
+static struct export_operations fuse_export_operations = {
+	.get_dentry	= fuse_get_dentry,
+	.encode_fh      = fuse_encode_fh,
+};
+#endif
+
+static struct super_operations fuse_super_operations = {
 	.alloc_inode    = fuse_alloc_inode,
 	.destroy_inode  = fuse_destroy_inode,
 	.read_inode	= fuse_read_inode,
@@ -548,6 +616,9 @@
 	sb->s_magic = FUSE_SUPER_MAGIC;
 	sb->s_op = &fuse_super_operations;
 	sb->s_maxbytes = MAX_LFS_FILESIZE;
+#ifndef FUSE_MAINLINE
+	sb->s_export_op = &fuse_export_operations;
+#endif
 
 	file = fget(d.fd);
 	if (!file)
