diff options
Diffstat (limited to 'fs')
90 files changed, 1854 insertions, 2672 deletions
diff --git a/fs/9p/vfs_dir.c b/fs/9p/vfs_dir.c index be1e34adc3c6..4d0c2e0be7e5 100644 --- a/fs/9p/vfs_dir.c +++ b/fs/9p/vfs_dir.c | |||
@@ -101,16 +101,15 @@ static struct p9_rdir *v9fs_alloc_rdir_buf(struct file *filp, int buflen) | |||
101 | } | 101 | } |
102 | 102 | ||
103 | /** | 103 | /** |
104 | * v9fs_dir_readdir - read a directory | 104 | * v9fs_dir_readdir - iterate through a directory |
105 | * @filp: opened file structure | 105 | * @file: opened file structure |
106 | * @dirent: directory structure ??? | 106 | * @ctx: actor we feed the entries to |
107 | * @filldir: function to populate directory structure ??? | ||
108 | * | 107 | * |
109 | */ | 108 | */ |
110 | 109 | ||
111 | static int v9fs_dir_readdir(struct file *filp, void *dirent, filldir_t filldir) | 110 | static int v9fs_dir_readdir(struct file *file, struct dir_context *ctx) |
112 | { | 111 | { |
113 | int over; | 112 | bool over; |
114 | struct p9_wstat st; | 113 | struct p9_wstat st; |
115 | int err = 0; | 114 | int err = 0; |
116 | struct p9_fid *fid; | 115 | struct p9_fid *fid; |
@@ -118,19 +117,19 @@ static int v9fs_dir_readdir(struct file *filp, void *dirent, filldir_t filldir) | |||
118 | int reclen = 0; | 117 | int reclen = 0; |
119 | struct p9_rdir *rdir; | 118 | struct p9_rdir *rdir; |
120 | 119 | ||
121 | p9_debug(P9_DEBUG_VFS, "name %s\n", filp->f_path.dentry->d_name.name); | 120 | p9_debug(P9_DEBUG_VFS, "name %s\n", file->f_path.dentry->d_name.name); |
122 | fid = filp->private_data; | 121 | fid = file->private_data; |
123 | 122 | ||
124 | buflen = fid->clnt->msize - P9_IOHDRSZ; | 123 | buflen = fid->clnt->msize - P9_IOHDRSZ; |
125 | 124 | ||
126 | rdir = v9fs_alloc_rdir_buf(filp, buflen); | 125 | rdir = v9fs_alloc_rdir_buf(file, buflen); |
127 | if (!rdir) | 126 | if (!rdir) |
128 | return -ENOMEM; | 127 | return -ENOMEM; |
129 | 128 | ||
130 | while (1) { | 129 | while (1) { |
131 | if (rdir->tail == rdir->head) { | 130 | if (rdir->tail == rdir->head) { |
132 | err = v9fs_file_readn(filp, rdir->buf, NULL, | 131 | err = v9fs_file_readn(file, rdir->buf, NULL, |
133 | buflen, filp->f_pos); | 132 | buflen, ctx->pos); |
134 | if (err <= 0) | 133 | if (err <= 0) |
135 | return err; | 134 | return err; |
136 | 135 | ||
@@ -148,51 +147,45 @@ static int v9fs_dir_readdir(struct file *filp, void *dirent, filldir_t filldir) | |||
148 | } | 147 | } |
149 | reclen = st.size+2; | 148 | reclen = st.size+2; |
150 | 149 | ||
151 | over = filldir(dirent, st.name, strlen(st.name), | 150 | over = !dir_emit(ctx, st.name, strlen(st.name), |
152 | filp->f_pos, v9fs_qid2ino(&st.qid), dt_type(&st)); | 151 | v9fs_qid2ino(&st.qid), dt_type(&st)); |
153 | |||
154 | p9stat_free(&st); | 152 | p9stat_free(&st); |
155 | |||
156 | if (over) | 153 | if (over) |
157 | return 0; | 154 | return 0; |
158 | 155 | ||
159 | rdir->head += reclen; | 156 | rdir->head += reclen; |
160 | filp->f_pos += reclen; | 157 | ctx->pos += reclen; |
161 | } | 158 | } |
162 | } | 159 | } |
163 | } | 160 | } |
164 | 161 | ||
165 | /** | 162 | /** |
166 | * v9fs_dir_readdir_dotl - read a directory | 163 | * v9fs_dir_readdir_dotl - iterate through a directory |
167 | * @filp: opened file structure | 164 | * @file: opened file structure |
168 | * @dirent: buffer to fill dirent structures | 165 | * @ctx: actor we feed the entries to |
169 | * @filldir: function to populate dirent structures | ||
170 | * | 166 | * |
171 | */ | 167 | */ |
172 | static int v9fs_dir_readdir_dotl(struct file *filp, void *dirent, | 168 | static int v9fs_dir_readdir_dotl(struct file *file, struct dir_context *ctx) |
173 | filldir_t filldir) | ||
174 | { | 169 | { |
175 | int over; | ||
176 | int err = 0; | 170 | int err = 0; |
177 | struct p9_fid *fid; | 171 | struct p9_fid *fid; |
178 | int buflen; | 172 | int buflen; |
179 | struct p9_rdir *rdir; | 173 | struct p9_rdir *rdir; |
180 | struct p9_dirent curdirent; | 174 | struct p9_dirent curdirent; |
181 | u64 oldoffset = 0; | ||
182 | 175 | ||
183 | p9_debug(P9_DEBUG_VFS, "name %s\n", filp->f_path.dentry->d_name.name); | 176 | p9_debug(P9_DEBUG_VFS, "name %s\n", file->f_path.dentry->d_name.name); |
184 | fid = filp->private_data; | 177 | fid = file->private_data; |
185 | 178 | ||
186 | buflen = fid->clnt->msize - P9_READDIRHDRSZ; | 179 | buflen = fid->clnt->msize - P9_READDIRHDRSZ; |
187 | 180 | ||
188 | rdir = v9fs_alloc_rdir_buf(filp, buflen); | 181 | rdir = v9fs_alloc_rdir_buf(file, buflen); |
189 | if (!rdir) | 182 | if (!rdir) |
190 | return -ENOMEM; | 183 | return -ENOMEM; |
191 | 184 | ||
192 | while (1) { | 185 | while (1) { |
193 | if (rdir->tail == rdir->head) { | 186 | if (rdir->tail == rdir->head) { |
194 | err = p9_client_readdir(fid, rdir->buf, buflen, | 187 | err = p9_client_readdir(fid, rdir->buf, buflen, |
195 | filp->f_pos); | 188 | ctx->pos); |
196 | if (err <= 0) | 189 | if (err <= 0) |
197 | return err; | 190 | return err; |
198 | 191 | ||
@@ -210,22 +203,13 @@ static int v9fs_dir_readdir_dotl(struct file *filp, void *dirent, | |||
210 | return -EIO; | 203 | return -EIO; |
211 | } | 204 | } |
212 | 205 | ||
213 | /* d_off in dirent structure tracks the offset into | 206 | if (!dir_emit(ctx, curdirent.d_name, |
214 | * the next dirent in the dir. However, filldir() | 207 | strlen(curdirent.d_name), |
215 | * expects offset into the current dirent. Hence | 208 | v9fs_qid2ino(&curdirent.qid), |
216 | * while calling filldir send the offset from the | 209 | curdirent.d_type)) |
217 | * previous dirent structure. | ||
218 | */ | ||
219 | over = filldir(dirent, curdirent.d_name, | ||
220 | strlen(curdirent.d_name), | ||
221 | oldoffset, v9fs_qid2ino(&curdirent.qid), | ||
222 | curdirent.d_type); | ||
223 | oldoffset = curdirent.d_off; | ||
224 | |||
225 | if (over) | ||
226 | return 0; | 210 | return 0; |
227 | 211 | ||
228 | filp->f_pos = curdirent.d_off; | 212 | ctx->pos = curdirent.d_off; |
229 | rdir->head += err; | 213 | rdir->head += err; |
230 | } | 214 | } |
231 | } | 215 | } |
@@ -254,7 +238,7 @@ int v9fs_dir_release(struct inode *inode, struct file *filp) | |||
254 | const struct file_operations v9fs_dir_operations = { | 238 | const struct file_operations v9fs_dir_operations = { |
255 | .read = generic_read_dir, | 239 | .read = generic_read_dir, |
256 | .llseek = generic_file_llseek, | 240 | .llseek = generic_file_llseek, |
257 | .readdir = v9fs_dir_readdir, | 241 | .iterate = v9fs_dir_readdir, |
258 | .open = v9fs_file_open, | 242 | .open = v9fs_file_open, |
259 | .release = v9fs_dir_release, | 243 | .release = v9fs_dir_release, |
260 | }; | 244 | }; |
@@ -262,7 +246,7 @@ const struct file_operations v9fs_dir_operations = { | |||
262 | const struct file_operations v9fs_dir_operations_dotl = { | 246 | const struct file_operations v9fs_dir_operations_dotl = { |
263 | .read = generic_read_dir, | 247 | .read = generic_read_dir, |
264 | .llseek = generic_file_llseek, | 248 | .llseek = generic_file_llseek, |
265 | .readdir = v9fs_dir_readdir_dotl, | 249 | .iterate = v9fs_dir_readdir_dotl, |
266 | .open = v9fs_file_open, | 250 | .open = v9fs_file_open, |
267 | .release = v9fs_dir_release, | 251 | .release = v9fs_dir_release, |
268 | .fsync = v9fs_file_fsync_dotl, | 252 | .fsync = v9fs_file_fsync_dotl, |
diff --git a/fs/adfs/dir.c b/fs/adfs/dir.c index 9cf874ce8336..ade28bb058e3 100644 --- a/fs/adfs/dir.c +++ b/fs/adfs/dir.c | |||
@@ -17,47 +17,43 @@ | |||
17 | static DEFINE_RWLOCK(adfs_dir_lock); | 17 | static DEFINE_RWLOCK(adfs_dir_lock); |
18 | 18 | ||
19 | static int | 19 | static int |
20 | adfs_readdir(struct file *filp, void *dirent, filldir_t filldir) | 20 | adfs_readdir(struct file *file, struct dir_context *ctx) |
21 | { | 21 | { |
22 | struct inode *inode = file_inode(filp); | 22 | struct inode *inode = file_inode(file); |
23 | struct super_block *sb = inode->i_sb; | 23 | struct super_block *sb = inode->i_sb; |
24 | struct adfs_dir_ops *ops = ADFS_SB(sb)->s_dir; | 24 | struct adfs_dir_ops *ops = ADFS_SB(sb)->s_dir; |
25 | struct object_info obj; | 25 | struct object_info obj; |
26 | struct adfs_dir dir; | 26 | struct adfs_dir dir; |
27 | int ret = 0; | 27 | int ret = 0; |
28 | 28 | ||
29 | if (filp->f_pos >> 32) | 29 | if (ctx->pos >> 32) |
30 | goto out; | 30 | return 0; |
31 | 31 | ||
32 | ret = ops->read(sb, inode->i_ino, inode->i_size, &dir); | 32 | ret = ops->read(sb, inode->i_ino, inode->i_size, &dir); |
33 | if (ret) | 33 | if (ret) |
34 | goto out; | 34 | return ret; |
35 | 35 | ||
36 | switch ((unsigned long)filp->f_pos) { | 36 | if (ctx->pos == 0) { |
37 | case 0: | 37 | if (!dir_emit_dot(file, ctx)) |
38 | if (filldir(dirent, ".", 1, 0, inode->i_ino, DT_DIR) < 0) | ||
39 | goto free_out; | 38 | goto free_out; |
40 | filp->f_pos += 1; | 39 | ctx->pos = 1; |
41 | 40 | } | |
42 | case 1: | 41 | if (ctx->pos == 1) { |
43 | if (filldir(dirent, "..", 2, 1, dir.parent_id, DT_DIR) < 0) | 42 | if (!dir_emit(ctx, "..", 2, dir.parent_id, DT_DIR)) |
44 | goto free_out; | 43 | goto free_out; |
45 | filp->f_pos += 1; | 44 | ctx->pos = 2; |
46 | |||
47 | default: | ||
48 | break; | ||
49 | } | 45 | } |
50 | 46 | ||
51 | read_lock(&adfs_dir_lock); | 47 | read_lock(&adfs_dir_lock); |
52 | 48 | ||
53 | ret = ops->setpos(&dir, filp->f_pos - 2); | 49 | ret = ops->setpos(&dir, ctx->pos - 2); |
54 | if (ret) | 50 | if (ret) |
55 | goto unlock_out; | 51 | goto unlock_out; |
56 | while (ops->getnext(&dir, &obj) == 0) { | 52 | while (ops->getnext(&dir, &obj) == 0) { |
57 | if (filldir(dirent, obj.name, obj.name_len, | 53 | if (!dir_emit(ctx, obj.name, obj.name_len, |
58 | filp->f_pos, obj.file_id, DT_UNKNOWN) < 0) | 54 | obj.file_id, DT_UNKNOWN)) |
59 | goto unlock_out; | 55 | break; |
60 | filp->f_pos += 1; | 56 | ctx->pos++; |
61 | } | 57 | } |
62 | 58 | ||
63 | unlock_out: | 59 | unlock_out: |
@@ -65,8 +61,6 @@ unlock_out: | |||
65 | 61 | ||
66 | free_out: | 62 | free_out: |
67 | ops->free(&dir); | 63 | ops->free(&dir); |
68 | |||
69 | out: | ||
70 | return ret; | 64 | return ret; |
71 | } | 65 | } |
72 | 66 | ||
@@ -192,7 +186,7 @@ out: | |||
192 | const struct file_operations adfs_dir_operations = { | 186 | const struct file_operations adfs_dir_operations = { |
193 | .read = generic_read_dir, | 187 | .read = generic_read_dir, |
194 | .llseek = generic_file_llseek, | 188 | .llseek = generic_file_llseek, |
195 | .readdir = adfs_readdir, | 189 | .iterate = adfs_readdir, |
196 | .fsync = generic_file_fsync, | 190 | .fsync = generic_file_fsync, |
197 | }; | 191 | }; |
198 | 192 | ||
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 | } |
diff --git a/fs/afs/dir.c b/fs/afs/dir.c index 7a465ed04444..34494fbead0a 100644 --- a/fs/afs/dir.c +++ b/fs/afs/dir.c | |||
@@ -22,7 +22,7 @@ | |||
22 | static struct dentry *afs_lookup(struct inode *dir, struct dentry *dentry, | 22 | static struct dentry *afs_lookup(struct inode *dir, struct dentry *dentry, |
23 | unsigned int flags); | 23 | unsigned int flags); |
24 | static int afs_dir_open(struct inode *inode, struct file *file); | 24 | static int afs_dir_open(struct inode *inode, struct file *file); |
25 | static int afs_readdir(struct file *file, void *dirent, filldir_t filldir); | 25 | static int afs_readdir(struct file *file, struct dir_context *ctx); |
26 | static int afs_d_revalidate(struct dentry *dentry, unsigned int flags); | 26 | static int afs_d_revalidate(struct dentry *dentry, unsigned int flags); |
27 | static int afs_d_delete(const struct dentry *dentry); | 27 | static int afs_d_delete(const struct dentry *dentry); |
28 | static void afs_d_release(struct dentry *dentry); | 28 | static void afs_d_release(struct dentry *dentry); |
@@ -43,7 +43,7 @@ static int afs_rename(struct inode *old_dir, struct dentry *old_dentry, | |||
43 | const struct file_operations afs_dir_file_operations = { | 43 | const struct file_operations afs_dir_file_operations = { |
44 | .open = afs_dir_open, | 44 | .open = afs_dir_open, |
45 | .release = afs_release, | 45 | .release = afs_release, |
46 | .readdir = afs_readdir, | 46 | .iterate = afs_readdir, |
47 | .lock = afs_lock, | 47 | .lock = afs_lock, |
48 | .llseek = generic_file_llseek, | 48 | .llseek = generic_file_llseek, |
49 | }; | 49 | }; |
@@ -119,9 +119,9 @@ struct afs_dir_page { | |||
119 | }; | 119 | }; |
120 | 120 | ||
121 | struct afs_lookup_cookie { | 121 | struct afs_lookup_cookie { |
122 | struct dir_context ctx; | ||
122 | struct afs_fid fid; | 123 | struct afs_fid fid; |
123 | const char *name; | 124 | struct qstr name; |
124 | size_t nlen; | ||
125 | int found; | 125 | int found; |
126 | }; | 126 | }; |
127 | 127 | ||
@@ -228,20 +228,18 @@ static int afs_dir_open(struct inode *inode, struct file *file) | |||
228 | /* | 228 | /* |
229 | * deal with one block in an AFS directory | 229 | * deal with one block in an AFS directory |
230 | */ | 230 | */ |
231 | static int afs_dir_iterate_block(unsigned *fpos, | 231 | static int afs_dir_iterate_block(struct dir_context *ctx, |
232 | union afs_dir_block *block, | 232 | union afs_dir_block *block, |
233 | unsigned blkoff, | 233 | unsigned blkoff) |
234 | void *cookie, | ||
235 | filldir_t filldir) | ||
236 | { | 234 | { |
237 | union afs_dirent *dire; | 235 | union afs_dirent *dire; |
238 | unsigned offset, next, curr; | 236 | unsigned offset, next, curr; |
239 | size_t nlen; | 237 | size_t nlen; |
240 | int tmp, ret; | 238 | int tmp; |
241 | 239 | ||
242 | _enter("%u,%x,%p,,",*fpos,blkoff,block); | 240 | _enter("%u,%x,%p,,",(unsigned)ctx->pos,blkoff,block); |
243 | 241 | ||
244 | curr = (*fpos - blkoff) / sizeof(union afs_dirent); | 242 | curr = (ctx->pos - blkoff) / sizeof(union afs_dirent); |
245 | 243 | ||
246 | /* walk through the block, an entry at a time */ | 244 | /* walk through the block, an entry at a time */ |
247 | for (offset = AFS_DIRENT_PER_BLOCK - block->pagehdr.nentries; | 245 | for (offset = AFS_DIRENT_PER_BLOCK - block->pagehdr.nentries; |
@@ -256,7 +254,7 @@ static int afs_dir_iterate_block(unsigned *fpos, | |||
256 | _debug("ENT[%Zu.%u]: unused", | 254 | _debug("ENT[%Zu.%u]: unused", |
257 | blkoff / sizeof(union afs_dir_block), offset); | 255 | blkoff / sizeof(union afs_dir_block), offset); |
258 | if (offset >= curr) | 256 | if (offset >= curr) |
259 | *fpos = blkoff + | 257 | ctx->pos = blkoff + |
260 | next * sizeof(union afs_dirent); | 258 | next * sizeof(union afs_dirent); |
261 | continue; | 259 | continue; |
262 | } | 260 | } |
@@ -302,19 +300,15 @@ static int afs_dir_iterate_block(unsigned *fpos, | |||
302 | continue; | 300 | continue; |
303 | 301 | ||
304 | /* found the next entry */ | 302 | /* found the next entry */ |
305 | ret = filldir(cookie, | 303 | if (!dir_emit(ctx, dire->u.name, nlen, |
306 | dire->u.name, | ||
307 | nlen, | ||
308 | blkoff + offset * sizeof(union afs_dirent), | ||
309 | ntohl(dire->u.vnode), | 304 | ntohl(dire->u.vnode), |
310 | filldir == afs_lookup_filldir ? | 305 | ctx->actor == afs_lookup_filldir ? |
311 | ntohl(dire->u.unique) : DT_UNKNOWN); | 306 | ntohl(dire->u.unique) : DT_UNKNOWN)) { |
312 | if (ret < 0) { | ||
313 | _leave(" = 0 [full]"); | 307 | _leave(" = 0 [full]"); |
314 | return 0; | 308 | return 0; |
315 | } | 309 | } |
316 | 310 | ||
317 | *fpos = blkoff + next * sizeof(union afs_dirent); | 311 | ctx->pos = blkoff + next * sizeof(union afs_dirent); |
318 | } | 312 | } |
319 | 313 | ||
320 | _leave(" = 1 [more]"); | 314 | _leave(" = 1 [more]"); |
@@ -324,8 +318,8 @@ static int afs_dir_iterate_block(unsigned *fpos, | |||
324 | /* | 318 | /* |
325 | * iterate through the data blob that lists the contents of an AFS directory | 319 | * iterate through the data blob that lists the contents of an AFS directory |
326 | */ | 320 | */ |
327 | static int afs_dir_iterate(struct inode *dir, unsigned *fpos, void *cookie, | 321 | static int afs_dir_iterate(struct inode *dir, struct dir_context *ctx, |
328 | filldir_t filldir, struct key *key) | 322 | struct key *key) |
329 | { | 323 | { |
330 | union afs_dir_block *dblock; | 324 | union afs_dir_block *dblock; |
331 | struct afs_dir_page *dbuf; | 325 | struct afs_dir_page *dbuf; |
@@ -333,7 +327,7 @@ static int afs_dir_iterate(struct inode *dir, unsigned *fpos, void *cookie, | |||
333 | unsigned blkoff, limit; | 327 | unsigned blkoff, limit; |
334 | int ret; | 328 | int ret; |
335 | 329 | ||
336 | _enter("{%lu},%u,,", dir->i_ino, *fpos); | 330 | _enter("{%lu},%u,,", dir->i_ino, (unsigned)ctx->pos); |
337 | 331 | ||
338 | if (test_bit(AFS_VNODE_DELETED, &AFS_FS_I(dir)->flags)) { | 332 | if (test_bit(AFS_VNODE_DELETED, &AFS_FS_I(dir)->flags)) { |
339 | _leave(" = -ESTALE"); | 333 | _leave(" = -ESTALE"); |
@@ -341,13 +335,13 @@ static int afs_dir_iterate(struct inode *dir, unsigned *fpos, void *cookie, | |||
341 | } | 335 | } |
342 | 336 | ||
343 | /* round the file position up to the next entry boundary */ | 337 | /* round the file position up to the next entry boundary */ |
344 | *fpos += sizeof(union afs_dirent) - 1; | 338 | ctx->pos += sizeof(union afs_dirent) - 1; |
345 | *fpos &= ~(sizeof(union afs_dirent) - 1); | 339 | ctx->pos &= ~(sizeof(union afs_dirent) - 1); |
346 | 340 | ||
347 | /* walk through the blocks in sequence */ | 341 | /* walk through the blocks in sequence */ |
348 | ret = 0; | 342 | ret = 0; |
349 | while (*fpos < dir->i_size) { | 343 | while (ctx->pos < dir->i_size) { |
350 | blkoff = *fpos & ~(sizeof(union afs_dir_block) - 1); | 344 | blkoff = ctx->pos & ~(sizeof(union afs_dir_block) - 1); |
351 | 345 | ||
352 | /* fetch the appropriate page from the directory */ | 346 | /* fetch the appropriate page from the directory */ |
353 | page = afs_dir_get_page(dir, blkoff / PAGE_SIZE, key); | 347 | page = afs_dir_get_page(dir, blkoff / PAGE_SIZE, key); |
@@ -364,8 +358,7 @@ static int afs_dir_iterate(struct inode *dir, unsigned *fpos, void *cookie, | |||
364 | do { | 358 | do { |
365 | dblock = &dbuf->blocks[(blkoff % PAGE_SIZE) / | 359 | dblock = &dbuf->blocks[(blkoff % PAGE_SIZE) / |
366 | sizeof(union afs_dir_block)]; | 360 | sizeof(union afs_dir_block)]; |
367 | ret = afs_dir_iterate_block(fpos, dblock, blkoff, | 361 | ret = afs_dir_iterate_block(ctx, dblock, blkoff); |
368 | cookie, filldir); | ||
369 | if (ret != 1) { | 362 | if (ret != 1) { |
370 | afs_dir_put_page(page); | 363 | afs_dir_put_page(page); |
371 | goto out; | 364 | goto out; |
@@ -373,7 +366,7 @@ static int afs_dir_iterate(struct inode *dir, unsigned *fpos, void *cookie, | |||
373 | 366 | ||
374 | blkoff += sizeof(union afs_dir_block); | 367 | blkoff += sizeof(union afs_dir_block); |
375 | 368 | ||
376 | } while (*fpos < dir->i_size && blkoff < limit); | 369 | } while (ctx->pos < dir->i_size && blkoff < limit); |
377 | 370 | ||
378 | afs_dir_put_page(page); | 371 | afs_dir_put_page(page); |
379 | ret = 0; | 372 | ret = 0; |
@@ -387,23 +380,10 @@ out: | |||
387 | /* | 380 | /* |
388 | * read an AFS directory | 381 | * read an AFS directory |
389 | */ | 382 | */ |
390 | static int afs_readdir(struct file *file, void *cookie, filldir_t filldir) | 383 | static int afs_readdir(struct file *file, struct dir_context *ctx) |
391 | { | 384 | { |
392 | unsigned fpos; | 385 | return afs_dir_iterate(file_inode(file), |
393 | int ret; | 386 | ctx, file->private_data); |
394 | |||
395 | _enter("{%Ld,{%lu}}", | ||
396 | file->f_pos, file_inode(file)->i_ino); | ||
397 | |||
398 | ASSERT(file->private_data != NULL); | ||
399 | |||
400 | fpos = file->f_pos; | ||
401 | ret = afs_dir_iterate(file_inode(file), &fpos, | ||
402 | cookie, filldir, file->private_data); | ||
403 | file->f_pos = fpos; | ||
404 | |||
405 | _leave(" = %d", ret); | ||
406 | return ret; | ||
407 | } | 387 | } |
408 | 388 | ||
409 | /* | 389 | /* |
@@ -416,15 +396,16 @@ static int afs_lookup_filldir(void *_cookie, const char *name, int nlen, | |||
416 | { | 396 | { |
417 | struct afs_lookup_cookie *cookie = _cookie; | 397 | struct afs_lookup_cookie *cookie = _cookie; |
418 | 398 | ||
419 | _enter("{%s,%Zu},%s,%u,,%llu,%u", | 399 | _enter("{%s,%u},%s,%u,,%llu,%u", |
420 | cookie->name, cookie->nlen, name, nlen, | 400 | cookie->name.name, cookie->name.len, name, nlen, |
421 | (unsigned long long) ino, dtype); | 401 | (unsigned long long) ino, dtype); |
422 | 402 | ||
423 | /* insanity checks first */ | 403 | /* insanity checks first */ |
424 | BUILD_BUG_ON(sizeof(union afs_dir_block) != 2048); | 404 | BUILD_BUG_ON(sizeof(union afs_dir_block) != 2048); |
425 | BUILD_BUG_ON(sizeof(union afs_dirent) != 32); | 405 | BUILD_BUG_ON(sizeof(union afs_dirent) != 32); |
426 | 406 | ||
427 | if (cookie->nlen != nlen || memcmp(cookie->name, name, nlen) != 0) { | 407 | if (cookie->name.len != nlen || |
408 | memcmp(cookie->name.name, name, nlen) != 0) { | ||
428 | _leave(" = 0 [no]"); | 409 | _leave(" = 0 [no]"); |
429 | return 0; | 410 | return 0; |
430 | } | 411 | } |
@@ -444,24 +425,18 @@ static int afs_lookup_filldir(void *_cookie, const char *name, int nlen, | |||
444 | static int afs_do_lookup(struct inode *dir, struct dentry *dentry, | 425 | static int afs_do_lookup(struct inode *dir, struct dentry *dentry, |
445 | struct afs_fid *fid, struct key *key) | 426 | struct afs_fid *fid, struct key *key) |
446 | { | 427 | { |
447 | struct afs_lookup_cookie cookie; | 428 | struct afs_super_info *as = dir->i_sb->s_fs_info; |
448 | struct afs_super_info *as; | 429 | struct afs_lookup_cookie cookie = { |
449 | unsigned fpos; | 430 | .ctx.actor = afs_lookup_filldir, |
431 | .name = dentry->d_name, | ||
432 | .fid.vid = as->volume->vid | ||
433 | }; | ||
450 | int ret; | 434 | int ret; |
451 | 435 | ||
452 | _enter("{%lu},%p{%s},", dir->i_ino, dentry, dentry->d_name.name); | 436 | _enter("{%lu},%p{%s},", dir->i_ino, dentry, dentry->d_name.name); |
453 | 437 | ||
454 | as = dir->i_sb->s_fs_info; | ||
455 | |||
456 | /* search the directory */ | 438 | /* search the directory */ |
457 | cookie.name = dentry->d_name.name; | 439 | ret = afs_dir_iterate(dir, &cookie.ctx, key); |
458 | cookie.nlen = dentry->d_name.len; | ||
459 | cookie.fid.vid = as->volume->vid; | ||
460 | cookie.found = 0; | ||
461 | |||
462 | fpos = 0; | ||
463 | ret = afs_dir_iterate(dir, &fpos, &cookie, afs_lookup_filldir, | ||
464 | key); | ||
465 | if (ret < 0) { | 440 | if (ret < 0) { |
466 | _leave(" = %d [iter]", ret); | 441 | _leave(" = %d [iter]", ret); |
467 | return ret; | 442 | return ret; |
diff --git a/fs/autofs4/root.c b/fs/autofs4/root.c index 085da86e07c2..ca8e55548d98 100644 --- a/fs/autofs4/root.c +++ b/fs/autofs4/root.c | |||
@@ -41,7 +41,7 @@ const struct file_operations autofs4_root_operations = { | |||
41 | .open = dcache_dir_open, | 41 | .open = dcache_dir_open, |
42 | .release = dcache_dir_close, | 42 | .release = dcache_dir_close, |
43 | .read = generic_read_dir, | 43 | .read = generic_read_dir, |
44 | .readdir = dcache_readdir, | 44 | .iterate = dcache_readdir, |
45 | .llseek = dcache_dir_lseek, | 45 | .llseek = dcache_dir_lseek, |
46 | .unlocked_ioctl = autofs4_root_ioctl, | 46 | .unlocked_ioctl = autofs4_root_ioctl, |
47 | #ifdef CONFIG_COMPAT | 47 | #ifdef CONFIG_COMPAT |
@@ -53,7 +53,7 @@ const struct file_operations autofs4_dir_operations = { | |||
53 | .open = autofs4_dir_open, | 53 | .open = autofs4_dir_open, |
54 | .release = dcache_dir_close, | 54 | .release = dcache_dir_close, |
55 | .read = generic_read_dir, | 55 | .read = generic_read_dir, |
56 | .readdir = dcache_readdir, | 56 | .iterate = dcache_readdir, |
57 | .llseek = dcache_dir_lseek, | 57 | .llseek = dcache_dir_lseek, |
58 | }; | 58 | }; |
59 | 59 | ||
diff --git a/fs/bad_inode.c b/fs/bad_inode.c index 922ad460bff9..7c93953030fb 100644 --- a/fs/bad_inode.c +++ b/fs/bad_inode.c | |||
@@ -45,7 +45,7 @@ static ssize_t bad_file_aio_write(struct kiocb *iocb, const struct iovec *iov, | |||
45 | return -EIO; | 45 | return -EIO; |
46 | } | 46 | } |
47 | 47 | ||
48 | static int bad_file_readdir(struct file *filp, void *dirent, filldir_t filldir) | 48 | static int bad_file_readdir(struct file *file, struct dir_context *ctx) |
49 | { | 49 | { |
50 | return -EIO; | 50 | return -EIO; |
51 | } | 51 | } |
@@ -152,7 +152,7 @@ static const struct file_operations bad_file_ops = | |||
152 | .write = bad_file_write, | 152 | .write = bad_file_write, |
153 | .aio_read = bad_file_aio_read, | 153 | .aio_read = bad_file_aio_read, |
154 | .aio_write = bad_file_aio_write, | 154 | .aio_write = bad_file_aio_write, |
155 | .readdir = bad_file_readdir, | 155 | .iterate = bad_file_readdir, |
156 | .poll = bad_file_poll, | 156 | .poll = bad_file_poll, |
157 | .unlocked_ioctl = bad_file_unlocked_ioctl, | 157 | .unlocked_ioctl = bad_file_unlocked_ioctl, |
158 | .compat_ioctl = bad_file_compat_ioctl, | 158 | .compat_ioctl = bad_file_compat_ioctl, |
diff --git a/fs/befs/linuxvfs.c b/fs/befs/linuxvfs.c index f95dddced968..e9c75e20db32 100644 --- a/fs/befs/linuxvfs.c +++ b/fs/befs/linuxvfs.c | |||
@@ -31,7 +31,7 @@ MODULE_LICENSE("GPL"); | |||
31 | /* The units the vfs expects inode->i_blocks to be in */ | 31 | /* The units the vfs expects inode->i_blocks to be in */ |
32 | #define VFS_BLOCK_SIZE 512 | 32 | #define VFS_BLOCK_SIZE 512 |
33 | 33 | ||
34 | static int befs_readdir(struct file *, void *, filldir_t); | 34 | static int befs_readdir(struct file *, struct dir_context *); |
35 | static int befs_get_block(struct inode *, sector_t, struct buffer_head *, int); | 35 | static int befs_get_block(struct inode *, sector_t, struct buffer_head *, int); |
36 | static int befs_readpage(struct file *file, struct page *page); | 36 | static int befs_readpage(struct file *file, struct page *page); |
37 | static sector_t befs_bmap(struct address_space *mapping, sector_t block); | 37 | static sector_t befs_bmap(struct address_space *mapping, sector_t block); |
@@ -66,7 +66,7 @@ static struct kmem_cache *befs_inode_cachep; | |||
66 | 66 | ||
67 | static const struct file_operations befs_dir_operations = { | 67 | static const struct file_operations befs_dir_operations = { |
68 | .read = generic_read_dir, | 68 | .read = generic_read_dir, |
69 | .readdir = befs_readdir, | 69 | .iterate = befs_readdir, |
70 | .llseek = generic_file_llseek, | 70 | .llseek = generic_file_llseek, |
71 | }; | 71 | }; |
72 | 72 | ||
@@ -211,9 +211,9 @@ befs_lookup(struct inode *dir, struct dentry *dentry, unsigned int flags) | |||
211 | } | 211 | } |
212 | 212 | ||
213 | static int | 213 | static int |
214 | befs_readdir(struct file *filp, void *dirent, filldir_t filldir) | 214 | befs_readdir(struct file *file, struct dir_context *ctx) |
215 | { | 215 | { |
216 | struct inode *inode = file_inode(filp); | 216 | struct inode *inode = file_inode(file); |
217 | struct super_block *sb = inode->i_sb; | 217 | struct super_block *sb = inode->i_sb; |
218 | befs_data_stream *ds = &BEFS_I(inode)->i_data.ds; | 218 | befs_data_stream *ds = &BEFS_I(inode)->i_data.ds; |
219 | befs_off_t value; | 219 | befs_off_t value; |
@@ -221,15 +221,14 @@ befs_readdir(struct file *filp, void *dirent, filldir_t filldir) | |||
221 | size_t keysize; | 221 | size_t keysize; |
222 | unsigned char d_type; | 222 | unsigned char d_type; |
223 | char keybuf[BEFS_NAME_LEN + 1]; | 223 | char keybuf[BEFS_NAME_LEN + 1]; |
224 | char *nlsname; | 224 | const char *dirname = file->f_path.dentry->d_name.name; |
225 | int nlsnamelen; | ||
226 | const char *dirname = filp->f_path.dentry->d_name.name; | ||
227 | 225 | ||
228 | befs_debug(sb, "---> befs_readdir() " | 226 | befs_debug(sb, "---> befs_readdir() " |
229 | "name %s, inode %ld, filp->f_pos %Ld", | 227 | "name %s, inode %ld, ctx->pos %Ld", |
230 | dirname, inode->i_ino, filp->f_pos); | 228 | dirname, inode->i_ino, ctx->pos); |
231 | 229 | ||
232 | result = befs_btree_read(sb, ds, filp->f_pos, BEFS_NAME_LEN + 1, | 230 | more: |
231 | result = befs_btree_read(sb, ds, ctx->pos, BEFS_NAME_LEN + 1, | ||
233 | keybuf, &keysize, &value); | 232 | keybuf, &keysize, &value); |
234 | 233 | ||
235 | if (result == BEFS_ERR) { | 234 | if (result == BEFS_ERR) { |
@@ -251,24 +250,29 @@ befs_readdir(struct file *filp, void *dirent, filldir_t filldir) | |||
251 | 250 | ||
252 | /* Convert to NLS */ | 251 | /* Convert to NLS */ |
253 | if (BEFS_SB(sb)->nls) { | 252 | if (BEFS_SB(sb)->nls) { |
253 | char *nlsname; | ||
254 | int nlsnamelen; | ||
254 | result = | 255 | result = |
255 | befs_utf2nls(sb, keybuf, keysize, &nlsname, &nlsnamelen); | 256 | befs_utf2nls(sb, keybuf, keysize, &nlsname, &nlsnamelen); |
256 | if (result < 0) { | 257 | if (result < 0) { |
257 | befs_debug(sb, "<--- befs_readdir() ERROR"); | 258 | befs_debug(sb, "<--- befs_readdir() ERROR"); |
258 | return result; | 259 | return result; |
259 | } | 260 | } |
260 | result = filldir(dirent, nlsname, nlsnamelen, filp->f_pos, | 261 | if (!dir_emit(ctx, nlsname, nlsnamelen, |
261 | (ino_t) value, d_type); | 262 | (ino_t) value, d_type)) { |
263 | kfree(nlsname); | ||
264 | return 0; | ||
265 | } | ||
262 | kfree(nlsname); | 266 | kfree(nlsname); |
263 | |||
264 | } else { | 267 | } else { |
265 | result = filldir(dirent, keybuf, keysize, filp->f_pos, | 268 | if (!dir_emit(ctx, keybuf, keysize, |
266 | (ino_t) value, d_type); | 269 | (ino_t) value, d_type)) |
270 | return 0; | ||
267 | } | 271 | } |
268 | if (!result) | 272 | ctx->pos++; |
269 | filp->f_pos++; | 273 | goto more; |
270 | 274 | ||
271 | befs_debug(sb, "<--- befs_readdir() filp->f_pos %Ld", filp->f_pos); | 275 | befs_debug(sb, "<--- befs_readdir() pos %Ld", ctx->pos); |
272 | 276 | ||
273 | return 0; | 277 | return 0; |
274 | } | 278 | } |
diff --git a/fs/bfs/dir.c b/fs/bfs/dir.c index 3f422f6bb5ca..a399e6d9dc74 100644 --- a/fs/bfs/dir.c +++ b/fs/bfs/dir.c | |||
@@ -26,58 +26,51 @@ static struct buffer_head *bfs_find_entry(struct inode *dir, | |||
26 | const unsigned char *name, int namelen, | 26 | const unsigned char *name, int namelen, |
27 | struct bfs_dirent **res_dir); | 27 | struct bfs_dirent **res_dir); |
28 | 28 | ||
29 | static int bfs_readdir(struct file *f, void *dirent, filldir_t filldir) | 29 | static int bfs_readdir(struct file *f, struct dir_context *ctx) |
30 | { | 30 | { |
31 | struct inode *dir = file_inode(f); | 31 | struct inode *dir = file_inode(f); |
32 | struct buffer_head *bh; | 32 | struct buffer_head *bh; |
33 | struct bfs_dirent *de; | 33 | struct bfs_dirent *de; |
34 | struct bfs_sb_info *info = BFS_SB(dir->i_sb); | ||
35 | unsigned int offset; | 34 | unsigned int offset; |
36 | int block; | 35 | int block; |
37 | 36 | ||
38 | mutex_lock(&info->bfs_lock); | 37 | if (ctx->pos & (BFS_DIRENT_SIZE - 1)) { |
39 | |||
40 | if (f->f_pos & (BFS_DIRENT_SIZE - 1)) { | ||
41 | printf("Bad f_pos=%08lx for %s:%08lx\n", | 38 | printf("Bad f_pos=%08lx for %s:%08lx\n", |
42 | (unsigned long)f->f_pos, | 39 | (unsigned long)ctx->pos, |
43 | dir->i_sb->s_id, dir->i_ino); | 40 | dir->i_sb->s_id, dir->i_ino); |
44 | mutex_unlock(&info->bfs_lock); | 41 | return -EINVAL; |
45 | return -EBADF; | ||
46 | } | 42 | } |
47 | 43 | ||
48 | while (f->f_pos < dir->i_size) { | 44 | while (ctx->pos < dir->i_size) { |
49 | offset = f->f_pos & (BFS_BSIZE - 1); | 45 | offset = ctx->pos & (BFS_BSIZE - 1); |
50 | block = BFS_I(dir)->i_sblock + (f->f_pos >> BFS_BSIZE_BITS); | 46 | block = BFS_I(dir)->i_sblock + (ctx->pos >> BFS_BSIZE_BITS); |
51 | bh = sb_bread(dir->i_sb, block); | 47 | bh = sb_bread(dir->i_sb, block); |
52 | if (!bh) { | 48 | if (!bh) { |
53 | f->f_pos += BFS_BSIZE - offset; | 49 | ctx->pos += BFS_BSIZE - offset; |
54 | continue; | 50 | continue; |
55 | } | 51 | } |
56 | do { | 52 | do { |
57 | de = (struct bfs_dirent *)(bh->b_data + offset); | 53 | de = (struct bfs_dirent *)(bh->b_data + offset); |
58 | if (de->ino) { | 54 | if (de->ino) { |
59 | int size = strnlen(de->name, BFS_NAMELEN); | 55 | int size = strnlen(de->name, BFS_NAMELEN); |
60 | if (filldir(dirent, de->name, size, f->f_pos, | 56 | if (!dir_emit(ctx, de->name, size, |
61 | le16_to_cpu(de->ino), | 57 | le16_to_cpu(de->ino), |
62 | DT_UNKNOWN) < 0) { | 58 | DT_UNKNOWN)) { |
63 | brelse(bh); | 59 | brelse(bh); |
64 | mutex_unlock(&info->bfs_lock); | ||
65 | return 0; | 60 | return 0; |
66 | } | 61 | } |
67 | } | 62 | } |
68 | offset += BFS_DIRENT_SIZE; | 63 | offset += BFS_DIRENT_SIZE; |
69 | f->f_pos += BFS_DIRENT_SIZE; | 64 | ctx->pos += BFS_DIRENT_SIZE; |
70 | } while ((offset < BFS_BSIZE) && (f->f_pos < dir->i_size)); | 65 | } while ((offset < BFS_BSIZE) && (ctx->pos < dir->i_size)); |
71 | brelse(bh); | 66 | brelse(bh); |
72 | } | 67 | } |
73 | 68 | return 0; | |
74 | mutex_unlock(&info->bfs_lock); | ||
75 | return 0; | ||
76 | } | 69 | } |
77 | 70 | ||
78 | const struct file_operations bfs_dir_operations = { | 71 | const struct file_operations bfs_dir_operations = { |
79 | .read = generic_read_dir, | 72 | .read = generic_read_dir, |
80 | .readdir = bfs_readdir, | 73 | .iterate = bfs_readdir, |
81 | .fsync = generic_file_fsync, | 74 | .fsync = generic_file_fsync, |
82 | .llseek = generic_file_llseek, | 75 | .llseek = generic_file_llseek, |
83 | }; | 76 | }; |
diff --git a/fs/btrfs/delayed-inode.c b/fs/btrfs/delayed-inode.c index f26f38ccd194..eb34438ddedb 100644 --- a/fs/btrfs/delayed-inode.c +++ b/fs/btrfs/delayed-inode.c | |||
@@ -1681,8 +1681,7 @@ int btrfs_should_delete_dir_index(struct list_head *del_list, | |||
1681 | * btrfs_readdir_delayed_dir_index - read dir info stored in the delayed tree | 1681 | * btrfs_readdir_delayed_dir_index - read dir info stored in the delayed tree |
1682 | * | 1682 | * |
1683 | */ | 1683 | */ |
1684 | int btrfs_readdir_delayed_dir_index(struct file *filp, void *dirent, | 1684 | int btrfs_readdir_delayed_dir_index(struct dir_context *ctx, |
1685 | filldir_t filldir, | ||
1686 | struct list_head *ins_list) | 1685 | struct list_head *ins_list) |
1687 | { | 1686 | { |
1688 | struct btrfs_dir_item *di; | 1687 | struct btrfs_dir_item *di; |
@@ -1704,13 +1703,13 @@ int btrfs_readdir_delayed_dir_index(struct file *filp, void *dirent, | |||
1704 | list_for_each_entry_safe(curr, next, ins_list, readdir_list) { | 1703 | list_for_each_entry_safe(curr, next, ins_list, readdir_list) { |
1705 | list_del(&curr->readdir_list); | 1704 | list_del(&curr->readdir_list); |
1706 | 1705 | ||
1707 | if (curr->key.offset < filp->f_pos) { | 1706 | if (curr->key.offset < ctx->pos) { |
1708 | if (atomic_dec_and_test(&curr->refs)) | 1707 | if (atomic_dec_and_test(&curr->refs)) |
1709 | kfree(curr); | 1708 | kfree(curr); |
1710 | continue; | 1709 | continue; |
1711 | } | 1710 | } |
1712 | 1711 | ||
1713 | filp->f_pos = curr->key.offset; | 1712 | ctx->pos = curr->key.offset; |
1714 | 1713 | ||
1715 | di = (struct btrfs_dir_item *)curr->data; | 1714 | di = (struct btrfs_dir_item *)curr->data; |
1716 | name = (char *)(di + 1); | 1715 | name = (char *)(di + 1); |
@@ -1719,7 +1718,7 @@ int btrfs_readdir_delayed_dir_index(struct file *filp, void *dirent, | |||
1719 | d_type = btrfs_filetype_table[di->type]; | 1718 | d_type = btrfs_filetype_table[di->type]; |
1720 | btrfs_disk_key_to_cpu(&location, &di->location); | 1719 | btrfs_disk_key_to_cpu(&location, &di->location); |
1721 | 1720 | ||
1722 | over = filldir(dirent, name, name_len, curr->key.offset, | 1721 | over = !dir_emit(ctx, name, name_len, |
1723 | location.objectid, d_type); | 1722 | location.objectid, d_type); |
1724 | 1723 | ||
1725 | if (atomic_dec_and_test(&curr->refs)) | 1724 | if (atomic_dec_and_test(&curr->refs)) |
diff --git a/fs/btrfs/delayed-inode.h b/fs/btrfs/delayed-inode.h index 1d5c5f7abe3e..a4b38f934d14 100644 --- a/fs/btrfs/delayed-inode.h +++ b/fs/btrfs/delayed-inode.h | |||
@@ -139,8 +139,7 @@ void btrfs_put_delayed_items(struct list_head *ins_list, | |||
139 | struct list_head *del_list); | 139 | struct list_head *del_list); |
140 | int btrfs_should_delete_dir_index(struct list_head *del_list, | 140 | int btrfs_should_delete_dir_index(struct list_head *del_list, |
141 | u64 index); | 141 | u64 index); |
142 | int btrfs_readdir_delayed_dir_index(struct file *filp, void *dirent, | 142 | int btrfs_readdir_delayed_dir_index(struct dir_context *ctx, |
143 | filldir_t filldir, | ||
144 | struct list_head *ins_list); | 143 | struct list_head *ins_list); |
145 | 144 | ||
146 | /* for init */ | 145 | /* for init */ |
diff --git a/fs/btrfs/inode.c b/fs/btrfs/inode.c index 17f3064b4a3e..a46b656d08de 100644 --- a/fs/btrfs/inode.c +++ b/fs/btrfs/inode.c | |||
@@ -5137,10 +5137,9 @@ unsigned char btrfs_filetype_table[] = { | |||
5137 | DT_UNKNOWN, DT_REG, DT_DIR, DT_CHR, DT_BLK, DT_FIFO, DT_SOCK, DT_LNK | 5137 | DT_UNKNOWN, DT_REG, DT_DIR, DT_CHR, DT_BLK, DT_FIFO, DT_SOCK, DT_LNK |
5138 | }; | 5138 | }; |
5139 | 5139 | ||
5140 | static int btrfs_real_readdir(struct file *filp, void *dirent, | 5140 | static int btrfs_real_readdir(struct file *file, struct dir_context *ctx) |
5141 | filldir_t filldir) | ||
5142 | { | 5141 | { |
5143 | struct inode *inode = file_inode(filp); | 5142 | struct inode *inode = file_inode(file); |
5144 | struct btrfs_root *root = BTRFS_I(inode)->root; | 5143 | struct btrfs_root *root = BTRFS_I(inode)->root; |
5145 | struct btrfs_item *item; | 5144 | struct btrfs_item *item; |
5146 | struct btrfs_dir_item *di; | 5145 | struct btrfs_dir_item *di; |
@@ -5161,29 +5160,15 @@ static int btrfs_real_readdir(struct file *filp, void *dirent, | |||
5161 | char tmp_name[32]; | 5160 | char tmp_name[32]; |
5162 | char *name_ptr; | 5161 | char *name_ptr; |
5163 | int name_len; | 5162 | int name_len; |
5164 | int is_curr = 0; /* filp->f_pos points to the current index? */ | 5163 | int is_curr = 0; /* ctx->pos points to the current index? */ |
5165 | 5164 | ||
5166 | /* FIXME, use a real flag for deciding about the key type */ | 5165 | /* FIXME, use a real flag for deciding about the key type */ |
5167 | if (root->fs_info->tree_root == root) | 5166 | if (root->fs_info->tree_root == root) |
5168 | key_type = BTRFS_DIR_ITEM_KEY; | 5167 | key_type = BTRFS_DIR_ITEM_KEY; |
5169 | 5168 | ||
5170 | /* special case for "." */ | 5169 | if (!dir_emit_dots(file, ctx)) |
5171 | if (filp->f_pos == 0) { | 5170 | return 0; |
5172 | over = filldir(dirent, ".", 1, | 5171 | |
5173 | filp->f_pos, btrfs_ino(inode), DT_DIR); | ||
5174 | if (over) | ||
5175 | return 0; | ||
5176 | filp->f_pos = 1; | ||
5177 | } | ||
5178 | /* special case for .., just use the back ref */ | ||
5179 | if (filp->f_pos == 1) { | ||
5180 | u64 pino = parent_ino(filp->f_path.dentry); | ||
5181 | over = filldir(dirent, "..", 2, | ||
5182 | filp->f_pos, pino, DT_DIR); | ||
5183 | if (over) | ||
5184 | return 0; | ||
5185 | filp->f_pos = 2; | ||
5186 | } | ||
5187 | path = btrfs_alloc_path(); | 5172 | path = btrfs_alloc_path(); |
5188 | if (!path) | 5173 | if (!path) |
5189 | return -ENOMEM; | 5174 | return -ENOMEM; |
@@ -5197,7 +5182,7 @@ static int btrfs_real_readdir(struct file *filp, void *dirent, | |||
5197 | } | 5182 | } |
5198 | 5183 | ||
5199 | btrfs_set_key_type(&key, key_type); | 5184 | btrfs_set_key_type(&key, key_type); |
5200 | key.offset = filp->f_pos; | 5185 | key.offset = ctx->pos; |
5201 | key.objectid = btrfs_ino(inode); | 5186 | key.objectid = btrfs_ino(inode); |
5202 | 5187 | ||
5203 | ret = btrfs_search_slot(NULL, root, &key, path, 0, 0); | 5188 | ret = btrfs_search_slot(NULL, root, &key, path, 0, 0); |
@@ -5223,14 +5208,14 @@ static int btrfs_real_readdir(struct file *filp, void *dirent, | |||
5223 | break; | 5208 | break; |
5224 | if (btrfs_key_type(&found_key) != key_type) | 5209 | if (btrfs_key_type(&found_key) != key_type) |
5225 | break; | 5210 | break; |
5226 | if (found_key.offset < filp->f_pos) | 5211 | if (found_key.offset < ctx->pos) |
5227 | goto next; | 5212 | goto next; |
5228 | if (key_type == BTRFS_DIR_INDEX_KEY && | 5213 | if (key_type == BTRFS_DIR_INDEX_KEY && |
5229 | btrfs_should_delete_dir_index(&del_list, | 5214 | btrfs_should_delete_dir_index(&del_list, |
5230 | found_key.offset)) | 5215 | found_key.offset)) |
5231 | goto next; | 5216 | goto next; |
5232 | 5217 | ||
5233 | filp->f_pos = found_key.offset; | 5218 | ctx->pos = found_key.offset; |
5234 | is_curr = 1; | 5219 | is_curr = 1; |
5235 | 5220 | ||
5236 | di = btrfs_item_ptr(leaf, slot, struct btrfs_dir_item); | 5221 | di = btrfs_item_ptr(leaf, slot, struct btrfs_dir_item); |
@@ -5274,9 +5259,8 @@ static int btrfs_real_readdir(struct file *filp, void *dirent, | |||
5274 | over = 0; | 5259 | over = 0; |
5275 | goto skip; | 5260 | goto skip; |
5276 | } | 5261 | } |
5277 | over = filldir(dirent, name_ptr, name_len, | 5262 | over = !dir_emit(ctx, name_ptr, name_len, |
5278 | found_key.offset, location.objectid, | 5263 | location.objectid, d_type); |
5279 | d_type); | ||
5280 | 5264 | ||
5281 | skip: | 5265 | skip: |
5282 | if (name_ptr != tmp_name) | 5266 | if (name_ptr != tmp_name) |
@@ -5295,9 +5279,8 @@ next: | |||
5295 | 5279 | ||
5296 | if (key_type == BTRFS_DIR_INDEX_KEY) { | 5280 | if (key_type == BTRFS_DIR_INDEX_KEY) { |
5297 | if (is_curr) | 5281 | if (is_curr) |
5298 | filp->f_pos++; | 5282 | ctx->pos++; |
5299 | ret = btrfs_readdir_delayed_dir_index(filp, dirent, filldir, | 5283 | ret = btrfs_readdir_delayed_dir_index(ctx, &ins_list); |
5300 | &ins_list); | ||
5301 | if (ret) | 5284 | if (ret) |
5302 | goto nopos; | 5285 | goto nopos; |
5303 | } | 5286 | } |
@@ -5308,9 +5291,9 @@ next: | |||
5308 | * 32-bit glibc will use getdents64, but then strtol - | 5291 | * 32-bit glibc will use getdents64, but then strtol - |
5309 | * so the last number we can serve is this. | 5292 | * so the last number we can serve is this. |
5310 | */ | 5293 | */ |
5311 | filp->f_pos = 0x7fffffff; | 5294 | ctx->pos = 0x7fffffff; |
5312 | else | 5295 | else |
5313 | filp->f_pos++; | 5296 | ctx->pos++; |
5314 | nopos: | 5297 | nopos: |
5315 | ret = 0; | 5298 | ret = 0; |
5316 | err: | 5299 | err: |
@@ -8731,7 +8714,7 @@ static const struct inode_operations btrfs_dir_ro_inode_operations = { | |||
8731 | static const struct file_operations btrfs_dir_file_operations = { | 8714 | static const struct file_operations btrfs_dir_file_operations = { |
8732 | .llseek = generic_file_llseek, | 8715 | .llseek = generic_file_llseek, |
8733 | .read = generic_read_dir, | 8716 | .read = generic_read_dir, |
8734 | .readdir = btrfs_real_readdir, | 8717 | .iterate = btrfs_real_readdir, |
8735 | .unlocked_ioctl = btrfs_ioctl, | 8718 | .unlocked_ioctl = btrfs_ioctl, |
8736 | #ifdef CONFIG_COMPAT | 8719 | #ifdef CONFIG_COMPAT |
8737 | .compat_ioctl = btrfs_ioctl, | 8720 | .compat_ioctl = btrfs_ioctl, |
diff --git a/fs/ceph/dir.c b/fs/ceph/dir.c index f02d82b7933e..a40ceda47a32 100644 --- a/fs/ceph/dir.c +++ b/fs/ceph/dir.c | |||
@@ -111,11 +111,10 @@ static unsigned fpos_off(loff_t p) | |||
111 | * defined IFF we hold CEPH_CAP_FILE_SHARED (which will be revoked by | 111 | * defined IFF we hold CEPH_CAP_FILE_SHARED (which will be revoked by |
112 | * the MDS if/when the directory is modified). | 112 | * the MDS if/when the directory is modified). |
113 | */ | 113 | */ |
114 | static int __dcache_readdir(struct file *filp, | 114 | static int __dcache_readdir(struct file *file, struct dir_context *ctx) |
115 | void *dirent, filldir_t filldir) | ||
116 | { | 115 | { |
117 | struct ceph_file_info *fi = filp->private_data; | 116 | struct ceph_file_info *fi = file->private_data; |
118 | struct dentry *parent = filp->f_dentry; | 117 | struct dentry *parent = file->f_dentry; |
119 | struct inode *dir = parent->d_inode; | 118 | struct inode *dir = parent->d_inode; |
120 | struct list_head *p; | 119 | struct list_head *p; |
121 | struct dentry *dentry, *last; | 120 | struct dentry *dentry, *last; |
@@ -126,14 +125,14 @@ static int __dcache_readdir(struct file *filp, | |||
126 | last = fi->dentry; | 125 | last = fi->dentry; |
127 | fi->dentry = NULL; | 126 | fi->dentry = NULL; |
128 | 127 | ||
129 | dout("__dcache_readdir %p at %llu (last %p)\n", dir, filp->f_pos, | 128 | dout("__dcache_readdir %p at %llu (last %p)\n", dir, ctx->pos, |
130 | last); | 129 | last); |
131 | 130 | ||
132 | spin_lock(&parent->d_lock); | 131 | spin_lock(&parent->d_lock); |
133 | 132 | ||
134 | /* start at beginning? */ | 133 | /* start at beginning? */ |
135 | if (filp->f_pos == 2 || last == NULL || | 134 | if (ctx->pos == 2 || last == NULL || |
136 | filp->f_pos < ceph_dentry(last)->offset) { | 135 | ctx->pos < ceph_dentry(last)->offset) { |
137 | if (list_empty(&parent->d_subdirs)) | 136 | if (list_empty(&parent->d_subdirs)) |
138 | goto out_unlock; | 137 | goto out_unlock; |
139 | p = parent->d_subdirs.prev; | 138 | p = parent->d_subdirs.prev; |
@@ -157,11 +156,11 @@ more: | |||
157 | if (!d_unhashed(dentry) && dentry->d_inode && | 156 | if (!d_unhashed(dentry) && dentry->d_inode && |
158 | ceph_snap(dentry->d_inode) != CEPH_SNAPDIR && | 157 | ceph_snap(dentry->d_inode) != CEPH_SNAPDIR && |
159 | ceph_ino(dentry->d_inode) != CEPH_INO_CEPH && | 158 | ceph_ino(dentry->d_inode) != CEPH_INO_CEPH && |
160 | filp->f_pos <= di->offset) | 159 | ctx->pos <= di->offset) |
161 | break; | 160 | break; |
162 | dout(" skipping %p %.*s at %llu (%llu)%s%s\n", dentry, | 161 | dout(" skipping %p %.*s at %llu (%llu)%s%s\n", dentry, |
163 | dentry->d_name.len, dentry->d_name.name, di->offset, | 162 | dentry->d_name.len, dentry->d_name.name, di->offset, |
164 | filp->f_pos, d_unhashed(dentry) ? " unhashed" : "", | 163 | ctx->pos, d_unhashed(dentry) ? " unhashed" : "", |
165 | !dentry->d_inode ? " null" : ""); | 164 | !dentry->d_inode ? " null" : ""); |
166 | spin_unlock(&dentry->d_lock); | 165 | spin_unlock(&dentry->d_lock); |
167 | p = p->prev; | 166 | p = p->prev; |
@@ -173,29 +172,27 @@ more: | |||
173 | spin_unlock(&dentry->d_lock); | 172 | spin_unlock(&dentry->d_lock); |
174 | spin_unlock(&parent->d_lock); | 173 | spin_unlock(&parent->d_lock); |
175 | 174 | ||
176 | dout(" %llu (%llu) dentry %p %.*s %p\n", di->offset, filp->f_pos, | 175 | dout(" %llu (%llu) dentry %p %.*s %p\n", di->offset, ctx->pos, |
177 | dentry, dentry->d_name.len, dentry->d_name.name, dentry->d_inode); | 176 | dentry, dentry->d_name.len, dentry->d_name.name, dentry->d_inode); |
178 | filp->f_pos = di->offset; | 177 | ctx->pos = di->offset; |
179 | err = filldir(dirent, dentry->d_name.name, | 178 | if (!dir_emit(ctx, dentry->d_name.name, |
180 | dentry->d_name.len, di->offset, | 179 | dentry->d_name.len, |
181 | ceph_translate_ino(dentry->d_sb, dentry->d_inode->i_ino), | 180 | ceph_translate_ino(dentry->d_sb, dentry->d_inode->i_ino), |
182 | dentry->d_inode->i_mode >> 12); | 181 | dentry->d_inode->i_mode >> 12)) { |
183 | 182 | if (last) { | |
184 | if (last) { | ||
185 | if (err < 0) { | ||
186 | /* remember our position */ | 183 | /* remember our position */ |
187 | fi->dentry = last; | 184 | fi->dentry = last; |
188 | fi->next_offset = di->offset; | 185 | fi->next_offset = di->offset; |
189 | } else { | ||
190 | dput(last); | ||
191 | } | 186 | } |
187 | dput(dentry); | ||
188 | return 0; | ||
192 | } | 189 | } |
193 | last = dentry; | ||
194 | 190 | ||
195 | if (err < 0) | 191 | if (last) |
196 | goto out; | 192 | dput(last); |
193 | last = dentry; | ||
197 | 194 | ||
198 | filp->f_pos++; | 195 | ctx->pos++; |
199 | 196 | ||
200 | /* make sure a dentry wasn't dropped while we didn't have parent lock */ | 197 | /* make sure a dentry wasn't dropped while we didn't have parent lock */ |
201 | if (!ceph_dir_is_complete(dir)) { | 198 | if (!ceph_dir_is_complete(dir)) { |
@@ -235,59 +232,59 @@ static int note_last_dentry(struct ceph_file_info *fi, const char *name, | |||
235 | return 0; | 232 | return 0; |
236 | } | 233 | } |
237 | 234 | ||
238 | static int ceph_readdir(struct file *filp, void *dirent, filldir_t filldir) | 235 | static int ceph_readdir(struct file *file, struct dir_context *ctx) |
239 | { | 236 | { |
240 | struct ceph_file_info *fi = filp->private_data; | 237 | struct ceph_file_info *fi = file->private_data; |
241 | struct inode *inode = file_inode(filp); | 238 | struct inode *inode = file_inode(file); |
242 | struct ceph_inode_info *ci = ceph_inode(inode); | 239 | struct ceph_inode_info *ci = ceph_inode(inode); |
243 | struct ceph_fs_client *fsc = ceph_inode_to_client(inode); | 240 | struct ceph_fs_client *fsc = ceph_inode_to_client(inode); |
244 | struct ceph_mds_client *mdsc = fsc->mdsc; | 241 | struct ceph_mds_client *mdsc = fsc->mdsc; |
245 | unsigned frag = fpos_frag(filp->f_pos); | 242 | unsigned frag = fpos_frag(ctx->pos); |
246 | int off = fpos_off(filp->f_pos); | 243 | int off = fpos_off(ctx->pos); |
247 | int err; | 244 | int err; |
248 | u32 ftype; | 245 | u32 ftype; |
249 | struct ceph_mds_reply_info_parsed *rinfo; | 246 | struct ceph_mds_reply_info_parsed *rinfo; |
250 | const int max_entries = fsc->mount_options->max_readdir; | 247 | const int max_entries = fsc->mount_options->max_readdir; |
251 | const int max_bytes = fsc->mount_options->max_readdir_bytes; | 248 | const int max_bytes = fsc->mount_options->max_readdir_bytes; |
252 | 249 | ||
253 | dout("readdir %p filp %p frag %u off %u\n", inode, filp, frag, off); | 250 | dout("readdir %p file %p frag %u off %u\n", inode, file, frag, off); |
254 | if (fi->flags & CEPH_F_ATEND) | 251 | if (fi->flags & CEPH_F_ATEND) |
255 | return 0; | 252 | return 0; |
256 | 253 | ||
257 | /* always start with . and .. */ | 254 | /* always start with . and .. */ |
258 | if (filp->f_pos == 0) { | 255 | if (ctx->pos == 0) { |
259 | /* note dir version at start of readdir so we can tell | 256 | /* note dir version at start of readdir so we can tell |
260 | * if any dentries get dropped */ | 257 | * if any dentries get dropped */ |
261 | fi->dir_release_count = atomic_read(&ci->i_release_count); | 258 | fi->dir_release_count = atomic_read(&ci->i_release_count); |
262 | 259 | ||
263 | dout("readdir off 0 -> '.'\n"); | 260 | dout("readdir off 0 -> '.'\n"); |
264 | if (filldir(dirent, ".", 1, ceph_make_fpos(0, 0), | 261 | if (!dir_emit(ctx, ".", 1, |
265 | ceph_translate_ino(inode->i_sb, inode->i_ino), | 262 | ceph_translate_ino(inode->i_sb, inode->i_ino), |
266 | inode->i_mode >> 12) < 0) | 263 | inode->i_mode >> 12)) |
267 | return 0; | 264 | return 0; |
268 | filp->f_pos = 1; | 265 | ctx->pos = 1; |
269 | off = 1; | 266 | off = 1; |
270 | } | 267 | } |
271 | if (filp->f_pos == 1) { | 268 | if (ctx->pos == 1) { |
272 | ino_t ino = parent_ino(filp->f_dentry); | 269 | ino_t ino = parent_ino(file->f_dentry); |
273 | dout("readdir off 1 -> '..'\n"); | 270 | dout("readdir off 1 -> '..'\n"); |
274 | if (filldir(dirent, "..", 2, ceph_make_fpos(0, 1), | 271 | if (!dir_emit(ctx, "..", 2, |
275 | ceph_translate_ino(inode->i_sb, ino), | 272 | ceph_translate_ino(inode->i_sb, ino), |
276 | inode->i_mode >> 12) < 0) | 273 | inode->i_mode >> 12)) |
277 | return 0; | 274 | return 0; |
278 | filp->f_pos = 2; | 275 | ctx->pos = 2; |
279 | off = 2; | 276 | off = 2; |
280 | } | 277 | } |
281 | 278 | ||
282 | /* can we use the dcache? */ | 279 | /* can we use the dcache? */ |
283 | spin_lock(&ci->i_ceph_lock); | 280 | spin_lock(&ci->i_ceph_lock); |
284 | if ((filp->f_pos == 2 || fi->dentry) && | 281 | if ((ctx->pos == 2 || fi->dentry) && |
285 | !ceph_test_mount_opt(fsc, NOASYNCREADDIR) && | 282 | !ceph_test_mount_opt(fsc, NOASYNCREADDIR) && |
286 | ceph_snap(inode) != CEPH_SNAPDIR && | 283 | ceph_snap(inode) != CEPH_SNAPDIR && |
287 | __ceph_dir_is_complete(ci) && | 284 | __ceph_dir_is_complete(ci) && |
288 | __ceph_caps_issued_mask(ci, CEPH_CAP_FILE_SHARED, 1)) { | 285 | __ceph_caps_issued_mask(ci, CEPH_CAP_FILE_SHARED, 1)) { |
289 | spin_unlock(&ci->i_ceph_lock); | 286 | spin_unlock(&ci->i_ceph_lock); |
290 | err = __dcache_readdir(filp, dirent, filldir); | 287 | err = __dcache_readdir(file, ctx); |
291 | if (err != -EAGAIN) | 288 | if (err != -EAGAIN) |
292 | return err; | 289 | return err; |
293 | } else { | 290 | } else { |
@@ -327,7 +324,7 @@ more: | |||
327 | return PTR_ERR(req); | 324 | return PTR_ERR(req); |
328 | req->r_inode = inode; | 325 | req->r_inode = inode; |
329 | ihold(inode); | 326 | ihold(inode); |
330 | req->r_dentry = dget(filp->f_dentry); | 327 | req->r_dentry = dget(file->f_dentry); |
331 | /* hints to request -> mds selection code */ | 328 | /* hints to request -> mds selection code */ |
332 | req->r_direct_mode = USE_AUTH_MDS; | 329 | req->r_direct_mode = USE_AUTH_MDS; |
333 | req->r_direct_hash = ceph_frag_value(frag); | 330 | req->r_direct_hash = ceph_frag_value(frag); |
@@ -379,15 +376,16 @@ more: | |||
379 | rinfo = &fi->last_readdir->r_reply_info; | 376 | rinfo = &fi->last_readdir->r_reply_info; |
380 | dout("readdir frag %x num %d off %d chunkoff %d\n", frag, | 377 | dout("readdir frag %x num %d off %d chunkoff %d\n", frag, |
381 | rinfo->dir_nr, off, fi->offset); | 378 | rinfo->dir_nr, off, fi->offset); |
379 | |||
380 | ctx->pos = ceph_make_fpos(frag, off); | ||
382 | while (off >= fi->offset && off - fi->offset < rinfo->dir_nr) { | 381 | while (off >= fi->offset && off - fi->offset < rinfo->dir_nr) { |
383 | u64 pos = ceph_make_fpos(frag, off); | ||
384 | struct ceph_mds_reply_inode *in = | 382 | struct ceph_mds_reply_inode *in = |
385 | rinfo->dir_in[off - fi->offset].in; | 383 | rinfo->dir_in[off - fi->offset].in; |
386 | struct ceph_vino vino; | 384 | struct ceph_vino vino; |
387 | ino_t ino; | 385 | ino_t ino; |
388 | 386 | ||
389 | dout("readdir off %d (%d/%d) -> %lld '%.*s' %p\n", | 387 | dout("readdir off %d (%d/%d) -> %lld '%.*s' %p\n", |
390 | off, off - fi->offset, rinfo->dir_nr, pos, | 388 | off, off - fi->offset, rinfo->dir_nr, ctx->pos, |
391 | rinfo->dir_dname_len[off - fi->offset], | 389 | rinfo->dir_dname_len[off - fi->offset], |
392 | rinfo->dir_dname[off - fi->offset], in); | 390 | rinfo->dir_dname[off - fi->offset], in); |
393 | BUG_ON(!in); | 391 | BUG_ON(!in); |
@@ -395,16 +393,15 @@ more: | |||
395 | vino.ino = le64_to_cpu(in->ino); | 393 | vino.ino = le64_to_cpu(in->ino); |
396 | vino.snap = le64_to_cpu(in->snapid); | 394 | vino.snap = le64_to_cpu(in->snapid); |
397 | ino = ceph_vino_to_ino(vino); | 395 | ino = ceph_vino_to_ino(vino); |
398 | if (filldir(dirent, | 396 | if (!dir_emit(ctx, |
399 | rinfo->dir_dname[off - fi->offset], | 397 | rinfo->dir_dname[off - fi->offset], |
400 | rinfo->dir_dname_len[off - fi->offset], | 398 | rinfo->dir_dname_len[off - fi->offset], |
401 | pos, | 399 | ceph_translate_ino(inode->i_sb, ino), ftype)) { |
402 | ceph_translate_ino(inode->i_sb, ino), ftype) < 0) { | ||
403 | dout("filldir stopping us...\n"); | 400 | dout("filldir stopping us...\n"); |
404 | return 0; | 401 | return 0; |
405 | } | 402 | } |
406 | off++; | 403 | off++; |
407 | filp->f_pos = pos + 1; | 404 | ctx->pos++; |
408 | } | 405 | } |
409 | 406 | ||
410 | if (fi->last_name) { | 407 | if (fi->last_name) { |
@@ -417,7 +414,7 @@ more: | |||
417 | if (!ceph_frag_is_rightmost(frag)) { | 414 | if (!ceph_frag_is_rightmost(frag)) { |
418 | frag = ceph_frag_next(frag); | 415 | frag = ceph_frag_next(frag); |
419 | off = 0; | 416 | off = 0; |
420 | filp->f_pos = ceph_make_fpos(frag, off); | 417 | ctx->pos = ceph_make_fpos(frag, off); |
421 | dout("readdir next frag is %x\n", frag); | 418 | dout("readdir next frag is %x\n", frag); |
422 | goto more; | 419 | goto more; |
423 | } | 420 | } |
@@ -432,11 +429,11 @@ more: | |||
432 | if (atomic_read(&ci->i_release_count) == fi->dir_release_count) { | 429 | if (atomic_read(&ci->i_release_count) == fi->dir_release_count) { |
433 | dout(" marking %p complete\n", inode); | 430 | dout(" marking %p complete\n", inode); |
434 | __ceph_dir_set_complete(ci, fi->dir_release_count); | 431 | __ceph_dir_set_complete(ci, fi->dir_release_count); |
435 | ci->i_max_offset = filp->f_pos; | 432 | ci->i_max_offset = ctx->pos; |
436 | } | 433 | } |
437 | spin_unlock(&ci->i_ceph_lock); | 434 | spin_unlock(&ci->i_ceph_lock); |
438 | 435 | ||
439 | dout("readdir %p filp %p done.\n", inode, filp); | 436 | dout("readdir %p file %p done.\n", inode, file); |
440 | return 0; | 437 | return 0; |
441 | } | 438 | } |
442 | 439 | ||
@@ -1268,7 +1265,7 @@ unsigned ceph_dentry_hash(struct inode *dir, struct dentry *dn) | |||
1268 | 1265 | ||
1269 | const struct file_operations ceph_dir_fops = { | 1266 | const struct file_operations ceph_dir_fops = { |
1270 | .read = ceph_read_dir, | 1267 | .read = ceph_read_dir, |
1271 | .readdir = ceph_readdir, | 1268 | .iterate = ceph_readdir, |
1272 | .llseek = ceph_dir_llseek, | 1269 | .llseek = ceph_dir_llseek, |
1273 | .open = ceph_open, | 1270 | .open = ceph_open, |
1274 | .release = ceph_release, | 1271 | .release = ceph_release, |
diff --git a/fs/cifs/cifsfs.c b/fs/cifs/cifsfs.c index 3752b9f6d9e4..540c1ccfcdb2 100644 --- a/fs/cifs/cifsfs.c +++ b/fs/cifs/cifsfs.c | |||
@@ -968,7 +968,7 @@ const struct file_operations cifs_file_direct_nobrl_ops = { | |||
968 | }; | 968 | }; |
969 | 969 | ||
970 | const struct file_operations cifs_dir_ops = { | 970 | const struct file_operations cifs_dir_ops = { |
971 | .readdir = cifs_readdir, | 971 | .iterate = cifs_readdir, |
972 | .release = cifs_closedir, | 972 | .release = cifs_closedir, |
973 | .read = generic_read_dir, | 973 | .read = generic_read_dir, |
974 | .unlocked_ioctl = cifs_ioctl, | 974 | .unlocked_ioctl = cifs_ioctl, |
diff --git a/fs/cifs/cifsfs.h b/fs/cifs/cifsfs.h index 0e32c3446ce9..d05b3028e3b9 100644 --- a/fs/cifs/cifsfs.h +++ b/fs/cifs/cifsfs.h | |||
@@ -101,7 +101,7 @@ extern int cifs_file_mmap(struct file * , struct vm_area_struct *); | |||
101 | extern int cifs_file_strict_mmap(struct file * , struct vm_area_struct *); | 101 | extern int cifs_file_strict_mmap(struct file * , struct vm_area_struct *); |
102 | extern const struct file_operations cifs_dir_ops; | 102 | extern const struct file_operations cifs_dir_ops; |
103 | extern int cifs_dir_open(struct inode *inode, struct file *file); | 103 | extern int cifs_dir_open(struct inode *inode, struct file *file); |
104 | extern int cifs_readdir(struct file *file, void *direntry, filldir_t filldir); | 104 | extern int cifs_readdir(struct file *file, struct dir_context *ctx); |
105 | 105 | ||
106 | /* Functions related to dir entries */ | 106 | /* Functions related to dir entries */ |
107 | extern const struct dentry_operations cifs_dentry_ops; | 107 | extern const struct dentry_operations cifs_dentry_ops; |
diff --git a/fs/cifs/readdir.c b/fs/cifs/readdir.c index 770d5a9781c1..f1213799de1a 100644 --- a/fs/cifs/readdir.c +++ b/fs/cifs/readdir.c | |||
@@ -537,14 +537,14 @@ static int cifs_save_resume_key(const char *current_entry, | |||
537 | * every entry (do not increment for . or .. entry). | 537 | * every entry (do not increment for . or .. entry). |
538 | */ | 538 | */ |
539 | static int | 539 | static int |
540 | find_cifs_entry(const unsigned int xid, struct cifs_tcon *tcon, | 540 | find_cifs_entry(const unsigned int xid, struct cifs_tcon *tcon, loff_t pos, |
541 | struct file *file, char **current_entry, int *num_to_ret) | 541 | struct file *file, char **current_entry, int *num_to_ret) |
542 | { | 542 | { |
543 | __u16 search_flags; | 543 | __u16 search_flags; |
544 | int rc = 0; | 544 | int rc = 0; |
545 | int pos_in_buf = 0; | 545 | int pos_in_buf = 0; |
546 | loff_t first_entry_in_buffer; | 546 | loff_t first_entry_in_buffer; |
547 | loff_t index_to_find = file->f_pos; | 547 | loff_t index_to_find = pos; |
548 | struct cifsFileInfo *cfile = file->private_data; | 548 | struct cifsFileInfo *cfile = file->private_data; |
549 | struct cifs_sb_info *cifs_sb = CIFS_SB(file->f_path.dentry->d_sb); | 549 | struct cifs_sb_info *cifs_sb = CIFS_SB(file->f_path.dentry->d_sb); |
550 | struct TCP_Server_Info *server = tcon->ses->server; | 550 | struct TCP_Server_Info *server = tcon->ses->server; |
@@ -659,8 +659,9 @@ find_cifs_entry(const unsigned int xid, struct cifs_tcon *tcon, | |||
659 | return rc; | 659 | return rc; |
660 | } | 660 | } |
661 | 661 | ||
662 | static int cifs_filldir(char *find_entry, struct file *file, filldir_t filldir, | 662 | static int cifs_filldir(char *find_entry, struct file *file, |
663 | void *dirent, char *scratch_buf, unsigned int max_len) | 663 | struct dir_context *ctx, |
664 | char *scratch_buf, unsigned int max_len) | ||
664 | { | 665 | { |
665 | struct cifsFileInfo *file_info = file->private_data; | 666 | struct cifsFileInfo *file_info = file->private_data; |
666 | struct super_block *sb = file->f_path.dentry->d_sb; | 667 | struct super_block *sb = file->f_path.dentry->d_sb; |
@@ -740,13 +741,11 @@ static int cifs_filldir(char *find_entry, struct file *file, filldir_t filldir, | |||
740 | cifs_prime_dcache(file->f_dentry, &name, &fattr); | 741 | cifs_prime_dcache(file->f_dentry, &name, &fattr); |
741 | 742 | ||
742 | ino = cifs_uniqueid_to_ino_t(fattr.cf_uniqueid); | 743 | ino = cifs_uniqueid_to_ino_t(fattr.cf_uniqueid); |
743 | rc = filldir(dirent, name.name, name.len, file->f_pos, ino, | 744 | return !dir_emit(ctx, name.name, name.len, ino, fattr.cf_dtype); |
744 | fattr.cf_dtype); | ||
745 | return rc; | ||
746 | } | 745 | } |
747 | 746 | ||
748 | 747 | ||
749 | int cifs_readdir(struct file *file, void *direntry, filldir_t filldir) | 748 | int cifs_readdir(struct file *file, struct dir_context *ctx) |
750 | { | 749 | { |
751 | int rc = 0; | 750 | int rc = 0; |
752 | unsigned int xid; | 751 | unsigned int xid; |
@@ -772,103 +771,86 @@ int cifs_readdir(struct file *file, void *direntry, filldir_t filldir) | |||
772 | goto rddir2_exit; | 771 | goto rddir2_exit; |
773 | } | 772 | } |
774 | 773 | ||
775 | switch ((int) file->f_pos) { | 774 | if (!dir_emit_dots(file, ctx)) |
776 | case 0: | 775 | goto rddir2_exit; |
777 | if (filldir(direntry, ".", 1, file->f_pos, | ||
778 | file_inode(file)->i_ino, DT_DIR) < 0) { | ||
779 | cifs_dbg(VFS, "Filldir for current dir failed\n"); | ||
780 | rc = -ENOMEM; | ||
781 | break; | ||
782 | } | ||
783 | file->f_pos++; | ||
784 | case 1: | ||
785 | if (filldir(direntry, "..", 2, file->f_pos, | ||
786 | parent_ino(file->f_path.dentry), DT_DIR) < 0) { | ||
787 | cifs_dbg(VFS, "Filldir for parent dir failed\n"); | ||
788 | rc = -ENOMEM; | ||
789 | break; | ||
790 | } | ||
791 | file->f_pos++; | ||
792 | default: | ||
793 | /* 1) If search is active, | ||
794 | is in current search buffer? | ||
795 | if it before then restart search | ||
796 | if after then keep searching till find it */ | ||
797 | |||
798 | if (file->private_data == NULL) { | ||
799 | rc = -EINVAL; | ||
800 | free_xid(xid); | ||
801 | return rc; | ||
802 | } | ||
803 | cifsFile = file->private_data; | ||
804 | if (cifsFile->srch_inf.endOfSearch) { | ||
805 | if (cifsFile->srch_inf.emptyDir) { | ||
806 | cifs_dbg(FYI, "End of search, empty dir\n"); | ||
807 | rc = 0; | ||
808 | break; | ||
809 | } | ||
810 | } /* else { | ||
811 | cifsFile->invalidHandle = true; | ||
812 | tcon->ses->server->close(xid, tcon, &cifsFile->fid); | ||
813 | } */ | ||
814 | 776 | ||
815 | tcon = tlink_tcon(cifsFile->tlink); | 777 | /* 1) If search is active, |
816 | rc = find_cifs_entry(xid, tcon, file, ¤t_entry, | 778 | is in current search buffer? |
817 | &num_to_fill); | 779 | if it before then restart search |
818 | if (rc) { | 780 | if after then keep searching till find it */ |
819 | cifs_dbg(FYI, "fce error %d\n", rc); | 781 | |
820 | goto rddir2_exit; | 782 | if (file->private_data == NULL) { |
821 | } else if (current_entry != NULL) { | 783 | rc = -EINVAL; |
822 | cifs_dbg(FYI, "entry %lld found\n", file->f_pos); | 784 | goto rddir2_exit; |
823 | } else { | 785 | } |
824 | cifs_dbg(FYI, "could not find entry\n"); | 786 | cifsFile = file->private_data; |
787 | if (cifsFile->srch_inf.endOfSearch) { | ||
788 | if (cifsFile->srch_inf.emptyDir) { | ||
789 | cifs_dbg(FYI, "End of search, empty dir\n"); | ||
790 | rc = 0; | ||
825 | goto rddir2_exit; | 791 | goto rddir2_exit; |
826 | } | 792 | } |
827 | cifs_dbg(FYI, "loop through %d times filling dir for net buf %p\n", | 793 | } /* else { |
828 | num_to_fill, cifsFile->srch_inf.ntwrk_buf_start); | 794 | cifsFile->invalidHandle = true; |
829 | max_len = tcon->ses->server->ops->calc_smb_size( | 795 | tcon->ses->server->close(xid, tcon, &cifsFile->fid); |
830 | cifsFile->srch_inf.ntwrk_buf_start); | 796 | } */ |
831 | end_of_smb = cifsFile->srch_inf.ntwrk_buf_start + max_len; | 797 | |
832 | 798 | tcon = tlink_tcon(cifsFile->tlink); | |
833 | tmp_buf = kmalloc(UNICODE_NAME_MAX, GFP_KERNEL); | 799 | rc = find_cifs_entry(xid, tcon, ctx->pos, file, ¤t_entry, |
834 | if (tmp_buf == NULL) { | 800 | &num_to_fill); |
835 | rc = -ENOMEM; | 801 | if (rc) { |
802 | cifs_dbg(FYI, "fce error %d\n", rc); | ||
803 | goto rddir2_exit; | ||
804 | } else if (current_entry != NULL) { | ||
805 | cifs_dbg(FYI, "entry %lld found\n", ctx->pos); | ||
806 | } else { | ||
807 | cifs_dbg(FYI, "could not find entry\n"); | ||
808 | goto rddir2_exit; | ||
809 | } | ||
810 | cifs_dbg(FYI, "loop through %d times filling dir for net buf %p\n", | ||
811 | num_to_fill, cifsFile->srch_inf.ntwrk_buf_start); | ||
812 | max_len = tcon->ses->server->ops->calc_smb_size( | ||
813 | cifsFile->srch_inf.ntwrk_buf_start); | ||
814 | end_of_smb = cifsFile->srch_inf.ntwrk_buf_start + max_len; | ||
815 | |||
816 | tmp_buf = kmalloc(UNICODE_NAME_MAX, GFP_KERNEL); | ||
817 | if (tmp_buf == NULL) { | ||
818 | rc = -ENOMEM; | ||
819 | goto rddir2_exit; | ||
820 | } | ||
821 | |||
822 | for (i = 0; i < num_to_fill; i++) { | ||
823 | if (current_entry == NULL) { | ||
824 | /* evaluate whether this case is an error */ | ||
825 | cifs_dbg(VFS, "past SMB end, num to fill %d i %d\n", | ||
826 | num_to_fill, i); | ||
836 | break; | 827 | break; |
837 | } | 828 | } |
838 | 829 | /* | |
839 | for (i = 0; (i < num_to_fill) && (rc == 0); i++) { | 830 | * if buggy server returns . and .. late do we want to |
840 | if (current_entry == NULL) { | 831 | * check for that here? |
841 | /* evaluate whether this case is an error */ | 832 | */ |
842 | cifs_dbg(VFS, "past SMB end, num to fill %d i %d\n", | 833 | rc = cifs_filldir(current_entry, file, ctx, |
843 | num_to_fill, i); | 834 | tmp_buf, max_len); |
844 | break; | 835 | if (rc) { |
845 | } | 836 | if (rc > 0) |
846 | /* | ||
847 | * if buggy server returns . and .. late do we want to | ||
848 | * check for that here? | ||
849 | */ | ||
850 | rc = cifs_filldir(current_entry, file, filldir, | ||
851 | direntry, tmp_buf, max_len); | ||
852 | if (rc == -EOVERFLOW) { | ||
853 | rc = 0; | 837 | rc = 0; |
854 | break; | 838 | break; |
855 | } | ||
856 | |||
857 | file->f_pos++; | ||
858 | if (file->f_pos == | ||
859 | cifsFile->srch_inf.index_of_last_entry) { | ||
860 | cifs_dbg(FYI, "last entry in buf at pos %lld %s\n", | ||
861 | file->f_pos, tmp_buf); | ||
862 | cifs_save_resume_key(current_entry, cifsFile); | ||
863 | break; | ||
864 | } else | ||
865 | current_entry = | ||
866 | nxt_dir_entry(current_entry, end_of_smb, | ||
867 | cifsFile->srch_inf.info_level); | ||
868 | } | 839 | } |
869 | kfree(tmp_buf); | 840 | |
870 | break; | 841 | ctx->pos++; |
871 | } /* end switch */ | 842 | if (ctx->pos == |
843 | cifsFile->srch_inf.index_of_last_entry) { | ||
844 | cifs_dbg(FYI, "last entry in buf at pos %lld %s\n", | ||
845 | ctx->pos, tmp_buf); | ||
846 | cifs_save_resume_key(current_entry, cifsFile); | ||
847 | break; | ||
848 | } else | ||
849 | current_entry = | ||
850 | nxt_dir_entry(current_entry, end_of_smb, | ||
851 | cifsFile->srch_inf.info_level); | ||
852 | } | ||
853 | kfree(tmp_buf); | ||
872 | 854 | ||
873 | rddir2_exit: | 855 | rddir2_exit: |
874 | free_xid(xid); | 856 | free_xid(xid); |
diff --git a/fs/coda/dir.c b/fs/coda/dir.c index b7d3a05c062c..87e0ee9f4465 100644 --- a/fs/coda/dir.c +++ b/fs/coda/dir.c | |||
@@ -43,15 +43,14 @@ static int coda_rename(struct inode *old_inode, struct dentry *old_dentry, | |||
43 | struct inode *new_inode, struct dentry *new_dentry); | 43 | struct inode *new_inode, struct dentry *new_dentry); |
44 | 44 | ||
45 | /* dir file-ops */ | 45 | /* dir file-ops */ |
46 | static int coda_readdir(struct file *file, void *buf, filldir_t filldir); | 46 | static int coda_readdir(struct file *file, struct dir_context *ctx); |
47 | 47 | ||
48 | /* dentry ops */ | 48 | /* dentry ops */ |
49 | static int coda_dentry_revalidate(struct dentry *de, unsigned int flags); | 49 | static int coda_dentry_revalidate(struct dentry *de, unsigned int flags); |
50 | static int coda_dentry_delete(const struct dentry *); | 50 | static int coda_dentry_delete(const struct dentry *); |
51 | 51 | ||
52 | /* support routines */ | 52 | /* support routines */ |
53 | static int coda_venus_readdir(struct file *coda_file, void *buf, | 53 | static int coda_venus_readdir(struct file *, struct dir_context *); |
54 | filldir_t filldir); | ||
55 | 54 | ||
56 | /* same as fs/bad_inode.c */ | 55 | /* same as fs/bad_inode.c */ |
57 | static int coda_return_EIO(void) | 56 | static int coda_return_EIO(void) |
@@ -85,7 +84,7 @@ const struct inode_operations coda_dir_inode_operations = | |||
85 | const struct file_operations coda_dir_operations = { | 84 | const struct file_operations coda_dir_operations = { |
86 | .llseek = generic_file_llseek, | 85 | .llseek = generic_file_llseek, |
87 | .read = generic_read_dir, | 86 | .read = generic_read_dir, |
88 | .readdir = coda_readdir, | 87 | .iterate = coda_readdir, |
89 | .open = coda_open, | 88 | .open = coda_open, |
90 | .release = coda_release, | 89 | .release = coda_release, |
91 | .fsync = coda_fsync, | 90 | .fsync = coda_fsync, |
@@ -378,7 +377,7 @@ static int coda_rename(struct inode *old_dir, struct dentry *old_dentry, | |||
378 | 377 | ||
379 | 378 | ||
380 | /* file operations for directories */ | 379 | /* file operations for directories */ |
381 | static int coda_readdir(struct file *coda_file, void *buf, filldir_t filldir) | 380 | static int coda_readdir(struct file *coda_file, struct dir_context *ctx) |
382 | { | 381 | { |
383 | struct coda_file_info *cfi; | 382 | struct coda_file_info *cfi; |
384 | struct file *host_file; | 383 | struct file *host_file; |
@@ -391,30 +390,19 @@ static int coda_readdir(struct file *coda_file, void *buf, filldir_t filldir) | |||
391 | if (!host_file->f_op) | 390 | if (!host_file->f_op) |
392 | return -ENOTDIR; | 391 | return -ENOTDIR; |
393 | 392 | ||
394 | if (host_file->f_op->readdir) | 393 | if (host_file->f_op->iterate) { |
395 | { | ||
396 | /* potemkin case: we were handed a directory inode. | ||
397 | * We can't use vfs_readdir because we have to keep the file | ||
398 | * position in sync between the coda_file and the host_file. | ||
399 | * and as such we need grab the inode mutex. */ | ||
400 | struct inode *host_inode = file_inode(host_file); | 394 | struct inode *host_inode = file_inode(host_file); |
401 | |||
402 | mutex_lock(&host_inode->i_mutex); | 395 | mutex_lock(&host_inode->i_mutex); |
403 | host_file->f_pos = coda_file->f_pos; | ||
404 | |||
405 | ret = -ENOENT; | 396 | ret = -ENOENT; |
406 | if (!IS_DEADDIR(host_inode)) { | 397 | if (!IS_DEADDIR(host_inode)) { |
407 | ret = host_file->f_op->readdir(host_file, buf, filldir); | 398 | ret = host_file->f_op->iterate(host_file, ctx); |
408 | file_accessed(host_file); | 399 | file_accessed(host_file); |
409 | } | 400 | } |
410 | |||
411 | coda_file->f_pos = host_file->f_pos; | ||
412 | mutex_unlock(&host_inode->i_mutex); | 401 | mutex_unlock(&host_inode->i_mutex); |
402 | return ret; | ||
413 | } | 403 | } |
414 | else /* Venus: we must read Venus dirents from a file */ | 404 | /* Venus: we must read Venus dirents from a file */ |
415 | ret = coda_venus_readdir(coda_file, buf, filldir); | 405 | return coda_venus_readdir(coda_file, ctx); |
416 | |||
417 | return ret; | ||
418 | } | 406 | } |
419 | 407 | ||
420 | static inline unsigned int CDT2DT(unsigned char cdt) | 408 | static inline unsigned int CDT2DT(unsigned char cdt) |
@@ -437,10 +425,8 @@ static inline unsigned int CDT2DT(unsigned char cdt) | |||
437 | } | 425 | } |
438 | 426 | ||
439 | /* support routines */ | 427 | /* support routines */ |
440 | static int coda_venus_readdir(struct file *coda_file, void *buf, | 428 | static int coda_venus_readdir(struct file *coda_file, struct dir_context *ctx) |
441 | filldir_t filldir) | ||
442 | { | 429 | { |
443 | int result = 0; /* # of entries returned */ | ||
444 | struct coda_file_info *cfi; | 430 | struct coda_file_info *cfi; |
445 | struct coda_inode_info *cii; | 431 | struct coda_inode_info *cii; |
446 | struct file *host_file; | 432 | struct file *host_file; |
@@ -462,23 +448,12 @@ static int coda_venus_readdir(struct file *coda_file, void *buf, | |||
462 | vdir = kmalloc(sizeof(*vdir), GFP_KERNEL); | 448 | vdir = kmalloc(sizeof(*vdir), GFP_KERNEL); |
463 | if (!vdir) return -ENOMEM; | 449 | if (!vdir) return -ENOMEM; |
464 | 450 | ||
465 | if (coda_file->f_pos == 0) { | 451 | if (!dir_emit_dots(coda_file, ctx)) |
466 | ret = filldir(buf, ".", 1, 0, de->d_inode->i_ino, DT_DIR); | 452 | goto out; |
467 | if (ret < 0) | 453 | |
468 | goto out; | ||
469 | result++; | ||
470 | coda_file->f_pos++; | ||
471 | } | ||
472 | if (coda_file->f_pos == 1) { | ||
473 | ret = filldir(buf, "..", 2, 1, parent_ino(de), DT_DIR); | ||
474 | if (ret < 0) | ||
475 | goto out; | ||
476 | result++; | ||
477 | coda_file->f_pos++; | ||
478 | } | ||
479 | while (1) { | 454 | while (1) { |
480 | /* read entries from the directory file */ | 455 | /* read entries from the directory file */ |
481 | ret = kernel_read(host_file, coda_file->f_pos - 2, (char *)vdir, | 456 | ret = kernel_read(host_file, ctx->pos - 2, (char *)vdir, |
482 | sizeof(*vdir)); | 457 | sizeof(*vdir)); |
483 | if (ret < 0) { | 458 | if (ret < 0) { |
484 | printk(KERN_ERR "coda readdir: read dir %s failed %d\n", | 459 | printk(KERN_ERR "coda readdir: read dir %s failed %d\n", |
@@ -507,7 +482,7 @@ static int coda_venus_readdir(struct file *coda_file, void *buf, | |||
507 | 482 | ||
508 | /* Make sure we skip '.' and '..', we already got those */ | 483 | /* Make sure we skip '.' and '..', we already got those */ |
509 | if (name.name[0] == '.' && (name.len == 1 || | 484 | if (name.name[0] == '.' && (name.len == 1 || |
510 | (vdir->d_name[1] == '.' && name.len == 2))) | 485 | (name.name[1] == '.' && name.len == 2))) |
511 | vdir->d_fileno = name.len = 0; | 486 | vdir->d_fileno = name.len = 0; |
512 | 487 | ||
513 | /* skip null entries */ | 488 | /* skip null entries */ |
@@ -520,19 +495,16 @@ static int coda_venus_readdir(struct file *coda_file, void *buf, | |||
520 | if (!ino) ino = vdir->d_fileno; | 495 | if (!ino) ino = vdir->d_fileno; |
521 | 496 | ||
522 | type = CDT2DT(vdir->d_type); | 497 | type = CDT2DT(vdir->d_type); |
523 | ret = filldir(buf, name.name, name.len, | 498 | if (!dir_emit(ctx, name.name, name.len, ino, type)) |
524 | coda_file->f_pos, ino, type); | 499 | break; |
525 | /* failure means no space for filling in this round */ | ||
526 | if (ret < 0) break; | ||
527 | result++; | ||
528 | } | 500 | } |
529 | /* we'll always have progress because d_reclen is unsigned and | 501 | /* we'll always have progress because d_reclen is unsigned and |
530 | * we've already established it is non-zero. */ | 502 | * we've already established it is non-zero. */ |
531 | coda_file->f_pos += vdir->d_reclen; | 503 | ctx->pos += vdir->d_reclen; |
532 | } | 504 | } |
533 | out: | 505 | out: |
534 | kfree(vdir); | 506 | kfree(vdir); |
535 | return result ? result : ret; | 507 | return 0; |
536 | } | 508 | } |
537 | 509 | ||
538 | /* called when a cache lookup succeeds */ | 510 | /* called when a cache lookup succeeds */ |
diff --git a/fs/compat.c b/fs/compat.c index fc3b55dce184..6af20de2c1a3 100644 --- a/fs/compat.c +++ b/fs/compat.c | |||
@@ -832,6 +832,7 @@ struct compat_old_linux_dirent { | |||
832 | }; | 832 | }; |
833 | 833 | ||
834 | struct compat_readdir_callback { | 834 | struct compat_readdir_callback { |
835 | struct dir_context ctx; | ||
835 | struct compat_old_linux_dirent __user *dirent; | 836 | struct compat_old_linux_dirent __user *dirent; |
836 | int result; | 837 | int result; |
837 | }; | 838 | }; |
@@ -873,15 +874,15 @@ asmlinkage long compat_sys_old_readdir(unsigned int fd, | |||
873 | { | 874 | { |
874 | int error; | 875 | int error; |
875 | struct fd f = fdget(fd); | 876 | struct fd f = fdget(fd); |
876 | struct compat_readdir_callback buf; | 877 | struct compat_readdir_callback buf = { |
878 | .ctx.actor = compat_fillonedir, | ||
879 | .dirent = dirent | ||
880 | }; | ||
877 | 881 | ||
878 | if (!f.file) | 882 | if (!f.file) |
879 | return -EBADF; | 883 | return -EBADF; |
880 | 884 | ||
881 | buf.result = 0; | 885 | error = iterate_dir(f.file, &buf.ctx); |
882 | buf.dirent = dirent; | ||
883 | |||
884 | error = vfs_readdir(f.file, compat_fillonedir, &buf); | ||
885 | if (buf.result) | 886 | if (buf.result) |
886 | error = buf.result; | 887 | error = buf.result; |
887 | 888 | ||
@@ -897,6 +898,7 @@ struct compat_linux_dirent { | |||
897 | }; | 898 | }; |
898 | 899 | ||
899 | struct compat_getdents_callback { | 900 | struct compat_getdents_callback { |
901 | struct dir_context ctx; | ||
900 | struct compat_linux_dirent __user *current_dir; | 902 | struct compat_linux_dirent __user *current_dir; |
901 | struct compat_linux_dirent __user *previous; | 903 | struct compat_linux_dirent __user *previous; |
902 | int count; | 904 | int count; |
@@ -951,7 +953,11 @@ asmlinkage long compat_sys_getdents(unsigned int fd, | |||
951 | { | 953 | { |
952 | struct fd f; | 954 | struct fd f; |
953 | struct compat_linux_dirent __user * lastdirent; | 955 | struct compat_linux_dirent __user * lastdirent; |
954 | struct compat_getdents_callback buf; | 956 | struct compat_getdents_callback buf = { |
957 | .ctx.actor = compat_filldir, | ||
958 | .current_dir = dirent, | ||
959 | .count = count | ||
960 | }; | ||
955 | int error; | 961 | int error; |
956 | 962 | ||
957 | if (!access_ok(VERIFY_WRITE, dirent, count)) | 963 | if (!access_ok(VERIFY_WRITE, dirent, count)) |
@@ -961,17 +967,12 @@ asmlinkage long compat_sys_getdents(unsigned int fd, | |||
961 | if (!f.file) | 967 | if (!f.file) |
962 | return -EBADF; | 968 | return -EBADF; |
963 | 969 | ||
964 | buf.current_dir = dirent; | 970 | error = iterate_dir(f.file, &buf.ctx); |
965 | buf.previous = NULL; | ||
966 | buf.count = count; | ||
967 | buf.error = 0; | ||
968 | |||
969 | error = vfs_readdir(f.file, compat_filldir, &buf); | ||
970 | if (error >= 0) | 971 | if (error >= 0) |
971 | error = buf.error; | 972 | error = buf.error; |
972 | lastdirent = buf.previous; | 973 | lastdirent = buf.previous; |
973 | if (lastdirent) { | 974 | if (lastdirent) { |
974 | if (put_user(f.file->f_pos, &lastdirent->d_off)) | 975 | if (put_user(buf.ctx.pos, &lastdirent->d_off)) |
975 | error = -EFAULT; | 976 | error = -EFAULT; |
976 | else | 977 | else |
977 | error = count - buf.count; | 978 | error = count - buf.count; |
@@ -983,6 +984,7 @@ asmlinkage long compat_sys_getdents(unsigned int fd, | |||
983 | #ifndef __ARCH_OMIT_COMPAT_SYS_GETDENTS64 | 984 | #ifndef __ARCH_OMIT_COMPAT_SYS_GETDENTS64 |
984 | 985 | ||
985 | struct compat_getdents_callback64 { | 986 | struct compat_getdents_callback64 { |
987 | struct dir_context ctx; | ||
986 | struct linux_dirent64 __user *current_dir; | 988 | struct linux_dirent64 __user *current_dir; |
987 | struct linux_dirent64 __user *previous; | 989 | struct linux_dirent64 __user *previous; |
988 | int count; | 990 | int count; |
@@ -1036,7 +1038,11 @@ asmlinkage long compat_sys_getdents64(unsigned int fd, | |||
1036 | { | 1038 | { |
1037 | struct fd f; | 1039 | struct fd f; |
1038 | struct linux_dirent64 __user * lastdirent; | 1040 | struct linux_dirent64 __user * lastdirent; |
1039 | struct compat_getdents_callback64 buf; | 1041 | struct compat_getdents_callback64 buf = { |
1042 | .ctx.actor = compat_filldir64, | ||
1043 | .current_dir = dirent, | ||
1044 | .count = count | ||
1045 | }; | ||
1040 | int error; | 1046 | int error; |
1041 | 1047 | ||
1042 | if (!access_ok(VERIFY_WRITE, dirent, count)) | 1048 | if (!access_ok(VERIFY_WRITE, dirent, count)) |
@@ -1046,17 +1052,12 @@ asmlinkage long compat_sys_getdents64(unsigned int fd, | |||
1046 | if (!f.file) | 1052 | if (!f.file) |
1047 | return -EBADF; | 1053 | return -EBADF; |
1048 | 1054 | ||
1049 | buf.current_dir = dirent; | 1055 | error = iterate_dir(f.file, &buf.ctx); |
1050 | buf.previous = NULL; | ||
1051 | buf.count = count; | ||
1052 | buf.error = 0; | ||
1053 | |||
1054 | error = vfs_readdir(f.file, compat_filldir64, &buf); | ||
1055 | if (error >= 0) | 1056 | if (error >= 0) |
1056 | error = buf.error; | 1057 | error = buf.error; |
1057 | lastdirent = buf.previous; | 1058 | lastdirent = buf.previous; |
1058 | if (lastdirent) { | 1059 | if (lastdirent) { |
1059 | typeof(lastdirent->d_off) d_off = f.file->f_pos; | 1060 | typeof(lastdirent->d_off) d_off = buf.ctx.pos; |
1060 | if (__put_user_unaligned(d_off, &lastdirent->d_off)) | 1061 | if (__put_user_unaligned(d_off, &lastdirent->d_off)) |
1061 | error = -EFAULT; | 1062 | error = -EFAULT; |
1062 | else | 1063 | else |
diff --git a/fs/compat_ioctl.c b/fs/compat_ioctl.c index 996cdc5abb85..5d19acfa7c6c 100644 --- a/fs/compat_ioctl.c +++ b/fs/compat_ioctl.c | |||
@@ -66,7 +66,6 @@ | |||
66 | #include <linux/gigaset_dev.h> | 66 | #include <linux/gigaset_dev.h> |
67 | 67 | ||
68 | #ifdef CONFIG_BLOCK | 68 | #ifdef CONFIG_BLOCK |
69 | #include <linux/loop.h> | ||
70 | #include <linux/cdrom.h> | 69 | #include <linux/cdrom.h> |
71 | #include <linux/fd.h> | 70 | #include <linux/fd.h> |
72 | #include <scsi/scsi.h> | 71 | #include <scsi/scsi.h> |
@@ -954,8 +953,6 @@ COMPATIBLE_IOCTL(MTIOCTOP) | |||
954 | /* Socket level stuff */ | 953 | /* Socket level stuff */ |
955 | COMPATIBLE_IOCTL(FIOQSIZE) | 954 | COMPATIBLE_IOCTL(FIOQSIZE) |
956 | #ifdef CONFIG_BLOCK | 955 | #ifdef CONFIG_BLOCK |
957 | /* loop */ | ||
958 | IGNORE_IOCTL(LOOP_CLR_FD) | ||
959 | /* md calls this on random blockdevs */ | 956 | /* md calls this on random blockdevs */ |
960 | IGNORE_IOCTL(RAID_VERSION) | 957 | IGNORE_IOCTL(RAID_VERSION) |
961 | /* qemu/qemu-img might call these two on plain files for probing */ | 958 | /* qemu/qemu-img might call these two on plain files for probing */ |
diff --git a/fs/configfs/dir.c b/fs/configfs/dir.c index 7aabc6ad4e9b..64e5323cbbb0 100644 --- a/fs/configfs/dir.c +++ b/fs/configfs/dir.c | |||
@@ -1532,84 +1532,66 @@ static inline unsigned char dt_type(struct configfs_dirent *sd) | |||
1532 | return (sd->s_mode >> 12) & 15; | 1532 | return (sd->s_mode >> 12) & 15; |
1533 | } | 1533 | } |
1534 | 1534 | ||
1535 | static int configfs_readdir(struct file * filp, void * dirent, filldir_t filldir) | 1535 | static int configfs_readdir(struct file *file, struct dir_context *ctx) |
1536 | { | 1536 | { |
1537 | struct dentry *dentry = filp->f_path.dentry; | 1537 | struct dentry *dentry = file->f_path.dentry; |
1538 | struct super_block *sb = dentry->d_sb; | 1538 | struct super_block *sb = dentry->d_sb; |
1539 | struct configfs_dirent * parent_sd = dentry->d_fsdata; | 1539 | struct configfs_dirent * parent_sd = dentry->d_fsdata; |
1540 | struct configfs_dirent *cursor = filp->private_data; | 1540 | struct configfs_dirent *cursor = file->private_data; |
1541 | struct list_head *p, *q = &cursor->s_sibling; | 1541 | struct list_head *p, *q = &cursor->s_sibling; |
1542 | ino_t ino = 0; | 1542 | ino_t ino = 0; |
1543 | int i = filp->f_pos; | ||
1544 | 1543 | ||
1545 | switch (i) { | 1544 | if (!dir_emit_dots(file, ctx)) |
1546 | case 0: | 1545 | return 0; |
1547 | ino = dentry->d_inode->i_ino; | 1546 | if (ctx->pos == 2) { |
1548 | if (filldir(dirent, ".", 1, i, ino, DT_DIR) < 0) | 1547 | spin_lock(&configfs_dirent_lock); |
1549 | break; | 1548 | list_move(q, &parent_sd->s_children); |
1550 | filp->f_pos++; | 1549 | spin_unlock(&configfs_dirent_lock); |
1551 | i++; | 1550 | } |
1552 | /* fallthrough */ | 1551 | for (p = q->next; p != &parent_sd->s_children; p = p->next) { |
1553 | case 1: | 1552 | struct configfs_dirent *next; |
1554 | ino = parent_ino(dentry); | 1553 | const char *name; |
1555 | if (filldir(dirent, "..", 2, i, ino, DT_DIR) < 0) | 1554 | int len; |
1556 | break; | 1555 | struct inode *inode = NULL; |
1557 | filp->f_pos++; | 1556 | |
1558 | i++; | 1557 | next = list_entry(p, struct configfs_dirent, s_sibling); |
1559 | /* fallthrough */ | 1558 | if (!next->s_element) |
1560 | default: | 1559 | continue; |
1561 | if (filp->f_pos == 2) { | ||
1562 | spin_lock(&configfs_dirent_lock); | ||
1563 | list_move(q, &parent_sd->s_children); | ||
1564 | spin_unlock(&configfs_dirent_lock); | ||
1565 | } | ||
1566 | for (p=q->next; p!= &parent_sd->s_children; p=p->next) { | ||
1567 | struct configfs_dirent *next; | ||
1568 | const char * name; | ||
1569 | int len; | ||
1570 | struct inode *inode = NULL; | ||
1571 | 1560 | ||
1572 | next = list_entry(p, struct configfs_dirent, | 1561 | name = configfs_get_name(next); |
1573 | s_sibling); | 1562 | len = strlen(name); |
1574 | if (!next->s_element) | 1563 | |
1575 | continue; | 1564 | /* |
1576 | 1565 | * We'll have a dentry and an inode for | |
1577 | name = configfs_get_name(next); | 1566 | * PINNED items and for open attribute |
1578 | len = strlen(name); | 1567 | * files. We lock here to prevent a race |
1579 | 1568 | * with configfs_d_iput() clearing | |
1580 | /* | 1569 | * s_dentry before calling iput(). |
1581 | * We'll have a dentry and an inode for | 1570 | * |
1582 | * PINNED items and for open attribute | 1571 | * Why do we go to the trouble? If |
1583 | * files. We lock here to prevent a race | 1572 | * someone has an attribute file open, |
1584 | * with configfs_d_iput() clearing | 1573 | * the inode number should match until |
1585 | * s_dentry before calling iput(). | 1574 | * they close it. Beyond that, we don't |
1586 | * | 1575 | * care. |
1587 | * Why do we go to the trouble? If | 1576 | */ |
1588 | * someone has an attribute file open, | 1577 | spin_lock(&configfs_dirent_lock); |
1589 | * the inode number should match until | 1578 | dentry = next->s_dentry; |
1590 | * they close it. Beyond that, we don't | 1579 | if (dentry) |
1591 | * care. | 1580 | inode = dentry->d_inode; |
1592 | */ | 1581 | if (inode) |
1593 | spin_lock(&configfs_dirent_lock); | 1582 | ino = inode->i_ino; |
1594 | dentry = next->s_dentry; | 1583 | spin_unlock(&configfs_dirent_lock); |
1595 | if (dentry) | 1584 | if (!inode) |
1596 | inode = dentry->d_inode; | 1585 | ino = iunique(sb, 2); |
1597 | if (inode) | ||
1598 | ino = inode->i_ino; | ||
1599 | spin_unlock(&configfs_dirent_lock); | ||
1600 | if (!inode) | ||
1601 | ino = iunique(sb, 2); | ||
1602 | 1586 | ||
1603 | if (filldir(dirent, name, len, filp->f_pos, ino, | 1587 | if (!dir_emit(ctx, name, len, ino, dt_type(next))) |
1604 | dt_type(next)) < 0) | 1588 | return 0; |
1605 | return 0; | ||
1606 | 1589 | ||
1607 | spin_lock(&configfs_dirent_lock); | 1590 | spin_lock(&configfs_dirent_lock); |
1608 | list_move(q, p); | 1591 | list_move(q, p); |
1609 | spin_unlock(&configfs_dirent_lock); | 1592 | spin_unlock(&configfs_dirent_lock); |
1610 | p = q; | 1593 | p = q; |
1611 | filp->f_pos++; | 1594 | ctx->pos++; |
1612 | } | ||
1613 | } | 1595 | } |
1614 | return 0; | 1596 | return 0; |
1615 | } | 1597 | } |
@@ -1661,7 +1643,7 @@ const struct file_operations configfs_dir_operations = { | |||
1661 | .release = configfs_dir_close, | 1643 | .release = configfs_dir_close, |
1662 | .llseek = configfs_dir_lseek, | 1644 | .llseek = configfs_dir_lseek, |
1663 | .read = generic_read_dir, | 1645 | .read = generic_read_dir, |
1664 | .readdir = configfs_readdir, | 1646 | .iterate = configfs_readdir, |
1665 | }; | 1647 | }; |
1666 | 1648 | ||
1667 | int configfs_register_subsystem(struct configfs_subsystem *subsys) | 1649 | int configfs_register_subsystem(struct configfs_subsystem *subsys) |
diff --git a/fs/cramfs/inode.c b/fs/cramfs/inode.c index 35b1c7bd18b7..e501ac3a49ff 100644 --- a/fs/cramfs/inode.c +++ b/fs/cramfs/inode.c | |||
@@ -349,18 +349,17 @@ static int cramfs_statfs(struct dentry *dentry, struct kstatfs *buf) | |||
349 | /* | 349 | /* |
350 | * Read a cramfs directory entry. | 350 | * Read a cramfs directory entry. |
351 | */ | 351 | */ |
352 | static int cramfs_readdir(struct file *filp, void *dirent, filldir_t filldir) | 352 | static int cramfs_readdir(struct file *file, struct dir_context *ctx) |
353 | { | 353 | { |
354 | struct inode *inode = file_inode(filp); | 354 | struct inode *inode = file_inode(file); |
355 | struct super_block *sb = inode->i_sb; | 355 | struct super_block *sb = inode->i_sb; |
356 | char *buf; | 356 | char *buf; |
357 | unsigned int offset; | 357 | unsigned int offset; |
358 | int copied; | ||
359 | 358 | ||
360 | /* Offset within the thing. */ | 359 | /* Offset within the thing. */ |
361 | offset = filp->f_pos; | 360 | if (ctx->pos >= inode->i_size) |
362 | if (offset >= inode->i_size) | ||
363 | return 0; | 361 | return 0; |
362 | offset = ctx->pos; | ||
364 | /* Directory entries are always 4-byte aligned */ | 363 | /* Directory entries are always 4-byte aligned */ |
365 | if (offset & 3) | 364 | if (offset & 3) |
366 | return -EINVAL; | 365 | return -EINVAL; |
@@ -369,14 +368,13 @@ static int cramfs_readdir(struct file *filp, void *dirent, filldir_t filldir) | |||
369 | if (!buf) | 368 | if (!buf) |
370 | return -ENOMEM; | 369 | return -ENOMEM; |
371 | 370 | ||
372 | copied = 0; | ||
373 | while (offset < inode->i_size) { | 371 | while (offset < inode->i_size) { |
374 | struct cramfs_inode *de; | 372 | struct cramfs_inode *de; |
375 | unsigned long nextoffset; | 373 | unsigned long nextoffset; |
376 | char *name; | 374 | char *name; |
377 | ino_t ino; | 375 | ino_t ino; |
378 | umode_t mode; | 376 | umode_t mode; |
379 | int namelen, error; | 377 | int namelen; |
380 | 378 | ||
381 | mutex_lock(&read_mutex); | 379 | mutex_lock(&read_mutex); |
382 | de = cramfs_read(sb, OFFSET(inode) + offset, sizeof(*de)+CRAMFS_MAXPATHLEN); | 380 | de = cramfs_read(sb, OFFSET(inode) + offset, sizeof(*de)+CRAMFS_MAXPATHLEN); |
@@ -402,13 +400,10 @@ static int cramfs_readdir(struct file *filp, void *dirent, filldir_t filldir) | |||
402 | break; | 400 | break; |
403 | namelen--; | 401 | namelen--; |
404 | } | 402 | } |
405 | error = filldir(dirent, buf, namelen, offset, ino, mode >> 12); | 403 | if (!dir_emit(ctx, buf, namelen, ino, mode >> 12)) |
406 | if (error) | ||
407 | break; | 404 | break; |
408 | 405 | ||
409 | offset = nextoffset; | 406 | ctx->pos = offset = nextoffset; |
410 | filp->f_pos = offset; | ||
411 | copied++; | ||
412 | } | 407 | } |
413 | kfree(buf); | 408 | kfree(buf); |
414 | return 0; | 409 | return 0; |
@@ -547,7 +542,7 @@ static const struct address_space_operations cramfs_aops = { | |||
547 | static const struct file_operations cramfs_directory_operations = { | 542 | static const struct file_operations cramfs_directory_operations = { |
548 | .llseek = generic_file_llseek, | 543 | .llseek = generic_file_llseek, |
549 | .read = generic_read_dir, | 544 | .read = generic_read_dir, |
550 | .readdir = cramfs_readdir, | 545 | .iterate = cramfs_readdir, |
551 | }; | 546 | }; |
552 | 547 | ||
553 | static const struct inode_operations cramfs_dir_inode_operations = { | 548 | static const struct inode_operations cramfs_dir_inode_operations = { |
diff --git a/fs/ecryptfs/file.c b/fs/ecryptfs/file.c index a7abbea2c096..9aa05e08060b 100644 --- a/fs/ecryptfs/file.c +++ b/fs/ecryptfs/file.c | |||
@@ -68,9 +68,9 @@ static ssize_t ecryptfs_read_update_atime(struct kiocb *iocb, | |||
68 | } | 68 | } |
69 | 69 | ||
70 | struct ecryptfs_getdents_callback { | 70 | struct ecryptfs_getdents_callback { |
71 | void *dirent; | 71 | struct dir_context ctx; |
72 | struct dir_context *caller; | ||
72 | struct dentry *dentry; | 73 | struct dentry *dentry; |
73 | filldir_t filldir; | ||
74 | int filldir_called; | 74 | int filldir_called; |
75 | int entries_written; | 75 | int entries_written; |
76 | }; | 76 | }; |
@@ -96,9 +96,10 @@ ecryptfs_filldir(void *dirent, const char *lower_name, int lower_namelen, | |||
96 | rc); | 96 | rc); |
97 | goto out; | 97 | goto out; |
98 | } | 98 | } |
99 | rc = buf->filldir(buf->dirent, name, name_size, offset, ino, d_type); | 99 | buf->caller->pos = buf->ctx.pos; |
100 | rc = !dir_emit(buf->caller, name, name_size, ino, d_type); | ||
100 | kfree(name); | 101 | kfree(name); |
101 | if (rc >= 0) | 102 | if (!rc) |
102 | buf->entries_written++; | 103 | buf->entries_written++; |
103 | out: | 104 | out: |
104 | return rc; | 105 | return rc; |
@@ -107,27 +108,23 @@ out: | |||
107 | /** | 108 | /** |
108 | * ecryptfs_readdir | 109 | * ecryptfs_readdir |
109 | * @file: The eCryptfs directory file | 110 | * @file: The eCryptfs directory file |
110 | * @dirent: Directory entry handle | 111 | * @ctx: The actor to feed the entries to |
111 | * @filldir: The filldir callback function | ||
112 | */ | 112 | */ |
113 | static int ecryptfs_readdir(struct file *file, void *dirent, filldir_t filldir) | 113 | static int ecryptfs_readdir(struct file *file, struct dir_context *ctx) |
114 | { | 114 | { |
115 | int rc; | 115 | int rc; |
116 | struct file *lower_file; | 116 | struct file *lower_file; |
117 | struct inode *inode; | 117 | struct inode *inode; |
118 | struct ecryptfs_getdents_callback buf; | 118 | struct ecryptfs_getdents_callback buf = { |
119 | 119 | .ctx.actor = ecryptfs_filldir, | |
120 | .caller = ctx, | ||
121 | .dentry = file->f_path.dentry | ||
122 | }; | ||
120 | lower_file = ecryptfs_file_to_lower(file); | 123 | lower_file = ecryptfs_file_to_lower(file); |
121 | lower_file->f_pos = file->f_pos; | 124 | lower_file->f_pos = ctx->pos; |
122 | inode = file_inode(file); | 125 | inode = file_inode(file); |
123 | memset(&buf, 0, sizeof(buf)); | 126 | rc = iterate_dir(lower_file, &buf.ctx); |
124 | buf.dirent = dirent; | 127 | ctx->pos = buf.ctx.pos; |
125 | buf.dentry = file->f_path.dentry; | ||
126 | buf.filldir = filldir; | ||
127 | buf.filldir_called = 0; | ||
128 | buf.entries_written = 0; | ||
129 | rc = vfs_readdir(lower_file, ecryptfs_filldir, (void *)&buf); | ||
130 | file->f_pos = lower_file->f_pos; | ||
131 | if (rc < 0) | 128 | if (rc < 0) |
132 | goto out; | 129 | goto out; |
133 | if (buf.filldir_called && !buf.entries_written) | 130 | if (buf.filldir_called && !buf.entries_written) |
@@ -344,7 +341,7 @@ ecryptfs_compat_ioctl(struct file *file, unsigned int cmd, unsigned long arg) | |||
344 | #endif | 341 | #endif |
345 | 342 | ||
346 | const struct file_operations ecryptfs_dir_fops = { | 343 | const struct file_operations ecryptfs_dir_fops = { |
347 | .readdir = ecryptfs_readdir, | 344 | .iterate = ecryptfs_readdir, |
348 | .read = generic_read_dir, | 345 | .read = generic_read_dir, |
349 | .unlocked_ioctl = ecryptfs_unlocked_ioctl, | 346 | .unlocked_ioctl = ecryptfs_unlocked_ioctl, |
350 | #ifdef CONFIG_COMPAT | 347 | #ifdef CONFIG_COMPAT |
@@ -365,7 +362,7 @@ const struct file_operations ecryptfs_main_fops = { | |||
365 | .aio_read = ecryptfs_read_update_atime, | 362 | .aio_read = ecryptfs_read_update_atime, |
366 | .write = do_sync_write, | 363 | .write = do_sync_write, |
367 | .aio_write = generic_file_aio_write, | 364 | .aio_write = generic_file_aio_write, |
368 | .readdir = ecryptfs_readdir, | 365 | .iterate = ecryptfs_readdir, |
369 | .unlocked_ioctl = ecryptfs_unlocked_ioctl, | 366 | .unlocked_ioctl = ecryptfs_unlocked_ioctl, |
370 | #ifdef CONFIG_COMPAT | 367 | #ifdef CONFIG_COMPAT |
371 | .compat_ioctl = ecryptfs_compat_ioctl, | 368 | .compat_ioctl = ecryptfs_compat_ioctl, |
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 | ||
diff --git a/fs/exofs/dir.c b/fs/exofs/dir.c index 46375896cfc0..49f51ab4caac 100644 --- a/fs/exofs/dir.c +++ b/fs/exofs/dir.c | |||
@@ -239,22 +239,19 @@ void exofs_set_de_type(struct exofs_dir_entry *de, struct inode *inode) | |||
239 | } | 239 | } |
240 | 240 | ||
241 | static int | 241 | static int |
242 | exofs_readdir(struct file *filp, void *dirent, filldir_t filldir) | 242 | exofs_readdir(struct file *file, struct dir_context *ctx) |
243 | { | 243 | { |
244 | loff_t pos = filp->f_pos; | 244 | loff_t pos = ctx->pos; |
245 | struct inode *inode = file_inode(filp); | 245 | struct inode *inode = file_inode(file); |
246 | unsigned int offset = pos & ~PAGE_CACHE_MASK; | 246 | unsigned int offset = pos & ~PAGE_CACHE_MASK; |
247 | unsigned long n = pos >> PAGE_CACHE_SHIFT; | 247 | unsigned long n = pos >> PAGE_CACHE_SHIFT; |
248 | unsigned long npages = dir_pages(inode); | 248 | unsigned long npages = dir_pages(inode); |
249 | unsigned chunk_mask = ~(exofs_chunk_size(inode)-1); | 249 | unsigned chunk_mask = ~(exofs_chunk_size(inode)-1); |
250 | unsigned char *types = NULL; | 250 | int need_revalidate = (file->f_version != inode->i_version); |
251 | int need_revalidate = (filp->f_version != inode->i_version); | ||
252 | 251 | ||
253 | if (pos > inode->i_size - EXOFS_DIR_REC_LEN(1)) | 252 | if (pos > inode->i_size - EXOFS_DIR_REC_LEN(1)) |
254 | return 0; | 253 | return 0; |
255 | 254 | ||
256 | types = exofs_filetype_table; | ||
257 | |||
258 | for ( ; n < npages; n++, offset = 0) { | 255 | for ( ; n < npages; n++, offset = 0) { |
259 | char *kaddr, *limit; | 256 | char *kaddr, *limit; |
260 | struct exofs_dir_entry *de; | 257 | struct exofs_dir_entry *de; |
@@ -263,7 +260,7 @@ exofs_readdir(struct file *filp, void *dirent, filldir_t filldir) | |||
263 | if (IS_ERR(page)) { | 260 | if (IS_ERR(page)) { |
264 | EXOFS_ERR("ERROR: bad page in directory(0x%lx)\n", | 261 | EXOFS_ERR("ERROR: bad page in directory(0x%lx)\n", |
265 | inode->i_ino); | 262 | inode->i_ino); |
266 | filp->f_pos += PAGE_CACHE_SIZE - offset; | 263 | ctx->pos += PAGE_CACHE_SIZE - offset; |
267 | return PTR_ERR(page); | 264 | return PTR_ERR(page); |
268 | } | 265 | } |
269 | kaddr = page_address(page); | 266 | kaddr = page_address(page); |
@@ -271,9 +268,9 @@ exofs_readdir(struct file *filp, void *dirent, filldir_t filldir) | |||
271 | if (offset) { | 268 | if (offset) { |
272 | offset = exofs_validate_entry(kaddr, offset, | 269 | offset = exofs_validate_entry(kaddr, offset, |
273 | chunk_mask); | 270 | chunk_mask); |
274 | filp->f_pos = (n<<PAGE_CACHE_SHIFT) + offset; | 271 | ctx->pos = (n<<PAGE_CACHE_SHIFT) + offset; |
275 | } | 272 | } |
276 | filp->f_version = inode->i_version; | 273 | file->f_version = inode->i_version; |
277 | need_revalidate = 0; | 274 | need_revalidate = 0; |
278 | } | 275 | } |
279 | de = (struct exofs_dir_entry *)(kaddr + offset); | 276 | de = (struct exofs_dir_entry *)(kaddr + offset); |
@@ -288,27 +285,24 @@ exofs_readdir(struct file *filp, void *dirent, filldir_t filldir) | |||
288 | return -EIO; | 285 | return -EIO; |
289 | } | 286 | } |
290 | if (de->inode_no) { | 287 | if (de->inode_no) { |
291 | int over; | 288 | unsigned char t; |
292 | unsigned char d_type = DT_UNKNOWN; | ||
293 | 289 | ||
294 | if (types && de->file_type < EXOFS_FT_MAX) | 290 | if (de->file_type < EXOFS_FT_MAX) |
295 | d_type = types[de->file_type]; | 291 | t = exofs_filetype_table[de->file_type]; |
292 | else | ||
293 | t = DT_UNKNOWN; | ||
296 | 294 | ||
297 | offset = (char *)de - kaddr; | 295 | if (!dir_emit(ctx, de->name, de->name_len, |
298 | over = filldir(dirent, de->name, de->name_len, | ||
299 | (n<<PAGE_CACHE_SHIFT) | offset, | ||
300 | le64_to_cpu(de->inode_no), | 296 | le64_to_cpu(de->inode_no), |
301 | d_type); | 297 | t)) { |
302 | if (over) { | ||
303 | exofs_put_page(page); | 298 | exofs_put_page(page); |
304 | return 0; | 299 | return 0; |
305 | } | 300 | } |
306 | } | 301 | } |
307 | filp->f_pos += le16_to_cpu(de->rec_len); | 302 | ctx->pos += le16_to_cpu(de->rec_len); |
308 | } | 303 | } |
309 | exofs_put_page(page); | 304 | exofs_put_page(page); |
310 | } | 305 | } |
311 | |||
312 | return 0; | 306 | return 0; |
313 | } | 307 | } |
314 | 308 | ||
@@ -669,5 +663,5 @@ not_empty: | |||
669 | const struct file_operations exofs_dir_operations = { | 663 | const struct file_operations exofs_dir_operations = { |
670 | .llseek = generic_file_llseek, | 664 | .llseek = generic_file_llseek, |
671 | .read = generic_read_dir, | 665 | .read = generic_read_dir, |
672 | .readdir = exofs_readdir, | 666 | .iterate = exofs_readdir, |
673 | }; | 667 | }; |
diff --git a/fs/exportfs/expfs.c b/fs/exportfs/expfs.c index 262fc9940982..293bc2e47a73 100644 --- a/fs/exportfs/expfs.c +++ b/fs/exportfs/expfs.c | |||
@@ -212,6 +212,7 @@ reconnect_path(struct vfsmount *mnt, struct dentry *target_dir, char *nbuf) | |||
212 | } | 212 | } |
213 | 213 | ||
214 | struct getdents_callback { | 214 | struct getdents_callback { |
215 | struct dir_context ctx; | ||
215 | char *name; /* name that was found. It already points to a | 216 | char *name; /* name that was found. It already points to a |
216 | buffer NAME_MAX+1 is size */ | 217 | buffer NAME_MAX+1 is size */ |
217 | unsigned long ino; /* the inum we are looking for */ | 218 | unsigned long ino; /* the inum we are looking for */ |
@@ -254,7 +255,11 @@ static int get_name(const struct path *path, char *name, struct dentry *child) | |||
254 | struct inode *dir = path->dentry->d_inode; | 255 | struct inode *dir = path->dentry->d_inode; |
255 | int error; | 256 | int error; |
256 | struct file *file; | 257 | struct file *file; |
257 | struct getdents_callback buffer; | 258 | struct getdents_callback buffer = { |
259 | .ctx.actor = filldir_one, | ||
260 | .name = name, | ||
261 | .ino = child->d_inode->i_ino | ||
262 | }; | ||
258 | 263 | ||
259 | error = -ENOTDIR; | 264 | error = -ENOTDIR; |
260 | if (!dir || !S_ISDIR(dir->i_mode)) | 265 | if (!dir || !S_ISDIR(dir->i_mode)) |
@@ -271,17 +276,14 @@ static int get_name(const struct path *path, char *name, struct dentry *child) | |||
271 | goto out; | 276 | goto out; |
272 | 277 | ||
273 | error = -EINVAL; | 278 | error = -EINVAL; |
274 | if (!file->f_op->readdir) | 279 | if (!file->f_op->iterate) |
275 | goto out_close; | 280 | goto out_close; |
276 | 281 | ||
277 | buffer.name = name; | ||
278 | buffer.ino = child->d_inode->i_ino; | ||
279 | buffer.found = 0; | ||
280 | buffer.sequence = 0; | 282 | buffer.sequence = 0; |
281 | while (1) { | 283 | while (1) { |
282 | int old_seq = buffer.sequence; | 284 | int old_seq = buffer.sequence; |
283 | 285 | ||
284 | error = vfs_readdir(file, filldir_one, &buffer); | 286 | error = iterate_dir(file, &buffer.ctx); |
285 | if (buffer.found) { | 287 | if (buffer.found) { |
286 | error = 0; | 288 | error = 0; |
287 | break; | 289 | break; |
diff --git a/fs/ext2/dir.c b/fs/ext2/dir.c index 4237722bfd27..6e1d4ab09d72 100644 --- a/fs/ext2/dir.c +++ b/fs/ext2/dir.c | |||
@@ -287,17 +287,17 @@ static inline void ext2_set_de_type(ext2_dirent *de, struct inode *inode) | |||
287 | } | 287 | } |
288 | 288 | ||
289 | static int | 289 | static int |
290 | ext2_readdir (struct file * filp, void * dirent, filldir_t filldir) | 290 | ext2_readdir(struct file *file, struct dir_context *ctx) |
291 | { | 291 | { |
292 | loff_t pos = filp->f_pos; | 292 | loff_t pos = ctx->pos; |
293 | struct inode *inode = file_inode(filp); | 293 | struct inode *inode = file_inode(file); |
294 | struct super_block *sb = inode->i_sb; | 294 | struct super_block *sb = inode->i_sb; |
295 | unsigned int offset = pos & ~PAGE_CACHE_MASK; | 295 | unsigned int offset = pos & ~PAGE_CACHE_MASK; |
296 | unsigned long n = pos >> PAGE_CACHE_SHIFT; | 296 | unsigned long n = pos >> PAGE_CACHE_SHIFT; |
297 | unsigned long npages = dir_pages(inode); | 297 | unsigned long npages = dir_pages(inode); |
298 | unsigned chunk_mask = ~(ext2_chunk_size(inode)-1); | 298 | unsigned chunk_mask = ~(ext2_chunk_size(inode)-1); |
299 | unsigned char *types = NULL; | 299 | unsigned char *types = NULL; |
300 | int need_revalidate = filp->f_version != inode->i_version; | 300 | int need_revalidate = file->f_version != inode->i_version; |
301 | 301 | ||
302 | if (pos > inode->i_size - EXT2_DIR_REC_LEN(1)) | 302 | if (pos > inode->i_size - EXT2_DIR_REC_LEN(1)) |
303 | return 0; | 303 | return 0; |
@@ -314,16 +314,16 @@ ext2_readdir (struct file * filp, void * dirent, filldir_t filldir) | |||
314 | ext2_error(sb, __func__, | 314 | ext2_error(sb, __func__, |
315 | "bad page in #%lu", | 315 | "bad page in #%lu", |
316 | inode->i_ino); | 316 | inode->i_ino); |
317 | filp->f_pos += PAGE_CACHE_SIZE - offset; | 317 | ctx->pos += PAGE_CACHE_SIZE - offset; |
318 | return PTR_ERR(page); | 318 | return PTR_ERR(page); |
319 | } | 319 | } |
320 | kaddr = page_address(page); | 320 | kaddr = page_address(page); |
321 | if (unlikely(need_revalidate)) { | 321 | if (unlikely(need_revalidate)) { |
322 | if (offset) { | 322 | if (offset) { |
323 | offset = ext2_validate_entry(kaddr, offset, chunk_mask); | 323 | offset = ext2_validate_entry(kaddr, offset, chunk_mask); |
324 | filp->f_pos = (n<<PAGE_CACHE_SHIFT) + offset; | 324 | ctx->pos = (n<<PAGE_CACHE_SHIFT) + offset; |
325 | } | 325 | } |
326 | filp->f_version = inode->i_version; | 326 | file->f_version = inode->i_version; |
327 | need_revalidate = 0; | 327 | need_revalidate = 0; |
328 | } | 328 | } |
329 | de = (ext2_dirent *)(kaddr+offset); | 329 | de = (ext2_dirent *)(kaddr+offset); |
@@ -336,22 +336,19 @@ ext2_readdir (struct file * filp, void * dirent, filldir_t filldir) | |||
336 | return -EIO; | 336 | return -EIO; |
337 | } | 337 | } |
338 | if (de->inode) { | 338 | if (de->inode) { |
339 | int over; | ||
340 | unsigned char d_type = DT_UNKNOWN; | 339 | unsigned char d_type = DT_UNKNOWN; |
341 | 340 | ||
342 | if (types && de->file_type < EXT2_FT_MAX) | 341 | if (types && de->file_type < EXT2_FT_MAX) |
343 | d_type = types[de->file_type]; | 342 | d_type = types[de->file_type]; |
344 | 343 | ||
345 | offset = (char *)de - kaddr; | 344 | if (!dir_emit(ctx, de->name, de->name_len, |
346 | over = filldir(dirent, de->name, de->name_len, | 345 | le32_to_cpu(de->inode), |
347 | (n<<PAGE_CACHE_SHIFT) | offset, | 346 | d_type)) { |
348 | le32_to_cpu(de->inode), d_type); | ||
349 | if (over) { | ||
350 | ext2_put_page(page); | 347 | ext2_put_page(page); |
351 | return 0; | 348 | return 0; |
352 | } | 349 | } |
353 | } | 350 | } |
354 | filp->f_pos += ext2_rec_len_from_disk(de->rec_len); | 351 | ctx->pos += ext2_rec_len_from_disk(de->rec_len); |
355 | } | 352 | } |
356 | ext2_put_page(page); | 353 | ext2_put_page(page); |
357 | } | 354 | } |
@@ -724,7 +721,7 @@ not_empty: | |||
724 | const struct file_operations ext2_dir_operations = { | 721 | const struct file_operations ext2_dir_operations = { |
725 | .llseek = generic_file_llseek, | 722 | .llseek = generic_file_llseek, |
726 | .read = generic_read_dir, | 723 | .read = generic_read_dir, |
727 | .readdir = ext2_readdir, | 724 | .iterate = ext2_readdir, |
728 | .unlocked_ioctl = ext2_ioctl, | 725 | .unlocked_ioctl = ext2_ioctl, |
729 | #ifdef CONFIG_COMPAT | 726 | #ifdef CONFIG_COMPAT |
730 | .compat_ioctl = ext2_compat_ioctl, | 727 | .compat_ioctl = ext2_compat_ioctl, |
diff --git a/fs/ext3/dir.c b/fs/ext3/dir.c index 87eccbbca255..f522425aaa24 100644 --- a/fs/ext3/dir.c +++ b/fs/ext3/dir.c | |||
@@ -28,8 +28,7 @@ static unsigned char ext3_filetype_table[] = { | |||
28 | DT_UNKNOWN, DT_REG, DT_DIR, DT_CHR, DT_BLK, DT_FIFO, DT_SOCK, DT_LNK | 28 | DT_UNKNOWN, DT_REG, DT_DIR, DT_CHR, DT_BLK, DT_FIFO, DT_SOCK, DT_LNK |
29 | }; | 29 | }; |
30 | 30 | ||
31 | static int ext3_dx_readdir(struct file * filp, | 31 | static int ext3_dx_readdir(struct file *, struct dir_context *); |
32 | void * dirent, filldir_t filldir); | ||
33 | 32 | ||
34 | static unsigned char get_dtype(struct super_block *sb, int filetype) | 33 | static unsigned char get_dtype(struct super_block *sb, int filetype) |
35 | { | 34 | { |
@@ -91,36 +90,30 @@ int ext3_check_dir_entry (const char * function, struct inode * dir, | |||
91 | return error_msg == NULL ? 1 : 0; | 90 | return error_msg == NULL ? 1 : 0; |
92 | } | 91 | } |
93 | 92 | ||
94 | static int ext3_readdir(struct file * filp, | 93 | static int ext3_readdir(struct file *file, struct dir_context *ctx) |
95 | void * dirent, filldir_t filldir) | ||
96 | { | 94 | { |
97 | int error = 0; | ||
98 | unsigned long offset; | 95 | unsigned long offset; |
99 | int i, stored; | 96 | int i; |
100 | struct ext3_dir_entry_2 *de; | 97 | struct ext3_dir_entry_2 *de; |
101 | int err; | 98 | int err; |
102 | struct inode *inode = file_inode(filp); | 99 | struct inode *inode = file_inode(file); |
103 | struct super_block *sb = inode->i_sb; | 100 | struct super_block *sb = inode->i_sb; |
104 | int ret = 0; | ||
105 | int dir_has_error = 0; | 101 | int dir_has_error = 0; |
106 | 102 | ||
107 | if (is_dx_dir(inode)) { | 103 | if (is_dx_dir(inode)) { |
108 | err = ext3_dx_readdir(filp, dirent, filldir); | 104 | err = ext3_dx_readdir(file, ctx); |
109 | if (err != ERR_BAD_DX_DIR) { | 105 | if (err != ERR_BAD_DX_DIR) |
110 | ret = err; | 106 | return err; |
111 | goto out; | ||
112 | } | ||
113 | /* | 107 | /* |
114 | * We don't set the inode dirty flag since it's not | 108 | * We don't set the inode dirty flag since it's not |
115 | * critical that it get flushed back to the disk. | 109 | * critical that it get flushed back to the disk. |
116 | */ | 110 | */ |
117 | EXT3_I(file_inode(filp))->i_flags &= ~EXT3_INDEX_FL; | 111 | EXT3_I(inode)->i_flags &= ~EXT3_INDEX_FL; |
118 | } | 112 | } |
119 | stored = 0; | 113 | offset = ctx->pos & (sb->s_blocksize - 1); |
120 | offset = filp->f_pos & (sb->s_blocksize - 1); | ||
121 | 114 | ||
122 | while (!error && !stored && filp->f_pos < inode->i_size) { | 115 | while (ctx->pos < inode->i_size) { |
123 | unsigned long blk = filp->f_pos >> EXT3_BLOCK_SIZE_BITS(sb); | 116 | unsigned long blk = ctx->pos >> EXT3_BLOCK_SIZE_BITS(sb); |
124 | struct buffer_head map_bh; | 117 | struct buffer_head map_bh; |
125 | struct buffer_head *bh = NULL; | 118 | struct buffer_head *bh = NULL; |
126 | 119 | ||
@@ -129,12 +122,12 @@ static int ext3_readdir(struct file * filp, | |||
129 | if (err > 0) { | 122 | if (err > 0) { |
130 | pgoff_t index = map_bh.b_blocknr >> | 123 | pgoff_t index = map_bh.b_blocknr >> |
131 | (PAGE_CACHE_SHIFT - inode->i_blkbits); | 124 | (PAGE_CACHE_SHIFT - inode->i_blkbits); |
132 | if (!ra_has_index(&filp->f_ra, index)) | 125 | if (!ra_has_index(&file->f_ra, index)) |
133 | page_cache_sync_readahead( | 126 | page_cache_sync_readahead( |
134 | sb->s_bdev->bd_inode->i_mapping, | 127 | sb->s_bdev->bd_inode->i_mapping, |
135 | &filp->f_ra, filp, | 128 | &file->f_ra, file, |
136 | index, 1); | 129 | index, 1); |
137 | filp->f_ra.prev_pos = (loff_t)index << PAGE_CACHE_SHIFT; | 130 | file->f_ra.prev_pos = (loff_t)index << PAGE_CACHE_SHIFT; |
138 | bh = ext3_bread(NULL, inode, blk, 0, &err); | 131 | bh = ext3_bread(NULL, inode, blk, 0, &err); |
139 | } | 132 | } |
140 | 133 | ||
@@ -146,22 +139,21 @@ static int ext3_readdir(struct file * filp, | |||
146 | if (!dir_has_error) { | 139 | if (!dir_has_error) { |
147 | ext3_error(sb, __func__, "directory #%lu " | 140 | ext3_error(sb, __func__, "directory #%lu " |
148 | "contains a hole at offset %lld", | 141 | "contains a hole at offset %lld", |
149 | inode->i_ino, filp->f_pos); | 142 | inode->i_ino, ctx->pos); |
150 | dir_has_error = 1; | 143 | dir_has_error = 1; |
151 | } | 144 | } |
152 | /* corrupt size? Maybe no more blocks to read */ | 145 | /* corrupt size? Maybe no more blocks to read */ |
153 | if (filp->f_pos > inode->i_blocks << 9) | 146 | if (ctx->pos > inode->i_blocks << 9) |
154 | break; | 147 | break; |
155 | filp->f_pos += sb->s_blocksize - offset; | 148 | ctx->pos += sb->s_blocksize - offset; |
156 | continue; | 149 | continue; |
157 | } | 150 | } |
158 | 151 | ||
159 | revalidate: | ||
160 | /* If the dir block has changed since the last call to | 152 | /* If the dir block has changed since the last call to |
161 | * readdir(2), then we might be pointing to an invalid | 153 | * readdir(2), then we might be pointing to an invalid |
162 | * dirent right now. Scan from the start of the block | 154 | * dirent right now. Scan from the start of the block |
163 | * to make sure. */ | 155 | * to make sure. */ |
164 | if (filp->f_version != inode->i_version) { | 156 | if (offset && file->f_version != inode->i_version) { |
165 | for (i = 0; i < sb->s_blocksize && i < offset; ) { | 157 | for (i = 0; i < sb->s_blocksize && i < offset; ) { |
166 | de = (struct ext3_dir_entry_2 *) | 158 | de = (struct ext3_dir_entry_2 *) |
167 | (bh->b_data + i); | 159 | (bh->b_data + i); |
@@ -177,53 +169,40 @@ revalidate: | |||
177 | i += ext3_rec_len_from_disk(de->rec_len); | 169 | i += ext3_rec_len_from_disk(de->rec_len); |
178 | } | 170 | } |
179 | offset = i; | 171 | offset = i; |
180 | filp->f_pos = (filp->f_pos & ~(sb->s_blocksize - 1)) | 172 | ctx->pos = (ctx->pos & ~(sb->s_blocksize - 1)) |
181 | | offset; | 173 | | offset; |
182 | filp->f_version = inode->i_version; | 174 | file->f_version = inode->i_version; |
183 | } | 175 | } |
184 | 176 | ||
185 | while (!error && filp->f_pos < inode->i_size | 177 | while (ctx->pos < inode->i_size |
186 | && offset < sb->s_blocksize) { | 178 | && offset < sb->s_blocksize) { |
187 | de = (struct ext3_dir_entry_2 *) (bh->b_data + offset); | 179 | de = (struct ext3_dir_entry_2 *) (bh->b_data + offset); |
188 | if (!ext3_check_dir_entry ("ext3_readdir", inode, de, | 180 | if (!ext3_check_dir_entry ("ext3_readdir", inode, de, |
189 | bh, offset)) { | 181 | bh, offset)) { |
190 | /* On error, skip the f_pos to the | 182 | /* On error, skip the to the |
191 | next block. */ | 183 | next block. */ |
192 | filp->f_pos = (filp->f_pos | | 184 | ctx->pos = (ctx->pos | |
193 | (sb->s_blocksize - 1)) + 1; | 185 | (sb->s_blocksize - 1)) + 1; |
194 | brelse (bh); | 186 | break; |
195 | ret = stored; | ||
196 | goto out; | ||
197 | } | 187 | } |
198 | offset += ext3_rec_len_from_disk(de->rec_len); | 188 | offset += ext3_rec_len_from_disk(de->rec_len); |
199 | if (le32_to_cpu(de->inode)) { | 189 | if (le32_to_cpu(de->inode)) { |
200 | /* We might block in the next section | 190 | if (!dir_emit(ctx, de->name, de->name_len, |
201 | * if the data destination is | 191 | le32_to_cpu(de->inode), |
202 | * currently swapped out. So, use a | 192 | get_dtype(sb, de->file_type))) { |
203 | * version stamp to detect whether or | 193 | brelse(bh); |
204 | * not the directory has been modified | 194 | return 0; |
205 | * during the copy operation. | 195 | } |
206 | */ | ||
207 | u64 version = filp->f_version; | ||
208 | |||
209 | error = filldir(dirent, de->name, | ||
210 | de->name_len, | ||
211 | filp->f_pos, | ||
212 | le32_to_cpu(de->inode), | ||
213 | get_dtype(sb, de->file_type)); | ||
214 | if (error) | ||
215 | break; | ||
216 | if (version != filp->f_version) | ||
217 | goto revalidate; | ||
218 | stored ++; | ||
219 | } | 196 | } |
220 | filp->f_pos += ext3_rec_len_from_disk(de->rec_len); | 197 | ctx->pos += ext3_rec_len_from_disk(de->rec_len); |
221 | } | 198 | } |
222 | offset = 0; | 199 | offset = 0; |
223 | brelse (bh); | 200 | brelse (bh); |
201 | if (ctx->pos < inode->i_size) | ||
202 | if (!dir_relax(inode)) | ||
203 | return 0; | ||
224 | } | 204 | } |
225 | out: | 205 | return 0; |
226 | return ret; | ||
227 | } | 206 | } |
228 | 207 | ||
229 | static inline int is_32bit_api(void) | 208 | static inline int is_32bit_api(void) |
@@ -452,62 +431,54 @@ int ext3_htree_store_dirent(struct file *dir_file, __u32 hash, | |||
452 | * for all entres on the fname linked list. (Normally there is only | 431 | * for all entres on the fname linked list. (Normally there is only |
453 | * one entry on the linked list, unless there are 62 bit hash collisions.) | 432 | * one entry on the linked list, unless there are 62 bit hash collisions.) |
454 | */ | 433 | */ |
455 | static int call_filldir(struct file * filp, void * dirent, | 434 | static bool call_filldir(struct file *file, struct dir_context *ctx, |
456 | filldir_t filldir, struct fname *fname) | 435 | struct fname *fname) |
457 | { | 436 | { |
458 | struct dir_private_info *info = filp->private_data; | 437 | struct dir_private_info *info = file->private_data; |
459 | loff_t curr_pos; | 438 | struct inode *inode = file_inode(file); |
460 | struct inode *inode = file_inode(filp); | 439 | struct super_block *sb = inode->i_sb; |
461 | struct super_block * sb; | ||
462 | int error; | ||
463 | |||
464 | sb = inode->i_sb; | ||
465 | 440 | ||
466 | if (!fname) { | 441 | if (!fname) { |
467 | printk("call_filldir: called with null fname?!?\n"); | 442 | printk("call_filldir: called with null fname?!?\n"); |
468 | return 0; | 443 | return true; |
469 | } | 444 | } |
470 | curr_pos = hash2pos(filp, fname->hash, fname->minor_hash); | 445 | ctx->pos = hash2pos(file, fname->hash, fname->minor_hash); |
471 | while (fname) { | 446 | while (fname) { |
472 | error = filldir(dirent, fname->name, | 447 | if (!dir_emit(ctx, fname->name, fname->name_len, |
473 | fname->name_len, curr_pos, | ||
474 | fname->inode, | 448 | fname->inode, |
475 | get_dtype(sb, fname->file_type)); | 449 | get_dtype(sb, fname->file_type))) { |
476 | if (error) { | ||
477 | filp->f_pos = curr_pos; | ||
478 | info->extra_fname = fname; | 450 | info->extra_fname = fname; |
479 | return error; | 451 | return false; |
480 | } | 452 | } |
481 | fname = fname->next; | 453 | fname = fname->next; |
482 | } | 454 | } |
483 | return 0; | 455 | return true; |
484 | } | 456 | } |
485 | 457 | ||
486 | static int ext3_dx_readdir(struct file * filp, | 458 | static int ext3_dx_readdir(struct file *file, struct dir_context *ctx) |
487 | void * dirent, filldir_t filldir) | ||
488 | { | 459 | { |
489 | struct dir_private_info *info = filp->private_data; | 460 | struct dir_private_info *info = file->private_data; |
490 | struct inode *inode = file_inode(filp); | 461 | struct inode *inode = file_inode(file); |
491 | struct fname *fname; | 462 | struct fname *fname; |
492 | int ret; | 463 | int ret; |
493 | 464 | ||
494 | if (!info) { | 465 | if (!info) { |
495 | info = ext3_htree_create_dir_info(filp, filp->f_pos); | 466 | info = ext3_htree_create_dir_info(file, ctx->pos); |
496 | if (!info) | 467 | if (!info) |
497 | return -ENOMEM; | 468 | return -ENOMEM; |
498 | filp->private_data = info; | 469 | file->private_data = info; |
499 | } | 470 | } |
500 | 471 | ||
501 | if (filp->f_pos == ext3_get_htree_eof(filp)) | 472 | if (ctx->pos == ext3_get_htree_eof(file)) |
502 | return 0; /* EOF */ | 473 | return 0; /* EOF */ |
503 | 474 | ||
504 | /* Some one has messed with f_pos; reset the world */ | 475 | /* Some one has messed with f_pos; reset the world */ |
505 | if (info->last_pos != filp->f_pos) { | 476 | if (info->last_pos != ctx->pos) { |
506 | free_rb_tree_fname(&info->root); | 477 | free_rb_tree_fname(&info->root); |
507 | info->curr_node = NULL; | 478 | info->curr_node = NULL; |
508 | info->extra_fname = NULL; | 479 | info->extra_fname = NULL; |
509 | info->curr_hash = pos2maj_hash(filp, filp->f_pos); | 480 | info->curr_hash = pos2maj_hash(file, ctx->pos); |
510 | info->curr_minor_hash = pos2min_hash(filp, filp->f_pos); | 481 | info->curr_minor_hash = pos2min_hash(file, ctx->pos); |
511 | } | 482 | } |
512 | 483 | ||
513 | /* | 484 | /* |
@@ -515,7 +486,7 @@ static int ext3_dx_readdir(struct file * filp, | |||
515 | * chain, return them first. | 486 | * chain, return them first. |
516 | */ | 487 | */ |
517 | if (info->extra_fname) { | 488 | if (info->extra_fname) { |
518 | if (call_filldir(filp, dirent, filldir, info->extra_fname)) | 489 | if (!call_filldir(file, ctx, info->extra_fname)) |
519 | goto finished; | 490 | goto finished; |
520 | info->extra_fname = NULL; | 491 | info->extra_fname = NULL; |
521 | goto next_node; | 492 | goto next_node; |
@@ -529,17 +500,17 @@ static int ext3_dx_readdir(struct file * filp, | |||
529 | * cached entries. | 500 | * cached entries. |
530 | */ | 501 | */ |
531 | if ((!info->curr_node) || | 502 | if ((!info->curr_node) || |
532 | (filp->f_version != inode->i_version)) { | 503 | (file->f_version != inode->i_version)) { |
533 | info->curr_node = NULL; | 504 | info->curr_node = NULL; |
534 | free_rb_tree_fname(&info->root); | 505 | free_rb_tree_fname(&info->root); |
535 | filp->f_version = inode->i_version; | 506 | file->f_version = inode->i_version; |
536 | ret = ext3_htree_fill_tree(filp, info->curr_hash, | 507 | ret = ext3_htree_fill_tree(file, info->curr_hash, |
537 | info->curr_minor_hash, | 508 | info->curr_minor_hash, |
538 | &info->next_hash); | 509 | &info->next_hash); |
539 | if (ret < 0) | 510 | if (ret < 0) |
540 | return ret; | 511 | return ret; |
541 | if (ret == 0) { | 512 | if (ret == 0) { |
542 | filp->f_pos = ext3_get_htree_eof(filp); | 513 | ctx->pos = ext3_get_htree_eof(file); |
543 | break; | 514 | break; |
544 | } | 515 | } |
545 | info->curr_node = rb_first(&info->root); | 516 | info->curr_node = rb_first(&info->root); |
@@ -548,7 +519,7 @@ static int ext3_dx_readdir(struct file * filp, | |||
548 | fname = rb_entry(info->curr_node, struct fname, rb_hash); | 519 | fname = rb_entry(info->curr_node, struct fname, rb_hash); |
549 | info->curr_hash = fname->hash; | 520 | info->curr_hash = fname->hash; |
550 | info->curr_minor_hash = fname->minor_hash; | 521 | info->curr_minor_hash = fname->minor_hash; |
551 | if (call_filldir(filp, dirent, filldir, fname)) | 522 | if (!call_filldir(file, ctx, fname)) |
552 | break; | 523 | break; |
553 | next_node: | 524 | next_node: |
554 | info->curr_node = rb_next(info->curr_node); | 525 | info->curr_node = rb_next(info->curr_node); |
@@ -559,7 +530,7 @@ static int ext3_dx_readdir(struct file * filp, | |||
559 | info->curr_minor_hash = fname->minor_hash; | 530 | info->curr_minor_hash = fname->minor_hash; |
560 | } else { | 531 | } else { |
561 | if (info->next_hash == ~0) { | 532 | if (info->next_hash == ~0) { |
562 | filp->f_pos = ext3_get_htree_eof(filp); | 533 | ctx->pos = ext3_get_htree_eof(file); |
563 | break; | 534 | break; |
564 | } | 535 | } |
565 | info->curr_hash = info->next_hash; | 536 | info->curr_hash = info->next_hash; |
@@ -567,7 +538,7 @@ static int ext3_dx_readdir(struct file * filp, | |||
567 | } | 538 | } |
568 | } | 539 | } |
569 | finished: | 540 | finished: |
570 | info->last_pos = filp->f_pos; | 541 | info->last_pos = ctx->pos; |
571 | return 0; | 542 | return 0; |
572 | } | 543 | } |
573 | 544 | ||
@@ -582,7 +553,7 @@ static int ext3_release_dir (struct inode * inode, struct file * filp) | |||
582 | const struct file_operations ext3_dir_operations = { | 553 | const struct file_operations ext3_dir_operations = { |
583 | .llseek = ext3_dir_llseek, | 554 | .llseek = ext3_dir_llseek, |
584 | .read = generic_read_dir, | 555 | .read = generic_read_dir, |
585 | .readdir = ext3_readdir, | 556 | .iterate = ext3_readdir, |
586 | .unlocked_ioctl = ext3_ioctl, | 557 | .unlocked_ioctl = ext3_ioctl, |
587 | #ifdef CONFIG_COMPAT | 558 | #ifdef CONFIG_COMPAT |
588 | .compat_ioctl = ext3_compat_ioctl, | 559 | .compat_ioctl = ext3_compat_ioctl, |
diff --git a/fs/ext4/dir.c b/fs/ext4/dir.c index f8d56e4254e0..3c7d288ae94c 100644 --- a/fs/ext4/dir.c +++ b/fs/ext4/dir.c | |||
@@ -29,8 +29,7 @@ | |||
29 | #include "ext4.h" | 29 | #include "ext4.h" |
30 | #include "xattr.h" | 30 | #include "xattr.h" |
31 | 31 | ||
32 | static int ext4_dx_readdir(struct file *filp, | 32 | static int ext4_dx_readdir(struct file *, struct dir_context *); |
33 | void *dirent, filldir_t filldir); | ||
34 | 33 | ||
35 | /** | 34 | /** |
36 | * Check if the given dir-inode refers to an htree-indexed directory | 35 | * Check if the given dir-inode refers to an htree-indexed directory |
@@ -103,60 +102,56 @@ int __ext4_check_dir_entry(const char *function, unsigned int line, | |||
103 | return 1; | 102 | return 1; |
104 | } | 103 | } |
105 | 104 | ||
106 | static int ext4_readdir(struct file *filp, | 105 | static int ext4_readdir(struct file *file, struct dir_context *ctx) |
107 | void *dirent, filldir_t filldir) | ||
108 | { | 106 | { |
109 | int error = 0; | ||
110 | unsigned int offset; | 107 | unsigned int offset; |
111 | int i, stored; | 108 | int i, stored; |
112 | struct ext4_dir_entry_2 *de; | 109 | struct ext4_dir_entry_2 *de; |
113 | int err; | 110 | int err; |
114 | struct inode *inode = file_inode(filp); | 111 | struct inode *inode = file_inode(file); |
115 | struct super_block *sb = inode->i_sb; | 112 | struct super_block *sb = inode->i_sb; |
116 | int ret = 0; | ||
117 | int dir_has_error = 0; | 113 | int dir_has_error = 0; |
118 | 114 | ||
119 | if (is_dx_dir(inode)) { | 115 | if (is_dx_dir(inode)) { |
120 | err = ext4_dx_readdir(filp, dirent, filldir); | 116 | err = ext4_dx_readdir(file, ctx); |
121 | if (err != ERR_BAD_DX_DIR) { | 117 | if (err != ERR_BAD_DX_DIR) { |
122 | ret = err; | 118 | return err; |
123 | goto out; | ||
124 | } | 119 | } |
125 | /* | 120 | /* |
126 | * We don't set the inode dirty flag since it's not | 121 | * We don't set the inode dirty flag since it's not |
127 | * critical that it get flushed back to the disk. | 122 | * critical that it get flushed back to the disk. |
128 | */ | 123 | */ |
129 | ext4_clear_inode_flag(file_inode(filp), | 124 | ext4_clear_inode_flag(file_inode(file), |
130 | EXT4_INODE_INDEX); | 125 | EXT4_INODE_INDEX); |
131 | } | 126 | } |
132 | 127 | ||
133 | if (ext4_has_inline_data(inode)) { | 128 | if (ext4_has_inline_data(inode)) { |
134 | int has_inline_data = 1; | 129 | int has_inline_data = 1; |
135 | ret = ext4_read_inline_dir(filp, dirent, filldir, | 130 | int ret = ext4_read_inline_dir(file, ctx, |
136 | &has_inline_data); | 131 | &has_inline_data); |
137 | if (has_inline_data) | 132 | if (has_inline_data) |
138 | return ret; | 133 | return ret; |
139 | } | 134 | } |
140 | 135 | ||
141 | stored = 0; | 136 | stored = 0; |
142 | offset = filp->f_pos & (sb->s_blocksize - 1); | 137 | offset = ctx->pos & (sb->s_blocksize - 1); |
143 | 138 | ||
144 | while (!error && !stored && filp->f_pos < inode->i_size) { | 139 | while (ctx->pos < inode->i_size) { |
145 | struct ext4_map_blocks map; | 140 | struct ext4_map_blocks map; |
146 | struct buffer_head *bh = NULL; | 141 | struct buffer_head *bh = NULL; |
147 | 142 | ||
148 | map.m_lblk = filp->f_pos >> EXT4_BLOCK_SIZE_BITS(sb); | 143 | map.m_lblk = ctx->pos >> EXT4_BLOCK_SIZE_BITS(sb); |
149 | map.m_len = 1; | 144 | map.m_len = 1; |
150 | err = ext4_map_blocks(NULL, inode, &map, 0); | 145 | err = ext4_map_blocks(NULL, inode, &map, 0); |
151 | if (err > 0) { | 146 | if (err > 0) { |
152 | pgoff_t index = map.m_pblk >> | 147 | pgoff_t index = map.m_pblk >> |
153 | (PAGE_CACHE_SHIFT - inode->i_blkbits); | 148 | (PAGE_CACHE_SHIFT - inode->i_blkbits); |
154 | if (!ra_has_index(&filp->f_ra, index)) | 149 | if (!ra_has_index(&file->f_ra, index)) |
155 | page_cache_sync_readahead( | 150 | page_cache_sync_readahead( |
156 | sb->s_bdev->bd_inode->i_mapping, | 151 | sb->s_bdev->bd_inode->i_mapping, |
157 | &filp->f_ra, filp, | 152 | &file->f_ra, file, |
158 | index, 1); | 153 | index, 1); |
159 | filp->f_ra.prev_pos = (loff_t)index << PAGE_CACHE_SHIFT; | 154 | file->f_ra.prev_pos = (loff_t)index << PAGE_CACHE_SHIFT; |
160 | bh = ext4_bread(NULL, inode, map.m_lblk, 0, &err); | 155 | bh = ext4_bread(NULL, inode, map.m_lblk, 0, &err); |
161 | } | 156 | } |
162 | 157 | ||
@@ -166,16 +161,16 @@ static int ext4_readdir(struct file *filp, | |||
166 | */ | 161 | */ |
167 | if (!bh) { | 162 | if (!bh) { |
168 | if (!dir_has_error) { | 163 | if (!dir_has_error) { |
169 | EXT4_ERROR_FILE(filp, 0, | 164 | EXT4_ERROR_FILE(file, 0, |
170 | "directory contains a " | 165 | "directory contains a " |
171 | "hole at offset %llu", | 166 | "hole at offset %llu", |
172 | (unsigned long long) filp->f_pos); | 167 | (unsigned long long) ctx->pos); |
173 | dir_has_error = 1; | 168 | dir_has_error = 1; |
174 | } | 169 | } |
175 | /* corrupt size? Maybe no more blocks to read */ | 170 | /* corrupt size? Maybe no more blocks to read */ |
176 | if (filp->f_pos > inode->i_blocks << 9) | 171 | if (ctx->pos > inode->i_blocks << 9) |
177 | break; | 172 | break; |
178 | filp->f_pos += sb->s_blocksize - offset; | 173 | ctx->pos += sb->s_blocksize - offset; |
179 | continue; | 174 | continue; |
180 | } | 175 | } |
181 | 176 | ||
@@ -183,21 +178,20 @@ static int ext4_readdir(struct file *filp, | |||
183 | if (!buffer_verified(bh) && | 178 | if (!buffer_verified(bh) && |
184 | !ext4_dirent_csum_verify(inode, | 179 | !ext4_dirent_csum_verify(inode, |
185 | (struct ext4_dir_entry *)bh->b_data)) { | 180 | (struct ext4_dir_entry *)bh->b_data)) { |
186 | EXT4_ERROR_FILE(filp, 0, "directory fails checksum " | 181 | EXT4_ERROR_FILE(file, 0, "directory fails checksum " |
187 | "at offset %llu", | 182 | "at offset %llu", |
188 | (unsigned long long)filp->f_pos); | 183 | (unsigned long long)ctx->pos); |
189 | filp->f_pos += sb->s_blocksize - offset; | 184 | ctx->pos += sb->s_blocksize - offset; |
190 | brelse(bh); | 185 | brelse(bh); |
191 | continue; | 186 | continue; |
192 | } | 187 | } |
193 | set_buffer_verified(bh); | 188 | set_buffer_verified(bh); |
194 | 189 | ||
195 | revalidate: | ||
196 | /* If the dir block has changed since the last call to | 190 | /* If the dir block has changed since the last call to |
197 | * readdir(2), then we might be pointing to an invalid | 191 | * readdir(2), then we might be pointing to an invalid |
198 | * dirent right now. Scan from the start of the block | 192 | * dirent right now. Scan from the start of the block |
199 | * to make sure. */ | 193 | * to make sure. */ |
200 | if (filp->f_version != inode->i_version) { | 194 | if (file->f_version != inode->i_version) { |
201 | for (i = 0; i < sb->s_blocksize && i < offset; ) { | 195 | for (i = 0; i < sb->s_blocksize && i < offset; ) { |
202 | de = (struct ext4_dir_entry_2 *) | 196 | de = (struct ext4_dir_entry_2 *) |
203 | (bh->b_data + i); | 197 | (bh->b_data + i); |
@@ -214,57 +208,46 @@ revalidate: | |||
214 | sb->s_blocksize); | 208 | sb->s_blocksize); |
215 | } | 209 | } |
216 | offset = i; | 210 | offset = i; |
217 | filp->f_pos = (filp->f_pos & ~(sb->s_blocksize - 1)) | 211 | ctx->pos = (ctx->pos & ~(sb->s_blocksize - 1)) |
218 | | offset; | 212 | | offset; |
219 | filp->f_version = inode->i_version; | 213 | file->f_version = inode->i_version; |
220 | } | 214 | } |
221 | 215 | ||
222 | while (!error && filp->f_pos < inode->i_size | 216 | while (ctx->pos < inode->i_size |
223 | && offset < sb->s_blocksize) { | 217 | && offset < sb->s_blocksize) { |
224 | de = (struct ext4_dir_entry_2 *) (bh->b_data + offset); | 218 | de = (struct ext4_dir_entry_2 *) (bh->b_data + offset); |
225 | if (ext4_check_dir_entry(inode, filp, de, bh, | 219 | if (ext4_check_dir_entry(inode, file, de, bh, |
226 | bh->b_data, bh->b_size, | 220 | bh->b_data, bh->b_size, |
227 | offset)) { | 221 | offset)) { |
228 | /* | 222 | /* |
229 | * On error, skip the f_pos to the next block | 223 | * On error, skip to the next block |
230 | */ | 224 | */ |
231 | filp->f_pos = (filp->f_pos | | 225 | ctx->pos = (ctx->pos | |
232 | (sb->s_blocksize - 1)) + 1; | 226 | (sb->s_blocksize - 1)) + 1; |
233 | brelse(bh); | 227 | break; |
234 | ret = stored; | ||
235 | goto out; | ||
236 | } | 228 | } |
237 | offset += ext4_rec_len_from_disk(de->rec_len, | 229 | offset += ext4_rec_len_from_disk(de->rec_len, |
238 | sb->s_blocksize); | 230 | sb->s_blocksize); |
239 | if (le32_to_cpu(de->inode)) { | 231 | if (le32_to_cpu(de->inode)) { |
240 | /* We might block in the next section | 232 | if (!dir_emit(ctx, de->name, |
241 | * if the data destination is | ||
242 | * currently swapped out. So, use a | ||
243 | * version stamp to detect whether or | ||
244 | * not the directory has been modified | ||
245 | * during the copy operation. | ||
246 | */ | ||
247 | u64 version = filp->f_version; | ||
248 | |||
249 | error = filldir(dirent, de->name, | ||
250 | de->name_len, | 233 | de->name_len, |
251 | filp->f_pos, | ||
252 | le32_to_cpu(de->inode), | 234 | le32_to_cpu(de->inode), |
253 | get_dtype(sb, de->file_type)); | 235 | get_dtype(sb, de->file_type))) { |
254 | if (error) | 236 | brelse(bh); |
255 | break; | 237 | return 0; |
256 | if (version != filp->f_version) | 238 | } |
257 | goto revalidate; | ||
258 | stored++; | ||
259 | } | 239 | } |
260 | filp->f_pos += ext4_rec_len_from_disk(de->rec_len, | 240 | ctx->pos += ext4_rec_len_from_disk(de->rec_len, |
261 | sb->s_blocksize); | 241 | sb->s_blocksize); |
262 | } | 242 | } |
263 | offset = 0; | 243 | offset = 0; |
264 | brelse(bh); | 244 | brelse(bh); |
245 | if (ctx->pos < inode->i_size) { | ||
246 | if (!dir_relax(inode)) | ||
247 | return 0; | ||
248 | } | ||
265 | } | 249 | } |
266 | out: | 250 | return 0; |
267 | return ret; | ||
268 | } | 251 | } |
269 | 252 | ||
270 | static inline int is_32bit_api(void) | 253 | static inline int is_32bit_api(void) |
@@ -492,16 +475,12 @@ int ext4_htree_store_dirent(struct file *dir_file, __u32 hash, | |||
492 | * for all entres on the fname linked list. (Normally there is only | 475 | * for all entres on the fname linked list. (Normally there is only |
493 | * one entry on the linked list, unless there are 62 bit hash collisions.) | 476 | * one entry on the linked list, unless there are 62 bit hash collisions.) |
494 | */ | 477 | */ |
495 | static int call_filldir(struct file *filp, void *dirent, | 478 | static int call_filldir(struct file *file, struct dir_context *ctx, |
496 | filldir_t filldir, struct fname *fname) | 479 | struct fname *fname) |
497 | { | 480 | { |
498 | struct dir_private_info *info = filp->private_data; | 481 | struct dir_private_info *info = file->private_data; |
499 | loff_t curr_pos; | 482 | struct inode *inode = file_inode(file); |
500 | struct inode *inode = file_inode(filp); | 483 | struct super_block *sb = inode->i_sb; |
501 | struct super_block *sb; | ||
502 | int error; | ||
503 | |||
504 | sb = inode->i_sb; | ||
505 | 484 | ||
506 | if (!fname) { | 485 | if (!fname) { |
507 | ext4_msg(sb, KERN_ERR, "%s:%d: inode #%lu: comm %s: " | 486 | ext4_msg(sb, KERN_ERR, "%s:%d: inode #%lu: comm %s: " |
@@ -509,47 +488,44 @@ static int call_filldir(struct file *filp, void *dirent, | |||
509 | inode->i_ino, current->comm); | 488 | inode->i_ino, current->comm); |
510 | return 0; | 489 | return 0; |
511 | } | 490 | } |
512 | curr_pos = hash2pos(filp, fname->hash, fname->minor_hash); | 491 | ctx->pos = hash2pos(file, fname->hash, fname->minor_hash); |
513 | while (fname) { | 492 | while (fname) { |
514 | error = filldir(dirent, fname->name, | 493 | if (!dir_emit(ctx, fname->name, |
515 | fname->name_len, curr_pos, | 494 | fname->name_len, |
516 | fname->inode, | 495 | fname->inode, |
517 | get_dtype(sb, fname->file_type)); | 496 | get_dtype(sb, fname->file_type))) { |
518 | if (error) { | ||
519 | filp->f_pos = curr_pos; | ||
520 | info->extra_fname = fname; | 497 | info->extra_fname = fname; |
521 | return error; | 498 | return 1; |
522 | } | 499 | } |
523 | fname = fname->next; | 500 | fname = fname->next; |
524 | } | 501 | } |
525 | return 0; | 502 | return 0; |
526 | } | 503 | } |
527 | 504 | ||
528 | static int ext4_dx_readdir(struct file *filp, | 505 | static int ext4_dx_readdir(struct file *file, struct dir_context *ctx) |
529 | void *dirent, filldir_t filldir) | ||
530 | { | 506 | { |
531 | struct dir_private_info *info = filp->private_data; | 507 | struct dir_private_info *info = file->private_data; |
532 | struct inode *inode = file_inode(filp); | 508 | struct inode *inode = file_inode(file); |
533 | struct fname *fname; | 509 | struct fname *fname; |
534 | int ret; | 510 | int ret; |
535 | 511 | ||
536 | if (!info) { | 512 | if (!info) { |
537 | info = ext4_htree_create_dir_info(filp, filp->f_pos); | 513 | info = ext4_htree_create_dir_info(file, ctx->pos); |
538 | if (!info) | 514 | if (!info) |
539 | return -ENOMEM; | 515 | return -ENOMEM; |
540 | filp->private_data = info; | 516 | file->private_data = info; |
541 | } | 517 | } |
542 | 518 | ||
543 | if (filp->f_pos == ext4_get_htree_eof(filp)) | 519 | if (ctx->pos == ext4_get_htree_eof(file)) |
544 | return 0; /* EOF */ | 520 | return 0; /* EOF */ |
545 | 521 | ||
546 | /* Some one has messed with f_pos; reset the world */ | 522 | /* Some one has messed with f_pos; reset the world */ |
547 | if (info->last_pos != filp->f_pos) { | 523 | if (info->last_pos != ctx->pos) { |
548 | free_rb_tree_fname(&info->root); | 524 | free_rb_tree_fname(&info->root); |
549 | info->curr_node = NULL; | 525 | info->curr_node = NULL; |
550 | info->extra_fname = NULL; | 526 | info->extra_fname = NULL; |
551 | info->curr_hash = pos2maj_hash(filp, filp->f_pos); | 527 | info->curr_hash = pos2maj_hash(file, ctx->pos); |
552 | info->curr_minor_hash = pos2min_hash(filp, filp->f_pos); | 528 | info->curr_minor_hash = pos2min_hash(file, ctx->pos); |
553 | } | 529 | } |
554 | 530 | ||
555 | /* | 531 | /* |
@@ -557,7 +533,7 @@ static int ext4_dx_readdir(struct file *filp, | |||
557 | * chain, return them first. | 533 | * chain, return them first. |
558 | */ | 534 | */ |
559 | if (info->extra_fname) { | 535 | if (info->extra_fname) { |
560 | if (call_filldir(filp, dirent, filldir, info->extra_fname)) | 536 | if (call_filldir(file, ctx, info->extra_fname)) |
561 | goto finished; | 537 | goto finished; |
562 | info->extra_fname = NULL; | 538 | info->extra_fname = NULL; |
563 | goto next_node; | 539 | goto next_node; |
@@ -571,17 +547,17 @@ static int ext4_dx_readdir(struct file *filp, | |||
571 | * cached entries. | 547 | * cached entries. |
572 | */ | 548 | */ |
573 | if ((!info->curr_node) || | 549 | if ((!info->curr_node) || |
574 | (filp->f_version != inode->i_version)) { | 550 | (file->f_version != inode->i_version)) { |
575 | info->curr_node = NULL; | 551 | info->curr_node = NULL; |
576 | free_rb_tree_fname(&info->root); | 552 | free_rb_tree_fname(&info->root); |
577 | filp->f_version = inode->i_version; | 553 | file->f_version = inode->i_version; |
578 | ret = ext4_htree_fill_tree(filp, info->curr_hash, | 554 | ret = ext4_htree_fill_tree(file, info->curr_hash, |
579 | info->curr_minor_hash, | 555 | info->curr_minor_hash, |
580 | &info->next_hash); | 556 | &info->next_hash); |
581 | if (ret < 0) | 557 | if (ret < 0) |
582 | return ret; | 558 | return ret; |
583 | if (ret == 0) { | 559 | if (ret == 0) { |
584 | filp->f_pos = ext4_get_htree_eof(filp); | 560 | ctx->pos = ext4_get_htree_eof(file); |
585 | break; | 561 | break; |
586 | } | 562 | } |
587 | info->curr_node = rb_first(&info->root); | 563 | info->curr_node = rb_first(&info->root); |
@@ -590,7 +566,7 @@ static int ext4_dx_readdir(struct file *filp, | |||
590 | fname = rb_entry(info->curr_node, struct fname, rb_hash); | 566 | fname = rb_entry(info->curr_node, struct fname, rb_hash); |
591 | info->curr_hash = fname->hash; | 567 | info->curr_hash = fname->hash; |
592 | info->curr_minor_hash = fname->minor_hash; | 568 | info->curr_minor_hash = fname->minor_hash; |
593 | if (call_filldir(filp, dirent, filldir, fname)) | 569 | if (call_filldir(file, ctx, fname)) |
594 | break; | 570 | break; |
595 | next_node: | 571 | next_node: |
596 | info->curr_node = rb_next(info->curr_node); | 572 | info->curr_node = rb_next(info->curr_node); |
@@ -601,7 +577,7 @@ static int ext4_dx_readdir(struct file *filp, | |||
601 | info->curr_minor_hash = fname->minor_hash; | 577 | info->curr_minor_hash = fname->minor_hash; |
602 | } else { | 578 | } else { |
603 | if (info->next_hash == ~0) { | 579 | if (info->next_hash == ~0) { |
604 | filp->f_pos = ext4_get_htree_eof(filp); | 580 | ctx->pos = ext4_get_htree_eof(file); |
605 | break; | 581 | break; |
606 | } | 582 | } |
607 | info->curr_hash = info->next_hash; | 583 | info->curr_hash = info->next_hash; |
@@ -609,7 +585,7 @@ static int ext4_dx_readdir(struct file *filp, | |||
609 | } | 585 | } |
610 | } | 586 | } |
611 | finished: | 587 | finished: |
612 | info->last_pos = filp->f_pos; | 588 | info->last_pos = ctx->pos; |
613 | return 0; | 589 | return 0; |
614 | } | 590 | } |
615 | 591 | ||
@@ -624,7 +600,7 @@ static int ext4_release_dir(struct inode *inode, struct file *filp) | |||
624 | const struct file_operations ext4_dir_operations = { | 600 | const struct file_operations ext4_dir_operations = { |
625 | .llseek = ext4_dir_llseek, | 601 | .llseek = ext4_dir_llseek, |
626 | .read = generic_read_dir, | 602 | .read = generic_read_dir, |
627 | .readdir = ext4_readdir, | 603 | .iterate = ext4_readdir, |
628 | .unlocked_ioctl = ext4_ioctl, | 604 | .unlocked_ioctl = ext4_ioctl, |
629 | #ifdef CONFIG_COMPAT | 605 | #ifdef CONFIG_COMPAT |
630 | .compat_ioctl = ext4_compat_ioctl, | 606 | .compat_ioctl = ext4_compat_ioctl, |
diff --git a/fs/ext4/ext4.h b/fs/ext4/ext4.h index 5aae3d12d400..4af03ea84aa3 100644 --- a/fs/ext4/ext4.h +++ b/fs/ext4/ext4.h | |||
@@ -2515,7 +2515,7 @@ extern int ext4_try_create_inline_dir(handle_t *handle, | |||
2515 | struct inode *parent, | 2515 | struct inode *parent, |
2516 | struct inode *inode); | 2516 | struct inode *inode); |
2517 | extern int ext4_read_inline_dir(struct file *filp, | 2517 | extern int ext4_read_inline_dir(struct file *filp, |
2518 | void *dirent, filldir_t filldir, | 2518 | struct dir_context *ctx, |
2519 | int *has_inline_data); | 2519 | int *has_inline_data); |
2520 | extern int htree_inlinedir_to_tree(struct file *dir_file, | 2520 | extern int htree_inlinedir_to_tree(struct file *dir_file, |
2521 | struct inode *dir, ext4_lblk_t block, | 2521 | struct inode *dir, ext4_lblk_t block, |
diff --git a/fs/ext4/inline.c b/fs/ext4/inline.c index 3e2bf873e8a8..1a346a6bdc8f 100644 --- a/fs/ext4/inline.c +++ b/fs/ext4/inline.c | |||
@@ -1404,16 +1404,15 @@ out: | |||
1404 | * offset as if '.' and '..' really take place. | 1404 | * offset as if '.' and '..' really take place. |
1405 | * | 1405 | * |
1406 | */ | 1406 | */ |
1407 | int ext4_read_inline_dir(struct file *filp, | 1407 | int ext4_read_inline_dir(struct file *file, |
1408 | void *dirent, filldir_t filldir, | 1408 | struct dir_context *ctx, |
1409 | int *has_inline_data) | 1409 | int *has_inline_data) |
1410 | { | 1410 | { |
1411 | int error = 0; | ||
1412 | unsigned int offset, parent_ino; | 1411 | unsigned int offset, parent_ino; |
1413 | int i, stored; | 1412 | int i; |
1414 | struct ext4_dir_entry_2 *de; | 1413 | struct ext4_dir_entry_2 *de; |
1415 | struct super_block *sb; | 1414 | struct super_block *sb; |
1416 | struct inode *inode = file_inode(filp); | 1415 | struct inode *inode = file_inode(file); |
1417 | int ret, inline_size = 0; | 1416 | int ret, inline_size = 0; |
1418 | struct ext4_iloc iloc; | 1417 | struct ext4_iloc iloc; |
1419 | void *dir_buf = NULL; | 1418 | void *dir_buf = NULL; |
@@ -1444,9 +1443,8 @@ int ext4_read_inline_dir(struct file *filp, | |||
1444 | goto out; | 1443 | goto out; |
1445 | 1444 | ||
1446 | sb = inode->i_sb; | 1445 | sb = inode->i_sb; |
1447 | stored = 0; | ||
1448 | parent_ino = le32_to_cpu(((struct ext4_dir_entry_2 *)dir_buf)->inode); | 1446 | parent_ino = le32_to_cpu(((struct ext4_dir_entry_2 *)dir_buf)->inode); |
1449 | offset = filp->f_pos; | 1447 | offset = ctx->pos; |
1450 | 1448 | ||
1451 | /* | 1449 | /* |
1452 | * dotdot_offset and dotdot_size is the real offset and | 1450 | * dotdot_offset and dotdot_size is the real offset and |
@@ -1460,104 +1458,74 @@ int ext4_read_inline_dir(struct file *filp, | |||
1460 | extra_offset = dotdot_size - EXT4_INLINE_DOTDOT_SIZE; | 1458 | extra_offset = dotdot_size - EXT4_INLINE_DOTDOT_SIZE; |
1461 | extra_size = extra_offset + inline_size; | 1459 | extra_size = extra_offset + inline_size; |
1462 | 1460 | ||
1463 | while (!error && !stored && filp->f_pos < extra_size) { | 1461 | /* |
1464 | revalidate: | 1462 | * If the version has changed since the last call to |
1465 | /* | 1463 | * readdir(2), then we might be pointing to an invalid |
1466 | * If the version has changed since the last call to | 1464 | * dirent right now. Scan from the start of the inline |
1467 | * readdir(2), then we might be pointing to an invalid | 1465 | * dir to make sure. |
1468 | * dirent right now. Scan from the start of the inline | 1466 | */ |
1469 | * dir to make sure. | 1467 | if (file->f_version != inode->i_version) { |
1470 | */ | 1468 | for (i = 0; i < extra_size && i < offset;) { |
1471 | if (filp->f_version != inode->i_version) { | 1469 | /* |
1472 | for (i = 0; i < extra_size && i < offset;) { | 1470 | * "." is with offset 0 and |
1473 | /* | 1471 | * ".." is dotdot_offset. |
1474 | * "." is with offset 0 and | 1472 | */ |
1475 | * ".." is dotdot_offset. | 1473 | if (!i) { |
1476 | */ | 1474 | i = dotdot_offset; |
1477 | if (!i) { | 1475 | continue; |
1478 | i = dotdot_offset; | 1476 | } else if (i == dotdot_offset) { |
1479 | continue; | 1477 | i = dotdot_size; |
1480 | } else if (i == dotdot_offset) { | ||
1481 | i = dotdot_size; | ||
1482 | continue; | ||
1483 | } | ||
1484 | /* for other entry, the real offset in | ||
1485 | * the buf has to be tuned accordingly. | ||
1486 | */ | ||
1487 | de = (struct ext4_dir_entry_2 *) | ||
1488 | (dir_buf + i - extra_offset); | ||
1489 | /* It's too expensive to do a full | ||
1490 | * dirent test each time round this | ||
1491 | * loop, but we do have to test at | ||
1492 | * least that it is non-zero. A | ||
1493 | * failure will be detected in the | ||
1494 | * dirent test below. */ | ||
1495 | if (ext4_rec_len_from_disk(de->rec_len, | ||
1496 | extra_size) < EXT4_DIR_REC_LEN(1)) | ||
1497 | break; | ||
1498 | i += ext4_rec_len_from_disk(de->rec_len, | ||
1499 | extra_size); | ||
1500 | } | ||
1501 | offset = i; | ||
1502 | filp->f_pos = offset; | ||
1503 | filp->f_version = inode->i_version; | ||
1504 | } | ||
1505 | |||
1506 | while (!error && filp->f_pos < extra_size) { | ||
1507 | if (filp->f_pos == 0) { | ||
1508 | error = filldir(dirent, ".", 1, 0, inode->i_ino, | ||
1509 | DT_DIR); | ||
1510 | if (error) | ||
1511 | break; | ||
1512 | stored++; | ||
1513 | filp->f_pos = dotdot_offset; | ||
1514 | continue; | 1478 | continue; |
1515 | } | 1479 | } |
1480 | /* for other entry, the real offset in | ||
1481 | * the buf has to be tuned accordingly. | ||
1482 | */ | ||
1483 | de = (struct ext4_dir_entry_2 *) | ||
1484 | (dir_buf + i - extra_offset); | ||
1485 | /* It's too expensive to do a full | ||
1486 | * dirent test each time round this | ||
1487 | * loop, but we do have to test at | ||
1488 | * least that it is non-zero. A | ||
1489 | * failure will be detected in the | ||
1490 | * dirent test below. */ | ||
1491 | if (ext4_rec_len_from_disk(de->rec_len, extra_size) | ||
1492 | < EXT4_DIR_REC_LEN(1)) | ||
1493 | break; | ||
1494 | i += ext4_rec_len_from_disk(de->rec_len, | ||
1495 | extra_size); | ||
1496 | } | ||
1497 | offset = i; | ||
1498 | ctx->pos = offset; | ||
1499 | file->f_version = inode->i_version; | ||
1500 | } | ||
1516 | 1501 | ||
1517 | if (filp->f_pos == dotdot_offset) { | 1502 | while (ctx->pos < extra_size) { |
1518 | error = filldir(dirent, "..", 2, | 1503 | if (ctx->pos == 0) { |
1519 | dotdot_offset, | 1504 | if (!dir_emit(ctx, ".", 1, inode->i_ino, DT_DIR)) |
1520 | parent_ino, DT_DIR); | 1505 | goto out; |
1521 | if (error) | 1506 | ctx->pos = dotdot_offset; |
1522 | break; | 1507 | continue; |
1523 | stored++; | 1508 | } |
1524 | 1509 | ||
1525 | filp->f_pos = dotdot_size; | 1510 | if (ctx->pos == dotdot_offset) { |
1526 | continue; | 1511 | if (!dir_emit(ctx, "..", 2, parent_ino, DT_DIR)) |
1527 | } | 1512 | goto out; |
1513 | ctx->pos = dotdot_size; | ||
1514 | continue; | ||
1515 | } | ||
1528 | 1516 | ||
1529 | de = (struct ext4_dir_entry_2 *) | 1517 | de = (struct ext4_dir_entry_2 *) |
1530 | (dir_buf + filp->f_pos - extra_offset); | 1518 | (dir_buf + ctx->pos - extra_offset); |
1531 | if (ext4_check_dir_entry(inode, filp, de, | 1519 | if (ext4_check_dir_entry(inode, file, de, iloc.bh, dir_buf, |
1532 | iloc.bh, dir_buf, | 1520 | extra_size, ctx->pos)) |
1533 | extra_size, filp->f_pos)) { | 1521 | goto out; |
1534 | ret = stored; | 1522 | if (le32_to_cpu(de->inode)) { |
1523 | if (!dir_emit(ctx, de->name, de->name_len, | ||
1524 | le32_to_cpu(de->inode), | ||
1525 | get_dtype(sb, de->file_type))) | ||
1535 | goto out; | 1526 | goto out; |
1536 | } | ||
1537 | if (le32_to_cpu(de->inode)) { | ||
1538 | /* We might block in the next section | ||
1539 | * if the data destination is | ||
1540 | * currently swapped out. So, use a | ||
1541 | * version stamp to detect whether or | ||
1542 | * not the directory has been modified | ||
1543 | * during the copy operation. | ||
1544 | */ | ||
1545 | u64 version = filp->f_version; | ||
1546 | |||
1547 | error = filldir(dirent, de->name, | ||
1548 | de->name_len, | ||
1549 | filp->f_pos, | ||
1550 | le32_to_cpu(de->inode), | ||
1551 | get_dtype(sb, de->file_type)); | ||
1552 | if (error) | ||
1553 | break; | ||
1554 | if (version != filp->f_version) | ||
1555 | goto revalidate; | ||
1556 | stored++; | ||
1557 | } | ||
1558 | filp->f_pos += ext4_rec_len_from_disk(de->rec_len, | ||
1559 | extra_size); | ||
1560 | } | 1527 | } |
1528 | ctx->pos += ext4_rec_len_from_disk(de->rec_len, extra_size); | ||
1561 | } | 1529 | } |
1562 | out: | 1530 | out: |
1563 | kfree(dir_buf); | 1531 | kfree(dir_buf); |
diff --git a/fs/f2fs/dir.c b/fs/f2fs/dir.c index 1ac6b93036b7..600bb5efe603 100644 --- a/fs/f2fs/dir.c +++ b/fs/f2fs/dir.c | |||
@@ -591,24 +591,19 @@ bool f2fs_empty_dir(struct inode *dir) | |||
591 | return true; | 591 | return true; |
592 | } | 592 | } |
593 | 593 | ||
594 | static int f2fs_readdir(struct file *file, void *dirent, filldir_t filldir) | 594 | static int f2fs_readdir(struct file *file, struct dir_context *ctx) |
595 | { | 595 | { |
596 | unsigned long pos = file->f_pos; | ||
597 | struct inode *inode = file_inode(file); | 596 | struct inode *inode = file_inode(file); |
598 | unsigned long npages = dir_blocks(inode); | 597 | unsigned long npages = dir_blocks(inode); |
599 | unsigned char *types = NULL; | ||
600 | unsigned int bit_pos = 0, start_bit_pos = 0; | 598 | unsigned int bit_pos = 0, start_bit_pos = 0; |
601 | int over = 0; | ||
602 | struct f2fs_dentry_block *dentry_blk = NULL; | 599 | struct f2fs_dentry_block *dentry_blk = NULL; |
603 | struct f2fs_dir_entry *de = NULL; | 600 | struct f2fs_dir_entry *de = NULL; |
604 | struct page *dentry_page = NULL; | 601 | struct page *dentry_page = NULL; |
605 | unsigned int n = 0; | 602 | unsigned int n = ((unsigned long)ctx->pos / NR_DENTRY_IN_BLOCK); |
606 | unsigned char d_type = DT_UNKNOWN; | 603 | unsigned char d_type = DT_UNKNOWN; |
607 | int slots; | 604 | int slots; |
608 | 605 | ||
609 | types = f2fs_filetype_table; | 606 | bit_pos = ((unsigned long)ctx->pos % NR_DENTRY_IN_BLOCK); |
610 | bit_pos = (pos % NR_DENTRY_IN_BLOCK); | ||
611 | n = (pos / NR_DENTRY_IN_BLOCK); | ||
612 | 607 | ||
613 | for ( ; n < npages; n++) { | 608 | for ( ; n < npages; n++) { |
614 | dentry_page = get_lock_data_page(inode, n); | 609 | dentry_page = get_lock_data_page(inode, n); |
@@ -618,31 +613,28 @@ static int f2fs_readdir(struct file *file, void *dirent, filldir_t filldir) | |||
618 | start_bit_pos = bit_pos; | 613 | start_bit_pos = bit_pos; |
619 | dentry_blk = kmap(dentry_page); | 614 | dentry_blk = kmap(dentry_page); |
620 | while (bit_pos < NR_DENTRY_IN_BLOCK) { | 615 | while (bit_pos < NR_DENTRY_IN_BLOCK) { |
621 | d_type = DT_UNKNOWN; | ||
622 | bit_pos = find_next_bit_le(&dentry_blk->dentry_bitmap, | 616 | bit_pos = find_next_bit_le(&dentry_blk->dentry_bitmap, |
623 | NR_DENTRY_IN_BLOCK, | 617 | NR_DENTRY_IN_BLOCK, |
624 | bit_pos); | 618 | bit_pos); |
625 | if (bit_pos >= NR_DENTRY_IN_BLOCK) | 619 | if (bit_pos >= NR_DENTRY_IN_BLOCK) |
626 | break; | 620 | break; |
627 | 621 | ||
622 | ctx->pos += bit_pos - start_bit_pos; | ||
628 | de = &dentry_blk->dentry[bit_pos]; | 623 | de = &dentry_blk->dentry[bit_pos]; |
629 | if (types && de->file_type < F2FS_FT_MAX) | 624 | if (de->file_type < F2FS_FT_MAX) |
630 | d_type = types[de->file_type]; | 625 | d_type = f2fs_filetype_table[de->file_type]; |
631 | 626 | else | |
632 | over = filldir(dirent, | 627 | d_type = DT_UNKNOWN; |
633 | dentry_blk->filename[bit_pos], | 628 | if (!dir_emit(ctx, |
634 | le16_to_cpu(de->name_len), | 629 | dentry_blk->filename[bit_pos], |
635 | (n * NR_DENTRY_IN_BLOCK) + bit_pos, | 630 | le16_to_cpu(de->name_len), |
636 | le32_to_cpu(de->ino), d_type); | 631 | le32_to_cpu(de->ino), d_type)) |
637 | if (over) { | ||
638 | file->f_pos += bit_pos - start_bit_pos; | ||
639 | goto success; | 632 | goto success; |
640 | } | ||
641 | slots = GET_DENTRY_SLOTS(le16_to_cpu(de->name_len)); | 633 | slots = GET_DENTRY_SLOTS(le16_to_cpu(de->name_len)); |
642 | bit_pos += slots; | 634 | bit_pos += slots; |
643 | } | 635 | } |
644 | bit_pos = 0; | 636 | bit_pos = 0; |
645 | file->f_pos = (n + 1) * NR_DENTRY_IN_BLOCK; | 637 | ctx->pos = (n + 1) * NR_DENTRY_IN_BLOCK; |
646 | kunmap(dentry_page); | 638 | kunmap(dentry_page); |
647 | f2fs_put_page(dentry_page, 1); | 639 | f2fs_put_page(dentry_page, 1); |
648 | dentry_page = NULL; | 640 | dentry_page = NULL; |
@@ -659,7 +651,7 @@ success: | |||
659 | const struct file_operations f2fs_dir_operations = { | 651 | const struct file_operations f2fs_dir_operations = { |
660 | .llseek = generic_file_llseek, | 652 | .llseek = generic_file_llseek, |
661 | .read = generic_read_dir, | 653 | .read = generic_read_dir, |
662 | .readdir = f2fs_readdir, | 654 | .iterate = f2fs_readdir, |
663 | .fsync = f2fs_sync_file, | 655 | .fsync = f2fs_sync_file, |
664 | .unlocked_ioctl = f2fs_ioctl, | 656 | .unlocked_ioctl = f2fs_ioctl, |
665 | }; | 657 | }; |
diff --git a/fs/fat/dir.c b/fs/fat/dir.c index 7a6f02caf286..3963ede84eb0 100644 --- a/fs/fat/dir.c +++ b/fs/fat/dir.c | |||
@@ -543,6 +543,7 @@ end_of_dir: | |||
543 | EXPORT_SYMBOL_GPL(fat_search_long); | 543 | EXPORT_SYMBOL_GPL(fat_search_long); |
544 | 544 | ||
545 | struct fat_ioctl_filldir_callback { | 545 | struct fat_ioctl_filldir_callback { |
546 | struct dir_context ctx; | ||
546 | void __user *dirent; | 547 | void __user *dirent; |
547 | int result; | 548 | int result; |
548 | /* for dir ioctl */ | 549 | /* for dir ioctl */ |
@@ -552,8 +553,9 @@ struct fat_ioctl_filldir_callback { | |||
552 | int short_len; | 553 | int short_len; |
553 | }; | 554 | }; |
554 | 555 | ||
555 | static int __fat_readdir(struct inode *inode, struct file *filp, void *dirent, | 556 | static int __fat_readdir(struct inode *inode, struct file *file, |
556 | filldir_t filldir, int short_only, int both) | 557 | struct dir_context *ctx, int short_only, |
558 | struct fat_ioctl_filldir_callback *both) | ||
557 | { | 559 | { |
558 | struct super_block *sb = inode->i_sb; | 560 | struct super_block *sb = inode->i_sb; |
559 | struct msdos_sb_info *sbi = MSDOS_SB(sb); | 561 | struct msdos_sb_info *sbi = MSDOS_SB(sb); |
@@ -564,27 +566,20 @@ static int __fat_readdir(struct inode *inode, struct file *filp, void *dirent, | |||
564 | unsigned char bufname[FAT_MAX_SHORT_SIZE]; | 566 | unsigned char bufname[FAT_MAX_SHORT_SIZE]; |
565 | int isvfat = sbi->options.isvfat; | 567 | int isvfat = sbi->options.isvfat; |
566 | const char *fill_name = NULL; | 568 | const char *fill_name = NULL; |
567 | unsigned long inum; | 569 | int fake_offset = 0; |
568 | unsigned long lpos, dummy, *furrfu = &lpos; | ||
569 | loff_t cpos; | 570 | loff_t cpos; |
570 | int short_len = 0, fill_len = 0; | 571 | int short_len = 0, fill_len = 0; |
571 | int ret = 0; | 572 | int ret = 0; |
572 | 573 | ||
573 | mutex_lock(&sbi->s_lock); | 574 | mutex_lock(&sbi->s_lock); |
574 | 575 | ||
575 | cpos = filp->f_pos; | 576 | cpos = ctx->pos; |
576 | /* Fake . and .. for the root directory. */ | 577 | /* Fake . and .. for the root directory. */ |
577 | if (inode->i_ino == MSDOS_ROOT_INO) { | 578 | if (inode->i_ino == MSDOS_ROOT_INO) { |
578 | while (cpos < 2) { | 579 | if (!dir_emit_dots(file, ctx)) |
579 | if (filldir(dirent, "..", cpos+1, cpos, | 580 | goto out; |
580 | MSDOS_ROOT_INO, DT_DIR) < 0) | 581 | if (ctx->pos == 2) { |
581 | goto out; | 582 | fake_offset = 1; |
582 | cpos++; | ||
583 | filp->f_pos++; | ||
584 | } | ||
585 | if (cpos == 2) { | ||
586 | dummy = 2; | ||
587 | furrfu = &dummy; | ||
588 | cpos = 0; | 583 | cpos = 0; |
589 | } | 584 | } |
590 | } | 585 | } |
@@ -619,7 +614,7 @@ parse_record: | |||
619 | int status = fat_parse_long(inode, &cpos, &bh, &de, | 614 | int status = fat_parse_long(inode, &cpos, &bh, &de, |
620 | &unicode, &nr_slots); | 615 | &unicode, &nr_slots); |
621 | if (status < 0) { | 616 | if (status < 0) { |
622 | filp->f_pos = cpos; | 617 | ctx->pos = cpos; |
623 | ret = status; | 618 | ret = status; |
624 | goto out; | 619 | goto out; |
625 | } else if (status == PARSE_INVALID) | 620 | } else if (status == PARSE_INVALID) |
@@ -639,6 +634,19 @@ parse_record: | |||
639 | /* !both && !short_only, so we don't need shortname. */ | 634 | /* !both && !short_only, so we don't need shortname. */ |
640 | if (!both) | 635 | if (!both) |
641 | goto start_filldir; | 636 | goto start_filldir; |
637 | |||
638 | short_len = fat_parse_short(sb, de, bufname, | ||
639 | sbi->options.dotsOK); | ||
640 | if (short_len == 0) | ||
641 | goto record_end; | ||
642 | /* hack for fat_ioctl_filldir() */ | ||
643 | both->longname = fill_name; | ||
644 | both->long_len = fill_len; | ||
645 | both->shortname = bufname; | ||
646 | both->short_len = short_len; | ||
647 | fill_name = NULL; | ||
648 | fill_len = 0; | ||
649 | goto start_filldir; | ||
642 | } | 650 | } |
643 | } | 651 | } |
644 | 652 | ||
@@ -646,28 +654,21 @@ parse_record: | |||
646 | if (short_len == 0) | 654 | if (short_len == 0) |
647 | goto record_end; | 655 | goto record_end; |
648 | 656 | ||
649 | if (nr_slots) { | 657 | fill_name = bufname; |
650 | /* hack for fat_ioctl_filldir() */ | 658 | fill_len = short_len; |
651 | struct fat_ioctl_filldir_callback *p = dirent; | ||
652 | |||
653 | p->longname = fill_name; | ||
654 | p->long_len = fill_len; | ||
655 | p->shortname = bufname; | ||
656 | p->short_len = short_len; | ||
657 | fill_name = NULL; | ||
658 | fill_len = 0; | ||
659 | } else { | ||
660 | fill_name = bufname; | ||
661 | fill_len = short_len; | ||
662 | } | ||
663 | 659 | ||
664 | start_filldir: | 660 | start_filldir: |
665 | lpos = cpos - (nr_slots + 1) * sizeof(struct msdos_dir_entry); | 661 | if (!fake_offset) |
666 | if (!memcmp(de->name, MSDOS_DOT, MSDOS_NAME)) | 662 | ctx->pos = cpos - (nr_slots + 1) * sizeof(struct msdos_dir_entry); |
667 | inum = inode->i_ino; | 663 | |
668 | else if (!memcmp(de->name, MSDOS_DOTDOT, MSDOS_NAME)) { | 664 | if (!memcmp(de->name, MSDOS_DOT, MSDOS_NAME)) { |
669 | inum = parent_ino(filp->f_path.dentry); | 665 | if (!dir_emit_dot(file, ctx)) |
666 | goto fill_failed; | ||
667 | } else if (!memcmp(de->name, MSDOS_DOTDOT, MSDOS_NAME)) { | ||
668 | if (!dir_emit_dotdot(file, ctx)) | ||
669 | goto fill_failed; | ||
670 | } else { | 670 | } else { |
671 | unsigned long inum; | ||
671 | loff_t i_pos = fat_make_i_pos(sb, bh, de); | 672 | loff_t i_pos = fat_make_i_pos(sb, bh, de); |
672 | struct inode *tmp = fat_iget(sb, i_pos); | 673 | struct inode *tmp = fat_iget(sb, i_pos); |
673 | if (tmp) { | 674 | if (tmp) { |
@@ -675,18 +676,17 @@ start_filldir: | |||
675 | iput(tmp); | 676 | iput(tmp); |
676 | } else | 677 | } else |
677 | inum = iunique(sb, MSDOS_ROOT_INO); | 678 | inum = iunique(sb, MSDOS_ROOT_INO); |
679 | if (!dir_emit(ctx, fill_name, fill_len, inum, | ||
680 | (de->attr & ATTR_DIR) ? DT_DIR : DT_REG)) | ||
681 | goto fill_failed; | ||
678 | } | 682 | } |
679 | 683 | ||
680 | if (filldir(dirent, fill_name, fill_len, *furrfu, inum, | ||
681 | (de->attr & ATTR_DIR) ? DT_DIR : DT_REG) < 0) | ||
682 | goto fill_failed; | ||
683 | |||
684 | record_end: | 684 | record_end: |
685 | furrfu = &lpos; | 685 | fake_offset = 0; |
686 | filp->f_pos = cpos; | 686 | ctx->pos = cpos; |
687 | goto get_new; | 687 | goto get_new; |
688 | end_of_dir: | 688 | end_of_dir: |
689 | filp->f_pos = cpos; | 689 | ctx->pos = cpos; |
690 | fill_failed: | 690 | fill_failed: |
691 | brelse(bh); | 691 | brelse(bh); |
692 | if (unicode) | 692 | if (unicode) |
@@ -696,10 +696,9 @@ out: | |||
696 | return ret; | 696 | return ret; |
697 | } | 697 | } |
698 | 698 | ||
699 | static int fat_readdir(struct file *filp, void *dirent, filldir_t filldir) | 699 | static int fat_readdir(struct file *file, struct dir_context *ctx) |
700 | { | 700 | { |
701 | struct inode *inode = file_inode(filp); | 701 | return __fat_readdir(file_inode(file), file, ctx, 0, NULL); |
702 | return __fat_readdir(inode, filp, dirent, filldir, 0, 0); | ||
703 | } | 702 | } |
704 | 703 | ||
705 | #define FAT_IOCTL_FILLDIR_FUNC(func, dirent_type) \ | 704 | #define FAT_IOCTL_FILLDIR_FUNC(func, dirent_type) \ |
@@ -755,20 +754,25 @@ efault: \ | |||
755 | 754 | ||
756 | FAT_IOCTL_FILLDIR_FUNC(fat_ioctl_filldir, __fat_dirent) | 755 | FAT_IOCTL_FILLDIR_FUNC(fat_ioctl_filldir, __fat_dirent) |
757 | 756 | ||
758 | static int fat_ioctl_readdir(struct inode *inode, struct file *filp, | 757 | static int fat_ioctl_readdir(struct inode *inode, struct file *file, |
759 | void __user *dirent, filldir_t filldir, | 758 | void __user *dirent, filldir_t filldir, |
760 | int short_only, int both) | 759 | int short_only, int both) |
761 | { | 760 | { |
762 | struct fat_ioctl_filldir_callback buf; | 761 | struct fat_ioctl_filldir_callback buf = { |
762 | .ctx.actor = filldir, | ||
763 | .dirent = dirent | ||
764 | }; | ||
763 | int ret; | 765 | int ret; |
764 | 766 | ||
765 | buf.dirent = dirent; | 767 | buf.dirent = dirent; |
766 | buf.result = 0; | 768 | buf.result = 0; |
767 | mutex_lock(&inode->i_mutex); | 769 | mutex_lock(&inode->i_mutex); |
770 | buf.ctx.pos = file->f_pos; | ||
768 | ret = -ENOENT; | 771 | ret = -ENOENT; |
769 | if (!IS_DEADDIR(inode)) { | 772 | if (!IS_DEADDIR(inode)) { |
770 | ret = __fat_readdir(inode, filp, &buf, filldir, | 773 | ret = __fat_readdir(inode, file, &buf.ctx, |
771 | short_only, both); | 774 | short_only, both ? &buf : NULL); |
775 | file->f_pos = buf.ctx.pos; | ||
772 | } | 776 | } |
773 | mutex_unlock(&inode->i_mutex); | 777 | mutex_unlock(&inode->i_mutex); |
774 | if (ret >= 0) | 778 | if (ret >= 0) |
@@ -854,7 +858,7 @@ static long fat_compat_dir_ioctl(struct file *filp, unsigned cmd, | |||
854 | const struct file_operations fat_dir_operations = { | 858 | const struct file_operations fat_dir_operations = { |
855 | .llseek = generic_file_llseek, | 859 | .llseek = generic_file_llseek, |
856 | .read = generic_read_dir, | 860 | .read = generic_read_dir, |
857 | .readdir = fat_readdir, | 861 | .iterate = fat_readdir, |
858 | .unlocked_ioctl = fat_dir_ioctl, | 862 | .unlocked_ioctl = fat_dir_ioctl, |
859 | #ifdef CONFIG_COMPAT | 863 | #ifdef CONFIG_COMPAT |
860 | .compat_ioctl = fat_compat_dir_ioctl, | 864 | .compat_ioctl = fat_compat_dir_ioctl, |
diff --git a/fs/freevxfs/vxfs_lookup.c b/fs/freevxfs/vxfs_lookup.c index 664b07a53870..25d4099a4aea 100644 --- a/fs/freevxfs/vxfs_lookup.c +++ b/fs/freevxfs/vxfs_lookup.c | |||
@@ -49,7 +49,7 @@ | |||
49 | 49 | ||
50 | 50 | ||
51 | static struct dentry * vxfs_lookup(struct inode *, struct dentry *, unsigned int); | 51 | static struct dentry * vxfs_lookup(struct inode *, struct dentry *, unsigned int); |
52 | static int vxfs_readdir(struct file *, void *, filldir_t); | 52 | static int vxfs_readdir(struct file *, struct dir_context *); |
53 | 53 | ||
54 | const struct inode_operations vxfs_dir_inode_ops = { | 54 | const struct inode_operations vxfs_dir_inode_ops = { |
55 | .lookup = vxfs_lookup, | 55 | .lookup = vxfs_lookup, |
@@ -58,7 +58,7 @@ const struct inode_operations vxfs_dir_inode_ops = { | |||
58 | const struct file_operations vxfs_dir_operations = { | 58 | const struct file_operations vxfs_dir_operations = { |
59 | .llseek = generic_file_llseek, | 59 | .llseek = generic_file_llseek, |
60 | .read = generic_read_dir, | 60 | .read = generic_read_dir, |
61 | .readdir = vxfs_readdir, | 61 | .iterate = vxfs_readdir, |
62 | }; | 62 | }; |
63 | 63 | ||
64 | 64 | ||
@@ -235,7 +235,7 @@ vxfs_lookup(struct inode *dip, struct dentry *dp, unsigned int flags) | |||
235 | * Zero. | 235 | * Zero. |
236 | */ | 236 | */ |
237 | static int | 237 | static int |
238 | vxfs_readdir(struct file *fp, void *retp, filldir_t filler) | 238 | vxfs_readdir(struct file *fp, struct dir_context *ctx) |
239 | { | 239 | { |
240 | struct inode *ip = file_inode(fp); | 240 | struct inode *ip = file_inode(fp); |
241 | struct super_block *sbp = ip->i_sb; | 241 | struct super_block *sbp = ip->i_sb; |
@@ -243,20 +243,17 @@ vxfs_readdir(struct file *fp, void *retp, filldir_t filler) | |||
243 | u_long page, npages, block, pblocks, nblocks, offset; | 243 | u_long page, npages, block, pblocks, nblocks, offset; |
244 | loff_t pos; | 244 | loff_t pos; |
245 | 245 | ||
246 | switch ((long)fp->f_pos) { | 246 | if (ctx->pos == 0) { |
247 | case 0: | 247 | if (!dir_emit_dot(fp, ctx)) |
248 | if (filler(retp, ".", 1, fp->f_pos, ip->i_ino, DT_DIR) < 0) | 248 | return 0; |
249 | goto out; | 249 | ctx->pos = 1; |
250 | fp->f_pos++; | ||
251 | /* fallthrough */ | ||
252 | case 1: | ||
253 | if (filler(retp, "..", 2, fp->f_pos, VXFS_INO(ip)->vii_dotdot, DT_DIR) < 0) | ||
254 | goto out; | ||
255 | fp->f_pos++; | ||
256 | /* fallthrough */ | ||
257 | } | 250 | } |
258 | 251 | if (ctx->pos == 1) { | |
259 | pos = fp->f_pos - 2; | 252 | if (!dir_emit(ctx, "..", 2, VXFS_INO(ip)->vii_dotdot, DT_DIR)) |
253 | return 0; | ||
254 | ctx->pos = 2; | ||
255 | } | ||
256 | pos = ctx->pos - 2; | ||
260 | 257 | ||
261 | if (pos > VXFS_DIRROUND(ip->i_size)) | 258 | if (pos > VXFS_DIRROUND(ip->i_size)) |
262 | return 0; | 259 | return 0; |
@@ -270,16 +267,16 @@ vxfs_readdir(struct file *fp, void *retp, filldir_t filler) | |||
270 | block = (u_long)(pos >> sbp->s_blocksize_bits) % pblocks; | 267 | block = (u_long)(pos >> sbp->s_blocksize_bits) % pblocks; |
271 | 268 | ||
272 | for (; page < npages; page++, block = 0) { | 269 | for (; page < npages; page++, block = 0) { |
273 | caddr_t kaddr; | 270 | char *kaddr; |
274 | struct page *pp; | 271 | struct page *pp; |
275 | 272 | ||
276 | pp = vxfs_get_page(ip->i_mapping, page); | 273 | pp = vxfs_get_page(ip->i_mapping, page); |
277 | if (IS_ERR(pp)) | 274 | if (IS_ERR(pp)) |
278 | continue; | 275 | continue; |
279 | kaddr = (caddr_t)page_address(pp); | 276 | kaddr = (char *)page_address(pp); |
280 | 277 | ||
281 | for (; block <= nblocks && block <= pblocks; block++) { | 278 | for (; block <= nblocks && block <= pblocks; block++) { |
282 | caddr_t baddr, limit; | 279 | char *baddr, *limit; |
283 | struct vxfs_dirblk *dbp; | 280 | struct vxfs_dirblk *dbp; |
284 | struct vxfs_direct *de; | 281 | struct vxfs_direct *de; |
285 | 282 | ||
@@ -292,21 +289,18 @@ vxfs_readdir(struct file *fp, void *retp, filldir_t filler) | |||
292 | (kaddr + offset) : | 289 | (kaddr + offset) : |
293 | (baddr + VXFS_DIRBLKOV(dbp))); | 290 | (baddr + VXFS_DIRBLKOV(dbp))); |
294 | 291 | ||
295 | for (; (caddr_t)de <= limit; de = vxfs_next_entry(de)) { | 292 | for (; (char *)de <= limit; de = vxfs_next_entry(de)) { |
296 | int over; | ||
297 | |||
298 | if (!de->d_reclen) | 293 | if (!de->d_reclen) |
299 | break; | 294 | break; |
300 | if (!de->d_ino) | 295 | if (!de->d_ino) |
301 | continue; | 296 | continue; |
302 | 297 | ||
303 | offset = (caddr_t)de - kaddr; | 298 | offset = (char *)de - kaddr; |
304 | over = filler(retp, de->d_name, de->d_namelen, | 299 | ctx->pos = ((page << PAGE_CACHE_SHIFT) | offset) + 2; |
305 | ((page << PAGE_CACHE_SHIFT) | offset) + 2, | 300 | if (!dir_emit(ctx, de->d_name, de->d_namelen, |
306 | de->d_ino, DT_UNKNOWN); | 301 | de->d_ino, DT_UNKNOWN)) { |
307 | if (over) { | ||
308 | vxfs_put_page(pp); | 302 | vxfs_put_page(pp); |
309 | goto done; | 303 | return 0; |
310 | } | 304 | } |
311 | } | 305 | } |
312 | offset = 0; | 306 | offset = 0; |
@@ -314,9 +308,6 @@ vxfs_readdir(struct file *fp, void *retp, filldir_t filler) | |||
314 | vxfs_put_page(pp); | 308 | vxfs_put_page(pp); |
315 | offset = 0; | 309 | offset = 0; |
316 | } | 310 | } |
317 | 311 | ctx->pos = ((page << PAGE_CACHE_SHIFT) | offset) + 2; | |
318 | done: | ||
319 | fp->f_pos = ((page << PAGE_CACHE_SHIFT) | offset) + 2; | ||
320 | out: | ||
321 | return 0; | 312 | return 0; |
322 | } | 313 | } |
diff --git a/fs/fuse/dir.c b/fs/fuse/dir.c index f3f783dc4f75..0eda52738ec4 100644 --- a/fs/fuse/dir.c +++ b/fs/fuse/dir.c | |||
@@ -14,7 +14,7 @@ | |||
14 | #include <linux/namei.h> | 14 | #include <linux/namei.h> |
15 | #include <linux/slab.h> | 15 | #include <linux/slab.h> |
16 | 16 | ||
17 | static bool fuse_use_readdirplus(struct inode *dir, struct file *filp) | 17 | static bool fuse_use_readdirplus(struct inode *dir, struct dir_context *ctx) |
18 | { | 18 | { |
19 | struct fuse_conn *fc = get_fuse_conn(dir); | 19 | struct fuse_conn *fc = get_fuse_conn(dir); |
20 | struct fuse_inode *fi = get_fuse_inode(dir); | 20 | struct fuse_inode *fi = get_fuse_inode(dir); |
@@ -25,7 +25,7 @@ static bool fuse_use_readdirplus(struct inode *dir, struct file *filp) | |||
25 | return true; | 25 | return true; |
26 | if (test_and_clear_bit(FUSE_I_ADVISE_RDPLUS, &fi->state)) | 26 | if (test_and_clear_bit(FUSE_I_ADVISE_RDPLUS, &fi->state)) |
27 | return true; | 27 | return true; |
28 | if (filp->f_pos == 0) | 28 | if (ctx->pos == 0) |
29 | return true; | 29 | return true; |
30 | return false; | 30 | return false; |
31 | } | 31 | } |
@@ -1165,25 +1165,23 @@ static int fuse_permission(struct inode *inode, int mask) | |||
1165 | } | 1165 | } |
1166 | 1166 | ||
1167 | static int parse_dirfile(char *buf, size_t nbytes, struct file *file, | 1167 | static int parse_dirfile(char *buf, size_t nbytes, struct file *file, |
1168 | void *dstbuf, filldir_t filldir) | 1168 | struct dir_context *ctx) |
1169 | { | 1169 | { |
1170 | while (nbytes >= FUSE_NAME_OFFSET) { | 1170 | while (nbytes >= FUSE_NAME_OFFSET) { |
1171 | struct fuse_dirent *dirent = (struct fuse_dirent *) buf; | 1171 | struct fuse_dirent *dirent = (struct fuse_dirent *) buf; |
1172 | size_t reclen = FUSE_DIRENT_SIZE(dirent); | 1172 | size_t reclen = FUSE_DIRENT_SIZE(dirent); |
1173 | int over; | ||
1174 | if (!dirent->namelen || dirent->namelen > FUSE_NAME_MAX) | 1173 | if (!dirent->namelen || dirent->namelen > FUSE_NAME_MAX) |
1175 | return -EIO; | 1174 | return -EIO; |
1176 | if (reclen > nbytes) | 1175 | if (reclen > nbytes) |
1177 | break; | 1176 | break; |
1178 | 1177 | ||
1179 | over = filldir(dstbuf, dirent->name, dirent->namelen, | 1178 | if (!dir_emit(ctx, dirent->name, dirent->namelen, |
1180 | file->f_pos, dirent->ino, dirent->type); | 1179 | dirent->ino, dirent->type)) |
1181 | if (over) | ||
1182 | break; | 1180 | break; |
1183 | 1181 | ||
1184 | buf += reclen; | 1182 | buf += reclen; |
1185 | nbytes -= reclen; | 1183 | nbytes -= reclen; |
1186 | file->f_pos = dirent->off; | 1184 | ctx->pos = dirent->off; |
1187 | } | 1185 | } |
1188 | 1186 | ||
1189 | return 0; | 1187 | return 0; |
@@ -1284,7 +1282,7 @@ out: | |||
1284 | } | 1282 | } |
1285 | 1283 | ||
1286 | static int parse_dirplusfile(char *buf, size_t nbytes, struct file *file, | 1284 | static int parse_dirplusfile(char *buf, size_t nbytes, struct file *file, |
1287 | void *dstbuf, filldir_t filldir, u64 attr_version) | 1285 | struct dir_context *ctx, u64 attr_version) |
1288 | { | 1286 | { |
1289 | struct fuse_direntplus *direntplus; | 1287 | struct fuse_direntplus *direntplus; |
1290 | struct fuse_dirent *dirent; | 1288 | struct fuse_dirent *dirent; |
@@ -1309,10 +1307,9 @@ static int parse_dirplusfile(char *buf, size_t nbytes, struct file *file, | |||
1309 | we need to send a FORGET for each of those | 1307 | we need to send a FORGET for each of those |
1310 | which we did not link. | 1308 | which we did not link. |
1311 | */ | 1309 | */ |
1312 | over = filldir(dstbuf, dirent->name, dirent->namelen, | 1310 | over = !dir_emit(ctx, dirent->name, dirent->namelen, |
1313 | file->f_pos, dirent->ino, | 1311 | dirent->ino, dirent->type); |
1314 | dirent->type); | 1312 | ctx->pos = dirent->off; |
1315 | file->f_pos = dirent->off; | ||
1316 | } | 1313 | } |
1317 | 1314 | ||
1318 | buf += reclen; | 1315 | buf += reclen; |
@@ -1326,7 +1323,7 @@ static int parse_dirplusfile(char *buf, size_t nbytes, struct file *file, | |||
1326 | return 0; | 1323 | return 0; |
1327 | } | 1324 | } |
1328 | 1325 | ||
1329 | static int fuse_readdir(struct file *file, void *dstbuf, filldir_t filldir) | 1326 | static int fuse_readdir(struct file *file, struct dir_context *ctx) |
1330 | { | 1327 | { |
1331 | int plus, err; | 1328 | int plus, err; |
1332 | size_t nbytes; | 1329 | size_t nbytes; |
@@ -1349,17 +1346,17 @@ static int fuse_readdir(struct file *file, void *dstbuf, filldir_t filldir) | |||
1349 | return -ENOMEM; | 1346 | return -ENOMEM; |
1350 | } | 1347 | } |
1351 | 1348 | ||
1352 | plus = fuse_use_readdirplus(inode, file); | 1349 | plus = fuse_use_readdirplus(inode, ctx); |
1353 | req->out.argpages = 1; | 1350 | req->out.argpages = 1; |
1354 | req->num_pages = 1; | 1351 | req->num_pages = 1; |
1355 | req->pages[0] = page; | 1352 | req->pages[0] = page; |
1356 | req->page_descs[0].length = PAGE_SIZE; | 1353 | req->page_descs[0].length = PAGE_SIZE; |
1357 | if (plus) { | 1354 | if (plus) { |
1358 | attr_version = fuse_get_attr_version(fc); | 1355 | attr_version = fuse_get_attr_version(fc); |
1359 | fuse_read_fill(req, file, file->f_pos, PAGE_SIZE, | 1356 | fuse_read_fill(req, file, ctx->pos, PAGE_SIZE, |
1360 | FUSE_READDIRPLUS); | 1357 | FUSE_READDIRPLUS); |
1361 | } else { | 1358 | } else { |
1362 | fuse_read_fill(req, file, file->f_pos, PAGE_SIZE, | 1359 | fuse_read_fill(req, file, ctx->pos, PAGE_SIZE, |
1363 | FUSE_READDIR); | 1360 | FUSE_READDIR); |
1364 | } | 1361 | } |
1365 | fuse_request_send(fc, req); | 1362 | fuse_request_send(fc, req); |
@@ -1369,11 +1366,11 @@ static int fuse_readdir(struct file *file, void *dstbuf, filldir_t filldir) | |||
1369 | if (!err) { | 1366 | if (!err) { |
1370 | if (plus) { | 1367 | if (plus) { |
1371 | err = parse_dirplusfile(page_address(page), nbytes, | 1368 | err = parse_dirplusfile(page_address(page), nbytes, |
1372 | file, dstbuf, filldir, | 1369 | file, ctx, |
1373 | attr_version); | 1370 | attr_version); |
1374 | } else { | 1371 | } else { |
1375 | err = parse_dirfile(page_address(page), nbytes, file, | 1372 | err = parse_dirfile(page_address(page), nbytes, file, |
1376 | dstbuf, filldir); | 1373 | ctx); |
1377 | } | 1374 | } |
1378 | } | 1375 | } |
1379 | 1376 | ||
@@ -1886,7 +1883,7 @@ static const struct inode_operations fuse_dir_inode_operations = { | |||
1886 | static const struct file_operations fuse_dir_operations = { | 1883 | static const struct file_operations fuse_dir_operations = { |
1887 | .llseek = generic_file_llseek, | 1884 | .llseek = generic_file_llseek, |
1888 | .read = generic_read_dir, | 1885 | .read = generic_read_dir, |
1889 | .readdir = fuse_readdir, | 1886 | .iterate = fuse_readdir, |
1890 | .open = fuse_dir_open, | 1887 | .open = fuse_dir_open, |
1891 | .release = fuse_dir_release, | 1888 | .release = fuse_dir_release, |
1892 | .fsync = fuse_dir_fsync, | 1889 | .fsync = fuse_dir_fsync, |
diff --git a/fs/gfs2/dir.c b/fs/gfs2/dir.c index b631c9043460..e0449c10286a 100644 --- a/fs/gfs2/dir.c +++ b/fs/gfs2/dir.c | |||
@@ -1212,9 +1212,7 @@ static int compare_dents(const void *a, const void *b) | |||
1212 | /** | 1212 | /** |
1213 | * do_filldir_main - read out directory entries | 1213 | * do_filldir_main - read out directory entries |
1214 | * @dip: The GFS2 inode | 1214 | * @dip: The GFS2 inode |
1215 | * @offset: The offset in the file to read from | 1215 | * @ctx: what to feed the entries to |
1216 | * @opaque: opaque data to pass to filldir | ||
1217 | * @filldir: The function to pass entries to | ||
1218 | * @darr: an array of struct gfs2_dirent pointers to read | 1216 | * @darr: an array of struct gfs2_dirent pointers to read |
1219 | * @entries: the number of entries in darr | 1217 | * @entries: the number of entries in darr |
1220 | * @copied: pointer to int that's non-zero if a entry has been copied out | 1218 | * @copied: pointer to int that's non-zero if a entry has been copied out |
@@ -1224,11 +1222,10 @@ static int compare_dents(const void *a, const void *b) | |||
1224 | * the possibility that they will fall into different readdir buffers or | 1222 | * the possibility that they will fall into different readdir buffers or |
1225 | * that someone will want to seek to that location. | 1223 | * that someone will want to seek to that location. |
1226 | * | 1224 | * |
1227 | * Returns: errno, >0 on exception from filldir | 1225 | * Returns: errno, >0 if the actor tells you to stop |
1228 | */ | 1226 | */ |
1229 | 1227 | ||
1230 | static int do_filldir_main(struct gfs2_inode *dip, u64 *offset, | 1228 | static int do_filldir_main(struct gfs2_inode *dip, struct dir_context *ctx, |
1231 | void *opaque, filldir_t filldir, | ||
1232 | const struct gfs2_dirent **darr, u32 entries, | 1229 | const struct gfs2_dirent **darr, u32 entries, |
1233 | int *copied) | 1230 | int *copied) |
1234 | { | 1231 | { |
@@ -1236,7 +1233,6 @@ static int do_filldir_main(struct gfs2_inode *dip, u64 *offset, | |||
1236 | u64 off, off_next; | 1233 | u64 off, off_next; |
1237 | unsigned int x, y; | 1234 | unsigned int x, y; |
1238 | int run = 0; | 1235 | int run = 0; |
1239 | int error = 0; | ||
1240 | 1236 | ||
1241 | sort(darr, entries, sizeof(struct gfs2_dirent *), compare_dents, NULL); | 1237 | sort(darr, entries, sizeof(struct gfs2_dirent *), compare_dents, NULL); |
1242 | 1238 | ||
@@ -1253,9 +1249,9 @@ static int do_filldir_main(struct gfs2_inode *dip, u64 *offset, | |||
1253 | off_next = be32_to_cpu(dent_next->de_hash); | 1249 | off_next = be32_to_cpu(dent_next->de_hash); |
1254 | off_next = gfs2_disk_hash2offset(off_next); | 1250 | off_next = gfs2_disk_hash2offset(off_next); |
1255 | 1251 | ||
1256 | if (off < *offset) | 1252 | if (off < ctx->pos) |
1257 | continue; | 1253 | continue; |
1258 | *offset = off; | 1254 | ctx->pos = off; |
1259 | 1255 | ||
1260 | if (off_next == off) { | 1256 | if (off_next == off) { |
1261 | if (*copied && !run) | 1257 | if (*copied && !run) |
@@ -1264,26 +1260,25 @@ static int do_filldir_main(struct gfs2_inode *dip, u64 *offset, | |||
1264 | } else | 1260 | } else |
1265 | run = 0; | 1261 | run = 0; |
1266 | } else { | 1262 | } else { |
1267 | if (off < *offset) | 1263 | if (off < ctx->pos) |
1268 | continue; | 1264 | continue; |
1269 | *offset = off; | 1265 | ctx->pos = off; |
1270 | } | 1266 | } |
1271 | 1267 | ||
1272 | error = filldir(opaque, (const char *)(dent + 1), | 1268 | if (!dir_emit(ctx, (const char *)(dent + 1), |
1273 | be16_to_cpu(dent->de_name_len), | 1269 | be16_to_cpu(dent->de_name_len), |
1274 | off, be64_to_cpu(dent->de_inum.no_addr), | 1270 | be64_to_cpu(dent->de_inum.no_addr), |
1275 | be16_to_cpu(dent->de_type)); | 1271 | be16_to_cpu(dent->de_type))) |
1276 | if (error) | ||
1277 | return 1; | 1272 | return 1; |
1278 | 1273 | ||
1279 | *copied = 1; | 1274 | *copied = 1; |
1280 | } | 1275 | } |
1281 | 1276 | ||
1282 | /* Increment the *offset by one, so the next time we come into the | 1277 | /* Increment the ctx->pos by one, so the next time we come into the |
1283 | do_filldir fxn, we get the next entry instead of the last one in the | 1278 | do_filldir fxn, we get the next entry instead of the last one in the |
1284 | current leaf */ | 1279 | current leaf */ |
1285 | 1280 | ||
1286 | (*offset)++; | 1281 | ctx->pos++; |
1287 | 1282 | ||
1288 | return 0; | 1283 | return 0; |
1289 | } | 1284 | } |
@@ -1307,8 +1302,8 @@ static void gfs2_free_sort_buffer(void *ptr) | |||
1307 | kfree(ptr); | 1302 | kfree(ptr); |
1308 | } | 1303 | } |
1309 | 1304 | ||
1310 | static int gfs2_dir_read_leaf(struct inode *inode, u64 *offset, void *opaque, | 1305 | static int gfs2_dir_read_leaf(struct inode *inode, struct dir_context *ctx, |
1311 | filldir_t filldir, int *copied, unsigned *depth, | 1306 | int *copied, unsigned *depth, |
1312 | u64 leaf_no) | 1307 | u64 leaf_no) |
1313 | { | 1308 | { |
1314 | struct gfs2_inode *ip = GFS2_I(inode); | 1309 | struct gfs2_inode *ip = GFS2_I(inode); |
@@ -1386,8 +1381,7 @@ static int gfs2_dir_read_leaf(struct inode *inode, u64 *offset, void *opaque, | |||
1386 | } while(lfn); | 1381 | } while(lfn); |
1387 | 1382 | ||
1388 | BUG_ON(entries2 != entries); | 1383 | BUG_ON(entries2 != entries); |
1389 | error = do_filldir_main(ip, offset, opaque, filldir, darr, | 1384 | error = do_filldir_main(ip, ctx, darr, entries, copied); |
1390 | entries, copied); | ||
1391 | out_free: | 1385 | out_free: |
1392 | for(i = 0; i < leaf; i++) | 1386 | for(i = 0; i < leaf; i++) |
1393 | brelse(larr[i]); | 1387 | brelse(larr[i]); |
@@ -1446,15 +1440,13 @@ static void gfs2_dir_readahead(struct inode *inode, unsigned hsize, u32 index, | |||
1446 | /** | 1440 | /** |
1447 | * dir_e_read - Reads the entries from a directory into a filldir buffer | 1441 | * dir_e_read - Reads the entries from a directory into a filldir buffer |
1448 | * @dip: dinode pointer | 1442 | * @dip: dinode pointer |
1449 | * @offset: the hash of the last entry read shifted to the right once | 1443 | * @ctx: actor to feed the entries to |
1450 | * @opaque: buffer for the filldir function to fill | ||
1451 | * @filldir: points to the filldir function to use | ||
1452 | * | 1444 | * |
1453 | * Returns: errno | 1445 | * Returns: errno |
1454 | */ | 1446 | */ |
1455 | 1447 | ||
1456 | static int dir_e_read(struct inode *inode, u64 *offset, void *opaque, | 1448 | static int dir_e_read(struct inode *inode, struct dir_context *ctx, |
1457 | filldir_t filldir, struct file_ra_state *f_ra) | 1449 | struct file_ra_state *f_ra) |
1458 | { | 1450 | { |
1459 | struct gfs2_inode *dip = GFS2_I(inode); | 1451 | struct gfs2_inode *dip = GFS2_I(inode); |
1460 | u32 hsize, len = 0; | 1452 | u32 hsize, len = 0; |
@@ -1465,7 +1457,7 @@ static int dir_e_read(struct inode *inode, u64 *offset, void *opaque, | |||
1465 | unsigned depth = 0; | 1457 | unsigned depth = 0; |
1466 | 1458 | ||
1467 | hsize = 1 << dip->i_depth; | 1459 | hsize = 1 << dip->i_depth; |
1468 | hash = gfs2_dir_offset2hash(*offset); | 1460 | hash = gfs2_dir_offset2hash(ctx->pos); |
1469 | index = hash >> (32 - dip->i_depth); | 1461 | index = hash >> (32 - dip->i_depth); |
1470 | 1462 | ||
1471 | if (dip->i_hash_cache == NULL) | 1463 | if (dip->i_hash_cache == NULL) |
@@ -1477,7 +1469,7 @@ static int dir_e_read(struct inode *inode, u64 *offset, void *opaque, | |||
1477 | gfs2_dir_readahead(inode, hsize, index, f_ra); | 1469 | gfs2_dir_readahead(inode, hsize, index, f_ra); |
1478 | 1470 | ||
1479 | while (index < hsize) { | 1471 | while (index < hsize) { |
1480 | error = gfs2_dir_read_leaf(inode, offset, opaque, filldir, | 1472 | error = gfs2_dir_read_leaf(inode, ctx, |
1481 | &copied, &depth, | 1473 | &copied, &depth, |
1482 | be64_to_cpu(lp[index])); | 1474 | be64_to_cpu(lp[index])); |
1483 | if (error) | 1475 | if (error) |
@@ -1492,8 +1484,8 @@ static int dir_e_read(struct inode *inode, u64 *offset, void *opaque, | |||
1492 | return error; | 1484 | return error; |
1493 | } | 1485 | } |
1494 | 1486 | ||
1495 | int gfs2_dir_read(struct inode *inode, u64 *offset, void *opaque, | 1487 | int gfs2_dir_read(struct inode *inode, struct dir_context *ctx, |
1496 | filldir_t filldir, struct file_ra_state *f_ra) | 1488 | struct file_ra_state *f_ra) |
1497 | { | 1489 | { |
1498 | struct gfs2_inode *dip = GFS2_I(inode); | 1490 | struct gfs2_inode *dip = GFS2_I(inode); |
1499 | struct gfs2_sbd *sdp = GFS2_SB(inode); | 1491 | struct gfs2_sbd *sdp = GFS2_SB(inode); |
@@ -1507,7 +1499,7 @@ int gfs2_dir_read(struct inode *inode, u64 *offset, void *opaque, | |||
1507 | return 0; | 1499 | return 0; |
1508 | 1500 | ||
1509 | if (dip->i_diskflags & GFS2_DIF_EXHASH) | 1501 | if (dip->i_diskflags & GFS2_DIF_EXHASH) |
1510 | return dir_e_read(inode, offset, opaque, filldir, f_ra); | 1502 | return dir_e_read(inode, ctx, f_ra); |
1511 | 1503 | ||
1512 | if (!gfs2_is_stuffed(dip)) { | 1504 | if (!gfs2_is_stuffed(dip)) { |
1513 | gfs2_consist_inode(dip); | 1505 | gfs2_consist_inode(dip); |
@@ -1539,7 +1531,7 @@ int gfs2_dir_read(struct inode *inode, u64 *offset, void *opaque, | |||
1539 | error = -EIO; | 1531 | error = -EIO; |
1540 | goto out; | 1532 | goto out; |
1541 | } | 1533 | } |
1542 | error = do_filldir_main(dip, offset, opaque, filldir, darr, | 1534 | error = do_filldir_main(dip, ctx, darr, |
1543 | dip->i_entries, &copied); | 1535 | dip->i_entries, &copied); |
1544 | out: | 1536 | out: |
1545 | kfree(darr); | 1537 | kfree(darr); |
diff --git a/fs/gfs2/dir.h b/fs/gfs2/dir.h index 98c960beab35..ba9000bc1397 100644 --- a/fs/gfs2/dir.h +++ b/fs/gfs2/dir.h | |||
@@ -24,8 +24,8 @@ extern int gfs2_dir_check(struct inode *dir, const struct qstr *filename, | |||
24 | extern int gfs2_dir_add(struct inode *inode, const struct qstr *filename, | 24 | extern int gfs2_dir_add(struct inode *inode, const struct qstr *filename, |
25 | const struct gfs2_inode *ip); | 25 | const struct gfs2_inode *ip); |
26 | extern int gfs2_dir_del(struct gfs2_inode *dip, const struct dentry *dentry); | 26 | extern int gfs2_dir_del(struct gfs2_inode *dip, const struct dentry *dentry); |
27 | extern int gfs2_dir_read(struct inode *inode, u64 *offset, void *opaque, | 27 | extern int gfs2_dir_read(struct inode *inode, struct dir_context *ctx, |
28 | filldir_t filldir, struct file_ra_state *f_ra); | 28 | struct file_ra_state *f_ra); |
29 | extern int gfs2_dir_mvino(struct gfs2_inode *dip, const struct qstr *filename, | 29 | extern int gfs2_dir_mvino(struct gfs2_inode *dip, const struct qstr *filename, |
30 | const struct gfs2_inode *nip, unsigned int new_type); | 30 | const struct gfs2_inode *nip, unsigned int new_type); |
31 | 31 | ||
diff --git a/fs/gfs2/export.c b/fs/gfs2/export.c index 9973df4ff565..8b9b3775e2e7 100644 --- a/fs/gfs2/export.c +++ b/fs/gfs2/export.c | |||
@@ -64,6 +64,7 @@ static int gfs2_encode_fh(struct inode *inode, __u32 *p, int *len, | |||
64 | } | 64 | } |
65 | 65 | ||
66 | struct get_name_filldir { | 66 | struct get_name_filldir { |
67 | struct dir_context ctx; | ||
67 | struct gfs2_inum_host inum; | 68 | struct gfs2_inum_host inum; |
68 | char *name; | 69 | char *name; |
69 | }; | 70 | }; |
@@ -88,9 +89,11 @@ static int gfs2_get_name(struct dentry *parent, char *name, | |||
88 | struct inode *dir = parent->d_inode; | 89 | struct inode *dir = parent->d_inode; |
89 | struct inode *inode = child->d_inode; | 90 | struct inode *inode = child->d_inode; |
90 | struct gfs2_inode *dip, *ip; | 91 | struct gfs2_inode *dip, *ip; |
91 | struct get_name_filldir gnfd; | 92 | struct get_name_filldir gnfd = { |
93 | .ctx.actor = get_name_filldir, | ||
94 | .name = name | ||
95 | }; | ||
92 | struct gfs2_holder gh; | 96 | struct gfs2_holder gh; |
93 | u64 offset = 0; | ||
94 | int error; | 97 | int error; |
95 | struct file_ra_state f_ra = { .start = 0 }; | 98 | struct file_ra_state f_ra = { .start = 0 }; |
96 | 99 | ||
@@ -106,13 +109,12 @@ static int gfs2_get_name(struct dentry *parent, char *name, | |||
106 | *name = 0; | 109 | *name = 0; |
107 | gnfd.inum.no_addr = ip->i_no_addr; | 110 | gnfd.inum.no_addr = ip->i_no_addr; |
108 | gnfd.inum.no_formal_ino = ip->i_no_formal_ino; | 111 | gnfd.inum.no_formal_ino = ip->i_no_formal_ino; |
109 | gnfd.name = name; | ||
110 | 112 | ||
111 | error = gfs2_glock_nq_init(dip->i_gl, LM_ST_SHARED, 0, &gh); | 113 | error = gfs2_glock_nq_init(dip->i_gl, LM_ST_SHARED, 0, &gh); |
112 | if (error) | 114 | if (error) |
113 | return error; | 115 | return error; |
114 | 116 | ||
115 | error = gfs2_dir_read(dir, &offset, &gnfd, get_name_filldir, &f_ra); | 117 | error = gfs2_dir_read(dir, &gnfd.ctx, &f_ra); |
116 | 118 | ||
117 | gfs2_glock_dq_uninit(&gh); | 119 | gfs2_glock_dq_uninit(&gh); |
118 | 120 | ||
diff --git a/fs/gfs2/file.c b/fs/gfs2/file.c index ad0dc38d87ab..b3333371aebb 100644 --- a/fs/gfs2/file.c +++ b/fs/gfs2/file.c | |||
@@ -82,35 +82,28 @@ static loff_t gfs2_llseek(struct file *file, loff_t offset, int whence) | |||
82 | } | 82 | } |
83 | 83 | ||
84 | /** | 84 | /** |
85 | * gfs2_readdir - Read directory entries from a directory | 85 | * gfs2_readdir - Iterator for a directory |
86 | * @file: The directory to read from | 86 | * @file: The directory to read from |
87 | * @dirent: Buffer for dirents | 87 | * @ctx: What to feed directory entries to |
88 | * @filldir: Function used to do the copying | ||
89 | * | 88 | * |
90 | * Returns: errno | 89 | * Returns: errno |
91 | */ | 90 | */ |
92 | 91 | ||
93 | static int gfs2_readdir(struct file *file, void *dirent, filldir_t filldir) | 92 | static int gfs2_readdir(struct file *file, struct dir_context *ctx) |
94 | { | 93 | { |
95 | struct inode *dir = file->f_mapping->host; | 94 | struct inode *dir = file->f_mapping->host; |
96 | struct gfs2_inode *dip = GFS2_I(dir); | 95 | struct gfs2_inode *dip = GFS2_I(dir); |
97 | struct gfs2_holder d_gh; | 96 | struct gfs2_holder d_gh; |
98 | u64 offset = file->f_pos; | ||
99 | int error; | 97 | int error; |
100 | 98 | ||
101 | gfs2_holder_init(dip->i_gl, LM_ST_SHARED, 0, &d_gh); | 99 | error = gfs2_glock_nq_init(dip->i_gl, LM_ST_SHARED, 0, &d_gh); |
102 | error = gfs2_glock_nq(&d_gh); | 100 | if (error) |
103 | if (error) { | ||
104 | gfs2_holder_uninit(&d_gh); | ||
105 | return error; | 101 | return error; |
106 | } | ||
107 | 102 | ||
108 | error = gfs2_dir_read(dir, &offset, dirent, filldir, &file->f_ra); | 103 | error = gfs2_dir_read(dir, ctx, &file->f_ra); |
109 | 104 | ||
110 | gfs2_glock_dq_uninit(&d_gh); | 105 | gfs2_glock_dq_uninit(&d_gh); |
111 | 106 | ||
112 | file->f_pos = offset; | ||
113 | |||
114 | return error; | 107 | return error; |
115 | } | 108 | } |
116 | 109 | ||
@@ -1048,7 +1041,7 @@ const struct file_operations gfs2_file_fops = { | |||
1048 | }; | 1041 | }; |
1049 | 1042 | ||
1050 | const struct file_operations gfs2_dir_fops = { | 1043 | const struct file_operations gfs2_dir_fops = { |
1051 | .readdir = gfs2_readdir, | 1044 | .iterate = gfs2_readdir, |
1052 | .unlocked_ioctl = gfs2_ioctl, | 1045 | .unlocked_ioctl = gfs2_ioctl, |
1053 | .open = gfs2_open, | 1046 | .open = gfs2_open, |
1054 | .release = gfs2_release, | 1047 | .release = gfs2_release, |
@@ -1078,7 +1071,7 @@ const struct file_operations gfs2_file_fops_nolock = { | |||
1078 | }; | 1071 | }; |
1079 | 1072 | ||
1080 | const struct file_operations gfs2_dir_fops_nolock = { | 1073 | const struct file_operations gfs2_dir_fops_nolock = { |
1081 | .readdir = gfs2_readdir, | 1074 | .iterate = gfs2_readdir, |
1082 | .unlocked_ioctl = gfs2_ioctl, | 1075 | .unlocked_ioctl = gfs2_ioctl, |
1083 | .open = gfs2_open, | 1076 | .open = gfs2_open, |
1084 | .release = gfs2_release, | 1077 | .release = gfs2_release, |
diff --git a/fs/hfs/dir.c b/fs/hfs/dir.c index e0101b6fb0d7..145566851e7a 100644 --- a/fs/hfs/dir.c +++ b/fs/hfs/dir.c | |||
@@ -51,9 +51,9 @@ done: | |||
51 | /* | 51 | /* |
52 | * hfs_readdir | 52 | * hfs_readdir |
53 | */ | 53 | */ |
54 | static int hfs_readdir(struct file *filp, void *dirent, filldir_t filldir) | 54 | static int hfs_readdir(struct file *file, struct dir_context *ctx) |
55 | { | 55 | { |
56 | struct inode *inode = file_inode(filp); | 56 | struct inode *inode = file_inode(file); |
57 | struct super_block *sb = inode->i_sb; | 57 | struct super_block *sb = inode->i_sb; |
58 | int len, err; | 58 | int len, err; |
59 | char strbuf[HFS_MAX_NAMELEN]; | 59 | char strbuf[HFS_MAX_NAMELEN]; |
@@ -62,7 +62,7 @@ static int hfs_readdir(struct file *filp, void *dirent, filldir_t filldir) | |||
62 | struct hfs_readdir_data *rd; | 62 | struct hfs_readdir_data *rd; |
63 | u16 type; | 63 | u16 type; |
64 | 64 | ||
65 | if (filp->f_pos >= inode->i_size) | 65 | if (ctx->pos >= inode->i_size) |
66 | return 0; | 66 | return 0; |
67 | 67 | ||
68 | err = hfs_find_init(HFS_SB(sb)->cat_tree, &fd); | 68 | err = hfs_find_init(HFS_SB(sb)->cat_tree, &fd); |
@@ -73,14 +73,13 @@ static int hfs_readdir(struct file *filp, void *dirent, filldir_t filldir) | |||
73 | if (err) | 73 | if (err) |
74 | goto out; | 74 | goto out; |
75 | 75 | ||
76 | switch ((u32)filp->f_pos) { | 76 | if (ctx->pos == 0) { |
77 | case 0: | ||
78 | /* This is completely artificial... */ | 77 | /* This is completely artificial... */ |
79 | if (filldir(dirent, ".", 1, 0, inode->i_ino, DT_DIR)) | 78 | if (!dir_emit_dot(file, ctx)) |
80 | goto out; | 79 | goto out; |
81 | filp->f_pos++; | 80 | ctx->pos = 1; |
82 | /* fall through */ | 81 | } |
83 | case 1: | 82 | if (ctx->pos == 1) { |
84 | if (fd.entrylength > sizeof(entry) || fd.entrylength < 0) { | 83 | if (fd.entrylength > sizeof(entry) || fd.entrylength < 0) { |
85 | err = -EIO; | 84 | err = -EIO; |
86 | goto out; | 85 | goto out; |
@@ -97,18 +96,16 @@ static int hfs_readdir(struct file *filp, void *dirent, filldir_t filldir) | |||
97 | // err = -EIO; | 96 | // err = -EIO; |
98 | // goto out; | 97 | // goto out; |
99 | //} | 98 | //} |
100 | if (filldir(dirent, "..", 2, 1, | 99 | if (!dir_emit(ctx, "..", 2, |
101 | be32_to_cpu(entry.thread.ParID), DT_DIR)) | 100 | be32_to_cpu(entry.thread.ParID), DT_DIR)) |
102 | goto out; | 101 | goto out; |
103 | filp->f_pos++; | 102 | ctx->pos = 2; |
104 | /* fall through */ | ||
105 | default: | ||
106 | if (filp->f_pos >= inode->i_size) | ||
107 | goto out; | ||
108 | err = hfs_brec_goto(&fd, filp->f_pos - 1); | ||
109 | if (err) | ||
110 | goto out; | ||
111 | } | 103 | } |
104 | if (ctx->pos >= inode->i_size) | ||
105 | goto out; | ||
106 | err = hfs_brec_goto(&fd, ctx->pos - 1); | ||
107 | if (err) | ||
108 | goto out; | ||
112 | 109 | ||
113 | for (;;) { | 110 | for (;;) { |
114 | if (be32_to_cpu(fd.key->cat.ParID) != inode->i_ino) { | 111 | if (be32_to_cpu(fd.key->cat.ParID) != inode->i_ino) { |
@@ -131,7 +128,7 @@ static int hfs_readdir(struct file *filp, void *dirent, filldir_t filldir) | |||
131 | err = -EIO; | 128 | err = -EIO; |
132 | goto out; | 129 | goto out; |
133 | } | 130 | } |
134 | if (filldir(dirent, strbuf, len, filp->f_pos, | 131 | if (!dir_emit(ctx, strbuf, len, |
135 | be32_to_cpu(entry.dir.DirID), DT_DIR)) | 132 | be32_to_cpu(entry.dir.DirID), DT_DIR)) |
136 | break; | 133 | break; |
137 | } else if (type == HFS_CDR_FIL) { | 134 | } else if (type == HFS_CDR_FIL) { |
@@ -140,7 +137,7 @@ static int hfs_readdir(struct file *filp, void *dirent, filldir_t filldir) | |||
140 | err = -EIO; | 137 | err = -EIO; |
141 | goto out; | 138 | goto out; |
142 | } | 139 | } |
143 | if (filldir(dirent, strbuf, len, filp->f_pos, | 140 | if (!dir_emit(ctx, strbuf, len, |
144 | be32_to_cpu(entry.file.FlNum), DT_REG)) | 141 | be32_to_cpu(entry.file.FlNum), DT_REG)) |
145 | break; | 142 | break; |
146 | } else { | 143 | } else { |
@@ -148,22 +145,22 @@ static int hfs_readdir(struct file *filp, void *dirent, filldir_t filldir) | |||
148 | err = -EIO; | 145 | err = -EIO; |
149 | goto out; | 146 | goto out; |
150 | } | 147 | } |
151 | filp->f_pos++; | 148 | ctx->pos++; |
152 | if (filp->f_pos >= inode->i_size) | 149 | if (ctx->pos >= inode->i_size) |
153 | goto out; | 150 | goto out; |
154 | err = hfs_brec_goto(&fd, 1); | 151 | err = hfs_brec_goto(&fd, 1); |
155 | if (err) | 152 | if (err) |
156 | goto out; | 153 | goto out; |
157 | } | 154 | } |
158 | rd = filp->private_data; | 155 | rd = file->private_data; |
159 | if (!rd) { | 156 | if (!rd) { |
160 | rd = kmalloc(sizeof(struct hfs_readdir_data), GFP_KERNEL); | 157 | rd = kmalloc(sizeof(struct hfs_readdir_data), GFP_KERNEL); |
161 | if (!rd) { | 158 | if (!rd) { |
162 | err = -ENOMEM; | 159 | err = -ENOMEM; |
163 | goto out; | 160 | goto out; |
164 | } | 161 | } |
165 | filp->private_data = rd; | 162 | file->private_data = rd; |
166 | rd->file = filp; | 163 | rd->file = file; |
167 | list_add(&rd->list, &HFS_I(inode)->open_dir_list); | 164 | list_add(&rd->list, &HFS_I(inode)->open_dir_list); |
168 | } | 165 | } |
169 | memcpy(&rd->key, &fd.key, sizeof(struct hfs_cat_key)); | 166 | memcpy(&rd->key, &fd.key, sizeof(struct hfs_cat_key)); |
@@ -306,7 +303,7 @@ static int hfs_rename(struct inode *old_dir, struct dentry *old_dentry, | |||
306 | 303 | ||
307 | const struct file_operations hfs_dir_operations = { | 304 | const struct file_operations hfs_dir_operations = { |
308 | .read = generic_read_dir, | 305 | .read = generic_read_dir, |
309 | .readdir = hfs_readdir, | 306 | .iterate = hfs_readdir, |
310 | .llseek = generic_file_llseek, | 307 | .llseek = generic_file_llseek, |
311 | .release = hfs_dir_release, | 308 | .release = hfs_dir_release, |
312 | }; | 309 | }; |
diff --git a/fs/hfsplus/dir.c b/fs/hfsplus/dir.c index a37ac934732f..d8ce4bd17fc5 100644 --- a/fs/hfsplus/dir.c +++ b/fs/hfsplus/dir.c | |||
@@ -121,9 +121,9 @@ fail: | |||
121 | return ERR_PTR(err); | 121 | return ERR_PTR(err); |
122 | } | 122 | } |
123 | 123 | ||
124 | static int hfsplus_readdir(struct file *filp, void *dirent, filldir_t filldir) | 124 | static int hfsplus_readdir(struct file *file, struct dir_context *ctx) |
125 | { | 125 | { |
126 | struct inode *inode = file_inode(filp); | 126 | struct inode *inode = file_inode(file); |
127 | struct super_block *sb = inode->i_sb; | 127 | struct super_block *sb = inode->i_sb; |
128 | int len, err; | 128 | int len, err; |
129 | char strbuf[HFSPLUS_MAX_STRLEN + 1]; | 129 | char strbuf[HFSPLUS_MAX_STRLEN + 1]; |
@@ -132,7 +132,7 @@ static int hfsplus_readdir(struct file *filp, void *dirent, filldir_t filldir) | |||
132 | struct hfsplus_readdir_data *rd; | 132 | struct hfsplus_readdir_data *rd; |
133 | u16 type; | 133 | u16 type; |
134 | 134 | ||
135 | if (filp->f_pos >= inode->i_size) | 135 | if (file->f_pos >= inode->i_size) |
136 | return 0; | 136 | return 0; |
137 | 137 | ||
138 | err = hfs_find_init(HFSPLUS_SB(sb)->cat_tree, &fd); | 138 | err = hfs_find_init(HFSPLUS_SB(sb)->cat_tree, &fd); |
@@ -143,14 +143,13 @@ static int hfsplus_readdir(struct file *filp, void *dirent, filldir_t filldir) | |||
143 | if (err) | 143 | if (err) |
144 | goto out; | 144 | goto out; |
145 | 145 | ||
146 | switch ((u32)filp->f_pos) { | 146 | if (ctx->pos == 0) { |
147 | case 0: | ||
148 | /* This is completely artificial... */ | 147 | /* This is completely artificial... */ |
149 | if (filldir(dirent, ".", 1, 0, inode->i_ino, DT_DIR)) | 148 | if (!dir_emit_dot(file, ctx)) |
150 | goto out; | 149 | goto out; |
151 | filp->f_pos++; | 150 | ctx->pos = 1; |
152 | /* fall through */ | 151 | } |
153 | case 1: | 152 | if (ctx->pos == 1) { |
154 | if (fd.entrylength > sizeof(entry) || fd.entrylength < 0) { | 153 | if (fd.entrylength > sizeof(entry) || fd.entrylength < 0) { |
155 | err = -EIO; | 154 | err = -EIO; |
156 | goto out; | 155 | goto out; |
@@ -168,19 +167,16 @@ static int hfsplus_readdir(struct file *filp, void *dirent, filldir_t filldir) | |||
168 | err = -EIO; | 167 | err = -EIO; |
169 | goto out; | 168 | goto out; |
170 | } | 169 | } |
171 | if (filldir(dirent, "..", 2, 1, | 170 | if (!dir_emit(ctx, "..", 2, |
172 | be32_to_cpu(entry.thread.parentID), DT_DIR)) | 171 | be32_to_cpu(entry.thread.parentID), DT_DIR)) |
173 | goto out; | 172 | goto out; |
174 | filp->f_pos++; | 173 | ctx->pos = 2; |
175 | /* fall through */ | ||
176 | default: | ||
177 | if (filp->f_pos >= inode->i_size) | ||
178 | goto out; | ||
179 | err = hfs_brec_goto(&fd, filp->f_pos - 1); | ||
180 | if (err) | ||
181 | goto out; | ||
182 | } | 174 | } |
183 | 175 | if (ctx->pos >= inode->i_size) | |
176 | goto out; | ||
177 | err = hfs_brec_goto(&fd, ctx->pos - 1); | ||
178 | if (err) | ||
179 | goto out; | ||
184 | for (;;) { | 180 | for (;;) { |
185 | if (be32_to_cpu(fd.key->cat.parent) != inode->i_ino) { | 181 | if (be32_to_cpu(fd.key->cat.parent) != inode->i_ino) { |
186 | pr_err("walked past end of dir\n"); | 182 | pr_err("walked past end of dir\n"); |
@@ -211,7 +207,7 @@ static int hfsplus_readdir(struct file *filp, void *dirent, filldir_t filldir) | |||
211 | HFSPLUS_SB(sb)->hidden_dir->i_ino == | 207 | HFSPLUS_SB(sb)->hidden_dir->i_ino == |
212 | be32_to_cpu(entry.folder.id)) | 208 | be32_to_cpu(entry.folder.id)) |
213 | goto next; | 209 | goto next; |
214 | if (filldir(dirent, strbuf, len, filp->f_pos, | 210 | if (!dir_emit(ctx, strbuf, len, |
215 | be32_to_cpu(entry.folder.id), DT_DIR)) | 211 | be32_to_cpu(entry.folder.id), DT_DIR)) |
216 | break; | 212 | break; |
217 | } else if (type == HFSPLUS_FILE) { | 213 | } else if (type == HFSPLUS_FILE) { |
@@ -220,7 +216,7 @@ static int hfsplus_readdir(struct file *filp, void *dirent, filldir_t filldir) | |||
220 | err = -EIO; | 216 | err = -EIO; |
221 | goto out; | 217 | goto out; |
222 | } | 218 | } |
223 | if (filldir(dirent, strbuf, len, filp->f_pos, | 219 | if (!dir_emit(ctx, strbuf, len, |
224 | be32_to_cpu(entry.file.id), DT_REG)) | 220 | be32_to_cpu(entry.file.id), DT_REG)) |
225 | break; | 221 | break; |
226 | } else { | 222 | } else { |
@@ -229,22 +225,22 @@ static int hfsplus_readdir(struct file *filp, void *dirent, filldir_t filldir) | |||
229 | goto out; | 225 | goto out; |
230 | } | 226 | } |
231 | next: | 227 | next: |
232 | filp->f_pos++; | 228 | ctx->pos++; |
233 | if (filp->f_pos >= inode->i_size) | 229 | if (ctx->pos >= inode->i_size) |
234 | goto out; | 230 | goto out; |
235 | err = hfs_brec_goto(&fd, 1); | 231 | err = hfs_brec_goto(&fd, 1); |
236 | if (err) | 232 | if (err) |
237 | goto out; | 233 | goto out; |
238 | } | 234 | } |
239 | rd = filp->private_data; | 235 | rd = file->private_data; |
240 | if (!rd) { | 236 | if (!rd) { |
241 | rd = kmalloc(sizeof(struct hfsplus_readdir_data), GFP_KERNEL); | 237 | rd = kmalloc(sizeof(struct hfsplus_readdir_data), GFP_KERNEL); |
242 | if (!rd) { | 238 | if (!rd) { |
243 | err = -ENOMEM; | 239 | err = -ENOMEM; |
244 | goto out; | 240 | goto out; |
245 | } | 241 | } |
246 | filp->private_data = rd; | 242 | file->private_data = rd; |
247 | rd->file = filp; | 243 | rd->file = file; |
248 | list_add(&rd->list, &HFSPLUS_I(inode)->open_dir_list); | 244 | list_add(&rd->list, &HFSPLUS_I(inode)->open_dir_list); |
249 | } | 245 | } |
250 | memcpy(&rd->key, fd.key, sizeof(struct hfsplus_cat_key)); | 246 | memcpy(&rd->key, fd.key, sizeof(struct hfsplus_cat_key)); |
@@ -538,7 +534,7 @@ const struct inode_operations hfsplus_dir_inode_operations = { | |||
538 | const struct file_operations hfsplus_dir_operations = { | 534 | const struct file_operations hfsplus_dir_operations = { |
539 | .fsync = hfsplus_file_fsync, | 535 | .fsync = hfsplus_file_fsync, |
540 | .read = generic_read_dir, | 536 | .read = generic_read_dir, |
541 | .readdir = hfsplus_readdir, | 537 | .iterate = hfsplus_readdir, |
542 | .unlocked_ioctl = hfsplus_ioctl, | 538 | .unlocked_ioctl = hfsplus_ioctl, |
543 | .llseek = generic_file_llseek, | 539 | .llseek = generic_file_llseek, |
544 | .release = hfsplus_dir_release, | 540 | .release = hfsplus_dir_release, |
diff --git a/fs/hostfs/hostfs_kern.c b/fs/hostfs/hostfs_kern.c index 32f35f187989..cddb05217512 100644 --- a/fs/hostfs/hostfs_kern.c +++ b/fs/hostfs/hostfs_kern.c | |||
@@ -277,7 +277,7 @@ static const struct super_operations hostfs_sbops = { | |||
277 | .show_options = hostfs_show_options, | 277 | .show_options = hostfs_show_options, |
278 | }; | 278 | }; |
279 | 279 | ||
280 | int hostfs_readdir(struct file *file, void *ent, filldir_t filldir) | 280 | int hostfs_readdir(struct file *file, struct dir_context *ctx) |
281 | { | 281 | { |
282 | void *dir; | 282 | void *dir; |
283 | char *name; | 283 | char *name; |
@@ -292,12 +292,11 @@ int hostfs_readdir(struct file *file, void *ent, filldir_t filldir) | |||
292 | __putname(name); | 292 | __putname(name); |
293 | if (dir == NULL) | 293 | if (dir == NULL) |
294 | return -error; | 294 | return -error; |
295 | next = file->f_pos; | 295 | next = ctx->pos; |
296 | while ((name = read_dir(dir, &next, &ino, &len, &type)) != NULL) { | 296 | while ((name = read_dir(dir, &next, &ino, &len, &type)) != NULL) { |
297 | error = (*filldir)(ent, name, len, file->f_pos, | 297 | if (!dir_emit(ctx, name, len, ino, type)) |
298 | ino, type); | 298 | break; |
299 | if (error) break; | 299 | ctx->pos = next; |
300 | file->f_pos = next; | ||
301 | } | 300 | } |
302 | close_dir(dir); | 301 | close_dir(dir); |
303 | return 0; | 302 | return 0; |
@@ -393,7 +392,7 @@ static const struct file_operations hostfs_file_fops = { | |||
393 | 392 | ||
394 | static const struct file_operations hostfs_dir_fops = { | 393 | static const struct file_operations hostfs_dir_fops = { |
395 | .llseek = generic_file_llseek, | 394 | .llseek = generic_file_llseek, |
396 | .readdir = hostfs_readdir, | 395 | .iterate = hostfs_readdir, |
397 | .read = generic_read_dir, | 396 | .read = generic_read_dir, |
398 | }; | 397 | }; |
399 | 398 | ||
diff --git a/fs/hpfs/dir.c b/fs/hpfs/dir.c index 834ac13c04b7..292b1acb9b81 100644 --- a/fs/hpfs/dir.c +++ b/fs/hpfs/dir.c | |||
@@ -57,14 +57,14 @@ fail: | |||
57 | return -ESPIPE; | 57 | return -ESPIPE; |
58 | } | 58 | } |
59 | 59 | ||
60 | static int hpfs_readdir(struct file *filp, void *dirent, filldir_t filldir) | 60 | static int hpfs_readdir(struct file *file, struct dir_context *ctx) |
61 | { | 61 | { |
62 | struct inode *inode = file_inode(filp); | 62 | struct inode *inode = file_inode(file); |
63 | struct hpfs_inode_info *hpfs_inode = hpfs_i(inode); | 63 | struct hpfs_inode_info *hpfs_inode = hpfs_i(inode); |
64 | struct quad_buffer_head qbh; | 64 | struct quad_buffer_head qbh; |
65 | struct hpfs_dirent *de; | 65 | struct hpfs_dirent *de; |
66 | int lc; | 66 | int lc; |
67 | long old_pos; | 67 | loff_t next_pos; |
68 | unsigned char *tempname; | 68 | unsigned char *tempname; |
69 | int c1, c2 = 0; | 69 | int c1, c2 = 0; |
70 | int ret = 0; | 70 | int ret = 0; |
@@ -105,11 +105,11 @@ static int hpfs_readdir(struct file *filp, void *dirent, filldir_t filldir) | |||
105 | } | 105 | } |
106 | } | 106 | } |
107 | lc = hpfs_sb(inode->i_sb)->sb_lowercase; | 107 | lc = hpfs_sb(inode->i_sb)->sb_lowercase; |
108 | if (filp->f_pos == 12) { /* diff -r requires this (note, that diff -r */ | 108 | if (ctx->pos == 12) { /* diff -r requires this (note, that diff -r */ |
109 | filp->f_pos = 13; /* also fails on msdos filesystem in 2.0) */ | 109 | ctx->pos = 13; /* also fails on msdos filesystem in 2.0) */ |
110 | goto out; | 110 | goto out; |
111 | } | 111 | } |
112 | if (filp->f_pos == 13) { | 112 | if (ctx->pos == 13) { |
113 | ret = -ENOENT; | 113 | ret = -ENOENT; |
114 | goto out; | 114 | goto out; |
115 | } | 115 | } |
@@ -120,33 +120,34 @@ static int hpfs_readdir(struct file *filp, void *dirent, filldir_t filldir) | |||
120 | accepted by filldir, but what can I do? | 120 | accepted by filldir, but what can I do? |
121 | maybe killall -9 ls helps */ | 121 | maybe killall -9 ls helps */ |
122 | if (hpfs_sb(inode->i_sb)->sb_chk) | 122 | if (hpfs_sb(inode->i_sb)->sb_chk) |
123 | if (hpfs_stop_cycles(inode->i_sb, filp->f_pos, &c1, &c2, "hpfs_readdir")) { | 123 | if (hpfs_stop_cycles(inode->i_sb, ctx->pos, &c1, &c2, "hpfs_readdir")) { |
124 | ret = -EFSERROR; | 124 | ret = -EFSERROR; |
125 | goto out; | 125 | goto out; |
126 | } | 126 | } |
127 | if (filp->f_pos == 12) | 127 | if (ctx->pos == 12) |
128 | goto out; | 128 | goto out; |
129 | if (filp->f_pos == 3 || filp->f_pos == 4 || filp->f_pos == 5) { | 129 | if (ctx->pos == 3 || ctx->pos == 4 || ctx->pos == 5) { |
130 | printk("HPFS: warning: pos==%d\n",(int)filp->f_pos); | 130 | printk("HPFS: warning: pos==%d\n",(int)ctx->pos); |
131 | goto out; | 131 | goto out; |
132 | } | 132 | } |
133 | if (filp->f_pos == 0) { | 133 | if (ctx->pos == 0) { |
134 | if (filldir(dirent, ".", 1, filp->f_pos, inode->i_ino, DT_DIR) < 0) | 134 | if (!dir_emit_dot(file, ctx)) |
135 | goto out; | 135 | goto out; |
136 | filp->f_pos = 11; | 136 | ctx->pos = 11; |
137 | } | 137 | } |
138 | if (filp->f_pos == 11) { | 138 | if (ctx->pos == 11) { |
139 | if (filldir(dirent, "..", 2, filp->f_pos, hpfs_inode->i_parent_dir, DT_DIR) < 0) | 139 | if (!dir_emit(ctx, "..", 2, hpfs_inode->i_parent_dir, DT_DIR)) |
140 | goto out; | 140 | goto out; |
141 | filp->f_pos = 1; | 141 | ctx->pos = 1; |
142 | } | 142 | } |
143 | if (filp->f_pos == 1) { | 143 | if (ctx->pos == 1) { |
144 | filp->f_pos = ((loff_t) hpfs_de_as_down_as_possible(inode->i_sb, hpfs_inode->i_dno) << 4) + 1; | 144 | ctx->pos = ((loff_t) hpfs_de_as_down_as_possible(inode->i_sb, hpfs_inode->i_dno) << 4) + 1; |
145 | hpfs_add_pos(inode, &filp->f_pos); | 145 | hpfs_add_pos(inode, &file->f_pos); |
146 | filp->f_version = inode->i_version; | 146 | file->f_version = inode->i_version; |
147 | } | 147 | } |
148 | old_pos = filp->f_pos; | 148 | next_pos = ctx->pos; |
149 | if (!(de = map_pos_dirent(inode, &filp->f_pos, &qbh))) { | 149 | if (!(de = map_pos_dirent(inode, &next_pos, &qbh))) { |
150 | ctx->pos = next_pos; | ||
150 | ret = -EIOERROR; | 151 | ret = -EIOERROR; |
151 | goto out; | 152 | goto out; |
152 | } | 153 | } |
@@ -154,20 +155,21 @@ static int hpfs_readdir(struct file *filp, void *dirent, filldir_t filldir) | |||
154 | if (hpfs_sb(inode->i_sb)->sb_chk) { | 155 | if (hpfs_sb(inode->i_sb)->sb_chk) { |
155 | if (de->first && !de->last && (de->namelen != 2 | 156 | if (de->first && !de->last && (de->namelen != 2 |
156 | || de ->name[0] != 1 || de->name[1] != 1)) | 157 | || de ->name[0] != 1 || de->name[1] != 1)) |
157 | hpfs_error(inode->i_sb, "hpfs_readdir: bad ^A^A entry; pos = %08lx", old_pos); | 158 | hpfs_error(inode->i_sb, "hpfs_readdir: bad ^A^A entry; pos = %08lx", (unsigned long)ctx->pos); |
158 | if (de->last && (de->namelen != 1 || de ->name[0] != 255)) | 159 | if (de->last && (de->namelen != 1 || de ->name[0] != 255)) |
159 | hpfs_error(inode->i_sb, "hpfs_readdir: bad \\377 entry; pos = %08lx", old_pos); | 160 | hpfs_error(inode->i_sb, "hpfs_readdir: bad \\377 entry; pos = %08lx", (unsigned long)ctx->pos); |
160 | } | 161 | } |
161 | hpfs_brelse4(&qbh); | 162 | hpfs_brelse4(&qbh); |
163 | ctx->pos = next_pos; | ||
162 | goto again; | 164 | goto again; |
163 | } | 165 | } |
164 | tempname = hpfs_translate_name(inode->i_sb, de->name, de->namelen, lc, de->not_8x3); | 166 | tempname = hpfs_translate_name(inode->i_sb, de->name, de->namelen, lc, de->not_8x3); |
165 | if (filldir(dirent, tempname, de->namelen, old_pos, le32_to_cpu(de->fnode), DT_UNKNOWN) < 0) { | 167 | if (!dir_emit(ctx, tempname, de->namelen, le32_to_cpu(de->fnode), DT_UNKNOWN)) { |
166 | filp->f_pos = old_pos; | ||
167 | if (tempname != de->name) kfree(tempname); | 168 | if (tempname != de->name) kfree(tempname); |
168 | hpfs_brelse4(&qbh); | 169 | hpfs_brelse4(&qbh); |
169 | goto out; | 170 | goto out; |
170 | } | 171 | } |
172 | ctx->pos = next_pos; | ||
171 | if (tempname != de->name) kfree(tempname); | 173 | if (tempname != de->name) kfree(tempname); |
172 | hpfs_brelse4(&qbh); | 174 | hpfs_brelse4(&qbh); |
173 | } | 175 | } |
@@ -322,7 +324,7 @@ const struct file_operations hpfs_dir_ops = | |||
322 | { | 324 | { |
323 | .llseek = hpfs_dir_lseek, | 325 | .llseek = hpfs_dir_lseek, |
324 | .read = generic_read_dir, | 326 | .read = generic_read_dir, |
325 | .readdir = hpfs_readdir, | 327 | .iterate = hpfs_readdir, |
326 | .release = hpfs_dir_release, | 328 | .release = hpfs_dir_release, |
327 | .fsync = hpfs_file_fsync, | 329 | .fsync = hpfs_file_fsync, |
328 | }; | 330 | }; |
diff --git a/fs/hppfs/hppfs.c b/fs/hppfs/hppfs.c index cd3e38972c86..fc90ab11c340 100644 --- a/fs/hppfs/hppfs.c +++ b/fs/hppfs/hppfs.c | |||
@@ -542,8 +542,8 @@ static const struct file_operations hppfs_file_fops = { | |||
542 | }; | 542 | }; |
543 | 543 | ||
544 | struct hppfs_dirent { | 544 | struct hppfs_dirent { |
545 | void *vfs_dirent; | 545 | struct dir_context ctx; |
546 | filldir_t filldir; | 546 | struct dir_context *caller; |
547 | struct dentry *dentry; | 547 | struct dentry *dentry; |
548 | }; | 548 | }; |
549 | 549 | ||
@@ -555,34 +555,29 @@ static int hppfs_filldir(void *d, const char *name, int size, | |||
555 | if (file_removed(dirent->dentry, name)) | 555 | if (file_removed(dirent->dentry, name)) |
556 | return 0; | 556 | return 0; |
557 | 557 | ||
558 | return (*dirent->filldir)(dirent->vfs_dirent, name, size, offset, | 558 | dirent->caller->pos = dirent->ctx.pos; |
559 | inode, type); | 559 | return !dir_emit(dirent->caller, name, size, inode, type); |
560 | } | 560 | } |
561 | 561 | ||
562 | static int hppfs_readdir(struct file *file, void *ent, filldir_t filldir) | 562 | static int hppfs_readdir(struct file *file, struct dir_context *ctx) |
563 | { | 563 | { |
564 | struct hppfs_private *data = file->private_data; | 564 | struct hppfs_private *data = file->private_data; |
565 | struct file *proc_file = data->proc_file; | 565 | struct file *proc_file = data->proc_file; |
566 | int (*readdir)(struct file *, void *, filldir_t); | 566 | struct hppfs_dirent d = { |
567 | struct hppfs_dirent dirent = ((struct hppfs_dirent) | 567 | .ctx.actor = hppfs_filldir, |
568 | { .vfs_dirent = ent, | 568 | .caller = ctx, |
569 | .filldir = filldir, | 569 | .dentry = file->f_path.dentry |
570 | .dentry = file->f_path.dentry | 570 | }; |
571 | }); | ||
572 | int err; | 571 | int err; |
573 | 572 | proc_file->f_pos = ctx->pos; | |
574 | readdir = file_inode(proc_file)->i_fop->readdir; | 573 | err = iterate_dir(proc_file, &d.ctx); |
575 | 574 | ctx->pos = d.ctx.pos; | |
576 | proc_file->f_pos = file->f_pos; | ||
577 | err = (*readdir)(proc_file, &dirent, hppfs_filldir); | ||
578 | file->f_pos = proc_file->f_pos; | ||
579 | |||
580 | return err; | 575 | return err; |
581 | } | 576 | } |
582 | 577 | ||
583 | static const struct file_operations hppfs_dir_fops = { | 578 | static const struct file_operations hppfs_dir_fops = { |
584 | .owner = NULL, | 579 | .owner = NULL, |
585 | .readdir = hppfs_readdir, | 580 | .iterate = hppfs_readdir, |
586 | .open = hppfs_dir_open, | 581 | .open = hppfs_dir_open, |
587 | .llseek = default_llseek, | 582 | .llseek = default_llseek, |
588 | .release = hppfs_release, | 583 | .release = hppfs_release, |
diff --git a/fs/isofs/dir.c b/fs/isofs/dir.c index a7d5c3c3d4e6..b943cbd963bb 100644 --- a/fs/isofs/dir.c +++ b/fs/isofs/dir.c | |||
@@ -78,8 +78,8 @@ int get_acorn_filename(struct iso_directory_record *de, | |||
78 | /* | 78 | /* |
79 | * This should _really_ be cleaned up some day.. | 79 | * This should _really_ be cleaned up some day.. |
80 | */ | 80 | */ |
81 | static int do_isofs_readdir(struct inode *inode, struct file *filp, | 81 | static int do_isofs_readdir(struct inode *inode, struct file *file, |
82 | void *dirent, filldir_t filldir, | 82 | struct dir_context *ctx, |
83 | char *tmpname, struct iso_directory_record *tmpde) | 83 | char *tmpname, struct iso_directory_record *tmpde) |
84 | { | 84 | { |
85 | unsigned long bufsize = ISOFS_BUFFER_SIZE(inode); | 85 | unsigned long bufsize = ISOFS_BUFFER_SIZE(inode); |
@@ -94,10 +94,10 @@ static int do_isofs_readdir(struct inode *inode, struct file *filp, | |||
94 | struct iso_directory_record *de; | 94 | struct iso_directory_record *de; |
95 | struct isofs_sb_info *sbi = ISOFS_SB(inode->i_sb); | 95 | struct isofs_sb_info *sbi = ISOFS_SB(inode->i_sb); |
96 | 96 | ||
97 | offset = filp->f_pos & (bufsize - 1); | 97 | offset = ctx->pos & (bufsize - 1); |
98 | block = filp->f_pos >> bufbits; | 98 | block = ctx->pos >> bufbits; |
99 | 99 | ||
100 | while (filp->f_pos < inode->i_size) { | 100 | while (ctx->pos < inode->i_size) { |
101 | int de_len; | 101 | int de_len; |
102 | 102 | ||
103 | if (!bh) { | 103 | if (!bh) { |
@@ -108,7 +108,7 @@ static int do_isofs_readdir(struct inode *inode, struct file *filp, | |||
108 | 108 | ||
109 | de = (struct iso_directory_record *) (bh->b_data + offset); | 109 | de = (struct iso_directory_record *) (bh->b_data + offset); |
110 | 110 | ||
111 | de_len = *(unsigned char *) de; | 111 | de_len = *(unsigned char *)de; |
112 | 112 | ||
113 | /* | 113 | /* |
114 | * If the length byte is zero, we should move on to the next | 114 | * If the length byte is zero, we should move on to the next |
@@ -119,8 +119,8 @@ static int do_isofs_readdir(struct inode *inode, struct file *filp, | |||
119 | if (de_len == 0) { | 119 | if (de_len == 0) { |
120 | brelse(bh); | 120 | brelse(bh); |
121 | bh = NULL; | 121 | bh = NULL; |
122 | filp->f_pos = (filp->f_pos + ISOFS_BLOCK_SIZE) & ~(ISOFS_BLOCK_SIZE - 1); | 122 | ctx->pos = (ctx->pos + ISOFS_BLOCK_SIZE) & ~(ISOFS_BLOCK_SIZE - 1); |
123 | block = filp->f_pos >> bufbits; | 123 | block = ctx->pos >> bufbits; |
124 | offset = 0; | 124 | offset = 0; |
125 | continue; | 125 | continue; |
126 | } | 126 | } |
@@ -164,16 +164,16 @@ static int do_isofs_readdir(struct inode *inode, struct file *filp, | |||
164 | 164 | ||
165 | if (de->flags[-sbi->s_high_sierra] & 0x80) { | 165 | if (de->flags[-sbi->s_high_sierra] & 0x80) { |
166 | first_de = 0; | 166 | first_de = 0; |
167 | filp->f_pos += de_len; | 167 | ctx->pos += de_len; |
168 | continue; | 168 | continue; |
169 | } | 169 | } |
170 | first_de = 1; | 170 | first_de = 1; |
171 | 171 | ||
172 | /* Handle the case of the '.' directory */ | 172 | /* Handle the case of the '.' directory */ |
173 | if (de->name_len[0] == 1 && de->name[0] == 0) { | 173 | if (de->name_len[0] == 1 && de->name[0] == 0) { |
174 | if (filldir(dirent, ".", 1, filp->f_pos, inode->i_ino, DT_DIR) < 0) | 174 | if (!dir_emit_dot(file, ctx)) |
175 | break; | 175 | break; |
176 | filp->f_pos += de_len; | 176 | ctx->pos += de_len; |
177 | continue; | 177 | continue; |
178 | } | 178 | } |
179 | 179 | ||
@@ -181,10 +181,9 @@ static int do_isofs_readdir(struct inode *inode, struct file *filp, | |||
181 | 181 | ||
182 | /* Handle the case of the '..' directory */ | 182 | /* Handle the case of the '..' directory */ |
183 | if (de->name_len[0] == 1 && de->name[0] == 1) { | 183 | if (de->name_len[0] == 1 && de->name[0] == 1) { |
184 | inode_number = parent_ino(filp->f_path.dentry); | 184 | if (!dir_emit_dotdot(file, ctx)) |
185 | if (filldir(dirent, "..", 2, filp->f_pos, inode_number, DT_DIR) < 0) | ||
186 | break; | 185 | break; |
187 | filp->f_pos += de_len; | 186 | ctx->pos += de_len; |
188 | continue; | 187 | continue; |
189 | } | 188 | } |
190 | 189 | ||
@@ -198,7 +197,7 @@ static int do_isofs_readdir(struct inode *inode, struct file *filp, | |||
198 | if ((sbi->s_hide && (de->flags[-sbi->s_high_sierra] & 1)) || | 197 | if ((sbi->s_hide && (de->flags[-sbi->s_high_sierra] & 1)) || |
199 | (!sbi->s_showassoc && | 198 | (!sbi->s_showassoc && |
200 | (de->flags[-sbi->s_high_sierra] & 4))) { | 199 | (de->flags[-sbi->s_high_sierra] & 4))) { |
201 | filp->f_pos += de_len; | 200 | ctx->pos += de_len; |
202 | continue; | 201 | continue; |
203 | } | 202 | } |
204 | 203 | ||
@@ -230,10 +229,10 @@ static int do_isofs_readdir(struct inode *inode, struct file *filp, | |||
230 | } | 229 | } |
231 | } | 230 | } |
232 | if (len > 0) { | 231 | if (len > 0) { |
233 | if (filldir(dirent, p, len, filp->f_pos, inode_number, DT_UNKNOWN) < 0) | 232 | if (!dir_emit(ctx, p, len, inode_number, DT_UNKNOWN)) |
234 | break; | 233 | break; |
235 | } | 234 | } |
236 | filp->f_pos += de_len; | 235 | ctx->pos += de_len; |
237 | 236 | ||
238 | continue; | 237 | continue; |
239 | } | 238 | } |
@@ -247,13 +246,12 @@ static int do_isofs_readdir(struct inode *inode, struct file *filp, | |||
247 | * handling split directory entries.. The real work is done by | 246 | * handling split directory entries.. The real work is done by |
248 | * "do_isofs_readdir()". | 247 | * "do_isofs_readdir()". |
249 | */ | 248 | */ |
250 | static int isofs_readdir(struct file *filp, | 249 | static int isofs_readdir(struct file *file, struct dir_context *ctx) |
251 | void *dirent, filldir_t filldir) | ||
252 | { | 250 | { |
253 | int result; | 251 | int result; |
254 | char *tmpname; | 252 | char *tmpname; |
255 | struct iso_directory_record *tmpde; | 253 | struct iso_directory_record *tmpde; |
256 | struct inode *inode = file_inode(filp); | 254 | struct inode *inode = file_inode(file); |
257 | 255 | ||
258 | tmpname = (char *)__get_free_page(GFP_KERNEL); | 256 | tmpname = (char *)__get_free_page(GFP_KERNEL); |
259 | if (tmpname == NULL) | 257 | if (tmpname == NULL) |
@@ -261,7 +259,7 @@ static int isofs_readdir(struct file *filp, | |||
261 | 259 | ||
262 | tmpde = (struct iso_directory_record *) (tmpname+1024); | 260 | tmpde = (struct iso_directory_record *) (tmpname+1024); |
263 | 261 | ||
264 | result = do_isofs_readdir(inode, filp, dirent, filldir, tmpname, tmpde); | 262 | result = do_isofs_readdir(inode, file, ctx, tmpname, tmpde); |
265 | 263 | ||
266 | free_page((unsigned long) tmpname); | 264 | free_page((unsigned long) tmpname); |
267 | return result; | 265 | return result; |
@@ -271,7 +269,7 @@ const struct file_operations isofs_dir_operations = | |||
271 | { | 269 | { |
272 | .llseek = generic_file_llseek, | 270 | .llseek = generic_file_llseek, |
273 | .read = generic_read_dir, | 271 | .read = generic_read_dir, |
274 | .readdir = isofs_readdir, | 272 | .iterate = isofs_readdir, |
275 | }; | 273 | }; |
276 | 274 | ||
277 | /* | 275 | /* |
diff --git a/fs/jffs2/dir.c b/fs/jffs2/dir.c index acd46a4160cb..e3aac222472e 100644 --- a/fs/jffs2/dir.c +++ b/fs/jffs2/dir.c | |||
@@ -22,7 +22,7 @@ | |||
22 | #include <linux/time.h> | 22 | #include <linux/time.h> |
23 | #include "nodelist.h" | 23 | #include "nodelist.h" |
24 | 24 | ||
25 | static int jffs2_readdir (struct file *, void *, filldir_t); | 25 | static int jffs2_readdir (struct file *, struct dir_context *); |
26 | 26 | ||
27 | static int jffs2_create (struct inode *,struct dentry *,umode_t, | 27 | static int jffs2_create (struct inode *,struct dentry *,umode_t, |
28 | bool); | 28 | bool); |
@@ -40,7 +40,7 @@ static int jffs2_rename (struct inode *, struct dentry *, | |||
40 | const struct file_operations jffs2_dir_operations = | 40 | const struct file_operations jffs2_dir_operations = |
41 | { | 41 | { |
42 | .read = generic_read_dir, | 42 | .read = generic_read_dir, |
43 | .readdir = jffs2_readdir, | 43 | .iterate = jffs2_readdir, |
44 | .unlocked_ioctl=jffs2_ioctl, | 44 | .unlocked_ioctl=jffs2_ioctl, |
45 | .fsync = jffs2_fsync, | 45 | .fsync = jffs2_fsync, |
46 | .llseek = generic_file_llseek, | 46 | .llseek = generic_file_llseek, |
@@ -114,60 +114,40 @@ static struct dentry *jffs2_lookup(struct inode *dir_i, struct dentry *target, | |||
114 | /***********************************************************************/ | 114 | /***********************************************************************/ |
115 | 115 | ||
116 | 116 | ||
117 | static int jffs2_readdir(struct file *filp, void *dirent, filldir_t filldir) | 117 | static int jffs2_readdir(struct file *file, struct dir_context *ctx) |
118 | { | 118 | { |
119 | struct jffs2_inode_info *f; | 119 | struct inode *inode = file_inode(file); |
120 | struct inode *inode = file_inode(filp); | 120 | struct jffs2_inode_info *f = JFFS2_INODE_INFO(inode); |
121 | struct jffs2_full_dirent *fd; | 121 | struct jffs2_full_dirent *fd; |
122 | unsigned long offset, curofs; | 122 | unsigned long curofs = 1; |
123 | 123 | ||
124 | jffs2_dbg(1, "jffs2_readdir() for dir_i #%lu\n", | 124 | jffs2_dbg(1, "jffs2_readdir() for dir_i #%lu\n", inode->i_ino); |
125 | file_inode(filp)->i_ino); | ||
126 | 125 | ||
127 | f = JFFS2_INODE_INFO(inode); | 126 | if (!dir_emit_dots(file, ctx)) |
128 | 127 | return 0; | |
129 | offset = filp->f_pos; | ||
130 | |||
131 | if (offset == 0) { | ||
132 | jffs2_dbg(1, "Dirent 0: \".\", ino #%lu\n", inode->i_ino); | ||
133 | if (filldir(dirent, ".", 1, 0, inode->i_ino, DT_DIR) < 0) | ||
134 | goto out; | ||
135 | offset++; | ||
136 | } | ||
137 | if (offset == 1) { | ||
138 | unsigned long pino = parent_ino(filp->f_path.dentry); | ||
139 | jffs2_dbg(1, "Dirent 1: \"..\", ino #%lu\n", pino); | ||
140 | if (filldir(dirent, "..", 2, 1, pino, DT_DIR) < 0) | ||
141 | goto out; | ||
142 | offset++; | ||
143 | } | ||
144 | 128 | ||
145 | curofs=1; | ||
146 | mutex_lock(&f->sem); | 129 | mutex_lock(&f->sem); |
147 | for (fd = f->dents; fd; fd = fd->next) { | 130 | for (fd = f->dents; fd; fd = fd->next) { |
148 | |||
149 | curofs++; | 131 | curofs++; |
150 | /* First loop: curofs = 2; offset = 2 */ | 132 | /* First loop: curofs = 2; pos = 2 */ |
151 | if (curofs < offset) { | 133 | if (curofs < ctx->pos) { |
152 | jffs2_dbg(2, "Skipping dirent: \"%s\", ino #%u, type %d, because curofs %ld < offset %ld\n", | 134 | jffs2_dbg(2, "Skipping dirent: \"%s\", ino #%u, type %d, because curofs %ld < offset %ld\n", |
153 | fd->name, fd->ino, fd->type, curofs, offset); | 135 | fd->name, fd->ino, fd->type, curofs, (unsigned long)ctx->pos); |
154 | continue; | 136 | continue; |
155 | } | 137 | } |
156 | if (!fd->ino) { | 138 | if (!fd->ino) { |
157 | jffs2_dbg(2, "Skipping deletion dirent \"%s\"\n", | 139 | jffs2_dbg(2, "Skipping deletion dirent \"%s\"\n", |
158 | fd->name); | 140 | fd->name); |
159 | offset++; | 141 | ctx->pos++; |
160 | continue; | 142 | continue; |
161 | } | 143 | } |
162 | jffs2_dbg(2, "Dirent %ld: \"%s\", ino #%u, type %d\n", | 144 | jffs2_dbg(2, "Dirent %ld: \"%s\", ino #%u, type %d\n", |
163 | offset, fd->name, fd->ino, fd->type); | 145 | (unsigned long)ctx->pos, fd->name, fd->ino, fd->type); |
164 | if (filldir(dirent, fd->name, strlen(fd->name), offset, fd->ino, fd->type) < 0) | 146 | if (!dir_emit(ctx, fd->name, strlen(fd->name), fd->ino, fd->type)) |
165 | break; | 147 | break; |
166 | offset++; | 148 | ctx->pos++; |
167 | } | 149 | } |
168 | mutex_unlock(&f->sem); | 150 | mutex_unlock(&f->sem); |
169 | out: | ||
170 | filp->f_pos = offset; | ||
171 | return 0; | 151 | return 0; |
172 | } | 152 | } |
173 | 153 | ||
diff --git a/fs/jfs/jfs_dtree.c b/fs/jfs/jfs_dtree.c index 0ddbeceafc62..9f4ed13d9f15 100644 --- a/fs/jfs/jfs_dtree.c +++ b/fs/jfs/jfs_dtree.c | |||
@@ -3002,9 +3002,9 @@ static inline struct jfs_dirent *next_jfs_dirent(struct jfs_dirent *dirent) | |||
3002 | * return: offset = (pn, index) of start entry | 3002 | * return: offset = (pn, index) of start entry |
3003 | * of next jfs_readdir()/dtRead() | 3003 | * of next jfs_readdir()/dtRead() |
3004 | */ | 3004 | */ |
3005 | int jfs_readdir(struct file *filp, void *dirent, filldir_t filldir) | 3005 | int jfs_readdir(struct file *file, struct dir_context *ctx) |
3006 | { | 3006 | { |
3007 | struct inode *ip = file_inode(filp); | 3007 | struct inode *ip = file_inode(file); |
3008 | struct nls_table *codepage = JFS_SBI(ip->i_sb)->nls_tab; | 3008 | struct nls_table *codepage = JFS_SBI(ip->i_sb)->nls_tab; |
3009 | int rc = 0; | 3009 | int rc = 0; |
3010 | loff_t dtpos; /* legacy OS/2 style position */ | 3010 | loff_t dtpos; /* legacy OS/2 style position */ |
@@ -3033,7 +3033,7 @@ int jfs_readdir(struct file *filp, void *dirent, filldir_t filldir) | |||
3033 | int overflow, fix_page, page_fixed = 0; | 3033 | int overflow, fix_page, page_fixed = 0; |
3034 | static int unique_pos = 2; /* If we can't fix broken index */ | 3034 | static int unique_pos = 2; /* If we can't fix broken index */ |
3035 | 3035 | ||
3036 | if (filp->f_pos == DIREND) | 3036 | if (ctx->pos == DIREND) |
3037 | return 0; | 3037 | return 0; |
3038 | 3038 | ||
3039 | if (DO_INDEX(ip)) { | 3039 | if (DO_INDEX(ip)) { |
@@ -3045,7 +3045,7 @@ int jfs_readdir(struct file *filp, void *dirent, filldir_t filldir) | |||
3045 | */ | 3045 | */ |
3046 | do_index = 1; | 3046 | do_index = 1; |
3047 | 3047 | ||
3048 | dir_index = (u32) filp->f_pos; | 3048 | dir_index = (u32) ctx->pos; |
3049 | 3049 | ||
3050 | if (dir_index > 1) { | 3050 | if (dir_index > 1) { |
3051 | struct dir_table_slot dirtab_slot; | 3051 | struct dir_table_slot dirtab_slot; |
@@ -3053,25 +3053,25 @@ int jfs_readdir(struct file *filp, void *dirent, filldir_t filldir) | |||
3053 | if (dtEmpty(ip) || | 3053 | if (dtEmpty(ip) || |
3054 | (dir_index >= JFS_IP(ip)->next_index)) { | 3054 | (dir_index >= JFS_IP(ip)->next_index)) { |
3055 | /* Stale position. Directory has shrunk */ | 3055 | /* Stale position. Directory has shrunk */ |
3056 | filp->f_pos = DIREND; | 3056 | ctx->pos = DIREND; |
3057 | return 0; | 3057 | return 0; |
3058 | } | 3058 | } |
3059 | repeat: | 3059 | repeat: |
3060 | rc = read_index(ip, dir_index, &dirtab_slot); | 3060 | rc = read_index(ip, dir_index, &dirtab_slot); |
3061 | if (rc) { | 3061 | if (rc) { |
3062 | filp->f_pos = DIREND; | 3062 | ctx->pos = DIREND; |
3063 | return rc; | 3063 | return rc; |
3064 | } | 3064 | } |
3065 | if (dirtab_slot.flag == DIR_INDEX_FREE) { | 3065 | if (dirtab_slot.flag == DIR_INDEX_FREE) { |
3066 | if (loop_count++ > JFS_IP(ip)->next_index) { | 3066 | if (loop_count++ > JFS_IP(ip)->next_index) { |
3067 | jfs_err("jfs_readdir detected " | 3067 | jfs_err("jfs_readdir detected " |
3068 | "infinite loop!"); | 3068 | "infinite loop!"); |
3069 | filp->f_pos = DIREND; | 3069 | ctx->pos = DIREND; |
3070 | return 0; | 3070 | return 0; |
3071 | } | 3071 | } |
3072 | dir_index = le32_to_cpu(dirtab_slot.addr2); | 3072 | dir_index = le32_to_cpu(dirtab_slot.addr2); |
3073 | if (dir_index == -1) { | 3073 | if (dir_index == -1) { |
3074 | filp->f_pos = DIREND; | 3074 | ctx->pos = DIREND; |
3075 | return 0; | 3075 | return 0; |
3076 | } | 3076 | } |
3077 | goto repeat; | 3077 | goto repeat; |
@@ -3080,13 +3080,13 @@ int jfs_readdir(struct file *filp, void *dirent, filldir_t filldir) | |||
3080 | index = dirtab_slot.slot; | 3080 | index = dirtab_slot.slot; |
3081 | DT_GETPAGE(ip, bn, mp, PSIZE, p, rc); | 3081 | DT_GETPAGE(ip, bn, mp, PSIZE, p, rc); |
3082 | if (rc) { | 3082 | if (rc) { |
3083 | filp->f_pos = DIREND; | 3083 | ctx->pos = DIREND; |
3084 | return 0; | 3084 | return 0; |
3085 | } | 3085 | } |
3086 | if (p->header.flag & BT_INTERNAL) { | 3086 | if (p->header.flag & BT_INTERNAL) { |
3087 | jfs_err("jfs_readdir: bad index table"); | 3087 | jfs_err("jfs_readdir: bad index table"); |
3088 | DT_PUTPAGE(mp); | 3088 | DT_PUTPAGE(mp); |
3089 | filp->f_pos = -1; | 3089 | ctx->pos = -1; |
3090 | return 0; | 3090 | return 0; |
3091 | } | 3091 | } |
3092 | } else { | 3092 | } else { |
@@ -3094,23 +3094,22 @@ int jfs_readdir(struct file *filp, void *dirent, filldir_t filldir) | |||
3094 | /* | 3094 | /* |
3095 | * self "." | 3095 | * self "." |
3096 | */ | 3096 | */ |
3097 | filp->f_pos = 0; | 3097 | ctx->pos = 0; |
3098 | if (filldir(dirent, ".", 1, 0, ip->i_ino, | 3098 | if (!dir_emit(ctx, ".", 1, ip->i_ino, DT_DIR)) |
3099 | DT_DIR)) | ||
3100 | return 0; | 3099 | return 0; |
3101 | } | 3100 | } |
3102 | /* | 3101 | /* |
3103 | * parent ".." | 3102 | * parent ".." |
3104 | */ | 3103 | */ |
3105 | filp->f_pos = 1; | 3104 | ctx->pos = 1; |
3106 | if (filldir(dirent, "..", 2, 1, PARENT(ip), DT_DIR)) | 3105 | if (!dir_emit(ctx, "..", 2, PARENT(ip), DT_DIR)) |
3107 | return 0; | 3106 | return 0; |
3108 | 3107 | ||
3109 | /* | 3108 | /* |
3110 | * Find first entry of left-most leaf | 3109 | * Find first entry of left-most leaf |
3111 | */ | 3110 | */ |
3112 | if (dtEmpty(ip)) { | 3111 | if (dtEmpty(ip)) { |
3113 | filp->f_pos = DIREND; | 3112 | ctx->pos = DIREND; |
3114 | return 0; | 3113 | return 0; |
3115 | } | 3114 | } |
3116 | 3115 | ||
@@ -3128,23 +3127,19 @@ int jfs_readdir(struct file *filp, void *dirent, filldir_t filldir) | |||
3128 | * pn > 0: Real entries, pn=1 -> leftmost page | 3127 | * pn > 0: Real entries, pn=1 -> leftmost page |
3129 | * pn = index = -1: No more entries | 3128 | * pn = index = -1: No more entries |
3130 | */ | 3129 | */ |
3131 | dtpos = filp->f_pos; | 3130 | dtpos = ctx->pos; |
3132 | if (dtpos == 0) { | 3131 | if (dtpos == 0) { |
3133 | /* build "." entry */ | 3132 | /* build "." entry */ |
3134 | 3133 | if (!dir_emit(ctx, ".", 1, ip->i_ino, DT_DIR)) | |
3135 | if (filldir(dirent, ".", 1, filp->f_pos, ip->i_ino, | ||
3136 | DT_DIR)) | ||
3137 | return 0; | 3134 | return 0; |
3138 | dtoffset->index = 1; | 3135 | dtoffset->index = 1; |
3139 | filp->f_pos = dtpos; | 3136 | ctx->pos = dtpos; |
3140 | } | 3137 | } |
3141 | 3138 | ||
3142 | if (dtoffset->pn == 0) { | 3139 | if (dtoffset->pn == 0) { |
3143 | if (dtoffset->index == 1) { | 3140 | if (dtoffset->index == 1) { |
3144 | /* build ".." entry */ | 3141 | /* build ".." entry */ |
3145 | 3142 | if (!dir_emit(ctx, "..", 2, PARENT(ip), DT_DIR)) | |
3146 | if (filldir(dirent, "..", 2, filp->f_pos, | ||
3147 | PARENT(ip), DT_DIR)) | ||
3148 | return 0; | 3143 | return 0; |
3149 | } else { | 3144 | } else { |
3150 | jfs_err("jfs_readdir called with " | 3145 | jfs_err("jfs_readdir called with " |
@@ -3152,18 +3147,18 @@ int jfs_readdir(struct file *filp, void *dirent, filldir_t filldir) | |||
3152 | } | 3147 | } |
3153 | dtoffset->pn = 1; | 3148 | dtoffset->pn = 1; |
3154 | dtoffset->index = 0; | 3149 | dtoffset->index = 0; |
3155 | filp->f_pos = dtpos; | 3150 | ctx->pos = dtpos; |
3156 | } | 3151 | } |
3157 | 3152 | ||
3158 | if (dtEmpty(ip)) { | 3153 | if (dtEmpty(ip)) { |
3159 | filp->f_pos = DIREND; | 3154 | ctx->pos = DIREND; |
3160 | return 0; | 3155 | return 0; |
3161 | } | 3156 | } |
3162 | 3157 | ||
3163 | if ((rc = dtReadNext(ip, &filp->f_pos, &btstack))) { | 3158 | if ((rc = dtReadNext(ip, &ctx->pos, &btstack))) { |
3164 | jfs_err("jfs_readdir: unexpected rc = %d " | 3159 | jfs_err("jfs_readdir: unexpected rc = %d " |
3165 | "from dtReadNext", rc); | 3160 | "from dtReadNext", rc); |
3166 | filp->f_pos = DIREND; | 3161 | ctx->pos = DIREND; |
3167 | return 0; | 3162 | return 0; |
3168 | } | 3163 | } |
3169 | /* get start leaf page and index */ | 3164 | /* get start leaf page and index */ |
@@ -3171,7 +3166,7 @@ int jfs_readdir(struct file *filp, void *dirent, filldir_t filldir) | |||
3171 | 3166 | ||
3172 | /* offset beyond directory eof ? */ | 3167 | /* offset beyond directory eof ? */ |
3173 | if (bn < 0) { | 3168 | if (bn < 0) { |
3174 | filp->f_pos = DIREND; | 3169 | ctx->pos = DIREND; |
3175 | return 0; | 3170 | return 0; |
3176 | } | 3171 | } |
3177 | } | 3172 | } |
@@ -3180,7 +3175,7 @@ int jfs_readdir(struct file *filp, void *dirent, filldir_t filldir) | |||
3180 | if (dirent_buf == 0) { | 3175 | if (dirent_buf == 0) { |
3181 | DT_PUTPAGE(mp); | 3176 | DT_PUTPAGE(mp); |
3182 | jfs_warn("jfs_readdir: __get_free_page failed!"); | 3177 | jfs_warn("jfs_readdir: __get_free_page failed!"); |
3183 | filp->f_pos = DIREND; | 3178 | ctx->pos = DIREND; |
3184 | return -ENOMEM; | 3179 | return -ENOMEM; |
3185 | } | 3180 | } |
3186 | 3181 | ||
@@ -3295,9 +3290,9 @@ skip_one: | |||
3295 | 3290 | ||
3296 | jfs_dirent = (struct jfs_dirent *) dirent_buf; | 3291 | jfs_dirent = (struct jfs_dirent *) dirent_buf; |
3297 | while (jfs_dirents--) { | 3292 | while (jfs_dirents--) { |
3298 | filp->f_pos = jfs_dirent->position; | 3293 | ctx->pos = jfs_dirent->position; |
3299 | if (filldir(dirent, jfs_dirent->name, | 3294 | if (!dir_emit(ctx, jfs_dirent->name, |
3300 | jfs_dirent->name_len, filp->f_pos, | 3295 | jfs_dirent->name_len, |
3301 | jfs_dirent->ino, DT_UNKNOWN)) | 3296 | jfs_dirent->ino, DT_UNKNOWN)) |
3302 | goto out; | 3297 | goto out; |
3303 | jfs_dirent = next_jfs_dirent(jfs_dirent); | 3298 | jfs_dirent = next_jfs_dirent(jfs_dirent); |
@@ -3309,7 +3304,7 @@ skip_one: | |||
3309 | } | 3304 | } |
3310 | 3305 | ||
3311 | if (!overflow && (bn == 0)) { | 3306 | if (!overflow && (bn == 0)) { |
3312 | filp->f_pos = DIREND; | 3307 | ctx->pos = DIREND; |
3313 | break; | 3308 | break; |
3314 | } | 3309 | } |
3315 | 3310 | ||
diff --git a/fs/jfs/jfs_dtree.h b/fs/jfs/jfs_dtree.h index 2545bb317235..fd4169e6e698 100644 --- a/fs/jfs/jfs_dtree.h +++ b/fs/jfs/jfs_dtree.h | |||
@@ -265,5 +265,5 @@ extern int dtDelete(tid_t tid, struct inode *ip, struct component_name * key, | |||
265 | extern int dtModify(tid_t tid, struct inode *ip, struct component_name * key, | 265 | extern int dtModify(tid_t tid, struct inode *ip, struct component_name * key, |
266 | ino_t * orig_ino, ino_t new_ino, int flag); | 266 | ino_t * orig_ino, ino_t new_ino, int flag); |
267 | 267 | ||
268 | extern int jfs_readdir(struct file *filp, void *dirent, filldir_t filldir); | 268 | extern int jfs_readdir(struct file *file, struct dir_context *ctx); |
269 | #endif /* !_H_JFS_DTREE */ | 269 | #endif /* !_H_JFS_DTREE */ |
diff --git a/fs/jfs/namei.c b/fs/jfs/namei.c index 3b91a7ad6086..89186b7b9002 100644 --- a/fs/jfs/namei.c +++ b/fs/jfs/namei.c | |||
@@ -1529,7 +1529,7 @@ const struct inode_operations jfs_dir_inode_operations = { | |||
1529 | 1529 | ||
1530 | const struct file_operations jfs_dir_operations = { | 1530 | const struct file_operations jfs_dir_operations = { |
1531 | .read = generic_read_dir, | 1531 | .read = generic_read_dir, |
1532 | .readdir = jfs_readdir, | 1532 | .iterate = jfs_readdir, |
1533 | .fsync = jfs_fsync, | 1533 | .fsync = jfs_fsync, |
1534 | .unlocked_ioctl = jfs_ioctl, | 1534 | .unlocked_ioctl = jfs_ioctl, |
1535 | #ifdef CONFIG_COMPAT | 1535 | #ifdef CONFIG_COMPAT |
diff --git a/fs/libfs.c b/fs/libfs.c index 916da8c4158b..c3a0837fb861 100644 --- a/fs/libfs.c +++ b/fs/libfs.c | |||
@@ -135,60 +135,40 @@ static inline unsigned char dt_type(struct inode *inode) | |||
135 | * both impossible due to the lock on directory. | 135 | * both impossible due to the lock on directory. |
136 | */ | 136 | */ |
137 | 137 | ||
138 | int dcache_readdir(struct file * filp, void * dirent, filldir_t filldir) | 138 | int dcache_readdir(struct file *file, struct dir_context *ctx) |
139 | { | 139 | { |
140 | struct dentry *dentry = filp->f_path.dentry; | 140 | struct dentry *dentry = file->f_path.dentry; |
141 | struct dentry *cursor = filp->private_data; | 141 | struct dentry *cursor = file->private_data; |
142 | struct list_head *p, *q = &cursor->d_u.d_child; | 142 | struct list_head *p, *q = &cursor->d_u.d_child; |
143 | ino_t ino; | ||
144 | int i = filp->f_pos; | ||
145 | 143 | ||
146 | switch (i) { | 144 | if (!dir_emit_dots(file, ctx)) |
147 | case 0: | 145 | return 0; |
148 | ino = dentry->d_inode->i_ino; | 146 | spin_lock(&dentry->d_lock); |
149 | if (filldir(dirent, ".", 1, i, ino, DT_DIR) < 0) | 147 | if (ctx->pos == 2) |
150 | break; | 148 | list_move(q, &dentry->d_subdirs); |
151 | filp->f_pos++; | 149 | |
152 | i++; | 150 | for (p = q->next; p != &dentry->d_subdirs; p = p->next) { |
153 | /* fallthrough */ | 151 | struct dentry *next = list_entry(p, struct dentry, d_u.d_child); |
154 | case 1: | 152 | spin_lock_nested(&next->d_lock, DENTRY_D_LOCK_NESTED); |
155 | ino = parent_ino(dentry); | 153 | if (!simple_positive(next)) { |
156 | if (filldir(dirent, "..", 2, i, ino, DT_DIR) < 0) | 154 | spin_unlock(&next->d_lock); |
157 | break; | 155 | continue; |
158 | filp->f_pos++; | 156 | } |
159 | i++; | ||
160 | /* fallthrough */ | ||
161 | default: | ||
162 | spin_lock(&dentry->d_lock); | ||
163 | if (filp->f_pos == 2) | ||
164 | list_move(q, &dentry->d_subdirs); | ||
165 | |||
166 | for (p=q->next; p != &dentry->d_subdirs; p=p->next) { | ||
167 | struct dentry *next; | ||
168 | next = list_entry(p, struct dentry, d_u.d_child); | ||
169 | spin_lock_nested(&next->d_lock, DENTRY_D_LOCK_NESTED); | ||
170 | if (!simple_positive(next)) { | ||
171 | spin_unlock(&next->d_lock); | ||
172 | continue; | ||
173 | } | ||
174 | 157 | ||
175 | spin_unlock(&next->d_lock); | 158 | spin_unlock(&next->d_lock); |
176 | spin_unlock(&dentry->d_lock); | 159 | spin_unlock(&dentry->d_lock); |
177 | if (filldir(dirent, next->d_name.name, | 160 | if (!dir_emit(ctx, next->d_name.name, next->d_name.len, |
178 | next->d_name.len, filp->f_pos, | 161 | next->d_inode->i_ino, dt_type(next->d_inode))) |
179 | next->d_inode->i_ino, | 162 | return 0; |
180 | dt_type(next->d_inode)) < 0) | 163 | spin_lock(&dentry->d_lock); |
181 | return 0; | 164 | spin_lock_nested(&next->d_lock, DENTRY_D_LOCK_NESTED); |
182 | spin_lock(&dentry->d_lock); | 165 | /* next is still alive */ |
183 | spin_lock_nested(&next->d_lock, DENTRY_D_LOCK_NESTED); | 166 | list_move(q, p); |
184 | /* next is still alive */ | 167 | spin_unlock(&next->d_lock); |
185 | list_move(q, p); | 168 | p = q; |
186 | spin_unlock(&next->d_lock); | 169 | ctx->pos++; |
187 | p = q; | ||
188 | filp->f_pos++; | ||
189 | } | ||
190 | spin_unlock(&dentry->d_lock); | ||
191 | } | 170 | } |
171 | spin_unlock(&dentry->d_lock); | ||
192 | return 0; | 172 | return 0; |
193 | } | 173 | } |
194 | 174 | ||
@@ -202,7 +182,7 @@ const struct file_operations simple_dir_operations = { | |||
202 | .release = dcache_dir_close, | 182 | .release = dcache_dir_close, |
203 | .llseek = dcache_dir_lseek, | 183 | .llseek = dcache_dir_lseek, |
204 | .read = generic_read_dir, | 184 | .read = generic_read_dir, |
205 | .readdir = dcache_readdir, | 185 | .iterate = dcache_readdir, |
206 | .fsync = noop_fsync, | 186 | .fsync = noop_fsync, |
207 | }; | 187 | }; |
208 | 188 | ||
diff --git a/fs/logfs/dir.c b/fs/logfs/dir.c index b82751082112..6bdc347008f5 100644 --- a/fs/logfs/dir.c +++ b/fs/logfs/dir.c | |||
@@ -281,17 +281,23 @@ static int logfs_rmdir(struct inode *dir, struct dentry *dentry) | |||
281 | 281 | ||
282 | /* FIXME: readdir currently has it's own dir_walk code. I don't see a good | 282 | /* FIXME: readdir currently has it's own dir_walk code. I don't see a good |
283 | * way to combine the two copies */ | 283 | * way to combine the two copies */ |
284 | #define IMPLICIT_NODES 2 | 284 | static int logfs_readdir(struct file *file, struct dir_context *ctx) |
285 | static int __logfs_readdir(struct file *file, void *buf, filldir_t filldir) | ||
286 | { | 285 | { |
287 | struct inode *dir = file_inode(file); | 286 | struct inode *dir = file_inode(file); |
288 | loff_t pos = file->f_pos - IMPLICIT_NODES; | 287 | loff_t pos; |
289 | struct page *page; | 288 | struct page *page; |
290 | struct logfs_disk_dentry *dd; | 289 | struct logfs_disk_dentry *dd; |
291 | int full; | ||
292 | 290 | ||
291 | if (ctx->pos < 0) | ||
292 | return -EINVAL; | ||
293 | |||
294 | if (!dir_emit_dots(file, ctx)) | ||
295 | return 0; | ||
296 | |||
297 | pos = ctx->pos - 2; | ||
293 | BUG_ON(pos < 0); | 298 | BUG_ON(pos < 0); |
294 | for (;; pos++) { | 299 | for (;; pos++, ctx->pos++) { |
300 | bool full; | ||
295 | if (beyond_eof(dir, pos)) | 301 | if (beyond_eof(dir, pos)) |
296 | break; | 302 | break; |
297 | if (!logfs_exist_block(dir, pos)) { | 303 | if (!logfs_exist_block(dir, pos)) { |
@@ -306,42 +312,17 @@ static int __logfs_readdir(struct file *file, void *buf, filldir_t filldir) | |||
306 | dd = kmap(page); | 312 | dd = kmap(page); |
307 | BUG_ON(dd->namelen == 0); | 313 | BUG_ON(dd->namelen == 0); |
308 | 314 | ||
309 | full = filldir(buf, (char *)dd->name, be16_to_cpu(dd->namelen), | 315 | full = !dir_emit(ctx, (char *)dd->name, |
310 | pos, be64_to_cpu(dd->ino), dd->type); | 316 | be16_to_cpu(dd->namelen), |
317 | be64_to_cpu(dd->ino), dd->type); | ||
311 | kunmap(page); | 318 | kunmap(page); |
312 | page_cache_release(page); | 319 | page_cache_release(page); |
313 | if (full) | 320 | if (full) |
314 | break; | 321 | break; |
315 | } | 322 | } |
316 | |||
317 | file->f_pos = pos + IMPLICIT_NODES; | ||
318 | return 0; | 323 | return 0; |
319 | } | 324 | } |
320 | 325 | ||
321 | static int logfs_readdir(struct file *file, void *buf, filldir_t filldir) | ||
322 | { | ||
323 | struct inode *inode = file_inode(file); | ||
324 | ino_t pino = parent_ino(file->f_dentry); | ||
325 | int err; | ||
326 | |||
327 | if (file->f_pos < 0) | ||
328 | return -EINVAL; | ||
329 | |||
330 | if (file->f_pos == 0) { | ||
331 | if (filldir(buf, ".", 1, 1, inode->i_ino, DT_DIR) < 0) | ||
332 | return 0; | ||
333 | file->f_pos++; | ||
334 | } | ||
335 | if (file->f_pos == 1) { | ||
336 | if (filldir(buf, "..", 2, 2, pino, DT_DIR) < 0) | ||
337 | return 0; | ||
338 | file->f_pos++; | ||
339 | } | ||
340 | |||
341 | err = __logfs_readdir(file, buf, filldir); | ||
342 | return err; | ||
343 | } | ||
344 | |||
345 | static void logfs_set_name(struct logfs_disk_dentry *dd, struct qstr *name) | 326 | static void logfs_set_name(struct logfs_disk_dentry *dd, struct qstr *name) |
346 | { | 327 | { |
347 | dd->namelen = cpu_to_be16(name->len); | 328 | dd->namelen = cpu_to_be16(name->len); |
@@ -814,7 +795,7 @@ const struct inode_operations logfs_dir_iops = { | |||
814 | const struct file_operations logfs_dir_fops = { | 795 | const struct file_operations logfs_dir_fops = { |
815 | .fsync = logfs_fsync, | 796 | .fsync = logfs_fsync, |
816 | .unlocked_ioctl = logfs_ioctl, | 797 | .unlocked_ioctl = logfs_ioctl, |
817 | .readdir = logfs_readdir, | 798 | .iterate = logfs_readdir, |
818 | .read = generic_read_dir, | 799 | .read = generic_read_dir, |
819 | .llseek = default_llseek, | 800 | .llseek = default_llseek, |
820 | }; | 801 | }; |
diff --git a/fs/minix/dir.c b/fs/minix/dir.c index a9ed6f36e6ea..08c442902fcd 100644 --- a/fs/minix/dir.c +++ b/fs/minix/dir.c | |||
@@ -16,12 +16,12 @@ | |||
16 | typedef struct minix_dir_entry minix_dirent; | 16 | typedef struct minix_dir_entry minix_dirent; |
17 | typedef struct minix3_dir_entry minix3_dirent; | 17 | typedef struct minix3_dir_entry minix3_dirent; |
18 | 18 | ||
19 | static int minix_readdir(struct file *, void *, filldir_t); | 19 | static int minix_readdir(struct file *, struct dir_context *); |
20 | 20 | ||
21 | const struct file_operations minix_dir_operations = { | 21 | const struct file_operations minix_dir_operations = { |
22 | .llseek = generic_file_llseek, | 22 | .llseek = generic_file_llseek, |
23 | .read = generic_read_dir, | 23 | .read = generic_read_dir, |
24 | .readdir = minix_readdir, | 24 | .iterate = minix_readdir, |
25 | .fsync = generic_file_fsync, | 25 | .fsync = generic_file_fsync, |
26 | }; | 26 | }; |
27 | 27 | ||
@@ -82,22 +82,23 @@ static inline void *minix_next_entry(void *de, struct minix_sb_info *sbi) | |||
82 | return (void*)((char*)de + sbi->s_dirsize); | 82 | return (void*)((char*)de + sbi->s_dirsize); |
83 | } | 83 | } |
84 | 84 | ||
85 | static int minix_readdir(struct file * filp, void * dirent, filldir_t filldir) | 85 | static int minix_readdir(struct file *file, struct dir_context *ctx) |
86 | { | 86 | { |
87 | unsigned long pos = filp->f_pos; | 87 | struct inode *inode = file_inode(file); |
88 | struct inode *inode = file_inode(filp); | ||
89 | struct super_block *sb = inode->i_sb; | 88 | struct super_block *sb = inode->i_sb; |
90 | unsigned offset = pos & ~PAGE_CACHE_MASK; | ||
91 | unsigned long n = pos >> PAGE_CACHE_SHIFT; | ||
92 | unsigned long npages = dir_pages(inode); | ||
93 | struct minix_sb_info *sbi = minix_sb(sb); | 89 | struct minix_sb_info *sbi = minix_sb(sb); |
94 | unsigned chunk_size = sbi->s_dirsize; | 90 | unsigned chunk_size = sbi->s_dirsize; |
95 | char *name; | 91 | unsigned long npages = dir_pages(inode); |
96 | __u32 inumber; | 92 | unsigned long pos = ctx->pos; |
93 | unsigned offset; | ||
94 | unsigned long n; | ||
97 | 95 | ||
98 | pos = (pos + chunk_size-1) & ~(chunk_size-1); | 96 | ctx->pos = pos = (pos + chunk_size-1) & ~(chunk_size-1); |
99 | if (pos >= inode->i_size) | 97 | if (pos >= inode->i_size) |
100 | goto done; | 98 | return 0; |
99 | |||
100 | offset = pos & ~PAGE_CACHE_MASK; | ||
101 | n = pos >> PAGE_CACHE_SHIFT; | ||
101 | 102 | ||
102 | for ( ; n < npages; n++, offset = 0) { | 103 | for ( ; n < npages; n++, offset = 0) { |
103 | char *p, *kaddr, *limit; | 104 | char *p, *kaddr, *limit; |
@@ -109,6 +110,8 @@ static int minix_readdir(struct file * filp, void * dirent, filldir_t filldir) | |||
109 | p = kaddr+offset; | 110 | p = kaddr+offset; |
110 | limit = kaddr + minix_last_byte(inode, n) - chunk_size; | 111 | limit = kaddr + minix_last_byte(inode, n) - chunk_size; |
111 | for ( ; p <= limit; p = minix_next_entry(p, sbi)) { | 112 | for ( ; p <= limit; p = minix_next_entry(p, sbi)) { |
113 | const char *name; | ||
114 | __u32 inumber; | ||
112 | if (sbi->s_version == MINIX_V3) { | 115 | if (sbi->s_version == MINIX_V3) { |
113 | minix3_dirent *de3 = (minix3_dirent *)p; | 116 | minix3_dirent *de3 = (minix3_dirent *)p; |
114 | name = de3->name; | 117 | name = de3->name; |
@@ -119,24 +122,17 @@ static int minix_readdir(struct file * filp, void * dirent, filldir_t filldir) | |||
119 | inumber = de->inode; | 122 | inumber = de->inode; |
120 | } | 123 | } |
121 | if (inumber) { | 124 | if (inumber) { |
122 | int over; | ||
123 | |||
124 | unsigned l = strnlen(name, sbi->s_namelen); | 125 | unsigned l = strnlen(name, sbi->s_namelen); |
125 | offset = p - kaddr; | 126 | if (!dir_emit(ctx, name, l, |
126 | over = filldir(dirent, name, l, | 127 | inumber, DT_UNKNOWN)) { |
127 | (n << PAGE_CACHE_SHIFT) | offset, | ||
128 | inumber, DT_UNKNOWN); | ||
129 | if (over) { | ||
130 | dir_put_page(page); | 128 | dir_put_page(page); |
131 | goto done; | 129 | return 0; |
132 | } | 130 | } |
133 | } | 131 | } |
132 | ctx->pos += chunk_size; | ||
134 | } | 133 | } |
135 | dir_put_page(page); | 134 | dir_put_page(page); |
136 | } | 135 | } |
137 | |||
138 | done: | ||
139 | filp->f_pos = (n << PAGE_CACHE_SHIFT) | offset; | ||
140 | return 0; | 136 | return 0; |
141 | } | 137 | } |
142 | 138 | ||
diff --git a/fs/ncpfs/dir.c b/fs/ncpfs/dir.c index 6792ce11f2bf..0e7f00298213 100644 --- a/fs/ncpfs/dir.c +++ b/fs/ncpfs/dir.c | |||
@@ -23,12 +23,12 @@ | |||
23 | 23 | ||
24 | #include "ncp_fs.h" | 24 | #include "ncp_fs.h" |
25 | 25 | ||
26 | static void ncp_read_volume_list(struct file *, void *, filldir_t, | 26 | static void ncp_read_volume_list(struct file *, struct dir_context *, |
27 | struct ncp_cache_control *); | 27 | struct ncp_cache_control *); |
28 | static void ncp_do_readdir(struct file *, void *, filldir_t, | 28 | static void ncp_do_readdir(struct file *, struct dir_context *, |
29 | struct ncp_cache_control *); | 29 | struct ncp_cache_control *); |
30 | 30 | ||
31 | static int ncp_readdir(struct file *, void *, filldir_t); | 31 | static int ncp_readdir(struct file *, struct dir_context *); |
32 | 32 | ||
33 | static int ncp_create(struct inode *, struct dentry *, umode_t, bool); | 33 | static int ncp_create(struct inode *, struct dentry *, umode_t, bool); |
34 | static struct dentry *ncp_lookup(struct inode *, struct dentry *, unsigned int); | 34 | static struct dentry *ncp_lookup(struct inode *, struct dentry *, unsigned int); |
@@ -49,7 +49,7 @@ const struct file_operations ncp_dir_operations = | |||
49 | { | 49 | { |
50 | .llseek = generic_file_llseek, | 50 | .llseek = generic_file_llseek, |
51 | .read = generic_read_dir, | 51 | .read = generic_read_dir, |
52 | .readdir = ncp_readdir, | 52 | .iterate = ncp_readdir, |
53 | .unlocked_ioctl = ncp_ioctl, | 53 | .unlocked_ioctl = ncp_ioctl, |
54 | #ifdef CONFIG_COMPAT | 54 | #ifdef CONFIG_COMPAT |
55 | .compat_ioctl = ncp_compat_ioctl, | 55 | .compat_ioctl = ncp_compat_ioctl, |
@@ -424,9 +424,9 @@ static time_t ncp_obtain_mtime(struct dentry *dentry) | |||
424 | return ncp_date_dos2unix(i.modifyTime, i.modifyDate); | 424 | return ncp_date_dos2unix(i.modifyTime, i.modifyDate); |
425 | } | 425 | } |
426 | 426 | ||
427 | static int ncp_readdir(struct file *filp, void *dirent, filldir_t filldir) | 427 | static int ncp_readdir(struct file *file, struct dir_context *ctx) |
428 | { | 428 | { |
429 | struct dentry *dentry = filp->f_path.dentry; | 429 | struct dentry *dentry = file->f_path.dentry; |
430 | struct inode *inode = dentry->d_inode; | 430 | struct inode *inode = dentry->d_inode; |
431 | struct page *page = NULL; | 431 | struct page *page = NULL; |
432 | struct ncp_server *server = NCP_SERVER(inode); | 432 | struct ncp_server *server = NCP_SERVER(inode); |
@@ -440,7 +440,7 @@ static int ncp_readdir(struct file *filp, void *dirent, filldir_t filldir) | |||
440 | 440 | ||
441 | DDPRINTK("ncp_readdir: reading %s/%s, pos=%d\n", | 441 | DDPRINTK("ncp_readdir: reading %s/%s, pos=%d\n", |
442 | dentry->d_parent->d_name.name, dentry->d_name.name, | 442 | dentry->d_parent->d_name.name, dentry->d_name.name, |
443 | (int) filp->f_pos); | 443 | (int) ctx->pos); |
444 | 444 | ||
445 | result = -EIO; | 445 | result = -EIO; |
446 | /* Do not generate '.' and '..' when server is dead. */ | 446 | /* Do not generate '.' and '..' when server is dead. */ |
@@ -448,16 +448,8 @@ static int ncp_readdir(struct file *filp, void *dirent, filldir_t filldir) | |||
448 | goto out; | 448 | goto out; |
449 | 449 | ||
450 | result = 0; | 450 | result = 0; |
451 | if (filp->f_pos == 0) { | 451 | if (!dir_emit_dots(file, ctx)) |
452 | if (filldir(dirent, ".", 1, 0, inode->i_ino, DT_DIR)) | 452 | goto out; |
453 | goto out; | ||
454 | filp->f_pos = 1; | ||
455 | } | ||
456 | if (filp->f_pos == 1) { | ||
457 | if (filldir(dirent, "..", 2, 1, parent_ino(dentry), DT_DIR)) | ||
458 | goto out; | ||
459 | filp->f_pos = 2; | ||
460 | } | ||
461 | 453 | ||
462 | page = grab_cache_page(&inode->i_data, 0); | 454 | page = grab_cache_page(&inode->i_data, 0); |
463 | if (!page) | 455 | if (!page) |
@@ -469,7 +461,7 @@ static int ncp_readdir(struct file *filp, void *dirent, filldir_t filldir) | |||
469 | if (!PageUptodate(page) || !ctl.head.eof) | 461 | if (!PageUptodate(page) || !ctl.head.eof) |
470 | goto init_cache; | 462 | goto init_cache; |
471 | 463 | ||
472 | if (filp->f_pos == 2) { | 464 | if (ctx->pos == 2) { |
473 | if (jiffies - ctl.head.time >= NCP_MAX_AGE(server)) | 465 | if (jiffies - ctl.head.time >= NCP_MAX_AGE(server)) |
474 | goto init_cache; | 466 | goto init_cache; |
475 | 467 | ||
@@ -479,10 +471,10 @@ static int ncp_readdir(struct file *filp, void *dirent, filldir_t filldir) | |||
479 | goto init_cache; | 471 | goto init_cache; |
480 | } | 472 | } |
481 | 473 | ||
482 | if (filp->f_pos > ctl.head.end) | 474 | if (ctx->pos > ctl.head.end) |
483 | goto finished; | 475 | goto finished; |
484 | 476 | ||
485 | ctl.fpos = filp->f_pos + (NCP_DIRCACHE_START - 2); | 477 | ctl.fpos = ctx->pos + (NCP_DIRCACHE_START - 2); |
486 | ctl.ofs = ctl.fpos / NCP_DIRCACHE_SIZE; | 478 | ctl.ofs = ctl.fpos / NCP_DIRCACHE_SIZE; |
487 | ctl.idx = ctl.fpos % NCP_DIRCACHE_SIZE; | 479 | ctl.idx = ctl.fpos % NCP_DIRCACHE_SIZE; |
488 | 480 | ||
@@ -497,21 +489,21 @@ static int ncp_readdir(struct file *filp, void *dirent, filldir_t filldir) | |||
497 | } | 489 | } |
498 | while (ctl.idx < NCP_DIRCACHE_SIZE) { | 490 | while (ctl.idx < NCP_DIRCACHE_SIZE) { |
499 | struct dentry *dent; | 491 | struct dentry *dent; |
500 | int res; | 492 | bool over; |
501 | 493 | ||
502 | dent = ncp_dget_fpos(ctl.cache->dentry[ctl.idx], | 494 | dent = ncp_dget_fpos(ctl.cache->dentry[ctl.idx], |
503 | dentry, filp->f_pos); | 495 | dentry, ctx->pos); |
504 | if (!dent) | 496 | if (!dent) |
505 | goto invalid_cache; | 497 | goto invalid_cache; |
506 | res = filldir(dirent, dent->d_name.name, | 498 | over = !dir_emit(ctx, dent->d_name.name, |
507 | dent->d_name.len, filp->f_pos, | 499 | dent->d_name.len, |
508 | dent->d_inode->i_ino, DT_UNKNOWN); | 500 | dent->d_inode->i_ino, DT_UNKNOWN); |
509 | dput(dent); | 501 | dput(dent); |
510 | if (res) | 502 | if (over) |
511 | goto finished; | 503 | goto finished; |
512 | filp->f_pos += 1; | 504 | ctx->pos += 1; |
513 | ctl.idx += 1; | 505 | ctl.idx += 1; |
514 | if (filp->f_pos > ctl.head.end) | 506 | if (ctx->pos > ctl.head.end) |
515 | goto finished; | 507 | goto finished; |
516 | } | 508 | } |
517 | if (ctl.page) { | 509 | if (ctl.page) { |
@@ -548,9 +540,9 @@ init_cache: | |||
548 | ctl.valid = 1; | 540 | ctl.valid = 1; |
549 | read_really: | 541 | read_really: |
550 | if (ncp_is_server_root(inode)) { | 542 | if (ncp_is_server_root(inode)) { |
551 | ncp_read_volume_list(filp, dirent, filldir, &ctl); | 543 | ncp_read_volume_list(file, ctx, &ctl); |
552 | } else { | 544 | } else { |
553 | ncp_do_readdir(filp, dirent, filldir, &ctl); | 545 | ncp_do_readdir(file, ctx, &ctl); |
554 | } | 546 | } |
555 | ctl.head.end = ctl.fpos - 1; | 547 | ctl.head.end = ctl.fpos - 1; |
556 | ctl.head.eof = ctl.valid; | 548 | ctl.head.eof = ctl.valid; |
@@ -573,11 +565,11 @@ out: | |||
573 | } | 565 | } |
574 | 566 | ||
575 | static int | 567 | static int |
576 | ncp_fill_cache(struct file *filp, void *dirent, filldir_t filldir, | 568 | ncp_fill_cache(struct file *file, struct dir_context *ctx, |
577 | struct ncp_cache_control *ctrl, struct ncp_entry_info *entry, | 569 | struct ncp_cache_control *ctrl, struct ncp_entry_info *entry, |
578 | int inval_childs) | 570 | int inval_childs) |
579 | { | 571 | { |
580 | struct dentry *newdent, *dentry = filp->f_path.dentry; | 572 | struct dentry *newdent, *dentry = file->f_path.dentry; |
581 | struct inode *dir = dentry->d_inode; | 573 | struct inode *dir = dentry->d_inode; |
582 | struct ncp_cache_control ctl = *ctrl; | 574 | struct ncp_cache_control ctl = *ctrl; |
583 | struct qstr qname; | 575 | struct qstr qname; |
@@ -666,15 +658,15 @@ ncp_fill_cache(struct file *filp, void *dirent, filldir_t filldir, | |||
666 | end_advance: | 658 | end_advance: |
667 | if (!valid) | 659 | if (!valid) |
668 | ctl.valid = 0; | 660 | ctl.valid = 0; |
669 | if (!ctl.filled && (ctl.fpos == filp->f_pos)) { | 661 | if (!ctl.filled && (ctl.fpos == ctx->pos)) { |
670 | if (!ino) | 662 | if (!ino) |
671 | ino = find_inode_number(dentry, &qname); | 663 | ino = find_inode_number(dentry, &qname); |
672 | if (!ino) | 664 | if (!ino) |
673 | ino = iunique(dir->i_sb, 2); | 665 | ino = iunique(dir->i_sb, 2); |
674 | ctl.filled = filldir(dirent, qname.name, qname.len, | 666 | ctl.filled = !dir_emit(ctx, qname.name, qname.len, |
675 | filp->f_pos, ino, DT_UNKNOWN); | 667 | ino, DT_UNKNOWN); |
676 | if (!ctl.filled) | 668 | if (!ctl.filled) |
677 | filp->f_pos += 1; | 669 | ctx->pos += 1; |
678 | } | 670 | } |
679 | ctl.fpos += 1; | 671 | ctl.fpos += 1; |
680 | ctl.idx += 1; | 672 | ctl.idx += 1; |
@@ -683,10 +675,10 @@ end_advance: | |||
683 | } | 675 | } |
684 | 676 | ||
685 | static void | 677 | static void |
686 | ncp_read_volume_list(struct file *filp, void *dirent, filldir_t filldir, | 678 | ncp_read_volume_list(struct file *file, struct dir_context *ctx, |
687 | struct ncp_cache_control *ctl) | 679 | struct ncp_cache_control *ctl) |
688 | { | 680 | { |
689 | struct dentry *dentry = filp->f_path.dentry; | 681 | struct dentry *dentry = file->f_path.dentry; |
690 | struct inode *inode = dentry->d_inode; | 682 | struct inode *inode = dentry->d_inode; |
691 | struct ncp_server *server = NCP_SERVER(inode); | 683 | struct ncp_server *server = NCP_SERVER(inode); |
692 | struct ncp_volume_info info; | 684 | struct ncp_volume_info info; |
@@ -694,7 +686,7 @@ ncp_read_volume_list(struct file *filp, void *dirent, filldir_t filldir, | |||
694 | int i; | 686 | int i; |
695 | 687 | ||
696 | DPRINTK("ncp_read_volume_list: pos=%ld\n", | 688 | DPRINTK("ncp_read_volume_list: pos=%ld\n", |
697 | (unsigned long) filp->f_pos); | 689 | (unsigned long) ctx->pos); |
698 | 690 | ||
699 | for (i = 0; i < NCP_NUMBER_OF_VOLUMES; i++) { | 691 | for (i = 0; i < NCP_NUMBER_OF_VOLUMES; i++) { |
700 | int inval_dentry; | 692 | int inval_dentry; |
@@ -715,16 +707,16 @@ ncp_read_volume_list(struct file *filp, void *dirent, filldir_t filldir, | |||
715 | } | 707 | } |
716 | inval_dentry = ncp_update_known_namespace(server, entry.i.volNumber, NULL); | 708 | inval_dentry = ncp_update_known_namespace(server, entry.i.volNumber, NULL); |
717 | entry.volume = entry.i.volNumber; | 709 | entry.volume = entry.i.volNumber; |
718 | if (!ncp_fill_cache(filp, dirent, filldir, ctl, &entry, inval_dentry)) | 710 | if (!ncp_fill_cache(file, ctx, ctl, &entry, inval_dentry)) |
719 | return; | 711 | return; |
720 | } | 712 | } |
721 | } | 713 | } |
722 | 714 | ||
723 | static void | 715 | static void |
724 | ncp_do_readdir(struct file *filp, void *dirent, filldir_t filldir, | 716 | ncp_do_readdir(struct file *file, struct dir_context *ctx, |
725 | struct ncp_cache_control *ctl) | 717 | struct ncp_cache_control *ctl) |
726 | { | 718 | { |
727 | struct dentry *dentry = filp->f_path.dentry; | 719 | struct dentry *dentry = file->f_path.dentry; |
728 | struct inode *dir = dentry->d_inode; | 720 | struct inode *dir = dentry->d_inode; |
729 | struct ncp_server *server = NCP_SERVER(dir); | 721 | struct ncp_server *server = NCP_SERVER(dir); |
730 | struct nw_search_sequence seq; | 722 | struct nw_search_sequence seq; |
@@ -736,7 +728,7 @@ ncp_do_readdir(struct file *filp, void *dirent, filldir_t filldir, | |||
736 | 728 | ||
737 | DPRINTK("ncp_do_readdir: %s/%s, fpos=%ld\n", | 729 | DPRINTK("ncp_do_readdir: %s/%s, fpos=%ld\n", |
738 | dentry->d_parent->d_name.name, dentry->d_name.name, | 730 | dentry->d_parent->d_name.name, dentry->d_name.name, |
739 | (unsigned long) filp->f_pos); | 731 | (unsigned long) ctx->pos); |
740 | PPRINTK("ncp_do_readdir: init %s, volnum=%d, dirent=%u\n", | 732 | PPRINTK("ncp_do_readdir: init %s, volnum=%d, dirent=%u\n", |
741 | dentry->d_name.name, NCP_FINFO(dir)->volNumber, | 733 | dentry->d_name.name, NCP_FINFO(dir)->volNumber, |
742 | NCP_FINFO(dir)->dirEntNum); | 734 | NCP_FINFO(dir)->dirEntNum); |
@@ -778,7 +770,7 @@ ncp_do_readdir(struct file *filp, void *dirent, filldir_t filldir, | |||
778 | rpl += onerpl; | 770 | rpl += onerpl; |
779 | rpls -= onerpl; | 771 | rpls -= onerpl; |
780 | entry.volume = entry.i.volNumber; | 772 | entry.volume = entry.i.volNumber; |
781 | if (!ncp_fill_cache(filp, dirent, filldir, ctl, &entry, 0)) | 773 | if (!ncp_fill_cache(file, ctx, ctl, &entry, 0)) |
782 | break; | 774 | break; |
783 | } | 775 | } |
784 | } while (more); | 776 | } while (more); |
diff --git a/fs/nfs/dir.c b/fs/nfs/dir.c index e093e73178b7..5d051419527b 100644 --- a/fs/nfs/dir.c +++ b/fs/nfs/dir.c | |||
@@ -46,7 +46,7 @@ | |||
46 | 46 | ||
47 | static int nfs_opendir(struct inode *, struct file *); | 47 | static int nfs_opendir(struct inode *, struct file *); |
48 | static int nfs_closedir(struct inode *, struct file *); | 48 | static int nfs_closedir(struct inode *, struct file *); |
49 | static int nfs_readdir(struct file *, void *, filldir_t); | 49 | static int nfs_readdir(struct file *, struct dir_context *); |
50 | static int nfs_fsync_dir(struct file *, loff_t, loff_t, int); | 50 | static int nfs_fsync_dir(struct file *, loff_t, loff_t, int); |
51 | static loff_t nfs_llseek_dir(struct file *, loff_t, int); | 51 | static loff_t nfs_llseek_dir(struct file *, loff_t, int); |
52 | static void nfs_readdir_clear_array(struct page*); | 52 | static void nfs_readdir_clear_array(struct page*); |
@@ -54,7 +54,7 @@ static void nfs_readdir_clear_array(struct page*); | |||
54 | const struct file_operations nfs_dir_operations = { | 54 | const struct file_operations nfs_dir_operations = { |
55 | .llseek = nfs_llseek_dir, | 55 | .llseek = nfs_llseek_dir, |
56 | .read = generic_read_dir, | 56 | .read = generic_read_dir, |
57 | .readdir = nfs_readdir, | 57 | .iterate = nfs_readdir, |
58 | .open = nfs_opendir, | 58 | .open = nfs_opendir, |
59 | .release = nfs_closedir, | 59 | .release = nfs_closedir, |
60 | .fsync = nfs_fsync_dir, | 60 | .fsync = nfs_fsync_dir, |
@@ -147,6 +147,7 @@ typedef int (*decode_dirent_t)(struct xdr_stream *, struct nfs_entry *, int); | |||
147 | typedef struct { | 147 | typedef struct { |
148 | struct file *file; | 148 | struct file *file; |
149 | struct page *page; | 149 | struct page *page; |
150 | struct dir_context *ctx; | ||
150 | unsigned long page_index; | 151 | unsigned long page_index; |
151 | u64 *dir_cookie; | 152 | u64 *dir_cookie; |
152 | u64 last_cookie; | 153 | u64 last_cookie; |
@@ -252,7 +253,7 @@ out: | |||
252 | static | 253 | static |
253 | int nfs_readdir_search_for_pos(struct nfs_cache_array *array, nfs_readdir_descriptor_t *desc) | 254 | int nfs_readdir_search_for_pos(struct nfs_cache_array *array, nfs_readdir_descriptor_t *desc) |
254 | { | 255 | { |
255 | loff_t diff = desc->file->f_pos - desc->current_index; | 256 | loff_t diff = desc->ctx->pos - desc->current_index; |
256 | unsigned int index; | 257 | unsigned int index; |
257 | 258 | ||
258 | if (diff < 0) | 259 | if (diff < 0) |
@@ -289,7 +290,7 @@ int nfs_readdir_search_for_cookie(struct nfs_cache_array *array, nfs_readdir_des | |||
289 | || (nfsi->cache_validity & (NFS_INO_INVALID_ATTR|NFS_INO_INVALID_DATA))) { | 290 | || (nfsi->cache_validity & (NFS_INO_INVALID_ATTR|NFS_INO_INVALID_DATA))) { |
290 | ctx->duped = 0; | 291 | ctx->duped = 0; |
291 | ctx->attr_gencount = nfsi->attr_gencount; | 292 | ctx->attr_gencount = nfsi->attr_gencount; |
292 | } else if (new_pos < desc->file->f_pos) { | 293 | } else if (new_pos < desc->ctx->pos) { |
293 | if (ctx->duped > 0 | 294 | if (ctx->duped > 0 |
294 | && ctx->dup_cookie == *desc->dir_cookie) { | 295 | && ctx->dup_cookie == *desc->dir_cookie) { |
295 | if (printk_ratelimit()) { | 296 | if (printk_ratelimit()) { |
@@ -307,7 +308,7 @@ int nfs_readdir_search_for_cookie(struct nfs_cache_array *array, nfs_readdir_des | |||
307 | ctx->dup_cookie = *desc->dir_cookie; | 308 | ctx->dup_cookie = *desc->dir_cookie; |
308 | ctx->duped = -1; | 309 | ctx->duped = -1; |
309 | } | 310 | } |
310 | desc->file->f_pos = new_pos; | 311 | desc->ctx->pos = new_pos; |
311 | desc->cache_entry_index = i; | 312 | desc->cache_entry_index = i; |
312 | return 0; | 313 | return 0; |
313 | } | 314 | } |
@@ -405,13 +406,13 @@ different: | |||
405 | } | 406 | } |
406 | 407 | ||
407 | static | 408 | static |
408 | bool nfs_use_readdirplus(struct inode *dir, struct file *filp) | 409 | bool nfs_use_readdirplus(struct inode *dir, struct dir_context *ctx) |
409 | { | 410 | { |
410 | if (!nfs_server_capable(dir, NFS_CAP_READDIRPLUS)) | 411 | if (!nfs_server_capable(dir, NFS_CAP_READDIRPLUS)) |
411 | return false; | 412 | return false; |
412 | if (test_and_clear_bit(NFS_INO_ADVISE_RDPLUS, &NFS_I(dir)->flags)) | 413 | if (test_and_clear_bit(NFS_INO_ADVISE_RDPLUS, &NFS_I(dir)->flags)) |
413 | return true; | 414 | return true; |
414 | if (filp->f_pos == 0) | 415 | if (ctx->pos == 0) |
415 | return true; | 416 | return true; |
416 | return false; | 417 | return false; |
417 | } | 418 | } |
@@ -702,8 +703,7 @@ int readdir_search_pagecache(nfs_readdir_descriptor_t *desc) | |||
702 | * Once we've found the start of the dirent within a page: fill 'er up... | 703 | * Once we've found the start of the dirent within a page: fill 'er up... |
703 | */ | 704 | */ |
704 | static | 705 | static |
705 | int nfs_do_filldir(nfs_readdir_descriptor_t *desc, void *dirent, | 706 | int nfs_do_filldir(nfs_readdir_descriptor_t *desc) |
706 | filldir_t filldir) | ||
707 | { | 707 | { |
708 | struct file *file = desc->file; | 708 | struct file *file = desc->file; |
709 | int i = 0; | 709 | int i = 0; |
@@ -721,13 +721,12 @@ int nfs_do_filldir(nfs_readdir_descriptor_t *desc, void *dirent, | |||
721 | struct nfs_cache_array_entry *ent; | 721 | struct nfs_cache_array_entry *ent; |
722 | 722 | ||
723 | ent = &array->array[i]; | 723 | ent = &array->array[i]; |
724 | if (filldir(dirent, ent->string.name, ent->string.len, | 724 | if (!dir_emit(desc->ctx, ent->string.name, ent->string.len, |
725 | file->f_pos, nfs_compat_user_ino64(ent->ino), | 725 | nfs_compat_user_ino64(ent->ino), ent->d_type)) { |
726 | ent->d_type) < 0) { | ||
727 | desc->eof = 1; | 726 | desc->eof = 1; |
728 | break; | 727 | break; |
729 | } | 728 | } |
730 | file->f_pos++; | 729 | desc->ctx->pos++; |
731 | if (i < (array->size-1)) | 730 | if (i < (array->size-1)) |
732 | *desc->dir_cookie = array->array[i+1].cookie; | 731 | *desc->dir_cookie = array->array[i+1].cookie; |
733 | else | 732 | else |
@@ -759,8 +758,7 @@ out: | |||
759 | * directory in the page cache by the time we get here. | 758 | * directory in the page cache by the time we get here. |
760 | */ | 759 | */ |
761 | static inline | 760 | static inline |
762 | int uncached_readdir(nfs_readdir_descriptor_t *desc, void *dirent, | 761 | int uncached_readdir(nfs_readdir_descriptor_t *desc) |
763 | filldir_t filldir) | ||
764 | { | 762 | { |
765 | struct page *page = NULL; | 763 | struct page *page = NULL; |
766 | int status; | 764 | int status; |
@@ -785,7 +783,7 @@ int uncached_readdir(nfs_readdir_descriptor_t *desc, void *dirent, | |||
785 | if (status < 0) | 783 | if (status < 0) |
786 | goto out_release; | 784 | goto out_release; |
787 | 785 | ||
788 | status = nfs_do_filldir(desc, dirent, filldir); | 786 | status = nfs_do_filldir(desc); |
789 | 787 | ||
790 | out: | 788 | out: |
791 | dfprintk(DIRCACHE, "NFS: %s: returns %d\n", | 789 | dfprintk(DIRCACHE, "NFS: %s: returns %d\n", |
@@ -800,35 +798,36 @@ int uncached_readdir(nfs_readdir_descriptor_t *desc, void *dirent, | |||
800 | last cookie cache takes care of the common case of reading the | 798 | last cookie cache takes care of the common case of reading the |
801 | whole directory. | 799 | whole directory. |
802 | */ | 800 | */ |
803 | static int nfs_readdir(struct file *filp, void *dirent, filldir_t filldir) | 801 | static int nfs_readdir(struct file *file, struct dir_context *ctx) |
804 | { | 802 | { |
805 | struct dentry *dentry = filp->f_path.dentry; | 803 | struct dentry *dentry = file->f_path.dentry; |
806 | struct inode *inode = dentry->d_inode; | 804 | struct inode *inode = dentry->d_inode; |
807 | nfs_readdir_descriptor_t my_desc, | 805 | nfs_readdir_descriptor_t my_desc, |
808 | *desc = &my_desc; | 806 | *desc = &my_desc; |
809 | struct nfs_open_dir_context *dir_ctx = filp->private_data; | 807 | struct nfs_open_dir_context *dir_ctx = file->private_data; |
810 | int res; | 808 | int res; |
811 | 809 | ||
812 | dfprintk(FILE, "NFS: readdir(%s/%s) starting at cookie %llu\n", | 810 | dfprintk(FILE, "NFS: readdir(%s/%s) starting at cookie %llu\n", |
813 | dentry->d_parent->d_name.name, dentry->d_name.name, | 811 | dentry->d_parent->d_name.name, dentry->d_name.name, |
814 | (long long)filp->f_pos); | 812 | (long long)ctx->pos); |
815 | nfs_inc_stats(inode, NFSIOS_VFSGETDENTS); | 813 | nfs_inc_stats(inode, NFSIOS_VFSGETDENTS); |
816 | 814 | ||
817 | /* | 815 | /* |
818 | * filp->f_pos points to the dirent entry number. | 816 | * ctx->pos points to the dirent entry number. |
819 | * *desc->dir_cookie has the cookie for the next entry. We have | 817 | * *desc->dir_cookie has the cookie for the next entry. We have |
820 | * to either find the entry with the appropriate number or | 818 | * to either find the entry with the appropriate number or |
821 | * revalidate the cookie. | 819 | * revalidate the cookie. |
822 | */ | 820 | */ |
823 | memset(desc, 0, sizeof(*desc)); | 821 | memset(desc, 0, sizeof(*desc)); |
824 | 822 | ||
825 | desc->file = filp; | 823 | desc->file = file; |
824 | desc->ctx = ctx; | ||
826 | desc->dir_cookie = &dir_ctx->dir_cookie; | 825 | desc->dir_cookie = &dir_ctx->dir_cookie; |
827 | desc->decode = NFS_PROTO(inode)->decode_dirent; | 826 | desc->decode = NFS_PROTO(inode)->decode_dirent; |
828 | desc->plus = nfs_use_readdirplus(inode, filp) ? 1 : 0; | 827 | desc->plus = nfs_use_readdirplus(inode, ctx) ? 1 : 0; |
829 | 828 | ||
830 | nfs_block_sillyrename(dentry); | 829 | nfs_block_sillyrename(dentry); |
831 | res = nfs_revalidate_mapping(inode, filp->f_mapping); | 830 | res = nfs_revalidate_mapping(inode, file->f_mapping); |
832 | if (res < 0) | 831 | if (res < 0) |
833 | goto out; | 832 | goto out; |
834 | 833 | ||
@@ -840,7 +839,7 @@ static int nfs_readdir(struct file *filp, void *dirent, filldir_t filldir) | |||
840 | /* This means either end of directory */ | 839 | /* This means either end of directory */ |
841 | if (*desc->dir_cookie && desc->eof == 0) { | 840 | if (*desc->dir_cookie && desc->eof == 0) { |
842 | /* Or that the server has 'lost' a cookie */ | 841 | /* Or that the server has 'lost' a cookie */ |
843 | res = uncached_readdir(desc, dirent, filldir); | 842 | res = uncached_readdir(desc); |
844 | if (res == 0) | 843 | if (res == 0) |
845 | continue; | 844 | continue; |
846 | } | 845 | } |
@@ -857,7 +856,7 @@ static int nfs_readdir(struct file *filp, void *dirent, filldir_t filldir) | |||
857 | if (res < 0) | 856 | if (res < 0) |
858 | break; | 857 | break; |
859 | 858 | ||
860 | res = nfs_do_filldir(desc, dirent, filldir); | 859 | res = nfs_do_filldir(desc); |
861 | if (res < 0) | 860 | if (res < 0) |
862 | break; | 861 | break; |
863 | } while (!desc->eof); | 862 | } while (!desc->eof); |
diff --git a/fs/nfsd/nfs4recover.c b/fs/nfsd/nfs4recover.c index 4e9a21db867a..105a3b080d12 100644 --- a/fs/nfsd/nfs4recover.c +++ b/fs/nfsd/nfs4recover.c | |||
@@ -240,11 +240,16 @@ struct name_list { | |||
240 | struct list_head list; | 240 | struct list_head list; |
241 | }; | 241 | }; |
242 | 242 | ||
243 | struct nfs4_dir_ctx { | ||
244 | struct dir_context ctx; | ||
245 | struct list_head names; | ||
246 | }; | ||
247 | |||
243 | static int | 248 | static int |
244 | nfsd4_build_namelist(void *arg, const char *name, int namlen, | 249 | nfsd4_build_namelist(void *arg, const char *name, int namlen, |
245 | loff_t offset, u64 ino, unsigned int d_type) | 250 | loff_t offset, u64 ino, unsigned int d_type) |
246 | { | 251 | { |
247 | struct list_head *names = arg; | 252 | struct nfs4_dir_ctx *ctx = arg; |
248 | struct name_list *entry; | 253 | struct name_list *entry; |
249 | 254 | ||
250 | if (namlen != HEXDIR_LEN - 1) | 255 | if (namlen != HEXDIR_LEN - 1) |
@@ -254,7 +259,7 @@ nfsd4_build_namelist(void *arg, const char *name, int namlen, | |||
254 | return -ENOMEM; | 259 | return -ENOMEM; |
255 | memcpy(entry->name, name, HEXDIR_LEN - 1); | 260 | memcpy(entry->name, name, HEXDIR_LEN - 1); |
256 | entry->name[HEXDIR_LEN - 1] = '\0'; | 261 | entry->name[HEXDIR_LEN - 1] = '\0'; |
257 | list_add(&entry->list, names); | 262 | list_add(&entry->list, &ctx->names); |
258 | return 0; | 263 | return 0; |
259 | } | 264 | } |
260 | 265 | ||
@@ -263,7 +268,10 @@ nfsd4_list_rec_dir(recdir_func *f, struct nfsd_net *nn) | |||
263 | { | 268 | { |
264 | const struct cred *original_cred; | 269 | const struct cred *original_cred; |
265 | struct dentry *dir = nn->rec_file->f_path.dentry; | 270 | struct dentry *dir = nn->rec_file->f_path.dentry; |
266 | LIST_HEAD(names); | 271 | struct nfs4_dir_ctx ctx = { |
272 | .ctx.actor = nfsd4_build_namelist, | ||
273 | .names = LIST_HEAD_INIT(ctx.names) | ||
274 | }; | ||
267 | int status; | 275 | int status; |
268 | 276 | ||
269 | status = nfs4_save_creds(&original_cred); | 277 | status = nfs4_save_creds(&original_cred); |
@@ -276,11 +284,11 @@ nfsd4_list_rec_dir(recdir_func *f, struct nfsd_net *nn) | |||
276 | return status; | 284 | return status; |
277 | } | 285 | } |
278 | 286 | ||
279 | status = vfs_readdir(nn->rec_file, nfsd4_build_namelist, &names); | 287 | status = iterate_dir(nn->rec_file, &ctx.ctx); |
280 | mutex_lock_nested(&dir->d_inode->i_mutex, I_MUTEX_PARENT); | 288 | mutex_lock_nested(&dir->d_inode->i_mutex, I_MUTEX_PARENT); |
281 | while (!list_empty(&names)) { | 289 | while (!list_empty(&ctx.names)) { |
282 | struct name_list *entry; | 290 | struct name_list *entry; |
283 | entry = list_entry(names.next, struct name_list, list); | 291 | entry = list_entry(ctx.names.next, struct name_list, list); |
284 | if (!status) { | 292 | if (!status) { |
285 | struct dentry *dentry; | 293 | struct dentry *dentry; |
286 | dentry = lookup_one_len(entry->name, dir, HEXDIR_LEN-1); | 294 | dentry = lookup_one_len(entry->name, dir, HEXDIR_LEN-1); |
diff --git a/fs/nfsd/vfs.c b/fs/nfsd/vfs.c index 84ce601d8063..a6bc8a7423db 100644 --- a/fs/nfsd/vfs.c +++ b/fs/nfsd/vfs.c | |||
@@ -1912,6 +1912,7 @@ struct buffered_dirent { | |||
1912 | }; | 1912 | }; |
1913 | 1913 | ||
1914 | struct readdir_data { | 1914 | struct readdir_data { |
1915 | struct dir_context ctx; | ||
1915 | char *dirent; | 1916 | char *dirent; |
1916 | size_t used; | 1917 | size_t used; |
1917 | int full; | 1918 | int full; |
@@ -1943,13 +1944,15 @@ static int nfsd_buffered_filldir(void *__buf, const char *name, int namlen, | |||
1943 | static __be32 nfsd_buffered_readdir(struct file *file, filldir_t func, | 1944 | static __be32 nfsd_buffered_readdir(struct file *file, filldir_t func, |
1944 | struct readdir_cd *cdp, loff_t *offsetp) | 1945 | struct readdir_cd *cdp, loff_t *offsetp) |
1945 | { | 1946 | { |
1946 | struct readdir_data buf; | ||
1947 | struct buffered_dirent *de; | 1947 | struct buffered_dirent *de; |
1948 | int host_err; | 1948 | int host_err; |
1949 | int size; | 1949 | int size; |
1950 | loff_t offset; | 1950 | loff_t offset; |
1951 | struct readdir_data buf = { | ||
1952 | .ctx.actor = nfsd_buffered_filldir, | ||
1953 | .dirent = (void *)__get_free_page(GFP_KERNEL) | ||
1954 | }; | ||
1951 | 1955 | ||
1952 | buf.dirent = (void *)__get_free_page(GFP_KERNEL); | ||
1953 | if (!buf.dirent) | 1956 | if (!buf.dirent) |
1954 | return nfserrno(-ENOMEM); | 1957 | return nfserrno(-ENOMEM); |
1955 | 1958 | ||
@@ -1963,7 +1966,7 @@ static __be32 nfsd_buffered_readdir(struct file *file, filldir_t func, | |||
1963 | buf.used = 0; | 1966 | buf.used = 0; |
1964 | buf.full = 0; | 1967 | buf.full = 0; |
1965 | 1968 | ||
1966 | host_err = vfs_readdir(file, nfsd_buffered_filldir, &buf); | 1969 | host_err = iterate_dir(file, &buf.ctx); |
1967 | if (buf.full) | 1970 | if (buf.full) |
1968 | host_err = 0; | 1971 | host_err = 0; |
1969 | 1972 | ||
diff --git a/fs/nilfs2/dir.c b/fs/nilfs2/dir.c index f30b017740a7..197a63e9d102 100644 --- a/fs/nilfs2/dir.c +++ b/fs/nilfs2/dir.c | |||
@@ -256,22 +256,18 @@ static void nilfs_set_de_type(struct nilfs_dir_entry *de, struct inode *inode) | |||
256 | de->file_type = nilfs_type_by_mode[(mode & S_IFMT)>>S_SHIFT]; | 256 | de->file_type = nilfs_type_by_mode[(mode & S_IFMT)>>S_SHIFT]; |
257 | } | 257 | } |
258 | 258 | ||
259 | static int nilfs_readdir(struct file *filp, void *dirent, filldir_t filldir) | 259 | static int nilfs_readdir(struct file *file, struct dir_context *ctx) |
260 | { | 260 | { |
261 | loff_t pos = filp->f_pos; | 261 | loff_t pos = ctx->pos; |
262 | struct inode *inode = file_inode(filp); | 262 | struct inode *inode = file_inode(file); |
263 | struct super_block *sb = inode->i_sb; | 263 | struct super_block *sb = inode->i_sb; |
264 | unsigned int offset = pos & ~PAGE_CACHE_MASK; | 264 | unsigned int offset = pos & ~PAGE_CACHE_MASK; |
265 | unsigned long n = pos >> PAGE_CACHE_SHIFT; | 265 | unsigned long n = pos >> PAGE_CACHE_SHIFT; |
266 | unsigned long npages = dir_pages(inode); | 266 | unsigned long npages = dir_pages(inode); |
267 | /* unsigned chunk_mask = ~(nilfs_chunk_size(inode)-1); */ | 267 | /* unsigned chunk_mask = ~(nilfs_chunk_size(inode)-1); */ |
268 | unsigned char *types = NULL; | ||
269 | int ret; | ||
270 | 268 | ||
271 | if (pos > inode->i_size - NILFS_DIR_REC_LEN(1)) | 269 | if (pos > inode->i_size - NILFS_DIR_REC_LEN(1)) |
272 | goto success; | 270 | return 0; |
273 | |||
274 | types = nilfs_filetype_table; | ||
275 | 271 | ||
276 | for ( ; n < npages; n++, offset = 0) { | 272 | for ( ; n < npages; n++, offset = 0) { |
277 | char *kaddr, *limit; | 273 | char *kaddr, *limit; |
@@ -281,9 +277,8 @@ static int nilfs_readdir(struct file *filp, void *dirent, filldir_t filldir) | |||
281 | if (IS_ERR(page)) { | 277 | if (IS_ERR(page)) { |
282 | nilfs_error(sb, __func__, "bad page in #%lu", | 278 | nilfs_error(sb, __func__, "bad page in #%lu", |
283 | inode->i_ino); | 279 | inode->i_ino); |
284 | filp->f_pos += PAGE_CACHE_SIZE - offset; | 280 | ctx->pos += PAGE_CACHE_SIZE - offset; |
285 | ret = -EIO; | 281 | return -EIO; |
286 | goto done; | ||
287 | } | 282 | } |
288 | kaddr = page_address(page); | 283 | kaddr = page_address(page); |
289 | de = (struct nilfs_dir_entry *)(kaddr + offset); | 284 | de = (struct nilfs_dir_entry *)(kaddr + offset); |
@@ -293,35 +288,28 @@ static int nilfs_readdir(struct file *filp, void *dirent, filldir_t filldir) | |||
293 | if (de->rec_len == 0) { | 288 | if (de->rec_len == 0) { |
294 | nilfs_error(sb, __func__, | 289 | nilfs_error(sb, __func__, |
295 | "zero-length directory entry"); | 290 | "zero-length directory entry"); |
296 | ret = -EIO; | ||
297 | nilfs_put_page(page); | 291 | nilfs_put_page(page); |
298 | goto done; | 292 | return -EIO; |
299 | } | 293 | } |
300 | if (de->inode) { | 294 | if (de->inode) { |
301 | int over; | 295 | unsigned char t; |
302 | unsigned char d_type = DT_UNKNOWN; | ||
303 | 296 | ||
304 | if (types && de->file_type < NILFS_FT_MAX) | 297 | if (de->file_type < NILFS_FT_MAX) |
305 | d_type = types[de->file_type]; | 298 | t = nilfs_filetype_table[de->file_type]; |
299 | else | ||
300 | t = DT_UNKNOWN; | ||
306 | 301 | ||
307 | offset = (char *)de - kaddr; | 302 | if (!dir_emit(ctx, de->name, de->name_len, |
308 | over = filldir(dirent, de->name, de->name_len, | 303 | le64_to_cpu(de->inode), t)) { |
309 | (n<<PAGE_CACHE_SHIFT) | offset, | ||
310 | le64_to_cpu(de->inode), d_type); | ||
311 | if (over) { | ||
312 | nilfs_put_page(page); | 304 | nilfs_put_page(page); |
313 | goto success; | 305 | return 0; |
314 | } | 306 | } |
315 | } | 307 | } |
316 | filp->f_pos += nilfs_rec_len_from_disk(de->rec_len); | 308 | ctx->pos += nilfs_rec_len_from_disk(de->rec_len); |
317 | } | 309 | } |
318 | nilfs_put_page(page); | 310 | nilfs_put_page(page); |
319 | } | 311 | } |
320 | 312 | return 0; | |
321 | success: | ||
322 | ret = 0; | ||
323 | done: | ||
324 | return ret; | ||
325 | } | 313 | } |
326 | 314 | ||
327 | /* | 315 | /* |
@@ -678,7 +666,7 @@ not_empty: | |||
678 | const struct file_operations nilfs_dir_operations = { | 666 | const struct file_operations nilfs_dir_operations = { |
679 | .llseek = generic_file_llseek, | 667 | .llseek = generic_file_llseek, |
680 | .read = generic_read_dir, | 668 | .read = generic_read_dir, |
681 | .readdir = nilfs_readdir, | 669 | .iterate = nilfs_readdir, |
682 | .unlocked_ioctl = nilfs_ioctl, | 670 | .unlocked_ioctl = nilfs_ioctl, |
683 | #ifdef CONFIG_COMPAT | 671 | #ifdef CONFIG_COMPAT |
684 | .compat_ioctl = nilfs_compat_ioctl, | 672 | .compat_ioctl = nilfs_compat_ioctl, |
diff --git a/fs/ntfs/dir.c b/fs/ntfs/dir.c index aa411c3f20e9..9e38dafa3bc7 100644 --- a/fs/ntfs/dir.c +++ b/fs/ntfs/dir.c | |||
@@ -1004,13 +1004,11 @@ dir_err_out: | |||
1004 | /** | 1004 | /** |
1005 | * ntfs_filldir - ntfs specific filldir method | 1005 | * ntfs_filldir - ntfs specific filldir method |
1006 | * @vol: current ntfs volume | 1006 | * @vol: current ntfs volume |
1007 | * @fpos: position in the directory | ||
1008 | * @ndir: ntfs inode of current directory | 1007 | * @ndir: ntfs inode of current directory |
1009 | * @ia_page: page in which the index allocation buffer @ie is in resides | 1008 | * @ia_page: page in which the index allocation buffer @ie is in resides |
1010 | * @ie: current index entry | 1009 | * @ie: current index entry |
1011 | * @name: buffer to use for the converted name | 1010 | * @name: buffer to use for the converted name |
1012 | * @dirent: vfs filldir callback context | 1011 | * @actor: what to feed the entries to |
1013 | * @filldir: vfs filldir callback | ||
1014 | * | 1012 | * |
1015 | * Convert the Unicode @name to the loaded NLS and pass it to the @filldir | 1013 | * Convert the Unicode @name to the loaded NLS and pass it to the @filldir |
1016 | * callback. | 1014 | * callback. |
@@ -1024,12 +1022,12 @@ dir_err_out: | |||
1024 | * retake the lock if we are returning a non-zero value as ntfs_readdir() | 1022 | * retake the lock if we are returning a non-zero value as ntfs_readdir() |
1025 | * would need to drop the lock immediately anyway. | 1023 | * would need to drop the lock immediately anyway. |
1026 | */ | 1024 | */ |
1027 | static inline int ntfs_filldir(ntfs_volume *vol, loff_t fpos, | 1025 | static inline int ntfs_filldir(ntfs_volume *vol, |
1028 | ntfs_inode *ndir, struct page *ia_page, INDEX_ENTRY *ie, | 1026 | ntfs_inode *ndir, struct page *ia_page, INDEX_ENTRY *ie, |
1029 | u8 *name, void *dirent, filldir_t filldir) | 1027 | u8 *name, struct dir_context *actor) |
1030 | { | 1028 | { |
1031 | unsigned long mref; | 1029 | unsigned long mref; |
1032 | int name_len, rc; | 1030 | int name_len; |
1033 | unsigned dt_type; | 1031 | unsigned dt_type; |
1034 | FILE_NAME_TYPE_FLAGS name_type; | 1032 | FILE_NAME_TYPE_FLAGS name_type; |
1035 | 1033 | ||
@@ -1068,13 +1066,14 @@ static inline int ntfs_filldir(ntfs_volume *vol, loff_t fpos, | |||
1068 | if (ia_page) | 1066 | if (ia_page) |
1069 | unlock_page(ia_page); | 1067 | unlock_page(ia_page); |
1070 | ntfs_debug("Calling filldir for %s with len %i, fpos 0x%llx, inode " | 1068 | ntfs_debug("Calling filldir for %s with len %i, fpos 0x%llx, inode " |
1071 | "0x%lx, DT_%s.", name, name_len, fpos, mref, | 1069 | "0x%lx, DT_%s.", name, name_len, actor->pos, mref, |
1072 | dt_type == DT_DIR ? "DIR" : "REG"); | 1070 | dt_type == DT_DIR ? "DIR" : "REG"); |
1073 | rc = filldir(dirent, name, name_len, fpos, mref, dt_type); | 1071 | if (!dir_emit(actor, name, name_len, mref, dt_type)) |
1072 | return 1; | ||
1074 | /* Relock the page but not if we are aborting ->readdir. */ | 1073 | /* Relock the page but not if we are aborting ->readdir. */ |
1075 | if (!rc && ia_page) | 1074 | if (ia_page) |
1076 | lock_page(ia_page); | 1075 | lock_page(ia_page); |
1077 | return rc; | 1076 | return 0; |
1078 | } | 1077 | } |
1079 | 1078 | ||
1080 | /* | 1079 | /* |
@@ -1097,11 +1096,11 @@ static inline int ntfs_filldir(ntfs_volume *vol, loff_t fpos, | |||
1097 | * removes them again after the write is complete after which it | 1096 | * removes them again after the write is complete after which it |
1098 | * unlocks the page. | 1097 | * unlocks the page. |
1099 | */ | 1098 | */ |
1100 | static int ntfs_readdir(struct file *filp, void *dirent, filldir_t filldir) | 1099 | static int ntfs_readdir(struct file *file, struct dir_context *actor) |
1101 | { | 1100 | { |
1102 | s64 ia_pos, ia_start, prev_ia_pos, bmp_pos; | 1101 | s64 ia_pos, ia_start, prev_ia_pos, bmp_pos; |
1103 | loff_t fpos, i_size; | 1102 | loff_t i_size; |
1104 | struct inode *bmp_vi, *vdir = file_inode(filp); | 1103 | struct inode *bmp_vi, *vdir = file_inode(file); |
1105 | struct super_block *sb = vdir->i_sb; | 1104 | struct super_block *sb = vdir->i_sb; |
1106 | ntfs_inode *ndir = NTFS_I(vdir); | 1105 | ntfs_inode *ndir = NTFS_I(vdir); |
1107 | ntfs_volume *vol = NTFS_SB(sb); | 1106 | ntfs_volume *vol = NTFS_SB(sb); |
@@ -1116,33 +1115,16 @@ static int ntfs_readdir(struct file *filp, void *dirent, filldir_t filldir) | |||
1116 | u8 *kaddr, *bmp, *index_end; | 1115 | u8 *kaddr, *bmp, *index_end; |
1117 | ntfs_attr_search_ctx *ctx; | 1116 | ntfs_attr_search_ctx *ctx; |
1118 | 1117 | ||
1119 | fpos = filp->f_pos; | ||
1120 | ntfs_debug("Entering for inode 0x%lx, fpos 0x%llx.", | 1118 | ntfs_debug("Entering for inode 0x%lx, fpos 0x%llx.", |
1121 | vdir->i_ino, fpos); | 1119 | vdir->i_ino, actor->pos); |
1122 | rc = err = 0; | 1120 | rc = err = 0; |
1123 | /* Are we at end of dir yet? */ | 1121 | /* Are we at end of dir yet? */ |
1124 | i_size = i_size_read(vdir); | 1122 | i_size = i_size_read(vdir); |
1125 | if (fpos >= i_size + vol->mft_record_size) | 1123 | if (actor->pos >= i_size + vol->mft_record_size) |
1126 | goto done; | 1124 | return 0; |
1127 | /* Emulate . and .. for all directories. */ | 1125 | /* Emulate . and .. for all directories. */ |
1128 | if (!fpos) { | 1126 | if (!dir_emit_dots(file, actor)) |
1129 | ntfs_debug("Calling filldir for . with len 1, fpos 0x0, " | 1127 | return 0; |
1130 | "inode 0x%lx, DT_DIR.", vdir->i_ino); | ||
1131 | rc = filldir(dirent, ".", 1, fpos, vdir->i_ino, DT_DIR); | ||
1132 | if (rc) | ||
1133 | goto done; | ||
1134 | fpos++; | ||
1135 | } | ||
1136 | if (fpos == 1) { | ||
1137 | ntfs_debug("Calling filldir for .. with len 2, fpos 0x1, " | ||
1138 | "inode 0x%lx, DT_DIR.", | ||
1139 | (unsigned long)parent_ino(filp->f_path.dentry)); | ||
1140 | rc = filldir(dirent, "..", 2, fpos, | ||
1141 | parent_ino(filp->f_path.dentry), DT_DIR); | ||
1142 | if (rc) | ||
1143 | goto done; | ||
1144 | fpos++; | ||
1145 | } | ||
1146 | m = NULL; | 1128 | m = NULL; |
1147 | ctx = NULL; | 1129 | ctx = NULL; |
1148 | /* | 1130 | /* |
@@ -1155,7 +1137,7 @@ static int ntfs_readdir(struct file *filp, void *dirent, filldir_t filldir) | |||
1155 | goto err_out; | 1137 | goto err_out; |
1156 | } | 1138 | } |
1157 | /* Are we jumping straight into the index allocation attribute? */ | 1139 | /* Are we jumping straight into the index allocation attribute? */ |
1158 | if (fpos >= vol->mft_record_size) | 1140 | if (actor->pos >= vol->mft_record_size) |
1159 | goto skip_index_root; | 1141 | goto skip_index_root; |
1160 | /* Get hold of the mft record for the directory. */ | 1142 | /* Get hold of the mft record for the directory. */ |
1161 | m = map_mft_record(ndir); | 1143 | m = map_mft_record(ndir); |
@@ -1170,7 +1152,7 @@ static int ntfs_readdir(struct file *filp, void *dirent, filldir_t filldir) | |||
1170 | goto err_out; | 1152 | goto err_out; |
1171 | } | 1153 | } |
1172 | /* Get the offset into the index root attribute. */ | 1154 | /* Get the offset into the index root attribute. */ |
1173 | ir_pos = (s64)fpos; | 1155 | ir_pos = (s64)actor->pos; |
1174 | /* Find the index root attribute in the mft record. */ | 1156 | /* Find the index root attribute in the mft record. */ |
1175 | err = ntfs_attr_lookup(AT_INDEX_ROOT, I30, 4, CASE_SENSITIVE, 0, NULL, | 1157 | err = ntfs_attr_lookup(AT_INDEX_ROOT, I30, 4, CASE_SENSITIVE, 0, NULL, |
1176 | 0, ctx); | 1158 | 0, ctx); |
@@ -1226,10 +1208,9 @@ static int ntfs_readdir(struct file *filp, void *dirent, filldir_t filldir) | |||
1226 | if (ir_pos > (u8*)ie - (u8*)ir) | 1208 | if (ir_pos > (u8*)ie - (u8*)ir) |
1227 | continue; | 1209 | continue; |
1228 | /* Advance the position even if going to skip the entry. */ | 1210 | /* Advance the position even if going to skip the entry. */ |
1229 | fpos = (u8*)ie - (u8*)ir; | 1211 | actor->pos = (u8*)ie - (u8*)ir; |
1230 | /* Submit the name to the filldir callback. */ | 1212 | /* Submit the name to the filldir callback. */ |
1231 | rc = ntfs_filldir(vol, fpos, ndir, NULL, ie, name, dirent, | 1213 | rc = ntfs_filldir(vol, ndir, NULL, ie, name, actor); |
1232 | filldir); | ||
1233 | if (rc) { | 1214 | if (rc) { |
1234 | kfree(ir); | 1215 | kfree(ir); |
1235 | goto abort; | 1216 | goto abort; |
@@ -1242,12 +1223,12 @@ static int ntfs_readdir(struct file *filp, void *dirent, filldir_t filldir) | |||
1242 | if (!NInoIndexAllocPresent(ndir)) | 1223 | if (!NInoIndexAllocPresent(ndir)) |
1243 | goto EOD; | 1224 | goto EOD; |
1244 | /* Advance fpos to the beginning of the index allocation. */ | 1225 | /* Advance fpos to the beginning of the index allocation. */ |
1245 | fpos = vol->mft_record_size; | 1226 | actor->pos = vol->mft_record_size; |
1246 | skip_index_root: | 1227 | skip_index_root: |
1247 | kaddr = NULL; | 1228 | kaddr = NULL; |
1248 | prev_ia_pos = -1LL; | 1229 | prev_ia_pos = -1LL; |
1249 | /* Get the offset into the index allocation attribute. */ | 1230 | /* Get the offset into the index allocation attribute. */ |
1250 | ia_pos = (s64)fpos - vol->mft_record_size; | 1231 | ia_pos = (s64)actor->pos - vol->mft_record_size; |
1251 | ia_mapping = vdir->i_mapping; | 1232 | ia_mapping = vdir->i_mapping; |
1252 | ntfs_debug("Inode 0x%lx, getting index bitmap.", vdir->i_ino); | 1233 | ntfs_debug("Inode 0x%lx, getting index bitmap.", vdir->i_ino); |
1253 | bmp_vi = ntfs_attr_iget(vdir, AT_BITMAP, I30, 4); | 1234 | bmp_vi = ntfs_attr_iget(vdir, AT_BITMAP, I30, 4); |
@@ -1409,7 +1390,7 @@ find_next_index_buffer: | |||
1409 | if (ia_pos - ia_start > (u8*)ie - (u8*)ia) | 1390 | if (ia_pos - ia_start > (u8*)ie - (u8*)ia) |
1410 | continue; | 1391 | continue; |
1411 | /* Advance the position even if going to skip the entry. */ | 1392 | /* Advance the position even if going to skip the entry. */ |
1412 | fpos = (u8*)ie - (u8*)ia + | 1393 | actor->pos = (u8*)ie - (u8*)ia + |
1413 | (sle64_to_cpu(ia->index_block_vcn) << | 1394 | (sle64_to_cpu(ia->index_block_vcn) << |
1414 | ndir->itype.index.vcn_size_bits) + | 1395 | ndir->itype.index.vcn_size_bits) + |
1415 | vol->mft_record_size; | 1396 | vol->mft_record_size; |
@@ -1419,8 +1400,7 @@ find_next_index_buffer: | |||
1419 | * before returning, unless a non-zero value is returned in | 1400 | * before returning, unless a non-zero value is returned in |
1420 | * which case the page is left unlocked. | 1401 | * which case the page is left unlocked. |
1421 | */ | 1402 | */ |
1422 | rc = ntfs_filldir(vol, fpos, ndir, ia_page, ie, name, dirent, | 1403 | rc = ntfs_filldir(vol, ndir, ia_page, ie, name, actor); |
1423 | filldir); | ||
1424 | if (rc) { | 1404 | if (rc) { |
1425 | /* @ia_page is already unlocked in this case. */ | 1405 | /* @ia_page is already unlocked in this case. */ |
1426 | ntfs_unmap_page(ia_page); | 1406 | ntfs_unmap_page(ia_page); |
@@ -1439,18 +1419,9 @@ unm_EOD: | |||
1439 | iput(bmp_vi); | 1419 | iput(bmp_vi); |
1440 | EOD: | 1420 | EOD: |
1441 | /* We are finished, set fpos to EOD. */ | 1421 | /* We are finished, set fpos to EOD. */ |
1442 | fpos = i_size + vol->mft_record_size; | 1422 | actor->pos = i_size + vol->mft_record_size; |
1443 | abort: | 1423 | abort: |
1444 | kfree(name); | 1424 | kfree(name); |
1445 | done: | ||
1446 | #ifdef DEBUG | ||
1447 | if (!rc) | ||
1448 | ntfs_debug("EOD, fpos 0x%llx, returning 0.", fpos); | ||
1449 | else | ||
1450 | ntfs_debug("filldir returned %i, fpos 0x%llx, returning 0.", | ||
1451 | rc, fpos); | ||
1452 | #endif | ||
1453 | filp->f_pos = fpos; | ||
1454 | return 0; | 1425 | return 0; |
1455 | err_out: | 1426 | err_out: |
1456 | if (bmp_page) { | 1427 | if (bmp_page) { |
@@ -1471,7 +1442,6 @@ iput_err_out: | |||
1471 | if (!err) | 1442 | if (!err) |
1472 | err = -EIO; | 1443 | err = -EIO; |
1473 | ntfs_debug("Failed. Returning error code %i.", -err); | 1444 | ntfs_debug("Failed. Returning error code %i.", -err); |
1474 | filp->f_pos = fpos; | ||
1475 | return err; | 1445 | return err; |
1476 | } | 1446 | } |
1477 | 1447 | ||
@@ -1571,7 +1541,7 @@ static int ntfs_dir_fsync(struct file *filp, loff_t start, loff_t end, | |||
1571 | const struct file_operations ntfs_dir_ops = { | 1541 | const struct file_operations ntfs_dir_ops = { |
1572 | .llseek = generic_file_llseek, /* Seek inside directory. */ | 1542 | .llseek = generic_file_llseek, /* Seek inside directory. */ |
1573 | .read = generic_read_dir, /* Return -EISDIR. */ | 1543 | .read = generic_read_dir, /* Return -EISDIR. */ |
1574 | .readdir = ntfs_readdir, /* Read directory contents. */ | 1544 | .iterate = ntfs_readdir, /* Read directory contents. */ |
1575 | #ifdef NTFS_RW | 1545 | #ifdef NTFS_RW |
1576 | .fsync = ntfs_dir_fsync, /* Sync a directory to disk. */ | 1546 | .fsync = ntfs_dir_fsync, /* Sync a directory to disk. */ |
1577 | /*.aio_fsync = ,*/ /* Sync all outstanding async | 1547 | /*.aio_fsync = ,*/ /* Sync all outstanding async |
diff --git a/fs/ocfs2/dir.c b/fs/ocfs2/dir.c index f1e1aed8f638..eb760d8acd50 100644 --- a/fs/ocfs2/dir.c +++ b/fs/ocfs2/dir.c | |||
@@ -1761,11 +1761,10 @@ bail: | |||
1761 | 1761 | ||
1762 | static int ocfs2_dir_foreach_blk_id(struct inode *inode, | 1762 | static int ocfs2_dir_foreach_blk_id(struct inode *inode, |
1763 | u64 *f_version, | 1763 | u64 *f_version, |
1764 | loff_t *f_pos, void *priv, | 1764 | struct dir_context *ctx) |
1765 | filldir_t filldir, int *filldir_err) | ||
1766 | { | 1765 | { |
1767 | int ret, i, filldir_ret; | 1766 | int ret, i; |
1768 | unsigned long offset = *f_pos; | 1767 | unsigned long offset = ctx->pos; |
1769 | struct buffer_head *di_bh = NULL; | 1768 | struct buffer_head *di_bh = NULL; |
1770 | struct ocfs2_dinode *di; | 1769 | struct ocfs2_dinode *di; |
1771 | struct ocfs2_inline_data *data; | 1770 | struct ocfs2_inline_data *data; |
@@ -1781,8 +1780,7 @@ static int ocfs2_dir_foreach_blk_id(struct inode *inode, | |||
1781 | di = (struct ocfs2_dinode *)di_bh->b_data; | 1780 | di = (struct ocfs2_dinode *)di_bh->b_data; |
1782 | data = &di->id2.i_data; | 1781 | data = &di->id2.i_data; |
1783 | 1782 | ||
1784 | while (*f_pos < i_size_read(inode)) { | 1783 | while (ctx->pos < i_size_read(inode)) { |
1785 | revalidate: | ||
1786 | /* If the dir block has changed since the last call to | 1784 | /* If the dir block has changed since the last call to |
1787 | * readdir(2), then we might be pointing to an invalid | 1785 | * readdir(2), then we might be pointing to an invalid |
1788 | * dirent right now. Scan from the start of the block | 1786 | * dirent right now. Scan from the start of the block |
@@ -1802,50 +1800,31 @@ revalidate: | |||
1802 | break; | 1800 | break; |
1803 | i += le16_to_cpu(de->rec_len); | 1801 | i += le16_to_cpu(de->rec_len); |
1804 | } | 1802 | } |
1805 | *f_pos = offset = i; | 1803 | ctx->pos = offset = i; |
1806 | *f_version = inode->i_version; | 1804 | *f_version = inode->i_version; |
1807 | } | 1805 | } |
1808 | 1806 | ||
1809 | de = (struct ocfs2_dir_entry *) (data->id_data + *f_pos); | 1807 | de = (struct ocfs2_dir_entry *) (data->id_data + ctx->pos); |
1810 | if (!ocfs2_check_dir_entry(inode, de, di_bh, *f_pos)) { | 1808 | if (!ocfs2_check_dir_entry(inode, de, di_bh, ctx->pos)) { |
1811 | /* On error, skip the f_pos to the end. */ | 1809 | /* On error, skip the f_pos to the end. */ |
1812 | *f_pos = i_size_read(inode); | 1810 | ctx->pos = i_size_read(inode); |
1813 | goto out; | 1811 | break; |
1814 | } | 1812 | } |
1815 | offset += le16_to_cpu(de->rec_len); | 1813 | offset += le16_to_cpu(de->rec_len); |
1816 | if (le64_to_cpu(de->inode)) { | 1814 | if (le64_to_cpu(de->inode)) { |
1817 | /* We might block in the next section | ||
1818 | * if the data destination is | ||
1819 | * currently swapped out. So, use a | ||
1820 | * version stamp to detect whether or | ||
1821 | * not the directory has been modified | ||
1822 | * during the copy operation. | ||
1823 | */ | ||
1824 | u64 version = *f_version; | ||
1825 | unsigned char d_type = DT_UNKNOWN; | 1815 | unsigned char d_type = DT_UNKNOWN; |
1826 | 1816 | ||
1827 | if (de->file_type < OCFS2_FT_MAX) | 1817 | if (de->file_type < OCFS2_FT_MAX) |
1828 | d_type = ocfs2_filetype_table[de->file_type]; | 1818 | d_type = ocfs2_filetype_table[de->file_type]; |
1829 | 1819 | ||
1830 | filldir_ret = filldir(priv, de->name, | 1820 | if (!dir_emit(ctx, de->name, de->name_len, |
1831 | de->name_len, | 1821 | le64_to_cpu(de->inode), d_type)) |
1832 | *f_pos, | 1822 | goto out; |
1833 | le64_to_cpu(de->inode), | ||
1834 | d_type); | ||
1835 | if (filldir_ret) { | ||
1836 | if (filldir_err) | ||
1837 | *filldir_err = filldir_ret; | ||
1838 | break; | ||
1839 | } | ||
1840 | if (version != *f_version) | ||
1841 | goto revalidate; | ||
1842 | } | 1823 | } |
1843 | *f_pos += le16_to_cpu(de->rec_len); | 1824 | ctx->pos += le16_to_cpu(de->rec_len); |
1844 | } | 1825 | } |
1845 | |||
1846 | out: | 1826 | out: |
1847 | brelse(di_bh); | 1827 | brelse(di_bh); |
1848 | |||
1849 | return 0; | 1828 | return 0; |
1850 | } | 1829 | } |
1851 | 1830 | ||
@@ -1855,27 +1834,26 @@ out: | |||
1855 | */ | 1834 | */ |
1856 | static int ocfs2_dir_foreach_blk_el(struct inode *inode, | 1835 | static int ocfs2_dir_foreach_blk_el(struct inode *inode, |
1857 | u64 *f_version, | 1836 | u64 *f_version, |
1858 | loff_t *f_pos, void *priv, | 1837 | struct dir_context *ctx, |
1859 | filldir_t filldir, int *filldir_err) | 1838 | bool persist) |
1860 | { | 1839 | { |
1861 | int error = 0; | ||
1862 | unsigned long offset, blk, last_ra_blk = 0; | 1840 | unsigned long offset, blk, last_ra_blk = 0; |
1863 | int i, stored; | 1841 | int i; |
1864 | struct buffer_head * bh, * tmp; | 1842 | struct buffer_head * bh, * tmp; |
1865 | struct ocfs2_dir_entry * de; | 1843 | struct ocfs2_dir_entry * de; |
1866 | struct super_block * sb = inode->i_sb; | 1844 | struct super_block * sb = inode->i_sb; |
1867 | unsigned int ra_sectors = 16; | 1845 | unsigned int ra_sectors = 16; |
1846 | int stored = 0; | ||
1868 | 1847 | ||
1869 | stored = 0; | ||
1870 | bh = NULL; | 1848 | bh = NULL; |
1871 | 1849 | ||
1872 | offset = (*f_pos) & (sb->s_blocksize - 1); | 1850 | offset = ctx->pos & (sb->s_blocksize - 1); |
1873 | 1851 | ||
1874 | while (!error && !stored && *f_pos < i_size_read(inode)) { | 1852 | while (ctx->pos < i_size_read(inode)) { |
1875 | blk = (*f_pos) >> sb->s_blocksize_bits; | 1853 | blk = ctx->pos >> sb->s_blocksize_bits; |
1876 | if (ocfs2_read_dir_block(inode, blk, &bh, 0)) { | 1854 | if (ocfs2_read_dir_block(inode, blk, &bh, 0)) { |
1877 | /* Skip the corrupt dirblock and keep trying */ | 1855 | /* Skip the corrupt dirblock and keep trying */ |
1878 | *f_pos += sb->s_blocksize - offset; | 1856 | ctx->pos += sb->s_blocksize - offset; |
1879 | continue; | 1857 | continue; |
1880 | } | 1858 | } |
1881 | 1859 | ||
@@ -1897,7 +1875,6 @@ static int ocfs2_dir_foreach_blk_el(struct inode *inode, | |||
1897 | ra_sectors = 8; | 1875 | ra_sectors = 8; |
1898 | } | 1876 | } |
1899 | 1877 | ||
1900 | revalidate: | ||
1901 | /* If the dir block has changed since the last call to | 1878 | /* If the dir block has changed since the last call to |
1902 | * readdir(2), then we might be pointing to an invalid | 1879 | * readdir(2), then we might be pointing to an invalid |
1903 | * dirent right now. Scan from the start of the block | 1880 | * dirent right now. Scan from the start of the block |
@@ -1917,93 +1894,64 @@ revalidate: | |||
1917 | i += le16_to_cpu(de->rec_len); | 1894 | i += le16_to_cpu(de->rec_len); |
1918 | } | 1895 | } |
1919 | offset = i; | 1896 | offset = i; |
1920 | *f_pos = ((*f_pos) & ~(sb->s_blocksize - 1)) | 1897 | ctx->pos = (ctx->pos & ~(sb->s_blocksize - 1)) |
1921 | | offset; | 1898 | | offset; |
1922 | *f_version = inode->i_version; | 1899 | *f_version = inode->i_version; |
1923 | } | 1900 | } |
1924 | 1901 | ||
1925 | while (!error && *f_pos < i_size_read(inode) | 1902 | while (ctx->pos < i_size_read(inode) |
1926 | && offset < sb->s_blocksize) { | 1903 | && offset < sb->s_blocksize) { |
1927 | de = (struct ocfs2_dir_entry *) (bh->b_data + offset); | 1904 | de = (struct ocfs2_dir_entry *) (bh->b_data + offset); |
1928 | if (!ocfs2_check_dir_entry(inode, de, bh, offset)) { | 1905 | if (!ocfs2_check_dir_entry(inode, de, bh, offset)) { |
1929 | /* On error, skip the f_pos to the | 1906 | /* On error, skip the f_pos to the |
1930 | next block. */ | 1907 | next block. */ |
1931 | *f_pos = ((*f_pos) | (sb->s_blocksize - 1)) + 1; | 1908 | ctx->pos = (ctx->pos | (sb->s_blocksize - 1)) + 1; |
1932 | brelse(bh); | 1909 | brelse(bh); |
1933 | goto out; | 1910 | continue; |
1934 | } | 1911 | } |
1935 | offset += le16_to_cpu(de->rec_len); | ||
1936 | if (le64_to_cpu(de->inode)) { | 1912 | if (le64_to_cpu(de->inode)) { |
1937 | /* We might block in the next section | ||
1938 | * if the data destination is | ||
1939 | * currently swapped out. So, use a | ||
1940 | * version stamp to detect whether or | ||
1941 | * not the directory has been modified | ||
1942 | * during the copy operation. | ||
1943 | */ | ||
1944 | unsigned long version = *f_version; | ||
1945 | unsigned char d_type = DT_UNKNOWN; | 1913 | unsigned char d_type = DT_UNKNOWN; |
1946 | 1914 | ||
1947 | if (de->file_type < OCFS2_FT_MAX) | 1915 | if (de->file_type < OCFS2_FT_MAX) |
1948 | d_type = ocfs2_filetype_table[de->file_type]; | 1916 | d_type = ocfs2_filetype_table[de->file_type]; |
1949 | error = filldir(priv, de->name, | 1917 | if (!dir_emit(ctx, de->name, |
1950 | de->name_len, | 1918 | de->name_len, |
1951 | *f_pos, | ||
1952 | le64_to_cpu(de->inode), | 1919 | le64_to_cpu(de->inode), |
1953 | d_type); | 1920 | d_type)) { |
1954 | if (error) { | 1921 | brelse(bh); |
1955 | if (filldir_err) | 1922 | return 0; |
1956 | *filldir_err = error; | ||
1957 | break; | ||
1958 | } | 1923 | } |
1959 | if (version != *f_version) | 1924 | stored++; |
1960 | goto revalidate; | ||
1961 | stored ++; | ||
1962 | } | 1925 | } |
1963 | *f_pos += le16_to_cpu(de->rec_len); | 1926 | offset += le16_to_cpu(de->rec_len); |
1927 | ctx->pos += le16_to_cpu(de->rec_len); | ||
1964 | } | 1928 | } |
1965 | offset = 0; | 1929 | offset = 0; |
1966 | brelse(bh); | 1930 | brelse(bh); |
1967 | bh = NULL; | 1931 | bh = NULL; |
1932 | if (!persist && stored) | ||
1933 | break; | ||
1968 | } | 1934 | } |
1969 | 1935 | return 0; | |
1970 | stored = 0; | ||
1971 | out: | ||
1972 | return stored; | ||
1973 | } | 1936 | } |
1974 | 1937 | ||
1975 | static int ocfs2_dir_foreach_blk(struct inode *inode, u64 *f_version, | 1938 | static int ocfs2_dir_foreach_blk(struct inode *inode, u64 *f_version, |
1976 | loff_t *f_pos, void *priv, filldir_t filldir, | 1939 | struct dir_context *ctx, |
1977 | int *filldir_err) | 1940 | bool persist) |
1978 | { | 1941 | { |
1979 | if (OCFS2_I(inode)->ip_dyn_features & OCFS2_INLINE_DATA_FL) | 1942 | if (OCFS2_I(inode)->ip_dyn_features & OCFS2_INLINE_DATA_FL) |
1980 | return ocfs2_dir_foreach_blk_id(inode, f_version, f_pos, priv, | 1943 | return ocfs2_dir_foreach_blk_id(inode, f_version, ctx); |
1981 | filldir, filldir_err); | 1944 | return ocfs2_dir_foreach_blk_el(inode, f_version, ctx, persist); |
1982 | |||
1983 | return ocfs2_dir_foreach_blk_el(inode, f_version, f_pos, priv, filldir, | ||
1984 | filldir_err); | ||
1985 | } | 1945 | } |
1986 | 1946 | ||
1987 | /* | 1947 | /* |
1988 | * This is intended to be called from inside other kernel functions, | 1948 | * This is intended to be called from inside other kernel functions, |
1989 | * so we fake some arguments. | 1949 | * so we fake some arguments. |
1990 | */ | 1950 | */ |
1991 | int ocfs2_dir_foreach(struct inode *inode, loff_t *f_pos, void *priv, | 1951 | int ocfs2_dir_foreach(struct inode *inode, struct dir_context *ctx) |
1992 | filldir_t filldir) | ||
1993 | { | 1952 | { |
1994 | int ret = 0, filldir_err = 0; | ||
1995 | u64 version = inode->i_version; | 1953 | u64 version = inode->i_version; |
1996 | 1954 | ocfs2_dir_foreach_blk(inode, &version, ctx, true); | |
1997 | while (*f_pos < i_size_read(inode)) { | ||
1998 | ret = ocfs2_dir_foreach_blk(inode, &version, f_pos, priv, | ||
1999 | filldir, &filldir_err); | ||
2000 | if (ret || filldir_err) | ||
2001 | break; | ||
2002 | } | ||
2003 | |||
2004 | if (ret > 0) | ||
2005 | ret = -EIO; | ||
2006 | |||
2007 | return 0; | 1955 | return 0; |
2008 | } | 1956 | } |
2009 | 1957 | ||
@@ -2011,15 +1959,15 @@ int ocfs2_dir_foreach(struct inode *inode, loff_t *f_pos, void *priv, | |||
2011 | * ocfs2_readdir() | 1959 | * ocfs2_readdir() |
2012 | * | 1960 | * |
2013 | */ | 1961 | */ |
2014 | int ocfs2_readdir(struct file * filp, void * dirent, filldir_t filldir) | 1962 | int ocfs2_readdir(struct file *file, struct dir_context *ctx) |
2015 | { | 1963 | { |
2016 | int error = 0; | 1964 | int error = 0; |
2017 | struct inode *inode = file_inode(filp); | 1965 | struct inode *inode = file_inode(file); |
2018 | int lock_level = 0; | 1966 | int lock_level = 0; |
2019 | 1967 | ||
2020 | trace_ocfs2_readdir((unsigned long long)OCFS2_I(inode)->ip_blkno); | 1968 | trace_ocfs2_readdir((unsigned long long)OCFS2_I(inode)->ip_blkno); |
2021 | 1969 | ||
2022 | error = ocfs2_inode_lock_atime(inode, filp->f_path.mnt, &lock_level); | 1970 | error = ocfs2_inode_lock_atime(inode, file->f_path.mnt, &lock_level); |
2023 | if (lock_level && error >= 0) { | 1971 | if (lock_level && error >= 0) { |
2024 | /* We release EX lock which used to update atime | 1972 | /* We release EX lock which used to update atime |
2025 | * and get PR lock again to reduce contention | 1973 | * and get PR lock again to reduce contention |
@@ -2035,8 +1983,7 @@ int ocfs2_readdir(struct file * filp, void * dirent, filldir_t filldir) | |||
2035 | goto bail_nolock; | 1983 | goto bail_nolock; |
2036 | } | 1984 | } |
2037 | 1985 | ||
2038 | error = ocfs2_dir_foreach_blk(inode, &filp->f_version, &filp->f_pos, | 1986 | error = ocfs2_dir_foreach_blk(inode, &file->f_version, ctx, false); |
2039 | dirent, filldir, NULL); | ||
2040 | 1987 | ||
2041 | ocfs2_inode_unlock(inode, lock_level); | 1988 | ocfs2_inode_unlock(inode, lock_level); |
2042 | if (error) | 1989 | if (error) |
@@ -2120,6 +2067,7 @@ bail: | |||
2120 | } | 2067 | } |
2121 | 2068 | ||
2122 | struct ocfs2_empty_dir_priv { | 2069 | struct ocfs2_empty_dir_priv { |
2070 | struct dir_context ctx; | ||
2123 | unsigned seen_dot; | 2071 | unsigned seen_dot; |
2124 | unsigned seen_dot_dot; | 2072 | unsigned seen_dot_dot; |
2125 | unsigned seen_other; | 2073 | unsigned seen_other; |
@@ -2204,8 +2152,9 @@ out: | |||
2204 | int ocfs2_empty_dir(struct inode *inode) | 2152 | int ocfs2_empty_dir(struct inode *inode) |
2205 | { | 2153 | { |
2206 | int ret; | 2154 | int ret; |
2207 | loff_t start = 0; | 2155 | struct ocfs2_empty_dir_priv priv = { |
2208 | struct ocfs2_empty_dir_priv priv; | 2156 | .ctx.actor = ocfs2_empty_dir_filldir |
2157 | }; | ||
2209 | 2158 | ||
2210 | memset(&priv, 0, sizeof(priv)); | 2159 | memset(&priv, 0, sizeof(priv)); |
2211 | 2160 | ||
@@ -2219,7 +2168,7 @@ int ocfs2_empty_dir(struct inode *inode) | |||
2219 | */ | 2168 | */ |
2220 | } | 2169 | } |
2221 | 2170 | ||
2222 | ret = ocfs2_dir_foreach(inode, &start, &priv, ocfs2_empty_dir_filldir); | 2171 | ret = ocfs2_dir_foreach(inode, &priv.ctx); |
2223 | if (ret) | 2172 | if (ret) |
2224 | mlog_errno(ret); | 2173 | mlog_errno(ret); |
2225 | 2174 | ||
diff --git a/fs/ocfs2/dir.h b/fs/ocfs2/dir.h index e683f3deb645..f0344b75b14d 100644 --- a/fs/ocfs2/dir.h +++ b/fs/ocfs2/dir.h | |||
@@ -92,9 +92,8 @@ int ocfs2_find_files_on_disk(const char *name, | |||
92 | struct ocfs2_dir_lookup_result *res); | 92 | struct ocfs2_dir_lookup_result *res); |
93 | int ocfs2_lookup_ino_from_name(struct inode *dir, const char *name, | 93 | int ocfs2_lookup_ino_from_name(struct inode *dir, const char *name, |
94 | int namelen, u64 *blkno); | 94 | int namelen, u64 *blkno); |
95 | int ocfs2_readdir(struct file *filp, void *dirent, filldir_t filldir); | 95 | int ocfs2_readdir(struct file *file, struct dir_context *ctx); |
96 | int ocfs2_dir_foreach(struct inode *inode, loff_t *f_pos, void *priv, | 96 | int ocfs2_dir_foreach(struct inode *inode, struct dir_context *ctx); |
97 | filldir_t filldir); | ||
98 | int ocfs2_prepare_dir_for_insert(struct ocfs2_super *osb, | 97 | int ocfs2_prepare_dir_for_insert(struct ocfs2_super *osb, |
99 | struct inode *dir, | 98 | struct inode *dir, |
100 | struct buffer_head *parent_fe_bh, | 99 | struct buffer_head *parent_fe_bh, |
diff --git a/fs/ocfs2/file.c b/fs/ocfs2/file.c index ff54014a24ec..8a38714f1d92 100644 --- a/fs/ocfs2/file.c +++ b/fs/ocfs2/file.c | |||
@@ -2712,7 +2712,7 @@ const struct file_operations ocfs2_fops = { | |||
2712 | const struct file_operations ocfs2_dops = { | 2712 | const struct file_operations ocfs2_dops = { |
2713 | .llseek = generic_file_llseek, | 2713 | .llseek = generic_file_llseek, |
2714 | .read = generic_read_dir, | 2714 | .read = generic_read_dir, |
2715 | .readdir = ocfs2_readdir, | 2715 | .iterate = ocfs2_readdir, |
2716 | .fsync = ocfs2_sync_file, | 2716 | .fsync = ocfs2_sync_file, |
2717 | .release = ocfs2_dir_release, | 2717 | .release = ocfs2_dir_release, |
2718 | .open = ocfs2_dir_open, | 2718 | .open = ocfs2_dir_open, |
@@ -2759,7 +2759,7 @@ const struct file_operations ocfs2_fops_no_plocks = { | |||
2759 | const struct file_operations ocfs2_dops_no_plocks = { | 2759 | const struct file_operations ocfs2_dops_no_plocks = { |
2760 | .llseek = generic_file_llseek, | 2760 | .llseek = generic_file_llseek, |
2761 | .read = generic_read_dir, | 2761 | .read = generic_read_dir, |
2762 | .readdir = ocfs2_readdir, | 2762 | .iterate = ocfs2_readdir, |
2763 | .fsync = ocfs2_sync_file, | 2763 | .fsync = ocfs2_sync_file, |
2764 | .release = ocfs2_dir_release, | 2764 | .release = ocfs2_dir_release, |
2765 | .open = ocfs2_dir_open, | 2765 | .open = ocfs2_dir_open, |
diff --git a/fs/ocfs2/journal.c b/fs/ocfs2/journal.c index 8eccfabcd12e..242170d83971 100644 --- a/fs/ocfs2/journal.c +++ b/fs/ocfs2/journal.c | |||
@@ -1941,6 +1941,7 @@ void ocfs2_orphan_scan_start(struct ocfs2_super *osb) | |||
1941 | } | 1941 | } |
1942 | 1942 | ||
1943 | struct ocfs2_orphan_filldir_priv { | 1943 | struct ocfs2_orphan_filldir_priv { |
1944 | struct dir_context ctx; | ||
1944 | struct inode *head; | 1945 | struct inode *head; |
1945 | struct ocfs2_super *osb; | 1946 | struct ocfs2_super *osb; |
1946 | }; | 1947 | }; |
@@ -1977,11 +1978,11 @@ static int ocfs2_queue_orphans(struct ocfs2_super *osb, | |||
1977 | { | 1978 | { |
1978 | int status; | 1979 | int status; |
1979 | struct inode *orphan_dir_inode = NULL; | 1980 | struct inode *orphan_dir_inode = NULL; |
1980 | struct ocfs2_orphan_filldir_priv priv; | 1981 | struct ocfs2_orphan_filldir_priv priv = { |
1981 | loff_t pos = 0; | 1982 | .ctx.actor = ocfs2_orphan_filldir, |
1982 | 1983 | .osb = osb, | |
1983 | priv.osb = osb; | 1984 | .head = *head |
1984 | priv.head = *head; | 1985 | }; |
1985 | 1986 | ||
1986 | orphan_dir_inode = ocfs2_get_system_file_inode(osb, | 1987 | orphan_dir_inode = ocfs2_get_system_file_inode(osb, |
1987 | ORPHAN_DIR_SYSTEM_INODE, | 1988 | ORPHAN_DIR_SYSTEM_INODE, |
@@ -1999,8 +2000,7 @@ static int ocfs2_queue_orphans(struct ocfs2_super *osb, | |||
1999 | goto out; | 2000 | goto out; |
2000 | } | 2001 | } |
2001 | 2002 | ||
2002 | status = ocfs2_dir_foreach(orphan_dir_inode, &pos, &priv, | 2003 | status = ocfs2_dir_foreach(orphan_dir_inode, &priv.ctx); |
2003 | ocfs2_orphan_filldir); | ||
2004 | if (status) { | 2004 | if (status) { |
2005 | mlog_errno(status); | 2005 | mlog_errno(status); |
2006 | goto out_cluster; | 2006 | goto out_cluster; |
diff --git a/fs/omfs/dir.c b/fs/omfs/dir.c index acbaebcad3a8..1b8e9e8405b2 100644 --- a/fs/omfs/dir.c +++ b/fs/omfs/dir.c | |||
@@ -327,26 +327,23 @@ int omfs_is_bad(struct omfs_sb_info *sbi, struct omfs_header *header, | |||
327 | return is_bad; | 327 | return is_bad; |
328 | } | 328 | } |
329 | 329 | ||
330 | static int omfs_fill_chain(struct file *filp, void *dirent, filldir_t filldir, | 330 | static bool omfs_fill_chain(struct inode *dir, struct dir_context *ctx, |
331 | u64 fsblock, int hindex) | 331 | u64 fsblock, int hindex) |
332 | { | 332 | { |
333 | struct inode *dir = file_inode(filp); | ||
334 | struct buffer_head *bh; | ||
335 | struct omfs_inode *oi; | ||
336 | u64 self; | ||
337 | int res = 0; | ||
338 | unsigned char d_type; | ||
339 | |||
340 | /* follow chain in this bucket */ | 333 | /* follow chain in this bucket */ |
341 | while (fsblock != ~0) { | 334 | while (fsblock != ~0) { |
342 | bh = omfs_bread(dir->i_sb, fsblock); | 335 | struct buffer_head *bh = omfs_bread(dir->i_sb, fsblock); |
336 | struct omfs_inode *oi; | ||
337 | u64 self; | ||
338 | unsigned char d_type; | ||
339 | |||
343 | if (!bh) | 340 | if (!bh) |
344 | goto out; | 341 | return true; |
345 | 342 | ||
346 | oi = (struct omfs_inode *) bh->b_data; | 343 | oi = (struct omfs_inode *) bh->b_data; |
347 | if (omfs_is_bad(OMFS_SB(dir->i_sb), &oi->i_head, fsblock)) { | 344 | if (omfs_is_bad(OMFS_SB(dir->i_sb), &oi->i_head, fsblock)) { |
348 | brelse(bh); | 345 | brelse(bh); |
349 | goto out; | 346 | return true; |
350 | } | 347 | } |
351 | 348 | ||
352 | self = fsblock; | 349 | self = fsblock; |
@@ -361,15 +358,16 @@ static int omfs_fill_chain(struct file *filp, void *dirent, filldir_t filldir, | |||
361 | 358 | ||
362 | d_type = (oi->i_type == OMFS_DIR) ? DT_DIR : DT_REG; | 359 | d_type = (oi->i_type == OMFS_DIR) ? DT_DIR : DT_REG; |
363 | 360 | ||
364 | res = filldir(dirent, oi->i_name, strnlen(oi->i_name, | 361 | if (!dir_emit(ctx, oi->i_name, |
365 | OMFS_NAMELEN), filp->f_pos, self, d_type); | 362 | strnlen(oi->i_name, OMFS_NAMELEN), |
363 | self, d_type)) { | ||
364 | brelse(bh); | ||
365 | return false; | ||
366 | } | ||
366 | brelse(bh); | 367 | brelse(bh); |
367 | if (res < 0) | 368 | ctx->pos++; |
368 | break; | ||
369 | filp->f_pos++; | ||
370 | } | 369 | } |
371 | out: | 370 | return true; |
372 | return res; | ||
373 | } | 371 | } |
374 | 372 | ||
375 | static int omfs_rename(struct inode *old_dir, struct dentry *old_dentry, | 373 | static int omfs_rename(struct inode *old_dir, struct dentry *old_dentry, |
@@ -403,60 +401,44 @@ out: | |||
403 | return err; | 401 | return err; |
404 | } | 402 | } |
405 | 403 | ||
406 | static int omfs_readdir(struct file *filp, void *dirent, filldir_t filldir) | 404 | static int omfs_readdir(struct file *file, struct dir_context *ctx) |
407 | { | 405 | { |
408 | struct inode *dir = file_inode(filp); | 406 | struct inode *dir = file_inode(file); |
409 | struct buffer_head *bh; | 407 | struct buffer_head *bh; |
410 | loff_t offset, res; | 408 | __be64 *p; |
411 | unsigned int hchain, hindex; | 409 | unsigned int hchain, hindex; |
412 | int nbuckets; | 410 | int nbuckets; |
413 | u64 fsblock; | 411 | |
414 | int ret = -EINVAL; | 412 | if (ctx->pos >> 32) |
415 | 413 | return -EINVAL; | |
416 | if (filp->f_pos >> 32) | 414 | |
417 | goto success; | 415 | if (ctx->pos < 1 << 20) { |
418 | 416 | if (!dir_emit_dots(file, ctx)) | |
419 | switch ((unsigned long) filp->f_pos) { | 417 | return 0; |
420 | case 0: | 418 | ctx->pos = 1 << 20; |
421 | if (filldir(dirent, ".", 1, 0, dir->i_ino, DT_DIR) < 0) | ||
422 | goto success; | ||
423 | filp->f_pos++; | ||
424 | /* fall through */ | ||
425 | case 1: | ||
426 | if (filldir(dirent, "..", 2, 1, | ||
427 | parent_ino(filp->f_dentry), DT_DIR) < 0) | ||
428 | goto success; | ||
429 | filp->f_pos = 1 << 20; | ||
430 | /* fall through */ | ||
431 | } | 419 | } |
432 | 420 | ||
433 | nbuckets = (dir->i_size - OMFS_DIR_START) / 8; | 421 | nbuckets = (dir->i_size - OMFS_DIR_START) / 8; |
434 | 422 | ||
435 | /* high 12 bits store bucket + 1 and low 20 bits store hash index */ | 423 | /* high 12 bits store bucket + 1 and low 20 bits store hash index */ |
436 | hchain = (filp->f_pos >> 20) - 1; | 424 | hchain = (ctx->pos >> 20) - 1; |
437 | hindex = filp->f_pos & 0xfffff; | 425 | hindex = ctx->pos & 0xfffff; |
438 | 426 | ||
439 | bh = omfs_bread(dir->i_sb, dir->i_ino); | 427 | bh = omfs_bread(dir->i_sb, dir->i_ino); |
440 | if (!bh) | 428 | if (!bh) |
441 | goto out; | 429 | return -EINVAL; |
442 | 430 | ||
443 | offset = OMFS_DIR_START + hchain * 8; | 431 | p = (__be64 *)(bh->b_data + OMFS_DIR_START) + hchain; |
444 | 432 | ||
445 | for (; hchain < nbuckets; hchain++, offset += 8) { | 433 | for (; hchain < nbuckets; hchain++) { |
446 | fsblock = be64_to_cpu(*((__be64 *) &bh->b_data[offset])); | 434 | __u64 fsblock = be64_to_cpu(*p++); |
447 | 435 | if (!omfs_fill_chain(dir, ctx, fsblock, hindex)) | |
448 | res = omfs_fill_chain(filp, dirent, filldir, fsblock, hindex); | ||
449 | hindex = 0; | ||
450 | if (res < 0) | ||
451 | break; | 436 | break; |
452 | 437 | hindex = 0; | |
453 | filp->f_pos = (hchain+2) << 20; | 438 | ctx->pos = (hchain+2) << 20; |
454 | } | 439 | } |
455 | brelse(bh); | 440 | brelse(bh); |
456 | success: | 441 | return 0; |
457 | ret = 0; | ||
458 | out: | ||
459 | return ret; | ||
460 | } | 442 | } |
461 | 443 | ||
462 | const struct inode_operations omfs_dir_inops = { | 444 | const struct inode_operations omfs_dir_inops = { |
@@ -470,6 +452,6 @@ const struct inode_operations omfs_dir_inops = { | |||
470 | 452 | ||
471 | const struct file_operations omfs_dir_operations = { | 453 | const struct file_operations omfs_dir_operations = { |
472 | .read = generic_read_dir, | 454 | .read = generic_read_dir, |
473 | .readdir = omfs_readdir, | 455 | .iterate = omfs_readdir, |
474 | .llseek = generic_file_llseek, | 456 | .llseek = generic_file_llseek, |
475 | }; | 457 | }; |
diff --git a/fs/openpromfs/inode.c b/fs/openpromfs/inode.c index 75885ffde44e..8c0ceb8dd1f7 100644 --- a/fs/openpromfs/inode.c +++ b/fs/openpromfs/inode.c | |||
@@ -162,11 +162,11 @@ static const struct file_operations openpromfs_prop_ops = { | |||
162 | .release = seq_release, | 162 | .release = seq_release, |
163 | }; | 163 | }; |
164 | 164 | ||
165 | static int openpromfs_readdir(struct file *, void *, filldir_t); | 165 | static int openpromfs_readdir(struct file *, struct dir_context *); |
166 | 166 | ||
167 | static const struct file_operations openprom_operations = { | 167 | static const struct file_operations openprom_operations = { |
168 | .read = generic_read_dir, | 168 | .read = generic_read_dir, |
169 | .readdir = openpromfs_readdir, | 169 | .iterate = openpromfs_readdir, |
170 | .llseek = generic_file_llseek, | 170 | .llseek = generic_file_llseek, |
171 | }; | 171 | }; |
172 | 172 | ||
@@ -260,71 +260,64 @@ found: | |||
260 | return NULL; | 260 | return NULL; |
261 | } | 261 | } |
262 | 262 | ||
263 | static int openpromfs_readdir(struct file * filp, void * dirent, filldir_t filldir) | 263 | static int openpromfs_readdir(struct file *file, struct dir_context *ctx) |
264 | { | 264 | { |
265 | struct inode *inode = file_inode(filp); | 265 | struct inode *inode = file_inode(file); |
266 | struct op_inode_info *oi = OP_I(inode); | 266 | struct op_inode_info *oi = OP_I(inode); |
267 | struct device_node *dp = oi->u.node; | 267 | struct device_node *dp = oi->u.node; |
268 | struct device_node *child; | 268 | struct device_node *child; |
269 | struct property *prop; | 269 | struct property *prop; |
270 | unsigned int ino; | ||
271 | int i; | 270 | int i; |
272 | 271 | ||
273 | mutex_lock(&op_mutex); | 272 | mutex_lock(&op_mutex); |
274 | 273 | ||
275 | ino = inode->i_ino; | 274 | if (ctx->pos == 0) { |
276 | i = filp->f_pos; | 275 | if (!dir_emit(ctx, ".", 1, inode->i_ino, DT_DIR)) |
277 | switch (i) { | ||
278 | case 0: | ||
279 | if (filldir(dirent, ".", 1, i, ino, DT_DIR) < 0) | ||
280 | goto out; | 276 | goto out; |
281 | i++; | 277 | ctx->pos = 1; |
282 | filp->f_pos++; | 278 | } |
283 | /* fall thru */ | 279 | if (ctx->pos == 1) { |
284 | case 1: | 280 | if (!dir_emit(ctx, "..", 2, |
285 | if (filldir(dirent, "..", 2, i, | ||
286 | (dp->parent == NULL ? | 281 | (dp->parent == NULL ? |
287 | OPENPROM_ROOT_INO : | 282 | OPENPROM_ROOT_INO : |
288 | dp->parent->unique_id), DT_DIR) < 0) | 283 | dp->parent->unique_id), DT_DIR)) |
289 | goto out; | 284 | goto out; |
290 | i++; | 285 | ctx->pos = 2; |
291 | filp->f_pos++; | 286 | } |
292 | /* fall thru */ | 287 | i = ctx->pos - 2; |
293 | default: | ||
294 | i -= 2; | ||
295 | |||
296 | /* First, the children nodes as directories. */ | ||
297 | child = dp->child; | ||
298 | while (i && child) { | ||
299 | child = child->sibling; | ||
300 | i--; | ||
301 | } | ||
302 | while (child) { | ||
303 | if (filldir(dirent, | ||
304 | child->path_component_name, | ||
305 | strlen(child->path_component_name), | ||
306 | filp->f_pos, child->unique_id, DT_DIR) < 0) | ||
307 | goto out; | ||
308 | |||
309 | filp->f_pos++; | ||
310 | child = child->sibling; | ||
311 | } | ||
312 | 288 | ||
313 | /* Next, the properties as files. */ | 289 | /* First, the children nodes as directories. */ |
314 | prop = dp->properties; | 290 | child = dp->child; |
315 | while (i && prop) { | 291 | while (i && child) { |
316 | prop = prop->next; | 292 | child = child->sibling; |
317 | i--; | 293 | i--; |
318 | } | 294 | } |
319 | while (prop) { | 295 | while (child) { |
320 | if (filldir(dirent, prop->name, strlen(prop->name), | 296 | if (!dir_emit(ctx, |
321 | filp->f_pos, prop->unique_id, DT_REG) < 0) | 297 | child->path_component_name, |
322 | goto out; | 298 | strlen(child->path_component_name), |
299 | child->unique_id, DT_DIR)) | ||
300 | goto out; | ||
323 | 301 | ||
324 | filp->f_pos++; | 302 | ctx->pos++; |
325 | prop = prop->next; | 303 | child = child->sibling; |
326 | } | 304 | } |
305 | |||
306 | /* Next, the properties as files. */ | ||
307 | prop = dp->properties; | ||
308 | while (i && prop) { | ||
309 | prop = prop->next; | ||
310 | i--; | ||
327 | } | 311 | } |
312 | while (prop) { | ||
313 | if (!dir_emit(ctx, prop->name, strlen(prop->name), | ||
314 | prop->unique_id, DT_REG)) | ||
315 | goto out; | ||
316 | |||
317 | ctx->pos++; | ||
318 | prop = prop->next; | ||
319 | } | ||
320 | |||
328 | out: | 321 | out: |
329 | mutex_unlock(&op_mutex); | 322 | mutex_unlock(&op_mutex); |
330 | return 0; | 323 | return 0; |
diff --git a/fs/proc/base.c b/fs/proc/base.c index c3834dad09b3..0016350ad95e 100644 --- a/fs/proc/base.c +++ b/fs/proc/base.c | |||
@@ -1681,11 +1681,11 @@ const struct dentry_operations pid_dentry_operations = | |||
1681 | * reported by readdir in sync with the inode numbers reported | 1681 | * reported by readdir in sync with the inode numbers reported |
1682 | * by stat. | 1682 | * by stat. |
1683 | */ | 1683 | */ |
1684 | int proc_fill_cache(struct file *filp, void *dirent, filldir_t filldir, | 1684 | bool proc_fill_cache(struct file *file, struct dir_context *ctx, |
1685 | const char *name, int len, | 1685 | const char *name, int len, |
1686 | instantiate_t instantiate, struct task_struct *task, const void *ptr) | 1686 | instantiate_t instantiate, struct task_struct *task, const void *ptr) |
1687 | { | 1687 | { |
1688 | struct dentry *child, *dir = filp->f_path.dentry; | 1688 | struct dentry *child, *dir = file->f_path.dentry; |
1689 | struct inode *inode; | 1689 | struct inode *inode; |
1690 | struct qstr qname; | 1690 | struct qstr qname; |
1691 | ino_t ino = 0; | 1691 | ino_t ino = 0; |
@@ -1720,7 +1720,7 @@ end_instantiate: | |||
1720 | ino = find_inode_number(dir, &qname); | 1720 | ino = find_inode_number(dir, &qname); |
1721 | if (!ino) | 1721 | if (!ino) |
1722 | ino = 1; | 1722 | ino = 1; |
1723 | return filldir(dirent, name, len, filp->f_pos, ino, type); | 1723 | return dir_emit(ctx, name, len, ino, type); |
1724 | } | 1724 | } |
1725 | 1725 | ||
1726 | #ifdef CONFIG_CHECKPOINT_RESTORE | 1726 | #ifdef CONFIG_CHECKPOINT_RESTORE |
@@ -1931,14 +1931,15 @@ static const struct inode_operations proc_map_files_inode_operations = { | |||
1931 | }; | 1931 | }; |
1932 | 1932 | ||
1933 | static int | 1933 | static int |
1934 | proc_map_files_readdir(struct file *filp, void *dirent, filldir_t filldir) | 1934 | proc_map_files_readdir(struct file *file, struct dir_context *ctx) |
1935 | { | 1935 | { |
1936 | struct dentry *dentry = filp->f_path.dentry; | ||
1937 | struct inode *inode = dentry->d_inode; | ||
1938 | struct vm_area_struct *vma; | 1936 | struct vm_area_struct *vma; |
1939 | struct task_struct *task; | 1937 | struct task_struct *task; |
1940 | struct mm_struct *mm; | 1938 | struct mm_struct *mm; |
1941 | ino_t ino; | 1939 | unsigned long nr_files, pos, i; |
1940 | struct flex_array *fa = NULL; | ||
1941 | struct map_files_info info; | ||
1942 | struct map_files_info *p; | ||
1942 | int ret; | 1943 | int ret; |
1943 | 1944 | ||
1944 | ret = -EPERM; | 1945 | ret = -EPERM; |
@@ -1946,7 +1947,7 @@ proc_map_files_readdir(struct file *filp, void *dirent, filldir_t filldir) | |||
1946 | goto out; | 1947 | goto out; |
1947 | 1948 | ||
1948 | ret = -ENOENT; | 1949 | ret = -ENOENT; |
1949 | task = get_proc_task(inode); | 1950 | task = get_proc_task(file_inode(file)); |
1950 | if (!task) | 1951 | if (!task) |
1951 | goto out; | 1952 | goto out; |
1952 | 1953 | ||
@@ -1955,91 +1956,73 @@ proc_map_files_readdir(struct file *filp, void *dirent, filldir_t filldir) | |||
1955 | goto out_put_task; | 1956 | goto out_put_task; |
1956 | 1957 | ||
1957 | ret = 0; | 1958 | ret = 0; |
1958 | switch (filp->f_pos) { | 1959 | if (!dir_emit_dots(file, ctx)) |
1959 | case 0: | 1960 | goto out_put_task; |
1960 | ino = inode->i_ino; | ||
1961 | if (filldir(dirent, ".", 1, 0, ino, DT_DIR) < 0) | ||
1962 | goto out_put_task; | ||
1963 | filp->f_pos++; | ||
1964 | case 1: | ||
1965 | ino = parent_ino(dentry); | ||
1966 | if (filldir(dirent, "..", 2, 1, ino, DT_DIR) < 0) | ||
1967 | goto out_put_task; | ||
1968 | filp->f_pos++; | ||
1969 | default: | ||
1970 | { | ||
1971 | unsigned long nr_files, pos, i; | ||
1972 | struct flex_array *fa = NULL; | ||
1973 | struct map_files_info info; | ||
1974 | struct map_files_info *p; | ||
1975 | |||
1976 | mm = get_task_mm(task); | ||
1977 | if (!mm) | ||
1978 | goto out_put_task; | ||
1979 | down_read(&mm->mmap_sem); | ||
1980 | 1961 | ||
1981 | nr_files = 0; | 1962 | mm = get_task_mm(task); |
1963 | if (!mm) | ||
1964 | goto out_put_task; | ||
1965 | down_read(&mm->mmap_sem); | ||
1982 | 1966 | ||
1983 | /* | 1967 | nr_files = 0; |
1984 | * We need two passes here: | ||
1985 | * | ||
1986 | * 1) Collect vmas of mapped files with mmap_sem taken | ||
1987 | * 2) Release mmap_sem and instantiate entries | ||
1988 | * | ||
1989 | * otherwise we get lockdep complained, since filldir() | ||
1990 | * routine might require mmap_sem taken in might_fault(). | ||
1991 | */ | ||
1992 | 1968 | ||
1993 | for (vma = mm->mmap, pos = 2; vma; vma = vma->vm_next) { | 1969 | /* |
1994 | if (vma->vm_file && ++pos > filp->f_pos) | 1970 | * We need two passes here: |
1995 | nr_files++; | 1971 | * |
1996 | } | 1972 | * 1) Collect vmas of mapped files with mmap_sem taken |
1973 | * 2) Release mmap_sem and instantiate entries | ||
1974 | * | ||
1975 | * otherwise we get lockdep complained, since filldir() | ||
1976 | * routine might require mmap_sem taken in might_fault(). | ||
1977 | */ | ||
1997 | 1978 | ||
1998 | if (nr_files) { | 1979 | for (vma = mm->mmap, pos = 2; vma; vma = vma->vm_next) { |
1999 | fa = flex_array_alloc(sizeof(info), nr_files, | 1980 | if (vma->vm_file && ++pos > ctx->pos) |
2000 | GFP_KERNEL); | 1981 | nr_files++; |
2001 | if (!fa || flex_array_prealloc(fa, 0, nr_files, | 1982 | } |
2002 | GFP_KERNEL)) { | 1983 | |
2003 | ret = -ENOMEM; | 1984 | if (nr_files) { |
2004 | if (fa) | 1985 | fa = flex_array_alloc(sizeof(info), nr_files, |
2005 | flex_array_free(fa); | 1986 | GFP_KERNEL); |
2006 | up_read(&mm->mmap_sem); | 1987 | if (!fa || flex_array_prealloc(fa, 0, nr_files, |
2007 | mmput(mm); | 1988 | GFP_KERNEL)) { |
2008 | goto out_put_task; | 1989 | ret = -ENOMEM; |
2009 | } | 1990 | if (fa) |
2010 | for (i = 0, vma = mm->mmap, pos = 2; vma; | 1991 | flex_array_free(fa); |
2011 | vma = vma->vm_next) { | 1992 | up_read(&mm->mmap_sem); |
2012 | if (!vma->vm_file) | 1993 | mmput(mm); |
2013 | continue; | 1994 | goto out_put_task; |
2014 | if (++pos <= filp->f_pos) | ||
2015 | continue; | ||
2016 | |||
2017 | info.mode = vma->vm_file->f_mode; | ||
2018 | info.len = snprintf(info.name, | ||
2019 | sizeof(info.name), "%lx-%lx", | ||
2020 | vma->vm_start, vma->vm_end); | ||
2021 | if (flex_array_put(fa, i++, &info, GFP_KERNEL)) | ||
2022 | BUG(); | ||
2023 | } | ||
2024 | } | 1995 | } |
2025 | up_read(&mm->mmap_sem); | 1996 | for (i = 0, vma = mm->mmap, pos = 2; vma; |
2026 | 1997 | vma = vma->vm_next) { | |
2027 | for (i = 0; i < nr_files; i++) { | 1998 | if (!vma->vm_file) |
2028 | p = flex_array_get(fa, i); | 1999 | continue; |
2029 | ret = proc_fill_cache(filp, dirent, filldir, | 2000 | if (++pos <= ctx->pos) |
2030 | p->name, p->len, | 2001 | continue; |
2031 | proc_map_files_instantiate, | 2002 | |
2032 | task, | 2003 | info.mode = vma->vm_file->f_mode; |
2033 | (void *)(unsigned long)p->mode); | 2004 | info.len = snprintf(info.name, |
2034 | if (ret) | 2005 | sizeof(info.name), "%lx-%lx", |
2035 | break; | 2006 | vma->vm_start, vma->vm_end); |
2036 | filp->f_pos++; | 2007 | if (flex_array_put(fa, i++, &info, GFP_KERNEL)) |
2008 | BUG(); | ||
2037 | } | 2009 | } |
2038 | if (fa) | ||
2039 | flex_array_free(fa); | ||
2040 | mmput(mm); | ||
2041 | } | 2010 | } |
2011 | up_read(&mm->mmap_sem); | ||
2012 | |||
2013 | for (i = 0; i < nr_files; i++) { | ||
2014 | p = flex_array_get(fa, i); | ||
2015 | if (!proc_fill_cache(file, ctx, | ||
2016 | p->name, p->len, | ||
2017 | proc_map_files_instantiate, | ||
2018 | task, | ||
2019 | (void *)(unsigned long)p->mode)) | ||
2020 | break; | ||
2021 | ctx->pos++; | ||
2042 | } | 2022 | } |
2023 | if (fa) | ||
2024 | flex_array_free(fa); | ||
2025 | mmput(mm); | ||
2043 | 2026 | ||
2044 | out_put_task: | 2027 | out_put_task: |
2045 | put_task_struct(task); | 2028 | put_task_struct(task); |
@@ -2049,7 +2032,7 @@ out: | |||
2049 | 2032 | ||
2050 | static const struct file_operations proc_map_files_operations = { | 2033 | static const struct file_operations proc_map_files_operations = { |
2051 | .read = generic_read_dir, | 2034 | .read = generic_read_dir, |
2052 | .readdir = proc_map_files_readdir, | 2035 | .iterate = proc_map_files_readdir, |
2053 | .llseek = default_llseek, | 2036 | .llseek = default_llseek, |
2054 | }; | 2037 | }; |
2055 | 2038 | ||
@@ -2217,67 +2200,30 @@ out_no_task: | |||
2217 | return error; | 2200 | return error; |
2218 | } | 2201 | } |
2219 | 2202 | ||
2220 | static int proc_pident_fill_cache(struct file *filp, void *dirent, | 2203 | static int proc_pident_readdir(struct file *file, struct dir_context *ctx, |
2221 | filldir_t filldir, struct task_struct *task, const struct pid_entry *p) | ||
2222 | { | ||
2223 | return proc_fill_cache(filp, dirent, filldir, p->name, p->len, | ||
2224 | proc_pident_instantiate, task, p); | ||
2225 | } | ||
2226 | |||
2227 | static int proc_pident_readdir(struct file *filp, | ||
2228 | void *dirent, filldir_t filldir, | ||
2229 | const struct pid_entry *ents, unsigned int nents) | 2204 | const struct pid_entry *ents, unsigned int nents) |
2230 | { | 2205 | { |
2231 | int i; | 2206 | struct task_struct *task = get_proc_task(file_inode(file)); |
2232 | struct dentry *dentry = filp->f_path.dentry; | 2207 | const struct pid_entry *p; |
2233 | struct inode *inode = dentry->d_inode; | ||
2234 | struct task_struct *task = get_proc_task(inode); | ||
2235 | const struct pid_entry *p, *last; | ||
2236 | ino_t ino; | ||
2237 | int ret; | ||
2238 | 2208 | ||
2239 | ret = -ENOENT; | ||
2240 | if (!task) | 2209 | if (!task) |
2241 | goto out_no_task; | 2210 | return -ENOENT; |
2242 | 2211 | ||
2243 | ret = 0; | 2212 | if (!dir_emit_dots(file, ctx)) |
2244 | i = filp->f_pos; | 2213 | goto out; |
2245 | switch (i) { | 2214 | |
2246 | case 0: | 2215 | if (ctx->pos >= nents + 2) |
2247 | ino = inode->i_ino; | 2216 | goto out; |
2248 | if (filldir(dirent, ".", 1, i, ino, DT_DIR) < 0) | ||
2249 | goto out; | ||
2250 | i++; | ||
2251 | filp->f_pos++; | ||
2252 | /* fall through */ | ||
2253 | case 1: | ||
2254 | ino = parent_ino(dentry); | ||
2255 | if (filldir(dirent, "..", 2, i, ino, DT_DIR) < 0) | ||
2256 | goto out; | ||
2257 | i++; | ||
2258 | filp->f_pos++; | ||
2259 | /* fall through */ | ||
2260 | default: | ||
2261 | i -= 2; | ||
2262 | if (i >= nents) { | ||
2263 | ret = 1; | ||
2264 | goto out; | ||
2265 | } | ||
2266 | p = ents + i; | ||
2267 | last = &ents[nents - 1]; | ||
2268 | while (p <= last) { | ||
2269 | if (proc_pident_fill_cache(filp, dirent, filldir, task, p) < 0) | ||
2270 | goto out; | ||
2271 | filp->f_pos++; | ||
2272 | p++; | ||
2273 | } | ||
2274 | } | ||
2275 | 2217 | ||
2276 | ret = 1; | 2218 | for (p = ents + (ctx->pos - 2); p <= ents + nents - 1; p++) { |
2219 | if (!proc_fill_cache(file, ctx, p->name, p->len, | ||
2220 | proc_pident_instantiate, task, p)) | ||
2221 | break; | ||
2222 | ctx->pos++; | ||
2223 | } | ||
2277 | out: | 2224 | out: |
2278 | put_task_struct(task); | 2225 | put_task_struct(task); |
2279 | out_no_task: | 2226 | return 0; |
2280 | return ret; | ||
2281 | } | 2227 | } |
2282 | 2228 | ||
2283 | #ifdef CONFIG_SECURITY | 2229 | #ifdef CONFIG_SECURITY |
@@ -2362,16 +2308,15 @@ static const struct pid_entry attr_dir_stuff[] = { | |||
2362 | REG("sockcreate", S_IRUGO|S_IWUGO, proc_pid_attr_operations), | 2308 | REG("sockcreate", S_IRUGO|S_IWUGO, proc_pid_attr_operations), |
2363 | }; | 2309 | }; |
2364 | 2310 | ||
2365 | static int proc_attr_dir_readdir(struct file * filp, | 2311 | static int proc_attr_dir_readdir(struct file *file, struct dir_context *ctx) |
2366 | void * dirent, filldir_t filldir) | ||
2367 | { | 2312 | { |
2368 | return proc_pident_readdir(filp,dirent,filldir, | 2313 | return proc_pident_readdir(file, ctx, |
2369 | attr_dir_stuff,ARRAY_SIZE(attr_dir_stuff)); | 2314 | attr_dir_stuff, ARRAY_SIZE(attr_dir_stuff)); |
2370 | } | 2315 | } |
2371 | 2316 | ||
2372 | static const struct file_operations proc_attr_dir_operations = { | 2317 | static const struct file_operations proc_attr_dir_operations = { |
2373 | .read = generic_read_dir, | 2318 | .read = generic_read_dir, |
2374 | .readdir = proc_attr_dir_readdir, | 2319 | .iterate = proc_attr_dir_readdir, |
2375 | .llseek = default_llseek, | 2320 | .llseek = default_llseek, |
2376 | }; | 2321 | }; |
2377 | 2322 | ||
@@ -2725,16 +2670,15 @@ static const struct pid_entry tgid_base_stuff[] = { | |||
2725 | #endif | 2670 | #endif |
2726 | }; | 2671 | }; |
2727 | 2672 | ||
2728 | static int proc_tgid_base_readdir(struct file * filp, | 2673 | static int proc_tgid_base_readdir(struct file *file, struct dir_context *ctx) |
2729 | void * dirent, filldir_t filldir) | ||
2730 | { | 2674 | { |
2731 | return proc_pident_readdir(filp,dirent,filldir, | 2675 | return proc_pident_readdir(file, ctx, |
2732 | tgid_base_stuff,ARRAY_SIZE(tgid_base_stuff)); | 2676 | tgid_base_stuff, ARRAY_SIZE(tgid_base_stuff)); |
2733 | } | 2677 | } |
2734 | 2678 | ||
2735 | static const struct file_operations proc_tgid_base_operations = { | 2679 | static const struct file_operations proc_tgid_base_operations = { |
2736 | .read = generic_read_dir, | 2680 | .read = generic_read_dir, |
2737 | .readdir = proc_tgid_base_readdir, | 2681 | .iterate = proc_tgid_base_readdir, |
2738 | .llseek = default_llseek, | 2682 | .llseek = default_llseek, |
2739 | }; | 2683 | }; |
2740 | 2684 | ||
@@ -2936,58 +2880,42 @@ retry: | |||
2936 | 2880 | ||
2937 | #define TGID_OFFSET (FIRST_PROCESS_ENTRY + 1) | 2881 | #define TGID_OFFSET (FIRST_PROCESS_ENTRY + 1) |
2938 | 2882 | ||
2939 | static int proc_pid_fill_cache(struct file *filp, void *dirent, filldir_t filldir, | ||
2940 | struct tgid_iter iter) | ||
2941 | { | ||
2942 | char name[PROC_NUMBUF]; | ||
2943 | int len = snprintf(name, sizeof(name), "%d", iter.tgid); | ||
2944 | return proc_fill_cache(filp, dirent, filldir, name, len, | ||
2945 | proc_pid_instantiate, iter.task, NULL); | ||
2946 | } | ||
2947 | |||
2948 | static int fake_filldir(void *buf, const char *name, int namelen, | ||
2949 | loff_t offset, u64 ino, unsigned d_type) | ||
2950 | { | ||
2951 | return 0; | ||
2952 | } | ||
2953 | |||
2954 | /* for the /proc/ directory itself, after non-process stuff has been done */ | 2883 | /* for the /proc/ directory itself, after non-process stuff has been done */ |
2955 | int proc_pid_readdir(struct file * filp, void * dirent, filldir_t filldir) | 2884 | int proc_pid_readdir(struct file *file, struct dir_context *ctx) |
2956 | { | 2885 | { |
2957 | struct tgid_iter iter; | 2886 | struct tgid_iter iter; |
2958 | struct pid_namespace *ns; | 2887 | struct pid_namespace *ns; |
2959 | filldir_t __filldir; | 2888 | loff_t pos = ctx->pos; |
2960 | loff_t pos = filp->f_pos; | ||
2961 | 2889 | ||
2962 | if (pos >= PID_MAX_LIMIT + TGID_OFFSET) | 2890 | if (pos >= PID_MAX_LIMIT + TGID_OFFSET) |
2963 | goto out; | 2891 | return 0; |
2964 | 2892 | ||
2965 | if (pos == TGID_OFFSET - 1) { | 2893 | if (pos == TGID_OFFSET - 1) { |
2966 | if (proc_fill_cache(filp, dirent, filldir, "self", 4, | 2894 | if (!proc_fill_cache(file, ctx, "self", 4, NULL, NULL, NULL)) |
2967 | NULL, NULL, NULL) < 0) | 2895 | return 0; |
2968 | goto out; | ||
2969 | iter.tgid = 0; | 2896 | iter.tgid = 0; |
2970 | } else { | 2897 | } else { |
2971 | iter.tgid = pos - TGID_OFFSET; | 2898 | iter.tgid = pos - TGID_OFFSET; |
2972 | } | 2899 | } |
2973 | iter.task = NULL; | 2900 | iter.task = NULL; |
2974 | ns = filp->f_dentry->d_sb->s_fs_info; | 2901 | ns = file->f_dentry->d_sb->s_fs_info; |
2975 | for (iter = next_tgid(ns, iter); | 2902 | for (iter = next_tgid(ns, iter); |
2976 | iter.task; | 2903 | iter.task; |
2977 | iter.tgid += 1, iter = next_tgid(ns, iter)) { | 2904 | iter.tgid += 1, iter = next_tgid(ns, iter)) { |
2978 | if (has_pid_permissions(ns, iter.task, 2)) | 2905 | char name[PROC_NUMBUF]; |
2979 | __filldir = filldir; | 2906 | int len; |
2980 | else | 2907 | if (!has_pid_permissions(ns, iter.task, 2)) |
2981 | __filldir = fake_filldir; | 2908 | continue; |
2982 | 2909 | ||
2983 | filp->f_pos = iter.tgid + TGID_OFFSET; | 2910 | len = snprintf(name, sizeof(name), "%d", iter.tgid); |
2984 | if (proc_pid_fill_cache(filp, dirent, __filldir, iter) < 0) { | 2911 | ctx->pos = iter.tgid + TGID_OFFSET; |
2912 | if (!proc_fill_cache(file, ctx, name, len, | ||
2913 | proc_pid_instantiate, iter.task, NULL)) { | ||
2985 | put_task_struct(iter.task); | 2914 | put_task_struct(iter.task); |
2986 | goto out; | 2915 | return 0; |
2987 | } | 2916 | } |
2988 | } | 2917 | } |
2989 | filp->f_pos = PID_MAX_LIMIT + TGID_OFFSET; | 2918 | ctx->pos = PID_MAX_LIMIT + TGID_OFFSET; |
2990 | out: | ||
2991 | return 0; | 2919 | return 0; |
2992 | } | 2920 | } |
2993 | 2921 | ||
@@ -3075,11 +3003,10 @@ static const struct pid_entry tid_base_stuff[] = { | |||
3075 | #endif | 3003 | #endif |
3076 | }; | 3004 | }; |
3077 | 3005 | ||
3078 | static int proc_tid_base_readdir(struct file * filp, | 3006 | static int proc_tid_base_readdir(struct file *file, struct dir_context *ctx) |
3079 | void * dirent, filldir_t filldir) | ||
3080 | { | 3007 | { |
3081 | return proc_pident_readdir(filp,dirent,filldir, | 3008 | return proc_pident_readdir(file, ctx, |
3082 | tid_base_stuff,ARRAY_SIZE(tid_base_stuff)); | 3009 | tid_base_stuff, ARRAY_SIZE(tid_base_stuff)); |
3083 | } | 3010 | } |
3084 | 3011 | ||
3085 | static struct dentry *proc_tid_base_lookup(struct inode *dir, struct dentry *dentry, unsigned int flags) | 3012 | static struct dentry *proc_tid_base_lookup(struct inode *dir, struct dentry *dentry, unsigned int flags) |
@@ -3090,7 +3017,7 @@ static struct dentry *proc_tid_base_lookup(struct inode *dir, struct dentry *den | |||
3090 | 3017 | ||
3091 | static const struct file_operations proc_tid_base_operations = { | 3018 | static const struct file_operations proc_tid_base_operations = { |
3092 | .read = generic_read_dir, | 3019 | .read = generic_read_dir, |
3093 | .readdir = proc_tid_base_readdir, | 3020 | .iterate = proc_tid_base_readdir, |
3094 | .llseek = default_llseek, | 3021 | .llseek = default_llseek, |
3095 | }; | 3022 | }; |
3096 | 3023 | ||
@@ -3231,30 +3158,16 @@ static struct task_struct *next_tid(struct task_struct *start) | |||
3231 | return pos; | 3158 | return pos; |
3232 | } | 3159 | } |
3233 | 3160 | ||
3234 | static int proc_task_fill_cache(struct file *filp, void *dirent, filldir_t filldir, | ||
3235 | struct task_struct *task, int tid) | ||
3236 | { | ||
3237 | char name[PROC_NUMBUF]; | ||
3238 | int len = snprintf(name, sizeof(name), "%d", tid); | ||
3239 | return proc_fill_cache(filp, dirent, filldir, name, len, | ||
3240 | proc_task_instantiate, task, NULL); | ||
3241 | } | ||
3242 | |||
3243 | /* for the /proc/TGID/task/ directories */ | 3161 | /* for the /proc/TGID/task/ directories */ |
3244 | static int proc_task_readdir(struct file * filp, void * dirent, filldir_t filldir) | 3162 | static int proc_task_readdir(struct file *file, struct dir_context *ctx) |
3245 | { | 3163 | { |
3246 | struct dentry *dentry = filp->f_path.dentry; | ||
3247 | struct inode *inode = dentry->d_inode; | ||
3248 | struct task_struct *leader = NULL; | 3164 | struct task_struct *leader = NULL; |
3249 | struct task_struct *task; | 3165 | struct task_struct *task = get_proc_task(file_inode(file)); |
3250 | int retval = -ENOENT; | ||
3251 | ino_t ino; | ||
3252 | int tid; | ||
3253 | struct pid_namespace *ns; | 3166 | struct pid_namespace *ns; |
3167 | int tid; | ||
3254 | 3168 | ||
3255 | task = get_proc_task(inode); | ||
3256 | if (!task) | 3169 | if (!task) |
3257 | goto out_no_task; | 3170 | return -ENOENT; |
3258 | rcu_read_lock(); | 3171 | rcu_read_lock(); |
3259 | if (pid_alive(task)) { | 3172 | if (pid_alive(task)) { |
3260 | leader = task->group_leader; | 3173 | leader = task->group_leader; |
@@ -3263,46 +3176,36 @@ static int proc_task_readdir(struct file * filp, void * dirent, filldir_t filldi | |||
3263 | rcu_read_unlock(); | 3176 | rcu_read_unlock(); |
3264 | put_task_struct(task); | 3177 | put_task_struct(task); |
3265 | if (!leader) | 3178 | if (!leader) |
3266 | goto out_no_task; | 3179 | return -ENOENT; |
3267 | retval = 0; | ||
3268 | 3180 | ||
3269 | switch ((unsigned long)filp->f_pos) { | 3181 | if (!dir_emit_dots(file, ctx)) |
3270 | case 0: | 3182 | goto out; |
3271 | ino = inode->i_ino; | ||
3272 | if (filldir(dirent, ".", 1, filp->f_pos, ino, DT_DIR) < 0) | ||
3273 | goto out; | ||
3274 | filp->f_pos++; | ||
3275 | /* fall through */ | ||
3276 | case 1: | ||
3277 | ino = parent_ino(dentry); | ||
3278 | if (filldir(dirent, "..", 2, filp->f_pos, ino, DT_DIR) < 0) | ||
3279 | goto out; | ||
3280 | filp->f_pos++; | ||
3281 | /* fall through */ | ||
3282 | } | ||
3283 | 3183 | ||
3284 | /* f_version caches the tgid value that the last readdir call couldn't | 3184 | /* f_version caches the tgid value that the last readdir call couldn't |
3285 | * return. lseek aka telldir automagically resets f_version to 0. | 3185 | * return. lseek aka telldir automagically resets f_version to 0. |
3286 | */ | 3186 | */ |
3287 | ns = filp->f_dentry->d_sb->s_fs_info; | 3187 | ns = file->f_dentry->d_sb->s_fs_info; |
3288 | tid = (int)filp->f_version; | 3188 | tid = (int)file->f_version; |
3289 | filp->f_version = 0; | 3189 | file->f_version = 0; |
3290 | for (task = first_tid(leader, tid, filp->f_pos - 2, ns); | 3190 | for (task = first_tid(leader, tid, ctx->pos - 2, ns); |
3291 | task; | 3191 | task; |
3292 | task = next_tid(task), filp->f_pos++) { | 3192 | task = next_tid(task), ctx->pos++) { |
3193 | char name[PROC_NUMBUF]; | ||
3194 | int len; | ||
3293 | tid = task_pid_nr_ns(task, ns); | 3195 | tid = task_pid_nr_ns(task, ns); |
3294 | if (proc_task_fill_cache(filp, dirent, filldir, task, tid) < 0) { | 3196 | len = snprintf(name, sizeof(name), "%d", tid); |
3197 | if (!proc_fill_cache(file, ctx, name, len, | ||
3198 | proc_task_instantiate, task, NULL)) { | ||
3295 | /* returning this tgid failed, save it as the first | 3199 | /* returning this tgid failed, save it as the first |
3296 | * pid for the next readir call */ | 3200 | * pid for the next readir call */ |
3297 | filp->f_version = (u64)tid; | 3201 | file->f_version = (u64)tid; |
3298 | put_task_struct(task); | 3202 | put_task_struct(task); |
3299 | break; | 3203 | break; |
3300 | } | 3204 | } |
3301 | } | 3205 | } |
3302 | out: | 3206 | out: |
3303 | put_task_struct(leader); | 3207 | put_task_struct(leader); |
3304 | out_no_task: | 3208 | return 0; |
3305 | return retval; | ||
3306 | } | 3209 | } |
3307 | 3210 | ||
3308 | static int proc_task_getattr(struct vfsmount *mnt, struct dentry *dentry, struct kstat *stat) | 3211 | static int proc_task_getattr(struct vfsmount *mnt, struct dentry *dentry, struct kstat *stat) |
@@ -3328,6 +3231,6 @@ static const struct inode_operations proc_task_inode_operations = { | |||
3328 | 3231 | ||
3329 | static const struct file_operations proc_task_operations = { | 3232 | static const struct file_operations proc_task_operations = { |
3330 | .read = generic_read_dir, | 3233 | .read = generic_read_dir, |
3331 | .readdir = proc_task_readdir, | 3234 | .iterate = proc_task_readdir, |
3332 | .llseek = default_llseek, | 3235 | .llseek = default_llseek, |
3333 | }; | 3236 | }; |
diff --git a/fs/proc/fd.c b/fs/proc/fd.c index d7a4a28ef630..1441f143c43b 100644 --- a/fs/proc/fd.c +++ b/fs/proc/fd.c | |||
@@ -219,74 +219,58 @@ out_no_task: | |||
219 | return result; | 219 | return result; |
220 | } | 220 | } |
221 | 221 | ||
222 | static int proc_readfd_common(struct file * filp, void * dirent, | 222 | static int proc_readfd_common(struct file *file, struct dir_context *ctx, |
223 | filldir_t filldir, instantiate_t instantiate) | 223 | instantiate_t instantiate) |
224 | { | 224 | { |
225 | struct dentry *dentry = filp->f_path.dentry; | 225 | struct task_struct *p = get_proc_task(file_inode(file)); |
226 | struct inode *inode = dentry->d_inode; | ||
227 | struct task_struct *p = get_proc_task(inode); | ||
228 | struct files_struct *files; | 226 | struct files_struct *files; |
229 | unsigned int fd, ino; | 227 | unsigned int fd; |
230 | int retval; | ||
231 | 228 | ||
232 | retval = -ENOENT; | ||
233 | if (!p) | 229 | if (!p) |
234 | goto out_no_task; | 230 | return -ENOENT; |
235 | retval = 0; | ||
236 | |||
237 | fd = filp->f_pos; | ||
238 | switch (fd) { | ||
239 | case 0: | ||
240 | if (filldir(dirent, ".", 1, 0, inode->i_ino, DT_DIR) < 0) | ||
241 | goto out; | ||
242 | filp->f_pos++; | ||
243 | case 1: | ||
244 | ino = parent_ino(dentry); | ||
245 | if (filldir(dirent, "..", 2, 1, ino, DT_DIR) < 0) | ||
246 | goto out; | ||
247 | filp->f_pos++; | ||
248 | default: | ||
249 | files = get_files_struct(p); | ||
250 | if (!files) | ||
251 | goto out; | ||
252 | rcu_read_lock(); | ||
253 | for (fd = filp->f_pos - 2; | ||
254 | fd < files_fdtable(files)->max_fds; | ||
255 | fd++, filp->f_pos++) { | ||
256 | char name[PROC_NUMBUF]; | ||
257 | int len; | ||
258 | int rv; | ||
259 | |||
260 | if (!fcheck_files(files, fd)) | ||
261 | continue; | ||
262 | rcu_read_unlock(); | ||
263 | 231 | ||
264 | len = snprintf(name, sizeof(name), "%d", fd); | 232 | if (!dir_emit_dots(file, ctx)) |
265 | rv = proc_fill_cache(filp, dirent, filldir, | 233 | goto out; |
266 | name, len, instantiate, p, | 234 | if (!dir_emit_dots(file, ctx)) |
267 | (void *)(unsigned long)fd); | 235 | goto out; |
268 | if (rv < 0) | 236 | files = get_files_struct(p); |
269 | goto out_fd_loop; | 237 | if (!files) |
270 | rcu_read_lock(); | 238 | goto out; |
271 | } | 239 | |
272 | rcu_read_unlock(); | 240 | rcu_read_lock(); |
273 | out_fd_loop: | 241 | for (fd = ctx->pos - 2; |
274 | put_files_struct(files); | 242 | fd < files_fdtable(files)->max_fds; |
243 | fd++, ctx->pos++) { | ||
244 | char name[PROC_NUMBUF]; | ||
245 | int len; | ||
246 | |||
247 | if (!fcheck_files(files, fd)) | ||
248 | continue; | ||
249 | rcu_read_unlock(); | ||
250 | |||
251 | len = snprintf(name, sizeof(name), "%d", fd); | ||
252 | if (!proc_fill_cache(file, ctx, | ||
253 | name, len, instantiate, p, | ||
254 | (void *)(unsigned long)fd)) | ||
255 | goto out_fd_loop; | ||
256 | rcu_read_lock(); | ||
275 | } | 257 | } |
258 | rcu_read_unlock(); | ||
259 | out_fd_loop: | ||
260 | put_files_struct(files); | ||
276 | out: | 261 | out: |
277 | put_task_struct(p); | 262 | put_task_struct(p); |
278 | out_no_task: | 263 | return 0; |
279 | return retval; | ||
280 | } | 264 | } |
281 | 265 | ||
282 | static int proc_readfd(struct file *filp, void *dirent, filldir_t filldir) | 266 | static int proc_readfd(struct file *file, struct dir_context *ctx) |
283 | { | 267 | { |
284 | return proc_readfd_common(filp, dirent, filldir, proc_fd_instantiate); | 268 | return proc_readfd_common(file, ctx, proc_fd_instantiate); |
285 | } | 269 | } |
286 | 270 | ||
287 | const struct file_operations proc_fd_operations = { | 271 | const struct file_operations proc_fd_operations = { |
288 | .read = generic_read_dir, | 272 | .read = generic_read_dir, |
289 | .readdir = proc_readfd, | 273 | .iterate = proc_readfd, |
290 | .llseek = default_llseek, | 274 | .llseek = default_llseek, |
291 | }; | 275 | }; |
292 | 276 | ||
@@ -351,9 +335,9 @@ proc_lookupfdinfo(struct inode *dir, struct dentry *dentry, unsigned int flags) | |||
351 | return proc_lookupfd_common(dir, dentry, proc_fdinfo_instantiate); | 335 | return proc_lookupfd_common(dir, dentry, proc_fdinfo_instantiate); |
352 | } | 336 | } |
353 | 337 | ||
354 | static int proc_readfdinfo(struct file *filp, void *dirent, filldir_t filldir) | 338 | static int proc_readfdinfo(struct file *file, struct dir_context *ctx) |
355 | { | 339 | { |
356 | return proc_readfd_common(filp, dirent, filldir, | 340 | return proc_readfd_common(file, ctx, |
357 | proc_fdinfo_instantiate); | 341 | proc_fdinfo_instantiate); |
358 | } | 342 | } |
359 | 343 | ||
@@ -364,6 +348,6 @@ const struct inode_operations proc_fdinfo_inode_operations = { | |||
364 | 348 | ||
365 | const struct file_operations proc_fdinfo_operations = { | 349 | const struct file_operations proc_fdinfo_operations = { |
366 | .read = generic_read_dir, | 350 | .read = generic_read_dir, |
367 | .readdir = proc_readfdinfo, | 351 | .iterate = proc_readfdinfo, |
368 | .llseek = default_llseek, | 352 | .llseek = default_llseek, |
369 | }; | 353 | }; |
diff --git a/fs/proc/generic.c b/fs/proc/generic.c index a2596afffae6..94441a407337 100644 --- a/fs/proc/generic.c +++ b/fs/proc/generic.c | |||
@@ -233,76 +233,52 @@ struct dentry *proc_lookup(struct inode *dir, struct dentry *dentry, | |||
233 | * value of the readdir() call, as long as it's non-negative | 233 | * value of the readdir() call, as long as it's non-negative |
234 | * for success.. | 234 | * for success.. |
235 | */ | 235 | */ |
236 | int proc_readdir_de(struct proc_dir_entry *de, struct file *filp, void *dirent, | 236 | int proc_readdir_de(struct proc_dir_entry *de, struct file *file, |
237 | filldir_t filldir) | 237 | struct dir_context *ctx) |
238 | { | 238 | { |
239 | unsigned int ino; | ||
240 | int i; | 239 | int i; |
241 | struct inode *inode = file_inode(filp); | ||
242 | int ret = 0; | ||
243 | |||
244 | ino = inode->i_ino; | ||
245 | i = filp->f_pos; | ||
246 | switch (i) { | ||
247 | case 0: | ||
248 | if (filldir(dirent, ".", 1, i, ino, DT_DIR) < 0) | ||
249 | goto out; | ||
250 | i++; | ||
251 | filp->f_pos++; | ||
252 | /* fall through */ | ||
253 | case 1: | ||
254 | if (filldir(dirent, "..", 2, i, | ||
255 | parent_ino(filp->f_path.dentry), | ||
256 | DT_DIR) < 0) | ||
257 | goto out; | ||
258 | i++; | ||
259 | filp->f_pos++; | ||
260 | /* fall through */ | ||
261 | default: | ||
262 | spin_lock(&proc_subdir_lock); | ||
263 | de = de->subdir; | ||
264 | i -= 2; | ||
265 | for (;;) { | ||
266 | if (!de) { | ||
267 | ret = 1; | ||
268 | spin_unlock(&proc_subdir_lock); | ||
269 | goto out; | ||
270 | } | ||
271 | if (!i) | ||
272 | break; | ||
273 | de = de->next; | ||
274 | i--; | ||
275 | } | ||
276 | 240 | ||
277 | do { | 241 | if (!dir_emit_dots(file, ctx)) |
278 | struct proc_dir_entry *next; | 242 | return 0; |
279 | 243 | ||
280 | /* filldir passes info to user space */ | 244 | spin_lock(&proc_subdir_lock); |
281 | pde_get(de); | 245 | de = de->subdir; |
282 | spin_unlock(&proc_subdir_lock); | 246 | i = ctx->pos - 2; |
283 | if (filldir(dirent, de->name, de->namelen, filp->f_pos, | 247 | for (;;) { |
284 | de->low_ino, de->mode >> 12) < 0) { | 248 | if (!de) { |
285 | pde_put(de); | ||
286 | goto out; | ||
287 | } | ||
288 | spin_lock(&proc_subdir_lock); | ||
289 | filp->f_pos++; | ||
290 | next = de->next; | ||
291 | pde_put(de); | ||
292 | de = next; | ||
293 | } while (de); | ||
294 | spin_unlock(&proc_subdir_lock); | 249 | spin_unlock(&proc_subdir_lock); |
250 | return 0; | ||
251 | } | ||
252 | if (!i) | ||
253 | break; | ||
254 | de = de->next; | ||
255 | i--; | ||
295 | } | 256 | } |
296 | ret = 1; | 257 | |
297 | out: | 258 | do { |
298 | return ret; | 259 | struct proc_dir_entry *next; |
260 | pde_get(de); | ||
261 | spin_unlock(&proc_subdir_lock); | ||
262 | if (!dir_emit(ctx, de->name, de->namelen, | ||
263 | de->low_ino, de->mode >> 12)) { | ||
264 | pde_put(de); | ||
265 | return 0; | ||
266 | } | ||
267 | spin_lock(&proc_subdir_lock); | ||
268 | ctx->pos++; | ||
269 | next = de->next; | ||
270 | pde_put(de); | ||
271 | de = next; | ||
272 | } while (de); | ||
273 | spin_unlock(&proc_subdir_lock); | ||
274 | return 0; | ||
299 | } | 275 | } |
300 | 276 | ||
301 | int proc_readdir(struct file *filp, void *dirent, filldir_t filldir) | 277 | int proc_readdir(struct file *file, struct dir_context *ctx) |
302 | { | 278 | { |
303 | struct inode *inode = file_inode(filp); | 279 | struct inode *inode = file_inode(file); |
304 | 280 | ||
305 | return proc_readdir_de(PDE(inode), filp, dirent, filldir); | 281 | return proc_readdir_de(PDE(inode), file, ctx); |
306 | } | 282 | } |
307 | 283 | ||
308 | /* | 284 | /* |
@@ -313,7 +289,7 @@ int proc_readdir(struct file *filp, void *dirent, filldir_t filldir) | |||
313 | static const struct file_operations proc_dir_operations = { | 289 | static const struct file_operations proc_dir_operations = { |
314 | .llseek = generic_file_llseek, | 290 | .llseek = generic_file_llseek, |
315 | .read = generic_read_dir, | 291 | .read = generic_read_dir, |
316 | .readdir = proc_readdir, | 292 | .iterate = proc_readdir, |
317 | }; | 293 | }; |
318 | 294 | ||
319 | /* | 295 | /* |
diff --git a/fs/proc/internal.h b/fs/proc/internal.h index d600fb098b6a..4eae2e149f31 100644 --- a/fs/proc/internal.h +++ b/fs/proc/internal.h | |||
@@ -165,14 +165,14 @@ extern int proc_setattr(struct dentry *, struct iattr *); | |||
165 | extern struct inode *proc_pid_make_inode(struct super_block *, struct task_struct *); | 165 | extern struct inode *proc_pid_make_inode(struct super_block *, struct task_struct *); |
166 | extern int pid_revalidate(struct dentry *, unsigned int); | 166 | extern int pid_revalidate(struct dentry *, unsigned int); |
167 | extern int pid_delete_dentry(const struct dentry *); | 167 | extern int pid_delete_dentry(const struct dentry *); |
168 | extern int proc_pid_readdir(struct file *, void *, filldir_t); | 168 | extern int proc_pid_readdir(struct file *, struct dir_context *); |
169 | extern struct dentry *proc_pid_lookup(struct inode *, struct dentry *, unsigned int); | 169 | extern struct dentry *proc_pid_lookup(struct inode *, struct dentry *, unsigned int); |
170 | extern loff_t mem_lseek(struct file *, loff_t, int); | 170 | extern loff_t mem_lseek(struct file *, loff_t, int); |
171 | 171 | ||
172 | /* Lookups */ | 172 | /* Lookups */ |
173 | typedef struct dentry *instantiate_t(struct inode *, struct dentry *, | 173 | typedef struct dentry *instantiate_t(struct inode *, struct dentry *, |
174 | struct task_struct *, const void *); | 174 | struct task_struct *, const void *); |
175 | extern int proc_fill_cache(struct file *, void *, filldir_t, const char *, int, | 175 | extern bool proc_fill_cache(struct file *, struct dir_context *, const char *, int, |
176 | instantiate_t, struct task_struct *, const void *); | 176 | instantiate_t, struct task_struct *, const void *); |
177 | 177 | ||
178 | /* | 178 | /* |
@@ -183,8 +183,8 @@ extern spinlock_t proc_subdir_lock; | |||
183 | extern struct dentry *proc_lookup(struct inode *, struct dentry *, unsigned int); | 183 | extern struct dentry *proc_lookup(struct inode *, struct dentry *, unsigned int); |
184 | extern struct dentry *proc_lookup_de(struct proc_dir_entry *, struct inode *, | 184 | extern struct dentry *proc_lookup_de(struct proc_dir_entry *, struct inode *, |
185 | struct dentry *); | 185 | struct dentry *); |
186 | extern int proc_readdir(struct file *, void *, filldir_t); | 186 | extern int proc_readdir(struct file *, struct dir_context *); |
187 | extern int proc_readdir_de(struct proc_dir_entry *, struct file *, void *, filldir_t); | 187 | extern int proc_readdir_de(struct proc_dir_entry *, struct file *, struct dir_context *); |
188 | 188 | ||
189 | static inline struct proc_dir_entry *pde_get(struct proc_dir_entry *pde) | 189 | static inline struct proc_dir_entry *pde_get(struct proc_dir_entry *pde) |
190 | { | 190 | { |
diff --git a/fs/proc/namespaces.c b/fs/proc/namespaces.c index 54bdc6701e9f..f6abbbbfad8a 100644 --- a/fs/proc/namespaces.c +++ b/fs/proc/namespaces.c | |||
@@ -213,74 +213,36 @@ out: | |||
213 | return error; | 213 | return error; |
214 | } | 214 | } |
215 | 215 | ||
216 | static int proc_ns_fill_cache(struct file *filp, void *dirent, | 216 | static int proc_ns_dir_readdir(struct file *file, struct dir_context *ctx) |
217 | filldir_t filldir, struct task_struct *task, | ||
218 | const struct proc_ns_operations *ops) | ||
219 | { | 217 | { |
220 | return proc_fill_cache(filp, dirent, filldir, | 218 | struct task_struct *task = get_proc_task(file_inode(file)); |
221 | ops->name, strlen(ops->name), | ||
222 | proc_ns_instantiate, task, ops); | ||
223 | } | ||
224 | |||
225 | static int proc_ns_dir_readdir(struct file *filp, void *dirent, | ||
226 | filldir_t filldir) | ||
227 | { | ||
228 | int i; | ||
229 | struct dentry *dentry = filp->f_path.dentry; | ||
230 | struct inode *inode = dentry->d_inode; | ||
231 | struct task_struct *task = get_proc_task(inode); | ||
232 | const struct proc_ns_operations **entry, **last; | 219 | const struct proc_ns_operations **entry, **last; |
233 | ino_t ino; | ||
234 | int ret; | ||
235 | 220 | ||
236 | ret = -ENOENT; | ||
237 | if (!task) | 221 | if (!task) |
238 | goto out_no_task; | 222 | return -ENOENT; |
239 | 223 | ||
240 | ret = 0; | 224 | if (!dir_emit_dots(file, ctx)) |
241 | i = filp->f_pos; | 225 | goto out; |
242 | switch (i) { | 226 | if (ctx->pos >= 2 + ARRAY_SIZE(ns_entries)) |
243 | case 0: | 227 | goto out; |
244 | ino = inode->i_ino; | 228 | entry = ns_entries + (ctx->pos - 2); |
245 | if (filldir(dirent, ".", 1, i, ino, DT_DIR) < 0) | 229 | last = &ns_entries[ARRAY_SIZE(ns_entries) - 1]; |
246 | goto out; | 230 | while (entry <= last) { |
247 | i++; | 231 | const struct proc_ns_operations *ops = *entry; |
248 | filp->f_pos++; | 232 | if (!proc_fill_cache(file, ctx, ops->name, strlen(ops->name), |
249 | /* fall through */ | 233 | proc_ns_instantiate, task, ops)) |
250 | case 1: | 234 | break; |
251 | ino = parent_ino(dentry); | 235 | ctx->pos++; |
252 | if (filldir(dirent, "..", 2, i, ino, DT_DIR) < 0) | 236 | entry++; |
253 | goto out; | ||
254 | i++; | ||
255 | filp->f_pos++; | ||
256 | /* fall through */ | ||
257 | default: | ||
258 | i -= 2; | ||
259 | if (i >= ARRAY_SIZE(ns_entries)) { | ||
260 | ret = 1; | ||
261 | goto out; | ||
262 | } | ||
263 | entry = ns_entries + i; | ||
264 | last = &ns_entries[ARRAY_SIZE(ns_entries) - 1]; | ||
265 | while (entry <= last) { | ||
266 | if (proc_ns_fill_cache(filp, dirent, filldir, | ||
267 | task, *entry) < 0) | ||
268 | goto out; | ||
269 | filp->f_pos++; | ||
270 | entry++; | ||
271 | } | ||
272 | } | 237 | } |
273 | |||
274 | ret = 1; | ||
275 | out: | 238 | out: |
276 | put_task_struct(task); | 239 | put_task_struct(task); |
277 | out_no_task: | 240 | return 0; |
278 | return ret; | ||
279 | } | 241 | } |
280 | 242 | ||
281 | const struct file_operations proc_ns_dir_operations = { | 243 | const struct file_operations proc_ns_dir_operations = { |
282 | .read = generic_read_dir, | 244 | .read = generic_read_dir, |
283 | .readdir = proc_ns_dir_readdir, | 245 | .iterate = proc_ns_dir_readdir, |
284 | }; | 246 | }; |
285 | 247 | ||
286 | static struct dentry *proc_ns_dir_lookup(struct inode *dir, | 248 | static struct dentry *proc_ns_dir_lookup(struct inode *dir, |
diff --git a/fs/proc/proc_net.c b/fs/proc/proc_net.c index 986e83220d56..4677bb7dc7c2 100644 --- a/fs/proc/proc_net.c +++ b/fs/proc/proc_net.c | |||
@@ -160,16 +160,15 @@ const struct inode_operations proc_net_inode_operations = { | |||
160 | .getattr = proc_tgid_net_getattr, | 160 | .getattr = proc_tgid_net_getattr, |
161 | }; | 161 | }; |
162 | 162 | ||
163 | static int proc_tgid_net_readdir(struct file *filp, void *dirent, | 163 | static int proc_tgid_net_readdir(struct file *file, struct dir_context *ctx) |
164 | filldir_t filldir) | ||
165 | { | 164 | { |
166 | int ret; | 165 | int ret; |
167 | struct net *net; | 166 | struct net *net; |
168 | 167 | ||
169 | ret = -EINVAL; | 168 | ret = -EINVAL; |
170 | net = get_proc_task_net(file_inode(filp)); | 169 | net = get_proc_task_net(file_inode(file)); |
171 | if (net != NULL) { | 170 | if (net != NULL) { |
172 | ret = proc_readdir_de(net->proc_net, filp, dirent, filldir); | 171 | ret = proc_readdir_de(net->proc_net, file, ctx); |
173 | put_net(net); | 172 | put_net(net); |
174 | } | 173 | } |
175 | return ret; | 174 | return ret; |
@@ -178,7 +177,7 @@ static int proc_tgid_net_readdir(struct file *filp, void *dirent, | |||
178 | const struct file_operations proc_net_operations = { | 177 | const struct file_operations proc_net_operations = { |
179 | .llseek = generic_file_llseek, | 178 | .llseek = generic_file_llseek, |
180 | .read = generic_read_dir, | 179 | .read = generic_read_dir, |
181 | .readdir = proc_tgid_net_readdir, | 180 | .iterate = proc_tgid_net_readdir, |
182 | }; | 181 | }; |
183 | 182 | ||
184 | static __net_init int proc_net_ns_init(struct net *net) | 183 | static __net_init int proc_net_ns_init(struct net *net) |
diff --git a/fs/proc/proc_sysctl.c b/fs/proc/proc_sysctl.c index ac05f33a0dde..f3a570e7c257 100644 --- a/fs/proc/proc_sysctl.c +++ b/fs/proc/proc_sysctl.c | |||
@@ -573,12 +573,12 @@ out: | |||
573 | return ret; | 573 | return ret; |
574 | } | 574 | } |
575 | 575 | ||
576 | static int proc_sys_fill_cache(struct file *filp, void *dirent, | 576 | static bool proc_sys_fill_cache(struct file *file, |
577 | filldir_t filldir, | 577 | struct dir_context *ctx, |
578 | struct ctl_table_header *head, | 578 | struct ctl_table_header *head, |
579 | struct ctl_table *table) | 579 | struct ctl_table *table) |
580 | { | 580 | { |
581 | struct dentry *child, *dir = filp->f_path.dentry; | 581 | struct dentry *child, *dir = file->f_path.dentry; |
582 | struct inode *inode; | 582 | struct inode *inode; |
583 | struct qstr qname; | 583 | struct qstr qname; |
584 | ino_t ino = 0; | 584 | ino_t ino = 0; |
@@ -595,38 +595,38 @@ static int proc_sys_fill_cache(struct file *filp, void *dirent, | |||
595 | inode = proc_sys_make_inode(dir->d_sb, head, table); | 595 | inode = proc_sys_make_inode(dir->d_sb, head, table); |
596 | if (!inode) { | 596 | if (!inode) { |
597 | dput(child); | 597 | dput(child); |
598 | return -ENOMEM; | 598 | return false; |
599 | } else { | 599 | } else { |
600 | d_set_d_op(child, &proc_sys_dentry_operations); | 600 | d_set_d_op(child, &proc_sys_dentry_operations); |
601 | d_add(child, inode); | 601 | d_add(child, inode); |
602 | } | 602 | } |
603 | } else { | 603 | } else { |
604 | return -ENOMEM; | 604 | return false; |
605 | } | 605 | } |
606 | } | 606 | } |
607 | inode = child->d_inode; | 607 | inode = child->d_inode; |
608 | ino = inode->i_ino; | 608 | ino = inode->i_ino; |
609 | type = inode->i_mode >> 12; | 609 | type = inode->i_mode >> 12; |
610 | dput(child); | 610 | dput(child); |
611 | return !!filldir(dirent, qname.name, qname.len, filp->f_pos, ino, type); | 611 | return dir_emit(ctx, qname.name, qname.len, ino, type); |
612 | } | 612 | } |
613 | 613 | ||
614 | static int proc_sys_link_fill_cache(struct file *filp, void *dirent, | 614 | static bool proc_sys_link_fill_cache(struct file *file, |
615 | filldir_t filldir, | 615 | struct dir_context *ctx, |
616 | struct ctl_table_header *head, | 616 | struct ctl_table_header *head, |
617 | struct ctl_table *table) | 617 | struct ctl_table *table) |
618 | { | 618 | { |
619 | int err, ret = 0; | 619 | bool ret = true; |
620 | head = sysctl_head_grab(head); | 620 | head = sysctl_head_grab(head); |
621 | 621 | ||
622 | if (S_ISLNK(table->mode)) { | 622 | if (S_ISLNK(table->mode)) { |
623 | /* It is not an error if we can not follow the link ignore it */ | 623 | /* It is not an error if we can not follow the link ignore it */ |
624 | err = sysctl_follow_link(&head, &table, current->nsproxy); | 624 | int err = sysctl_follow_link(&head, &table, current->nsproxy); |
625 | if (err) | 625 | if (err) |
626 | goto out; | 626 | goto out; |
627 | } | 627 | } |
628 | 628 | ||
629 | ret = proc_sys_fill_cache(filp, dirent, filldir, head, table); | 629 | ret = proc_sys_fill_cache(file, ctx, head, table); |
630 | out: | 630 | out: |
631 | sysctl_head_finish(head); | 631 | sysctl_head_finish(head); |
632 | return ret; | 632 | return ret; |
@@ -634,67 +634,50 @@ out: | |||
634 | 634 | ||
635 | static int scan(struct ctl_table_header *head, ctl_table *table, | 635 | static int scan(struct ctl_table_header *head, ctl_table *table, |
636 | unsigned long *pos, struct file *file, | 636 | unsigned long *pos, struct file *file, |
637 | void *dirent, filldir_t filldir) | 637 | struct dir_context *ctx) |
638 | { | 638 | { |
639 | int res; | 639 | bool res; |
640 | 640 | ||
641 | if ((*pos)++ < file->f_pos) | 641 | if ((*pos)++ < ctx->pos) |
642 | return 0; | 642 | return true; |
643 | 643 | ||
644 | if (unlikely(S_ISLNK(table->mode))) | 644 | if (unlikely(S_ISLNK(table->mode))) |
645 | res = proc_sys_link_fill_cache(file, dirent, filldir, head, table); | 645 | res = proc_sys_link_fill_cache(file, ctx, head, table); |
646 | else | 646 | else |
647 | res = proc_sys_fill_cache(file, dirent, filldir, head, table); | 647 | res = proc_sys_fill_cache(file, ctx, head, table); |
648 | 648 | ||
649 | if (res == 0) | 649 | if (res) |
650 | file->f_pos = *pos; | 650 | ctx->pos = *pos; |
651 | 651 | ||
652 | return res; | 652 | return res; |
653 | } | 653 | } |
654 | 654 | ||
655 | static int proc_sys_readdir(struct file *filp, void *dirent, filldir_t filldir) | 655 | static int proc_sys_readdir(struct file *file, struct dir_context *ctx) |
656 | { | 656 | { |
657 | struct dentry *dentry = filp->f_path.dentry; | 657 | struct ctl_table_header *head = grab_header(file_inode(file)); |
658 | struct inode *inode = dentry->d_inode; | ||
659 | struct ctl_table_header *head = grab_header(inode); | ||
660 | struct ctl_table_header *h = NULL; | 658 | struct ctl_table_header *h = NULL; |
661 | struct ctl_table *entry; | 659 | struct ctl_table *entry; |
662 | struct ctl_dir *ctl_dir; | 660 | struct ctl_dir *ctl_dir; |
663 | unsigned long pos; | 661 | unsigned long pos; |
664 | int ret = -EINVAL; | ||
665 | 662 | ||
666 | if (IS_ERR(head)) | 663 | if (IS_ERR(head)) |
667 | return PTR_ERR(head); | 664 | return PTR_ERR(head); |
668 | 665 | ||
669 | ctl_dir = container_of(head, struct ctl_dir, header); | 666 | ctl_dir = container_of(head, struct ctl_dir, header); |
670 | 667 | ||
671 | ret = 0; | 668 | if (!dir_emit_dots(file, ctx)) |
672 | /* Avoid a switch here: arm builds fail with missing __cmpdi2 */ | 669 | return 0; |
673 | if (filp->f_pos == 0) { | 670 | |
674 | if (filldir(dirent, ".", 1, filp->f_pos, | ||
675 | inode->i_ino, DT_DIR) < 0) | ||
676 | goto out; | ||
677 | filp->f_pos++; | ||
678 | } | ||
679 | if (filp->f_pos == 1) { | ||
680 | if (filldir(dirent, "..", 2, filp->f_pos, | ||
681 | parent_ino(dentry), DT_DIR) < 0) | ||
682 | goto out; | ||
683 | filp->f_pos++; | ||
684 | } | ||
685 | pos = 2; | 671 | pos = 2; |
686 | 672 | ||
687 | for (first_entry(ctl_dir, &h, &entry); h; next_entry(&h, &entry)) { | 673 | for (first_entry(ctl_dir, &h, &entry); h; next_entry(&h, &entry)) { |
688 | ret = scan(h, entry, &pos, filp, dirent, filldir); | 674 | if (!scan(h, entry, &pos, file, ctx)) { |
689 | if (ret) { | ||
690 | sysctl_head_finish(h); | 675 | sysctl_head_finish(h); |
691 | break; | 676 | break; |
692 | } | 677 | } |
693 | } | 678 | } |
694 | ret = 1; | ||
695 | out: | ||
696 | sysctl_head_finish(head); | 679 | sysctl_head_finish(head); |
697 | return ret; | 680 | return 0; |
698 | } | 681 | } |
699 | 682 | ||
700 | static int proc_sys_permission(struct inode *inode, int mask) | 683 | static int proc_sys_permission(struct inode *inode, int mask) |
@@ -769,7 +752,7 @@ static const struct file_operations proc_sys_file_operations = { | |||
769 | 752 | ||
770 | static const struct file_operations proc_sys_dir_file_operations = { | 753 | static const struct file_operations proc_sys_dir_file_operations = { |
771 | .read = generic_read_dir, | 754 | .read = generic_read_dir, |
772 | .readdir = proc_sys_readdir, | 755 | .iterate = proc_sys_readdir, |
773 | .llseek = generic_file_llseek, | 756 | .llseek = generic_file_llseek, |
774 | }; | 757 | }; |
775 | 758 | ||
diff --git a/fs/proc/root.c b/fs/proc/root.c index 41a6ea93f486..229e366598da 100644 --- a/fs/proc/root.c +++ b/fs/proc/root.c | |||
@@ -202,21 +202,14 @@ static struct dentry *proc_root_lookup(struct inode * dir, struct dentry * dentr | |||
202 | return proc_pid_lookup(dir, dentry, flags); | 202 | return proc_pid_lookup(dir, dentry, flags); |
203 | } | 203 | } |
204 | 204 | ||
205 | static int proc_root_readdir(struct file * filp, | 205 | static int proc_root_readdir(struct file *file, struct dir_context *ctx) |
206 | void * dirent, filldir_t filldir) | ||
207 | { | 206 | { |
208 | unsigned int nr = filp->f_pos; | 207 | if (ctx->pos < FIRST_PROCESS_ENTRY) { |
209 | int ret; | 208 | proc_readdir(file, ctx); |
210 | 209 | ctx->pos = FIRST_PROCESS_ENTRY; | |
211 | if (nr < FIRST_PROCESS_ENTRY) { | ||
212 | int error = proc_readdir(filp, dirent, filldir); | ||
213 | if (error <= 0) | ||
214 | return error; | ||
215 | filp->f_pos = FIRST_PROCESS_ENTRY; | ||
216 | } | 210 | } |
217 | 211 | ||
218 | ret = proc_pid_readdir(filp, dirent, filldir); | 212 | return proc_pid_readdir(file, ctx); |
219 | return ret; | ||
220 | } | 213 | } |
221 | 214 | ||
222 | /* | 215 | /* |
@@ -226,7 +219,7 @@ static int proc_root_readdir(struct file * filp, | |||
226 | */ | 219 | */ |
227 | static const struct file_operations proc_root_operations = { | 220 | static const struct file_operations proc_root_operations = { |
228 | .read = generic_read_dir, | 221 | .read = generic_read_dir, |
229 | .readdir = proc_root_readdir, | 222 | .iterate = proc_root_readdir, |
230 | .llseek = default_llseek, | 223 | .llseek = default_llseek, |
231 | }; | 224 | }; |
232 | 225 | ||
diff --git a/fs/qnx4/dir.c b/fs/qnx4/dir.c index 28ce014b3cef..b218f965817b 100644 --- a/fs/qnx4/dir.c +++ b/fs/qnx4/dir.c | |||
@@ -14,9 +14,9 @@ | |||
14 | #include <linux/buffer_head.h> | 14 | #include <linux/buffer_head.h> |
15 | #include "qnx4.h" | 15 | #include "qnx4.h" |
16 | 16 | ||
17 | static int qnx4_readdir(struct file *filp, void *dirent, filldir_t filldir) | 17 | static int qnx4_readdir(struct file *file, struct dir_context *ctx) |
18 | { | 18 | { |
19 | struct inode *inode = file_inode(filp); | 19 | struct inode *inode = file_inode(file); |
20 | unsigned int offset; | 20 | unsigned int offset; |
21 | struct buffer_head *bh; | 21 | struct buffer_head *bh; |
22 | struct qnx4_inode_entry *de; | 22 | struct qnx4_inode_entry *de; |
@@ -26,48 +26,44 @@ static int qnx4_readdir(struct file *filp, void *dirent, filldir_t filldir) | |||
26 | int size; | 26 | int size; |
27 | 27 | ||
28 | QNX4DEBUG((KERN_INFO "qnx4_readdir:i_size = %ld\n", (long) inode->i_size)); | 28 | QNX4DEBUG((KERN_INFO "qnx4_readdir:i_size = %ld\n", (long) inode->i_size)); |
29 | QNX4DEBUG((KERN_INFO "filp->f_pos = %ld\n", (long) filp->f_pos)); | 29 | QNX4DEBUG((KERN_INFO "pos = %ld\n", (long) ctx->pos)); |
30 | 30 | ||
31 | while (filp->f_pos < inode->i_size) { | 31 | while (ctx->pos < inode->i_size) { |
32 | blknum = qnx4_block_map( inode, filp->f_pos >> QNX4_BLOCK_SIZE_BITS ); | 32 | blknum = qnx4_block_map(inode, ctx->pos >> QNX4_BLOCK_SIZE_BITS); |
33 | bh = sb_bread(inode->i_sb, blknum); | 33 | bh = sb_bread(inode->i_sb, blknum); |
34 | if(bh==NULL) { | 34 | if (bh == NULL) { |
35 | printk(KERN_ERR "qnx4_readdir: bread failed (%ld)\n", blknum); | 35 | printk(KERN_ERR "qnx4_readdir: bread failed (%ld)\n", blknum); |
36 | break; | 36 | return 0; |
37 | } | 37 | } |
38 | ix = (int)(filp->f_pos >> QNX4_DIR_ENTRY_SIZE_BITS) % QNX4_INODES_PER_BLOCK; | 38 | ix = (ctx->pos >> QNX4_DIR_ENTRY_SIZE_BITS) % QNX4_INODES_PER_BLOCK; |
39 | while (ix < QNX4_INODES_PER_BLOCK) { | 39 | for (; ix < QNX4_INODES_PER_BLOCK; ix++, ctx->pos += QNX4_DIR_ENTRY_SIZE) { |
40 | offset = ix * QNX4_DIR_ENTRY_SIZE; | 40 | offset = ix * QNX4_DIR_ENTRY_SIZE; |
41 | de = (struct qnx4_inode_entry *) (bh->b_data + offset); | 41 | de = (struct qnx4_inode_entry *) (bh->b_data + offset); |
42 | size = strlen(de->di_fname); | 42 | if (!de->di_fname[0]) |
43 | if (size) { | 43 | continue; |
44 | if ( !( de->di_status & QNX4_FILE_LINK ) && size > QNX4_SHORT_NAME_MAX ) | 44 | if (!(de->di_status & (QNX4_FILE_USED|QNX4_FILE_LINK))) |
45 | size = QNX4_SHORT_NAME_MAX; | 45 | continue; |
46 | else if ( size > QNX4_NAME_MAX ) | 46 | if (!(de->di_status & QNX4_FILE_LINK)) |
47 | size = QNX4_NAME_MAX; | 47 | size = QNX4_SHORT_NAME_MAX; |
48 | 48 | else | |
49 | if ( ( de->di_status & (QNX4_FILE_USED|QNX4_FILE_LINK) ) != 0 ) { | 49 | size = QNX4_NAME_MAX; |
50 | QNX4DEBUG((KERN_INFO "qnx4_readdir:%.*s\n", size, de->di_fname)); | 50 | size = strnlen(de->di_fname, size); |
51 | if ( ( de->di_status & QNX4_FILE_LINK ) == 0 ) | 51 | QNX4DEBUG((KERN_INFO "qnx4_readdir:%.*s\n", size, de->di_fname)); |
52 | ino = blknum * QNX4_INODES_PER_BLOCK + ix - 1; | 52 | if (!(de->di_status & QNX4_FILE_LINK)) |
53 | else { | 53 | ino = blknum * QNX4_INODES_PER_BLOCK + ix - 1; |
54 | le = (struct qnx4_link_info*)de; | 54 | else { |
55 | ino = ( le32_to_cpu(le->dl_inode_blk) - 1 ) * | 55 | le = (struct qnx4_link_info*)de; |
56 | QNX4_INODES_PER_BLOCK + | 56 | ino = ( le32_to_cpu(le->dl_inode_blk) - 1 ) * |
57 | le->dl_inode_ndx; | 57 | QNX4_INODES_PER_BLOCK + |
58 | } | 58 | le->dl_inode_ndx; |
59 | if (filldir(dirent, de->di_fname, size, filp->f_pos, ino, DT_UNKNOWN) < 0) { | 59 | } |
60 | brelse(bh); | 60 | if (!dir_emit(ctx, de->di_fname, size, ino, DT_UNKNOWN)) { |
61 | goto out; | 61 | brelse(bh); |
62 | } | 62 | return 0; |
63 | } | ||
64 | } | 63 | } |
65 | ix++; | ||
66 | filp->f_pos += QNX4_DIR_ENTRY_SIZE; | ||
67 | } | 64 | } |
68 | brelse(bh); | 65 | brelse(bh); |
69 | } | 66 | } |
70 | out: | ||
71 | return 0; | 67 | return 0; |
72 | } | 68 | } |
73 | 69 | ||
@@ -75,7 +71,7 @@ const struct file_operations qnx4_dir_operations = | |||
75 | { | 71 | { |
76 | .llseek = generic_file_llseek, | 72 | .llseek = generic_file_llseek, |
77 | .read = generic_read_dir, | 73 | .read = generic_read_dir, |
78 | .readdir = qnx4_readdir, | 74 | .iterate = qnx4_readdir, |
79 | .fsync = generic_file_fsync, | 75 | .fsync = generic_file_fsync, |
80 | }; | 76 | }; |
81 | 77 | ||
diff --git a/fs/qnx6/dir.c b/fs/qnx6/dir.c index afa6be6fc397..15b7d92ed60d 100644 --- a/fs/qnx6/dir.c +++ b/fs/qnx6/dir.c | |||
@@ -65,8 +65,8 @@ static struct qnx6_long_filename *qnx6_longname(struct super_block *sb, | |||
65 | 65 | ||
66 | static int qnx6_dir_longfilename(struct inode *inode, | 66 | static int qnx6_dir_longfilename(struct inode *inode, |
67 | struct qnx6_long_dir_entry *de, | 67 | struct qnx6_long_dir_entry *de, |
68 | void *dirent, loff_t pos, | 68 | struct dir_context *ctx, |
69 | unsigned de_inode, filldir_t filldir) | 69 | unsigned de_inode) |
70 | { | 70 | { |
71 | struct qnx6_long_filename *lf; | 71 | struct qnx6_long_filename *lf; |
72 | struct super_block *s = inode->i_sb; | 72 | struct super_block *s = inode->i_sb; |
@@ -104,8 +104,7 @@ static int qnx6_dir_longfilename(struct inode *inode, | |||
104 | 104 | ||
105 | QNX6DEBUG((KERN_INFO "qnx6_readdir:%.*s inode:%u\n", | 105 | QNX6DEBUG((KERN_INFO "qnx6_readdir:%.*s inode:%u\n", |
106 | lf_size, lf->lf_fname, de_inode)); | 106 | lf_size, lf->lf_fname, de_inode)); |
107 | if (filldir(dirent, lf->lf_fname, lf_size, pos, de_inode, | 107 | if (!dir_emit(ctx, lf->lf_fname, lf_size, de_inode, DT_UNKNOWN)) { |
108 | DT_UNKNOWN) < 0) { | ||
109 | qnx6_put_page(page); | 108 | qnx6_put_page(page); |
110 | return 0; | 109 | return 0; |
111 | } | 110 | } |
@@ -115,18 +114,19 @@ static int qnx6_dir_longfilename(struct inode *inode, | |||
115 | return 1; | 114 | return 1; |
116 | } | 115 | } |
117 | 116 | ||
118 | static int qnx6_readdir(struct file *filp, void *dirent, filldir_t filldir) | 117 | static int qnx6_readdir(struct file *file, struct dir_context *ctx) |
119 | { | 118 | { |
120 | struct inode *inode = file_inode(filp); | 119 | struct inode *inode = file_inode(file); |
121 | struct super_block *s = inode->i_sb; | 120 | struct super_block *s = inode->i_sb; |
122 | struct qnx6_sb_info *sbi = QNX6_SB(s); | 121 | struct qnx6_sb_info *sbi = QNX6_SB(s); |
123 | loff_t pos = filp->f_pos & ~(QNX6_DIR_ENTRY_SIZE - 1); | 122 | loff_t pos = ctx->pos & ~(QNX6_DIR_ENTRY_SIZE - 1); |
124 | unsigned long npages = dir_pages(inode); | 123 | unsigned long npages = dir_pages(inode); |
125 | unsigned long n = pos >> PAGE_CACHE_SHIFT; | 124 | unsigned long n = pos >> PAGE_CACHE_SHIFT; |
126 | unsigned start = (pos & ~PAGE_CACHE_MASK) / QNX6_DIR_ENTRY_SIZE; | 125 | unsigned start = (pos & ~PAGE_CACHE_MASK) / QNX6_DIR_ENTRY_SIZE; |
127 | bool done = false; | 126 | bool done = false; |
128 | 127 | ||
129 | if (filp->f_pos >= inode->i_size) | 128 | ctx->pos = pos; |
129 | if (ctx->pos >= inode->i_size) | ||
130 | return 0; | 130 | return 0; |
131 | 131 | ||
132 | for ( ; !done && n < npages; n++, start = 0) { | 132 | for ( ; !done && n < npages; n++, start = 0) { |
@@ -137,11 +137,11 @@ static int qnx6_readdir(struct file *filp, void *dirent, filldir_t filldir) | |||
137 | 137 | ||
138 | if (IS_ERR(page)) { | 138 | if (IS_ERR(page)) { |
139 | printk(KERN_ERR "qnx6_readdir: read failed\n"); | 139 | printk(KERN_ERR "qnx6_readdir: read failed\n"); |
140 | filp->f_pos = (n + 1) << PAGE_CACHE_SHIFT; | 140 | ctx->pos = (n + 1) << PAGE_CACHE_SHIFT; |
141 | return PTR_ERR(page); | 141 | return PTR_ERR(page); |
142 | } | 142 | } |
143 | de = ((struct qnx6_dir_entry *)page_address(page)) + start; | 143 | de = ((struct qnx6_dir_entry *)page_address(page)) + start; |
144 | for (; i < limit; i++, de++, pos += QNX6_DIR_ENTRY_SIZE) { | 144 | for (; i < limit; i++, de++, ctx->pos += QNX6_DIR_ENTRY_SIZE) { |
145 | int size = de->de_size; | 145 | int size = de->de_size; |
146 | u32 no_inode = fs32_to_cpu(sbi, de->de_inode); | 146 | u32 no_inode = fs32_to_cpu(sbi, de->de_inode); |
147 | 147 | ||
@@ -154,8 +154,7 @@ static int qnx6_readdir(struct file *filp, void *dirent, filldir_t filldir) | |||
154 | structure / block */ | 154 | structure / block */ |
155 | if (!qnx6_dir_longfilename(inode, | 155 | if (!qnx6_dir_longfilename(inode, |
156 | (struct qnx6_long_dir_entry *)de, | 156 | (struct qnx6_long_dir_entry *)de, |
157 | dirent, pos, no_inode, | 157 | ctx, no_inode)) { |
158 | filldir)) { | ||
159 | done = true; | 158 | done = true; |
160 | break; | 159 | break; |
161 | } | 160 | } |
@@ -163,9 +162,8 @@ static int qnx6_readdir(struct file *filp, void *dirent, filldir_t filldir) | |||
163 | QNX6DEBUG((KERN_INFO "qnx6_readdir:%.*s" | 162 | QNX6DEBUG((KERN_INFO "qnx6_readdir:%.*s" |
164 | " inode:%u\n", size, de->de_fname, | 163 | " inode:%u\n", size, de->de_fname, |
165 | no_inode)); | 164 | no_inode)); |
166 | if (filldir(dirent, de->de_fname, size, | 165 | if (!dir_emit(ctx, de->de_fname, size, |
167 | pos, no_inode, DT_UNKNOWN) | 166 | no_inode, DT_UNKNOWN)) { |
168 | < 0) { | ||
169 | done = true; | 167 | done = true; |
170 | break; | 168 | break; |
171 | } | 169 | } |
@@ -173,7 +171,6 @@ static int qnx6_readdir(struct file *filp, void *dirent, filldir_t filldir) | |||
173 | } | 171 | } |
174 | qnx6_put_page(page); | 172 | qnx6_put_page(page); |
175 | } | 173 | } |
176 | filp->f_pos = pos; | ||
177 | return 0; | 174 | return 0; |
178 | } | 175 | } |
179 | 176 | ||
@@ -282,7 +279,7 @@ found: | |||
282 | const struct file_operations qnx6_dir_operations = { | 279 | const struct file_operations qnx6_dir_operations = { |
283 | .llseek = generic_file_llseek, | 280 | .llseek = generic_file_llseek, |
284 | .read = generic_read_dir, | 281 | .read = generic_read_dir, |
285 | .readdir = qnx6_readdir, | 282 | .iterate = qnx6_readdir, |
286 | .fsync = generic_file_fsync, | 283 | .fsync = generic_file_fsync, |
287 | }; | 284 | }; |
288 | 285 | ||
diff --git a/fs/readdir.c b/fs/readdir.c index fee38e04fae4..93d71e574310 100644 --- a/fs/readdir.c +++ b/fs/readdir.c | |||
@@ -20,11 +20,11 @@ | |||
20 | 20 | ||
21 | #include <asm/uaccess.h> | 21 | #include <asm/uaccess.h> |
22 | 22 | ||
23 | int vfs_readdir(struct file *file, filldir_t filler, void *buf) | 23 | int iterate_dir(struct file *file, struct dir_context *ctx) |
24 | { | 24 | { |
25 | struct inode *inode = file_inode(file); | 25 | struct inode *inode = file_inode(file); |
26 | int res = -ENOTDIR; | 26 | int res = -ENOTDIR; |
27 | if (!file->f_op || !file->f_op->readdir) | 27 | if (!file->f_op || !file->f_op->iterate) |
28 | goto out; | 28 | goto out; |
29 | 29 | ||
30 | res = security_file_permission(file, MAY_READ); | 30 | res = security_file_permission(file, MAY_READ); |
@@ -37,15 +37,16 @@ int vfs_readdir(struct file *file, filldir_t filler, void *buf) | |||
37 | 37 | ||
38 | res = -ENOENT; | 38 | res = -ENOENT; |
39 | if (!IS_DEADDIR(inode)) { | 39 | if (!IS_DEADDIR(inode)) { |
40 | res = file->f_op->readdir(file, buf, filler); | 40 | ctx->pos = file->f_pos; |
41 | res = file->f_op->iterate(file, ctx); | ||
42 | file->f_pos = ctx->pos; | ||
41 | file_accessed(file); | 43 | file_accessed(file); |
42 | } | 44 | } |
43 | mutex_unlock(&inode->i_mutex); | 45 | mutex_unlock(&inode->i_mutex); |
44 | out: | 46 | out: |
45 | return res; | 47 | return res; |
46 | } | 48 | } |
47 | 49 | EXPORT_SYMBOL(iterate_dir); | |
48 | EXPORT_SYMBOL(vfs_readdir); | ||
49 | 50 | ||
50 | /* | 51 | /* |
51 | * Traditional linux readdir() handling.. | 52 | * Traditional linux readdir() handling.. |
@@ -66,6 +67,7 @@ struct old_linux_dirent { | |||
66 | }; | 67 | }; |
67 | 68 | ||
68 | struct readdir_callback { | 69 | struct readdir_callback { |
70 | struct dir_context ctx; | ||
69 | struct old_linux_dirent __user * dirent; | 71 | struct old_linux_dirent __user * dirent; |
70 | int result; | 72 | int result; |
71 | }; | 73 | }; |
@@ -73,7 +75,7 @@ struct readdir_callback { | |||
73 | static int fillonedir(void * __buf, const char * name, int namlen, loff_t offset, | 75 | static int fillonedir(void * __buf, const char * name, int namlen, loff_t offset, |
74 | u64 ino, unsigned int d_type) | 76 | u64 ino, unsigned int d_type) |
75 | { | 77 | { |
76 | struct readdir_callback * buf = (struct readdir_callback *) __buf; | 78 | struct readdir_callback *buf = (struct readdir_callback *) __buf; |
77 | struct old_linux_dirent __user * dirent; | 79 | struct old_linux_dirent __user * dirent; |
78 | unsigned long d_ino; | 80 | unsigned long d_ino; |
79 | 81 | ||
@@ -107,15 +109,15 @@ SYSCALL_DEFINE3(old_readdir, unsigned int, fd, | |||
107 | { | 109 | { |
108 | int error; | 110 | int error; |
109 | struct fd f = fdget(fd); | 111 | struct fd f = fdget(fd); |
110 | struct readdir_callback buf; | 112 | struct readdir_callback buf = { |
113 | .ctx.actor = fillonedir, | ||
114 | .dirent = dirent | ||
115 | }; | ||
111 | 116 | ||
112 | if (!f.file) | 117 | if (!f.file) |
113 | return -EBADF; | 118 | return -EBADF; |
114 | 119 | ||
115 | buf.result = 0; | 120 | error = iterate_dir(f.file, &buf.ctx); |
116 | buf.dirent = dirent; | ||
117 | |||
118 | error = vfs_readdir(f.file, fillonedir, &buf); | ||
119 | if (buf.result) | 121 | if (buf.result) |
120 | error = buf.result; | 122 | error = buf.result; |
121 | 123 | ||
@@ -137,6 +139,7 @@ struct linux_dirent { | |||
137 | }; | 139 | }; |
138 | 140 | ||
139 | struct getdents_callback { | 141 | struct getdents_callback { |
142 | struct dir_context ctx; | ||
140 | struct linux_dirent __user * current_dir; | 143 | struct linux_dirent __user * current_dir; |
141 | struct linux_dirent __user * previous; | 144 | struct linux_dirent __user * previous; |
142 | int count; | 145 | int count; |
@@ -191,7 +194,11 @@ SYSCALL_DEFINE3(getdents, unsigned int, fd, | |||
191 | { | 194 | { |
192 | struct fd f; | 195 | struct fd f; |
193 | struct linux_dirent __user * lastdirent; | 196 | struct linux_dirent __user * lastdirent; |
194 | struct getdents_callback buf; | 197 | struct getdents_callback buf = { |
198 | .ctx.actor = filldir, | ||
199 | .count = count, | ||
200 | .current_dir = dirent | ||
201 | }; | ||
195 | int error; | 202 | int error; |
196 | 203 | ||
197 | if (!access_ok(VERIFY_WRITE, dirent, count)) | 204 | if (!access_ok(VERIFY_WRITE, dirent, count)) |
@@ -201,17 +208,12 @@ SYSCALL_DEFINE3(getdents, unsigned int, fd, | |||
201 | if (!f.file) | 208 | if (!f.file) |
202 | return -EBADF; | 209 | return -EBADF; |
203 | 210 | ||
204 | buf.current_dir = dirent; | 211 | error = iterate_dir(f.file, &buf.ctx); |
205 | buf.previous = NULL; | ||
206 | buf.count = count; | ||
207 | buf.error = 0; | ||
208 | |||
209 | error = vfs_readdir(f.file, filldir, &buf); | ||
210 | if (error >= 0) | 212 | if (error >= 0) |
211 | error = buf.error; | 213 | error = buf.error; |
212 | lastdirent = buf.previous; | 214 | lastdirent = buf.previous; |
213 | if (lastdirent) { | 215 | if (lastdirent) { |
214 | if (put_user(f.file->f_pos, &lastdirent->d_off)) | 216 | if (put_user(buf.ctx.pos, &lastdirent->d_off)) |
215 | error = -EFAULT; | 217 | error = -EFAULT; |
216 | else | 218 | else |
217 | error = count - buf.count; | 219 | error = count - buf.count; |
@@ -221,6 +223,7 @@ SYSCALL_DEFINE3(getdents, unsigned int, fd, | |||
221 | } | 223 | } |
222 | 224 | ||
223 | struct getdents_callback64 { | 225 | struct getdents_callback64 { |
226 | struct dir_context ctx; | ||
224 | struct linux_dirent64 __user * current_dir; | 227 | struct linux_dirent64 __user * current_dir; |
225 | struct linux_dirent64 __user * previous; | 228 | struct linux_dirent64 __user * previous; |
226 | int count; | 229 | int count; |
@@ -271,7 +274,11 @@ SYSCALL_DEFINE3(getdents64, unsigned int, fd, | |||
271 | { | 274 | { |
272 | struct fd f; | 275 | struct fd f; |
273 | struct linux_dirent64 __user * lastdirent; | 276 | struct linux_dirent64 __user * lastdirent; |
274 | struct getdents_callback64 buf; | 277 | struct getdents_callback64 buf = { |
278 | .ctx.actor = filldir64, | ||
279 | .count = count, | ||
280 | .current_dir = dirent | ||
281 | }; | ||
275 | int error; | 282 | int error; |
276 | 283 | ||
277 | if (!access_ok(VERIFY_WRITE, dirent, count)) | 284 | if (!access_ok(VERIFY_WRITE, dirent, count)) |
@@ -281,17 +288,12 @@ SYSCALL_DEFINE3(getdents64, unsigned int, fd, | |||
281 | if (!f.file) | 288 | if (!f.file) |
282 | return -EBADF; | 289 | return -EBADF; |
283 | 290 | ||
284 | buf.current_dir = dirent; | 291 | error = iterate_dir(f.file, &buf.ctx); |
285 | buf.previous = NULL; | ||
286 | buf.count = count; | ||
287 | buf.error = 0; | ||
288 | |||
289 | error = vfs_readdir(f.file, filldir64, &buf); | ||
290 | if (error >= 0) | 292 | if (error >= 0) |
291 | error = buf.error; | 293 | error = buf.error; |
292 | lastdirent = buf.previous; | 294 | lastdirent = buf.previous; |
293 | if (lastdirent) { | 295 | if (lastdirent) { |
294 | typeof(lastdirent->d_off) d_off = f.file->f_pos; | 296 | typeof(lastdirent->d_off) d_off = buf.ctx.pos; |
295 | if (__put_user(d_off, &lastdirent->d_off)) | 297 | if (__put_user(d_off, &lastdirent->d_off)) |
296 | error = -EFAULT; | 298 | error = -EFAULT; |
297 | else | 299 | else |
diff --git a/fs/reiserfs/dir.c b/fs/reiserfs/dir.c index 6c2d136561cb..03e4ca5624d6 100644 --- a/fs/reiserfs/dir.c +++ b/fs/reiserfs/dir.c | |||
@@ -13,14 +13,14 @@ | |||
13 | 13 | ||
14 | extern const struct reiserfs_key MIN_KEY; | 14 | extern const struct reiserfs_key MIN_KEY; |
15 | 15 | ||
16 | static int reiserfs_readdir(struct file *, void *, filldir_t); | 16 | static int reiserfs_readdir(struct file *, struct dir_context *); |
17 | static int reiserfs_dir_fsync(struct file *filp, loff_t start, loff_t end, | 17 | static int reiserfs_dir_fsync(struct file *filp, loff_t start, loff_t end, |
18 | int datasync); | 18 | int datasync); |
19 | 19 | ||
20 | const struct file_operations reiserfs_dir_operations = { | 20 | const struct file_operations reiserfs_dir_operations = { |
21 | .llseek = generic_file_llseek, | 21 | .llseek = generic_file_llseek, |
22 | .read = generic_read_dir, | 22 | .read = generic_read_dir, |
23 | .readdir = reiserfs_readdir, | 23 | .iterate = reiserfs_readdir, |
24 | .fsync = reiserfs_dir_fsync, | 24 | .fsync = reiserfs_dir_fsync, |
25 | .unlocked_ioctl = reiserfs_ioctl, | 25 | .unlocked_ioctl = reiserfs_ioctl, |
26 | #ifdef CONFIG_COMPAT | 26 | #ifdef CONFIG_COMPAT |
@@ -50,18 +50,15 @@ static int reiserfs_dir_fsync(struct file *filp, loff_t start, loff_t end, | |||
50 | 50 | ||
51 | #define store_ih(where,what) copy_item_head (where, what) | 51 | #define store_ih(where,what) copy_item_head (where, what) |
52 | 52 | ||
53 | static inline bool is_privroot_deh(struct dentry *dir, | 53 | static inline bool is_privroot_deh(struct inode *dir, struct reiserfs_de_head *deh) |
54 | struct reiserfs_de_head *deh) | ||
55 | { | 54 | { |
56 | struct dentry *privroot = REISERFS_SB(dir->d_sb)->priv_root; | 55 | struct dentry *privroot = REISERFS_SB(dir->i_sb)->priv_root; |
57 | return (dir == dir->d_parent && privroot->d_inode && | 56 | return (privroot->d_inode && |
58 | deh->deh_objectid == INODE_PKEY(privroot->d_inode)->k_objectid); | 57 | deh->deh_objectid == INODE_PKEY(privroot->d_inode)->k_objectid); |
59 | } | 58 | } |
60 | 59 | ||
61 | int reiserfs_readdir_dentry(struct dentry *dentry, void *dirent, | 60 | int reiserfs_readdir_inode(struct inode *inode, struct dir_context *ctx) |
62 | filldir_t filldir, loff_t *pos) | ||
63 | { | 61 | { |
64 | struct inode *inode = dentry->d_inode; | ||
65 | struct cpu_key pos_key; /* key of current position in the directory (key of directory entry) */ | 62 | struct cpu_key pos_key; /* key of current position in the directory (key of directory entry) */ |
66 | INITIALIZE_PATH(path_to_entry); | 63 | INITIALIZE_PATH(path_to_entry); |
67 | struct buffer_head *bh; | 64 | struct buffer_head *bh; |
@@ -81,7 +78,7 @@ int reiserfs_readdir_dentry(struct dentry *dentry, void *dirent, | |||
81 | 78 | ||
82 | /* form key for search the next directory entry using f_pos field of | 79 | /* form key for search the next directory entry using f_pos field of |
83 | file structure */ | 80 | file structure */ |
84 | make_cpu_key(&pos_key, inode, *pos ?: DOT_OFFSET, TYPE_DIRENTRY, 3); | 81 | make_cpu_key(&pos_key, inode, ctx->pos ?: DOT_OFFSET, TYPE_DIRENTRY, 3); |
85 | next_pos = cpu_key_k_offset(&pos_key); | 82 | next_pos = cpu_key_k_offset(&pos_key); |
86 | 83 | ||
87 | path_to_entry.reada = PATH_READA; | 84 | path_to_entry.reada = PATH_READA; |
@@ -126,7 +123,6 @@ int reiserfs_readdir_dentry(struct dentry *dentry, void *dirent, | |||
126 | entry_num++, deh++) { | 123 | entry_num++, deh++) { |
127 | int d_reclen; | 124 | int d_reclen; |
128 | char *d_name; | 125 | char *d_name; |
129 | off_t d_off; | ||
130 | ino_t d_ino; | 126 | ino_t d_ino; |
131 | 127 | ||
132 | if (!de_visible(deh)) | 128 | if (!de_visible(deh)) |
@@ -155,11 +151,10 @@ int reiserfs_readdir_dentry(struct dentry *dentry, void *dirent, | |||
155 | } | 151 | } |
156 | 152 | ||
157 | /* Ignore the .reiserfs_priv entry */ | 153 | /* Ignore the .reiserfs_priv entry */ |
158 | if (is_privroot_deh(dentry, deh)) | 154 | if (is_privroot_deh(inode, deh)) |
159 | continue; | 155 | continue; |
160 | 156 | ||
161 | d_off = deh_offset(deh); | 157 | ctx->pos = deh_offset(deh); |
162 | *pos = d_off; | ||
163 | d_ino = deh_objectid(deh); | 158 | d_ino = deh_objectid(deh); |
164 | if (d_reclen <= 32) { | 159 | if (d_reclen <= 32) { |
165 | local_buf = small_buf; | 160 | local_buf = small_buf; |
@@ -187,9 +182,9 @@ int reiserfs_readdir_dentry(struct dentry *dentry, void *dirent, | |||
187 | * the write lock here for other waiters | 182 | * the write lock here for other waiters |
188 | */ | 183 | */ |
189 | reiserfs_write_unlock(inode->i_sb); | 184 | reiserfs_write_unlock(inode->i_sb); |
190 | if (filldir | 185 | if (!dir_emit |
191 | (dirent, local_buf, d_reclen, d_off, d_ino, | 186 | (ctx, local_buf, d_reclen, d_ino, |
192 | DT_UNKNOWN) < 0) { | 187 | DT_UNKNOWN)) { |
193 | reiserfs_write_lock(inode->i_sb); | 188 | reiserfs_write_lock(inode->i_sb); |
194 | if (local_buf != small_buf) { | 189 | if (local_buf != small_buf) { |
195 | kfree(local_buf); | 190 | kfree(local_buf); |
@@ -237,7 +232,7 @@ int reiserfs_readdir_dentry(struct dentry *dentry, void *dirent, | |||
237 | } /* while */ | 232 | } /* while */ |
238 | 233 | ||
239 | end: | 234 | end: |
240 | *pos = next_pos; | 235 | ctx->pos = next_pos; |
241 | pathrelse(&path_to_entry); | 236 | pathrelse(&path_to_entry); |
242 | reiserfs_check_path(&path_to_entry); | 237 | reiserfs_check_path(&path_to_entry); |
243 | out: | 238 | out: |
@@ -245,10 +240,9 @@ out: | |||
245 | return ret; | 240 | return ret; |
246 | } | 241 | } |
247 | 242 | ||
248 | static int reiserfs_readdir(struct file *file, void *dirent, filldir_t filldir) | 243 | static int reiserfs_readdir(struct file *file, struct dir_context *ctx) |
249 | { | 244 | { |
250 | struct dentry *dentry = file->f_path.dentry; | 245 | return reiserfs_readdir_inode(file_inode(file), ctx); |
251 | return reiserfs_readdir_dentry(dentry, dirent, filldir, &file->f_pos); | ||
252 | } | 246 | } |
253 | 247 | ||
254 | /* compose directory item containing "." and ".." entries (entries are | 248 | /* compose directory item containing "." and ".." entries (entries are |
diff --git a/fs/reiserfs/reiserfs.h b/fs/reiserfs/reiserfs.h index 157e474ab303..3df5ce6c724d 100644 --- a/fs/reiserfs/reiserfs.h +++ b/fs/reiserfs/reiserfs.h | |||
@@ -2709,7 +2709,7 @@ extern const struct inode_operations reiserfs_dir_inode_operations; | |||
2709 | extern const struct inode_operations reiserfs_symlink_inode_operations; | 2709 | extern const struct inode_operations reiserfs_symlink_inode_operations; |
2710 | extern const struct inode_operations reiserfs_special_inode_operations; | 2710 | extern const struct inode_operations reiserfs_special_inode_operations; |
2711 | extern const struct file_operations reiserfs_dir_operations; | 2711 | extern const struct file_operations reiserfs_dir_operations; |
2712 | int reiserfs_readdir_dentry(struct dentry *, void *, filldir_t, loff_t *); | 2712 | int reiserfs_readdir_inode(struct inode *, struct dir_context *); |
2713 | 2713 | ||
2714 | /* tail_conversion.c */ | 2714 | /* tail_conversion.c */ |
2715 | int direct2indirect(struct reiserfs_transaction_handle *, struct inode *, | 2715 | int direct2indirect(struct reiserfs_transaction_handle *, struct inode *, |
diff --git a/fs/reiserfs/xattr.c b/fs/reiserfs/xattr.c index 821bcf70e467..c69cdd749f09 100644 --- a/fs/reiserfs/xattr.c +++ b/fs/reiserfs/xattr.c | |||
@@ -171,6 +171,7 @@ static struct dentry *open_xa_dir(const struct inode *inode, int flags) | |||
171 | * modifying extended attributes. This includes operations such as permissions | 171 | * modifying extended attributes. This includes operations such as permissions |
172 | * or ownership changes, object deletions, etc. */ | 172 | * or ownership changes, object deletions, etc. */ |
173 | struct reiserfs_dentry_buf { | 173 | struct reiserfs_dentry_buf { |
174 | struct dir_context ctx; | ||
174 | struct dentry *xadir; | 175 | struct dentry *xadir; |
175 | int count; | 176 | int count; |
176 | struct dentry *dentries[8]; | 177 | struct dentry *dentries[8]; |
@@ -223,9 +224,8 @@ static int reiserfs_for_each_xattr(struct inode *inode, | |||
223 | { | 224 | { |
224 | struct dentry *dir; | 225 | struct dentry *dir; |
225 | int i, err = 0; | 226 | int i, err = 0; |
226 | loff_t pos = 0; | ||
227 | struct reiserfs_dentry_buf buf = { | 227 | struct reiserfs_dentry_buf buf = { |
228 | .count = 0, | 228 | .ctx.actor = fill_with_dentries, |
229 | }; | 229 | }; |
230 | 230 | ||
231 | /* Skip out, an xattr has no xattrs associated with it */ | 231 | /* Skip out, an xattr has no xattrs associated with it */ |
@@ -249,29 +249,27 @@ static int reiserfs_for_each_xattr(struct inode *inode, | |||
249 | reiserfs_write_lock(inode->i_sb); | 249 | reiserfs_write_lock(inode->i_sb); |
250 | 250 | ||
251 | buf.xadir = dir; | 251 | buf.xadir = dir; |
252 | err = reiserfs_readdir_dentry(dir, &buf, fill_with_dentries, &pos); | 252 | while (1) { |
253 | while ((err == 0 || err == -ENOSPC) && buf.count) { | 253 | err = reiserfs_readdir_inode(dir->d_inode, &buf.ctx); |
254 | err = 0; | 254 | if (err) |
255 | 255 | break; | |
256 | for (i = 0; i < buf.count && buf.dentries[i]; i++) { | 256 | if (!buf.count) |
257 | int lerr = 0; | 257 | break; |
258 | for (i = 0; !err && i < buf.count && buf.dentries[i]; i++) { | ||
258 | struct dentry *dentry = buf.dentries[i]; | 259 | struct dentry *dentry = buf.dentries[i]; |
259 | 260 | ||
260 | if (err == 0 && !S_ISDIR(dentry->d_inode->i_mode)) | 261 | if (!S_ISDIR(dentry->d_inode->i_mode)) |
261 | lerr = action(dentry, data); | 262 | err = action(dentry, data); |
262 | 263 | ||
263 | dput(dentry); | 264 | dput(dentry); |
264 | buf.dentries[i] = NULL; | 265 | buf.dentries[i] = NULL; |
265 | err = lerr ?: err; | ||
266 | } | 266 | } |
267 | if (err) | ||
268 | break; | ||
267 | buf.count = 0; | 269 | buf.count = 0; |
268 | if (!err) | ||
269 | err = reiserfs_readdir_dentry(dir, &buf, | ||
270 | fill_with_dentries, &pos); | ||
271 | } | 270 | } |
272 | mutex_unlock(&dir->d_inode->i_mutex); | 271 | mutex_unlock(&dir->d_inode->i_mutex); |
273 | 272 | ||
274 | /* Clean up after a failed readdir */ | ||
275 | cleanup_dentry_buf(&buf); | 273 | cleanup_dentry_buf(&buf); |
276 | 274 | ||
277 | if (!err) { | 275 | if (!err) { |
@@ -800,6 +798,7 @@ int reiserfs_removexattr(struct dentry *dentry, const char *name) | |||
800 | } | 798 | } |
801 | 799 | ||
802 | struct listxattr_buf { | 800 | struct listxattr_buf { |
801 | struct dir_context ctx; | ||
803 | size_t size; | 802 | size_t size; |
804 | size_t pos; | 803 | size_t pos; |
805 | char *buf; | 804 | char *buf; |
@@ -845,8 +844,8 @@ ssize_t reiserfs_listxattr(struct dentry * dentry, char *buffer, size_t size) | |||
845 | { | 844 | { |
846 | struct dentry *dir; | 845 | struct dentry *dir; |
847 | int err = 0; | 846 | int err = 0; |
848 | loff_t pos = 0; | ||
849 | struct listxattr_buf buf = { | 847 | struct listxattr_buf buf = { |
848 | .ctx.actor = listxattr_filler, | ||
850 | .dentry = dentry, | 849 | .dentry = dentry, |
851 | .buf = buffer, | 850 | .buf = buffer, |
852 | .size = buffer ? size : 0, | 851 | .size = buffer ? size : 0, |
@@ -868,7 +867,7 @@ ssize_t reiserfs_listxattr(struct dentry * dentry, char *buffer, size_t size) | |||
868 | } | 867 | } |
869 | 868 | ||
870 | mutex_lock_nested(&dir->d_inode->i_mutex, I_MUTEX_XATTR); | 869 | mutex_lock_nested(&dir->d_inode->i_mutex, I_MUTEX_XATTR); |
871 | err = reiserfs_readdir_dentry(dir, &buf, listxattr_filler, &pos); | 870 | err = reiserfs_readdir_inode(dir->d_inode, &buf.ctx); |
872 | mutex_unlock(&dir->d_inode->i_mutex); | 871 | mutex_unlock(&dir->d_inode->i_mutex); |
873 | 872 | ||
874 | if (!err) | 873 | if (!err) |
diff --git a/fs/romfs/super.c b/fs/romfs/super.c index 15cbc41ee365..ff1d3d42e72a 100644 --- a/fs/romfs/super.c +++ b/fs/romfs/super.c | |||
@@ -145,19 +145,18 @@ static const struct address_space_operations romfs_aops = { | |||
145 | /* | 145 | /* |
146 | * read the entries from a directory | 146 | * read the entries from a directory |
147 | */ | 147 | */ |
148 | static int romfs_readdir(struct file *filp, void *dirent, filldir_t filldir) | 148 | static int romfs_readdir(struct file *file, struct dir_context *ctx) |
149 | { | 149 | { |
150 | struct inode *i = file_inode(filp); | 150 | struct inode *i = file_inode(file); |
151 | struct romfs_inode ri; | 151 | struct romfs_inode ri; |
152 | unsigned long offset, maxoff; | 152 | unsigned long offset, maxoff; |
153 | int j, ino, nextfh; | 153 | int j, ino, nextfh; |
154 | int stored = 0; | ||
155 | char fsname[ROMFS_MAXFN]; /* XXX dynamic? */ | 154 | char fsname[ROMFS_MAXFN]; /* XXX dynamic? */ |
156 | int ret; | 155 | int ret; |
157 | 156 | ||
158 | maxoff = romfs_maxsize(i->i_sb); | 157 | maxoff = romfs_maxsize(i->i_sb); |
159 | 158 | ||
160 | offset = filp->f_pos; | 159 | offset = ctx->pos; |
161 | if (!offset) { | 160 | if (!offset) { |
162 | offset = i->i_ino & ROMFH_MASK; | 161 | offset = i->i_ino & ROMFH_MASK; |
163 | ret = romfs_dev_read(i->i_sb, offset, &ri, ROMFH_SIZE); | 162 | ret = romfs_dev_read(i->i_sb, offset, &ri, ROMFH_SIZE); |
@@ -170,10 +169,10 @@ static int romfs_readdir(struct file *filp, void *dirent, filldir_t filldir) | |||
170 | for (;;) { | 169 | for (;;) { |
171 | if (!offset || offset >= maxoff) { | 170 | if (!offset || offset >= maxoff) { |
172 | offset = maxoff; | 171 | offset = maxoff; |
173 | filp->f_pos = offset; | 172 | ctx->pos = offset; |
174 | goto out; | 173 | goto out; |
175 | } | 174 | } |
176 | filp->f_pos = offset; | 175 | ctx->pos = offset; |
177 | 176 | ||
178 | /* Fetch inode info */ | 177 | /* Fetch inode info */ |
179 | ret = romfs_dev_read(i->i_sb, offset, &ri, ROMFH_SIZE); | 178 | ret = romfs_dev_read(i->i_sb, offset, &ri, ROMFH_SIZE); |
@@ -194,16 +193,14 @@ static int romfs_readdir(struct file *filp, void *dirent, filldir_t filldir) | |||
194 | nextfh = be32_to_cpu(ri.next); | 193 | nextfh = be32_to_cpu(ri.next); |
195 | if ((nextfh & ROMFH_TYPE) == ROMFH_HRD) | 194 | if ((nextfh & ROMFH_TYPE) == ROMFH_HRD) |
196 | ino = be32_to_cpu(ri.spec); | 195 | ino = be32_to_cpu(ri.spec); |
197 | if (filldir(dirent, fsname, j, offset, ino, | 196 | if (!dir_emit(ctx, fsname, j, ino, |
198 | romfs_dtype_table[nextfh & ROMFH_TYPE]) < 0) | 197 | romfs_dtype_table[nextfh & ROMFH_TYPE])) |
199 | goto out; | 198 | goto out; |
200 | 199 | ||
201 | stored++; | ||
202 | offset = nextfh & ROMFH_MASK; | 200 | offset = nextfh & ROMFH_MASK; |
203 | } | 201 | } |
204 | |||
205 | out: | 202 | out: |
206 | return stored; | 203 | return 0; |
207 | } | 204 | } |
208 | 205 | ||
209 | /* | 206 | /* |
@@ -281,7 +278,7 @@ error: | |||
281 | 278 | ||
282 | static const struct file_operations romfs_dir_operations = { | 279 | static const struct file_operations romfs_dir_operations = { |
283 | .read = generic_read_dir, | 280 | .read = generic_read_dir, |
284 | .readdir = romfs_readdir, | 281 | .iterate = romfs_readdir, |
285 | .llseek = default_llseek, | 282 | .llseek = default_llseek, |
286 | }; | 283 | }; |
287 | 284 | ||
diff --git a/fs/squashfs/dir.c b/fs/squashfs/dir.c index 57dc70ebbb19..f7f527bf8c10 100644 --- a/fs/squashfs/dir.c +++ b/fs/squashfs/dir.c | |||
@@ -100,7 +100,7 @@ static int get_dir_index_using_offset(struct super_block *sb, | |||
100 | } | 100 | } |
101 | 101 | ||
102 | 102 | ||
103 | static int squashfs_readdir(struct file *file, void *dirent, filldir_t filldir) | 103 | static int squashfs_readdir(struct file *file, struct dir_context *ctx) |
104 | { | 104 | { |
105 | struct inode *inode = file_inode(file); | 105 | struct inode *inode = file_inode(file); |
106 | struct squashfs_sb_info *msblk = inode->i_sb->s_fs_info; | 106 | struct squashfs_sb_info *msblk = inode->i_sb->s_fs_info; |
@@ -127,11 +127,11 @@ static int squashfs_readdir(struct file *file, void *dirent, filldir_t filldir) | |||
127 | * It also means that the external f_pos is offset by 3 from the | 127 | * It also means that the external f_pos is offset by 3 from the |
128 | * on-disk directory f_pos. | 128 | * on-disk directory f_pos. |
129 | */ | 129 | */ |
130 | while (file->f_pos < 3) { | 130 | while (ctx->pos < 3) { |
131 | char *name; | 131 | char *name; |
132 | int i_ino; | 132 | int i_ino; |
133 | 133 | ||
134 | if (file->f_pos == 0) { | 134 | if (ctx->pos == 0) { |
135 | name = "."; | 135 | name = "."; |
136 | size = 1; | 136 | size = 1; |
137 | i_ino = inode->i_ino; | 137 | i_ino = inode->i_ino; |
@@ -141,24 +141,18 @@ static int squashfs_readdir(struct file *file, void *dirent, filldir_t filldir) | |||
141 | i_ino = squashfs_i(inode)->parent; | 141 | i_ino = squashfs_i(inode)->parent; |
142 | } | 142 | } |
143 | 143 | ||
144 | TRACE("Calling filldir(%p, %s, %d, %lld, %d, %d)\n", | 144 | if (!dir_emit(ctx, name, size, i_ino, |
145 | dirent, name, size, file->f_pos, i_ino, | 145 | squashfs_filetype_table[1])) |
146 | squashfs_filetype_table[1]); | ||
147 | |||
148 | if (filldir(dirent, name, size, file->f_pos, i_ino, | ||
149 | squashfs_filetype_table[1]) < 0) { | ||
150 | TRACE("Filldir returned less than 0\n"); | ||
151 | goto finish; | 146 | goto finish; |
152 | } | ||
153 | 147 | ||
154 | file->f_pos += size; | 148 | ctx->pos += size; |
155 | } | 149 | } |
156 | 150 | ||
157 | length = get_dir_index_using_offset(inode->i_sb, &block, &offset, | 151 | length = get_dir_index_using_offset(inode->i_sb, &block, &offset, |
158 | squashfs_i(inode)->dir_idx_start, | 152 | squashfs_i(inode)->dir_idx_start, |
159 | squashfs_i(inode)->dir_idx_offset, | 153 | squashfs_i(inode)->dir_idx_offset, |
160 | squashfs_i(inode)->dir_idx_cnt, | 154 | squashfs_i(inode)->dir_idx_cnt, |
161 | file->f_pos); | 155 | ctx->pos); |
162 | 156 | ||
163 | while (length < i_size_read(inode)) { | 157 | while (length < i_size_read(inode)) { |
164 | /* | 158 | /* |
@@ -198,7 +192,7 @@ static int squashfs_readdir(struct file *file, void *dirent, filldir_t filldir) | |||
198 | 192 | ||
199 | length += sizeof(*dire) + size; | 193 | length += sizeof(*dire) + size; |
200 | 194 | ||
201 | if (file->f_pos >= length) | 195 | if (ctx->pos >= length) |
202 | continue; | 196 | continue; |
203 | 197 | ||
204 | dire->name[size] = '\0'; | 198 | dire->name[size] = '\0'; |
@@ -206,22 +200,12 @@ static int squashfs_readdir(struct file *file, void *dirent, filldir_t filldir) | |||
206 | ((short) le16_to_cpu(dire->inode_number)); | 200 | ((short) le16_to_cpu(dire->inode_number)); |
207 | type = le16_to_cpu(dire->type); | 201 | type = le16_to_cpu(dire->type); |
208 | 202 | ||
209 | TRACE("Calling filldir(%p, %s, %d, %lld, %x:%x, %d, %d)" | 203 | if (!dir_emit(ctx, dire->name, size, |
210 | "\n", dirent, dire->name, size, | ||
211 | file->f_pos, | ||
212 | le32_to_cpu(dirh.start_block), | ||
213 | le16_to_cpu(dire->offset), | ||
214 | inode_number, | ||
215 | squashfs_filetype_table[type]); | ||
216 | |||
217 | if (filldir(dirent, dire->name, size, file->f_pos, | ||
218 | inode_number, | 204 | inode_number, |
219 | squashfs_filetype_table[type]) < 0) { | 205 | squashfs_filetype_table[type])) |
220 | TRACE("Filldir returned less than 0\n"); | ||
221 | goto finish; | 206 | goto finish; |
222 | } | ||
223 | 207 | ||
224 | file->f_pos = length; | 208 | ctx->pos = length; |
225 | } | 209 | } |
226 | } | 210 | } |
227 | 211 | ||
@@ -238,6 +222,6 @@ failed_read: | |||
238 | 222 | ||
239 | const struct file_operations squashfs_dir_ops = { | 223 | const struct file_operations squashfs_dir_ops = { |
240 | .read = generic_read_dir, | 224 | .read = generic_read_dir, |
241 | .readdir = squashfs_readdir, | 225 | .iterate = squashfs_readdir, |
242 | .llseek = default_llseek, | 226 | .llseek = default_llseek, |
243 | }; | 227 | }; |
diff --git a/fs/sysfs/dir.c b/fs/sysfs/dir.c index e8e0e71b29d5..4cfd742d260d 100644 --- a/fs/sysfs/dir.c +++ b/fs/sysfs/dir.c | |||
@@ -998,68 +998,38 @@ static struct sysfs_dirent *sysfs_dir_next_pos(const void *ns, | |||
998 | return pos; | 998 | return pos; |
999 | } | 999 | } |
1000 | 1000 | ||
1001 | static int sysfs_readdir(struct file * filp, void * dirent, filldir_t filldir) | 1001 | static int sysfs_readdir(struct file *file, struct dir_context *ctx) |
1002 | { | 1002 | { |
1003 | struct dentry *dentry = filp->f_path.dentry; | 1003 | struct dentry *dentry = file->f_path.dentry; |
1004 | struct sysfs_dirent * parent_sd = dentry->d_fsdata; | 1004 | struct sysfs_dirent * parent_sd = dentry->d_fsdata; |
1005 | struct sysfs_dirent *pos = filp->private_data; | 1005 | struct sysfs_dirent *pos = file->private_data; |
1006 | enum kobj_ns_type type; | 1006 | enum kobj_ns_type type; |
1007 | const void *ns; | 1007 | const void *ns; |
1008 | ino_t ino; | ||
1009 | loff_t off; | ||
1010 | 1008 | ||
1011 | type = sysfs_ns_type(parent_sd); | 1009 | type = sysfs_ns_type(parent_sd); |
1012 | ns = sysfs_info(dentry->d_sb)->ns[type]; | 1010 | ns = sysfs_info(dentry->d_sb)->ns[type]; |
1013 | 1011 | ||
1014 | if (filp->f_pos == 0) { | 1012 | if (!dir_emit_dots(file, ctx)) |
1015 | ino = parent_sd->s_ino; | 1013 | return 0; |
1016 | if (filldir(dirent, ".", 1, filp->f_pos, ino, DT_DIR) == 0) | ||
1017 | filp->f_pos++; | ||
1018 | else | ||
1019 | return 0; | ||
1020 | } | ||
1021 | if (filp->f_pos == 1) { | ||
1022 | if (parent_sd->s_parent) | ||
1023 | ino = parent_sd->s_parent->s_ino; | ||
1024 | else | ||
1025 | ino = parent_sd->s_ino; | ||
1026 | if (filldir(dirent, "..", 2, filp->f_pos, ino, DT_DIR) == 0) | ||
1027 | filp->f_pos++; | ||
1028 | else | ||
1029 | return 0; | ||
1030 | } | ||
1031 | mutex_lock(&sysfs_mutex); | 1014 | mutex_lock(&sysfs_mutex); |
1032 | off = filp->f_pos; | 1015 | for (pos = sysfs_dir_pos(ns, parent_sd, ctx->pos, pos); |
1033 | for (pos = sysfs_dir_pos(ns, parent_sd, filp->f_pos, pos); | ||
1034 | pos; | 1016 | pos; |
1035 | pos = sysfs_dir_next_pos(ns, parent_sd, filp->f_pos, pos)) { | 1017 | pos = sysfs_dir_next_pos(ns, parent_sd, ctx->pos, pos)) { |
1036 | const char * name; | 1018 | const char *name = pos->s_name; |
1037 | unsigned int type; | 1019 | unsigned int type = dt_type(pos); |
1038 | int len, ret; | 1020 | int len = strlen(name); |
1039 | 1021 | ino_t ino = pos->s_ino; | |
1040 | name = pos->s_name; | 1022 | ctx->pos = pos->s_hash; |
1041 | len = strlen(name); | 1023 | file->private_data = sysfs_get(pos); |
1042 | ino = pos->s_ino; | ||
1043 | type = dt_type(pos); | ||
1044 | off = filp->f_pos = pos->s_hash; | ||
1045 | filp->private_data = sysfs_get(pos); | ||
1046 | 1024 | ||
1047 | mutex_unlock(&sysfs_mutex); | 1025 | mutex_unlock(&sysfs_mutex); |
1048 | ret = filldir(dirent, name, len, off, ino, type); | 1026 | if (!dir_emit(ctx, name, len, ino, type)) |
1027 | return 0; | ||
1049 | mutex_lock(&sysfs_mutex); | 1028 | mutex_lock(&sysfs_mutex); |
1050 | if (ret < 0) | ||
1051 | break; | ||
1052 | } | 1029 | } |
1053 | mutex_unlock(&sysfs_mutex); | 1030 | mutex_unlock(&sysfs_mutex); |
1054 | 1031 | file->private_data = NULL; | |
1055 | /* don't reference last entry if its refcount is dropped */ | 1032 | ctx->pos = INT_MAX; |
1056 | if (!pos) { | ||
1057 | filp->private_data = NULL; | ||
1058 | |||
1059 | /* EOF and not changed as 0 or 1 in read/write path */ | ||
1060 | if (off == filp->f_pos && off > 1) | ||
1061 | filp->f_pos = INT_MAX; | ||
1062 | } | ||
1063 | return 0; | 1033 | return 0; |
1064 | } | 1034 | } |
1065 | 1035 | ||
@@ -1077,7 +1047,7 @@ static loff_t sysfs_dir_llseek(struct file *file, loff_t offset, int whence) | |||
1077 | 1047 | ||
1078 | const struct file_operations sysfs_dir_operations = { | 1048 | const struct file_operations sysfs_dir_operations = { |
1079 | .read = generic_read_dir, | 1049 | .read = generic_read_dir, |
1080 | .readdir = sysfs_readdir, | 1050 | .iterate = sysfs_readdir, |
1081 | .release = sysfs_dir_release, | 1051 | .release = sysfs_dir_release, |
1082 | .llseek = sysfs_dir_llseek, | 1052 | .llseek = sysfs_dir_llseek, |
1083 | }; | 1053 | }; |
diff --git a/fs/sysv/dir.c b/fs/sysv/dir.c index 3799e8dac3eb..d42291d08215 100644 --- a/fs/sysv/dir.c +++ b/fs/sysv/dir.c | |||
@@ -18,12 +18,12 @@ | |||
18 | #include <linux/swap.h> | 18 | #include <linux/swap.h> |
19 | #include "sysv.h" | 19 | #include "sysv.h" |
20 | 20 | ||
21 | static int sysv_readdir(struct file *, void *, filldir_t); | 21 | static int sysv_readdir(struct file *, struct dir_context *); |
22 | 22 | ||
23 | const struct file_operations sysv_dir_operations = { | 23 | const struct file_operations sysv_dir_operations = { |
24 | .llseek = generic_file_llseek, | 24 | .llseek = generic_file_llseek, |
25 | .read = generic_read_dir, | 25 | .read = generic_read_dir, |
26 | .readdir = sysv_readdir, | 26 | .iterate = sysv_readdir, |
27 | .fsync = generic_file_fsync, | 27 | .fsync = generic_file_fsync, |
28 | }; | 28 | }; |
29 | 29 | ||
@@ -65,18 +65,21 @@ static struct page * dir_get_page(struct inode *dir, unsigned long n) | |||
65 | return page; | 65 | return page; |
66 | } | 66 | } |
67 | 67 | ||
68 | static int sysv_readdir(struct file * filp, void * dirent, filldir_t filldir) | 68 | static int sysv_readdir(struct file *file, struct dir_context *ctx) |
69 | { | 69 | { |
70 | unsigned long pos = filp->f_pos; | 70 | unsigned long pos = ctx->pos; |
71 | struct inode *inode = file_inode(filp); | 71 | struct inode *inode = file_inode(file); |
72 | struct super_block *sb = inode->i_sb; | 72 | struct super_block *sb = inode->i_sb; |
73 | unsigned offset = pos & ~PAGE_CACHE_MASK; | ||
74 | unsigned long n = pos >> PAGE_CACHE_SHIFT; | ||
75 | unsigned long npages = dir_pages(inode); | 73 | unsigned long npages = dir_pages(inode); |
74 | unsigned offset; | ||
75 | unsigned long n; | ||
76 | 76 | ||
77 | pos = (pos + SYSV_DIRSIZE-1) & ~(SYSV_DIRSIZE-1); | 77 | ctx->pos = pos = (pos + SYSV_DIRSIZE-1) & ~(SYSV_DIRSIZE-1); |
78 | if (pos >= inode->i_size) | 78 | if (pos >= inode->i_size) |
79 | goto done; | 79 | return 0; |
80 | |||
81 | offset = pos & ~PAGE_CACHE_MASK; | ||
82 | n = pos >> PAGE_CACHE_SHIFT; | ||
80 | 83 | ||
81 | for ( ; n < npages; n++, offset = 0) { | 84 | for ( ; n < npages; n++, offset = 0) { |
82 | char *kaddr, *limit; | 85 | char *kaddr, *limit; |
@@ -88,29 +91,21 @@ static int sysv_readdir(struct file * filp, void * dirent, filldir_t filldir) | |||
88 | kaddr = (char *)page_address(page); | 91 | kaddr = (char *)page_address(page); |
89 | de = (struct sysv_dir_entry *)(kaddr+offset); | 92 | de = (struct sysv_dir_entry *)(kaddr+offset); |
90 | limit = kaddr + PAGE_CACHE_SIZE - SYSV_DIRSIZE; | 93 | limit = kaddr + PAGE_CACHE_SIZE - SYSV_DIRSIZE; |
91 | for ( ;(char*)de <= limit; de++) { | 94 | for ( ;(char*)de <= limit; de++, ctx->pos += sizeof(*de)) { |
92 | char *name = de->name; | 95 | char *name = de->name; |
93 | int over; | ||
94 | 96 | ||
95 | if (!de->inode) | 97 | if (!de->inode) |
96 | continue; | 98 | continue; |
97 | 99 | ||
98 | offset = (char *)de - kaddr; | 100 | if (!dir_emit(ctx, name, strnlen(name,SYSV_NAMELEN), |
99 | |||
100 | over = filldir(dirent, name, strnlen(name,SYSV_NAMELEN), | ||
101 | ((loff_t)n<<PAGE_CACHE_SHIFT) | offset, | ||
102 | fs16_to_cpu(SYSV_SB(sb), de->inode), | 101 | fs16_to_cpu(SYSV_SB(sb), de->inode), |
103 | DT_UNKNOWN); | 102 | DT_UNKNOWN)) { |
104 | if (over) { | ||
105 | dir_put_page(page); | 103 | dir_put_page(page); |
106 | goto done; | 104 | return 0; |
107 | } | 105 | } |
108 | } | 106 | } |
109 | dir_put_page(page); | 107 | dir_put_page(page); |
110 | } | 108 | } |
111 | |||
112 | done: | ||
113 | filp->f_pos = ((loff_t)n << PAGE_CACHE_SHIFT) | offset; | ||
114 | return 0; | 109 | return 0; |
115 | } | 110 | } |
116 | 111 | ||
diff --git a/fs/ubifs/dir.c b/fs/ubifs/dir.c index 605af512aec2..6b4947f75af7 100644 --- a/fs/ubifs/dir.c +++ b/fs/ubifs/dir.c | |||
@@ -346,19 +346,18 @@ static unsigned int vfs_dent_type(uint8_t type) | |||
346 | * This means that UBIFS cannot support NFS which requires full | 346 | * This means that UBIFS cannot support NFS which requires full |
347 | * 'seekdir()'/'telldir()' support. | 347 | * 'seekdir()'/'telldir()' support. |
348 | */ | 348 | */ |
349 | static int ubifs_readdir(struct file *file, void *dirent, filldir_t filldir) | 349 | static int ubifs_readdir(struct file *file, struct dir_context *ctx) |
350 | { | 350 | { |
351 | int err, over = 0; | 351 | int err; |
352 | loff_t pos = file->f_pos; | ||
353 | struct qstr nm; | 352 | struct qstr nm; |
354 | union ubifs_key key; | 353 | union ubifs_key key; |
355 | struct ubifs_dent_node *dent; | 354 | struct ubifs_dent_node *dent; |
356 | struct inode *dir = file_inode(file); | 355 | struct inode *dir = file_inode(file); |
357 | struct ubifs_info *c = dir->i_sb->s_fs_info; | 356 | struct ubifs_info *c = dir->i_sb->s_fs_info; |
358 | 357 | ||
359 | dbg_gen("dir ino %lu, f_pos %#llx", dir->i_ino, pos); | 358 | dbg_gen("dir ino %lu, f_pos %#llx", dir->i_ino, ctx->pos); |
360 | 359 | ||
361 | if (pos > UBIFS_S_KEY_HASH_MASK || pos == 2) | 360 | if (ctx->pos > UBIFS_S_KEY_HASH_MASK || ctx->pos == 2) |
362 | /* | 361 | /* |
363 | * The directory was seek'ed to a senseless position or there | 362 | * The directory was seek'ed to a senseless position or there |
364 | * are no more entries. | 363 | * are no more entries. |
@@ -384,19 +383,9 @@ static int ubifs_readdir(struct file *file, void *dirent, filldir_t filldir) | |||
384 | file->f_version = 1; | 383 | file->f_version = 1; |
385 | 384 | ||
386 | /* File positions 0 and 1 correspond to "." and ".." */ | 385 | /* File positions 0 and 1 correspond to "." and ".." */ |
387 | if (pos == 0) { | 386 | if (ctx->pos < 2) { |
388 | ubifs_assert(!file->private_data); | ||
389 | over = filldir(dirent, ".", 1, 0, dir->i_ino, DT_DIR); | ||
390 | if (over) | ||
391 | return 0; | ||
392 | file->f_pos = pos = 1; | ||
393 | } | ||
394 | |||
395 | if (pos == 1) { | ||
396 | ubifs_assert(!file->private_data); | 387 | ubifs_assert(!file->private_data); |
397 | over = filldir(dirent, "..", 2, 1, | 388 | if (!dir_emit_dots(file, ctx)) |
398 | parent_ino(file->f_path.dentry), DT_DIR); | ||
399 | if (over) | ||
400 | return 0; | 389 | return 0; |
401 | 390 | ||
402 | /* Find the first entry in TNC and save it */ | 391 | /* Find the first entry in TNC and save it */ |
@@ -408,7 +397,7 @@ static int ubifs_readdir(struct file *file, void *dirent, filldir_t filldir) | |||
408 | goto out; | 397 | goto out; |
409 | } | 398 | } |
410 | 399 | ||
411 | file->f_pos = pos = key_hash_flash(c, &dent->key); | 400 | ctx->pos = key_hash_flash(c, &dent->key); |
412 | file->private_data = dent; | 401 | file->private_data = dent; |
413 | } | 402 | } |
414 | 403 | ||
@@ -416,16 +405,16 @@ static int ubifs_readdir(struct file *file, void *dirent, filldir_t filldir) | |||
416 | if (!dent) { | 405 | if (!dent) { |
417 | /* | 406 | /* |
418 | * The directory was seek'ed to and is now readdir'ed. | 407 | * The directory was seek'ed to and is now readdir'ed. |
419 | * Find the entry corresponding to @pos or the closest one. | 408 | * Find the entry corresponding to @ctx->pos or the closest one. |
420 | */ | 409 | */ |
421 | dent_key_init_hash(c, &key, dir->i_ino, pos); | 410 | dent_key_init_hash(c, &key, dir->i_ino, ctx->pos); |
422 | nm.name = NULL; | 411 | nm.name = NULL; |
423 | dent = ubifs_tnc_next_ent(c, &key, &nm); | 412 | dent = ubifs_tnc_next_ent(c, &key, &nm); |
424 | if (IS_ERR(dent)) { | 413 | if (IS_ERR(dent)) { |
425 | err = PTR_ERR(dent); | 414 | err = PTR_ERR(dent); |
426 | goto out; | 415 | goto out; |
427 | } | 416 | } |
428 | file->f_pos = pos = key_hash_flash(c, &dent->key); | 417 | ctx->pos = key_hash_flash(c, &dent->key); |
429 | file->private_data = dent; | 418 | file->private_data = dent; |
430 | } | 419 | } |
431 | 420 | ||
@@ -437,10 +426,9 @@ static int ubifs_readdir(struct file *file, void *dirent, filldir_t filldir) | |||
437 | ubifs_inode(dir)->creat_sqnum); | 426 | ubifs_inode(dir)->creat_sqnum); |
438 | 427 | ||
439 | nm.len = le16_to_cpu(dent->nlen); | 428 | nm.len = le16_to_cpu(dent->nlen); |
440 | over = filldir(dirent, dent->name, nm.len, pos, | 429 | if (!dir_emit(ctx, dent->name, nm.len, |
441 | le64_to_cpu(dent->inum), | 430 | le64_to_cpu(dent->inum), |
442 | vfs_dent_type(dent->type)); | 431 | vfs_dent_type(dent->type))) |
443 | if (over) | ||
444 | return 0; | 432 | return 0; |
445 | 433 | ||
446 | /* Switch to the next entry */ | 434 | /* Switch to the next entry */ |
@@ -453,17 +441,9 @@ static int ubifs_readdir(struct file *file, void *dirent, filldir_t filldir) | |||
453 | } | 441 | } |
454 | 442 | ||
455 | kfree(file->private_data); | 443 | kfree(file->private_data); |
456 | file->f_pos = pos = key_hash_flash(c, &dent->key); | 444 | ctx->pos = key_hash_flash(c, &dent->key); |
457 | file->private_data = dent; | 445 | file->private_data = dent; |
458 | cond_resched(); | 446 | cond_resched(); |
459 | |||
460 | if (file->f_version == 0) | ||
461 | /* | ||
462 | * The file was seek'ed meanwhile, lets return and start | ||
463 | * reading direntries from the new position on the next | ||
464 | * invocation. | ||
465 | */ | ||
466 | return 0; | ||
467 | } | 447 | } |
468 | 448 | ||
469 | out: | 449 | out: |
@@ -475,15 +455,10 @@ out: | |||
475 | kfree(file->private_data); | 455 | kfree(file->private_data); |
476 | file->private_data = NULL; | 456 | file->private_data = NULL; |
477 | /* 2 is a special value indicating that there are no more direntries */ | 457 | /* 2 is a special value indicating that there are no more direntries */ |
478 | file->f_pos = 2; | 458 | ctx->pos = 2; |
479 | return 0; | 459 | return 0; |
480 | } | 460 | } |
481 | 461 | ||
482 | static loff_t ubifs_dir_llseek(struct file *file, loff_t offset, int whence) | ||
483 | { | ||
484 | return generic_file_llseek(file, offset, whence); | ||
485 | } | ||
486 | |||
487 | /* Free saved readdir() state when the directory is closed */ | 462 | /* Free saved readdir() state when the directory is closed */ |
488 | static int ubifs_dir_release(struct inode *dir, struct file *file) | 463 | static int ubifs_dir_release(struct inode *dir, struct file *file) |
489 | { | 464 | { |
@@ -1201,10 +1176,10 @@ const struct inode_operations ubifs_dir_inode_operations = { | |||
1201 | }; | 1176 | }; |
1202 | 1177 | ||
1203 | const struct file_operations ubifs_dir_operations = { | 1178 | const struct file_operations ubifs_dir_operations = { |
1204 | .llseek = ubifs_dir_llseek, | 1179 | .llseek = generic_file_llseek, |
1205 | .release = ubifs_dir_release, | 1180 | .release = ubifs_dir_release, |
1206 | .read = generic_read_dir, | 1181 | .read = generic_read_dir, |
1207 | .readdir = ubifs_readdir, | 1182 | .iterate = ubifs_readdir, |
1208 | .fsync = ubifs_fsync, | 1183 | .fsync = ubifs_fsync, |
1209 | .unlocked_ioctl = ubifs_ioctl, | 1184 | .unlocked_ioctl = ubifs_ioctl, |
1210 | #ifdef CONFIG_COMPAT | 1185 | #ifdef CONFIG_COMPAT |
diff --git a/fs/udf/dir.c b/fs/udf/dir.c index b3e93f5e17c3..a012c51caffd 100644 --- a/fs/udf/dir.c +++ b/fs/udf/dir.c | |||
@@ -35,14 +35,16 @@ | |||
35 | #include "udf_i.h" | 35 | #include "udf_i.h" |
36 | #include "udf_sb.h" | 36 | #include "udf_sb.h" |
37 | 37 | ||
38 | static int do_udf_readdir(struct inode *dir, struct file *filp, | 38 | |
39 | filldir_t filldir, void *dirent) | 39 | static int udf_readdir(struct file *file, struct dir_context *ctx) |
40 | { | 40 | { |
41 | struct inode *dir = file_inode(file); | ||
42 | struct udf_inode_info *iinfo = UDF_I(dir); | ||
41 | struct udf_fileident_bh fibh = { .sbh = NULL, .ebh = NULL}; | 43 | struct udf_fileident_bh fibh = { .sbh = NULL, .ebh = NULL}; |
42 | struct fileIdentDesc *fi = NULL; | 44 | struct fileIdentDesc *fi = NULL; |
43 | struct fileIdentDesc cfi; | 45 | struct fileIdentDesc cfi; |
44 | int block, iblock; | 46 | int block, iblock; |
45 | loff_t nf_pos = (filp->f_pos - 1) << 2; | 47 | loff_t nf_pos; |
46 | int flen; | 48 | int flen; |
47 | unsigned char *fname = NULL; | 49 | unsigned char *fname = NULL; |
48 | unsigned char *nameptr; | 50 | unsigned char *nameptr; |
@@ -54,10 +56,14 @@ static int do_udf_readdir(struct inode *dir, struct file *filp, | |||
54 | uint32_t elen; | 56 | uint32_t elen; |
55 | sector_t offset; | 57 | sector_t offset; |
56 | int i, num, ret = 0; | 58 | int i, num, ret = 0; |
57 | unsigned int dt_type; | ||
58 | struct extent_position epos = { NULL, 0, {0, 0} }; | 59 | struct extent_position epos = { NULL, 0, {0, 0} }; |
59 | struct udf_inode_info *iinfo; | ||
60 | 60 | ||
61 | if (ctx->pos == 0) { | ||
62 | if (!dir_emit_dot(file, ctx)) | ||
63 | return 0; | ||
64 | ctx->pos = 1; | ||
65 | } | ||
66 | nf_pos = (ctx->pos - 1) << 2; | ||
61 | if (nf_pos >= size) | 67 | if (nf_pos >= size) |
62 | goto out; | 68 | goto out; |
63 | 69 | ||
@@ -71,7 +77,6 @@ static int do_udf_readdir(struct inode *dir, struct file *filp, | |||
71 | nf_pos = udf_ext0_offset(dir); | 77 | nf_pos = udf_ext0_offset(dir); |
72 | 78 | ||
73 | fibh.soffset = fibh.eoffset = nf_pos & (dir->i_sb->s_blocksize - 1); | 79 | fibh.soffset = fibh.eoffset = nf_pos & (dir->i_sb->s_blocksize - 1); |
74 | iinfo = UDF_I(dir); | ||
75 | if (iinfo->i_alloc_type != ICBTAG_FLAG_AD_IN_ICB) { | 80 | if (iinfo->i_alloc_type != ICBTAG_FLAG_AD_IN_ICB) { |
76 | if (inode_bmap(dir, nf_pos >> dir->i_sb->s_blocksize_bits, | 81 | if (inode_bmap(dir, nf_pos >> dir->i_sb->s_blocksize_bits, |
77 | &epos, &eloc, &elen, &offset) | 82 | &epos, &eloc, &elen, &offset) |
@@ -116,7 +121,9 @@ static int do_udf_readdir(struct inode *dir, struct file *filp, | |||
116 | } | 121 | } |
117 | 122 | ||
118 | while (nf_pos < size) { | 123 | while (nf_pos < size) { |
119 | filp->f_pos = (nf_pos >> 2) + 1; | 124 | struct kernel_lb_addr tloc; |
125 | |||
126 | ctx->pos = (nf_pos >> 2) + 1; | ||
120 | 127 | ||
121 | fi = udf_fileident_read(dir, &nf_pos, &fibh, &cfi, &epos, &eloc, | 128 | fi = udf_fileident_read(dir, &nf_pos, &fibh, &cfi, &epos, &eloc, |
122 | &elen, &offset); | 129 | &elen, &offset); |
@@ -155,24 +162,22 @@ static int do_udf_readdir(struct inode *dir, struct file *filp, | |||
155 | } | 162 | } |
156 | 163 | ||
157 | if (cfi.fileCharacteristics & FID_FILE_CHAR_PARENT) { | 164 | if (cfi.fileCharacteristics & FID_FILE_CHAR_PARENT) { |
158 | iblock = parent_ino(filp->f_path.dentry); | 165 | if (!dir_emit_dotdot(file, ctx)) |
159 | flen = 2; | 166 | goto out; |
160 | memcpy(fname, "..", flen); | 167 | continue; |
161 | dt_type = DT_DIR; | ||
162 | } else { | ||
163 | struct kernel_lb_addr tloc = lelb_to_cpu(cfi.icb.extLocation); | ||
164 | |||
165 | iblock = udf_get_lb_pblock(dir->i_sb, &tloc, 0); | ||
166 | flen = udf_get_filename(dir->i_sb, nameptr, fname, lfi); | ||
167 | dt_type = DT_UNKNOWN; | ||
168 | } | 168 | } |
169 | 169 | ||
170 | if (flen && filldir(dirent, fname, flen, filp->f_pos, | 170 | flen = udf_get_filename(dir->i_sb, nameptr, fname, lfi); |
171 | iblock, dt_type) < 0) | 171 | if (!flen) |
172 | continue; | ||
173 | |||
174 | tloc = lelb_to_cpu(cfi.icb.extLocation); | ||
175 | iblock = udf_get_lb_pblock(dir->i_sb, &tloc, 0); | ||
176 | if (!dir_emit(ctx, fname, flen, iblock, DT_UNKNOWN)) | ||
172 | goto out; | 177 | goto out; |
173 | } /* end while */ | 178 | } /* end while */ |
174 | 179 | ||
175 | filp->f_pos = (nf_pos >> 2) + 1; | 180 | ctx->pos = (nf_pos >> 2) + 1; |
176 | 181 | ||
177 | out: | 182 | out: |
178 | if (fibh.sbh != fibh.ebh) | 183 | if (fibh.sbh != fibh.ebh) |
@@ -184,27 +189,11 @@ out: | |||
184 | return ret; | 189 | return ret; |
185 | } | 190 | } |
186 | 191 | ||
187 | static int udf_readdir(struct file *filp, void *dirent, filldir_t filldir) | ||
188 | { | ||
189 | struct inode *dir = file_inode(filp); | ||
190 | int result; | ||
191 | |||
192 | if (filp->f_pos == 0) { | ||
193 | if (filldir(dirent, ".", 1, filp->f_pos, dir->i_ino, DT_DIR) < 0) { | ||
194 | return 0; | ||
195 | } | ||
196 | filp->f_pos++; | ||
197 | } | ||
198 | |||
199 | result = do_udf_readdir(dir, filp, filldir, dirent); | ||
200 | return result; | ||
201 | } | ||
202 | |||
203 | /* readdir and lookup functions */ | 192 | /* readdir and lookup functions */ |
204 | const struct file_operations udf_dir_operations = { | 193 | const struct file_operations udf_dir_operations = { |
205 | .llseek = generic_file_llseek, | 194 | .llseek = generic_file_llseek, |
206 | .read = generic_read_dir, | 195 | .read = generic_read_dir, |
207 | .readdir = udf_readdir, | 196 | .iterate = udf_readdir, |
208 | .unlocked_ioctl = udf_ioctl, | 197 | .unlocked_ioctl = udf_ioctl, |
209 | .fsync = generic_file_fsync, | 198 | .fsync = generic_file_fsync, |
210 | }; | 199 | }; |
diff --git a/fs/ufs/dir.c b/fs/ufs/dir.c index 3a75ca09c506..0ecc2cebed8f 100644 --- a/fs/ufs/dir.c +++ b/fs/ufs/dir.c | |||
@@ -430,16 +430,16 @@ ufs_validate_entry(struct super_block *sb, char *base, | |||
430 | * This is blatantly stolen from ext2fs | 430 | * This is blatantly stolen from ext2fs |
431 | */ | 431 | */ |
432 | static int | 432 | static int |
433 | ufs_readdir(struct file *filp, void *dirent, filldir_t filldir) | 433 | ufs_readdir(struct file *file, struct dir_context *ctx) |
434 | { | 434 | { |
435 | loff_t pos = filp->f_pos; | 435 | loff_t pos = ctx->pos; |
436 | struct inode *inode = file_inode(filp); | 436 | struct inode *inode = file_inode(file); |
437 | struct super_block *sb = inode->i_sb; | 437 | struct super_block *sb = inode->i_sb; |
438 | unsigned int offset = pos & ~PAGE_CACHE_MASK; | 438 | unsigned int offset = pos & ~PAGE_CACHE_MASK; |
439 | unsigned long n = pos >> PAGE_CACHE_SHIFT; | 439 | unsigned long n = pos >> PAGE_CACHE_SHIFT; |
440 | unsigned long npages = ufs_dir_pages(inode); | 440 | unsigned long npages = ufs_dir_pages(inode); |
441 | unsigned chunk_mask = ~(UFS_SB(sb)->s_uspi->s_dirblksize - 1); | 441 | unsigned chunk_mask = ~(UFS_SB(sb)->s_uspi->s_dirblksize - 1); |
442 | int need_revalidate = filp->f_version != inode->i_version; | 442 | int need_revalidate = file->f_version != inode->i_version; |
443 | unsigned flags = UFS_SB(sb)->s_flags; | 443 | unsigned flags = UFS_SB(sb)->s_flags; |
444 | 444 | ||
445 | UFSD("BEGIN\n"); | 445 | UFSD("BEGIN\n"); |
@@ -457,16 +457,16 @@ ufs_readdir(struct file *filp, void *dirent, filldir_t filldir) | |||
457 | ufs_error(sb, __func__, | 457 | ufs_error(sb, __func__, |
458 | "bad page in #%lu", | 458 | "bad page in #%lu", |
459 | inode->i_ino); | 459 | inode->i_ino); |
460 | filp->f_pos += PAGE_CACHE_SIZE - offset; | 460 | ctx->pos += PAGE_CACHE_SIZE - offset; |
461 | return -EIO; | 461 | return -EIO; |
462 | } | 462 | } |
463 | kaddr = page_address(page); | 463 | kaddr = page_address(page); |
464 | if (unlikely(need_revalidate)) { | 464 | if (unlikely(need_revalidate)) { |
465 | if (offset) { | 465 | if (offset) { |
466 | offset = ufs_validate_entry(sb, kaddr, offset, chunk_mask); | 466 | offset = ufs_validate_entry(sb, kaddr, offset, chunk_mask); |
467 | filp->f_pos = (n<<PAGE_CACHE_SHIFT) + offset; | 467 | ctx->pos = (n<<PAGE_CACHE_SHIFT) + offset; |
468 | } | 468 | } |
469 | filp->f_version = inode->i_version; | 469 | file->f_version = inode->i_version; |
470 | need_revalidate = 0; | 470 | need_revalidate = 0; |
471 | } | 471 | } |
472 | de = (struct ufs_dir_entry *)(kaddr+offset); | 472 | de = (struct ufs_dir_entry *)(kaddr+offset); |
@@ -479,11 +479,8 @@ ufs_readdir(struct file *filp, void *dirent, filldir_t filldir) | |||
479 | return -EIO; | 479 | return -EIO; |
480 | } | 480 | } |
481 | if (de->d_ino) { | 481 | if (de->d_ino) { |
482 | int over; | ||
483 | unsigned char d_type = DT_UNKNOWN; | 482 | unsigned char d_type = DT_UNKNOWN; |
484 | 483 | ||
485 | offset = (char *)de - kaddr; | ||
486 | |||
487 | UFSD("filldir(%s,%u)\n", de->d_name, | 484 | UFSD("filldir(%s,%u)\n", de->d_name, |
488 | fs32_to_cpu(sb, de->d_ino)); | 485 | fs32_to_cpu(sb, de->d_ino)); |
489 | UFSD("namlen %u\n", ufs_get_de_namlen(sb, de)); | 486 | UFSD("namlen %u\n", ufs_get_de_namlen(sb, de)); |
@@ -491,16 +488,15 @@ ufs_readdir(struct file *filp, void *dirent, filldir_t filldir) | |||
491 | if ((flags & UFS_DE_MASK) == UFS_DE_44BSD) | 488 | if ((flags & UFS_DE_MASK) == UFS_DE_44BSD) |
492 | d_type = de->d_u.d_44.d_type; | 489 | d_type = de->d_u.d_44.d_type; |
493 | 490 | ||
494 | over = filldir(dirent, de->d_name, | 491 | if (!dir_emit(ctx, de->d_name, |
495 | ufs_get_de_namlen(sb, de), | 492 | ufs_get_de_namlen(sb, de), |
496 | (n<<PAGE_CACHE_SHIFT) | offset, | 493 | fs32_to_cpu(sb, de->d_ino), |
497 | fs32_to_cpu(sb, de->d_ino), d_type); | 494 | d_type)) { |
498 | if (over) { | ||
499 | ufs_put_page(page); | 495 | ufs_put_page(page); |
500 | return 0; | 496 | return 0; |
501 | } | 497 | } |
502 | } | 498 | } |
503 | filp->f_pos += fs16_to_cpu(sb, de->d_reclen); | 499 | ctx->pos += fs16_to_cpu(sb, de->d_reclen); |
504 | } | 500 | } |
505 | ufs_put_page(page); | 501 | ufs_put_page(page); |
506 | } | 502 | } |
@@ -660,7 +656,7 @@ not_empty: | |||
660 | 656 | ||
661 | const struct file_operations ufs_dir_operations = { | 657 | const struct file_operations ufs_dir_operations = { |
662 | .read = generic_read_dir, | 658 | .read = generic_read_dir, |
663 | .readdir = ufs_readdir, | 659 | .iterate = ufs_readdir, |
664 | .fsync = generic_file_fsync, | 660 | .fsync = generic_file_fsync, |
665 | .llseek = generic_file_llseek, | 661 | .llseek = generic_file_llseek, |
666 | }; | 662 | }; |
diff --git a/fs/xfs/xfs_dir2.c b/fs/xfs/xfs_dir2.c index b26a50f9921d..8f023dee404d 100644 --- a/fs/xfs/xfs_dir2.c +++ b/fs/xfs/xfs_dir2.c | |||
@@ -368,10 +368,8 @@ xfs_dir_removename( | |||
368 | int | 368 | int |
369 | xfs_readdir( | 369 | xfs_readdir( |
370 | xfs_inode_t *dp, | 370 | xfs_inode_t *dp, |
371 | void *dirent, | 371 | struct dir_context *ctx, |
372 | size_t bufsize, | 372 | size_t bufsize) |
373 | xfs_off_t *offset, | ||
374 | filldir_t filldir) | ||
375 | { | 373 | { |
376 | int rval; /* return value */ | 374 | int rval; /* return value */ |
377 | int v; /* type-checking value */ | 375 | int v; /* type-checking value */ |
@@ -385,14 +383,13 @@ xfs_readdir( | |||
385 | XFS_STATS_INC(xs_dir_getdents); | 383 | XFS_STATS_INC(xs_dir_getdents); |
386 | 384 | ||
387 | if (dp->i_d.di_format == XFS_DINODE_FMT_LOCAL) | 385 | if (dp->i_d.di_format == XFS_DINODE_FMT_LOCAL) |
388 | rval = xfs_dir2_sf_getdents(dp, dirent, offset, filldir); | 386 | rval = xfs_dir2_sf_getdents(dp, ctx); |
389 | else if ((rval = xfs_dir2_isblock(NULL, dp, &v))) | 387 | else if ((rval = xfs_dir2_isblock(NULL, dp, &v))) |
390 | ; | 388 | ; |
391 | else if (v) | 389 | else if (v) |
392 | rval = xfs_dir2_block_getdents(dp, dirent, offset, filldir); | 390 | rval = xfs_dir2_block_getdents(dp, ctx); |
393 | else | 391 | else |
394 | rval = xfs_dir2_leaf_getdents(dp, dirent, bufsize, offset, | 392 | rval = xfs_dir2_leaf_getdents(dp, ctx, bufsize); |
395 | filldir); | ||
396 | return rval; | 393 | return rval; |
397 | } | 394 | } |
398 | 395 | ||
diff --git a/fs/xfs/xfs_dir2_block.c b/fs/xfs/xfs_dir2_block.c index e59f5fc816fe..09aea0247d96 100644 --- a/fs/xfs/xfs_dir2_block.c +++ b/fs/xfs/xfs_dir2_block.c | |||
@@ -569,9 +569,7 @@ xfs_dir2_block_addname( | |||
569 | int /* error */ | 569 | int /* error */ |
570 | xfs_dir2_block_getdents( | 570 | xfs_dir2_block_getdents( |
571 | xfs_inode_t *dp, /* incore inode */ | 571 | xfs_inode_t *dp, /* incore inode */ |
572 | void *dirent, | 572 | struct dir_context *ctx) |
573 | xfs_off_t *offset, | ||
574 | filldir_t filldir) | ||
575 | { | 573 | { |
576 | xfs_dir2_data_hdr_t *hdr; /* block header */ | 574 | xfs_dir2_data_hdr_t *hdr; /* block header */ |
577 | struct xfs_buf *bp; /* buffer for block */ | 575 | struct xfs_buf *bp; /* buffer for block */ |
@@ -589,7 +587,7 @@ xfs_dir2_block_getdents( | |||
589 | /* | 587 | /* |
590 | * If the block number in the offset is out of range, we're done. | 588 | * If the block number in the offset is out of range, we're done. |
591 | */ | 589 | */ |
592 | if (xfs_dir2_dataptr_to_db(mp, *offset) > mp->m_dirdatablk) | 590 | if (xfs_dir2_dataptr_to_db(mp, ctx->pos) > mp->m_dirdatablk) |
593 | return 0; | 591 | return 0; |
594 | 592 | ||
595 | error = xfs_dir3_block_read(NULL, dp, &bp); | 593 | error = xfs_dir3_block_read(NULL, dp, &bp); |
@@ -600,7 +598,7 @@ xfs_dir2_block_getdents( | |||
600 | * Extract the byte offset we start at from the seek pointer. | 598 | * Extract the byte offset we start at from the seek pointer. |
601 | * We'll skip entries before this. | 599 | * We'll skip entries before this. |
602 | */ | 600 | */ |
603 | wantoff = xfs_dir2_dataptr_to_off(mp, *offset); | 601 | wantoff = xfs_dir2_dataptr_to_off(mp, ctx->pos); |
604 | hdr = bp->b_addr; | 602 | hdr = bp->b_addr; |
605 | xfs_dir3_data_check(dp, bp); | 603 | xfs_dir3_data_check(dp, bp); |
606 | /* | 604 | /* |
@@ -639,13 +637,12 @@ xfs_dir2_block_getdents( | |||
639 | cook = xfs_dir2_db_off_to_dataptr(mp, mp->m_dirdatablk, | 637 | cook = xfs_dir2_db_off_to_dataptr(mp, mp->m_dirdatablk, |
640 | (char *)dep - (char *)hdr); | 638 | (char *)dep - (char *)hdr); |
641 | 639 | ||
640 | ctx->pos = cook & 0x7fffffff; | ||
642 | /* | 641 | /* |
643 | * If it didn't fit, set the final offset to here & return. | 642 | * If it didn't fit, set the final offset to here & return. |
644 | */ | 643 | */ |
645 | if (filldir(dirent, (char *)dep->name, dep->namelen, | 644 | if (!dir_emit(ctx, (char *)dep->name, dep->namelen, |
646 | cook & 0x7fffffff, be64_to_cpu(dep->inumber), | 645 | be64_to_cpu(dep->inumber), DT_UNKNOWN)) { |
647 | DT_UNKNOWN)) { | ||
648 | *offset = cook & 0x7fffffff; | ||
649 | xfs_trans_brelse(NULL, bp); | 646 | xfs_trans_brelse(NULL, bp); |
650 | return 0; | 647 | return 0; |
651 | } | 648 | } |
@@ -655,7 +652,7 @@ xfs_dir2_block_getdents( | |||
655 | * Reached the end of the block. | 652 | * Reached the end of the block. |
656 | * Set the offset to a non-existent block 1 and return. | 653 | * Set the offset to a non-existent block 1 and return. |
657 | */ | 654 | */ |
658 | *offset = xfs_dir2_db_off_to_dataptr(mp, mp->m_dirdatablk + 1, 0) & | 655 | ctx->pos = xfs_dir2_db_off_to_dataptr(mp, mp->m_dirdatablk + 1, 0) & |
659 | 0x7fffffff; | 656 | 0x7fffffff; |
660 | xfs_trans_brelse(NULL, bp); | 657 | xfs_trans_brelse(NULL, bp); |
661 | return 0; | 658 | return 0; |
diff --git a/fs/xfs/xfs_dir2_leaf.c b/fs/xfs/xfs_dir2_leaf.c index da71a1819d78..e0cc1243a8aa 100644 --- a/fs/xfs/xfs_dir2_leaf.c +++ b/fs/xfs/xfs_dir2_leaf.c | |||
@@ -1300,10 +1300,8 @@ out: | |||
1300 | int /* error */ | 1300 | int /* error */ |
1301 | xfs_dir2_leaf_getdents( | 1301 | xfs_dir2_leaf_getdents( |
1302 | xfs_inode_t *dp, /* incore directory inode */ | 1302 | xfs_inode_t *dp, /* incore directory inode */ |
1303 | void *dirent, | 1303 | struct dir_context *ctx, |
1304 | size_t bufsize, | 1304 | size_t bufsize) |
1305 | xfs_off_t *offset, | ||
1306 | filldir_t filldir) | ||
1307 | { | 1305 | { |
1308 | struct xfs_buf *bp = NULL; /* data block buffer */ | 1306 | struct xfs_buf *bp = NULL; /* data block buffer */ |
1309 | xfs_dir2_data_hdr_t *hdr; /* data block header */ | 1307 | xfs_dir2_data_hdr_t *hdr; /* data block header */ |
@@ -1322,7 +1320,7 @@ xfs_dir2_leaf_getdents( | |||
1322 | * If the offset is at or past the largest allowed value, | 1320 | * If the offset is at or past the largest allowed value, |
1323 | * give up right away. | 1321 | * give up right away. |
1324 | */ | 1322 | */ |
1325 | if (*offset >= XFS_DIR2_MAX_DATAPTR) | 1323 | if (ctx->pos >= XFS_DIR2_MAX_DATAPTR) |
1326 | return 0; | 1324 | return 0; |
1327 | 1325 | ||
1328 | mp = dp->i_mount; | 1326 | mp = dp->i_mount; |
@@ -1343,7 +1341,7 @@ xfs_dir2_leaf_getdents( | |||
1343 | * Inside the loop we keep the main offset value as a byte offset | 1341 | * Inside the loop we keep the main offset value as a byte offset |
1344 | * in the directory file. | 1342 | * in the directory file. |
1345 | */ | 1343 | */ |
1346 | curoff = xfs_dir2_dataptr_to_byte(mp, *offset); | 1344 | curoff = xfs_dir2_dataptr_to_byte(mp, ctx->pos); |
1347 | 1345 | ||
1348 | /* | 1346 | /* |
1349 | * Force this conversion through db so we truncate the offset | 1347 | * Force this conversion through db so we truncate the offset |
@@ -1444,8 +1442,8 @@ xfs_dir2_leaf_getdents( | |||
1444 | dep = (xfs_dir2_data_entry_t *)ptr; | 1442 | dep = (xfs_dir2_data_entry_t *)ptr; |
1445 | length = xfs_dir2_data_entsize(dep->namelen); | 1443 | length = xfs_dir2_data_entsize(dep->namelen); |
1446 | 1444 | ||
1447 | if (filldir(dirent, (char *)dep->name, dep->namelen, | 1445 | ctx->pos = xfs_dir2_byte_to_dataptr(mp, curoff) & 0x7fffffff; |
1448 | xfs_dir2_byte_to_dataptr(mp, curoff) & 0x7fffffff, | 1446 | if (!dir_emit(ctx, (char *)dep->name, dep->namelen, |
1449 | be64_to_cpu(dep->inumber), DT_UNKNOWN)) | 1447 | be64_to_cpu(dep->inumber), DT_UNKNOWN)) |
1450 | break; | 1448 | break; |
1451 | 1449 | ||
@@ -1462,9 +1460,9 @@ xfs_dir2_leaf_getdents( | |||
1462 | * All done. Set output offset value to current offset. | 1460 | * All done. Set output offset value to current offset. |
1463 | */ | 1461 | */ |
1464 | if (curoff > xfs_dir2_dataptr_to_byte(mp, XFS_DIR2_MAX_DATAPTR)) | 1462 | if (curoff > xfs_dir2_dataptr_to_byte(mp, XFS_DIR2_MAX_DATAPTR)) |
1465 | *offset = XFS_DIR2_MAX_DATAPTR & 0x7fffffff; | 1463 | ctx->pos = XFS_DIR2_MAX_DATAPTR & 0x7fffffff; |
1466 | else | 1464 | else |
1467 | *offset = xfs_dir2_byte_to_dataptr(mp, curoff) & 0x7fffffff; | 1465 | ctx->pos = xfs_dir2_byte_to_dataptr(mp, curoff) & 0x7fffffff; |
1468 | kmem_free(map_info); | 1466 | kmem_free(map_info); |
1469 | if (bp) | 1467 | if (bp) |
1470 | xfs_trans_brelse(NULL, bp); | 1468 | xfs_trans_brelse(NULL, bp); |
diff --git a/fs/xfs/xfs_dir2_priv.h b/fs/xfs/xfs_dir2_priv.h index 7cf573c88aad..0511cda4a712 100644 --- a/fs/xfs/xfs_dir2_priv.h +++ b/fs/xfs/xfs_dir2_priv.h | |||
@@ -33,8 +33,8 @@ extern int xfs_dir_cilookup_result(struct xfs_da_args *args, | |||
33 | extern const struct xfs_buf_ops xfs_dir3_block_buf_ops; | 33 | extern const struct xfs_buf_ops xfs_dir3_block_buf_ops; |
34 | 34 | ||
35 | extern int xfs_dir2_block_addname(struct xfs_da_args *args); | 35 | extern int xfs_dir2_block_addname(struct xfs_da_args *args); |
36 | extern int xfs_dir2_block_getdents(struct xfs_inode *dp, void *dirent, | 36 | extern int xfs_dir2_block_getdents(struct xfs_inode *dp, |
37 | xfs_off_t *offset, filldir_t filldir); | 37 | struct dir_context *ctx); |
38 | extern int xfs_dir2_block_lookup(struct xfs_da_args *args); | 38 | extern int xfs_dir2_block_lookup(struct xfs_da_args *args); |
39 | extern int xfs_dir2_block_removename(struct xfs_da_args *args); | 39 | extern int xfs_dir2_block_removename(struct xfs_da_args *args); |
40 | extern int xfs_dir2_block_replace(struct xfs_da_args *args); | 40 | extern int xfs_dir2_block_replace(struct xfs_da_args *args); |
@@ -91,8 +91,8 @@ extern void xfs_dir3_leaf_compact(struct xfs_da_args *args, | |||
91 | extern void xfs_dir3_leaf_compact_x1(struct xfs_dir3_icleaf_hdr *leafhdr, | 91 | extern void xfs_dir3_leaf_compact_x1(struct xfs_dir3_icleaf_hdr *leafhdr, |
92 | struct xfs_dir2_leaf_entry *ents, int *indexp, | 92 | struct xfs_dir2_leaf_entry *ents, int *indexp, |
93 | int *lowstalep, int *highstalep, int *lowlogp, int *highlogp); | 93 | int *lowstalep, int *highstalep, int *lowlogp, int *highlogp); |
94 | extern int xfs_dir2_leaf_getdents(struct xfs_inode *dp, void *dirent, | 94 | extern int xfs_dir2_leaf_getdents(struct xfs_inode *dp, struct dir_context *ctx, |
95 | size_t bufsize, xfs_off_t *offset, filldir_t filldir); | 95 | size_t bufsize); |
96 | extern int xfs_dir3_leaf_get_buf(struct xfs_da_args *args, xfs_dir2_db_t bno, | 96 | extern int xfs_dir3_leaf_get_buf(struct xfs_da_args *args, xfs_dir2_db_t bno, |
97 | struct xfs_buf **bpp, __uint16_t magic); | 97 | struct xfs_buf **bpp, __uint16_t magic); |
98 | extern void xfs_dir3_leaf_log_ents(struct xfs_trans *tp, struct xfs_buf *bp, | 98 | extern void xfs_dir3_leaf_log_ents(struct xfs_trans *tp, struct xfs_buf *bp, |
@@ -153,8 +153,7 @@ extern int xfs_dir2_block_to_sf(struct xfs_da_args *args, struct xfs_buf *bp, | |||
153 | int size, xfs_dir2_sf_hdr_t *sfhp); | 153 | int size, xfs_dir2_sf_hdr_t *sfhp); |
154 | extern int xfs_dir2_sf_addname(struct xfs_da_args *args); | 154 | extern int xfs_dir2_sf_addname(struct xfs_da_args *args); |
155 | extern int xfs_dir2_sf_create(struct xfs_da_args *args, xfs_ino_t pino); | 155 | extern int xfs_dir2_sf_create(struct xfs_da_args *args, xfs_ino_t pino); |
156 | extern int xfs_dir2_sf_getdents(struct xfs_inode *dp, void *dirent, | 156 | extern int xfs_dir2_sf_getdents(struct xfs_inode *dp, struct dir_context *ctx); |
157 | xfs_off_t *offset, filldir_t filldir); | ||
158 | extern int xfs_dir2_sf_lookup(struct xfs_da_args *args); | 157 | extern int xfs_dir2_sf_lookup(struct xfs_da_args *args); |
159 | extern int xfs_dir2_sf_removename(struct xfs_da_args *args); | 158 | extern int xfs_dir2_sf_removename(struct xfs_da_args *args); |
160 | extern int xfs_dir2_sf_replace(struct xfs_da_args *args); | 159 | extern int xfs_dir2_sf_replace(struct xfs_da_args *args); |
diff --git a/fs/xfs/xfs_dir2_sf.c b/fs/xfs/xfs_dir2_sf.c index 6157424dbf8f..97676a347da1 100644 --- a/fs/xfs/xfs_dir2_sf.c +++ b/fs/xfs/xfs_dir2_sf.c | |||
@@ -768,9 +768,7 @@ xfs_dir2_sf_create( | |||
768 | int /* error */ | 768 | int /* error */ |
769 | xfs_dir2_sf_getdents( | 769 | xfs_dir2_sf_getdents( |
770 | xfs_inode_t *dp, /* incore directory inode */ | 770 | xfs_inode_t *dp, /* incore directory inode */ |
771 | void *dirent, | 771 | struct dir_context *ctx) |
772 | xfs_off_t *offset, | ||
773 | filldir_t filldir) | ||
774 | { | 772 | { |
775 | int i; /* shortform entry number */ | 773 | int i; /* shortform entry number */ |
776 | xfs_mount_t *mp; /* filesystem mount point */ | 774 | xfs_mount_t *mp; /* filesystem mount point */ |
@@ -802,7 +800,7 @@ xfs_dir2_sf_getdents( | |||
802 | /* | 800 | /* |
803 | * If the block number in the offset is out of range, we're done. | 801 | * If the block number in the offset is out of range, we're done. |
804 | */ | 802 | */ |
805 | if (xfs_dir2_dataptr_to_db(mp, *offset) > mp->m_dirdatablk) | 803 | if (xfs_dir2_dataptr_to_db(mp, ctx->pos) > mp->m_dirdatablk) |
806 | return 0; | 804 | return 0; |
807 | 805 | ||
808 | /* | 806 | /* |
@@ -819,22 +817,20 @@ xfs_dir2_sf_getdents( | |||
819 | /* | 817 | /* |
820 | * Put . entry unless we're starting past it. | 818 | * Put . entry unless we're starting past it. |
821 | */ | 819 | */ |
822 | if (*offset <= dot_offset) { | 820 | if (ctx->pos <= dot_offset) { |
823 | if (filldir(dirent, ".", 1, dot_offset & 0x7fffffff, dp->i_ino, DT_DIR)) { | 821 | ctx->pos = dot_offset & 0x7fffffff; |
824 | *offset = dot_offset & 0x7fffffff; | 822 | if (!dir_emit(ctx, ".", 1, dp->i_ino, DT_DIR)) |
825 | return 0; | 823 | return 0; |
826 | } | ||
827 | } | 824 | } |
828 | 825 | ||
829 | /* | 826 | /* |
830 | * Put .. entry unless we're starting past it. | 827 | * Put .. entry unless we're starting past it. |
831 | */ | 828 | */ |
832 | if (*offset <= dotdot_offset) { | 829 | if (ctx->pos <= dotdot_offset) { |
833 | ino = xfs_dir2_sf_get_parent_ino(sfp); | 830 | ino = xfs_dir2_sf_get_parent_ino(sfp); |
834 | if (filldir(dirent, "..", 2, dotdot_offset & 0x7fffffff, ino, DT_DIR)) { | 831 | ctx->pos = dotdot_offset & 0x7fffffff; |
835 | *offset = dotdot_offset & 0x7fffffff; | 832 | if (!dir_emit(ctx, "..", 2, ino, DT_DIR)) |
836 | return 0; | 833 | return 0; |
837 | } | ||
838 | } | 834 | } |
839 | 835 | ||
840 | /* | 836 | /* |
@@ -845,21 +841,20 @@ xfs_dir2_sf_getdents( | |||
845 | off = xfs_dir2_db_off_to_dataptr(mp, mp->m_dirdatablk, | 841 | off = xfs_dir2_db_off_to_dataptr(mp, mp->m_dirdatablk, |
846 | xfs_dir2_sf_get_offset(sfep)); | 842 | xfs_dir2_sf_get_offset(sfep)); |
847 | 843 | ||
848 | if (*offset > off) { | 844 | if (ctx->pos > off) { |
849 | sfep = xfs_dir2_sf_nextentry(sfp, sfep); | 845 | sfep = xfs_dir2_sf_nextentry(sfp, sfep); |
850 | continue; | 846 | continue; |
851 | } | 847 | } |
852 | 848 | ||
853 | ino = xfs_dir2_sfe_get_ino(sfp, sfep); | 849 | ino = xfs_dir2_sfe_get_ino(sfp, sfep); |
854 | if (filldir(dirent, (char *)sfep->name, sfep->namelen, | 850 | ctx->pos = off & 0x7fffffff; |
855 | off & 0x7fffffff, ino, DT_UNKNOWN)) { | 851 | if (!dir_emit(ctx, (char *)sfep->name, sfep->namelen, |
856 | *offset = off & 0x7fffffff; | 852 | ino, DT_UNKNOWN)) |
857 | return 0; | 853 | return 0; |
858 | } | ||
859 | sfep = xfs_dir2_sf_nextentry(sfp, sfep); | 854 | sfep = xfs_dir2_sf_nextentry(sfp, sfep); |
860 | } | 855 | } |
861 | 856 | ||
862 | *offset = xfs_dir2_db_off_to_dataptr(mp, mp->m_dirdatablk + 1, 0) & | 857 | ctx->pos = xfs_dir2_db_off_to_dataptr(mp, mp->m_dirdatablk + 1, 0) & |
863 | 0x7fffffff; | 858 | 0x7fffffff; |
864 | return 0; | 859 | return 0; |
865 | } | 860 | } |
diff --git a/fs/xfs/xfs_file.c b/fs/xfs/xfs_file.c index a5f2042aec8b..0ad2b95fca12 100644 --- a/fs/xfs/xfs_file.c +++ b/fs/xfs/xfs_file.c | |||
@@ -906,11 +906,10 @@ xfs_file_release( | |||
906 | 906 | ||
907 | STATIC int | 907 | STATIC int |
908 | xfs_file_readdir( | 908 | xfs_file_readdir( |
909 | struct file *filp, | 909 | struct file *file, |
910 | void *dirent, | 910 | struct dir_context *ctx) |
911 | filldir_t filldir) | ||
912 | { | 911 | { |
913 | struct inode *inode = file_inode(filp); | 912 | struct inode *inode = file_inode(file); |
914 | xfs_inode_t *ip = XFS_I(inode); | 913 | xfs_inode_t *ip = XFS_I(inode); |
915 | int error; | 914 | int error; |
916 | size_t bufsize; | 915 | size_t bufsize; |
@@ -929,8 +928,7 @@ xfs_file_readdir( | |||
929 | */ | 928 | */ |
930 | bufsize = (size_t)min_t(loff_t, 32768, ip->i_d.di_size); | 929 | bufsize = (size_t)min_t(loff_t, 32768, ip->i_d.di_size); |
931 | 930 | ||
932 | error = xfs_readdir(ip, dirent, bufsize, | 931 | error = xfs_readdir(ip, ctx, bufsize); |
933 | (xfs_off_t *)&filp->f_pos, filldir); | ||
934 | if (error) | 932 | if (error) |
935 | return -error; | 933 | return -error; |
936 | return 0; | 934 | return 0; |
@@ -1432,7 +1430,7 @@ const struct file_operations xfs_file_operations = { | |||
1432 | const struct file_operations xfs_dir_file_operations = { | 1430 | const struct file_operations xfs_dir_file_operations = { |
1433 | .open = xfs_dir_open, | 1431 | .open = xfs_dir_open, |
1434 | .read = generic_read_dir, | 1432 | .read = generic_read_dir, |
1435 | .readdir = xfs_file_readdir, | 1433 | .iterate = xfs_file_readdir, |
1436 | .llseek = generic_file_llseek, | 1434 | .llseek = generic_file_llseek, |
1437 | .unlocked_ioctl = xfs_file_ioctl, | 1435 | .unlocked_ioctl = xfs_file_ioctl, |
1438 | #ifdef CONFIG_COMPAT | 1436 | #ifdef CONFIG_COMPAT |
diff --git a/fs/xfs/xfs_vnodeops.h b/fs/xfs/xfs_vnodeops.h index 5163022d9808..38c67c34d73f 100644 --- a/fs/xfs/xfs_vnodeops.h +++ b/fs/xfs/xfs_vnodeops.h | |||
@@ -31,8 +31,7 @@ int xfs_remove(struct xfs_inode *dp, struct xfs_name *name, | |||
31 | struct xfs_inode *ip); | 31 | struct xfs_inode *ip); |
32 | int xfs_link(struct xfs_inode *tdp, struct xfs_inode *sip, | 32 | int xfs_link(struct xfs_inode *tdp, struct xfs_inode *sip, |
33 | struct xfs_name *target_name); | 33 | struct xfs_name *target_name); |
34 | int xfs_readdir(struct xfs_inode *dp, void *dirent, size_t bufsize, | 34 | int xfs_readdir(struct xfs_inode *dp, struct dir_context *ctx, size_t bufsize); |
35 | xfs_off_t *offset, filldir_t filldir); | ||
36 | int xfs_symlink(struct xfs_inode *dp, struct xfs_name *link_name, | 35 | int xfs_symlink(struct xfs_inode *dp, struct xfs_name *link_name, |
37 | const char *target_path, umode_t mode, struct xfs_inode **ipp); | 36 | const char *target_path, umode_t mode, struct xfs_inode **ipp); |
38 | int xfs_set_dmattrs(struct xfs_inode *ip, u_int evmask, u_int16_t state); | 37 | int xfs_set_dmattrs(struct xfs_inode *ip, u_int evmask, u_int16_t state); |