2.6.22-rc6-mm1: BUG_ON() mm/memory.c, vm_insert_pfn(), filemap_xip.c, and spufs

2007-07-03 Thread Jared Hulbert

Recently there has been some discussion of the possiblity of reworking
some of filemap_xip.c to be pfn oriented.  This would allow an XIP
fork of cramfs to use the filemap_xip framework.  Today this is not
possible.

I've been trying out vm_insert_pfn() to start down that road.  I used
spufs as a reference for how to use it.  The include patch to cramfs
is my hack at it.

When I try to execute an XIP binary I get a BUG() on 2.6.22-rc6-mm1 at
mm/memory.c line 2334.  The way I read this is says that spufs might
not work.  I can't test it.
In spufs_mem_mmap() line 196 the vma is flagged as VM_PFNMAP:
vma->vm_flags |= VM_IO | VM_PFNMAP;

When you get a fault in a vma  __do_fault() will get this vma and
BUG() on line 2334:
BUG_ON(vma->vm_flags & VM_PFNMAP);

What happened to the functionality of do_no_pfn()?




diff -r 74bad9e01817 fs/Kconfig
--- a/fs/KconfigThu Jun 28 13:49:43 2007 -0700
+++ b/fs/KconfigMon Jul 02 15:47:16 2007 -0700
@@ -65,8 +65,7 @@ config FS_XIP
config FS_XIP
# execute in place
bool
-   depends on EXT2_FS_XIP
-   default y
+   default n

config EXT3_FS
tristate "Ext3 journalling file system support"
@@ -1399,8 +1398,8 @@ endchoice

config CRAMFS
tristate "Compressed ROM file system support (cramfs)"
-   depends on BLOCK
select ZLIB_INFLATE
+   select FS_XIP
help
  Saying Y here includes support for CramFs (Compressed ROM File
  System).  CramFs is designed to be a simple, small, and compressed
diff -r 74bad9e01817 fs/cramfs/inode.c
--- a/fs/cramfs/inode.c Thu Jun 28 13:49:43 2007 -0700
+++ b/fs/cramfs/inode.c Tue Jul 03 17:45:42 2007 -0700
@@ -24,15 +24,21 @@
#include 
#include 
#include 
-
+#include 
#include 

+static const struct file_operations cramfs_xip_fops;
static const struct super_operations cramfs_ops;
static const struct inode_operations cramfs_dir_inode_operations;
static const struct file_operations cramfs_directory_operations;
static const struct address_space_operations cramfs_aops;
+static const struct address_space_operations cramfs_xip_aops;

static DEFINE_MUTEX(read_mutex);
+
+static struct backing_dev_info cramfs_backing_dev_info = {
+   .ra_pages   = 0,/* No readahead */
+};


/* These two macros may change in future, to provide better st_ino
@@ -77,19 +83,31 @@ static int cramfs_iget5_set(struct inode
/* Struct copy intentional */
inode->i_mtime = inode->i_atime = inode->i_ctime = zerotime;
inode->i_ino = CRAMINO(cramfs_inode);
+
+   if (CRAMFS_INODE_IS_XIP(inode))
+   inode->i_mapping->backing_dev_info = _backing_dev_info;
+
/* inode->i_nlink is left 1 - arguably wrong for directories,
   but it's the best we can do without reading the directory
   contents.  1 yields the right result in GNU find, even
   without -noleaf option. */
if (S_ISREG(inode->i_mode)) {
-   inode->i_fop = _ro_fops;
-   inode->i_data.a_ops = _aops;
+   if (CRAMFS_INODE_IS_XIP(inode)) {
+   inode->i_fop = _xip_fops;
+   inode->i_data.a_ops = _xip_aops;
+   } else {
+   inode->i_fop = _ro_fops;
+   inode->i_data.a_ops = _aops;
+   }
} else if (S_ISDIR(inode->i_mode)) {
inode->i_op = _dir_inode_operations;
inode->i_fop = _directory_operations;
} else if (S_ISLNK(inode->i_mode)) {
inode->i_op = _symlink_inode_operations;
-   inode->i_data.a_ops = _aops;
+   if (CRAMFS_INODE_IS_XIP(inode))
+   inode->i_data.a_ops = _xip_aops;
+   else
+   inode->i_data.a_ops = _aops;
} else {
inode->i_size = 0;
inode->i_blocks = 0;
@@ -111,34 +129,6 @@ static struct inode *get_cramfs_inode(st
return inode;
}

-/*
- * We have our own block cache: don't fill up the buffer cache
- * with the rom-image, because the way the filesystem is set
- * up the accesses should be fairly regular and cached in the
- * page cache and dentry tree anyway..
- *
- * This also acts as a way to guarantee contiguous areas of up to
- * BLKS_PER_BUF*PAGE_CACHE_SIZE, so that the caller doesn't need to
- * worry about end-of-buffer issues even when decompressing a full
- * page cache.
- */
-#define READ_BUFFERS (2)
-/* NEXT_BUFFER(): Loop over [0..(READ_BUFFERS-1)]. */
-#define NEXT_BUFFER(_ix) ((_ix) ^ 1)
-
-/*
- * BLKS_PER_BUF_SHIFT should be at least 2 to allow for "compressed"
- * data that takes up more space than the original and with unlucky
- * alignment.
- */
-#define BLKS_PER_BUF_SHIFT (2)
-#define BLKS_PER_BUF   (1 << BLKS_PER_BUF_SHIFT)
-#define BUFFER_SIZE(BLKS_PER_BUF*PAGE_CACHE_SIZE)
-
-static unsigned char read_buffers[READ_BUFFERS][BUFFER_SIZE];
-static unsigned 

2.6.22-rc6-mm1: BUG_ON() mm/memory.c, vm_insert_pfn(), filemap_xip.c, and spufs

2007-07-03 Thread Jared Hulbert

Recently there has been some discussion of the possiblity of reworking
some of filemap_xip.c to be pfn oriented.  This would allow an XIP
fork of cramfs to use the filemap_xip framework.  Today this is not
possible.

I've been trying out vm_insert_pfn() to start down that road.  I used
spufs as a reference for how to use it.  The include patch to cramfs
is my hack at it.

When I try to execute an XIP binary I get a BUG() on 2.6.22-rc6-mm1 at
mm/memory.c line 2334.  The way I read this is says that spufs might
not work.  I can't test it.
In spufs_mem_mmap() line 196 the vma is flagged as VM_PFNMAP:
vma-vm_flags |= VM_IO | VM_PFNMAP;

When you get a fault in a vma  __do_fault() will get this vma and
BUG() on line 2334:
BUG_ON(vma-vm_flags  VM_PFNMAP);

What happened to the functionality of do_no_pfn()?




diff -r 74bad9e01817 fs/Kconfig
--- a/fs/KconfigThu Jun 28 13:49:43 2007 -0700
+++ b/fs/KconfigMon Jul 02 15:47:16 2007 -0700
@@ -65,8 +65,7 @@ config FS_XIP
config FS_XIP
# execute in place
bool
-   depends on EXT2_FS_XIP
-   default y
+   default n

config EXT3_FS
tristate Ext3 journalling file system support
@@ -1399,8 +1398,8 @@ endchoice

config CRAMFS
tristate Compressed ROM file system support (cramfs)
-   depends on BLOCK
select ZLIB_INFLATE
+   select FS_XIP
help
  Saying Y here includes support for CramFs (Compressed ROM File
  System).  CramFs is designed to be a simple, small, and compressed
diff -r 74bad9e01817 fs/cramfs/inode.c
--- a/fs/cramfs/inode.c Thu Jun 28 13:49:43 2007 -0700
+++ b/fs/cramfs/inode.c Tue Jul 03 17:45:42 2007 -0700
@@ -24,15 +24,21 @@
#include linux/vfs.h
#include linux/mutex.h
#include asm/semaphore.h
-
+#include linux/vmalloc.h
#include asm/uaccess.h

+static const struct file_operations cramfs_xip_fops;
static const struct super_operations cramfs_ops;
static const struct inode_operations cramfs_dir_inode_operations;
static const struct file_operations cramfs_directory_operations;
static const struct address_space_operations cramfs_aops;
+static const struct address_space_operations cramfs_xip_aops;

static DEFINE_MUTEX(read_mutex);
+
+static struct backing_dev_info cramfs_backing_dev_info = {
+   .ra_pages   = 0,/* No readahead */
+};


/* These two macros may change in future, to provide better st_ino
@@ -77,19 +83,31 @@ static int cramfs_iget5_set(struct inode
/* Struct copy intentional */
inode-i_mtime = inode-i_atime = inode-i_ctime = zerotime;
inode-i_ino = CRAMINO(cramfs_inode);
+
+   if (CRAMFS_INODE_IS_XIP(inode))
+   inode-i_mapping-backing_dev_info = cramfs_backing_dev_info;
+
/* inode-i_nlink is left 1 - arguably wrong for directories,
   but it's the best we can do without reading the directory
   contents.  1 yields the right result in GNU find, even
   without -noleaf option. */
if (S_ISREG(inode-i_mode)) {
-   inode-i_fop = generic_ro_fops;
-   inode-i_data.a_ops = cramfs_aops;
+   if (CRAMFS_INODE_IS_XIP(inode)) {
+   inode-i_fop = cramfs_xip_fops;
+   inode-i_data.a_ops = cramfs_xip_aops;
+   } else {
+   inode-i_fop = generic_ro_fops;
+   inode-i_data.a_ops = cramfs_aops;
+   }
} else if (S_ISDIR(inode-i_mode)) {
inode-i_op = cramfs_dir_inode_operations;
inode-i_fop = cramfs_directory_operations;
} else if (S_ISLNK(inode-i_mode)) {
inode-i_op = page_symlink_inode_operations;
-   inode-i_data.a_ops = cramfs_aops;
+   if (CRAMFS_INODE_IS_XIP(inode))
+   inode-i_data.a_ops = cramfs_xip_aops;
+   else
+   inode-i_data.a_ops = cramfs_aops;
} else {
inode-i_size = 0;
inode-i_blocks = 0;
@@ -111,34 +129,6 @@ static struct inode *get_cramfs_inode(st
return inode;
}

-/*
- * We have our own block cache: don't fill up the buffer cache
- * with the rom-image, because the way the filesystem is set
- * up the accesses should be fairly regular and cached in the
- * page cache and dentry tree anyway..
- *
- * This also acts as a way to guarantee contiguous areas of up to
- * BLKS_PER_BUF*PAGE_CACHE_SIZE, so that the caller doesn't need to
- * worry about end-of-buffer issues even when decompressing a full
- * page cache.
- */
-#define READ_BUFFERS (2)
-/* NEXT_BUFFER(): Loop over [0..(READ_BUFFERS-1)]. */
-#define NEXT_BUFFER(_ix) ((_ix) ^ 1)
-
-/*
- * BLKS_PER_BUF_SHIFT should be at least 2 to allow for compressed
- * data that takes up more space than the original and with unlucky
- * alignment.
- */
-#define BLKS_PER_BUF_SHIFT (2)
-#define BLKS_PER_BUF   (1  BLKS_PER_BUF_SHIFT)
-#define BUFFER_SIZE