diff options
author | Al Viro <viro@zeniv.linux.org.uk> | 2013-05-17 17:44:42 -0400 |
---|---|---|
committer | Al Viro <viro@zeniv.linux.org.uk> | 2013-06-29 04:56:44 -0400 |
commit | 0edf977d2ae32b492780828d4b5bd41c5d51cb02 (patch) | |
tree | 5c6461e41ef1fb49beba2b179e2cc89b1733925b /fs/affs | |
parent | 2638ffbac9e2f411e911ff8194dc8d69c46f9f78 (diff) |
[readdir] convert affs
Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
Diffstat (limited to 'fs/affs')
-rw-r--r-- | fs/affs/dir.c | 69 |
1 files changed, 24 insertions, 45 deletions
diff --git a/fs/affs/dir.c b/fs/affs/dir.c index fd11a6d608ee..f1eba8c3644e 100644 --- a/fs/affs/dir.c +++ b/fs/affs/dir.c | |||
@@ -15,12 +15,12 @@ | |||
15 | 15 | ||
16 | #include "affs.h" | 16 | #include "affs.h" |
17 | 17 | ||
18 | static int affs_readdir(struct file *, void *, filldir_t); | 18 | static int affs_readdir(struct file *, struct dir_context *); |
19 | 19 | ||
20 | const struct file_operations affs_dir_operations = { | 20 | const struct file_operations affs_dir_operations = { |
21 | .read = generic_read_dir, | 21 | .read = generic_read_dir, |
22 | .llseek = generic_file_llseek, | 22 | .llseek = generic_file_llseek, |
23 | .readdir = affs_readdir, | 23 | .iterate = affs_readdir, |
24 | .fsync = affs_file_fsync, | 24 | .fsync = affs_file_fsync, |
25 | }; | 25 | }; |
26 | 26 | ||
@@ -40,52 +40,35 @@ const struct inode_operations affs_dir_inode_operations = { | |||
40 | }; | 40 | }; |
41 | 41 | ||
42 | static int | 42 | static int |
43 | affs_readdir(struct file *filp, void *dirent, filldir_t filldir) | 43 | affs_readdir(struct file *file, struct dir_context *ctx) |
44 | { | 44 | { |
45 | struct inode *inode = file_inode(filp); | 45 | struct inode *inode = file_inode(file); |
46 | struct super_block *sb = inode->i_sb; | 46 | struct super_block *sb = inode->i_sb; |
47 | struct buffer_head *dir_bh; | 47 | struct buffer_head *dir_bh = NULL; |
48 | struct buffer_head *fh_bh; | 48 | struct buffer_head *fh_bh = NULL; |
49 | unsigned char *name; | 49 | unsigned char *name; |
50 | int namelen; | 50 | int namelen; |
51 | u32 i; | 51 | u32 i; |
52 | int hash_pos; | 52 | int hash_pos; |
53 | int chain_pos; | 53 | int chain_pos; |
54 | u32 f_pos; | ||
55 | u32 ino; | 54 | u32 ino; |
56 | int stored; | ||
57 | int res; | ||
58 | 55 | ||
59 | pr_debug("AFFS: readdir(ino=%lu,f_pos=%lx)\n",inode->i_ino,(unsigned long)filp->f_pos); | 56 | pr_debug("AFFS: readdir(ino=%lu,f_pos=%lx)\n",inode->i_ino,(unsigned long)ctx->pos); |
60 | 57 | ||
61 | stored = 0; | 58 | if (ctx->pos < 2) { |
62 | res = -EIO; | 59 | file->private_data = (void *)0; |
63 | dir_bh = NULL; | 60 | if (!dir_emit_dots(file, ctx)) |
64 | fh_bh = NULL; | ||
65 | f_pos = filp->f_pos; | ||
66 | |||
67 | if (f_pos == 0) { | ||
68 | filp->private_data = (void *)0; | ||
69 | if (filldir(dirent, ".", 1, f_pos, inode->i_ino, DT_DIR) < 0) | ||
70 | return 0; | 61 | return 0; |
71 | filp->f_pos = f_pos = 1; | ||
72 | stored++; | ||
73 | } | ||
74 | if (f_pos == 1) { | ||
75 | if (filldir(dirent, "..", 2, f_pos, parent_ino(filp->f_path.dentry), DT_DIR) < 0) | ||
76 | return stored; | ||
77 | filp->f_pos = f_pos = 2; | ||
78 | stored++; | ||
79 | } | 62 | } |
80 | 63 | ||
81 | affs_lock_dir(inode); | 64 | affs_lock_dir(inode); |
82 | chain_pos = (f_pos - 2) & 0xffff; | 65 | chain_pos = (ctx->pos - 2) & 0xffff; |
83 | hash_pos = (f_pos - 2) >> 16; | 66 | hash_pos = (ctx->pos - 2) >> 16; |
84 | if (chain_pos == 0xffff) { | 67 | if (chain_pos == 0xffff) { |
85 | affs_warning(sb, "readdir", "More than 65535 entries in chain"); | 68 | affs_warning(sb, "readdir", "More than 65535 entries in chain"); |
86 | chain_pos = 0; | 69 | chain_pos = 0; |
87 | hash_pos++; | 70 | hash_pos++; |
88 | filp->f_pos = ((hash_pos << 16) | chain_pos) + 2; | 71 | ctx->pos = ((hash_pos << 16) | chain_pos) + 2; |
89 | } | 72 | } |
90 | dir_bh = affs_bread(sb, inode->i_ino); | 73 | dir_bh = affs_bread(sb, inode->i_ino); |
91 | if (!dir_bh) | 74 | if (!dir_bh) |
@@ -94,8 +77,8 @@ affs_readdir(struct file *filp, void *dirent, filldir_t filldir) | |||
94 | /* If the directory hasn't changed since the last call to readdir(), | 77 | /* If the directory hasn't changed since the last call to readdir(), |
95 | * we can jump directly to where we left off. | 78 | * we can jump directly to where we left off. |
96 | */ | 79 | */ |
97 | ino = (u32)(long)filp->private_data; | 80 | ino = (u32)(long)file->private_data; |
98 | if (ino && filp->f_version == inode->i_version) { | 81 | if (ino && file->f_version == inode->i_version) { |
99 | pr_debug("AFFS: readdir() left off=%d\n", ino); | 82 | pr_debug("AFFS: readdir() left off=%d\n", ino); |
100 | goto inside; | 83 | goto inside; |
101 | } | 84 | } |
@@ -105,7 +88,7 @@ affs_readdir(struct file *filp, void *dirent, filldir_t filldir) | |||
105 | fh_bh = affs_bread(sb, ino); | 88 | fh_bh = affs_bread(sb, ino); |
106 | if (!fh_bh) { | 89 | if (!fh_bh) { |
107 | affs_error(sb, "readdir","Cannot read block %d", i); | 90 | affs_error(sb, "readdir","Cannot read block %d", i); |
108 | goto readdir_out; | 91 | return -EIO; |
109 | } | 92 | } |
110 | ino = be32_to_cpu(AFFS_TAIL(sb, fh_bh)->hash_chain); | 93 | ino = be32_to_cpu(AFFS_TAIL(sb, fh_bh)->hash_chain); |
111 | affs_brelse(fh_bh); | 94 | affs_brelse(fh_bh); |
@@ -119,38 +102,34 @@ affs_readdir(struct file *filp, void *dirent, filldir_t filldir) | |||
119 | ino = be32_to_cpu(AFFS_HEAD(dir_bh)->table[hash_pos]); | 102 | ino = be32_to_cpu(AFFS_HEAD(dir_bh)->table[hash_pos]); |
120 | if (!ino) | 103 | if (!ino) |
121 | continue; | 104 | continue; |
122 | f_pos = (hash_pos << 16) + 2; | 105 | ctx->pos = (hash_pos << 16) + 2; |
123 | inside: | 106 | inside: |
124 | do { | 107 | do { |
125 | fh_bh = affs_bread(sb, ino); | 108 | fh_bh = affs_bread(sb, ino); |
126 | if (!fh_bh) { | 109 | if (!fh_bh) { |
127 | affs_error(sb, "readdir","Cannot read block %d", ino); | 110 | affs_error(sb, "readdir","Cannot read block %d", ino); |
128 | goto readdir_done; | 111 | break; |
129 | } | 112 | } |
130 | 113 | ||
131 | namelen = min(AFFS_TAIL(sb, fh_bh)->name[0], (u8)30); | 114 | namelen = min(AFFS_TAIL(sb, fh_bh)->name[0], (u8)30); |
132 | name = AFFS_TAIL(sb, fh_bh)->name + 1; | 115 | name = AFFS_TAIL(sb, fh_bh)->name + 1; |
133 | pr_debug("AFFS: readdir(): filldir(\"%.*s\", ino=%u), hash=%d, f_pos=%x\n", | 116 | pr_debug("AFFS: readdir(): filldir(\"%.*s\", ino=%u), hash=%d, f_pos=%x\n", |
134 | namelen, name, ino, hash_pos, f_pos); | 117 | namelen, name, ino, hash_pos, (u32)ctx->pos); |
135 | if (filldir(dirent, name, namelen, f_pos, ino, DT_UNKNOWN) < 0) | 118 | if (!dir_emit(ctx, name, namelen, ino, DT_UNKNOWN)) |
136 | goto readdir_done; | 119 | goto readdir_done; |
137 | stored++; | 120 | ctx->pos++; |
138 | f_pos++; | ||
139 | ino = be32_to_cpu(AFFS_TAIL(sb, fh_bh)->hash_chain); | 121 | ino = be32_to_cpu(AFFS_TAIL(sb, fh_bh)->hash_chain); |
140 | affs_brelse(fh_bh); | 122 | affs_brelse(fh_bh); |
141 | fh_bh = NULL; | 123 | fh_bh = NULL; |
142 | } while (ino); | 124 | } while (ino); |
143 | } | 125 | } |
144 | readdir_done: | 126 | readdir_done: |
145 | filp->f_pos = f_pos; | 127 | file->f_version = inode->i_version; |
146 | filp->f_version = inode->i_version; | 128 | file->private_data = (void *)(long)ino; |
147 | filp->private_data = (void *)(long)ino; | ||
148 | res = stored; | ||
149 | 129 | ||
150 | readdir_out: | 130 | readdir_out: |
151 | affs_brelse(dir_bh); | 131 | affs_brelse(dir_bh); |
152 | affs_brelse(fh_bh); | 132 | affs_brelse(fh_bh); |
153 | affs_unlock_dir(inode); | 133 | affs_unlock_dir(inode); |
154 | pr_debug("AFFS: readdir()=%d\n", stored); | 134 | return 0; |
155 | return res; | ||
156 | } | 135 | } |