diff options
Diffstat (limited to 'fs/xfs/xfs_dir2.c')
-rw-r--r-- | fs/xfs/xfs_dir2.c | 117 |
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 | ||
46 | static int xfs_dir2_put_dirent64_direct(xfs_dir2_put_args_t *pa); | ||
47 | static int xfs_dir2_put_dirent64_uio(xfs_dir2_put_args_t *pa); | ||
48 | 46 | ||
49 | void | 47 | void |
50 | xfs_dir_mount( | 48 | xfs_dir_mount( |
@@ -293,47 +291,33 @@ xfs_dir_removename( | |||
293 | * Read a directory. | 291 | * Read a directory. |
294 | */ | 292 | */ |
295 | int | 293 | int |
296 | xfs_dir_getdents( | 294 | xfs_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 | */ | ||
618 | static int | ||
619 | xfs_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 | */ | ||
655 | static int | ||
656 | xfs_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. |