aboutsummaryrefslogtreecommitdiffstats
path: root/fs/xfs/linux-2.6/xfs_file.c
diff options
context:
space:
mode:
authorChristoph Hellwig <hch@infradead.org>2007-08-27 23:58:24 -0400
committerTim Shimmin <tes@chook.melbourne.sgi.com>2007-10-15 02:49:49 -0400
commit051e7cd44ab8f0f7c2958371485b4a1ff64a8d1b (patch)
tree23389d878944e0566effed4eb2de4c1ed5fed96e /fs/xfs/linux-2.6/xfs_file.c
parent2bdf7cd0baa67608ada1517a281af359faf4c58c (diff)
[XFS] use filldir internally
Currently xfs has a rather complicated internal scheme to allow for different directory formats in IRIX. This patch rips all code related to this out and pushes useage of the Linux filldir callback into the lowlevel directory code. This does not make the code any less portable because filldir can be used to create dirents of all possible variations (including the IRIX ones as proved by the IRIX binary emulation code under arch/mips/). This patch get rid of an unessecary copy in the readdir path, about 400 lines of code and one of the last two users of the uio structure. This version is updated to deal with dmapi aswell which greatly simplifies the get_dirattrs code. The dmapi part has been tested using the get_dirattrs tools from the xfstest dmapi suite1 with various small and large directories. SGI-PV: 968563 SGI-Modid: xfs-linux-melb:xfs-kern:29478a Signed-off-by: Christoph Hellwig <hch@infradead.org> Signed-off-by: David Chinner <dgc@sgi.com> Signed-off-by: Tim Shimmin <tes@sgi.com>
Diffstat (limited to 'fs/xfs/linux-2.6/xfs_file.c')
-rw-r--r--fs/xfs/linux-2.6/xfs_file.c90
1 files changed, 23 insertions, 67 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