diff options
Diffstat (limited to 'fs/efs/dir.c')
-rw-r--r-- | fs/efs/dir.c | 75 |
1 files changed, 33 insertions, 42 deletions
diff --git a/fs/efs/dir.c b/fs/efs/dir.c index 055a9e9ca747..b72307ccdf7a 100644 --- a/fs/efs/dir.c +++ b/fs/efs/dir.c | |||
@@ -7,40 +7,38 @@ | |||
7 | #include <linux/buffer_head.h> | 7 | #include <linux/buffer_head.h> |
8 | #include "efs.h" | 8 | #include "efs.h" |
9 | 9 | ||
10 | static int efs_readdir(struct file *, void *, filldir_t); | 10 | static int efs_readdir(struct file *, struct dir_context *); |
11 | 11 | ||
12 | const struct file_operations efs_dir_operations = { | 12 | const struct file_operations efs_dir_operations = { |
13 | .llseek = generic_file_llseek, | 13 | .llseek = generic_file_llseek, |
14 | .read = generic_read_dir, | 14 | .read = generic_read_dir, |
15 | .readdir = efs_readdir, | 15 | .iterate = efs_readdir, |
16 | }; | 16 | }; |
17 | 17 | ||
18 | const struct inode_operations efs_dir_inode_operations = { | 18 | const struct inode_operations efs_dir_inode_operations = { |
19 | .lookup = efs_lookup, | 19 | .lookup = efs_lookup, |
20 | }; | 20 | }; |
21 | 21 | ||
22 | static int efs_readdir(struct file *filp, void *dirent, filldir_t filldir) { | 22 | static int efs_readdir(struct file *file, struct dir_context *ctx) |
23 | struct inode *inode = file_inode(filp); | 23 | { |
24 | struct buffer_head *bh; | 24 | struct inode *inode = file_inode(file); |
25 | |||
26 | struct efs_dir *dirblock; | ||
27 | struct efs_dentry *dirslot; | ||
28 | efs_ino_t inodenum; | ||
29 | efs_block_t block; | 25 | efs_block_t block; |
30 | int slot, namelen; | 26 | int slot; |
31 | char *nameptr; | ||
32 | 27 | ||
33 | if (inode->i_size & (EFS_DIRBSIZE-1)) | 28 | if (inode->i_size & (EFS_DIRBSIZE-1)) |
34 | printk(KERN_WARNING "EFS: WARNING: readdir(): directory size not a multiple of EFS_DIRBSIZE\n"); | 29 | printk(KERN_WARNING "EFS: WARNING: readdir(): directory size not a multiple of EFS_DIRBSIZE\n"); |
35 | 30 | ||
36 | /* work out where this entry can be found */ | 31 | /* work out where this entry can be found */ |
37 | block = filp->f_pos >> EFS_DIRBSIZE_BITS; | 32 | block = ctx->pos >> EFS_DIRBSIZE_BITS; |
38 | 33 | ||
39 | /* each block contains at most 256 slots */ | 34 | /* each block contains at most 256 slots */ |
40 | slot = filp->f_pos & 0xff; | 35 | slot = ctx->pos & 0xff; |
41 | 36 | ||
42 | /* look at all blocks */ | 37 | /* look at all blocks */ |
43 | while (block < inode->i_blocks) { | 38 | while (block < inode->i_blocks) { |
39 | struct efs_dir *dirblock; | ||
40 | struct buffer_head *bh; | ||
41 | |||
44 | /* read the dir block */ | 42 | /* read the dir block */ |
45 | bh = sb_bread(inode->i_sb, efs_bmap(inode, block)); | 43 | bh = sb_bread(inode->i_sb, efs_bmap(inode, block)); |
46 | 44 | ||
@@ -57,11 +55,14 @@ static int efs_readdir(struct file *filp, void *dirent, filldir_t filldir) { | |||
57 | break; | 55 | break; |
58 | } | 56 | } |
59 | 57 | ||
60 | while (slot < dirblock->slots) { | 58 | for (; slot < dirblock->slots; slot++) { |
61 | if (dirblock->space[slot] == 0) { | 59 | struct efs_dentry *dirslot; |
62 | slot++; | 60 | efs_ino_t inodenum; |
61 | const char *nameptr; | ||
62 | int namelen; | ||
63 | |||
64 | if (dirblock->space[slot] == 0) | ||
63 | continue; | 65 | continue; |
64 | } | ||
65 | 66 | ||
66 | dirslot = (struct efs_dentry *) (((char *) bh->b_data) + EFS_SLOTAT(dirblock, slot)); | 67 | dirslot = (struct efs_dentry *) (((char *) bh->b_data) + EFS_SLOTAT(dirblock, slot)); |
67 | 68 | ||
@@ -72,39 +73,29 @@ static int efs_readdir(struct file *filp, void *dirent, filldir_t filldir) { | |||
72 | #ifdef DEBUG | 73 | #ifdef DEBUG |
73 | printk(KERN_DEBUG "EFS: readdir(): block %d slot %d/%d: inode %u, name \"%s\", namelen %u\n", block, slot, dirblock->slots-1, inodenum, nameptr, namelen); | 74 | printk(KERN_DEBUG "EFS: readdir(): block %d slot %d/%d: inode %u, name \"%s\", namelen %u\n", block, slot, dirblock->slots-1, inodenum, nameptr, namelen); |
74 | #endif | 75 | #endif |
75 | if (namelen > 0) { | 76 | if (!namelen) |
76 | /* found the next entry */ | 77 | continue; |
77 | filp->f_pos = (block << EFS_DIRBSIZE_BITS) | slot; | 78 | /* found the next entry */ |
78 | 79 | ctx->pos = (block << EFS_DIRBSIZE_BITS) | slot; | |
79 | /* copy filename and data in dirslot */ | 80 | |
80 | filldir(dirent, nameptr, namelen, filp->f_pos, inodenum, DT_UNKNOWN); | 81 | /* sanity check */ |
81 | 82 | if (nameptr - (char *) dirblock + namelen > EFS_DIRBSIZE) { | |
82 | /* sanity check */ | 83 | printk(KERN_WARNING "EFS: directory entry %d exceeds directory block\n", slot); |
83 | if (nameptr - (char *) dirblock + namelen > EFS_DIRBSIZE) { | 84 | continue; |
84 | printk(KERN_WARNING "EFS: directory entry %d exceeds directory block\n", slot); | 85 | } |
85 | slot++; | 86 | |
86 | continue; | 87 | /* copy filename and data in dirslot */ |
87 | } | 88 | if (!dir_emit(ctx, nameptr, namelen, inodenum, DT_UNKNOWN)) { |
88 | |||
89 | /* store position of next slot */ | ||
90 | if (++slot == dirblock->slots) { | ||
91 | slot = 0; | ||
92 | block++; | ||
93 | } | ||
94 | brelse(bh); | 89 | brelse(bh); |
95 | filp->f_pos = (block << EFS_DIRBSIZE_BITS) | slot; | 90 | return 0; |
96 | goto out; | ||
97 | } | 91 | } |
98 | slot++; | ||
99 | } | 92 | } |
100 | brelse(bh); | 93 | brelse(bh); |
101 | 94 | ||
102 | slot = 0; | 95 | slot = 0; |
103 | block++; | 96 | block++; |
104 | } | 97 | } |
105 | 98 | ctx->pos = (block << EFS_DIRBSIZE_BITS) | slot; | |
106 | filp->f_pos = (block << EFS_DIRBSIZE_BITS) | slot; | ||
107 | out: | ||
108 | return 0; | 99 | return 0; |
109 | } | 100 | } |
110 | 101 | ||