aboutsummaryrefslogtreecommitdiffstats
path: root/fs/coda/dir.c
diff options
context:
space:
mode:
Diffstat (limited to 'fs/coda/dir.c')
-rw-r--r--fs/coda/dir.c76
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 */
46static int coda_readdir(struct file *file, void *buf, filldir_t filldir); 46static int coda_readdir(struct file *file, struct dir_context *ctx);
47 47
48/* dentry ops */ 48/* dentry ops */
49static int coda_dentry_revalidate(struct dentry *de, unsigned int flags); 49static int coda_dentry_revalidate(struct dentry *de, unsigned int flags);
50static int coda_dentry_delete(const struct dentry *); 50static int coda_dentry_delete(const struct dentry *);
51 51
52/* support routines */ 52/* support routines */
53static int coda_venus_readdir(struct file *coda_file, void *buf, 53static 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 */
57static int coda_return_EIO(void) 56static int coda_return_EIO(void)
@@ -85,7 +84,7 @@ const struct inode_operations coda_dir_inode_operations =
85const struct file_operations coda_dir_operations = { 84const 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 */
381static int coda_readdir(struct file *coda_file, void *buf, filldir_t filldir) 380static 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
420static inline unsigned int CDT2DT(unsigned char cdt) 408static 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 */
440static int coda_venus_readdir(struct file *coda_file, void *buf, 428static 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 }
533out: 499out:
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