diff options
-rw-r--r-- | fs/xfs/xfs_itable.c | 71 |
1 files changed, 34 insertions, 37 deletions
diff --git a/fs/xfs/xfs_itable.c b/fs/xfs/xfs_itable.c index ff3f431671b9..894924a5129b 100644 --- a/fs/xfs/xfs_itable.c +++ b/fs/xfs/xfs_itable.c | |||
@@ -282,30 +282,31 @@ xfs_bulkstat_ag_ichunk( | |||
282 | bulkstat_one_pf formatter, | 282 | bulkstat_one_pf formatter, |
283 | size_t statstruct_size, | 283 | size_t statstruct_size, |
284 | struct xfs_bulkstat_agichunk *acp, | 284 | struct xfs_bulkstat_agichunk *acp, |
285 | xfs_ino_t *lastino) | 285 | xfs_agino_t *last_agino) |
286 | { | 286 | { |
287 | char __user **ubufp = acp->ac_ubuffer; | 287 | char __user **ubufp = acp->ac_ubuffer; |
288 | int chunkidx; | 288 | int chunkidx; |
289 | int error = 0; | 289 | int error = 0; |
290 | xfs_agino_t agino; | 290 | xfs_agino_t agino = irbp->ir_startino; |
291 | 291 | ||
292 | agino = irbp->ir_startino; | ||
293 | for (chunkidx = 0; chunkidx < XFS_INODES_PER_CHUNK; | 292 | for (chunkidx = 0; chunkidx < XFS_INODES_PER_CHUNK; |
294 | chunkidx++, agino++) { | 293 | chunkidx++, agino++) { |
295 | int fmterror; | 294 | int fmterror; |
296 | int ubused; | 295 | int ubused; |
297 | xfs_ino_t ino = XFS_AGINO_TO_INO(mp, agno, agino); | 296 | |
297 | /* inode won't fit in buffer, we are done */ | ||
298 | if (acp->ac_ubleft < statstruct_size) | ||
299 | break; | ||
298 | 300 | ||
299 | /* Skip if this inode is free */ | 301 | /* Skip if this inode is free */ |
300 | if (XFS_INOBT_MASK(chunkidx) & irbp->ir_free) { | 302 | if (XFS_INOBT_MASK(chunkidx) & irbp->ir_free) |
301 | *lastino = ino; | ||
302 | continue; | 303 | continue; |
303 | } | ||
304 | 304 | ||
305 | /* Get the inode and fill in a single buffer */ | 305 | /* Get the inode and fill in a single buffer */ |
306 | ubused = statstruct_size; | 306 | ubused = statstruct_size; |
307 | error = formatter(mp, ino, *ubufp, acp->ac_ubleft, | 307 | error = formatter(mp, XFS_AGINO_TO_INO(mp, agno, agino), |
308 | &ubused, &fmterror); | 308 | *ubufp, acp->ac_ubleft, &ubused, &fmterror); |
309 | |||
309 | if (fmterror == BULKSTAT_RV_GIVEUP || | 310 | if (fmterror == BULKSTAT_RV_GIVEUP || |
310 | (error && error != -ENOENT && error != -EINVAL)) { | 311 | (error && error != -ENOENT && error != -EINVAL)) { |
311 | acp->ac_ubleft = 0; | 312 | acp->ac_ubleft = 0; |
@@ -315,7 +316,6 @@ xfs_bulkstat_ag_ichunk( | |||
315 | 316 | ||
316 | /* be careful not to leak error if at end of chunk */ | 317 | /* be careful not to leak error if at end of chunk */ |
317 | if (fmterror == BULKSTAT_RV_NOTHING || error) { | 318 | if (fmterror == BULKSTAT_RV_NOTHING || error) { |
318 | *lastino = ino; | ||
319 | error = 0; | 319 | error = 0; |
320 | continue; | 320 | continue; |
321 | } | 321 | } |
@@ -323,12 +323,18 @@ xfs_bulkstat_ag_ichunk( | |||
323 | *ubufp += ubused; | 323 | *ubufp += ubused; |
324 | acp->ac_ubleft -= ubused; | 324 | acp->ac_ubleft -= ubused; |
325 | acp->ac_ubelem++; | 325 | acp->ac_ubelem++; |
326 | *lastino = ino; | ||
327 | |||
328 | if (acp->ac_ubleft < statstruct_size) | ||
329 | break; | ||
330 | } | 326 | } |
331 | 327 | ||
328 | /* | ||
329 | * Post-update *last_agino. At this point, agino will always point one | ||
330 | * inode past the last inode we processed successfully. Hence we | ||
331 | * substract that inode when setting the *last_agino cursor so that we | ||
332 | * return the correct cookie to userspace. On the next bulkstat call, | ||
333 | * the inode under the lastino cookie will be skipped as we have already | ||
334 | * processed it here. | ||
335 | */ | ||
336 | *last_agino = agino - 1; | ||
337 | |||
332 | return error; | 338 | return error; |
333 | } | 339 | } |
334 | 340 | ||
@@ -352,7 +358,6 @@ xfs_bulkstat( | |||
352 | xfs_btree_cur_t *cur; /* btree cursor for ialloc btree */ | 358 | xfs_btree_cur_t *cur; /* btree cursor for ialloc btree */ |
353 | size_t irbsize; /* size of irec buffer in bytes */ | 359 | size_t irbsize; /* size of irec buffer in bytes */ |
354 | xfs_inobt_rec_incore_t *irbuf; /* start of irec buffer */ | 360 | xfs_inobt_rec_incore_t *irbuf; /* start of irec buffer */ |
355 | xfs_ino_t lastino; /* last inode number returned */ | ||
356 | int nirbuf; /* size of irbuf */ | 361 | int nirbuf; /* size of irbuf */ |
357 | int ubcount; /* size of user's buffer */ | 362 | int ubcount; /* size of user's buffer */ |
358 | struct xfs_bulkstat_agichunk ac; | 363 | struct xfs_bulkstat_agichunk ac; |
@@ -361,11 +366,10 @@ xfs_bulkstat( | |||
361 | /* | 366 | /* |
362 | * Get the last inode value, see if there's nothing to do. | 367 | * Get the last inode value, see if there's nothing to do. |
363 | */ | 368 | */ |
364 | lastino = *lastinop; | 369 | agno = XFS_INO_TO_AGNO(mp, *lastinop); |
365 | agno = XFS_INO_TO_AGNO(mp, lastino); | 370 | agino = XFS_INO_TO_AGINO(mp, *lastinop); |
366 | agino = XFS_INO_TO_AGINO(mp, lastino); | ||
367 | if (agno >= mp->m_sb.sb_agcount || | 371 | if (agno >= mp->m_sb.sb_agcount || |
368 | lastino != XFS_AGINO_TO_INO(mp, agno, agino)) { | 372 | *lastinop != XFS_AGINO_TO_INO(mp, agno, agino)) { |
369 | *done = 1; | 373 | *done = 1; |
370 | *ubcountp = 0; | 374 | *ubcountp = 0; |
371 | return 0; | 375 | return 0; |
@@ -420,7 +424,6 @@ xfs_bulkstat( | |||
420 | irbp->ir_freecount = r.ir_freecount; | 424 | irbp->ir_freecount = r.ir_freecount; |
421 | irbp->ir_free = r.ir_free; | 425 | irbp->ir_free = r.ir_free; |
422 | irbp++; | 426 | irbp++; |
423 | agino = r.ir_startino + XFS_INODES_PER_CHUNK; | ||
424 | } | 427 | } |
425 | /* Increment to the next record */ | 428 | /* Increment to the next record */ |
426 | error = xfs_btree_increment(cur, 0, &stat); | 429 | error = xfs_btree_increment(cur, 0, &stat); |
@@ -458,10 +461,6 @@ xfs_bulkstat( | |||
458 | irbp++; | 461 | irbp++; |
459 | icount += XFS_INODES_PER_CHUNK - r.ir_freecount; | 462 | icount += XFS_INODES_PER_CHUNK - r.ir_freecount; |
460 | } | 463 | } |
461 | /* | ||
462 | * Set agino to after this chunk and bump the cursor. | ||
463 | */ | ||
464 | agino = r.ir_startino + XFS_INODES_PER_CHUNK; | ||
465 | error = xfs_btree_increment(cur, 0, &stat); | 464 | error = xfs_btree_increment(cur, 0, &stat); |
466 | if (error || stat == 0) { | 465 | if (error || stat == 0) { |
467 | end_of_ag = true; | 466 | end_of_ag = true; |
@@ -481,7 +480,9 @@ del_cursor: | |||
481 | if (error) | 480 | if (error) |
482 | break; | 481 | break; |
483 | /* | 482 | /* |
484 | * Now format all the good inodes into the user's buffer. | 483 | * Now format all the good inodes into the user's buffer. The |
484 | * call to xfs_bulkstat_ag_ichunk() sets up the agino pointer | ||
485 | * for the next loop iteration. | ||
485 | */ | 486 | */ |
486 | irbufend = irbp; | 487 | irbufend = irbp; |
487 | for (irbp = irbuf; | 488 | for (irbp = irbuf; |
@@ -489,7 +490,7 @@ del_cursor: | |||
489 | irbp++) { | 490 | irbp++) { |
490 | error = xfs_bulkstat_ag_ichunk(mp, agno, irbp, | 491 | error = xfs_bulkstat_ag_ichunk(mp, agno, irbp, |
491 | formatter, statstruct_size, &ac, | 492 | formatter, statstruct_size, &ac, |
492 | &lastino); | 493 | &agino); |
493 | if (error) | 494 | if (error) |
494 | break; | 495 | break; |
495 | 496 | ||
@@ -506,8 +507,7 @@ del_cursor: | |||
506 | if (end_of_ag) { | 507 | if (end_of_ag) { |
507 | agno++; | 508 | agno++; |
508 | agino = 0; | 509 | agino = 0; |
509 | } else | 510 | } |
510 | agino = XFS_INO_TO_AGINO(mp, lastino); | ||
511 | } | 511 | } |
512 | /* | 512 | /* |
513 | * Done, we're either out of filesystem or space to put the data. | 513 | * Done, we're either out of filesystem or space to put the data. |
@@ -525,16 +525,13 @@ del_cursor: | |||
525 | if (ac.ac_ubelem) | 525 | if (ac.ac_ubelem) |
526 | error = 0; | 526 | error = 0; |
527 | 527 | ||
528 | if (agno >= mp->m_sb.sb_agcount) { | 528 | /* |
529 | /* | 529 | * If we ran out of filesystem, lastino will point off the end of |
530 | * If we ran out of filesystem, mark lastino as off | 530 | * the filesystem so the next call will return immediately. |
531 | * the end of the filesystem, so the next call | 531 | */ |
532 | * will return immediately. | 532 | *lastinop = XFS_AGINO_TO_INO(mp, agno, agino); |
533 | */ | 533 | if (agno >= mp->m_sb.sb_agcount) |
534 | *lastinop = (xfs_ino_t)XFS_AGINO_TO_INO(mp, agno, 0); | ||
535 | *done = 1; | 534 | *done = 1; |
536 | } else | ||
537 | *lastinop = (xfs_ino_t)lastino; | ||
538 | 535 | ||
539 | return error; | 536 | return error; |
540 | } | 537 | } |