aboutsummaryrefslogtreecommitdiffstats
path: root/fs
diff options
context:
space:
mode:
authorNick Piggin <npiggin@suse.de>2008-04-28 05:13:02 -0400
committerLinus Torvalds <torvalds@linux-foundation.org>2008-04-28 11:58:23 -0400
commit70688e4dd1647f0ceb502bbd5964fa344c5eb411 (patch)
treee0bd8c3b4b6050c067a453d800c2e87948d1abaf /fs
parent30afcb4bd2762fa4b87b17ada9500aa46dc10b1b (diff)
xip: support non-struct page backed memory
Convert XIP to support non-struct page backed memory, using VM_MIXEDMAP for the user mappings. This requires the get_xip_page API to be changed to an address based one. Improve the API layering a little bit too, while we're here. This is required in order to support XIP filesystems on memory that isn't backed with struct page (but memory with struct page is still supported too). Signed-off-by: Nick Piggin <npiggin@suse.de> Acked-by: Carsten Otte <cotte@de.ibm.com> Cc: Jared Hulbert <jaredeh@gmail.com> Cc: Martin Schwidefsky <schwidefsky@de.ibm.com> Cc: Heiko Carstens <heiko.carstens@de.ibm.com> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Diffstat (limited to 'fs')
-rw-r--r--fs/ext2/inode.c2
-rw-r--r--fs/ext2/xip.c37
-rw-r--r--fs/ext2/xip.h9
-rw-r--r--fs/open.c2
4 files changed, 22 insertions, 28 deletions
diff --git a/fs/ext2/inode.c b/fs/ext2/inode.c
index b8a2990bab83..687023bdfd1e 100644
--- a/fs/ext2/inode.c
+++ b/fs/ext2/inode.c
@@ -796,7 +796,7 @@ const struct address_space_operations ext2_aops = {
796 796
797const struct address_space_operations ext2_aops_xip = { 797const struct address_space_operations ext2_aops_xip = {
798 .bmap = ext2_bmap, 798 .bmap = ext2_bmap,
799 .get_xip_page = ext2_get_xip_page, 799 .get_xip_mem = ext2_get_xip_mem,
800}; 800};
801 801
802const struct address_space_operations ext2_nobh_aops = { 802const struct address_space_operations ext2_nobh_aops = {
diff --git a/fs/ext2/xip.c b/fs/ext2/xip.c
index 430b4c8ee971..233f7fdbe31d 100644
--- a/fs/ext2/xip.c
+++ b/fs/ext2/xip.c
@@ -15,26 +15,28 @@
15#include "xip.h" 15#include "xip.h"
16 16
17static inline int 17static inline int
18__inode_direct_access(struct inode *inode, sector_t sector, 18__inode_direct_access(struct inode *inode, sector_t block,
19 void **kaddr, unsigned long *pfn) 19 void **kaddr, unsigned long *pfn)
20{ 20{
21 struct block_device *bdev = inode->i_sb->s_bdev; 21 struct block_device *bdev = inode->i_sb->s_bdev;
22 struct block_device_operations *ops = bdev->bd_disk->fops; 22 struct block_device_operations *ops = bdev->bd_disk->fops;
23 sector_t sector;
24
25 sector = block * (PAGE_SIZE / 512); /* ext2 block to bdev sector */
23 26
24 BUG_ON(!ops->direct_access); 27 BUG_ON(!ops->direct_access);
25 return ops->direct_access(bdev, sector, kaddr, pfn); 28 return ops->direct_access(bdev, sector, kaddr, pfn);
26} 29}
27 30
28static inline int 31static inline int
29__ext2_get_sector(struct inode *inode, sector_t offset, int create, 32__ext2_get_block(struct inode *inode, pgoff_t pgoff, int create,
30 sector_t *result) 33 sector_t *result)
31{ 34{
32 struct buffer_head tmp; 35 struct buffer_head tmp;
33 int rc; 36 int rc;
34 37
35 memset(&tmp, 0, sizeof(struct buffer_head)); 38 memset(&tmp, 0, sizeof(struct buffer_head));
36 rc = ext2_get_block(inode, offset/ (PAGE_SIZE/512), &tmp, 39 rc = ext2_get_block(inode, pgoff, &tmp, create);
37 create);
38 *result = tmp.b_blocknr; 40 *result = tmp.b_blocknr;
39 41
40 /* did we get a sparse block (hole in the file)? */ 42 /* did we get a sparse block (hole in the file)? */
@@ -47,14 +49,13 @@ __ext2_get_sector(struct inode *inode, sector_t offset, int create,
47} 49}
48 50
49int 51int
50ext2_clear_xip_target(struct inode *inode, int block) 52ext2_clear_xip_target(struct inode *inode, sector_t block)
51{ 53{
52 sector_t sector = block * (PAGE_SIZE/512);
53 void *kaddr; 54 void *kaddr;
54 unsigned long pfn; 55 unsigned long pfn;
55 int rc; 56 int rc;
56 57
57 rc = __inode_direct_access(inode, sector, &kaddr, &pfn); 58 rc = __inode_direct_access(inode, block, &kaddr, &pfn);
58 if (!rc) 59 if (!rc)
59 clear_page(kaddr); 60 clear_page(kaddr);
60 return rc; 61 return rc;
@@ -72,26 +73,18 @@ void ext2_xip_verify_sb(struct super_block *sb)
72 } 73 }
73} 74}
74 75
75struct page * 76int ext2_get_xip_mem(struct address_space *mapping, pgoff_t pgoff, int create,
76ext2_get_xip_page(struct address_space *mapping, sector_t offset, 77 void **kmem, unsigned long *pfn)
77 int create)
78{ 78{
79 int rc; 79 int rc;
80 void *kaddr; 80 sector_t block;
81 unsigned long pfn;
82 sector_t sector;
83 81
84 /* first, retrieve the sector number */ 82 /* first, retrieve the sector number */
85 rc = __ext2_get_sector(mapping->host, offset, create, &sector); 83 rc = __ext2_get_block(mapping->host, pgoff, create, &block);
86 if (rc) 84 if (rc)
87 goto error; 85 return rc;
88 86
89 /* retrieve address of the target data */ 87 /* retrieve address of the target data */
90 rc = __inode_direct_access 88 rc = __inode_direct_access(mapping->host, block, kmem, pfn);
91 (mapping->host, sector * (PAGE_SIZE/512), &kaddr, &pfn); 89 return rc;
92 if (!rc)
93 return pfn_to_page(pfn);
94
95 error:
96 return ERR_PTR(rc);
97} 90}
diff --git a/fs/ext2/xip.h b/fs/ext2/xip.h
index aa85331d6c56..18b34d2f31b3 100644
--- a/fs/ext2/xip.h
+++ b/fs/ext2/xip.h
@@ -7,19 +7,20 @@
7 7
8#ifdef CONFIG_EXT2_FS_XIP 8#ifdef CONFIG_EXT2_FS_XIP
9extern void ext2_xip_verify_sb (struct super_block *); 9extern void ext2_xip_verify_sb (struct super_block *);
10extern int ext2_clear_xip_target (struct inode *, int); 10extern int ext2_clear_xip_target (struct inode *, sector_t);
11 11
12static inline int ext2_use_xip (struct super_block *sb) 12static inline int ext2_use_xip (struct super_block *sb)
13{ 13{
14 struct ext2_sb_info *sbi = EXT2_SB(sb); 14 struct ext2_sb_info *sbi = EXT2_SB(sb);
15 return (sbi->s_mount_opt & EXT2_MOUNT_XIP); 15 return (sbi->s_mount_opt & EXT2_MOUNT_XIP);
16} 16}
17struct page* ext2_get_xip_page (struct address_space *, sector_t, int); 17int ext2_get_xip_mem(struct address_space *, pgoff_t, int,
18#define mapping_is_xip(map) unlikely(map->a_ops->get_xip_page) 18 void **, unsigned long *);
19#define mapping_is_xip(map) unlikely(map->a_ops->get_xip_mem)
19#else 20#else
20#define mapping_is_xip(map) 0 21#define mapping_is_xip(map) 0
21#define ext2_xip_verify_sb(sb) do { } while (0) 22#define ext2_xip_verify_sb(sb) do { } while (0)
22#define ext2_use_xip(sb) 0 23#define ext2_use_xip(sb) 0
23#define ext2_clear_xip_target(inode, chain) 0 24#define ext2_clear_xip_target(inode, chain) 0
24#define ext2_get_xip_page NULL 25#define ext2_get_xip_mem NULL
25#endif 26#endif
diff --git a/fs/open.c b/fs/open.c
index b70e7666bb2c..7af1f05d5978 100644
--- a/fs/open.c
+++ b/fs/open.c
@@ -837,7 +837,7 @@ static struct file *__dentry_open(struct dentry *dentry, struct vfsmount *mnt,
837 if (f->f_flags & O_DIRECT) { 837 if (f->f_flags & O_DIRECT) {
838 if (!f->f_mapping->a_ops || 838 if (!f->f_mapping->a_ops ||
839 ((!f->f_mapping->a_ops->direct_IO) && 839 ((!f->f_mapping->a_ops->direct_IO) &&
840 (!f->f_mapping->a_ops->get_xip_page))) { 840 (!f->f_mapping->a_ops->get_xip_mem))) {
841 fput(f); 841 fput(f);
842 f = ERR_PTR(-EINVAL); 842 f = ERR_PTR(-EINVAL);
843 } 843 }