diff options
author | Jared Hulbert <jaredeh@gmail.com> | 2008-04-28 05:13:02 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2008-04-28 11:58:23 -0400 |
commit | 30afcb4bd2762fa4b87b17ada9500aa46dc10b1b (patch) | |
tree | 0920f491a37683a8784c146270b98f82a7e0aa2c /fs/ext2 | |
parent | 423bad600443c590f34ed7ce357591f76f48f137 (diff) |
return pfn from direct_access, for XIP
Alter the block device ->direct_access() API to work with the new
get_xip_mem() API (that requires both kaddr and pfn are returned).
Some architectures will not do the right thing in their virt_to_page() for use
by XIP (to translate from the kernel virtual address returned by
direct_access(), to a user mappable pfn in XIP's page fault handler.
However, we can't switch it to just return the pfn and not the kaddr, because
we have no good way to get a kva from a pfn, and XIP requires the kva for its
read(2) and write(2) handlers. So we have to return both.
Signed-off-by: Jared Hulbert <jaredeh@gmail.com>
Signed-off-by: Nick Piggin <npiggin@suse.de>
Cc: Carsten Otte <cotte@de.ibm.com>
Cc: Heiko Carstens <heiko.carstens@de.ibm.com>
Cc: linux-mm@kvack.org
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Diffstat (limited to 'fs/ext2')
-rw-r--r-- | fs/ext2/xip.c | 24 |
1 files changed, 14 insertions, 10 deletions
diff --git a/fs/ext2/xip.c b/fs/ext2/xip.c index ca7f00312388..430b4c8ee971 100644 --- a/fs/ext2/xip.c +++ b/fs/ext2/xip.c | |||
@@ -16,11 +16,13 @@ | |||
16 | 16 | ||
17 | static inline int | 17 | static inline int |
18 | __inode_direct_access(struct inode *inode, sector_t sector, | 18 | __inode_direct_access(struct inode *inode, sector_t sector, |
19 | unsigned long *data) | 19 | void **kaddr, unsigned long *pfn) |
20 | { | 20 | { |
21 | BUG_ON(!inode->i_sb->s_bdev->bd_disk->fops->direct_access); | 21 | struct block_device *bdev = inode->i_sb->s_bdev; |
22 | return inode->i_sb->s_bdev->bd_disk->fops | 22 | struct block_device_operations *ops = bdev->bd_disk->fops; |
23 | ->direct_access(inode->i_sb->s_bdev,sector,data); | 23 | |
24 | BUG_ON(!ops->direct_access); | ||
25 | return ops->direct_access(bdev, sector, kaddr, pfn); | ||
24 | } | 26 | } |
25 | 27 | ||
26 | static inline int | 28 | static inline int |
@@ -48,12 +50,13 @@ int | |||
48 | ext2_clear_xip_target(struct inode *inode, int block) | 50 | ext2_clear_xip_target(struct inode *inode, int block) |
49 | { | 51 | { |
50 | sector_t sector = block * (PAGE_SIZE/512); | 52 | sector_t sector = block * (PAGE_SIZE/512); |
51 | unsigned long data; | 53 | void *kaddr; |
54 | unsigned long pfn; | ||
52 | int rc; | 55 | int rc; |
53 | 56 | ||
54 | rc = __inode_direct_access(inode, sector, &data); | 57 | rc = __inode_direct_access(inode, sector, &kaddr, &pfn); |
55 | if (!rc) | 58 | if (!rc) |
56 | clear_page((void*)data); | 59 | clear_page(kaddr); |
57 | return rc; | 60 | return rc; |
58 | } | 61 | } |
59 | 62 | ||
@@ -74,7 +77,8 @@ ext2_get_xip_page(struct address_space *mapping, sector_t offset, | |||
74 | int create) | 77 | int create) |
75 | { | 78 | { |
76 | int rc; | 79 | int rc; |
77 | unsigned long data; | 80 | void *kaddr; |
81 | unsigned long pfn; | ||
78 | sector_t sector; | 82 | sector_t sector; |
79 | 83 | ||
80 | /* first, retrieve the sector number */ | 84 | /* first, retrieve the sector number */ |
@@ -84,9 +88,9 @@ ext2_get_xip_page(struct address_space *mapping, sector_t offset, | |||
84 | 88 | ||
85 | /* retrieve address of the target data */ | 89 | /* retrieve address of the target data */ |
86 | rc = __inode_direct_access | 90 | rc = __inode_direct_access |
87 | (mapping->host, sector * (PAGE_SIZE/512), &data); | 91 | (mapping->host, sector * (PAGE_SIZE/512), &kaddr, &pfn); |
88 | if (!rc) | 92 | if (!rc) |
89 | return virt_to_page(data); | 93 | return pfn_to_page(pfn); |
90 | 94 | ||
91 | error: | 95 | error: |
92 | return ERR_PTR(rc); | 96 | return ERR_PTR(rc); |