2005-06-24 09:05:26 +04:00
/*
* 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
2005-07-15 14:56:30 +04:00
__inode_direct_access ( struct inode * inode , sector_t sector ,
unsigned long * data )
{
2005-06-24 09:05:26 +04:00
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 ) ;
}
2005-07-15 14:56:30 +04:00
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)? */
2005-07-27 22:43:52 +04:00
if ( ! tmp . b_blocknr & & ! rc ) {
2005-07-15 14:56:30 +04:00
BUG_ON ( create ) ;
rc = - ENODATA ;
}
return rc ;
}
2005-06-24 09:05:26 +04:00
int
2005-07-15 14:56:30 +04:00
ext2_clear_xip_target ( struct inode * inode , int block )
{
sector_t sector = block * ( PAGE_SIZE / 512 ) ;
2005-06-24 09:05:26 +04:00
unsigned long data ;
int rc ;
rc = __inode_direct_access ( inode , sector , & data ) ;
2005-07-15 14:56:30 +04:00
if ( ! rc )
clear_page ( ( void * ) data ) ;
return rc ;
2005-06-24 09:05:26 +04:00
}
void ext2_xip_verify_sb ( struct super_block * sb )
{
struct ext2_sb_info * sbi = EXT2_SB ( sb ) ;
2005-07-15 14:56:30 +04:00
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 " ) ;
2005-06-24 09:05:26 +04:00
}
}
2005-07-15 14:56:30 +04:00
struct page *
ext2_get_xip_page ( struct address_space * mapping , sector_t offset ,
2005-06-24 09:05:26 +04:00
int create )
{
int rc ;
unsigned long data ;
2005-07-15 14:56:30 +04:00
sector_t sector ;
2005-06-24 09:05:26 +04:00
2005-07-15 14:56:30 +04:00
/* first, retrieve the sector number */
rc = __ext2_get_sector ( mapping - > host , offset , create , & sector ) ;
2005-06-24 09:05:26 +04:00
if ( rc )
2005-07-15 14:56:30 +04:00
goto error ;
2005-06-24 09:05:26 +04:00
2005-07-15 14:56:30 +04:00
/* retrieve address of the target data */
2005-06-24 09:05:26 +04:00
rc = __inode_direct_access
2005-07-15 14:56:30 +04:00
( mapping - > host , sector * ( PAGE_SIZE / 512 ) , & data ) ;
if ( ! rc )
return virt_to_page ( data ) ;
2005-06-24 09:05:26 +04:00
2005-07-15 14:56:30 +04:00
error :
return ERR_PTR ( rc ) ;
2005-06-24 09:05:26 +04:00
}