diff options
author | Al Viro <viro@zeniv.linux.org.uk> | 2013-05-22 16:31:14 -0400 |
---|---|---|
committer | Al Viro <viro@zeniv.linux.org.uk> | 2013-06-29 04:56:58 -0400 |
commit | 1bbae9f818609959b8ffc0bf61ba8026a7059426 (patch) | |
tree | cc6b89a0b534db005cbe469d134eac4b6d1f91ee | |
parent | 76f582a8f60a94c116e0b92d07c9047410274b20 (diff) |
[readdir] convert afs
Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
-rw-r--r-- | fs/afs/dir.c | 99 |
1 files changed, 37 insertions, 62 deletions
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; |