aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--fs/ocfs2/dir.c103
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/* 417static 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 */
421int 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;
556bail: 530out:
531 return stored;
532}
533
534/*
535 * ocfs2_readdir()
536 *
537 */
538int 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
559bail_nolock: 568bail_nolock:
560 mlog_exit(stored); 569 mlog_exit(error);
561 570
562 return stored; 571 return error;
563} 572}
564 573
565/* 574/*