aboutsummaryrefslogtreecommitdiffstats
path: root/fs/xfs/xfs_itable.c
diff options
context:
space:
mode:
authorDave Chinner <dchinner@redhat.com>2014-11-06 16:29:57 -0500
committerDave Chinner <david@fromorbit.com>2014-11-06 16:29:57 -0500
commitafa947cb52a8e73fe71915a0b0af6fcf98dfbe1a (patch)
treebd4e27a0faac80e48da23c1bbc19a9622ffe35ed /fs/xfs/xfs_itable.c
parent77783d06427293b2d711c45cfd4abc6494a1af9c (diff)
xfs: bulkstat btree walk doesn't terminate
The bulkstat code has several different ways of detecting the end of an AG when doing a walk. They are not consistently detected, and the code that checks for the end of AG conditions is not consistently coded. Hence the are conditions where the walk code can get stuck in an endless loop making no progress and not triggering any termination conditions. Convert all the "tmp/i" status return codes from btree operations to a common name (stat) and apply end-of-ag detection to these operations consistently. 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>
Diffstat (limited to 'fs/xfs/xfs_itable.c')
-rw-r--r--fs/xfs/xfs_itable.c19
1 files changed, 10 insertions, 9 deletions
diff --git a/fs/xfs/xfs_itable.c b/fs/xfs/xfs_itable.c
index 7765ff743e91..16737cbbee17 100644
--- a/fs/xfs/xfs_itable.c
+++ b/fs/xfs/xfs_itable.c
@@ -356,7 +356,6 @@ xfs_bulkstat(
356 int end_of_ag; /* set if we've seen the ag end */ 356 int end_of_ag; /* set if we've seen the ag end */
357 int error; /* error code */ 357 int error; /* error code */
358 int fmterror;/* bulkstat formatter result */ 358 int fmterror;/* bulkstat formatter result */
359 int i; /* loop index */
360 int icount; /* count of inodes good in irbuf */ 359 int icount; /* count of inodes good in irbuf */
361 size_t irbsize; /* size of irec buffer in bytes */ 360 size_t irbsize; /* size of irec buffer in bytes */
362 xfs_ino_t ino; /* inode number (filesystem) */ 361 xfs_ino_t ino; /* inode number (filesystem) */
@@ -366,11 +365,11 @@ xfs_bulkstat(
366 xfs_ino_t lastino; /* last inode number returned */ 365 xfs_ino_t lastino; /* last inode number returned */
367 int nirbuf; /* size of irbuf */ 366 int nirbuf; /* size of irbuf */
368 int rval; /* return value error code */ 367 int rval; /* return value error code */
369 int tmp; /* result value from btree calls */
370 int ubcount; /* size of user's buffer */ 368 int ubcount; /* size of user's buffer */
371 int ubleft; /* bytes left in user's buffer */ 369 int ubleft; /* bytes left in user's buffer */
372 char __user *ubufp; /* pointer into user's buffer */ 370 char __user *ubufp; /* pointer into user's buffer */
373 int ubelem; /* spaces used in user's buffer */ 371 int ubelem; /* spaces used in user's buffer */
372 int stat;
374 373
375 /* 374 /*
376 * Get the last inode value, see if there's nothing to do. 375 * Get the last inode value, see if there's nothing to do.
@@ -436,13 +435,15 @@ xfs_bulkstat(
436 agino = r.ir_startino + XFS_INODES_PER_CHUNK; 435 agino = r.ir_startino + XFS_INODES_PER_CHUNK;
437 } 436 }
438 /* Increment to the next record */ 437 /* Increment to the next record */
439 error = xfs_btree_increment(cur, 0, &tmp); 438 error = xfs_btree_increment(cur, 0, &stat);
440 } else { 439 } else {
441 /* Start of ag. Lookup the first inode chunk */ 440 /* Start of ag. Lookup the first inode chunk */
442 error = xfs_inobt_lookup(cur, 0, XFS_LOOKUP_GE, &tmp); 441 error = xfs_inobt_lookup(cur, 0, XFS_LOOKUP_GE, &stat);
443 } 442 }
444 if (error) 443 if (error || stat == 0) {
444 end_of_ag = 1;
445 goto del_cursor; 445 goto del_cursor;
446 }
446 447
447 /* 448 /*
448 * Loop through inode btree records in this ag, 449 * Loop through inode btree records in this ag,
@@ -451,8 +452,8 @@ xfs_bulkstat(
451 while (irbp < irbufend && icount < ubcount) { 452 while (irbp < irbufend && icount < ubcount) {
452 struct xfs_inobt_rec_incore r; 453 struct xfs_inobt_rec_incore r;
453 454
454 error = xfs_inobt_get_rec(cur, &r, &i); 455 error = xfs_inobt_get_rec(cur, &r, &stat);
455 if (error || i == 0) { 456 if (error || stat == 0) {
456 end_of_ag = 1; 457 end_of_ag = 1;
457 goto del_cursor; 458 goto del_cursor;
458 } 459 }
@@ -473,8 +474,8 @@ xfs_bulkstat(
473 * Set agino to after this chunk and bump the cursor. 474 * Set agino to after this chunk and bump the cursor.
474 */ 475 */
475 agino = r.ir_startino + XFS_INODES_PER_CHUNK; 476 agino = r.ir_startino + XFS_INODES_PER_CHUNK;
476 error = xfs_btree_increment(cur, 0, &tmp); 477 error = xfs_btree_increment(cur, 0, &stat);
477 if (error) { 478 if (error || stat == 0) {
478 end_of_ag = 1; 479 end_of_ag = 1;
479 goto del_cursor; 480 goto del_cursor;
480 } 481 }