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