aboutsummaryrefslogtreecommitdiffstats
path: root/fs/xfs/xfs_dir2.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.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.c')
-rw-r--r--fs/xfs/xfs_dir2.c121
1 files changed, 18 insertions, 103 deletions
diff --git a/fs/xfs/xfs_dir2.c b/fs/xfs/xfs_dir2.c
index 29e091914df4..c2d2bef26cbd 100644
--- a/fs/xfs/xfs_dir2.c
+++ b/fs/xfs/xfs_dir2.c
@@ -43,8 +43,6 @@
43#include "xfs_dir2_trace.h" 43#include "xfs_dir2_trace.h"
44#include "xfs_error.h" 44#include "xfs_error.h"
45 45
46static int xfs_dir2_put_dirent64_direct(xfs_dir2_put_args_t *pa);
47static int xfs_dir2_put_dirent64_uio(xfs_dir2_put_args_t *pa);
48 46
49void 47void
50xfs_dir_mount( 48xfs_dir_mount(
@@ -293,47 +291,35 @@ xfs_dir_removename(
293 * Read a directory. 291 * Read a directory.
294 */ 292 */
295int 293int
296xfs_dir_getdents( 294xfs_readdir(
297 xfs_trans_t *tp, 295 bhv_desc_t *dir_bdp,
298 xfs_inode_t *dp, 296 void *dirent,
299 uio_t *uio, /* caller's buffer control */ 297 size_t bufsize,
300 int *eofp) /* out: eof reached */ 298 xfs_off_t *offset,
299 filldir_t filldir)
301{ 300{
302 int alignment; /* alignment required for ABI */ 301 xfs_inode_t *dp = XFS_BHVTOI(dir_bdp);
303 xfs_dirent_t *dbp; /* malloc'ed buffer */
304 xfs_dir2_put_t put; /* entry formatting routine */
305 int rval; /* return value */ 302 int rval; /* return value */
306 int v; /* type-checking value */ 303 int v; /* type-checking value */
307 304
305 vn_trace_entry(BHV_TO_VNODE(dir_bdp), __FUNCTION__,
306 (inst_t *)__return_address);
307
308 if (XFS_FORCED_SHUTDOWN(dp->i_mount))
309 return XFS_ERROR(EIO);
310
308 ASSERT((dp->i_d.di_mode & S_IFMT) == S_IFDIR); 311 ASSERT((dp->i_d.di_mode & S_IFMT) == S_IFDIR);
309 XFS_STATS_INC(xs_dir_getdents); 312 XFS_STATS_INC(xs_dir_getdents);
310 /*
311 * If our caller has given us a single contiguous aligned memory buffer,
312 * just work directly within that buffer. If it's in user memory,
313 * lock it down first.
314 */
315 alignment = sizeof(xfs_off_t) - 1;
316 if ((uio->uio_iovcnt == 1) &&
317 (((__psint_t)uio->uio_iov[0].iov_base & alignment) == 0) &&
318 ((uio->uio_iov[0].iov_len & alignment) == 0)) {
319 dbp = NULL;
320 put = xfs_dir2_put_dirent64_direct;
321 } else {
322 dbp = kmem_alloc(sizeof(*dbp) + MAXNAMELEN, KM_SLEEP);
323 put = xfs_dir2_put_dirent64_uio;
324 }
325 313
326 *eofp = 0;
327 if (dp->i_d.di_format == XFS_DINODE_FMT_LOCAL) 314 if (dp->i_d.di_format == XFS_DINODE_FMT_LOCAL)
328 rval = xfs_dir2_sf_getdents(dp, uio, eofp, dbp, put); 315 rval = xfs_dir2_sf_getdents(dp, dirent, offset, filldir);
329 else if ((rval = xfs_dir2_isblock(tp, dp, &v))) 316 else if ((rval = xfs_dir2_isblock(NULL, dp, &v)))
330 ; 317 ;
331 else if (v) 318 else if (v)
332 rval = xfs_dir2_block_getdents(tp, dp, uio, eofp, dbp, put); 319 rval = xfs_dir2_block_getdents(dp, dirent, offset, filldir);
333 else 320 else
334 rval = xfs_dir2_leaf_getdents(tp, dp, uio, eofp, dbp, put); 321 rval = xfs_dir2_leaf_getdents(dp, dirent, bufsize, offset,
335 if (dbp != NULL) 322 filldir);
336 kmem_free(dbp, sizeof(*dbp) + MAXNAMELEN);
337 return rval; 323 return rval;
338} 324}
339 325
@@ -613,77 +599,6 @@ xfs_dir2_isleaf(
613} 599}
614 600
615/* 601/*
616 * Getdents put routine for 64-bit ABI, direct form.
617 */
618static int
619xfs_dir2_put_dirent64_direct(
620 xfs_dir2_put_args_t *pa)
621{
622 xfs_dirent_t *idbp; /* dirent pointer */
623 iovec_t *iovp; /* io vector */
624 int namelen; /* entry name length */
625 int reclen; /* entry total length */
626 uio_t *uio; /* I/O control */
627
628 namelen = pa->namelen;
629 reclen = DIRENTSIZE(namelen);
630 uio = pa->uio;
631 /*
632 * Won't fit in the remaining space.
633 */
634 if (reclen > uio->uio_resid) {
635 pa->done = 0;
636 return 0;
637 }
638 iovp = uio->uio_iov;
639 idbp = (xfs_dirent_t *)iovp->iov_base;
640 iovp->iov_base = (char *)idbp + reclen;
641 iovp->iov_len -= reclen;
642 uio->uio_resid -= reclen;
643 idbp->d_reclen = reclen;
644 idbp->d_ino = pa->ino;
645 idbp->d_off = pa->cook;
646 idbp->d_name[namelen] = '\0';
647 pa->done = 1;
648 memcpy(idbp->d_name, pa->name, namelen);
649 return 0;
650}
651
652/*
653 * Getdents put routine for 64-bit ABI, uio form.
654 */
655static int
656xfs_dir2_put_dirent64_uio(
657 xfs_dir2_put_args_t *pa)
658{
659 xfs_dirent_t *idbp; /* dirent pointer */
660 int namelen; /* entry name length */
661 int reclen; /* entry total length */
662 int rval; /* return value */
663 uio_t *uio; /* I/O control */
664
665 namelen = pa->namelen;
666 reclen = DIRENTSIZE(namelen);
667 uio = pa->uio;
668 /*
669 * Won't fit in the remaining space.
670 */
671 if (reclen > uio->uio_resid) {
672 pa->done = 0;
673 return 0;
674 }
675 idbp = pa->dbp;
676 idbp->d_reclen = reclen;
677 idbp->d_ino = pa->ino;
678 idbp->d_off = pa->cook;
679 idbp->d_name[namelen] = '\0';
680 memcpy(idbp->d_name, pa->name, namelen);
681 rval = xfs_uio_read((caddr_t)idbp, reclen, uio);
682 pa->done = (rval == 0);
683 return rval;
684}
685
686/*
687 * Remove the given block from the directory. 602 * Remove the given block from the directory.
688 * This routine is used for data and free blocks, leaf/node are done 603 * This routine is used for data and free blocks, leaf/node are done
689 * by xfs_da_shrink_inode. 604 * by xfs_da_shrink_inode.