aboutsummaryrefslogtreecommitdiffstats
path: root/fs/xfs/xfs_dir2_sf.c
diff options
context:
space:
mode:
authorChristoph Hellwig <hch@infradead.org>2007-08-27 23:58:24 -0400
committerTim Shimmin <tes@chook.melbourne.sgi.com>2007-10-15 02:49:49 -0400
commit051e7cd44ab8f0f7c2958371485b4a1ff64a8d1b (patch)
tree23389d878944e0566effed4eb2de4c1ed5fed96e /fs/xfs/xfs_dir2_sf.c
parent2bdf7cd0baa67608ada1517a281af359faf4c58c (diff)
[XFS] use filldir internally
Currently xfs has a rather complicated internal scheme to allow for different directory formats in IRIX. This patch rips all code related to this out and pushes useage of the Linux filldir callback into the lowlevel directory code. This does not make the code any less portable because filldir can be used to create dirents of all possible variations (including the IRIX ones as proved by the IRIX binary emulation code under arch/mips/). This patch get rid of an unessecary copy in the readdir path, about 400 lines of code and one of the last two users of the uio structure. This version is updated to deal with dmapi aswell which greatly simplifies the get_dirattrs code. The dmapi part has been tested using the get_dirattrs tools from the xfstest dmapi suite1 with various small and large directories. SGI-PV: 968563 SGI-Modid: xfs-linux-melb:xfs-kern:29478a Signed-off-by: Christoph Hellwig <hch@infradead.org> Signed-off-by: David Chinner <dgc@sgi.com> Signed-off-by: Tim Shimmin <tes@sgi.com>
Diffstat (limited to 'fs/xfs/xfs_dir2_sf.c')
-rw-r--r--fs/xfs/xfs_dir2_sf.c121
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(
695int /* error */ 695int /* error */
696xfs_dir2_sf_getdents( 696xfs_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