Skip to content

Commit

Permalink
xip: support non-struct page backed memory
Browse files Browse the repository at this point in the history
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 <[email protected]>
Acked-by: Carsten Otte <[email protected]>
Cc: Jared Hulbert <[email protected]>
Cc: Martin Schwidefsky <[email protected]>
Cc: Heiko Carstens <[email protected]>
Signed-off-by: Andrew Morton <[email protected]>
Signed-off-by: Linus Torvalds <[email protected]>
  • Loading branch information
Nick Piggin authored and torvalds committed Apr 28, 2008
1 parent 30afcb4 commit 70688e4
Show file tree
Hide file tree
Showing 8 changed files with 126 additions and 132 deletions.
2 changes: 1 addition & 1 deletion fs/ext2/inode.c
Original file line number Diff line number Diff line change
Expand Up @@ -796,7 +796,7 @@ const struct address_space_operations ext2_aops = {

const struct address_space_operations ext2_aops_xip = {
.bmap = ext2_bmap,
.get_xip_page = ext2_get_xip_page,
.get_xip_mem = ext2_get_xip_mem,
};

const struct address_space_operations ext2_nobh_aops = {
Expand Down
37 changes: 15 additions & 22 deletions fs/ext2/xip.c
Original file line number Diff line number Diff line change
Expand Up @@ -15,26 +15,28 @@
#include "xip.h"

static inline int
__inode_direct_access(struct inode *inode, sector_t sector,
__inode_direct_access(struct inode *inode, sector_t block,
void **kaddr, unsigned long *pfn)
{
struct block_device *bdev = inode->i_sb->s_bdev;
struct block_device_operations *ops = bdev->bd_disk->fops;
sector_t sector;

sector = block * (PAGE_SIZE / 512); /* ext2 block to bdev sector */

BUG_ON(!ops->direct_access);
return ops->direct_access(bdev, sector, kaddr, pfn);
}

static inline int
__ext2_get_sector(struct inode *inode, sector_t offset, int create,
__ext2_get_block(struct inode *inode, pgoff_t pgoff, int create,
sector_t *result)
{
struct buffer_head tmp;
int rc;

memset(&tmp, 0, sizeof(struct buffer_head));
rc = ext2_get_block(inode, offset/ (PAGE_SIZE/512), &tmp,
create);
rc = ext2_get_block(inode, pgoff, &tmp, create);
*result = tmp.b_blocknr;

/* did we get a sparse block (hole in the file)? */
Expand All @@ -47,14 +49,13 @@ __ext2_get_sector(struct inode *inode, sector_t offset, int create,
}

int
ext2_clear_xip_target(struct inode *inode, int block)
ext2_clear_xip_target(struct inode *inode, sector_t block)
{
sector_t sector = block * (PAGE_SIZE/512);
void *kaddr;
unsigned long pfn;
int rc;

rc = __inode_direct_access(inode, sector, &kaddr, &pfn);
rc = __inode_direct_access(inode, block, &kaddr, &pfn);
if (!rc)
clear_page(kaddr);
return rc;
Expand All @@ -72,26 +73,18 @@ void ext2_xip_verify_sb(struct super_block *sb)
}
}

struct page *
ext2_get_xip_page(struct address_space *mapping, sector_t offset,
int create)
int ext2_get_xip_mem(struct address_space *mapping, pgoff_t pgoff, int create,
void **kmem, unsigned long *pfn)
{
int rc;
void *kaddr;
unsigned long pfn;
sector_t sector;
sector_t block;

/* first, retrieve the sector number */
rc = __ext2_get_sector(mapping->host, offset, create, &sector);
rc = __ext2_get_block(mapping->host, pgoff, create, &block);
if (rc)
goto error;
return rc;

/* retrieve address of the target data */
rc = __inode_direct_access
(mapping->host, sector * (PAGE_SIZE/512), &kaddr, &pfn);
if (!rc)
return pfn_to_page(pfn);

error:
return ERR_PTR(rc);
rc = __inode_direct_access(mapping->host, block, kmem, pfn);
return rc;
}
9 changes: 5 additions & 4 deletions fs/ext2/xip.h
Original file line number Diff line number Diff line change
Expand Up @@ -7,19 +7,20 @@

#ifdef CONFIG_EXT2_FS_XIP
extern void ext2_xip_verify_sb (struct super_block *);
extern int ext2_clear_xip_target (struct inode *, int);
extern int ext2_clear_xip_target (struct inode *, sector_t);

static inline int ext2_use_xip (struct super_block *sb)
{
struct ext2_sb_info *sbi = EXT2_SB(sb);
return (sbi->s_mount_opt & EXT2_MOUNT_XIP);
}
struct page* ext2_get_xip_page (struct address_space *, sector_t, int);
#define mapping_is_xip(map) unlikely(map->a_ops->get_xip_page)
int ext2_get_xip_mem(struct address_space *, pgoff_t, int,
void **, unsigned long *);
#define mapping_is_xip(map) unlikely(map->a_ops->get_xip_mem)
#else
#define mapping_is_xip(map) 0
#define ext2_xip_verify_sb(sb) do { } while (0)
#define ext2_use_xip(sb) 0
#define ext2_clear_xip_target(inode, chain) 0
#define ext2_get_xip_page NULL
#define ext2_get_xip_mem NULL
#endif
2 changes: 1 addition & 1 deletion fs/open.c
Original file line number Diff line number Diff line change
Expand Up @@ -837,7 +837,7 @@ static struct file *__dentry_open(struct dentry *dentry, struct vfsmount *mnt,
if (f->f_flags & O_DIRECT) {
if (!f->f_mapping->a_ops ||
((!f->f_mapping->a_ops->direct_IO) &&
(!f->f_mapping->a_ops->get_xip_page))) {
(!f->f_mapping->a_ops->get_xip_mem))) {
fput(f);
f = ERR_PTR(-EINVAL);
}
Expand Down
4 changes: 2 additions & 2 deletions include/linux/fs.h
Original file line number Diff line number Diff line change
Expand Up @@ -474,8 +474,8 @@ struct address_space_operations {
int (*releasepage) (struct page *, gfp_t);
ssize_t (*direct_IO)(int, struct kiocb *, const struct iovec *iov,
loff_t offset, unsigned long nr_segs);
struct page* (*get_xip_page)(struct address_space *, sector_t,
int);
int (*get_xip_mem)(struct address_space *, pgoff_t, int,
void **, unsigned long *);
/* migrate the contents of a page to the specified target */
int (*migratepage) (struct address_space *,
struct page *, struct page *);
Expand Down
2 changes: 1 addition & 1 deletion mm/fadvise.c
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,7 @@ asmlinkage long sys_fadvise64_64(int fd, loff_t offset, loff_t len, int advice)
goto out;
}

if (mapping->a_ops->get_xip_page) {
if (mapping->a_ops->get_xip_mem) {
switch (advice) {
case POSIX_FADV_NORMAL:
case POSIX_FADV_RANDOM:
Expand Down
Loading

0 comments on commit 70688e4

Please sign in to comment.