Commit 002758992693ae63c04122603ea9261a0a58d728

Authored by Dave Chinner
Committed by Dave Chinner
1 parent febe3cbe38

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>

Showing 1 changed file with 34 additions and 37 deletions Side-by-side Diff

... ... @@ -282,30 +282,31 @@
282 282 bulkstat_one_pf formatter,
283 283 size_t statstruct_size,
284 284 struct xfs_bulkstat_agichunk *acp,
285   - xfs_ino_t *lastino)
  285 + xfs_agino_t *last_agino)
286 286 {
287 287 char __user **ubufp = acp->ac_ubuffer;
288 288 int chunkidx;
289 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 292 for (chunkidx = 0; chunkidx < XFS_INODES_PER_CHUNK;
294 293 chunkidx++, agino++) {
295 294 int fmterror;
296 295 int ubused;
297   - xfs_ino_t ino = XFS_AGINO_TO_INO(mp, agno, agino);
298 296  
  297 + /* inode won't fit in buffer, we are done */
  298 + if (acp->ac_ubleft < statstruct_size)
  299 + break;
  300 +
299 301 /* Skip if this inode is free */
300   - if (XFS_INOBT_MASK(chunkidx) & irbp->ir_free) {
301   - *lastino = ino;
  302 + if (XFS_INOBT_MASK(chunkidx) & irbp->ir_free)
302 303 continue;
303   - }
304 304  
305 305 /* Get the inode and fill in a single buffer */
306 306 ubused = statstruct_size;
307   - error = formatter(mp, ino, *ubufp, acp->ac_ubleft,
308   - &ubused, &fmterror);
  307 + error = formatter(mp, XFS_AGINO_TO_INO(mp, agno, agino),
  308 + *ubufp, acp->ac_ubleft, &ubused, &fmterror);
  309 +
309 310 if (fmterror == BULKSTAT_RV_GIVEUP ||
310 311 (error && error != -ENOENT && error != -EINVAL)) {
311 312 acp->ac_ubleft = 0;
... ... @@ -315,7 +316,6 @@
315 316  
316 317 /* be careful not to leak error if at end of chunk */
317 318 if (fmterror == BULKSTAT_RV_NOTHING || error) {
318   - *lastino = ino;
319 319 error = 0;
320 320 continue;
321 321 }
322 322  
... ... @@ -323,12 +323,18 @@
323 323 *ubufp += ubused;
324 324 acp->ac_ubleft -= ubused;
325 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 338 return error;
333 339 }
334 340  
... ... @@ -352,7 +358,6 @@
352 358 xfs_btree_cur_t *cur; /* btree cursor for ialloc btree */
353 359 size_t irbsize; /* size of irec buffer in bytes */
354 360 xfs_inobt_rec_incore_t *irbuf; /* start of irec buffer */
355   - xfs_ino_t lastino; /* last inode number returned */
356 361 int nirbuf; /* size of irbuf */
357 362 int ubcount; /* size of user's buffer */
358 363 struct xfs_bulkstat_agichunk ac;
359 364  
... ... @@ -361,11 +366,10 @@
361 366 /*
362 367 * Get the last inode value, see if there's nothing to do.
363 368 */
364   - lastino = *lastinop;
365   - agno = XFS_INO_TO_AGNO(mp, lastino);
366   - agino = XFS_INO_TO_AGINO(mp, lastino);
  369 + agno = XFS_INO_TO_AGNO(mp, *lastinop);
  370 + agino = XFS_INO_TO_AGINO(mp, *lastinop);
367 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 373 *done = 1;
370 374 *ubcountp = 0;
371 375 return 0;
... ... @@ -420,7 +424,6 @@
420 424 irbp->ir_freecount = r.ir_freecount;
421 425 irbp->ir_free = r.ir_free;
422 426 irbp++;
423   - agino = r.ir_startino + XFS_INODES_PER_CHUNK;
424 427 }
425 428 /* Increment to the next record */
426 429 error = xfs_btree_increment(cur, 0, &stat);
... ... @@ -458,10 +461,6 @@
458 461 irbp++;
459 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 464 error = xfs_btree_increment(cur, 0, &stat);
466 465 if (error || stat == 0) {
467 466 end_of_ag = true;
... ... @@ -481,7 +480,9 @@
481 480 if (error)
482 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 487 irbufend = irbp;
487 488 for (irbp = irbuf;
... ... @@ -489,7 +490,7 @@
489 490 irbp++) {
490 491 error = xfs_bulkstat_ag_ichunk(mp, agno, irbp,
491 492 formatter, statstruct_size, &ac,
492   - &lastino);
  493 + &agino);
493 494 if (error)
494 495 break;
495 496  
... ... @@ -506,8 +507,7 @@
506 507 if (end_of_ag) {
507 508 agno++;
508 509 agino = 0;
509   - } else
510   - agino = XFS_INO_TO_AGINO(mp, lastino);
  510 + }
511 511 }
512 512 /*
513 513 * Done, we're either out of filesystem or space to put the data.
514 514  
... ... @@ -525,16 +525,13 @@
525 525 if (ac.ac_ubelem)
526 526 error = 0;
527 527  
528   - if (agno >= mp->m_sb.sb_agcount) {
529   - /*
530   - * If we ran out of filesystem, mark lastino as off
531   - * the end of the filesystem, so the next call
532   - * will return immediately.
533   - */
534   - *lastinop = (xfs_ino_t)XFS_AGINO_TO_INO(mp, agno, 0);
  528 + /*
  529 + * If we ran out of filesystem, lastino will point off the end of
  530 + * the filesystem so the next call will return immediately.
  531 + */
  532 + *lastinop = XFS_AGINO_TO_INO(mp, agno, agino);
  533 + if (agno >= mp->m_sb.sb_agcount)
535 534 *done = 1;
536   - } else
537   - *lastinop = (xfs_ino_t)lastino;
538 535  
539 536 return error;
540 537 }