summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDave Chinner <dchinner@redhat.com>2014-11-07 08:29:57 +1100
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>2014-11-14 10:10:40 -0800
commit6de2ef500fca4fe624b759faba57d523841f9f65 (patch)
tree733bed65e63b740f87b728168165792ba6b18b24
parenta1606786b627409d725ba211d6ac679006415ba4 (diff)
downloadlwn-6de2ef500fca4fe624b759faba57d523841f9f65.tar.gz
lwn-6de2ef500fca4fe624b759faba57d523841f9f65.zip
xfs: bulkstat btree walk doesn't terminate
commit afa947cb52a8e73fe71915a0b0af6fcf98dfbe1a upstream. 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. Signed-off-by: Dave Chinner <dchinner@redhat.com> Reviewed-by: Brian Foster <bfoster@redhat.com> Signed-off-by: Dave Chinner <david@fromorbit.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
-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(
int end_of_ag; /* set if we've seen the ag end */
int error; /* error code */
int fmterror;/* bulkstat formatter result */
- int i; /* loop index */
int icount; /* count of inodes good in irbuf */
size_t irbsize; /* size of irec buffer in bytes */
xfs_ino_t ino; /* inode number (filesystem) */
@@ -366,11 +365,11 @@ xfs_bulkstat(
xfs_ino_t lastino; /* last inode number returned */
int nirbuf; /* size of irbuf */
int rval; /* return value error code */
- int tmp; /* result value from btree calls */
int ubcount; /* size of user's buffer */
int ubleft; /* bytes left in user's buffer */
char __user *ubufp; /* pointer into user's buffer */
int ubelem; /* spaces used in user's buffer */
+ int stat;
/*
* Get the last inode value, see if there's nothing to do.
@@ -436,13 +435,15 @@ xfs_bulkstat(
agino = r.ir_startino + XFS_INODES_PER_CHUNK;
}
/* Increment to the next record */
- error = xfs_btree_increment(cur, 0, &tmp);
+ error = xfs_btree_increment(cur, 0, &stat);
} else {
/* Start of ag. Lookup the first inode chunk */
- error = xfs_inobt_lookup(cur, 0, XFS_LOOKUP_GE, &tmp);
+ error = xfs_inobt_lookup(cur, 0, XFS_LOOKUP_GE, &stat);
}
- if (error)
+ if (error || stat == 0) {
+ end_of_ag = 1;
goto del_cursor;
+ }
/*
* Loop through inode btree records in this ag,
@@ -451,8 +452,8 @@ xfs_bulkstat(
while (irbp < irbufend && icount < ubcount) {
struct xfs_inobt_rec_incore r;
- error = xfs_inobt_get_rec(cur, &r, &i);
- if (error || i == 0) {
+ error = xfs_inobt_get_rec(cur, &r, &stat);
+ if (error || stat == 0) {
end_of_ag = 1;
goto del_cursor;
}
@@ -473,8 +474,8 @@ xfs_bulkstat(
* Set agino to after this chunk and bump the cursor.
*/
agino = r.ir_startino + XFS_INODES_PER_CHUNK;
- error = xfs_btree_increment(cur, 0, &tmp);
- if (error) {
+ error = xfs_btree_increment(cur, 0, &stat);
+ if (error || stat == 0) {
end_of_ag = 1;
goto del_cursor;
}