X-Git-Url: https://err.no/cgi-bin/gitweb.cgi?a=blobdiff_plain;f=fs%2Fext2%2Fxip.c;h=4fb94c20041b5e44c5ee2152a151bf65e486daa9;hb=6924d1ab8b7bbe5ab416713f5701b3316b2df85b;hp=d44431d1a338cd24e3c054b789fc46b2c219a755;hpb=aef7b83c92dd0b7e994805440655d1d64147287b;p=linux-2.6 diff --git a/fs/ext2/xip.c b/fs/ext2/xip.c index d44431d1a3..4fb94c2004 100644 --- a/fs/ext2/xip.c +++ b/fs/ext2/xip.c @@ -15,66 +15,76 @@ #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); +__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_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, pgoff, &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; +ext2_clear_xip_target(struct inode *inode, sector_t block) +{ + void *kaddr; + unsigned long pfn; int rc; - rc = __inode_direct_access(inode, sector, &data); - if (rc) - return rc; - clear_page((void*)data); - return 0; + rc = __inode_direct_access(inode, block, &kaddr, &pfn); + if (!rc) + clear_page(kaddr); + 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)) { - if ((sb->s_bdev == NULL) || - sb->s_bdev->bd_disk == NULL || - sb->s_bdev->bd_disk->fops == NULL || - sb->s_bdev->bd_disk->fops->direct_access == NULL) { - sbi->s_mount_opt &= (~EXT2_MOUNT_XIP); - ext2_warning(sb, __FUNCTION__, - "ignoring xip option - not supported by bdev"); - } + 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, __func__, + "ignoring xip option - not supported by bdev"); } } -struct page* -ext2_get_xip_page(struct address_space *mapping, sector_t blockno, - int create) +int ext2_get_xip_mem(struct address_space *mapping, pgoff_t pgoff, int create, + void **kmem, unsigned long *pfn) { int rc; - unsigned long data; - struct buffer_head tmp; + sector_t block; - tmp.b_state = 0; - tmp.b_blocknr = 0; - rc = ext2_get_block(mapping->host, blockno/(PAGE_SIZE/512) , &tmp, - create); + /* first, retrieve the sector number */ + rc = __ext2_get_block(mapping->host, pgoff, create, &block); if (rc) - return ERR_PTR(rc); - if (tmp.b_blocknr == 0) { - /* SPARSE block */ - BUG_ON(create); - return ERR_PTR(-ENODATA); - } - - rc = __inode_direct_access - (mapping->host,tmp.b_blocknr*(PAGE_SIZE/512) ,&data); - if (rc) - return ERR_PTR(rc); + return rc; - SetPageUptodate(virt_to_page(data)); - return virt_to_page(data); + /* retrieve address of the target data */ + rc = __inode_direct_access(mapping->host, block, kmem, pfn); + return rc; }