[Unionfs] mmap unionfs bug

Erez Zadok ezk at cs.sunysb.edu
Tue Oct 16 10:52:18 EDT 2007


In message <cfa94dc20710051657y4d855892h301ef72e52c2a083 at mail.gmail.com>, "Ryan Finnie" writes:
> I'm getting apt errors when running a root on unionfs2.  It looks like
> this was already discovered in Ubuntu:
> 
> https://bugs.launchpad.net/ubuntu/+source/apt/+bug/144001
> 
> and a workaround was made for apt, but it was never reported to
> unionfs.  Note Colin Watson's explanation halfway down.
> 
> Thanks,
> RF

Ryan, I brought the issue up on lkml, and there was some discussion about
ensuring that msync(2) never returns AOP_WRITEPAGE_ACTIVATE back to
userland.  In addition, based on recommendations from Pekka, I've got this
patch tested well on 2.6.23.1.  I plan to test it on all the backports and
then release it officially.  But in the mean time, it'd be very useful if
anyone who's noted problems with msync(2) (esp. when using unionfs w/ tmpfs)
to try this patch below.  I especially like it if you can try it with an
unpatched apt-get and see if when it calls msync(2), does it ever get
AOP_WRITEPAGE_ACTIVATE back.

Thanks,
Erez.


diff --git a/fs/unionfs/mmap.c b/fs/unionfs/mmap.c
index 6440282..b43557e 100644
--- a/fs/unionfs/mmap.c
+++ b/fs/unionfs/mmap.c
@@ -144,6 +144,28 @@ out:
 	return err;
 }
 
+static int unionfs_writepages(struct address_space *mapping,
+			      struct writeback_control *wbc)
+{
+	int err = 0;
+	struct inode *lower_inode;
+	struct inode *inode;
+
+	inode = mapping->host;
+	lower_inode = unionfs_lower_inode(inode);
+	BUG_ON(!lower_inode);
+
+	if (!mapping_cap_writeback_dirty(lower_inode->i_mapping))
+		goto out;
+
+	/* Note: generic_writepages may return AOP_WRITEPAGE_ACTIVATE */
+	err = generic_writepages(mapping, wbc);
+	if (err == 0)
+		unionfs_copy_attr_times(inode);
+out:
+	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
@@ -374,6 +396,7 @@ out:
 
 struct address_space_operations unionfs_aops = {
 	.writepage	= unionfs_writepage,
+	.writepages	= unionfs_writepages,
 	.readpage	= unionfs_readpage,
 	.prepare_write	= unionfs_prepare_write,
 	.commit_write	= unionfs_commit_write,
diff --git a/fs/unionfs/union.h b/fs/unionfs/union.h
index 22a4b91..36dddd4 100644
--- a/fs/unionfs/union.h
+++ b/fs/unionfs/union.h
@@ -45,6 +45,7 @@
 #include <linux/log2.h>
 #include <linux/poison.h>
 #include <linux/mman.h>
+#include <linux/backing-dev.h>
 
 #include <asm/system.h>
 


More information about the unionfs mailing list