2.6.22-rc6-mm1: BUG_ON() mm/memory.c, vm_insert_pfn(), filemap_xip.c, and spufs
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
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