diff options
author | Al Viro <viro@zeniv.linux.org.uk> | 2013-05-17 16:52:26 -0400 |
---|---|---|
committer | Al Viro <viro@zeniv.linux.org.uk> | 2013-06-29 04:56:41 -0400 |
commit | 77acfa29e10cc859cc165963093a83f754598b03 (patch) | |
tree | 1b72a5d24a8b4de1be2522532d0fa46a0c1e34b0 /fs/ceph | |
parent | 23db862060e05e52363aa872c50e518db9c94f6d (diff) |
[readdir] convert ceph
Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
Diffstat (limited to 'fs/ceph')
-rw-r--r-- | fs/ceph/dir.c | 99 |
1 files changed, 48 insertions, 51 deletions
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, |