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 | |
parent | cad646a41d689e717fec6272cba6cdd1258381c8 (diff) |
some fixes and streamlining of code; indirect extents still don't work right =(
Diffstat (limited to 'fs')
-rw-r--r-- | fs/efs/dir.c | 2 | ||||
-rw-r--r-- | fs/efs/file.c | 144 | ||||
-rw-r--r-- | fs/efs/inode.c | 333 | ||||
-rw-r--r-- | fs/efs/namei.c | 4 | ||||
-rw-r--r-- | fs/efs/symlink.c | 10 |
5 files changed, 235 insertions, 258 deletions
diff --git a/fs/efs/dir.c b/fs/efs/dir.c index 0fd4f3187..ccf4fb0df 100644 --- a/fs/efs/dir.c +++ b/fs/efs/dir.c @@ -83,7 +83,7 @@ efs_readdir(struct file *filp, return -EBADF; } - if(ini->tot!=1) { + if(ini->efs_total!=1) { printk("EFS: directory %s has more than one extent.\n", filp->f_dentry->d_name.name); printk("EFS: Mike is lazy, so we can't handle this yet. Sorry =(\n"); diff --git a/fs/efs/file.c b/fs/efs/file.c index 4c04616bb..40f5d5a72 100644 --- a/fs/efs/file.c +++ b/fs/efs/file.c @@ -48,15 +48,10 @@ struct inode_operations efs_file_in_ops = { NULL, NULL }; - -#define MIN(a,b) ((a)<(b)?(a):(b)) -#define CHECK(num) \ - eblk = ini->extents[num].ex_bytes[0]; \ - epos = ini->extents[num].ex_bytes[1] & 0xffffff; \ - elen = ini->extents[num].ex_bytes[1] >> 24; \ - if((blk >= epos)&&(blk < (epos+elen))) \ - result = (blk - epos) + eblk + sbi->fs_start; +#ifndef MIN +#define MIN(a,b) ((a)<(b)?(a):(b)) +#endif /* ----- efs_getblknum ----- @@ -71,119 +66,42 @@ 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; - struct buffer_head *bh; __u32 result = 0; - __u32 eblk,epos,elen; - int num,extnum,readahead; - __u32 extblk; - __u16 extoff,pos,cur,tot; - union efs_extent *ptr; + __u32 eblk,epos,elen; /* used by the CHECK macro */ + __u16 pos; - /* first check the current extend */ - cur = ini->cur; - tot = ini->tot; - CHECK(cur) - if(result) - return result; - - /* if only one extent exists and we are here the test failed */ - if(tot==1) { - printk("efs: bmap failed on one extent!\n"); - return 0; - } - - /* check the stored extents in the inode */ - num = MIN(tot,EFS_MAX_EXTENTS); - for(pos=0;pos<num;pos++) { - /* don't check the current again! */ - if(pos==cur) - continue; + /* + * This routine is a linear search of the extents, from zero. + * A smarter implementation would: + * - check the current extent first + * - continue from the current extent forward, and then wrap + */ + +#define CHECK(num) \ + eblk = ini->efs_extents[num].ex_bytes[0]; \ + epos = ini->efs_extents[num].ex_bytes[1] & 0xffffff; \ + elen = ini->efs_extents[num].ex_bytes[1] >> 24; \ + if((blk >= epos)&&(blk < (epos+elen))) \ + result = (blk - epos) + eblk + sbi->fs_start; + for(pos=0;pos < ini->efs_total; pos++) { CHECK(pos) if(result) { - ini->cur = pos; - return result; - } - } - - /* If the inode has only direct extents, - the above tests must have found the block's extend! */ - if(tot<=EFS_MAX_EXTENTS) { - printk("efs: bmap failed for direct extents!\n"); - return 0; - } - - /* --- search in the indirect extensions list blocks --- */ -#ifdef DEBUG - printk("efs - indirect search for %lu\n",blk); + /* ini->efs_current = pos; */ +#ifdef DEBUG_EFS_EXTENTS_VERBOSE + printk("EFS: inode %#0lx blk %d is phys blk %d\n", + in->i_ino, blk, result); #endif - - /* calculate block and offset for begin of extent descr and read it */ - extblk = ini->extblk; - extoff = 0; - bh = bread(in->i_dev,extblk,EFS_BLOCK_SIZE); - if(!bh) { - printk("efs: read error in indirect extents\n"); - return 0; - } - ptr = (union efs_extent *)bh->b_data; - - pos = 0; /* number of extend store in the inode */ - extnum = 0; /* count the extents in the indirect blocks */ - readahead = 10; /* number of extents to read ahead */ - while(1) { - - /* skip last current extent store in the inode */ - if(pos==cur) pos++; - - /* read new extent in inode buffer */ - ini->extents[pos].ex_bytes[0] = efs_swab32(ptr[pos].ex_bytes[0]); - ini->extents[pos].ex_bytes[1] = efs_swab32(ptr[pos].ex_bytes[1]); - - /* we must still search */ - if(!result) { - CHECK(pos) - if(result) - ini->cur = pos; - } - /* we found it already and read ahead */ - else { - readahead--; - if(!readahead) - break; - } - - /* next storage place */ - pos++; - extnum++; - - /* last extent checked -> finished */ - if(extnum==tot) { - if(!result) - printk("efs: bmap on indirect failed!\n"); - break; - } - - extoff += 8; - /* need new block */ - if(extoff==EFS_BLOCK_SIZE) { - extoff = 0; - extblk++; - - brelse(bh); - bh = bread(in->i_dev,extblk,EFS_BLOCK_SIZE); - if(!bh) { - printk("efs: read error in indirect extents\n"); - return 0; - } - ptr = (union efs_extent *)bh->b_data; + return result; } } - brelse(bh); - return result; + printk("EFS: didn't find physical blk for logical blk %d (inode %0#lx)!\n", + blk, in->i_ino); + return 0; + } @@ -193,13 +111,13 @@ static __u32 efs_getblk(struct inode *in,__u32 blk) in - inode owning the block block - block number - return - disk block + return - disk block, 0 on error */ int efs_bmap(struct inode *in, int block) { /* quickly reject invalid block numbers */ if(block<0) { -#ifdef DEBUG +#ifdef DEBUG_EFS_BMAP printk("efs_bmap: block < 0\n"); #endif return 0; @@ -207,7 +125,7 @@ int efs_bmap(struct inode *in, int block) /* since the kernel wants to read a full page of data, i.e. 8 blocks we must check if the block number is not too large */ if(block>((in->i_size-1)>>EFS_BLOCK_SIZE_BITS)) { -#ifdef DEBUG +#ifdef DEBUG_EFS_BMAP printk("efs_bmap: block %d > max %d == %d\n", block,in->i_size>>EFS_BLOCK_SIZE_BITS,in->i_blocks); #endif 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; - } } diff --git a/fs/efs/namei.c b/fs/efs/namei.c index 9cbdd9550..f96a962e6 100644 --- a/fs/efs/namei.c +++ b/fs/efs/namei.c @@ -39,7 +39,7 @@ static struct buffer_head * efs_find_entry(struct inode *dir, struct efs_dirblk *db; /* Warnings */ - if(ini->tot!=1) + if(ini->efs_total!=1) printk("efs_find: More than one extent!\n"); if(dir->i_size & (EFS_BLOCK_SIZE-1)) printk("efs_find: dirsize != blocklen * n\n"); @@ -100,7 +100,7 @@ static struct buffer_head * efs_find_entry(struct inode *dir, } } } -#ifdef DEBUG_EFS +#ifdef DEBUG_EFS_DIRS printk("EFS: efs_find_entry didn't find inode for \"%s\"/%d!\n", oname, onamelen); #endif diff --git a/fs/efs/symlink.c b/fs/efs/symlink.c index 8c52411a1..7a8cd79d8 100644 --- a/fs/efs/symlink.c +++ b/fs/efs/symlink.c @@ -50,7 +50,7 @@ static char *efs_getlinktarget(struct inode *in) __u32 size = in->i_size; __u32 block; -#ifdef DEBUG_EFS +#ifdef DEBUG_EFS_SYMLINK printk("efs_getlinktarget: size of inode %#0lx is %d\n", in->i_ino, size); #endif @@ -103,7 +103,7 @@ static struct dentry * efs_follow_link(struct dentry * dent, char * name; UPDATE_ATIME(dir); name = efs_getlinktarget(dir); -#ifdef DEBUG_EFS +#ifdef DEBUG_EFS_SYMLINK printk("EFS: efs_getlinktarget(%d) returned \"%s\"\n", dir->i_ino, name); #endif @@ -128,16 +128,16 @@ static int efs_readlink(struct dentry * dent, char * buffer, int buflen) return 0; /* copy the link target to the given buffer */ i = 0; -#ifdef DEBUG_EFS +#ifdef DEBUG_EFS_SYMLINK printk("EFS: efs_readlink returning "); #endif while (i<buflen && bh->b_data[i] && i < dir->i_size) { -#ifdef DEBUG_EFS +#ifdef DEBUG_EFS_SYMLINK printk("%c", bh->b_data[i]); #endif i++; } -#ifdef DEBUG_EFS +#ifdef DEBUG_EFS_SYMLINK printk("\n"); #endif if (copy_to_user(buffer, bh->b_data, i)) |