aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDave Chinner <dchinner@redhat.com>2014-11-06 16:33:52 -0500
committerDave Chinner <david@fromorbit.com>2014-11-06 16:33:52 -0500
commit002758992693ae63c04122603ea9261a0a58d728 (patch)
treea753dde5e9118cc908566a3aa37c9b3620a24a79
parentfebe3cbe38b0bc0a925906dc90e8d59048851f87 (diff)
xfs: track bulkstat progress by agino
The bulkstat main loop progress is tracked by the "lastino" variable, which is a full 64 bit inode. However, the loop actually works on agno/agino pairs, and so there's a significant disconnect between the rest of the loop and the main cursor. Convert this to use the agino, and pass the agino into the chunk formatting function and convert it too. This gets rid of the inconsistency in the loop processing, and finally makes it simple for us to skip inodes at any point in the loop simply by incrementing the agino cursor. cc: <stable@vger.kernel.org> # 3.17 Signed-off-by: Dave Chinner <dchinner@redhat.com> Reviewed-by: Brian Foster <bfoster@redhat.com> Signed-off-by: Dave Chinner <david@fromorbit.com>
-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}