diff options
| author | Al Viro <viro@zeniv.linux.org.uk> | 2013-05-22 21:15:30 -0400 |
|---|---|---|
| committer | Al Viro <viro@zeniv.linux.org.uk> | 2013-06-29 04:57:03 -0400 |
| commit | e924f251264bec0b73c32f15ed27a7fbb9912beb (patch) | |
| tree | d93c096ac0152fc8094734a0ac8a38b1d9bf7ccc /fs/coda | |
| parent | 3704412bdbf37ec836152f571ac74fe72220c05a (diff) | |
[readdir] convert coda
Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
Diffstat (limited to 'fs/coda')
| -rw-r--r-- | fs/coda/dir.c | 77 |
1 files changed, 19 insertions, 58 deletions
diff --git a/fs/coda/dir.c b/fs/coda/dir.c index fc66861b3598..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,28 +390,8 @@ 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 | /* potemkin case: we were handed a directory inode. | ||
| 396 | * We can't use vfs_readdir because we have to keep the file | ||
| 397 | * position in sync between the coda_file and the host_file. | ||
| 398 | * and as such we need grab the inode mutex. */ | ||
| 399 | struct inode *host_inode = file_inode(host_file); | 394 | struct inode *host_inode = file_inode(host_file); |
| 400 | |||
| 401 | mutex_lock(&host_inode->i_mutex); | ||
| 402 | host_file->f_pos = coda_file->f_pos; | ||
| 403 | |||
| 404 | ret = -ENOENT; | ||
| 405 | if (!IS_DEADDIR(host_inode)) { | ||
| 406 | ret = host_file->f_op->readdir(host_file, buf, filldir); | ||
| 407 | file_accessed(host_file); | ||
| 408 | } | ||
| 409 | |||
| 410 | coda_file->f_pos = host_file->f_pos; | ||
| 411 | mutex_unlock(&host_inode->i_mutex); | ||
| 412 | } else if (host_file->f_op->iterate) { | ||
| 413 | struct inode *host_inode = file_inode(host_file); | ||
| 414 | struct dir_context *ctx = buf; | ||
| 415 | |||
| 416 | mutex_lock(&host_inode->i_mutex); | 395 | mutex_lock(&host_inode->i_mutex); |
| 417 | ret = -ENOENT; | 396 | ret = -ENOENT; |
| 418 | if (!IS_DEADDIR(host_inode)) { | 397 | if (!IS_DEADDIR(host_inode)) { |
| @@ -420,12 +399,10 @@ static int coda_readdir(struct file *coda_file, void *buf, filldir_t filldir) | |||
| 420 | file_accessed(host_file); | 399 | file_accessed(host_file); |
| 421 | } | 400 | } |
| 422 | mutex_unlock(&host_inode->i_mutex); | 401 | mutex_unlock(&host_inode->i_mutex); |
| 423 | 402 | return ret; | |
| 424 | coda_file->f_pos = ctx->pos; | 403 | } |
| 425 | } else /* Venus: we must read Venus dirents from a file */ | 404 | /* Venus: we must read Venus dirents from a file */ |
| 426 | ret = coda_venus_readdir(coda_file, buf, filldir); | 405 | return coda_venus_readdir(coda_file, ctx); |
| 427 | |||
| 428 | return ret; | ||
| 429 | } | 406 | } |
| 430 | 407 | ||
| 431 | static inline unsigned int CDT2DT(unsigned char cdt) | 408 | static inline unsigned int CDT2DT(unsigned char cdt) |
| @@ -448,10 +425,8 @@ static inline unsigned int CDT2DT(unsigned char cdt) | |||
| 448 | } | 425 | } |
| 449 | 426 | ||
| 450 | /* support routines */ | 427 | /* support routines */ |
| 451 | 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) |
| 452 | filldir_t filldir) | ||
| 453 | { | 429 | { |
| 454 | int result = 0; /* # of entries returned */ | ||
| 455 | struct coda_file_info *cfi; | 430 | struct coda_file_info *cfi; |
| 456 | struct coda_inode_info *cii; | 431 | struct coda_inode_info *cii; |
| 457 | struct file *host_file; | 432 | struct file *host_file; |
| @@ -473,23 +448,12 @@ static int coda_venus_readdir(struct file *coda_file, void *buf, | |||
| 473 | vdir = kmalloc(sizeof(*vdir), GFP_KERNEL); | 448 | vdir = kmalloc(sizeof(*vdir), GFP_KERNEL); |
| 474 | if (!vdir) return -ENOMEM; | 449 | if (!vdir) return -ENOMEM; |
| 475 | 450 | ||
| 476 | if (coda_file->f_pos == 0) { | 451 | if (!dir_emit_dots(coda_file, ctx)) |
| 477 | ret = filldir(buf, ".", 1, 0, de->d_inode->i_ino, DT_DIR); | 452 | goto out; |
| 478 | if (ret < 0) | 453 | |
| 479 | goto out; | ||
| 480 | result++; | ||
| 481 | coda_file->f_pos++; | ||
| 482 | } | ||
| 483 | if (coda_file->f_pos == 1) { | ||
| 484 | ret = filldir(buf, "..", 2, 1, parent_ino(de), DT_DIR); | ||
| 485 | if (ret < 0) | ||
| 486 | goto out; | ||
| 487 | result++; | ||
| 488 | coda_file->f_pos++; | ||
| 489 | } | ||
| 490 | while (1) { | 454 | while (1) { |
| 491 | /* read entries from the directory file */ | 455 | /* read entries from the directory file */ |
| 492 | ret = kernel_read(host_file, coda_file->f_pos - 2, (char *)vdir, | 456 | ret = kernel_read(host_file, ctx->pos - 2, (char *)vdir, |
| 493 | sizeof(*vdir)); | 457 | sizeof(*vdir)); |
| 494 | if (ret < 0) { | 458 | if (ret < 0) { |
| 495 | printk(KERN_ERR "coda readdir: read dir %s failed %d\n", | 459 | printk(KERN_ERR "coda readdir: read dir %s failed %d\n", |
| @@ -518,7 +482,7 @@ static int coda_venus_readdir(struct file *coda_file, void *buf, | |||
| 518 | 482 | ||
| 519 | /* Make sure we skip '.' and '..', we already got those */ | 483 | /* Make sure we skip '.' and '..', we already got those */ |
| 520 | if (name.name[0] == '.' && (name.len == 1 || | 484 | if (name.name[0] == '.' && (name.len == 1 || |
| 521 | (vdir->d_name[1] == '.' && name.len == 2))) | 485 | (name.name[1] == '.' && name.len == 2))) |
| 522 | vdir->d_fileno = name.len = 0; | 486 | vdir->d_fileno = name.len = 0; |
| 523 | 487 | ||
| 524 | /* skip null entries */ | 488 | /* skip null entries */ |
| @@ -531,19 +495,16 @@ static int coda_venus_readdir(struct file *coda_file, void *buf, | |||
| 531 | if (!ino) ino = vdir->d_fileno; | 495 | if (!ino) ino = vdir->d_fileno; |
| 532 | 496 | ||
| 533 | type = CDT2DT(vdir->d_type); | 497 | type = CDT2DT(vdir->d_type); |
| 534 | ret = filldir(buf, name.name, name.len, | 498 | if (!dir_emit(ctx, name.name, name.len, ino, type)) |
| 535 | coda_file->f_pos, ino, type); | 499 | break; |
| 536 | /* failure means no space for filling in this round */ | ||
| 537 | if (ret < 0) break; | ||
| 538 | result++; | ||
| 539 | } | 500 | } |
| 540 | /* we'll always have progress because d_reclen is unsigned and | 501 | /* we'll always have progress because d_reclen is unsigned and |
| 541 | * we've already established it is non-zero. */ | 502 | * we've already established it is non-zero. */ |
| 542 | coda_file->f_pos += vdir->d_reclen; | 503 | ctx->pos += vdir->d_reclen; |
| 543 | } | 504 | } |
| 544 | out: | 505 | out: |
| 545 | kfree(vdir); | 506 | kfree(vdir); |
| 546 | return result ? result : ret; | 507 | return 0; |
| 547 | } | 508 | } |
| 548 | 509 | ||
| 549 | /* called when a cache lookup succeeds */ | 510 | /* called when a cache lookup succeeds */ |
