diff options
-rw-r--r-- | fs/xfs/linux-2.6/xfs_file.c | 90 | ||||
-rw-r--r-- | fs/xfs/linux-2.6/xfs_vnode.h | 8 | ||||
-rw-r--r-- | fs/xfs/xfs_dir2.c | 121 | ||||
-rw-r--r-- | fs/xfs/xfs_dir2.h | 19 | ||||
-rw-r--r-- | fs/xfs/xfs_dir2_block.c | 63 | ||||
-rw-r--r-- | fs/xfs/xfs_dir2_block.h | 5 | ||||
-rw-r--r-- | fs/xfs/xfs_dir2_leaf.c | 76 | ||||
-rw-r--r-- | fs/xfs/xfs_dir2_leaf.h | 6 | ||||
-rw-r--r-- | fs/xfs/xfs_dir2_sf.c | 121 | ||||
-rw-r--r-- | fs/xfs/xfs_dir2_sf.h | 5 | ||||
-rw-r--r-- | fs/xfs/xfs_types.h | 12 | ||||
-rw-r--r-- | fs/xfs/xfs_vnodeops.c | 31 |
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 | } | ||
294 | done: | ||
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 | ||
306 | STATIC int | 262 | STATIC 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 *, | |||
161 | typedef int (*vop_mkdir_t)(bhv_desc_t *, bhv_vname_t *, struct bhv_vattr *, | 161 | typedef 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 *); |
163 | typedef int (*vop_rmdir_t)(bhv_desc_t *, bhv_vname_t *, struct cred *); | 163 | typedef int (*vop_rmdir_t)(bhv_desc_t *, bhv_vname_t *, struct cred *); |
164 | typedef int (*vop_readdir_t)(bhv_desc_t *, struct uio *, struct cred *, | 164 | typedef int (*vop_readdir_t)(bhv_desc_t *, void *dirent, size_t bufsize, |
165 | int *); | 165 | xfs_off_t *offset, filldir_t filldir); |
166 | typedef int (*vop_symlink_t)(bhv_desc_t *, bhv_vname_t *, struct bhv_vattr*, | 166 | typedef 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 *); |
168 | typedef int (*vop_readlink_t)(bhv_desc_t *, struct uio *, int, | 168 | typedef 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 | ||
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,35 @@ 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, | 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 | */ | ||
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. | 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; | |||
60 | typedef xfs_off_t xfs_dir2_off_t; | 60 | typedef xfs_off_t xfs_dir2_off_t; |
61 | 61 | ||
62 | /* | 62 | /* |
63 | * For getdents, argument struct for put routines. | ||
64 | */ | ||
65 | typedef int (*xfs_dir2_put_t)(struct xfs_dir2_put_args *pa); | ||
66 | typedef 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 | */ |
80 | extern void xfs_dir_startup(void); | 65 | extern 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); |
95 | extern int xfs_dir_getdents(struct xfs_trans *tp, struct xfs_inode *dp, | ||
96 | uio_t *uio, int *eofp); | ||
97 | extern int xfs_dir_replace(struct xfs_trans *tp, struct xfs_inode *dp, | 80 | extern 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, | |||
101 | extern int xfs_dir_canenter(struct xfs_trans *tp, struct xfs_inode *dp, | 84 | extern int xfs_dir_canenter(struct xfs_trans *tp, struct xfs_inode *dp, |
102 | char *name, int namelen); | 85 | char *name, int namelen); |
103 | extern int xfs_dir_ino_validate(struct xfs_mount *mp, xfs_ino_t ino); | 86 | extern int xfs_dir_ino_validate(struct xfs_mount *mp, xfs_ino_t ino); |
87 | extern 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 | */ |
433 | int /* error */ | 433 | int /* error */ |
434 | xfs_dir2_block_getdents( | 434 | xfs_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 | */ |
82 | extern int xfs_dir2_block_addname(struct xfs_da_args *args); | 82 | extern int xfs_dir2_block_addname(struct xfs_da_args *args); |
83 | extern int xfs_dir2_block_getdents(struct xfs_trans *tp, struct xfs_inode *dp, | 83 | extern 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); | ||
86 | extern int xfs_dir2_block_lookup(struct xfs_da_args *args); | 85 | extern int xfs_dir2_block_lookup(struct xfs_da_args *args); |
87 | extern int xfs_dir2_block_removename(struct xfs_da_args *args); | 86 | extern int xfs_dir2_block_removename(struct xfs_da_args *args); |
88 | extern int xfs_dir2_block_replace(struct xfs_da_args *args); | 87 | extern 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 | */ |
750 | int /* error */ | 750 | int /* error */ |
751 | xfs_dir2_leaf_getdents( | 751 | xfs_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, | |||
232 | extern void xfs_dir2_leaf_compact_x1(struct xfs_dabuf *bp, int *indexp, | 232 | extern 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); |
235 | extern int xfs_dir2_leaf_getdents(struct xfs_trans *tp, struct xfs_inode *dp, | 235 | extern 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); |
238 | extern int xfs_dir2_leaf_init(struct xfs_da_args *args, xfs_dir2_db_t bno, | 238 | extern 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); |
240 | extern void xfs_dir2_leaf_log_ents(struct xfs_trans *tp, struct xfs_dabuf *bp, | 240 | extern 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( | |||
695 | int /* error */ | 695 | int /* error */ |
696 | xfs_dir2_sf_getdents( | 696 | xfs_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); |
170 | extern int xfs_dir2_sf_addname(struct xfs_da_args *args); | 170 | extern int xfs_dir2_sf_addname(struct xfs_da_args *args); |
171 | extern int xfs_dir2_sf_create(struct xfs_da_args *args, xfs_ino_t pino); | 171 | extern int xfs_dir2_sf_create(struct xfs_da_args *args, xfs_ino_t pino); |
172 | extern int xfs_dir2_sf_getdents(struct xfs_inode *dp, struct uio *uio, | 172 | extern 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); | ||
175 | extern int xfs_dir2_sf_lookup(struct xfs_da_args *args); | 174 | extern int xfs_dir2_sf_lookup(struct xfs_da_args *args); |
176 | extern int xfs_dir2_sf_removename(struct xfs_da_args *args); | 175 | extern int xfs_dir2_sf_removename(struct xfs_da_args *args); |
177 | extern int xfs_dir2_sf_replace(struct xfs_da_args *args); | 176 | extern 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 | ||
154 | typedef 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 | |||
166 | typedef enum { | 154 | typedef 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 | */ | ||
3292 | STATIC int | ||
3293 | xfs_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 | |||
3318 | STATIC int | 3287 | STATIC int |
3319 | xfs_symlink( | 3288 | xfs_symlink( |
3320 | bhv_desc_t *dir_bdp, | 3289 | bhv_desc_t *dir_bdp, |