Signed-off-by: Josef 'Jeff' Sipek <jeffpc@xxxxxxxxxxxxxx> --- fs/cmsfs/bmap.c | 104 +++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 files changed, 104 insertions(+), 0 deletions(-) create mode 100644 fs/cmsfs/bmap.c diff --git a/fs/cmsfs/bmap.c b/fs/cmsfs/bmap.c new file mode 100644 index 0000000..ce9eccf --- /dev/null +++ b/fs/cmsfs/bmap.c @@ -0,0 +1,104 @@ +/* + * CMSFS + * + * (C) 2008 Josef 'Jeff' Sipek <jeffpc@xxxxxxxxxxxxxx> + * + * Based on cmsfs from 2.4.12-ac6: + * + * (C) 2001 Rick Troth <rtroth@xxxxxxx> + * (C) 2001 BMC Software, Inc., Houston, Texas, USA + * + */ + +#include <linux/mm.h> +#include <linux/slab.h> +#include <linux/fs.h> +#include <linux/buffer_head.h> +#include <linux/mpage.h> + +#include "cmsfs.h" + +/** + * cmsfs_get_blocks - map a inode offset to a disk block + * @inode: inode to map + * @iblock: inode offset to map (in fs blocks) + * @bh_result: resulting buffer_head + * @create: ? + */ +static int cmsfs_get_blocks(struct inode *inode, sector_t iblock, + struct buffer_head *bh_result, int create) +{ + struct cmsfs_inode_info *cinode = CMSFS_I(inode); + struct super_block *sb = inode->i_sb; + struct buffer_head *bh; + + BUG_ON(create); + + /* indirection? */ + if (cinode->level != 0) { + int ptrs_per_blk; + int i, lvl; + void *bp; + u32 b1, b2; + + b2 = ~0; /* to avoid potentially uninit var warning */ + + /* pointers per block */ + if (cinode->psize > 0) + ptrs_per_blk = CMSFS_SB(sb)->blksz / cinode->psize; + else + ptrs_per_blk = CMSFS_SB(sb)->blksz / 4; + + /* read first block for indirection */ + b1 = iblock; + for (i = 0; i < cinode->level; i++) + b1 = b1 / ptrs_per_blk; + bh = sb_bread(sb, cinode->origin - 1 + b1); + if (!bh) + goto fail; + + for (lvl = 1; lvl <= cinode->level; lvl++) { + /* read next block for indirection */ + b1 = iblock; + for (i = lvl; i < cinode->level; i++) + b1 = b1 / ptrs_per_blk; + b1 = b1 % ptrs_per_blk; + bp = bh->b_data; + bp += b1 * cinode->psize; + b2 = be32_to_cpu(*(u32*)bp); + + brelse(bh); + + /* read next block for indirection */ + bh = sb_bread(sb, b2 - 1); + if (!bh) + goto fail; + } + + clear_buffer_new(bh_result); + map_bh(bh_result, inode->i_sb, b2-1); + } else { + clear_buffer_new(bh_result); + map_bh(bh_result, inode->i_sb, + cinode->origin - 1 + iblock); + } + + return 0; + +fail: + return -EIO; +} + +/** + * cmsfs_readpage - read a page for an inode + * @unused: (unused) + * @page: page to read + */ +static int cmsfs_readpage(struct file *unused, struct page *page) +{ + return mpage_readpage(page, cmsfs_get_blocks); +} + +struct address_space_operations cmsfs_aops = { + .readpage = cmsfs_readpage, +}; -- 1.5.6.3 -- To unsubscribe from this list: send the line "unsubscribe linux-fsdevel" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html