diff options
Diffstat (limited to 'fs/ext2/xip.c')
-rw-r--r-- | fs/ext2/xip.c | 93 |
1 files changed, 93 insertions, 0 deletions
diff --git a/fs/ext2/xip.c b/fs/ext2/xip.c new file mode 100644 index 000000000000..ca7f00312388 --- /dev/null +++ b/fs/ext2/xip.c @@ -0,0 +1,93 @@ +/* + * linux/fs/ext2/xip.c + * + * Copyright (C) 2005 IBM Corporation + * Author: Carsten Otte (cotte@de.ibm.com) + */ + +#include <linux/mm.h> +#include <linux/fs.h> +#include <linux/genhd.h> +#include <linux/buffer_head.h> +#include <linux/ext2_fs_sb.h> +#include <linux/ext2_fs.h> +#include "ext2.h" +#include "xip.h" + +static inline int +__inode_direct_access(struct inode *inode, sector_t sector, + unsigned long *data) +{ + BUG_ON(!inode->i_sb->s_bdev->bd_disk->fops->direct_access); + return inode->i_sb->s_bdev->bd_disk->fops + ->direct_access(inode->i_sb->s_bdev,sector,data); +} + +static inline int +__ext2_get_sector(struct inode *inode, sector_t offset, 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); + *result = tmp.b_blocknr; + + /* did we get a sparse block (hole in the file)? */ + if (!tmp.b_blocknr && !rc) { + BUG_ON(create); + rc = -ENODATA; + } + + return rc; +} + +int +ext2_clear_xip_target(struct inode *inode, int block) +{ + sector_t sector = block * (PAGE_SIZE/512); + unsigned long data; + int rc; + + rc = __inode_direct_access(inode, sector, &data); + if (!rc) + clear_page((void*)data); + return rc; +} + +void ext2_xip_verify_sb(struct super_block *sb) +{ + struct ext2_sb_info *sbi = EXT2_SB(sb); + + if ((sbi->s_mount_opt & EXT2_MOUNT_XIP) && + !sb->s_bdev->bd_disk->fops->direct_access) { + sbi->s_mount_opt &= (~EXT2_MOUNT_XIP); + ext2_warning(sb, __FUNCTION__, + "ignoring xip option - not supported by bdev"); + } +} + +struct page * +ext2_get_xip_page(struct address_space *mapping, sector_t offset, + int create) +{ + int rc; + unsigned long data; + sector_t sector; + + /* first, retrieve the sector number */ + rc = __ext2_get_sector(mapping->host, offset, create, §or); + if (rc) + goto error; + + /* retrieve address of the target data */ + rc = __inode_direct_access + (mapping->host, sector * (PAGE_SIZE/512), &data); + if (!rc) + return virt_to_page(data); + + error: + return ERR_PTR(rc); +} |