aboutsummaryrefslogtreecommitdiffstats
path: root/fs/xfs/linux-2.6/xfs_file.c
diff options
context:
space:
mode:
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