aboutsummaryrefslogtreecommitdiffstats
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
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>
-rw-r--r--fs/xfs/linux-2.6/xfs_file.c90
-rw-r--r--fs/xfs/linux-2.6/xfs_vnode.h8
-rw-r--r--fs/xfs/xfs_dir2.c121
-rw-r--r--fs/xfs/xfs_dir2.h19
-rw-r--r--fs/xfs/xfs_dir2_block.c63
-rw-r--r--fs/xfs/xfs_dir2_block.h5
-rw-r--r--fs/xfs/xfs_dir2_leaf.c76
-rw-r--r--fs/xfs/xfs_dir2_leaf.h6
-rw-r--r--fs/xfs/xfs_dir2_sf.c121
-rw-r--r--fs/xfs/xfs_dir2_sf.h5
-rw-r--r--fs/xfs/xfs_types.h12
-rw-r--r--fs/xfs/xfs_vnodeops.c31
12 files changed, 151 insertions, 406 deletions
diff --git a/fs/xfs/linux-2.6/xfs_file.c b/fs/xfs/linux-2.6/xfs_file.c
index 4fc0f58edacf..3678f6912d04 100644
--- a/fs/xfs/linux-2.6/xfs_file.c
+++ b/fs/xfs/linux-2.6/xfs_file.c
@@ -233,74 +233,30 @@ xfs_file_readdir(
233 void *dirent, 233 void *dirent,
234 filldir_t filldir) 234 filldir_t filldir)
235{ 235{
236 int error = 0; 236 struct inode *inode = filp->f_path.dentry->d_inode;
237 bhv_vnode_t *vp = vn_from_inode(filp->f_path.dentry->d_inode); 237 bhv_vnode_t *vp = vn_from_inode(inode);
238 uio_t uio; 238 int error;
239 iovec_t iov; 239 size_t bufsize;
240 int eof = 0; 240
241 caddr_t read_buf; 241 /*
242 int namelen, size = 0; 242 * The Linux API doesn't pass down the total size of the buffer
243 size_t rlen = PAGE_CACHE_SIZE; 243 * we read into down to the filesystem. With the filldir concept
244 xfs_off_t start_offset, curr_offset; 244 * it's not needed for correct information, but the XFS dir2 leaf
245 xfs_dirent_t *dbp = NULL; 245 * code wants an estimate of the buffer size to calculate it's
246 246 * readahead window and size the buffers used for mapping to
247 /* Try fairly hard to get memory */ 247 * physical blocks.
248 do { 248 *
249 if ((read_buf = kmalloc(rlen, GFP_KERNEL))) 249 * Try to give it an estimate that's good enough, maybe at some
250 break; 250 * point we can change the ->readdir prototype to include the
251 rlen >>= 1; 251 * buffer size.
252 } while (rlen >= 1024); 252 */
253 253 bufsize = (size_t)min_t(loff_t, PAGE_SIZE, inode->i_size);
254 if (read_buf == NULL)
255 return -ENOMEM;
256
257 uio.uio_iov = &iov;
258 uio.uio_segflg = UIO_SYSSPACE;
259 curr_offset = filp->f_pos;
260 if (filp->f_pos != 0x7fffffff)
261 uio.uio_offset = filp->f_pos;
262 else
263 uio.uio_offset = 0xffffffff;
264
265 while (!eof) {
266 uio.uio_resid = iov.iov_len = rlen;
267 iov.iov_base = read_buf;
268 uio.uio_iovcnt = 1;
269
270 start_offset = uio.uio_offset;
271
272 error = bhv_vop_readdir(vp, &uio, NULL, &eof);
273 if ((uio.uio_offset == start_offset) || error) {
274 size = 0;
275 break;
276 }
277
278 size = rlen - uio.uio_resid;
279 dbp = (xfs_dirent_t *)read_buf;
280 while (size > 0) {
281 namelen = strlen(dbp->d_name);
282
283 if (filldir(dirent, dbp->d_name, namelen,
284 (loff_t) curr_offset & 0x7fffffff,
285 (ino_t) dbp->d_ino,
286 DT_UNKNOWN)) {
287 goto done;
288 }
289 size -= dbp->d_reclen;
290 curr_offset = (loff_t)dbp->d_off /* & 0x7fffffff */;
291 dbp = (xfs_dirent_t *)((char *)dbp + dbp->d_reclen);
292 }
293 }
294done:
295 if (!error) {
296 if (size == 0)
297 filp->f_pos = uio.uio_offset & 0x7fffffff;
298 else if (dbp)
299 filp->f_pos = curr_offset;
300 }
301 254
302 kfree(read_buf); 255 error = bhv_vop_readdir(vp, dirent, bufsize,
303 return -error; 256 (xfs_off_t *)&filp->f_pos, filldir);
257 if (error)
258 return -error;
259 return 0;
304} 260}
305 261
306STATIC int 262STATIC int
diff --git a/fs/xfs/linux-2.6/xfs_vnode.h b/fs/xfs/linux-2.6/xfs_vnode.h
index 5742d65f0785..146c84ba6941 100644
--- a/fs/xfs/linux-2.6/xfs_vnode.h
+++ b/fs/xfs/linux-2.6/xfs_vnode.h
@@ -161,8 +161,8 @@ typedef int (*vop_rename_t)(bhv_desc_t *, bhv_vname_t *, bhv_vnode_t *,
161typedef int (*vop_mkdir_t)(bhv_desc_t *, bhv_vname_t *, struct bhv_vattr *, 161typedef int (*vop_mkdir_t)(bhv_desc_t *, bhv_vname_t *, struct bhv_vattr *,
162 bhv_vnode_t **, struct cred *); 162 bhv_vnode_t **, struct cred *);
163typedef int (*vop_rmdir_t)(bhv_desc_t *, bhv_vname_t *, struct cred *); 163typedef int (*vop_rmdir_t)(bhv_desc_t *, bhv_vname_t *, struct cred *);
164typedef int (*vop_readdir_t)(bhv_desc_t *, struct uio *, struct cred *, 164typedef int (*vop_readdir_t)(bhv_desc_t *, void *dirent, size_t bufsize,
165 int *); 165 xfs_off_t *offset, filldir_t filldir);
166typedef int (*vop_symlink_t)(bhv_desc_t *, bhv_vname_t *, struct bhv_vattr*, 166typedef int (*vop_symlink_t)(bhv_desc_t *, bhv_vname_t *, struct bhv_vattr*,
167 char *, bhv_vnode_t **, struct cred *); 167 char *, bhv_vnode_t **, struct cred *);
168typedef int (*vop_readlink_t)(bhv_desc_t *, struct uio *, int, 168typedef int (*vop_readlink_t)(bhv_desc_t *, struct uio *, int,
@@ -267,8 +267,8 @@ typedef struct bhv_vnodeops {
267#define bhv_vop_mkdir(dp,d,vap,vpp,cr) \ 267#define bhv_vop_mkdir(dp,d,vap,vpp,cr) \
268 VOP(vop_mkdir, dp)(VNHEAD(dp),d,vap,vpp,cr) 268 VOP(vop_mkdir, dp)(VNHEAD(dp),d,vap,vpp,cr)
269#define bhv_vop_rmdir(dp,d,cr) VOP(vop_rmdir, dp)(VNHEAD(dp),d,cr) 269#define bhv_vop_rmdir(dp,d,cr) VOP(vop_rmdir, dp)(VNHEAD(dp),d,cr)
270#define bhv_vop_readdir(vp,uiop,cr,eofp) \ 270#define bhv_vop_readdir(vp,dirent,bufsize,offset,filldir) \
271 VOP(vop_readdir, vp)(VNHEAD(vp),uiop,cr,eofp) 271 VOP(vop_readdir, vp)(VNHEAD(vp),dirent,bufsize,offset,filldir)
272#define bhv_vop_symlink(dvp,d,vap,tnm,vpp,cr) \ 272#define bhv_vop_symlink(dvp,d,vap,tnm,vpp,cr) \
273 VOP(vop_symlink, dvp)(VNHEAD(dvp),d,vap,tnm,vpp,cr) 273 VOP(vop_symlink, dvp)(VNHEAD(dvp),d,vap,tnm,vpp,cr)
274#define bhv_vop_readlink(vp,uiop,fl,cr) \ 274#define bhv_vop_readlink(vp,uiop,fl,cr) \
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.
diff --git a/fs/xfs/xfs_dir2.h b/fs/xfs/xfs_dir2.h
index 86560b6f794c..fa5a533a3427 100644
--- a/fs/xfs/xfs_dir2.h
+++ b/fs/xfs/xfs_dir2.h
@@ -60,21 +60,6 @@ typedef __uint32_t xfs_dir2_db_t;
60typedef xfs_off_t xfs_dir2_off_t; 60typedef xfs_off_t xfs_dir2_off_t;
61 61
62/* 62/*
63 * For getdents, argument struct for put routines.
64 */
65typedef int (*xfs_dir2_put_t)(struct xfs_dir2_put_args *pa);
66typedef struct xfs_dir2_put_args {
67 xfs_off_t cook; /* cookie of (next) entry */
68 xfs_intino_t ino; /* inode number */
69 xfs_dirent_t *dbp; /* buffer pointer */
70 char *name; /* directory entry name */
71 int namelen; /* length of name */
72 int done; /* output: set if value was stored */
73 xfs_dir2_put_t put; /* put function ptr (i/o) */
74 struct uio *uio; /* uio control structure */
75} xfs_dir2_put_args_t;
76
77/*
78 * Generic directory interface routines 63 * Generic directory interface routines
79 */ 64 */
80extern void xfs_dir_startup(void); 65extern void xfs_dir_startup(void);
@@ -92,8 +77,6 @@ extern int xfs_dir_removename(struct xfs_trans *tp, struct xfs_inode *dp,
92 char *name, int namelen, xfs_ino_t ino, 77 char *name, int namelen, xfs_ino_t ino,
93 xfs_fsblock_t *first, 78 xfs_fsblock_t *first,
94 struct xfs_bmap_free *flist, xfs_extlen_t tot); 79 struct xfs_bmap_free *flist, xfs_extlen_t tot);
95extern int xfs_dir_getdents(struct xfs_trans *tp, struct xfs_inode *dp,
96 uio_t *uio, int *eofp);
97extern int xfs_dir_replace(struct xfs_trans *tp, struct xfs_inode *dp, 80extern int xfs_dir_replace(struct xfs_trans *tp, struct xfs_inode *dp,
98 char *name, int namelen, xfs_ino_t inum, 81 char *name, int namelen, xfs_ino_t inum,
99 xfs_fsblock_t *first, 82 xfs_fsblock_t *first,
@@ -101,6 +84,8 @@ extern int xfs_dir_replace(struct xfs_trans *tp, struct xfs_inode *dp,
101extern int xfs_dir_canenter(struct xfs_trans *tp, struct xfs_inode *dp, 84extern int xfs_dir_canenter(struct xfs_trans *tp, struct xfs_inode *dp,
102 char *name, int namelen); 85 char *name, int namelen);
103extern int xfs_dir_ino_validate(struct xfs_mount *mp, xfs_ino_t ino); 86extern int xfs_dir_ino_validate(struct xfs_mount *mp, xfs_ino_t ino);
87extern int xfs_readdir(bhv_desc_t *dir_bdp, void *dirent, size_t bufsize,
88 xfs_off_t *offset, filldir_t filldir);
104 89
105/* 90/*
106 * Utility routines for v2 directories. 91 * Utility routines for v2 directories.
diff --git a/fs/xfs/xfs_dir2_block.c b/fs/xfs/xfs_dir2_block.c
index e4df1aaae2a2..f6b919af7b82 100644
--- a/fs/xfs/xfs_dir2_block.c
+++ b/fs/xfs/xfs_dir2_block.c
@@ -432,12 +432,10 @@ xfs_dir2_block_addname(
432 */ 432 */
433int /* error */ 433int /* error */
434xfs_dir2_block_getdents( 434xfs_dir2_block_getdents(
435 xfs_trans_t *tp, /* transaction (NULL) */
436 xfs_inode_t *dp, /* incore inode */ 435 xfs_inode_t *dp, /* incore inode */
437 uio_t *uio, /* caller's buffer control */ 436 void *dirent,
438 int *eofp, /* eof reached? (out) */ 437 xfs_off_t *offset,
439 xfs_dirent_t *dbp, /* caller's buffer */ 438 filldir_t filldir)
440 xfs_dir2_put_t put) /* abi's formatting function */
441{ 439{
442 xfs_dir2_block_t *block; /* directory block structure */ 440 xfs_dir2_block_t *block; /* directory block structure */
443 xfs_dabuf_t *bp; /* buffer for block */ 441 xfs_dabuf_t *bp; /* buffer for block */
@@ -447,31 +445,32 @@ xfs_dir2_block_getdents(
447 char *endptr; /* end of the data entries */ 445 char *endptr; /* end of the data entries */
448 int error; /* error return value */ 446 int error; /* error return value */
449 xfs_mount_t *mp; /* filesystem mount point */ 447 xfs_mount_t *mp; /* filesystem mount point */
450 xfs_dir2_put_args_t p; /* arg package for put rtn */
451 char *ptr; /* current data entry */ 448 char *ptr; /* current data entry */
452 int wantoff; /* starting block offset */ 449 int wantoff; /* starting block offset */
450 xfs_ino_t ino;
451 xfs_off_t cook;
453 452
454 mp = dp->i_mount; 453 mp = dp->i_mount;
455 /* 454 /*
456 * If the block number in the offset is out of range, we're done. 455 * If the block number in the offset is out of range, we're done.
457 */ 456 */
458 if (xfs_dir2_dataptr_to_db(mp, uio->uio_offset) > mp->m_dirdatablk) { 457 if (xfs_dir2_dataptr_to_db(mp, *offset) > mp->m_dirdatablk) {
459 *eofp = 1;
460 return 0; 458 return 0;
461 } 459 }
462 /* 460 /*
463 * Can't read the block, give up, else get dabuf in bp. 461 * Can't read the block, give up, else get dabuf in bp.
464 */ 462 */
465 if ((error = 463 error = xfs_da_read_buf(NULL, dp, mp->m_dirdatablk, -1,
466 xfs_da_read_buf(tp, dp, mp->m_dirdatablk, -1, &bp, XFS_DATA_FORK))) { 464 &bp, XFS_DATA_FORK);
465 if (error)
467 return error; 466 return error;
468 } 467
469 ASSERT(bp != NULL); 468 ASSERT(bp != NULL);
470 /* 469 /*
471 * Extract the byte offset we start at from the seek pointer. 470 * Extract the byte offset we start at from the seek pointer.
472 * We'll skip entries before this. 471 * We'll skip entries before this.
473 */ 472 */
474 wantoff = xfs_dir2_dataptr_to_off(mp, uio->uio_offset); 473 wantoff = xfs_dir2_dataptr_to_off(mp, *offset);
475 block = bp->data; 474 block = bp->data;
476 xfs_dir2_data_check(dp, bp); 475 xfs_dir2_data_check(dp, bp);
477 /* 476 /*
@@ -480,9 +479,7 @@ xfs_dir2_block_getdents(
480 btp = xfs_dir2_block_tail_p(mp, block); 479 btp = xfs_dir2_block_tail_p(mp, block);
481 ptr = (char *)block->u; 480 ptr = (char *)block->u;
482 endptr = (char *)xfs_dir2_block_leaf_p(btp); 481 endptr = (char *)xfs_dir2_block_leaf_p(btp);
483 p.dbp = dbp; 482
484 p.put = put;
485 p.uio = uio;
486 /* 483 /*
487 * Loop over the data portion of the block. 484 * Loop over the data portion of the block.
488 * Each object is a real entry (dep) or an unused one (dup). 485 * Each object is a real entry (dep) or an unused one (dup).
@@ -508,33 +505,24 @@ xfs_dir2_block_getdents(
508 */ 505 */
509 if ((char *)dep - (char *)block < wantoff) 506 if ((char *)dep - (char *)block < wantoff)
510 continue; 507 continue;
511 /*
512 * Set up argument structure for put routine.
513 */
514 p.namelen = dep->namelen;
515 508
516 p.cook = xfs_dir2_db_off_to_dataptr(mp, mp->m_dirdatablk, 509 cook = xfs_dir2_db_off_to_dataptr(mp, mp->m_dirdatablk,
517 ptr - (char *)block); 510 ptr - (char *)block);
518 p.ino = be64_to_cpu(dep->inumber); 511 ino = be64_to_cpu(dep->inumber);
519#if XFS_BIG_INUMS 512#if XFS_BIG_INUMS
520 p.ino += mp->m_inoadd; 513 ino += mp->m_inoadd;
521#endif 514#endif
522 p.name = (char *)dep->name;
523
524 /*
525 * Put the entry in the caller's buffer.
526 */
527 error = p.put(&p);
528 515
529 /* 516 /*
530 * If it didn't fit, set the final offset to here & return. 517 * If it didn't fit, set the final offset to here & return.
531 */ 518 */
532 if (!p.done) { 519 if (filldir(dirent, dep->name, dep->namelen, cook,
533 uio->uio_offset = 520 ino, DT_UNKNOWN)) {
534 xfs_dir2_db_off_to_dataptr(mp, mp->m_dirdatablk, 521 *offset = xfs_dir2_db_off_to_dataptr(mp,
522 mp->m_dirdatablk,
535 (char *)dep - (char *)block); 523 (char *)dep - (char *)block);
536 xfs_da_brelse(tp, bp); 524 xfs_da_brelse(NULL, bp);
537 return error; 525 return 0;
538 } 526 }
539 } 527 }
540 528
@@ -542,13 +530,8 @@ xfs_dir2_block_getdents(
542 * Reached the end of the block. 530 * Reached the end of the block.
543 * Set the offset to a non-existent block 1 and return. 531 * Set the offset to a non-existent block 1 and return.
544 */ 532 */
545 *eofp = 1; 533 *offset = xfs_dir2_db_off_to_dataptr(mp, mp->m_dirdatablk + 1, 0);
546 534 xfs_da_brelse(NULL, bp);
547 uio->uio_offset =
548 xfs_dir2_db_off_to_dataptr(mp, mp->m_dirdatablk + 1, 0);
549
550 xfs_da_brelse(tp, bp);
551
552 return 0; 535 return 0;
553} 536}
554 537
diff --git a/fs/xfs/xfs_dir2_block.h b/fs/xfs/xfs_dir2_block.h
index e7c2606161e9..10e689676382 100644
--- a/fs/xfs/xfs_dir2_block.h
+++ b/fs/xfs/xfs_dir2_block.h
@@ -80,9 +80,8 @@ xfs_dir2_block_leaf_p(xfs_dir2_block_tail_t *btp)
80 * Function declarations. 80 * Function declarations.
81 */ 81 */
82extern int xfs_dir2_block_addname(struct xfs_da_args *args); 82extern int xfs_dir2_block_addname(struct xfs_da_args *args);
83extern int xfs_dir2_block_getdents(struct xfs_trans *tp, struct xfs_inode *dp, 83extern int xfs_dir2_block_getdents(struct xfs_inode *dp, void *dirent,
84 struct uio *uio, int *eofp, 84 xfs_off_t *offset, filldir_t filldir);
85 struct xfs_dirent *dbp, xfs_dir2_put_t put);
86extern int xfs_dir2_block_lookup(struct xfs_da_args *args); 85extern int xfs_dir2_block_lookup(struct xfs_da_args *args);
87extern int xfs_dir2_block_removename(struct xfs_da_args *args); 86extern int xfs_dir2_block_removename(struct xfs_da_args *args);
88extern int xfs_dir2_block_replace(struct xfs_da_args *args); 87extern int xfs_dir2_block_replace(struct xfs_da_args *args);
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
diff --git a/fs/xfs/xfs_dir2_leaf.h b/fs/xfs/xfs_dir2_leaf.h
index 70c97f3f815e..6c9539f06987 100644
--- a/fs/xfs/xfs_dir2_leaf.h
+++ b/fs/xfs/xfs_dir2_leaf.h
@@ -232,9 +232,9 @@ extern void xfs_dir2_leaf_compact(struct xfs_da_args *args,
232extern void xfs_dir2_leaf_compact_x1(struct xfs_dabuf *bp, int *indexp, 232extern void xfs_dir2_leaf_compact_x1(struct xfs_dabuf *bp, int *indexp,
233 int *lowstalep, int *highstalep, 233 int *lowstalep, int *highstalep,
234 int *lowlogp, int *highlogp); 234 int *lowlogp, int *highlogp);
235extern int xfs_dir2_leaf_getdents(struct xfs_trans *tp, struct xfs_inode *dp, 235extern int xfs_dir2_leaf_getdents(struct xfs_inode *dp, void *dirent,
236 struct uio *uio, int *eofp, 236 size_t bufsize, xfs_off_t *offset,
237 struct xfs_dirent *dbp, xfs_dir2_put_t put); 237 filldir_t filldir);
238extern int xfs_dir2_leaf_init(struct xfs_da_args *args, xfs_dir2_db_t bno, 238extern int xfs_dir2_leaf_init(struct xfs_da_args *args, xfs_dir2_db_t bno,
239 struct xfs_dabuf **bpp, int magic); 239 struct xfs_dabuf **bpp, int magic);
240extern void xfs_dir2_leaf_log_ents(struct xfs_trans *tp, struct xfs_dabuf *bp, 240extern void xfs_dir2_leaf_log_ents(struct xfs_trans *tp, struct xfs_dabuf *bp,
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
diff --git a/fs/xfs/xfs_dir2_sf.h b/fs/xfs/xfs_dir2_sf.h
index 11e503209afa..005629d702d2 100644
--- a/fs/xfs/xfs_dir2_sf.h
+++ b/fs/xfs/xfs_dir2_sf.h
@@ -169,9 +169,8 @@ extern int xfs_dir2_block_to_sf(struct xfs_da_args *args, struct xfs_dabuf *bp,
169 int size, xfs_dir2_sf_hdr_t *sfhp); 169 int size, xfs_dir2_sf_hdr_t *sfhp);
170extern int xfs_dir2_sf_addname(struct xfs_da_args *args); 170extern int xfs_dir2_sf_addname(struct xfs_da_args *args);
171extern int xfs_dir2_sf_create(struct xfs_da_args *args, xfs_ino_t pino); 171extern int xfs_dir2_sf_create(struct xfs_da_args *args, xfs_ino_t pino);
172extern int xfs_dir2_sf_getdents(struct xfs_inode *dp, struct uio *uio, 172extern int xfs_dir2_sf_getdents(struct xfs_inode *dp, void *dirent,
173 int *eofp, struct xfs_dirent *dbp, 173 xfs_off_t *offset, filldir_t filldir);
174 xfs_dir2_put_t put);
175extern int xfs_dir2_sf_lookup(struct xfs_da_args *args); 174extern int xfs_dir2_sf_lookup(struct xfs_da_args *args);
176extern int xfs_dir2_sf_removename(struct xfs_da_args *args); 175extern int xfs_dir2_sf_removename(struct xfs_da_args *args);
177extern int xfs_dir2_sf_replace(struct xfs_da_args *args); 176extern int xfs_dir2_sf_replace(struct xfs_da_args *args);
diff --git a/fs/xfs/xfs_types.h b/fs/xfs/xfs_types.h
index 104f64a98790..5c89be475464 100644
--- a/fs/xfs/xfs_types.h
+++ b/fs/xfs/xfs_types.h
@@ -151,18 +151,6 @@ typedef __uint8_t xfs_arch_t; /* architecture of an xfs fs */
151 */ 151 */
152#define MAXNAMELEN 256 152#define MAXNAMELEN 256
153 153
154typedef struct xfs_dirent { /* data from readdir() */
155 xfs_ino_t d_ino; /* inode number of entry */
156 xfs_off_t d_off; /* offset of disk directory entry */
157 unsigned short d_reclen; /* length of this record */
158 char d_name[1]; /* name of file */
159} xfs_dirent_t;
160
161#define DIRENTBASESIZE (((xfs_dirent_t *)0)->d_name - (char *)0)
162#define DIRENTSIZE(namelen) \
163 ((DIRENTBASESIZE + (namelen) + \
164 sizeof(xfs_off_t)) & ~(sizeof(xfs_off_t) - 1))
165
166typedef enum { 154typedef enum {
167 XFS_LOOKUP_EQi, XFS_LOOKUP_LEi, XFS_LOOKUP_GEi 155 XFS_LOOKUP_EQi, XFS_LOOKUP_LEi, XFS_LOOKUP_GEi
168} xfs_lookup_t; 156} xfs_lookup_t;
diff --git a/fs/xfs/xfs_vnodeops.c b/fs/xfs/xfs_vnodeops.c
index 0116ce1ad59e..36318c66a7bf 100644
--- a/fs/xfs/xfs_vnodeops.c
+++ b/fs/xfs/xfs_vnodeops.c
@@ -3284,37 +3284,6 @@ xfs_rmdir(
3284 goto std_return; 3284 goto std_return;
3285} 3285}
3286 3286
3287
3288/*
3289 * Read dp's entries starting at uiop->uio_offset and translate them into
3290 * bufsize bytes worth of struct dirents starting at bufbase.
3291 */
3292STATIC int
3293xfs_readdir(
3294 bhv_desc_t *dir_bdp,
3295 uio_t *uiop,
3296 cred_t *credp,
3297 int *eofp)
3298{
3299 xfs_inode_t *dp;
3300 xfs_trans_t *tp = NULL;
3301 int error = 0;
3302 uint lock_mode;
3303
3304 vn_trace_entry(BHV_TO_VNODE(dir_bdp), __FUNCTION__,
3305 (inst_t *)__return_address);
3306 dp = XFS_BHVTOI(dir_bdp);
3307
3308 if (XFS_FORCED_SHUTDOWN(dp->i_mount))
3309 return XFS_ERROR(EIO);
3310
3311 lock_mode = xfs_ilock_map_shared(dp);
3312 error = xfs_dir_getdents(tp, dp, uiop, eofp);
3313 xfs_iunlock_map_shared(dp, lock_mode);
3314 return error;
3315}
3316
3317
3318STATIC int 3287STATIC int
3319xfs_symlink( 3288xfs_symlink(
3320 bhv_desc_t *dir_bdp, 3289 bhv_desc_t *dir_bdp,