diff options
Diffstat (limited to 'fs/xfs/xfs_dir2_sf.c')
-rw-r--r-- | fs/xfs/xfs_dir2_sf.c | 121 |
1 files changed, 44 insertions, 77 deletions
diff --git a/fs/xfs/xfs_dir2_sf.c b/fs/xfs/xfs_dir2_sf.c index 38fc4f22b76d..c67d73572905 100644 --- a/fs/xfs/xfs_dir2_sf.c +++ b/fs/xfs/xfs_dir2_sf.c | |||
@@ -695,19 +695,18 @@ xfs_dir2_sf_create( | |||
695 | int /* error */ | 695 | int /* error */ |
696 | xfs_dir2_sf_getdents( | 696 | xfs_dir2_sf_getdents( |
697 | xfs_inode_t *dp, /* incore directory inode */ | 697 | xfs_inode_t *dp, /* incore directory inode */ |
698 | uio_t *uio, /* caller's buffer control */ | 698 | void *dirent, |
699 | int *eofp, /* eof reached? (out) */ | 699 | xfs_off_t *offset, |
700 | xfs_dirent_t *dbp, /* caller's buffer */ | 700 | filldir_t filldir) |
701 | xfs_dir2_put_t put) /* abi's formatting function */ | ||
702 | { | 701 | { |
703 | int error; /* error return value */ | ||
704 | int i; /* shortform entry number */ | 702 | int i; /* shortform entry number */ |
705 | xfs_mount_t *mp; /* filesystem mount point */ | 703 | xfs_mount_t *mp; /* filesystem mount point */ |
706 | xfs_dir2_dataptr_t off; /* current entry's offset */ | 704 | xfs_dir2_dataptr_t off; /* current entry's offset */ |
707 | xfs_dir2_put_args_t p; /* arg package for put rtn */ | ||
708 | xfs_dir2_sf_entry_t *sfep; /* shortform directory entry */ | 705 | xfs_dir2_sf_entry_t *sfep; /* shortform directory entry */ |
709 | xfs_dir2_sf_t *sfp; /* shortform structure */ | 706 | xfs_dir2_sf_t *sfp; /* shortform structure */ |
710 | xfs_off_t dir_offset; | 707 | xfs_dir2_dataptr_t dot_offset; |
708 | xfs_dir2_dataptr_t dotdot_offset; | ||
709 | xfs_ino_t ino; | ||
711 | 710 | ||
712 | mp = dp->i_mount; | 711 | mp = dp->i_mount; |
713 | 712 | ||
@@ -720,8 +719,6 @@ xfs_dir2_sf_getdents( | |||
720 | return XFS_ERROR(EIO); | 719 | return XFS_ERROR(EIO); |
721 | } | 720 | } |
722 | 721 | ||
723 | dir_offset = uio->uio_offset; | ||
724 | |||
725 | ASSERT(dp->i_df.if_bytes == dp->i_d.di_size); | 722 | ASSERT(dp->i_df.if_bytes == dp->i_d.di_size); |
726 | ASSERT(dp->i_df.if_u1.if_data != NULL); | 723 | ASSERT(dp->i_df.if_u1.if_data != NULL); |
727 | 724 | ||
@@ -732,108 +729,78 @@ xfs_dir2_sf_getdents( | |||
732 | /* | 729 | /* |
733 | * If the block number in the offset is out of range, we're done. | 730 | * If the block number in the offset is out of range, we're done. |
734 | */ | 731 | */ |
735 | if (xfs_dir2_dataptr_to_db(mp, dir_offset) > mp->m_dirdatablk) { | 732 | if (xfs_dir2_dataptr_to_db(mp, *offset) > mp->m_dirdatablk) |
736 | *eofp = 1; | ||
737 | return 0; | 733 | return 0; |
738 | } | ||
739 | 734 | ||
740 | /* | 735 | /* |
741 | * Set up putargs structure. | 736 | * Precalculate offsets for . and .. as we will always need them. |
737 | * | ||
738 | * XXX(hch): the second argument is sometimes 0 and sometimes | ||
739 | * mp->m_dirdatablk. | ||
742 | */ | 740 | */ |
743 | p.dbp = dbp; | 741 | dot_offset = xfs_dir2_db_off_to_dataptr(mp, mp->m_dirdatablk, |
744 | p.put = put; | 742 | XFS_DIR2_DATA_DOT_OFFSET); |
745 | p.uio = uio; | 743 | dotdot_offset = xfs_dir2_db_off_to_dataptr(mp, mp->m_dirdatablk, |
744 | XFS_DIR2_DATA_DOTDOT_OFFSET); | ||
745 | |||
746 | /* | 746 | /* |
747 | * Put . entry unless we're starting past it. | 747 | * Put . entry unless we're starting past it. |
748 | */ | 748 | */ |
749 | if (dir_offset <= | 749 | if (*offset <= dot_offset) { |
750 | xfs_dir2_db_off_to_dataptr(mp, mp->m_dirdatablk, | 750 | ino = dp->i_ino; |
751 | XFS_DIR2_DATA_DOT_OFFSET)) { | ||
752 | p.cook = xfs_dir2_db_off_to_dataptr(mp, 0, | ||
753 | XFS_DIR2_DATA_DOTDOT_OFFSET); | ||
754 | p.ino = dp->i_ino; | ||
755 | #if XFS_BIG_INUMS | 751 | #if XFS_BIG_INUMS |
756 | p.ino += mp->m_inoadd; | 752 | ino += mp->m_inoadd; |
757 | #endif | 753 | #endif |
758 | p.name = "."; | 754 | if (filldir(dirent, ".", 1, dotdot_offset, ino, DT_DIR)) { |
759 | p.namelen = 1; | 755 | *offset = dot_offset; |
760 | 756 | return 0; | |
761 | error = p.put(&p); | ||
762 | |||
763 | if (!p.done) { | ||
764 | uio->uio_offset = | ||
765 | xfs_dir2_db_off_to_dataptr(mp, mp->m_dirdatablk, | ||
766 | XFS_DIR2_DATA_DOT_OFFSET); | ||
767 | return error; | ||
768 | } | 757 | } |
769 | } | 758 | } |
770 | 759 | ||
771 | /* | 760 | /* |
772 | * Put .. entry unless we're starting past it. | 761 | * Put .. entry unless we're starting past it. |
773 | */ | 762 | */ |
774 | if (dir_offset <= | 763 | if (*offset <= dotdot_offset) { |
775 | xfs_dir2_db_off_to_dataptr(mp, mp->m_dirdatablk, | 764 | off = xfs_dir2_db_off_to_dataptr(mp, mp->m_dirdatablk, |
776 | XFS_DIR2_DATA_DOTDOT_OFFSET)) { | 765 | XFS_DIR2_DATA_FIRST_OFFSET); |
777 | p.cook = xfs_dir2_db_off_to_dataptr(mp, mp->m_dirdatablk, | 766 | ino = xfs_dir2_sf_get_inumber(sfp, &sfp->hdr.parent); |
778 | XFS_DIR2_DATA_FIRST_OFFSET); | ||
779 | p.ino = xfs_dir2_sf_get_inumber(sfp, &sfp->hdr.parent); | ||
780 | #if XFS_BIG_INUMS | 767 | #if XFS_BIG_INUMS |
781 | p.ino += mp->m_inoadd; | 768 | ino += mp->m_inoadd; |
782 | #endif | 769 | #endif |
783 | p.name = ".."; | 770 | if (filldir(dirent, "..", 2, off, ino, DT_DIR)) { |
784 | p.namelen = 2; | 771 | *offset = dotdot_offset; |
785 | 772 | return 0; | |
786 | error = p.put(&p); | ||
787 | |||
788 | if (!p.done) { | ||
789 | uio->uio_offset = | ||
790 | xfs_dir2_db_off_to_dataptr(mp, mp->m_dirdatablk, | ||
791 | XFS_DIR2_DATA_DOTDOT_OFFSET); | ||
792 | return error; | ||
793 | } | 773 | } |
794 | } | 774 | } |
795 | 775 | ||
796 | /* | 776 | /* |
797 | * Loop while there are more entries and put'ing works. | 777 | * Loop while there are more entries and put'ing works. |
798 | */ | 778 | */ |
799 | for (i = 0, sfep = xfs_dir2_sf_firstentry(sfp); | 779 | sfep = xfs_dir2_sf_firstentry(sfp); |
800 | i < sfp->hdr.count; | 780 | for (i = 0; i < sfp->hdr.count; i++) { |
801 | i++, sfep = xfs_dir2_sf_nextentry(sfp, sfep)) { | ||
802 | |||
803 | off = xfs_dir2_db_off_to_dataptr(mp, mp->m_dirdatablk, | 781 | off = xfs_dir2_db_off_to_dataptr(mp, mp->m_dirdatablk, |
804 | xfs_dir2_sf_get_offset(sfep)); | 782 | xfs_dir2_sf_get_offset(sfep)); |
805 | 783 | ||
806 | if (dir_offset > off) | 784 | if (*offset > off) { |
785 | sfep = xfs_dir2_sf_nextentry(sfp, sfep); | ||
807 | continue; | 786 | continue; |
787 | } | ||
808 | 788 | ||
809 | p.namelen = sfep->namelen; | 789 | ino = xfs_dir2_sf_get_inumber(sfp, xfs_dir2_sf_inumberp(sfep)); |
810 | |||
811 | p.cook = xfs_dir2_db_off_to_dataptr(mp, mp->m_dirdatablk, | ||
812 | xfs_dir2_sf_get_offset(sfep) + | ||
813 | xfs_dir2_data_entsize(p.namelen)); | ||
814 | |||
815 | p.ino = xfs_dir2_sf_get_inumber(sfp, xfs_dir2_sf_inumberp(sfep)); | ||
816 | #if XFS_BIG_INUMS | 790 | #if XFS_BIG_INUMS |
817 | p.ino += mp->m_inoadd; | 791 | ino += mp->m_inoadd; |
818 | #endif | 792 | #endif |
819 | p.name = (char *)sfep->name; | ||
820 | |||
821 | error = p.put(&p); | ||
822 | 793 | ||
823 | if (!p.done) { | 794 | if (filldir(dirent, sfep->name, sfep->namelen, |
824 | uio->uio_offset = off; | 795 | off + xfs_dir2_data_entsize(sfep->namelen), |
825 | return error; | 796 | ino, DT_UNKNOWN)) { |
797 | *offset = off; | ||
798 | return 0; | ||
826 | } | 799 | } |
800 | sfep = xfs_dir2_sf_nextentry(sfp, sfep); | ||
827 | } | 801 | } |
828 | 802 | ||
829 | /* | 803 | *offset = xfs_dir2_db_off_to_dataptr(mp, mp->m_dirdatablk + 1, 0); |
830 | * They all fit. | ||
831 | */ | ||
832 | *eofp = 1; | ||
833 | |||
834 | uio->uio_offset = | ||
835 | xfs_dir2_db_off_to_dataptr(mp, mp->m_dirdatablk + 1, 0); | ||
836 | |||
837 | return 0; | 804 | return 0; |
838 | } | 805 | } |
839 | 806 | ||