diff options
author | Mike Shaver <shaver@ingenia.com> | 1998-05-27 14:14:52 +0000 |
---|---|---|
committer | Mike Shaver <shaver@ingenia.com> | 1998-05-27 14:14:52 +0000 |
commit | fd6df4960deca7a60c11720fdc9e2d20d4b80eb0 (patch) | |
tree | c22717fc06d0ff303f0fd2427a5e96df01cb992b /fs/efs/inode.c | |
parent | cad646a41d689e717fec6272cba6cdd1258381c8 (diff) |
some fixes and streamlining of code; indirect extents still don't work right =(
Diffstat (limited to 'fs/efs/inode.c')
-rw-r--r-- | fs/efs/inode.c | 333 |
1 files changed, 196 insertions, 137 deletions
diff --git a/fs/efs/inode.c b/fs/efs/inode.c index a75d44956..6fae52e86 100644 --- a/fs/efs/inode.c +++ b/fs/efs/inode.c @@ -12,14 +12,15 @@ #include <linux/efs_fs_i.h> #include <linux/efs_fs_sb.h> #include <linux/locks.h> +#include <linux/malloc.h> #include <asm/uaccess.h> /* ----- Define the operations for the Superblock ----- */ -void efs_read_inode(struct inode *); -void efs_put_inode(struct inode *); -void efs_put_super(struct super_block *); -int efs_statfs(struct super_block *, struct statfs *,int ); +static void efs_read_inode(struct inode *); +static void efs_put_inode(struct inode *); +static void efs_put_super(struct super_block *); +static int efs_statfs(struct super_block *, struct statfs *,int ); static struct super_operations efs_sops = { efs_read_inode, @@ -34,7 +35,7 @@ static struct super_operations efs_sops = { }; static void efs_put_inode(struct inode *i) { - printk("efs_put_inode: iput()ting inode %d\n", i->i_ino); + printk("efs_put_inode: iput()ting inode %#0lx\n", i->i_ino); } @@ -255,14 +256,14 @@ struct super_block *efs_read_super(struct super_block *s, void *d, int silent) /* Read the Superblock */ if(!error) { -#ifdef DEBUG_EFS +#ifdef DEBUG_EFS_SB if (!silent) printk("EFS: reading superblock.\n"); #endif bh = bread(dev, EFS_BLK_SUPER, EFS_BLOCK_SIZE ); if(bh) { es = (struct efs_super_block *)(bh->b_data); -#ifdef DEBUG_EFS +#ifdef DEBUG_EFS_SB if(!silent) efs_dump_super(es); #endif @@ -319,7 +320,7 @@ struct super_block *efs_read_super(struct super_block *s, void *d, int silent) s - superblock */ -void efs_put_super(struct super_block *s) +static void efs_put_super(struct super_block *s) { lock_super(s); s->s_dev = 0; @@ -334,7 +335,7 @@ void efs_put_super(struct super_block *s) s - superblock of fs buf - statfs struct that has to be filled */ -int efs_statfs(struct super_block *s, struct statfs *buf,int bufsize) +static int efs_statfs(struct super_block *s, struct statfs *buf,int bufsize) { struct efs_sb_info *sbi = (struct efs_sb_info *)&s->u.generic_sbp; struct statfs tmp; @@ -360,144 +361,202 @@ int efs_statfs(struct super_block *s, struct statfs *buf,int bufsize) */ void efs_read_inode(struct inode *in) { - struct buffer_head *bh; - struct efs_sb_info *sbi = (struct efs_sb_info *)&in->i_sb->u.generic_sbp; - __u32 blk,off; - int error = 0; + struct buffer_head *bh; + struct efs_sb_info *sbi = (struct efs_sb_info *)&in->i_sb->u.generic_sbp; + struct efs_disk_inode *di; + struct efs_inode_info *ini; + __u32 blk, off, rdev; + __u16 numext; + int i; + int error = 0; - /* Calc the discblock and the offset for inode (4 Nodes fit in one block) */ - blk = in->i_ino >> 2; - blk = sbi->fs_start + sbi->first_block + - (sbi->group_size * (blk / sbi->inode_blocks)) + - (blk % sbi->inode_blocks); - off = (in->i_ino&3)<<7; + /* + * Find the block and offset for desired inode (4 inodes fit in one block) + */ + blk = in->i_ino >> 2; + blk = sbi->fs_start + sbi->first_block + + (sbi->group_size * (blk / sbi->inode_blocks)) + + (blk % sbi->inode_blocks); + off = (in->i_ino&3)<<7; - /* Read the block with the inode from disk */ -#ifdef DEBUG_EFS - printk("EFS: looking for inode %#lx\n", in->i_ino); + /* Read the block with the inode from disk */ +#ifdef DEBUG_EFS_INODE + printk("EFS: looking for inode %#lx at %d/%d\n", in->i_ino, blk, off); #endif - bh = bread(in->i_dev,blk,EFS_BLOCK_SIZE); - if(bh) { - - struct efs_disk_inode *di = (struct efs_disk_inode *)(bh->b_data + off); - __u16 numext; - struct efs_inode_info *ini = &in->u.efs_i; - __u32 rdev; - int i; - - /* fill in standard inode infos */ - in->i_mtime = efs_swab32(di->di_mtime); - in->i_ctime = efs_swab32(di->di_ctime); - in->i_atime = efs_swab32(di->di_atime); - in->i_size = efs_swab32(di->di_size); - in->i_nlink = efs_swab16(di->di_nlink); - in->i_uid = efs_swab16(di->di_uid); - in->i_gid = efs_swab16(di->di_gid); - in->i_mode = efs_swab16(di->di_mode); - - /* Special files store their rdev value where the extends of - a regular file are found */ - /* rdev = ConvertLong(rawnode,EFS_IN_EXTENTS);*/ - /* XXX this isn't right */ - rdev = efs_swab32(*(__u32 *)&di->di_u.di_dev); + bh = bread(in->i_dev,blk,EFS_BLOCK_SIZE); + if (!bh) { + printk("EFS: can't read physical block %d for inode %#lx\n", + blk, in->i_ino); + return; + } + di = (struct efs_disk_inode *)(bh->b_data + off); + ini = &in->u.efs_i; + + /* fill in standard inode infos */ + in->i_mtime = efs_swab32(di->di_mtime); + in->i_ctime = efs_swab32(di->di_ctime); + in->i_atime = efs_swab32(di->di_atime); + in->i_size = efs_swab32(di->di_size); + in->i_nlink = efs_swab16(di->di_nlink); + in->i_uid = efs_swab16(di->di_uid); + in->i_gid = efs_swab16(di->di_gid); + in->i_mode = efs_swab16(di->di_mode); + + /* Special files store their rdev value where the extends of + a regular file are found */ + /* rdev = ConvertLong(rawnode,EFS_IN_EXTENTS);*/ + /* XXX this isn't right */ + rdev = efs_swab32(*(__u32 *)&di->di_u.di_dev); - /* ----------------------------------------------------------------- - The following values are stored in my private part of the Inode. - They are necessary for further operations with the file */ - - /* get the number of extends the inode posseses */ - numext = efs_swab16(di->di_numextents); - - /* if this inode has more than EFS_MAX_EXTENDS then the extends are - stored not directly in the inode but indirect on an extra block. - The address of the extends-block is stored in the inode */ - if(numext>EFS_MAX_EXTENTS) { - struct buffer_head *bh2; - printk("EFS: inode #%lx has > EFS_MAX_EXTENTS (%d)\n", - in->i_ino, numext); - - /* Store the discblock and offset of extend-list in Inode info */ - ini->extblk = sbi->fs_start + efs_swab32((__u32)(di->di_u.di_extents)); - - /* read INI_MAX_EXT extents from the indirect block */ - printk("EFS: "); - bh2 = bread(in->i_dev,ini->extblk,EFS_BLOCK_SIZE); - if(bh2) { - union efs_extent *ptr = - (union efs_extent *)bh2->b_data; - for(i=0;i<EFS_MAX_EXTENTS;i++) { - ini->extents[i].ex_bytes[0] = efs_swab32(ptr[i].ex_bytes[0]); - ini->extents[i].ex_bytes[1] = efs_swab32(ptr[i].ex_bytes[1]); - } - brelse(bh2); - } else - printk("efs: failed reading indirect extents!\n"); + /* get the number of extends the inode posseses */ + numext = efs_swab16(di->di_numextents); + ini->efs_extents = kmalloc(sizeof(union efs_extent) * numext, GFP_KERNEL); + if (!ini->efs_extents) { + printk("EFS: not enough memory\n"); + brelse(bh); + return; + } + +#define COPY_EXTENT(from, to) \ + (to).ex_bytes[0] = efs_swab32((from).ex_bytes[0]); \ + (to).ex_bytes[1] = efs_swab32((from).ex_bytes[1]); + +#define EXTENTS_PER_BLOCK (EFS_BLOCK_SIZE / sizeof (union efs_extent)) + + /* if this inode has more than EFS_MAX_EXTENDS then the extends are + stored not directly in the inode but indirect on an extra block. + The address of the extends-block is stored in the inode */ + if(numext>EFS_MAX_EXTENTS) { + __u32 numindirect, count; + union efs_extent indirect; + + numindirect = di->di_u.di_extents[0].ex_ex.ex_offset; +#if defined(DEBUG_EFS_INODE) || defined(DEBUG_EFS_EXTENTS) + printk("EFS: indirect inode #%lx has %d extents (%d indirect)\n", + in->i_ino, numext, numindirect); +#endif - } else { -#ifdef DEBUG_EFS - printk("EFS: inode %#lx is direct (woohoo!)\n", - in->i_ino); + count = 0; + for (i = 0; i < numindirect; i++) { + union efs_extent *ptr; + struct buffer_head *bh2; + __u32 extbytes, copybytes; + + COPY_EXTENT(di->di_u.di_extents[i], indirect); + if (numext - count > EXTENTS_PER_BLOCK) { + extbytes = indirect.ex_ex.ex_length * EFS_BLOCK_SIZE; + copybytes = extbytes; + } else { + extbytes = (numext - count) * sizeof (union efs_extent); + copybytes = (extbytes & ~511) + 512; + } + bh2 = bread(in->i_dev, indirect.ex_ex.ex_bn, copybytes); + if (!bh2) { + printk("EFS: failed reading indirect extents\n"); + brelse(bh); + return; + } + + ptr = (union efs_extent *)bh2->b_data; + +#ifdef __BIG_ENDIAN + /* we're the same endianness as EFS, so we can just copy them + into place */ + { + void * copyto = ini->efs_extents + count; +#ifdef DEBUG_EFS_EXTENTS_VERBOSE + union efs_extent *iter = copyto; + printk("EFS: copying %lx extbytes (%d exts) from %p to %p " + "(ini %p, ->efs_extents %p)\n", + extbytes, extbytes / sizeof (union efs_extent), + ptr, copyto, ini, ini->efs_extents); #endif - /* The extends are found in the inode block */ - ini->extblk = blk; - - /* copy extends directly from rawinode */ - for(i=0;i<numext;i++) { - ini->extents[i].ex_bytes[0] = efs_swab32(di->di_u.di_extents[i].ex_bytes[0]); - ini->extents[i].ex_bytes[1] = efs_swab32(di->di_u.di_extents[i].ex_bytes[1]); - } + bcopy((void *)ptr, copyto, extbytes); + count += extbytes / sizeof (union efs_extent); +#ifdef DEBUG_EFS_EXTENTS_VERBOSE + for(; iter < (char *)copyto + extbytes; iter++) { + printk("EFS: ext: [%08x%08x]: magic: %x bn: %0#6x " + "length: %0#2x offset: %0#6x\n", + iter->ex_bytes[0], iter->ex_bytes[1], + iter->ex_ex.ex_magic, iter->ex_ex.ex_bn, + iter->ex_ex.ex_length, iter->ex_ex.ex_offset); } - ini->tot = numext; - ini->cur = 0; +#endif + } +#else +#error "EFS not supported on __LITTLE_ENDIAN systems yet" +#if 0 + + for (j = 0; j < EXTENTS_PER_BLOCK * indirect.ex_ex.ex_length; j++){ + union efs_extent *_ext = &ini->efs_extents[count]; + COPY_EXTENT(ptr[k], *_ext); + +#ifdef DEBUG_EFS_EXTENTS_VERBOSE + printk("EFS: %d/%d: extent %d is %8d-%8d (phys %d)\n", + i, j, count, _ext->ex_ex.ex_offset, + _ext->ex_ex.ex_offset + _ext->ex_ex.ex_length, + _ext->ex_ex.ex_bn); +#endif - brelse(bh); + if (++count == numext) + break; + } +#endif /* 0 */ +#endif /* ENDIAN */ + brelse(bh2); + if (count == numext) + break; + } +#ifdef DEBUG_EFS_EXTENTS + printk("EFS: loaded %d of %d extents from indirect inode %#0lx\n", + count, numext, in->i_ino); +#endif + } else { +#if defined(DEBUG_EFS_INODE) || defined(DEBUG_EFS_EXTENTS) + printk("EFS: inode %#lx is direct with %d extents\n", + in->i_ino, numext); +#endif + /* copy extends directly from rawinode */ + for(i=0; i<numext; i++) { + COPY_EXTENT(di->di_u.di_extents[i], ini->efs_extents[i]); + } + } + ini->efs_total = numext; + ini->efs_current = 0; -#ifdef DEBUG_EFS - printk("%lx inode: blk %lx numext %x\n",in->i_ino,ini->extblk,numext); - efs_dump_inode(di); + brelse(bh); + +#ifdef DEBUG_EFS_INODE + printk("%lx inode: blk %lx numext %x\n",in->i_ino,ini->extblk,numext); + efs_dump_inode(di); #endif - /* Install the filetype Handler */ - switch(in->i_mode & S_IFMT) { - case S_IFDIR: - in->i_op = &efs_dir_in_ops; - break; - case S_IFREG: - in->i_op = &efs_file_in_ops; - break; - case S_IFLNK: - in->i_op = &efs_symlink_in_ops; - break; - case S_IFCHR: - in->i_rdev = rdev; - in->i_op = &chrdev_inode_operations; - break; - case S_IFBLK: - in->i_rdev = rdev; - in->i_op = &blkdev_inode_operations; - break; - case S_IFIFO: - init_fifo(in); - break; - default: - printk("EFS: Unsupported inode Mode %o\n",(unsigned int)(in->i_mode)); - error++; - break; - } + /* Install the filetype Handler */ + switch(in->i_mode & S_IFMT) { + case S_IFDIR: + in->i_op = &efs_dir_in_ops; + break; + case S_IFREG: + in->i_op = &efs_file_in_ops; + break; + case S_IFLNK: + in->i_op = &efs_symlink_in_ops; + break; + case S_IFCHR: + in->i_rdev = rdev; + in->i_op = &chrdev_inode_operations; + break; + case S_IFBLK: + in->i_rdev = rdev; + in->i_op = &blkdev_inode_operations; + break; + case S_IFIFO: + init_fifo(in); + break; + default: + printk("EFS: Unsupported inode mode %o\n",(unsigned int)(in->i_mode)); + error++; + break; + } - } else { - printk("EFS: Inode: failed bread!\n"); - error++; - } - - /* failed inode */ - if(error) { - printk("EFS: read inode failed with %d errors\n",error); - in->i_mtime = in->i_atime = in->i_ctime = 0; - in->i_size = 0; - in->i_nlink = 1; - in->i_uid = in->i_gid = 0; - in->i_mode = S_IFREG; - in->i_op = NULL; - } } |