diff options
Diffstat (limited to 'fs/xfs/linux-2.6/xfs_file.c')
-rw-r--r-- | fs/xfs/linux-2.6/xfs_file.c | 90 |
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 | } | ||
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 |