diff options
Diffstat (limited to 'fs/efs/file.c')
-rw-r--r-- | fs/efs/file.c | 200 |
1 files changed, 48 insertions, 152 deletions
diff --git a/fs/efs/file.c b/fs/efs/file.c index e30ac301b..405143225 100644 --- a/fs/efs/file.c +++ b/fs/efs/file.c @@ -1,169 +1,65 @@ /* - * linux/fs/efs/file.c + * file.c * - * Copyright (C) 1998 Mike Shaver + * Copyright (c) 1999 Al Smith * - * Portions derived from work (C) 1995,1996 Christian Vogelgsang. - * ``Inspired by'' fs/minix/file.c. + * Portions derived from work (c) 1995,1996 Christian Vogelgsang. */ -#include <linux/efs_fs.h> +#include <linux/efs.h> static struct file_operations efs_file_operations = { - NULL, /* lseek */ - generic_file_read, - NULL, /* write */ - NULL, /* readdir */ - NULL, /* poll */ - NULL, /* ioctl */ - generic_file_mmap, /* mmap */ - NULL, /* open */ - NULL, /* flush */ - NULL, /* release */ - NULL /* fsync */ + NULL, /* lseek */ + generic_file_read, + NULL, /* write */ + NULL, /* readdir */ + NULL, /* poll */ + NULL, /* ioctl */ + generic_file_mmap, + NULL, /* flush */ + NULL, /* no special release code */ + NULL /* fsync */ }; struct inode_operations efs_file_inode_operations = { - &efs_file_operations, /* default file ops */ - NULL, /* create */ - NULL, /* lookup */ - NULL, /* link */ - NULL, /* unlink */ - NULL, /* symlink */ - NULL, /* mkdir */ - NULL, /* rmdir */ - NULL, /* mknod */ - NULL, /* rename */ - NULL, /* readlink */ - NULL, /* follow_link */ - generic_readpage, /* readpage */ - NULL, /* writepage */ - efs_bmap, /* bmap */ - NULL, /* truncate */ - NULL /* permission */ + &efs_file_operations, + NULL, /* create */ + NULL, /* lookup */ + NULL, /* link */ + NULL, /* unlink */ + NULL, /* symlink */ + NULL, /* mkdir */ + NULL, /* rmdir */ + NULL, /* mknod */ + NULL, /* rename */ + NULL, /* readlink */ + NULL, /* follow_link */ + generic_readpage, + NULL, /* writepage */ + efs_bmap, + NULL, /* truncate */ + NULL /* permission */ }; + +int efs_bmap(struct inode *inode, efs_block_t block) { -static inline __u32 -check_extent(union efs_extent *ext, int blk, int fs_start) -{ - int eblk, epos, elen; - - eblk = ext->ex_bytes[0]; /* start disk block of the extent */ - epos = ext->ex_bytes[1] & 0xFFFFFF; /* starting logical block */ - elen = ext->ex_bytes[1] >> 24; /* length of the extent */ - - if ( (blk >= epos) && (blk < epos+elen) ) - return blk - epos + eblk + fs_start; - return 0; -} - -#define CHECK(index) (check_extent(&ini->extents[index], blk, sbi->fs_start)) - -static __u32 -efs_getblk(struct inode *in, __u32 blk) -{ - struct efs_sb_info *sbi = &in->i_sb->u.efs_sb; - struct efs_inode_info *ini = &in->u.efs_i; - int iter; - - __u32 diskblk, total = ini->tot, current = ini->cur; - - if (total <= EFS_MAX_EXTENTS) { - diskblk = CHECK(current); - if (diskblk) - return diskblk; - - if (total == 1) - return 0; - - /* - * OPT: start with current and then wrap, to optimize for - * read-forward pattern. - */ - for (iter = 0; iter < total; iter++) { - if (iter == current) - continue; /* already checked the current extent */ - diskblk = CHECK(iter); - if (diskblk) { - ini->cur = iter; - DB(("EFS: inode %ld: found block %d as %d in ext %d\n", - in->i_ino, blk, diskblk, iter)); - return diskblk; - } + if (block < 0) { + printk("EFS: efs_bmap(): block < 0\n"); + return 0; } - DB(("EFS: block %d not found in direct inode %ld (size %ld)\n", - blk, in->i_ino, (long)in->i_size)); - return 0; - - } else { - int indirext = 0, total_extents_checked = 0; - - /* indirect inode */ - DB(("EFS: inode %ld is indirect (total %d, indir ", in->i_ino, total)); - total = ini->extents[0].ex_ex.ex_offset; - DB(("%d)\n", total)); - - for (indirext = 0; indirext < total; indirext++) { - struct buffer_head *extbh; - union efs_extent *ptr; - int indirblk, indirbn, indirlen; - /* - * OPT: copy the current direct extent into the inode info for a - * quick check before we start reading blocks. - * OPT: copy _10_ into the inode info, like the old code did. - */ - - indirbn = ini->extents[indirext].ex_ex.ex_bn; - indirlen = ini->extents[indirext].ex_ex.ex_length; - for (indirblk = indirbn; - indirblk < indirbn + indirlen; - indirblk++) { - extbh = bread(in->i_dev, indirblk, EFS_BLOCK_SIZE); - if (!extbh) { - printk("EFS: ERROR: inode %ld bread of extent block %d failed\n", - in->i_ino, indirblk); - return 0; - } - - for (ptr = (union efs_extent *)extbh->b_data; - ptr < (union efs_extent *)(extbh->b_data+EFS_BLOCK_SIZE); - ptr++, ++total_extents_checked) { - - diskblk = check_extent(ptr, blk, sbi->fs_start); - if (diskblk || total_extents_checked > ini->tot) { - brelse(extbh); - return diskblk; - } - } - - brelse(extbh); - } + /* are we about to read past the end of a file ? */ + if (block > inode->i_blocks) { +#ifdef DEBUG + /* dunno why this happens */ + printk("EFS: efs_bmap(): block %d > last block %ld (filesize %ld)\n", + block, + inode->i_blocks, + inode->i_size); +#endif + return 0; } - DB(("EFS: inode %ld: didn't find block %d (indir search, size %ld)\n", - in->i_ino, blk, (long)in->i_size)); - return 0; - } -} - -int efs_bmap(struct inode *in, int block) -{ - if (block < 0) - return 0; - - if (!in->i_size) { - DB(("EFS: um, inode %ld has size 0. What up?\n", in->i_ino)); - } - /* - * the kernel wants a full page (== 4K == 8 EFS blocks), so be sure that - * the block number isn't too large for that. - */ - if (block > ((in->i_size - 1) >> EFS_BLOCK_SIZE_BITS)) { - DB(("EFS: wacky: block %d > max %ld\n", block, - ((in->i_size - 1) >> EFS_BLOCK_SIZE_BITS))); - return 0; - } - - return efs_getblk(in, block); + return efs_read_block(inode, block); } + |