aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--fs/xfs/xfs_itable.c71
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}