aboutsummaryrefslogtreecommitdiffstats
path: root/fs/xfs/xfs_dir2.c
diff options
context:
space:
mode:
Diffstat (limited to 'fs/xfs/xfs_dir2.c')
-rw-r--r--fs/xfs/xfs_dir2.c117
1 files changed, 15 insertions, 102 deletions
diff --git a/fs/xfs/xfs_dir2.c b/fs/xfs/xfs_dir2.c
index 29e091914df4..b0f1ee8fcb90 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,33 @@ 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,
298 xfs_inode_t *dp, 295 xfs_inode_t *dp,
299 uio_t *uio, /* caller's buffer control */ 296 void *dirent,
300 int *eofp) /* out: eof reached */ 297 size_t bufsize,
298 xfs_off_t *offset,
299 filldir_t filldir)
301{ 300{
302 int alignment; /* alignment required for ABI */
303 xfs_dirent_t *dbp; /* malloc'ed buffer */
304 xfs_dir2_put_t put; /* entry formatting routine */
305 int rval; /* return value */ 301 int rval; /* return value */
306 int v; /* type-checking value */ 302 int v; /* type-checking value */
307 303
304 vn_trace_entry(dp, __FUNCTION__, (inst_t *)__return_address);
305
306 if (XFS_FORCED_SHUTDOWN(dp->i_mount))
307 return XFS_ERROR(EIO);
308
308 ASSERT((dp->i_d.di_mode & S_IFMT) == S_IFDIR); 309 ASSERT((dp->i_d.di_mode & S_IFMT) == S_IFDIR);
309 XFS_STATS_INC(xs_dir_getdents); 310 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 311
326 *eofp = 0;
327 if (dp->i_d.di_format == XFS_DINODE_FMT_LOCAL) 312 if (dp->i_d.di_format == XFS_DINODE_FMT_LOCAL)
328 rval = xfs_dir2_sf_getdents(dp, uio, eofp, dbp, put); 313 rval = xfs_dir2_sf_getdents(dp, dirent, offset, filldir);
329 else if ((rval = xfs_dir2_isblock(tp, dp, &v))) 314 else if ((rval = xfs_dir2_isblock(NULL, dp, &v)))
330 ; 315 ;
331 else if (v) 316 else if (v)
332 rval = xfs_dir2_block_getdents(tp, dp, uio, eofp, dbp, put); 317 rval = xfs_dir2_block_getdents(dp, dirent, offset, filldir);
333 else 318 else
334 rval = xfs_dir2_leaf_getdents(tp, dp, uio, eofp, dbp, put); 319 rval = xfs_dir2_leaf_getdents(dp, dirent, bufsize, offset,
335 if (dbp != NULL) 320 filldir);
336 kmem_free(dbp, sizeof(*dbp) + MAXNAMELEN);
337 return rval; 321 return rval;
338} 322}
339 323
@@ -613,77 +597,6 @@ xfs_dir2_isleaf(
613} 597}
614 598
615/* 599/*
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. 600 * Remove the given block from the directory.
688 * This routine is used for data and free blocks, leaf/node are done 601 * This routine is used for data and free blocks, leaf/node are done
689 * by xfs_da_shrink_inode. 602 * by xfs_da_shrink_inode.