diff options
-rw-r--r-- | fs/ocfs2/dir.c | 103 |
1 files changed, 56 insertions, 47 deletions
diff --git a/fs/ocfs2/dir.c b/fs/ocfs2/dir.c index 8e0ae022b2e9..d1f92fd2ed96 100644 --- a/fs/ocfs2/dir.c +++ b/fs/ocfs2/dir.c | |||
@@ -414,11 +414,8 @@ bail: | |||
414 | return retval; | 414 | return retval; |
415 | } | 415 | } |
416 | 416 | ||
417 | /* | 417 | static int ocfs2_dir_foreach_blk(struct inode *inode, unsigned long *f_version, |
418 | * ocfs2_readdir() | 418 | loff_t *f_pos, void *priv, filldir_t filldir) |
419 | * | ||
420 | */ | ||
421 | int ocfs2_readdir(struct file * filp, void * dirent, filldir_t filldir) | ||
422 | { | 419 | { |
423 | int error = 0; | 420 | int error = 0; |
424 | unsigned long offset, blk, last_ra_blk = 0; | 421 | unsigned long offset, blk, last_ra_blk = 0; |
@@ -426,45 +423,23 @@ int ocfs2_readdir(struct file * filp, void * dirent, filldir_t filldir) | |||
426 | struct buffer_head * bh, * tmp; | 423 | struct buffer_head * bh, * tmp; |
427 | struct ocfs2_dir_entry * de; | 424 | struct ocfs2_dir_entry * de; |
428 | int err; | 425 | int err; |
429 | struct inode *inode = filp->f_path.dentry->d_inode; | ||
430 | struct super_block * sb = inode->i_sb; | 426 | struct super_block * sb = inode->i_sb; |
431 | unsigned int ra_sectors = 16; | 427 | unsigned int ra_sectors = 16; |
432 | int lock_level = 0; | ||
433 | |||
434 | mlog_entry("dirino=%llu\n", | ||
435 | (unsigned long long)OCFS2_I(inode)->ip_blkno); | ||
436 | 428 | ||
437 | stored = 0; | 429 | stored = 0; |
438 | bh = NULL; | 430 | bh = NULL; |
439 | 431 | ||
440 | error = ocfs2_meta_lock_atime(inode, filp->f_vfsmnt, &lock_level); | 432 | offset = (*f_pos) & (sb->s_blocksize - 1); |
441 | if (lock_level && error >= 0) { | ||
442 | /* We release EX lock which used to update atime | ||
443 | * and get PR lock again to reduce contention | ||
444 | * on commonly accessed directories. */ | ||
445 | ocfs2_meta_unlock(inode, 1); | ||
446 | lock_level = 0; | ||
447 | error = ocfs2_meta_lock(inode, NULL, 0); | ||
448 | } | ||
449 | if (error < 0) { | ||
450 | if (error != -ENOENT) | ||
451 | mlog_errno(error); | ||
452 | /* we haven't got any yet, so propagate the error. */ | ||
453 | stored = error; | ||
454 | goto bail_nolock; | ||
455 | } | ||
456 | |||
457 | offset = filp->f_pos & (sb->s_blocksize - 1); | ||
458 | 433 | ||
459 | while (!error && !stored && filp->f_pos < i_size_read(inode)) { | 434 | while (!error && !stored && *f_pos < i_size_read(inode)) { |
460 | blk = (filp->f_pos) >> sb->s_blocksize_bits; | 435 | blk = (*f_pos) >> sb->s_blocksize_bits; |
461 | bh = ocfs2_bread(inode, blk, &err, 0); | 436 | bh = ocfs2_bread(inode, blk, &err, 0); |
462 | if (!bh) { | 437 | if (!bh) { |
463 | mlog(ML_ERROR, | 438 | mlog(ML_ERROR, |
464 | "directory #%llu contains a hole at offset %lld\n", | 439 | "directory #%llu contains a hole at offset %lld\n", |
465 | (unsigned long long)OCFS2_I(inode)->ip_blkno, | 440 | (unsigned long long)OCFS2_I(inode)->ip_blkno, |
466 | filp->f_pos); | 441 | *f_pos); |
467 | filp->f_pos += sb->s_blocksize - offset; | 442 | *f_pos += sb->s_blocksize - offset; |
468 | continue; | 443 | continue; |
469 | } | 444 | } |
470 | 445 | ||
@@ -490,7 +465,7 @@ revalidate: | |||
490 | * readdir(2), then we might be pointing to an invalid | 465 | * readdir(2), then we might be pointing to an invalid |
491 | * dirent right now. Scan from the start of the block | 466 | * dirent right now. Scan from the start of the block |
492 | * to make sure. */ | 467 | * to make sure. */ |
493 | if (filp->f_version != inode->i_version) { | 468 | if (*f_version != inode->i_version) { |
494 | for (i = 0; i < sb->s_blocksize && i < offset; ) { | 469 | for (i = 0; i < sb->s_blocksize && i < offset; ) { |
495 | de = (struct ocfs2_dir_entry *) (bh->b_data + i); | 470 | de = (struct ocfs2_dir_entry *) (bh->b_data + i); |
496 | /* It's too expensive to do a full | 471 | /* It's too expensive to do a full |
@@ -505,21 +480,20 @@ revalidate: | |||
505 | i += le16_to_cpu(de->rec_len); | 480 | i += le16_to_cpu(de->rec_len); |
506 | } | 481 | } |
507 | offset = i; | 482 | offset = i; |
508 | filp->f_pos = (filp->f_pos & ~(sb->s_blocksize - 1)) | 483 | *f_pos = ((*f_pos) & ~(sb->s_blocksize - 1)) |
509 | | offset; | 484 | | offset; |
510 | filp->f_version = inode->i_version; | 485 | *f_version = inode->i_version; |
511 | } | 486 | } |
512 | 487 | ||
513 | while (!error && filp->f_pos < i_size_read(inode) | 488 | while (!error && *f_pos < i_size_read(inode) |
514 | && offset < sb->s_blocksize) { | 489 | && offset < sb->s_blocksize) { |
515 | de = (struct ocfs2_dir_entry *) (bh->b_data + offset); | 490 | de = (struct ocfs2_dir_entry *) (bh->b_data + offset); |
516 | if (!ocfs2_check_dir_entry(inode, de, bh, offset)) { | 491 | if (!ocfs2_check_dir_entry(inode, de, bh, offset)) { |
517 | /* On error, skip the f_pos to the | 492 | /* On error, skip the f_pos to the |
518 | next block. */ | 493 | next block. */ |
519 | filp->f_pos = (filp->f_pos | | 494 | *f_pos = ((*f_pos) | (sb->s_blocksize - 1)) + 1; |
520 | (sb->s_blocksize - 1)) + 1; | ||
521 | brelse(bh); | 495 | brelse(bh); |
522 | goto bail; | 496 | goto out; |
523 | } | 497 | } |
524 | offset += le16_to_cpu(de->rec_len); | 498 | offset += le16_to_cpu(de->rec_len); |
525 | if (le64_to_cpu(de->inode)) { | 499 | if (le64_to_cpu(de->inode)) { |
@@ -530,36 +504,71 @@ revalidate: | |||
530 | * not the directory has been modified | 504 | * not the directory has been modified |
531 | * during the copy operation. | 505 | * during the copy operation. |
532 | */ | 506 | */ |
533 | unsigned long version = filp->f_version; | 507 | unsigned long version = *f_version; |
534 | unsigned char d_type = DT_UNKNOWN; | 508 | unsigned char d_type = DT_UNKNOWN; |
535 | 509 | ||
536 | if (de->file_type < OCFS2_FT_MAX) | 510 | if (de->file_type < OCFS2_FT_MAX) |
537 | d_type = ocfs2_filetype_table[de->file_type]; | 511 | d_type = ocfs2_filetype_table[de->file_type]; |
538 | error = filldir(dirent, de->name, | 512 | error = filldir(priv, de->name, |
539 | de->name_len, | 513 | de->name_len, |
540 | filp->f_pos, | 514 | *f_pos, |
541 | ino_from_blkno(sb, le64_to_cpu(de->inode)), | 515 | ino_from_blkno(sb, le64_to_cpu(de->inode)), |
542 | d_type); | 516 | d_type); |
543 | if (error) | 517 | if (error) |
544 | break; | 518 | break; |
545 | if (version != filp->f_version) | 519 | if (version != *f_version) |
546 | goto revalidate; | 520 | goto revalidate; |
547 | stored ++; | 521 | stored ++; |
548 | } | 522 | } |
549 | filp->f_pos += le16_to_cpu(de->rec_len); | 523 | *f_pos += le16_to_cpu(de->rec_len); |
550 | } | 524 | } |
551 | offset = 0; | 525 | offset = 0; |
552 | brelse(bh); | 526 | brelse(bh); |
553 | } | 527 | } |
554 | 528 | ||
555 | stored = 0; | 529 | stored = 0; |
556 | bail: | 530 | out: |
531 | return stored; | ||
532 | } | ||
533 | |||
534 | /* | ||
535 | * ocfs2_readdir() | ||
536 | * | ||
537 | */ | ||
538 | int ocfs2_readdir(struct file * filp, void * dirent, filldir_t filldir) | ||
539 | { | ||
540 | int error = 0; | ||
541 | struct inode *inode = filp->f_path.dentry->d_inode; | ||
542 | int lock_level = 0; | ||
543 | |||
544 | mlog_entry("dirino=%llu\n", | ||
545 | (unsigned long long)OCFS2_I(inode)->ip_blkno); | ||
546 | |||
547 | error = ocfs2_meta_lock_atime(inode, filp->f_vfsmnt, &lock_level); | ||
548 | if (lock_level && error >= 0) { | ||
549 | /* We release EX lock which used to update atime | ||
550 | * and get PR lock again to reduce contention | ||
551 | * on commonly accessed directories. */ | ||
552 | ocfs2_meta_unlock(inode, 1); | ||
553 | lock_level = 0; | ||
554 | error = ocfs2_meta_lock(inode, NULL, 0); | ||
555 | } | ||
556 | if (error < 0) { | ||
557 | if (error != -ENOENT) | ||
558 | mlog_errno(error); | ||
559 | /* we haven't got any yet, so propagate the error. */ | ||
560 | goto bail_nolock; | ||
561 | } | ||
562 | |||
563 | error = ocfs2_dir_foreach_blk(inode, &filp->f_version, &filp->f_pos, | ||
564 | dirent, filldir); | ||
565 | |||
557 | ocfs2_meta_unlock(inode, lock_level); | 566 | ocfs2_meta_unlock(inode, lock_level); |
558 | 567 | ||
559 | bail_nolock: | 568 | bail_nolock: |
560 | mlog_exit(stored); | 569 | mlog_exit(error); |
561 | 570 | ||
562 | return stored; | 571 | return error; |
563 | } | 572 | } |
564 | 573 | ||
565 | /* | 574 | /* |