I'm rejected to post on the list so I'm resending.
Hope it works this time.

Thanks,
Joonwoo

---------- Forwarded message ----------
From: Joonwoo Park <[email protected]>
To: "J. R. Okajima" <[email protected]>
Date: Tue, 12 May 2009 14:29:49 -0700
Subject: aufs2 with ubifs mmap problem
Hello,

I've encounter a aufs related problem when I use mmap on ubifs as
read-write branch.
FYI, I cannot see this problem on ubifs only partition, aufs with
tmpfs branch and aufs with ext3 branch.

The problem that I encountered was ubifs set_page_dirty() assertion
failure when mmap-ing to aufs filesystem which has branch as ubifs
filesystem.
I had a quick aufs hacking and I've inclined that aufs should have
handled page_mkwrite of vm_operation.  The current version of aufs2 is
registering only aufs_fault.
Please find attached patch file aufs-mmap-fault.patch and correct me
if I'm wrong.

Attached patch looked like solve this problem but no luck.
This patch reduced lots of ubifs assertion failures but I'm still
seeing assertion failure after large size of mmap writing (actually
exiting the process after mmap writing).
It seems that I still have a problem when do_munmap from sys_exit is called.

Do you have any idea for this issue?

Thanks,
Joonwoo

I can reproduce this problem without real nand flash chip like below,
You have to configure CONFIG_UBIFS_FS_DEBUG to get ubifs assertion:
modprobe ubifs
modprobe nandsim
ubiattach /dev/ubi_ctrl -m 0
ubimkvol /dev/ubi1 -m -N commonrw
mount -t ubifs -o rw,sync ubi1:commonrw /tmp/rw
mount -t aufs -o dirs=/tmp/rw=rw none /mnt
while [ 1 ]; do ./mwr /mnt/a; done;
[ 1939.037049] UBIFS assert failed in ubifs_set_page_dirty at 1144 (pid 1435)
[ 1939.037049] UBIFS assert failed in ubifs_set_page_dirty at 1144 (pid 1435)
[ 1939.037049] UBIFS assert failed in ubifs_set_page_dirty at 1144 (pid 1435)
...


# dmesg | grep aufs
aufs 2-standalone.tree-27-20090427
# uname -a
Linux (none) 2.6.27 #8 Mon May 11 17:59:03 PDT 2009 i586 unknown

...
#
# UBI debugging options
#
CONFIG_MTD_UBI_DEBUG=y
# CONFIG_MTD_UBI_DEBUG_MSG is not set
# CONFIG_MTD_UBI_DEBUG_PARANOID is not set
CONFIG_MTD_UBI_DEBUG_DISABLE_BGT=y
# CONFIG_MTD_UBI_DEBUG_USERSPACE_IO is not set
# CONFIG_MTD_UBI_DEBUG_EMULATE_BITFLIPS is not set
# CONFIG_MTD_UBI_DEBUG_EMULATE_WRITE_FAILURES is not set
# CONFIG_MTD_UBI_DEBUG_EMULATE_ERASE_FAILURES is not set

#
# Additional UBI debugging messages
#
# CONFIG_MTD_UBI_DEBUG_MSG_BLD is not set
# CONFIG_MTD_UBI_DEBUG_MSG_EBA is not set
# CONFIG_MTD_UBI_DEBUG_MSG_WL is not set
# CONFIG_MTD_UBI_DEBUG_MSG_IO is not set
...
CONFIG_UBIFS_FS=m
# CONFIG_UBIFS_FS_XATTR is not set
CONFIG_UBIFS_FS_ADVANCED_COMPR=y
CONFIG_UBIFS_FS_LZO=y
# CONFIG_UBIFS_FS_ZLIB is not set
CONFIG_UBIFS_FS_DEBUG=y
CONFIG_UBIFS_FS_DEBUG_MSG_LVL=0
# CONFIG_UBIFS_FS_DEBUG_CHKS is not set
# CONFIG_CRAMFS is not set
# CONFIG_VXFS_FS is not set
# CONFIG_MINIX_FS is not set
# CONFIG_OMFS_FS is not set
# CONFIG_HPFS_FS is not set
# CONFIG_QNX4FS_FS is not set
# CONFIG_ROMFS_FS is not set
# CONFIG_SYSV_FS is not set
# CONFIG_UFS_FS is not set
....
CONFIG_AUFS_FS=m
CONFIG_AUFS_BRANCH_MAX_127=y
# CONFIG_AUFS_BRANCH_MAX_511 is not set
# CONFIG_AUFS_BRANCH_MAX_1023 is not set
# CONFIG_AUFS_BRANCH_MAX_32767 is not set
CONFIG_AUFS_HINOTIFY=y
CONFIG_AUFS_BR_RAMFS=y
# CONFIG_AUFS_DEBUG is not set
--- linux-2.6.27.orig/fs/aufs/f_op.c	2009-05-08 08:51:04.000000000 -0700
+++ linux-2.6.27/fs/aufs/f_op.c	2009-05-08 10:04:40.000000000 -0700
@@ -263,6 +263,32 @@ static void au_reset_file(struct vm_area
 	/* smp_mb(); */ /* flush vm_file */
 }
 
+static int aufs_page_mkwrite(struct vm_area_struct *vma, struct page *page)
+{
+	int err;
+	static DECLARE_WAIT_QUEUE_HEAD(wq);
+	struct file *file, *h_file;
+	struct au_finfo *finfo;
+
+	wait_event(wq, (file = au_safe_file(vma)));
+
+	finfo = au_fi(file);
+	h_file = finfo->fi_hfile[0 + finfo->fi_bstart].hf_file;
+	AuDebugOn(!h_file || !au_test_mmapped(file));
+
+	fi_write_lock(file);
+	vma->vm_file = h_file;
+	if (finfo->fi_h_vm_ops->page_mkwrite)
+		err = finfo->fi_h_vm_ops->page_mkwrite(vma, page);
+	else
+		err = 0;
+	au_reset_file(vma, file);
+	fi_write_unlock(file);
+	wake_up(&wq);
+
+	return err;
+}
+
 static int aufs_fault(struct vm_area_struct *vma, struct vm_fault *vmf)
 {
 	int err;
@@ -296,7 +322,8 @@ static int aufs_fault(struct vm_area_str
 }
 
 static struct vm_operations_struct aufs_vm_ops = {
-	.fault		= aufs_fault
+	.fault		= aufs_fault,
+	.page_mkwrite	= aufs_page_mkwrite,
 };
 
 /* ---------------------------------------------------------------------- */
#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>
#include <fcntl.h>
#include <sys/mman.h>

#define FILEPATH "/mnt/tmp/mmapped.bin"
#define NUMINTS  (1000 * 1000 * 5)
#define FILESIZE (NUMINTS * sizeof(int))

int main(int argc, char *argv[])
{
    int i;
    int fd;
    int result;
    int *map;  /* mmapped array of int's */
    char* filename;

    if (argc != 2) {
        printf("filename is needed\n");
	return 1;
    }
    filename = argv[1];

    /* Open a file for writing.
     *  - Creating the file if it doesn't exist.
     *  - Truncating it to 0 size if it already exists. (not really needed)
     *
     * Note: "O_WRONLY" mode is not sufficient when mmaping.
     */
    fd = open(filename, O_RDWR | O_CREAT | O_TRUNC, (mode_t)0600);
    if (fd == -1) {
	perror("Error opening file for writing");
	exit(EXIT_FAILURE);
    }

    /* Stretch the file size to the size of the (mmapped) array of ints
     */
    result = lseek(fd, FILESIZE-1, SEEK_SET);
    if (result == -1) {
	close(fd);
	perror("Error calling lseek() to 'stretch' the file");
	exit(EXIT_FAILURE);
    }
    
    /* Something needs to be written at the end of the file to
     * have the file actually have the new size.
     * Just writing an empty string at the current file position will do.
     *
     * Note:
     *  - The current position in the file is at the end of the stretched 
     *    file due to the call to lseek().
     *  - An empty string is actually a single '\0' character, so a zero-byte
     *    will be written at the last byte of the file.
     */
    result = write(fd, "", 1);
    if (result != 1) {
	close(fd);
	perror("Error writing last byte of the file");
	exit(EXIT_FAILURE);
    }

    /* Now the file is ready to be mmapped.
     */
#if 1
    int flags = MAP_SHARED;
#else
    int flags = MAP_SHARED | MAP_NORESERVE;
#endif
    map = mmap(0, FILESIZE, PROT_READ | PROT_WRITE, flags, fd, 0);
    if (map == MAP_FAILED) {
	close(fd);
	perror("Error mmapping the file");
	exit(EXIT_FAILURE);
    }
    
    /* Now write int's to the file as if it were memory (an array of ints).
     */
    for (i = 1; i <=NUMINTS; ++i) {
	map[i] = 2 * i; 
    }

    /* Don't forget to free the mmapped memory
     */
    if (munmap(map, FILESIZE) == -1) {
	perror("Error un-mmapping the file");
	/* Decide here whether to close(fd) and exit() or not. Depends... */
    }

    /* Un-mmaping doesn't close the file, so we still need to do that.
     */
//    close(fd);
    return 0;
}
------------------------------------------------------------------------------
The NEW KODAK i700 Series Scanners deliver under ANY circumstances! Your
production scanning environment may not be a perfect world - but thanks to
Kodak, there's a perfect scanner to get the job done! With the NEW KODAK i700
Series Scanner you'll get full speed at 300 dpi even with all image 
processing features enabled. http://p.sf.net/sfu/kodak-com

Reply via email to