patch-2.4.4 linux/fs/affs/dir.c
Next file: linux/fs/affs/file.c
Previous file: linux/fs/affs/bitmap.c
Back to the patch index
Back to the overall index
- Lines: 198
- Date:
Thu Apr 26 22:17:26 2001
- Orig file:
v2.4.3/linux/fs/affs/dir.c
- Orig date:
Fri Aug 11 14:29:02 2000
diff -u --recursive --new-file v2.4.3/linux/fs/affs/dir.c linux/fs/affs/dir.c
@@ -13,7 +13,6 @@
*
*/
-#define DEBUG 0
#include <asm/uaccess.h>
#include <linux/errno.h>
#include <linux/fs.h>
@@ -50,109 +49,115 @@
static int
affs_readdir(struct file *filp, void *dirent, filldir_t filldir)
{
- int j, namelen;
- s32 i;
+ struct inode *inode = filp->f_dentry->d_inode;
+ struct super_block *sb = inode->i_sb;
+ struct buffer_head *dir_bh;
+ struct buffer_head *fh_bh;
+ unsigned char *name;
+ int namelen;
+ u32 i;
int hash_pos;
int chain_pos;
- unsigned long ino;
+ u32 f_pos;
+ u32 ino;
int stored;
- unsigned char *name;
- struct buffer_head *dir_bh;
- struct buffer_head *fh_bh;
- struct inode *dir;
- struct inode *inode = filp->f_dentry->d_inode;
+ int res;
- pr_debug("AFFS: readdir(ino=%lu,f_pos=%lu)\n",inode->i_ino,(unsigned long)filp->f_pos);
+ pr_debug("AFFS: readdir(ino=%lu,f_pos=%lx)\n",inode->i_ino,(unsigned long)filp->f_pos);
stored = 0;
+ res = -EIO;
dir_bh = NULL;
fh_bh = NULL;
- dir = NULL;
- ino = inode->i_ino;
+ f_pos = filp->f_pos;
- if (filp->f_pos == 0) {
+ if (f_pos == 0) {
filp->private_data = (void *)0;
- if (filldir(dirent,".",1,filp->f_pos,inode->i_ino,DT_DIR) < 0) {
+ if (filldir(dirent, ".", 1, f_pos, inode->i_ino, DT_DIR) < 0)
return 0;
- }
- ++filp->f_pos;
+ filp->f_pos = f_pos = 1;
stored++;
}
- if (filp->f_pos == 1) {
- if (filldir(dirent,"..",2,filp->f_pos,affs_parent_ino(inode),DT_DIR) < 0) {
+ if (f_pos == 1) {
+ if (filldir(dirent, "..", 2, f_pos, filp->f_dentry->d_parent->d_inode->i_ino, DT_DIR) < 0)
return stored;
- }
- filp->f_pos = 2;
+ filp->f_pos = f_pos = 2;
stored++;
}
- chain_pos = (filp->f_pos - 2) & 0xffff;
- hash_pos = (filp->f_pos - 2) >> 16;
+
+ down(&AFFS_INODE->i_hash_lock);
+ chain_pos = (f_pos - 2) & 0xffff;
+ hash_pos = (f_pos - 2) >> 16;
if (chain_pos == 0xffff) {
- affs_warning(inode->i_sb,"readdir","More than 65535 entries in chain");
+ affs_warning(sb, "readdir", "More than 65535 entries in chain");
chain_pos = 0;
hash_pos++;
filp->f_pos = ((hash_pos << 16) | chain_pos) + 2;
}
- if (!(dir_bh = affs_bread(inode->i_dev,inode->i_ino,
- AFFS_I2BSIZE(inode))))
- goto readdir_done;
-
- while (1) {
- while (hash_pos < AFFS_I2HSIZE(inode) &&
- !((struct dir_front *)dir_bh->b_data)->hashtable[hash_pos])
- hash_pos++;
- if (hash_pos >= AFFS_I2HSIZE(inode))
- break;
-
- i = be32_to_cpu(((struct dir_front *)dir_bh->b_data)->hashtable[hash_pos]);
- j = chain_pos;
-
- /* If the directory hasn't changed since the last call to readdir(),
- * we can jump directly to where we left off.
- */
- if (filp->private_data && filp->f_version == inode->i_version) {
- i = (s32)(unsigned long)filp->private_data;
- j = 0;
- pr_debug("AFFS: readdir() left off=%d\n",i);
+ dir_bh = affs_bread(sb, inode->i_ino);
+ if (!dir_bh)
+ goto readdir_out;
+
+ /* If the directory hasn't changed since the last call to readdir(),
+ * we can jump directly to where we left off.
+ */
+ ino = (u32)(long)filp->private_data;
+ if (ino && filp->f_version == inode->i_version) {
+ pr_debug("AFFS: readdir() left off=%d\n", ino);
+ goto inside;
+ }
+
+ ino = be32_to_cpu(AFFS_HEAD(dir_bh)->table[hash_pos]);
+ for (i = 0; ino && i < chain_pos; i++) {
+ fh_bh = affs_bread(sb, ino);
+ if (!fh_bh) {
+ affs_error(sb, "readdir","Cannot read block %d", i);
+ goto readdir_out;
}
- filp->f_version = inode->i_version;
- pr_debug("AFFS: hash_pos=%d chain_pos=%d\n",hash_pos,chain_pos);
- while (i) {
- if (!(fh_bh = affs_bread(inode->i_dev,i,AFFS_I2BSIZE(inode)))) {
- affs_error(inode->i_sb,"readdir","Cannot read block %d",i);
+ ino = be32_to_cpu(AFFS_TAIL(sb, fh_bh)->hash_chain);
+ affs_brelse(fh_bh);
+ fh_bh = NULL;
+ }
+ if (ino)
+ goto inside;
+ hash_pos++;
+
+ for (; hash_pos < AFFS_SB->s_hashsize; hash_pos++) {
+ ino = be32_to_cpu(AFFS_HEAD(dir_bh)->table[hash_pos]);
+ if (!ino)
+ continue;
+ f_pos = (hash_pos << 16) + 2;
+inside:
+ do {
+ fh_bh = affs_bread(sb, ino);
+ if (!fh_bh) {
+ affs_error(sb, "readdir","Cannot read block %d", ino);
goto readdir_done;
}
- ino = i;
- i = be32_to_cpu(FILE_END(fh_bh->b_data,inode)->hash_chain);
- if (j == 0)
- break;
- affs_brelse(fh_bh);
- fh_bh = NULL;
- j--;
- }
- if (fh_bh) {
- namelen = affs_get_file_name(AFFS_I2BSIZE(inode),fh_bh->b_data,&name);
- pr_debug("AFFS: readdir(): filldir(\"%.*s\",ino=%lu), i=%d\n",
- namelen,name,ino,i);
- filp->private_data = (void *)ino;
- if (filldir(dirent,name,namelen,filp->f_pos,ino,DT_UNKNOWN) < 0)
+
+ namelen = MIN(AFFS_TAIL(sb, fh_bh)->name[0], 30);
+ name = AFFS_TAIL(sb, fh_bh)->name + 1;
+ pr_debug("AFFS: readdir(): filldir(\"%.*s\", ino=%u), hash=%d, f_pos=%x\n",
+ namelen, name, ino, hash_pos, f_pos);
+ if (filldir(dirent, name, namelen, f_pos, ino, DT_UNKNOWN) < 0)
goto readdir_done;
- filp->private_data = (void *)(unsigned long)i;
+ stored++;
+ f_pos++;
+ ino = be32_to_cpu(AFFS_TAIL(sb, fh_bh)->hash_chain);
affs_brelse(fh_bh);
fh_bh = NULL;
- stored++;
- }
- if (i == 0) {
- hash_pos++;
- chain_pos = 0;
- } else
- chain_pos++;
- filp->f_pos = ((hash_pos << 16) | chain_pos) + 2;
+ } while (ino);
}
-
readdir_done:
+ filp->f_pos = f_pos;
+ filp->f_version = inode->i_version;
+ filp->private_data = (void *)(long)ino;
+ res = stored;
+
+readdir_out:
affs_brelse(dir_bh);
affs_brelse(fh_bh);
- pr_debug("AFFS: readdir()=%d\n",stored);
- return stored;
+ up(&AFFS_INODE->i_hash_lock);
+ pr_debug("AFFS: readdir()=%d\n", stored);
+ return res;
}
FUNET's LINUX-ADM group, linux-adm@nic.funet.fi
TCL-scripts by Sam Shen (who was at: slshen@lbl.gov)