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 | } |
