1/* 2 * linux/fs/ext2/xip.c 3 * 4 * Copyright (C) 2005 IBM Corporation 5 * Author: Carsten Otte (cotte@de.ibm.com) 6 */ 7 8#include <linux/mm.h> 9#include <linux/fs.h> 10#include <linux/genhd.h> 11#include <linux/buffer_head.h> 12#include <linux/ext2_fs_sb.h> 13#include <linux/ext2_fs.h> 14#include <linux/blkdev.h> 15#include "ext2.h" 16#include "xip.h" 17 18static inline int 19__inode_direct_access(struct inode *inode, sector_t block, 20 void **kaddr, unsigned long *pfn) 21{ 22 struct block_device *bdev = inode->i_sb->s_bdev; 23 const struct block_device_operations *ops = bdev->bd_disk->fops; 24 sector_t sector; 25 26 sector = block * (PAGE_SIZE / 512); /* ext2 block to bdev sector */ 27 28 BUG_ON(!ops->direct_access); 29 return ops->direct_access(bdev, sector, kaddr, pfn); 30} 31 32static inline int 33__ext2_get_block(struct inode *inode, pgoff_t pgoff, int create, 34 sector_t *result) 35{ 36 struct buffer_head tmp; 37 int rc; 38 39 memset(&tmp, 0, sizeof(struct buffer_head)); 40 rc = ext2_get_block(inode, pgoff, &tmp, create); 41 *result = tmp.b_blocknr; 42 43 /* did we get a sparse block (hole in the file)? */ 44 if (!tmp.b_blocknr && !rc) { 45 BUG_ON(create); 46 rc = -ENODATA; 47 } 48 49 return rc; 50} 51 52int 53ext2_clear_xip_target(struct inode *inode, sector_t block) 54{ 55 void *kaddr; 56 unsigned long pfn; 57 int rc; 58 59 rc = __inode_direct_access(inode, block, &kaddr, &pfn); 60 if (!rc) 61 clear_page(kaddr); 62 return rc; 63} 64 65void ext2_xip_verify_sb(struct super_block *sb) 66{ 67 struct ext2_sb_info *sbi = EXT2_SB(sb); 68 69 if ((sbi->s_mount_opt & EXT2_MOUNT_XIP) && 70 !sb->s_bdev->bd_disk->fops->direct_access) { 71 sbi->s_mount_opt &= (~EXT2_MOUNT_XIP); 72 ext2_msg(sb, KERN_WARNING, 73 "warning: ignoring xip option - " 74 "not supported by bdev"); 75 } 76} 77 78int ext2_get_xip_mem(struct address_space *mapping, pgoff_t pgoff, int create, 79 void **kmem, unsigned long *pfn) 80{ 81 int rc; 82 sector_t block; 83 84 /* first, retrieve the sector number */ 85 rc = __ext2_get_block(mapping->host, pgoff, create, &block); 86 if (rc) 87 return rc; 88 89 /* retrieve address of the target data */ 90 rc = __inode_direct_access(mapping->host, block, kmem, pfn); 91 return rc; 92} 93