diff options
author | Mike Shaver <shaver@ingenia.com> | 1999-01-18 04:16:25 +0000 |
---|---|---|
committer | Mike Shaver <shaver@ingenia.com> | 1999-01-18 04:16:25 +0000 |
commit | 6bafd683c6bd78f19df9a42aea24037137f913ce (patch) | |
tree | 7580dc3040c32da4048009721d60a7ac442962ca /fs/efs/dir.c | |
parent | 317b660279d583d4db3fc112e3ef2e56b20bec87 (diff) |
EFS mark II. Incomplete, but much cleaner.
Diffstat (limited to 'fs/efs/dir.c')
-rw-r--r-- | fs/efs/dir.c | 239 |
1 files changed, 124 insertions, 115 deletions
diff --git a/fs/efs/dir.c b/fs/efs/dir.c index a89dd304e..a31f6784a 100644 --- a/fs/efs/dir.c +++ b/fs/efs/dir.c @@ -1,137 +1,146 @@ -/* dir.c - - directory inode operations for EFS filesystem - - (C)95,96 Christian Vogelgsang -*/ +/* + * linux/fs/efs/dir.c + * + * Copyright (C) 1998 Mike Shaver + * + * Portions derived from work (C) 1995,1996 Christian Vogelgsang. + * ``Inspired by'' fs/minix/dir.c. + */ #include <linux/string.h> #include <linux/errno.h> -#include <linux/fs.h> #include <linux/efs_fs.h> -#include <linux/efs_fs_i.h> -#include <linux/stat.h> #include <asm/uaccess.h> -static int efs_readdir(struct file *,void *,filldir_t); -extern int efs_lookup(struct inode *, struct dentry *); +static int efs_readdir(struct file *, void *, filldir_t); +int efs_lookup(struct inode *, struct dentry *); + +static ssize_t +efs_dir_read(struct file *filp, char *buf, size_t count, loff_t *ppos) +{ + return -EISDIR; +} static struct file_operations efs_dir_ops = { - NULL, - NULL, - NULL, - efs_readdir, - NULL, - NULL, - NULL, - NULL, - NULL + NULL, /* lseek */ + efs_dir_read, + NULL, /* write */ + efs_readdir, + NULL, /* poll */ + NULL, /* ioctl */ + NULL, /* mmap */ + NULL, /* open */ + NULL, /* flush */ + NULL, /* release */ + NULL /* fsync */ }; -struct inode_operations efs_dir_in_ops = { - &efs_dir_ops, - NULL, - efs_lookup, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - efs_bmap, - NULL, - NULL +struct inode_operations efs_dir_inode_operations = { + &efs_dir_ops, + NULL, /* create */ + efs_lookup, + NULL, /* link */ + NULL, /* unlink */ + NULL, /* symlink */ + NULL, /* mkdir */ + NULL, /* rmdir */ + NULL, /* mknod */ + NULL, /* rename */ + NULL, /* readlink */ + NULL, /* follow_link */ + NULL, /* readpage */ + NULL, /* writepage */ + efs_bmap, + NULL, /* truncate */ + NULL /* permission */ }; +static int +efs_readdir(struct file *filp, void *dirent, filldir_t filldir) +{ + struct inode *in = filp->f_dentry->d_inode; + struct efs_inode_info *ini = &in->u.efs_i; + struct buffer_head *bh; + __u16 item; + __u32 block; + __u16 offset; + struct efs_dirblk *dirblk; + struct efs_dir_entry *entry; + + if (!in || !in->i_sb || !S_ISDIR(in->i_mode) || !ini->tot) + return -EBADF; + + if (ini->tot > 1) { + printk("EFS: ERROR: directory %s has %d extents\n", + filp->f_dentry->d_name.name, ini->tot); + printk("EFS: ERROR: Mike is lazy, so this is NYI.\n"); + return 0; + }; + + if (in->i_size & (EFS_BLOCK_SIZE - 1)) + printk("EFS: readdir: dirsize %#lx not block multiple\n", in->i_size); + + /* filp->f_pos is (block << BLOCK_SIZE | item) */ + block = filp->f_pos >> EFS_BLOCK_SIZE_BITS; + item = filp->f_pos & 0xFF; + + start_block: + if (block == (in->i_size >> EFS_BLOCK_SIZE_BITS)) + return 0; /* all done! */ + + bh = bread(in->i_dev, efs_bmap(in, block), EFS_BLOCK_SIZE); + if (!bh) { + printk("EFS: ERROR: readdir: bread of %#lx/%#x\n", + in->i_ino, efs_bmap(in, block)); + return 0; + } -/* ----- efs_readdir ----- - readdir inode operation: - read the next directory entry of a given dir file - - inode - pointer to inode struct of directory - filp - pointer to file struct of directory inode - dirent - pointer to dirent struct that has to be filled - filldir - function to store values in the directory + dirblk = (struct efs_dirblk *)bh->b_data; - return - 0 ok, <0 error -*/ -static int efs_readdir(struct file *filp, - void *dirent, filldir_t filldir) -{ - struct inode *inode = filp->f_dentry->d_inode; - struct efs_inode_info *ini = (struct efs_inode_info *)&inode->u.efs_i; - struct buffer_head *bh; - __u8 *rawdirblk; - __u32 iteminode; - __u16 namelen; - __u8 *nameptr; - __u32 numitems; - __u16 itemnum; - __u32 block; - __u16 rawdepos; - - /* some checks */ - if(!inode || !inode->i_sb || !S_ISDIR(inode->i_mode)) - return -EBADF; - - /* Warnings */ - if(ini->tot!=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"); - return 0; + /* skip empty slots */ + do { + offset = EFS_SLOT2OFF(dirblk, item); + if (!offset) { + DB(("EFS: skipping empty slot %d\n", item)); + } + item++; + if (item == dirblk->db_slots) { + item = 0; + block++; + if (!offset) { + brelse(bh); + goto start_block; + } } - if(inode->i_size & (EFS_BLOCK_SIZE-1)) - printk("efs_readdir: dirsize != blocksize*n\n"); - - /* f_pos contains: dirblock<<BLOCK_SIZE | # of item in dirblock */ - block = filp->f_pos >> EFS_BLOCK_SIZE_BITS; - itemnum = filp->f_pos & 0xff; - - /* We found the last entry -> ready */ - if(block == (inode->i_size>>EFS_BLOCK_SIZE_BITS)) - return 0; - - /* get disc block number from dir block num: 0..i_size/BLOCK_SIZE */ - bh = bread(inode->i_dev,efs_bmap(inode,block),EFS_BLOCK_SIZE); - if(!bh) return 0; - - /* dirblock */ - rawdirblk = (__u8 *)bh->b_data; - /* number of entries stored in this dirblock */ - numitems = rawdirblk[EFS_DB_ENTRIES]; - /* offset in block of #off diritem */ - rawdepos = (__u16)rawdirblk[EFS_DB_FIRST+itemnum]<<1; - - /* diritem first contains the inode number, the namelen and the name */ - iteminode = ConvertLong(rawdirblk,rawdepos); - namelen = (__u16)rawdirblk[rawdepos+EFS_DI_NAMELEN]; - nameptr = rawdirblk + rawdepos + EFS_DI_NAME; + } while(!offset); + entry = EFS_DENT4OFF(dirblk, offset); + /* + DB(("EFS_SLOT2OFF(%d) -> %d, EFS_DENT4OFF(%p, %d) -> %p) || ", + item-1, offset, dirblk, offset, entry)); #ifdef DEBUG_EFS - printk("efs: dir #%d @ %0#3x - inode %lx %s namelen %u\n", - itemnum,rawdepos,iteminode,nameptr,namelen); + { + __u8 *rawdirblk, nameptr; + __u32 iteminode; + __u16 namelen, rawdepos; + rawdirblk = (__u8*)bh->b_data; + rawdepos = (__u16)rawdirblk[EFS_DB_FIRST+item-1] << 1; + DB(("OLD_WAY: offset = %d, dent = %p ||", rawdepos, + (struct efs_dir_entry *)(rawdirblk + rawdepos))); + } #endif - /* copy filename and data in direntry */ - filldir(dirent,nameptr,namelen,filp->f_pos,iteminode); + DB(("EFS: filldir(dirent, \"%.*s\", %d, %d, %d)\n", + entry->d_namelen, entry->d_name, entry->d_namelen, + filp->f_pos, efs_swab32(entry->ud_inum.l))); + */ + filldir(dirent, entry->d_name, entry->d_namelen, filp->f_pos, + efs_swab32(entry->ud_inum.l)); + + brelse(bh); - brelse(bh); + filp->f_pos = (block << EFS_BLOCK_SIZE_BITS) | item; + UPDATE_ATIME(in); - /* store pos of next item */ - itemnum++; - if(itemnum==numitems) { - itemnum = 0; - block++; - } - filp->f_pos = (block<<EFS_BLOCK_SIZE_BITS) | itemnum; - UPDATE_ATIME(inode); - - return 0; + return 0; } - |