linux/fs/ext2/xip.c
<<
>>
Prefs
   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