never mind, here's my current patch against 1.1.3 (doesn't need
UNIONFS_MMAP, as uses it by default, I'd be interested if you see the
oops there as well).

the only difference there should be between this, and the version I
posted a few months ago is that I fixed a major bug in commit_write()
where the page would get set uptodate for any write, even if it was just
a partial page write (i.e. from 1k to 3k in the page, where 0-1k hadn't
been read in yet).  This "should" not cause any oopses, but could cause
programs to fail due to incorrect data in the page if read/written
weirdly.  I only hit this in practice when we restarted a checkpointed
session.

On Thu, 2006-05-11 at 05:25 -0400, Shaya Potter wrote:
> there's one major bug in it that I know of, which I reported and fixed in my 
> private tree. (and reported the fix)  besides that I've spent many hours 
> running with it, w/o experiencing a problem.
> 
> Please try w/ the patch I made against 1.1.3 if the cvs version are giving 
> you trouble.  I should create a patch of my fix after I wake up for real in a 
> few hours.
> 
> -----Original Message-----
> From: Klaus Knopper <[EMAIL PROTECTED]>
> Date: Thursday, May 11, 2006 3:31 am
> Subject: [Unionfs] UNIONFS_MMAP unstable
> 
> Hi,
> 
> On Tue, Mar 07, 2006 at 03:24:05PM -0500, Erez Zadok wrote:
>  We have done very little testing on it; it's highly experimental, but looks
>  promising as a starting point.  So I preferred to have at least _something_
>  available for people to try, and hopefully help us enhance and fix it (while
>  we're continuing to stabilize the rest of the code in preparation for a
>  first release).
>  
>  So, consider this a request for testing from those of you who feel
>  comfortable enough with the unionfs code, to try out UNIONFS_MMAP, find
>  what's missing/broken, and give us feedback (or patches :-)
> 
> Well, after using the current snapshot from 3.5.06 on Knoppix with
> -DUNIONFS_MMAP, Kernel 2.6.17-rc3-git17, I have to report that this is one of 
> the more unstable versions. I get various kernel oopses because of apparently 
> defective page caches after dpkg -i (too many different dmesg's to report 
> something reliable). Seems t be caused by mmap, but I'll have to retry 
> without -DUNIONFS_MMAP again today.
> 
> Also, the current snapshot doesn't compile with Kernel 2.6.17-rc3-git17 
> because of wrong calling of sync_page(). It should probably be
> block_sync_page(), but that's just a guess.
> 
> Btw, is anybody doing something about the "mv directory .." bug?
> 
> With kind regards
> -Klaus Knopper
> _______________________________________________
> unionfs mailing list
> [email protected]
> http://www.fsl.cs.sunysb.edu/mailman/listinfo/unionfs
> 
> 
> _______________________________________________
> unionfs mailing list
> [email protected]
> http://www.fsl.cs.sunysb.edu/mailman/listinfo/unionfs
diff -rNu /root/unionfs-1.1.3/Makefile unionfs-1.1.3-mmap/Makefile
--- /root/unionfs-1.1.3/Makefile	2006-02-20 22:47:06.000000000 +0000
+++ unionfs-1.1.3-mmap/Makefile	2006-03-02 03:28:56.000000000 +0000
@@ -36,7 +36,7 @@
 unionfs-objs := subr.o dentry.o file.o inode.o main.o super.o \
 	stale_inode.o branchman.o xattr.o rdstate.o copyup.o  \
 	dirhelper.o rename.o unlink.o lookup.o persistent_inode.o \
-	commonfops.o dirfops.o print.o malloc_debug.o
+	commonfops.o dirfops.o print.o malloc_debug.o mmap.o
 
 BINS	:=	unionctl uniondbg unionimap
 
diff -rNu /root/unionfs-1.1.3/copyup.c unionfs-1.1.3-mmap/copyup.c
--- /root/unionfs-1.1.3/copyup.c	2006-02-20 22:47:06.000000000 +0000
+++ unionfs-1.1.3-mmap/copyup.c	2006-03-02 16:10:22.000000000 +0000
@@ -373,6 +373,18 @@
 		set_fs(old_fs);
 		KFREE(buf);
 
+		/* SP: Now that we copied up the file, have to sync its data
+		 * as otherwise when we do a read_cache_page(), we'll possibly
+		 * read crap.
+		 *
+		 * another posisble solution would be in the address op code
+		 * would be to check the "lower" page to see if its dirty,
+		 * and if it's dirty, use it directl 
+		 */
+		if (!err) {
+			err = output_file->f_op->fsync(output_file, new_hidden_dentry, 0);
+		}
+
 		if (err) {
 			/* copyup failed, because we ran out of space or quota,
 			 * or something else happened so let's unlink; we don't
diff -rNu /root/unionfs-1.1.3/dentry.c unionfs-1.1.3-mmap/dentry.c
--- /root/unionfs-1.1.3/dentry.c	2006-02-20 22:47:06.000000000 +0000
+++ unionfs-1.1.3-mmap/dentry.c	2006-03-06 15:05:39.000000000 +0000
@@ -166,8 +166,22 @@
 
 	if (!dentry->d_inode)
 		valid = 0;
-	if (valid)
+	if (valid) {
+		//all besides fist_copy_attr_all is extra
+		struct inode * hidden_inode;
+		int index = itopd(dentry->d_inode)->b_start;
+		if (index < 0) {
+			printk("inode has invalid b_start\n");
+		}
+		hidden_inode = itopd(dentry->d_inode)->uii_inode[index];
+		if (hidden_inode) {
+			if ((atomic_read(&hidden_inode->i_count)) <= 0) {
+				printk("about to bug on itohi, as hidden_inode's i_count is <= 0\n");
+				printk("inode belong to dentry %s in %s\n", dentry->d_name.name, dentry->d_parent->d_name.name);
+			}
+		}
 		fist_copy_attr_all(dentry->d_inode, itohi(dentry->d_inode));
+	}
 
       out:
 	if (locked)
diff -rNu /root/unionfs-1.1.3/file.c unionfs-1.1.3-mmap/file.c
--- /root/unionfs-1.1.3/file.c	2006-02-20 22:47:06.000000000 +0000
+++ unionfs-1.1.3-mmap/file.c	2006-03-02 16:22:35.000000000 +0000
@@ -30,6 +30,8 @@
  * File Operations *
  *******************/
 
+/* SP: Disable unionfs_llseek, as use generic_file_llseek on upper file */
+#if 0
 static loff_t unionfs_llseek(struct file *file, loff_t offset, int origin)
 {
 	loff_t err;
@@ -68,42 +70,30 @@
 	print_exit_status((int)err);
 	return err;
 }
+#endif
 
-ssize_t unionfs_read(struct file * file, char __user * buf, size_t count,
-		     loff_t * ppos)
+ssize_t unionfs_read(struct file * file, char __user * buf, size_t count, loff_t * ppos)
 {
 	int err = -EINVAL;
-	struct file *hidden_file = NULL;
-	loff_t pos = *ppos;
 
 	print_entry_location();
 
 	if ((err = unionfs_file_revalidate(file, 0)))
 		goto out;
+		
+	err = generic_file_read(file, buf, count, ppos);
 
-	fist_print_file("entering read()", file);
-
-	hidden_file = ftohf(file);
-
-	if (!hidden_file->f_op || !hidden_file->f_op->read)
-		goto out;
-
-	err = hidden_file->f_op->read(hidden_file, buf, count, &pos);
-	*ppos = pos;
-	if (err >= 0) {
-		/* atime should also be updated for reads of size zero or more */
-		fist_copy_attr_atime(file->f_dentry->d_inode,
-				     hidden_file->f_dentry->d_inode);
-	}
-	memcpy(&(file->f_ra), &(hidden_file->f_ra),
-	       sizeof(struct file_ra_state));
+	if (err >= 0)
+		update_atime(itohi(file->f_dentry->d_inode)); 
 
-      out:
-	fist_print_file("leaving read()", file);
+	out:
+	
 	print_exit_status(err);
 	return err;
 }
 
+/* SP: Sendfile code not updated, but should be able to use 
+ * generic_file_sendfile, as it would use readpage, which we now have */
 #ifdef SUPPORT_BROKEN_LOSETUP
 static ssize_t unionfs_sendfile(struct file *file, loff_t * ppos,
 				size_t count, read_actor_t actor, void *target)
@@ -131,55 +121,18 @@
 }
 #endif
 
-/* this unionfs_write() does not modify data pages! */
-ssize_t unionfs_write(struct file * file, const char __user * buf, size_t count,
-		      loff_t * ppos)
+ssize_t unionfs_write(struct file * file, const char __user * buf, size_t count,loff_t * ppos)
 {
-	int err = -EINVAL;
-	struct file *hidden_file = NULL;
-	struct inode *inode;
-	struct inode *hidden_inode;
-	loff_t pos = *ppos;
-	int bstart, bend;
+	int err = 0;
 
 	print_entry_location();
 
 	if ((err = unionfs_file_revalidate(file, 1)))
 		goto out;
+	
+	err = generic_file_write(file, buf, count, ppos);
 
-	inode = file->f_dentry->d_inode;
-
-	bstart = fbstart(file);
-	bend = fbend(file);
-
-	BUG_ON(bstart == -1);
-
-	hidden_file = ftohf(file);
-	hidden_inode = hidden_file->f_dentry->d_inode;
-
-	if (!hidden_file->f_op || !hidden_file->f_op->write)
-		goto out;
-
-	/* adjust for append -- seek to the end of the file */
-	if (file->f_flags & O_APPEND)
-		pos = inode->i_size;
-
-	err = hidden_file->f_op->write(hidden_file, buf, count, &pos);
-
-	/*
-	 * copy ctime and mtime from lower layer attributes
-	 * atime is unchanged for both layers
-	 */
-	if (err >= 0)
-		fist_copy_attr_times(inode, hidden_inode);
-
-	*ppos = pos;
-
-	/* update this inode's size */
-	if (pos > inode->i_size)
-		inode->i_size = pos;
-
-      out:
+out:
 	print_exit_status(err);
 	return err;
 }
@@ -193,6 +146,10 @@
 	return err;
 }
 
+/* SP: disabled, unsure why even here in the first place, none of the in 
+ * kernel file systems have it
+ */
+#if 0
 static unsigned int unionfs_poll(struct file *file, poll_table * wait)
 {
 	unsigned int mask = DEFAULT_POLLMASK;
@@ -217,37 +174,37 @@
 	print_exit_status(mask);
 	return mask;
 }
+#endif
 
-/* FIST-LITE special version of mmap */
+/* SP: mmap code now maps upper file
+ * like old code, will only copyup at this point, it's possible to copyup
+ * in writepage(), but I haven't bothered with that, as only apt-get seem
+ * to want to write to a shared/write mapping
+ */
 static int unionfs_mmap(struct file *file, struct vm_area_struct *vma)
 {
-	int err = 0;
-	struct file *hidden_file = NULL;
-	int willwrite;
+        int err = 0;
+        int willwrite;
 
-	print_entry_location();
+        print_entry_location();
 
-	/* This might could be deferred to mmap's writepage. */
-	willwrite = ((vma->vm_flags | VM_SHARED | VM_WRITE) == vma->vm_flags);
-	if ((err = unionfs_file_revalidate(file, willwrite)))
-		goto out;
-
-	hidden_file = ftohf(file);
-
-	err = -ENODEV;
-	if (!hidden_file->f_op || !hidden_file->f_op->mmap)
-		goto out;
-
-	vma->vm_file = hidden_file;
-	err = hidden_file->f_op->mmap(hidden_file, vma);
-	get_file(hidden_file);	/* make sure it doesn't get freed on us */
-	fput(file);		/* no need to keep extra ref on ours */
+        /* This might could be deferred to mmap's writepage. */
+        willwrite = ((vma->vm_flags | VM_SHARED | VM_WRITE) == vma->vm_flags);
+        if ((err = unionfs_file_revalidate(file, willwrite)))
+                goto out;
+
+        err = generic_file_mmap(file, vma);
+        if (err) {
+                printk("unionfs_mmap: generic_file_mmap failed\n");
+        }
 
       out:
-	print_exit_status(err);
-	return err;
+        print_exit_status(err);
+        return err;
 }
 
+/* SP: disabled as use the generic file_fsync */
+#if 0
 static int unionfs_fsync(struct file *file, struct dentry *dentry, int datasync)
 {
 	int err;
@@ -273,7 +230,10 @@
 	print_exit_status(err);
 	return err;
 }
+#endif
 
+/* SP: disabled as none of the other in kernel fs's seem to use it */
+#if 0
 static int unionfs_fasync(int fd, struct file *file, int flag)
 {
 	int err = 0;
@@ -293,22 +253,29 @@
 	print_exit_status(err);
 	return err;
 }
+#endif
 
 struct file_operations unionfs_main_fops = {
-	.llseek = unionfs_llseek,
+	.llseek = generic_file_llseek,
 	.read = unionfs_read,
 	.write = unionfs_write,
 	.readdir = unionfs_file_readdir,
+#if 0
 	.poll = unionfs_poll,
+#endif
 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,11)
 	.unlocked_ioctl = unionfs_ioctl,
+#else
+	.ioctl = unionfs_ioctl,
 #endif
 	.mmap = unionfs_mmap,
 	.open = unionfs_open,
 	.flush = unionfs_flush,
 	.release = unionfs_file_release,
-	.fsync = unionfs_fsync,
+	.fsync = file_fsync,
+#if 0
 	.fasync = unionfs_fasync,
+#endif
 #ifdef SUPPORT_BROKEN_LOSETUP
 	.sendfile = unionfs_sendfile,
 #endif
diff -rNu /root/unionfs-1.1.3/fistdev.mk unionfs-1.1.3-mmap/fistdev.mk
--- /root/unionfs-1.1.3/fistdev.mk	1970-01-01 00:00:00.000000000 +0000
+++ unionfs-1.1.3-mmap/fistdev.mk	2006-04-11 07:43:58.000000000 +0000
@@ -0,0 +1 @@
+EXTRACFLAGS=-DUNIONFS_NDEBUG
diff -rNu /root/unionfs-1.1.3/inode.c unionfs-1.1.3-mmap/inode.c
--- /root/unionfs-1.1.3/inode.c	2006-02-20 22:47:06.000000000 +0000
+++ unionfs-1.1.3-mmap/inode.c	2006-03-02 16:24:37.000000000 +0000
@@ -979,6 +979,21 @@
 		break;
 	}
 
+	/* 
+	 * SP: notify_change will change the lower file's size,
+	 * but we need to truncate the page tables, so need to call
+	 * vmtruncate()
+	 */
+
+	if (ia->ia_valid & ATTR_SIZE) {
+		if (ia->ia_size != i_size_read(inode)) {
+			err = vmtruncate(inode, ia->ia_size);
+			if (err) {
+				printk("unionfs_setattr: vmtruncate failed\n");
+			}
+		}
+	}
+
 	/* get the size from the first hidden inode */
 	hidden_inode = itohi(dentry->d_inode);
 	fist_checkinode(inode, "unionfs_setattr");
diff -rNu /root/unionfs-1.1.3/main.c unionfs-1.1.3-mmap/main.c
--- /root/unionfs-1.1.3/main.c	2006-02-20 22:47:06.000000000 +0000
+++ unionfs-1.1.3-mmap/main.c	2006-03-02 16:28:23.000000000 +0000
@@ -141,14 +141,6 @@
 		init_special_inode(inode, hidden_inode->i_mode,
 				   hidden_inode->i_rdev);
 
-	/* Fix our inode's address operations to that of the lower inode (Unionfs is FiST-Lite) */
-	if (inode->i_mapping->a_ops != hidden_inode->i_mapping->a_ops) {
-		fist_dprint(7, "fixing inode 0x%p a_ops (0x%p -> 0x%p)\n",
-			    inode, inode->i_mapping->a_ops,
-			    hidden_inode->i_mapping->a_ops);
-		inode->i_mapping->a_ops = hidden_inode->i_mapping->a_ops;
-	}
-
 	/* all well, copy inode attributes */
 	fist_copy_attr_all(inode, hidden_inode);
 
@@ -747,7 +739,7 @@
 static int __init init_unionfs_fs(void)
 {
 	int err;
-	printk("Registering unionfs " UNIONFS_VERSION "\n");
+	printk("Registering unionfs " UNIONFS_VERSION " (mmap)\n");
 
 	fist_set_debug_value(init_debug);
 
diff -rNu /root/unionfs-1.1.3/mmap.c unionfs-1.1.3-mmap/mmap.c
--- /root/unionfs-1.1.3/mmap.c	1970-01-01 00:00:00.000000000 +0000
+++ unionfs-1.1.3-mmap/mmap.c	2006-04-18 09:43:20.000000000 +0000
@@ -0,0 +1,345 @@
+/*
+ * Copyright (c) 1997-2005 Erez Zadok <[EMAIL PROTECTED]>
+ * Copyright (c) 2001-2005 Stony Brook University
+ *
+ * For specific licensing information, see the COPYING file distributed with
+ * this package, or get one from ftp://ftp.filesystems.org/pub/fistgen/COPYING.
+ *
+ * This Copyright notice must be kept intact and distributed with all
+ * fistgen sources INCLUDING sources generated by fistgen.
+ */
+/*
+ *  $Id: mmap.c,v 1.18 2005/02/04 15:40:10 cwright Exp $
+ */
+
+#include "unionfs.h"
+
+void unionfs_copy_block(const char * from, char * to, unsigned len)
+{
+	        memcpy(to, from, len);
+}
+
+/* SP: writepage doesn't handle copyup yet
+ * a possible solution
+ *
+ * inode = d_find_alias(inode);
+ * dentry = d_find_alias(inode);
+ *
+ * then can determine if dentry needs to be copied up
+ *
+ * Questions:
+ *
+ * 1) will d_find_alias() always return a dentry?
+ * 2) hard links? (generic problem)
+ */
+int unionfs_writepage(struct page *page, struct writeback_control *wbc)
+{
+	int err = -EIO;
+	struct inode * inode;
+	struct inode * lower_inode;
+	struct page * lower_page;
+	char * kaddr, * lower_kaddr;
+
+	print_entry_location();
+
+	inode = page->mapping->host;
+	lower_inode = itohi(inode);
+
+	/* find lower page (returns a locked page) */
+	lower_page = grab_cache_page(lower_inode->i_mapping, page->index);
+	if (!lower_page)
+		goto out;
+
+	/* get page address, and encode it */
+	kaddr = (char *) kmap(page);
+	lower_kaddr = (char*) kmap(lower_page);
+	
+	unionfs_copy_block(kaddr, lower_kaddr, PAGE_CACHE_SIZE);
+	
+	kunmap(page);
+	kunmap(lower_page);
+
+	/* call lower writepage (expects locked page) */
+	err = lower_inode->i_mapping->a_ops->writepage(lower_page, wbc);
+
+	/*
+	 * update mtime and ctime of lower level file system
+	 * unionfs' mtime and ctime are updated by generic_file_write
+	 */
+	lower_inode->i_mtime = lower_inode->i_ctime = CURRENT_TIME;
+
+	page_cache_release(lower_page);	/* b/c grab_cache_page increased refcnt */
+
+	if (err)
+		ClearPageUptodate(page);
+	else
+		SetPageUptodate(page);
+out:
+	unlock_page(page);
+	print_exit_status(err);
+	return err;
+}
+
+/*
+ * readpage is called from generic_page_read and the fault handler.
+ * If your file system uses generic_page_read for the read op, it
+ * must implement readpage.
+ *
+ * Readpage expects a locked page, and must unlock it.
+ */
+int unionfs_do_readpage(struct file * file, struct page * page)
+{
+	int err = -EIO;
+	struct dentry * dentry;
+	struct file * lower_file = NULL;
+	struct inode * inode, * lower_inode;
+	char *page_data;
+	struct page * lower_page;
+	char * lower_page_data;
+
+	print_entry_location();
+
+	dentry = file->f_dentry; /* CPW: Moved below print_entry_location */
+	if (ftopd(file) == NULL) {
+		err = -ENOENT;
+		goto out_err;
+	}
+	lower_file = ftohf(file);
+	BUG_ON(lower_file == NULL);	/* XXX: is this assertion right here? */
+	inode = dentry->d_inode;
+	lower_inode = itohi(inode);
+
+        lower_page = NULL;
+
+	/* find lower page (returns a locked page) */
+	lower_page = read_cache_page(lower_inode->i_mapping,
+				     page->index,
+                                     (filler_t *) lower_inode->i_mapping->a_ops->readpage,
+                                     (void *) lower_file);
+	
+	if (IS_ERR(lower_page)) {
+		err = PTR_ERR(lower_page);
+		lower_page = NULL;
+		goto out_release;
+	}
+
+	/*
+	 * wait for the page data to show up
+	 * (signaled by readpage as unlocking the page)
+	 */
+	wait_on_page_locked(lower_page);
+	if (!PageUptodate(lower_page)) {
+		/*
+		 * call readpage() again if we returned from wait_on_page with a
+		 * page that's not up-to-date; that can happen when a partial
+		 * page has a few buffers which are ok, but not the whole
+		 * page.
+		 */
+		lock_page(lower_page);
+		err = lower_inode->i_mapping->a_ops->readpage(lower_file,
+							      lower_page);
+		if (err) {
+			lower_page = NULL;
+			goto out_release;
+		}
+		wait_on_page_locked(lower_page);
+		if (!PageUptodate(lower_page)) {
+			err = -EIO;
+			goto out_release;
+		}
+	}
+
+	/* map pages, get their addresses */
+	page_data = (char *) kmap(page);
+        lower_page_data = (char *) kmap(lower_page);
+
+	unionfs_copy_block(lower_page_data, page_data, PAGE_CACHE_SIZE);
+
+	err = 0;
+	
+        kunmap(lower_page);
+	kunmap(page);
+
+out_release:
+	if (lower_page)
+		page_cache_release(lower_page);	/* undo read_cache_page */
+
+	if (err == 0)
+		SetPageUptodate(page);
+	else
+		ClearPageUptodate(page);
+
+out_err:
+	print_exit_status(err);
+	return err;
+}
+
+int unionfs_readpage(struct file * file, struct page * page)
+{
+	int err;
+	print_entry_location();
+
+	err = unionfs_do_readpage(file, page);
+
+	/*
+	 * we have to unlock our page, b/c we _might_ have gotten a locked page.
+	 * but we no longer have to wakeup on our page here, b/c UnlockPage does
+	 * it
+	 */
+	
+	unlock_page(page);
+
+	print_exit_status(err);
+	return err;
+}
+
+int unionfs_prepare_write(struct file * file, struct page * page, unsigned from, unsigned to)
+{
+	int err = 0;
+
+	print_entry_location();
+
+/*	if (from == 0 && to == PAGE_CACHE_SIZE)
+		goto out;
+
+	if (!PageUptodate(page))
+		err = unionfs_do_readpage(file, page);
+
+out: */
+	print_exit_status(err);
+	return err;
+}
+
+int unionfs_commit_write(struct file * file, struct page * page, unsigned from, unsigned to)
+{
+        int err = -ENOMEM;
+        struct inode * inode, * lower_inode;
+        struct file * lower_file = NULL;
+        loff_t pos;
+        unsigned bytes = to - from;
+	char * page_data = NULL;
+	mm_segment_t old_fs;
+
+        print_entry_location();
+
+        BUG_ON(file == NULL);
+
+        inode = page->mapping->host; /* CPW: Moved below print_entry_location */
+        lower_inode = itohi(inode);
+
+        if (ftopd(file) != NULL)
+                lower_file = ftohf(file);
+	
+        BUG_ON(lower_file == NULL);	/* XXX: is this assertion right here? */
+	
+	page_data = (char *) kmap(page);
+	lower_file->f_pos = (page->index << PAGE_CACHE_SHIFT) + from;
+
+	/* SP: I use vfs_write instead of copying page data and the 
+	 * prepare_write/commit_write combo because file system's like 
+	 * GFS/OCFS2 don't like things touching those directly,
+	 * calling the underlying write op, while a little bit slower, will
+	 * call all the FS specific code as well
+	 */
+	old_fs = get_fs();
+	set_fs(KERNEL_DS);
+	err = vfs_write(lower_file, page_data + from, bytes, &lower_file->f_pos);
+	set_fs(old_fs);
+
+	kunmap(page);
+
+        if (err < 0)
+                goto out;
+
+        inode->i_blocks = lower_inode->i_blocks;
+        /* we may have to update i_size */
+        pos = ((loff_t)page->index << PAGE_CACHE_SHIFT) + to;
+        if (pos > i_size_read(inode))
+                i_size_write(inode, pos);
+
+        /*
+         * update mtime and ctime of lower level file system
+         * unionfs' mtime and ctime are updated by generic_file_write
+         */
+        lower_inode->i_mtime = lower_inode->i_ctime = CURRENT_TIME;
+
+        mark_inode_dirty_sync(inode);
+
+out:
+        print_exit_status(err);
+        return err;			/* assume all is ok */
+}
+
+sector_t unionfs_bmap(struct address_space * mapping, sector_t block)
+{
+        int err = 0;
+        struct inode * inode, * lower_inode;
+	
+        print_entry_location();
+
+        inode = (struct inode *) mapping->host;
+        lower_inode = itohi(inode);
+
+        if (lower_inode->i_mapping->a_ops->bmap)
+                err = lower_inode->i_mapping->a_ops->bmap(lower_inode->i_mapping, block);
+        print_exit_location();
+        return err;
+}
+
+
+/*
+ * This function is copied verbatim from mm/filemap.c.
+ * XXX: It should be simply moved to some header file instead -- bug Al about it!
+ */
+static inline int sync_page(struct page *page)
+{
+        struct address_space *mapping = page->mapping;
+
+        if (mapping && mapping->a_ops && mapping->a_ops->sync_page)
+                return mapping->a_ops->sync_page(page);
+        return 0;
+}
+
+int unionfs_sync_page(struct page *page)
+{
+        int err = 0;
+        struct inode * inode;
+        struct inode * lower_inode;
+        struct page * lower_page;
+
+        print_entry_location();
+
+        inode = page->mapping->host; /* CPW: Moved below print_entry_location */
+        lower_inode = itohi(inode);
+
+        /* find lower page (returns a locked page) */
+        lower_page = grab_cache_page(lower_inode->i_mapping, page->index);
+        if (!lower_page) {
+                err = -ENOMEM;
+                goto out;
+        }
+        err = sync_page(lower_page);
+
+        unlock_page(lower_page);	/* b/c grab_cache_page locked it */
+        page_cache_release(lower_page);	/* b/c grab_cache_page increased refcnt */
+
+out:
+        print_exit_status(err);
+        return err;
+}
+
+
+struct address_space_operations unionfs_aops = {
+        writepage:unionfs_writepage,
+        readpage:unionfs_readpage,
+        prepare_write:unionfs_prepare_write,
+        commit_write:unionfs_commit_write,
+        bmap:unionfs_bmap,
+        sync_page:unionfs_sync_page,
+};
+
+/*
+ * Local variables:
+ * c-basic-offset: 4
+ * End:
+ */
Binary files /root/unionfs-1.1.3/regression/progs/bug418 and unionfs-1.1.3-mmap/regression/progs/bug418 differ
Binary files /root/unionfs-1.1.3/regression/progs/creat-open and unionfs-1.1.3-mmap/regression/progs/creat-open differ
Binary files /root/unionfs-1.1.3/regression/progs/flock-copyup and unionfs-1.1.3-mmap/regression/progs/flock-copyup differ
Binary files /root/unionfs-1.1.3/regression/progs/fsync and unionfs-1.1.3-mmap/regression/progs/fsync differ
Binary files /root/unionfs-1.1.3/regression/progs/open-unlink and unionfs-1.1.3-mmap/regression/progs/open-unlink differ
Binary files /root/unionfs-1.1.3/regression/progs/rmdircheckinode and unionfs-1.1.3-mmap/regression/progs/rmdircheckinode differ
Binary files /root/unionfs-1.1.3/regression/progs/truncate and unionfs-1.1.3-mmap/regression/progs/truncate differ
diff -rNu /root/unionfs-1.1.3/super.c unionfs-1.1.3-mmap/super.c
--- /root/unionfs-1.1.3/super.c	2006-02-20 22:47:06.000000000 +0000
+++ unionfs-1.1.3-mmap/super.c	2006-03-02 16:27:56.000000000 +0000
@@ -28,7 +28,8 @@
 
 static void unionfs_read_inode(struct inode *inode)
 {
-	static struct address_space_operations unionfs_empty_aops;
+	/* SP: use real address operations */
+	extern struct address_space_operations unionfs_aops;
 	int size;
 
 	print_entry_location();
@@ -60,10 +61,7 @@
 	inode->i_version++;
 	inode->i_op = &unionfs_main_iops;
 	inode->i_fop = &unionfs_main_fops;
-	/* I don't think ->a_ops is ever allowed to be NULL */
-	inode->i_mapping->a_ops = &unionfs_empty_aops;
-	fist_dprint(7, "setting inode 0x%p a_ops to empty (0x%p)\n",
-		    inode, inode->i_mapping->a_ops);
+	inode->i_mapping->a_ops = &unionfs_aops;
 
 	print_exit_location();
 }
@@ -100,6 +98,13 @@
 
 	fist_checkinode(inode, "unionfs_delete_inode IN");
 	inode->i_size = 0;	/* every f/s seems to do that */
+
+	/* SP: if you try to clear_inode() when
+	 * inode->i_data.nrpages != 0, you'll hit a BUG
+	 * this is also what generic_delete_inode does */
+	if (inode->i_data.nrpages)
+		truncate_inode_pages(&inode->i_data, 0);
+	
 	clear_inode(inode);
 
 	print_exit_location();
_______________________________________________
unionfs mailing list
[email protected]
http://www.fsl.cs.sunysb.edu/mailman/listinfo/unionfs

Reply via email to