aboutsummaryrefslogtreecommitdiffstats
path: root/fs/xfs/xfs_dir2_leaf.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_leaf.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_leaf.c')
-rw-r--r--fs/xfs/xfs_dir2_leaf.c76
1 files changed, 30 insertions, 46 deletions
diff --git a/fs/xfs/xfs_dir2_leaf.c b/fs/xfs/xfs_dir2_leaf.c
index 1b73c9ad646a..e7c12fa1303e 100644
--- a/fs/xfs/xfs_dir2_leaf.c
+++ b/fs/xfs/xfs_dir2_leaf.c
@@ -749,12 +749,11 @@ xfs_dir2_leaf_compact_x1(
749 */ 749 */
750int /* error */ 750int /* error */
751xfs_dir2_leaf_getdents( 751xfs_dir2_leaf_getdents(
752 xfs_trans_t *tp, /* transaction pointer */
753 xfs_inode_t *dp, /* incore directory inode */ 752 xfs_inode_t *dp, /* incore directory inode */
754 uio_t *uio, /* I/O control & vectors */ 753 void *dirent,
755 int *eofp, /* out: reached end of dir */ 754 size_t bufsize,
756 xfs_dirent_t *dbp, /* caller's buffer */ 755 xfs_off_t *offset,
757 xfs_dir2_put_t put) /* ABI formatting routine */ 756 filldir_t filldir)
758{ 757{
759 xfs_dabuf_t *bp; /* data block buffer */ 758 xfs_dabuf_t *bp; /* data block buffer */
760 int byteoff; /* offset in current block */ 759 int byteoff; /* offset in current block */
@@ -763,7 +762,6 @@ xfs_dir2_leaf_getdents(
763 xfs_dir2_data_t *data; /* data block structure */ 762 xfs_dir2_data_t *data; /* data block structure */
764 xfs_dir2_data_entry_t *dep; /* data entry */ 763 xfs_dir2_data_entry_t *dep; /* data entry */
765 xfs_dir2_data_unused_t *dup; /* unused entry */ 764 xfs_dir2_data_unused_t *dup; /* unused entry */
766 int eof; /* reached end of directory */
767 int error = 0; /* error return value */ 765 int error = 0; /* error return value */
768 int i; /* temporary loop index */ 766 int i; /* temporary loop index */
769 int j; /* temporary loop index */ 767 int j; /* temporary loop index */
@@ -776,46 +774,38 @@ xfs_dir2_leaf_getdents(
776 xfs_mount_t *mp; /* filesystem mount point */ 774 xfs_mount_t *mp; /* filesystem mount point */
777 xfs_dir2_off_t newoff; /* new curoff after new blk */ 775 xfs_dir2_off_t newoff; /* new curoff after new blk */
778 int nmap; /* mappings to ask xfs_bmapi */ 776 int nmap; /* mappings to ask xfs_bmapi */
779 xfs_dir2_put_args_t *p; /* formatting arg bundle */
780 char *ptr = NULL; /* pointer to current data */ 777 char *ptr = NULL; /* pointer to current data */
781 int ra_current; /* number of read-ahead blks */ 778 int ra_current; /* number of read-ahead blks */
782 int ra_index; /* *map index for read-ahead */ 779 int ra_index; /* *map index for read-ahead */
783 int ra_offset; /* map entry offset for ra */ 780 int ra_offset; /* map entry offset for ra */
784 int ra_want; /* readahead count wanted */ 781 int ra_want; /* readahead count wanted */
782 xfs_ino_t ino;
785 783
786 /* 784 /*
787 * If the offset is at or past the largest allowed value, 785 * If the offset is at or past the largest allowed value,
788 * give up right away, return eof. 786 * give up right away.
789 */ 787 */
790 if (uio->uio_offset >= XFS_DIR2_MAX_DATAPTR) { 788 if (*offset >= XFS_DIR2_MAX_DATAPTR)
791 *eofp = 1;
792 return 0; 789 return 0;
793 } 790
794 mp = dp->i_mount; 791 mp = dp->i_mount;
795 /* 792
796 * Setup formatting arguments.
797 */
798 p = kmem_alloc(sizeof(*p), KM_SLEEP);
799 p->dbp = dbp;
800 p->put = put;
801 p->uio = uio;
802 /* 793 /*
803 * Set up to bmap a number of blocks based on the caller's 794 * Set up to bmap a number of blocks based on the caller's
804 * buffer size, the directory block size, and the filesystem 795 * buffer size, the directory block size, and the filesystem
805 * block size. 796 * block size.
806 */ 797 */
807 map_size = 798 map_size = howmany(bufsize + mp->m_dirblksize, mp->m_sb.sb_blocksize);
808 howmany(uio->uio_resid + mp->m_dirblksize,
809 mp->m_sb.sb_blocksize);
810 map = kmem_alloc(map_size * sizeof(*map), KM_SLEEP); 799 map = kmem_alloc(map_size * sizeof(*map), KM_SLEEP);
811 map_valid = ra_index = ra_offset = ra_current = map_blocks = 0; 800 map_valid = ra_index = ra_offset = ra_current = map_blocks = 0;
812 bp = NULL; 801 bp = NULL;
813 eof = 1; 802
814 /* 803 /*
815 * Inside the loop we keep the main offset value as a byte offset 804 * Inside the loop we keep the main offset value as a byte offset
816 * in the directory file. 805 * in the directory file.
817 */ 806 */
818 curoff = xfs_dir2_dataptr_to_byte(mp, uio->uio_offset); 807 curoff = xfs_dir2_dataptr_to_byte(mp, *offset);
808
819 /* 809 /*
820 * Force this conversion through db so we truncate the offset 810 * Force this conversion through db so we truncate the offset
821 * down to get the start of the data block. 811 * down to get the start of the data block.
@@ -836,7 +826,7 @@ xfs_dir2_leaf_getdents(
836 * take it out of the mapping. 826 * take it out of the mapping.
837 */ 827 */
838 if (bp) { 828 if (bp) {
839 xfs_da_brelse(tp, bp); 829 xfs_da_brelse(NULL, bp);
840 bp = NULL; 830 bp = NULL;
841 map_blocks -= mp->m_dirblkfsbs; 831 map_blocks -= mp->m_dirblkfsbs;
842 /* 832 /*
@@ -862,8 +852,9 @@ xfs_dir2_leaf_getdents(
862 /* 852 /*
863 * Recalculate the readahead blocks wanted. 853 * Recalculate the readahead blocks wanted.
864 */ 854 */
865 ra_want = howmany(uio->uio_resid + mp->m_dirblksize, 855 ra_want = howmany(bufsize + mp->m_dirblksize,
866 mp->m_sb.sb_blocksize) - 1; 856 mp->m_sb.sb_blocksize) - 1;
857
867 /* 858 /*
868 * If we don't have as many as we want, and we haven't 859 * If we don't have as many as we want, and we haven't
869 * run out of data blocks, get some more mappings. 860 * run out of data blocks, get some more mappings.
@@ -876,7 +867,7 @@ xfs_dir2_leaf_getdents(
876 * we already have in the table. 867 * we already have in the table.
877 */ 868 */
878 nmap = map_size - map_valid; 869 nmap = map_size - map_valid;
879 error = xfs_bmapi(tp, dp, 870 error = xfs_bmapi(NULL, dp,
880 map_off, 871 map_off,
881 xfs_dir2_byte_to_da(mp, 872 xfs_dir2_byte_to_da(mp,
882 XFS_DIR2_LEAF_OFFSET) - map_off, 873 XFS_DIR2_LEAF_OFFSET) - map_off,
@@ -939,7 +930,7 @@ xfs_dir2_leaf_getdents(
939 * mapping. 930 * mapping.
940 */ 931 */
941 curdb = xfs_dir2_da_to_db(mp, map->br_startoff); 932 curdb = xfs_dir2_da_to_db(mp, map->br_startoff);
942 error = xfs_da_read_buf(tp, dp, map->br_startoff, 933 error = xfs_da_read_buf(NULL, dp, map->br_startoff,
943 map->br_blockcount >= mp->m_dirblkfsbs ? 934 map->br_blockcount >= mp->m_dirblkfsbs ?
944 XFS_FSB_TO_DADDR(mp, map->br_startblock) : 935 XFS_FSB_TO_DADDR(mp, map->br_startblock) :
945 -1, 936 -1,
@@ -982,7 +973,7 @@ xfs_dir2_leaf_getdents(
982 * is a very rare case. 973 * is a very rare case.
983 */ 974 */
984 else if (i > ra_current) { 975 else if (i > ra_current) {
985 (void)xfs_da_reada_buf(tp, dp, 976 (void)xfs_da_reada_buf(NULL, dp,
986 map[ra_index].br_startoff + 977 map[ra_index].br_startoff +
987 ra_offset, XFS_DATA_FORK); 978 ra_offset, XFS_DATA_FORK);
988 ra_current = i; 979 ra_current = i;
@@ -1089,46 +1080,39 @@ xfs_dir2_leaf_getdents(
1089 */ 1080 */
1090 dep = (xfs_dir2_data_entry_t *)ptr; 1081 dep = (xfs_dir2_data_entry_t *)ptr;
1091 1082
1092 p->namelen = dep->namelen; 1083 length = xfs_dir2_data_entsize(dep->namelen);
1093
1094 length = xfs_dir2_data_entsize(p->namelen);
1095
1096 p->cook = xfs_dir2_byte_to_dataptr(mp, curoff + length);
1097 1084
1098 p->ino = be64_to_cpu(dep->inumber); 1085 ino = be64_to_cpu(dep->inumber);
1099#if XFS_BIG_INUMS 1086#if XFS_BIG_INUMS
1100 p->ino += mp->m_inoadd; 1087 ino += mp->m_inoadd;
1101#endif 1088#endif
1102 p->name = (char *)dep->name;
1103
1104 error = p->put(p);
1105 1089
1106 /* 1090 /*
1107 * Won't fit. Return to caller. 1091 * Won't fit. Return to caller.
1108 */ 1092 */
1109 if (!p->done) { 1093 if (filldir(dirent, dep->name, dep->namelen,
1110 eof = 0; 1094 xfs_dir2_byte_to_dataptr(mp, curoff + length),
1095 ino, DT_UNKNOWN))
1111 break; 1096 break;
1112 } 1097
1113 /* 1098 /*
1114 * Advance to next entry in the block. 1099 * Advance to next entry in the block.
1115 */ 1100 */
1116 ptr += length; 1101 ptr += length;
1117 curoff += length; 1102 curoff += length;
1103 bufsize -= length;
1118 } 1104 }
1119 1105
1120 /* 1106 /*
1121 * All done. Set output offset value to current offset. 1107 * All done. Set output offset value to current offset.
1122 */ 1108 */
1123 *eofp = eof;
1124 if (curoff > xfs_dir2_dataptr_to_byte(mp, XFS_DIR2_MAX_DATAPTR)) 1109 if (curoff > xfs_dir2_dataptr_to_byte(mp, XFS_DIR2_MAX_DATAPTR))
1125 uio->uio_offset = XFS_DIR2_MAX_DATAPTR; 1110 *offset = XFS_DIR2_MAX_DATAPTR;
1126 else 1111 else
1127 uio->uio_offset = xfs_dir2_byte_to_dataptr(mp, curoff); 1112 *offset = xfs_dir2_byte_to_dataptr(mp, curoff);
1128 kmem_free(map, map_size * sizeof(*map)); 1113 kmem_free(map, map_size * sizeof(*map));
1129 kmem_free(p, sizeof(*p));
1130 if (bp) 1114 if (bp)
1131 xfs_da_brelse(tp, bp); 1115 xfs_da_brelse(NULL, bp);
1132 return error; 1116 return error;
1133} 1117}
1134 1118