diff options
Diffstat (limited to 'fs/coda/dir.c')
-rw-r--r-- | fs/coda/dir.c | 76 |
1 files changed, 21 insertions, 55 deletions
diff --git a/fs/coda/dir.c b/fs/coda/dir.c index b7d3a05c062c..190effc6a6fa 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,32 +482,23 @@ 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 */ |
514 | if (vdir->d_fileno && name.len) { | 489 | if (vdir->d_fileno && name.len) { |
515 | /* try to look up this entry in the dcache, that way | 490 | ino = vdir->d_fileno; |
516 | * userspace doesn't have to worry about breaking | ||
517 | * getcwd by having mismatched inode numbers for | ||
518 | * internal volume mountpoints. */ | ||
519 | ino = find_inode_number(de, &name); | ||
520 | if (!ino) ino = vdir->d_fileno; | ||
521 | |||
522 | type = CDT2DT(vdir->d_type); | 491 | type = CDT2DT(vdir->d_type); |
523 | ret = filldir(buf, name.name, name.len, | 492 | if (!dir_emit(ctx, name.name, name.len, ino, type)) |
524 | coda_file->f_pos, ino, type); | 493 | break; |
525 | /* failure means no space for filling in this round */ | ||
526 | if (ret < 0) break; | ||
527 | result++; | ||
528 | } | 494 | } |
529 | /* we'll always have progress because d_reclen is unsigned and | 495 | /* we'll always have progress because d_reclen is unsigned and |
530 | * we've already established it is non-zero. */ | 496 | * we've already established it is non-zero. */ |
531 | coda_file->f_pos += vdir->d_reclen; | 497 | ctx->pos += vdir->d_reclen; |
532 | } | 498 | } |
533 | out: | 499 | out: |
534 | kfree(vdir); | 500 | kfree(vdir); |
535 | return result ? result : ret; | 501 | return 0; |
536 | } | 502 | } |
537 | 503 | ||
538 | /* called when a cache lookup succeeds */ | 504 | /* called when a cache lookup succeeds */ |
@@ -560,7 +526,7 @@ static int coda_dentry_revalidate(struct dentry *de, unsigned int flags) | |||
560 | if (cii->c_flags & C_FLUSH) | 526 | if (cii->c_flags & C_FLUSH) |
561 | coda_flag_inode_children(inode, C_FLUSH); | 527 | coda_flag_inode_children(inode, C_FLUSH); |
562 | 528 | ||
563 | if (de->d_count > 1) | 529 | if (d_count(de) > 1) |
564 | /* pretend it's valid, but don't change the flags */ | 530 | /* pretend it's valid, but don't change the flags */ |
565 | goto out; | 531 | goto out; |
566 | 532 | ||