git.openpandora.org
/
pandora-kernel.git
/ blobdiff
commit
grep
author
committer
pickaxe
?
search:
re
summary
|
shortlog
|
log
|
commit
|
commitdiff
|
tree
raw
|
inline
| side by side
xfs: bulkstat chunk-formatter has issues
[pandora-kernel.git]
/
fs
/
xfs
/
xfs_itable.c
diff --git
a/fs/xfs/xfs_itable.c
b/fs/xfs/xfs_itable.c
index
f1deb96
..
7ea2b11
100644
(file)
--- a/
fs/xfs/xfs_itable.c
+++ b/
fs/xfs/xfs_itable.c
@@
-262,75
+262,70
@@
xfs_bulkstat_grab_ichunk(
#define XFS_BULKSTAT_UBLEFT(ubleft) ((ubleft) >= statstruct_size)
#define XFS_BULKSTAT_UBLEFT(ubleft) ((ubleft) >= statstruct_size)
+struct xfs_bulkstat_agichunk {
+ char __user **ac_ubuffer;/* pointer into user's buffer */
+ int ac_ubleft; /* bytes left in user's buffer */
+ int ac_ubelem; /* spaces used in user's buffer */
+};
+
/*
* Process inodes in chunk with a pointer to a formatter function
* that will iget the inode and fill in the appropriate structure.
*/
/*
* Process inodes in chunk with a pointer to a formatter function
* that will iget the inode and fill in the appropriate structure.
*/
-int
+
static
int
xfs_bulkstat_ag_ichunk(
struct xfs_mount *mp,
xfs_agnumber_t agno,
struct xfs_inobt_rec_incore *irbp,
bulkstat_one_pf formatter,
size_t statstruct_size,
xfs_bulkstat_ag_ichunk(
struct xfs_mount *mp,
xfs_agnumber_t agno,
struct xfs_inobt_rec_incore *irbp,
bulkstat_one_pf formatter,
size_t statstruct_size,
- struct xfs_bulkstat_agichunk *acp)
+ struct xfs_bulkstat_agichunk *acp,
+ xfs_ino_t *lastino)
{
{
- xfs_ino_t lastino = acp->ac_lastino;
char __user **ubufp = acp->ac_ubuffer;
char __user **ubufp = acp->ac_ubuffer;
- int ubleft = acp->ac_ubleft;
- int ubelem = acp->ac_ubelem;
- int chunkidx, clustidx;
+ int chunkidx;
int error = 0;
xfs_agino_t agino;
int error = 0;
xfs_agino_t agino;
- for (agino = irbp->ir_startino, chunkidx = clustidx = 0;
- XFS_BULKSTAT_UBLEFT(ubleft) &&
- irbp->ir_freecount < XFS_INODES_PER_CHUNK;
- chunkidx++, clustidx++, agino++) {
- int fmterror; /* bulkstat formatter result */
+ agino = irbp->ir_startino;
+ for (chunkidx = 0; chunkidx < XFS_INODES_PER_CHUNK;
+ chunkidx++, agino++) {
+ int fmterror;
int ubused;
xfs_ino_t ino = XFS_AGINO_TO_INO(mp, agno, agino);
int ubused;
xfs_ino_t ino = XFS_AGINO_TO_INO(mp, agno, agino);
- ASSERT(chunkidx < XFS_INODES_PER_CHUNK);
-
/* Skip if this inode is free */
if (XFS_INOBT_MASK(chunkidx) & irbp->ir_free) {
/* Skip if this inode is free */
if (XFS_INOBT_MASK(chunkidx) & irbp->ir_free) {
- lastino = ino;
+
*
lastino = ino;
continue;
}
continue;
}
- /*
- * Count used inodes as free so we can tell when the
- * chunk is used up.
- */
- irbp->ir_freecount++;
-
/* Get the inode and fill in a single buffer */
ubused = statstruct_size;
/* Get the inode and fill in a single buffer */
ubused = statstruct_size;
- error = formatter(mp, ino, *ubufp, ubleft, &ubused, &fmterror);
- if (fmterror == BULKSTAT_RV_NOTHING) {
- if (error && error != -ENOENT && error != -EINVAL) {
- ubleft = 0;
- break;
- }
- lastino = ino;
- continue;
- }
- if (fmterror == BULKSTAT_RV_GIVEUP) {
- ubleft = 0;
+ error = formatter(mp, ino, *ubufp, acp->ac_ubleft,
+ &ubused, &fmterror);
+ if (fmterror == BULKSTAT_RV_GIVEUP ||
+ (error && error != -ENOENT && error != -EINVAL)) {
+ acp->ac_ubleft = 0;
ASSERT(error);
break;
}
ASSERT(error);
break;
}
- if (*ubufp)
- *ubufp += ubused;
- ubleft -= ubused;
- ubelem++;
- lastino = ino;
- }
- acp->ac_lastino = lastino;
- acp->ac_ubleft = ubleft;
- acp->ac_ubelem = ubelem;
+ /* be careful not to leak error if at end of chunk */
+ if (fmterror == BULKSTAT_RV_NOTHING || error) {
+ *lastino = ino;
+ error = 0;
+ continue;
+ }
+
+ *ubufp += ubused;
+ acp->ac_ubleft -= ubused;
+ acp->ac_ubelem++;
+ *lastino = ino;
+
+ if (acp->ac_ubleft < statstruct_size)
+ break;
+ }
return error;
}
return error;
}
@@
-355,8
+350,6
@@
xfs_bulkstat(
xfs_btree_cur_t *cur; /* btree cursor for ialloc btree */
int end_of_ag; /* set if we've seen the ag end */
int error; /* error code */
xfs_btree_cur_t *cur; /* btree cursor for ialloc btree */
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) */
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
+359,9
@@
xfs_bulkstat(
xfs_ino_t lastino; /* last inode number returned */
int nirbuf; /* size of irbuf */
int rval; /* return value error code */
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 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;
+ struct xfs_bulkstat_agichunk ac;
/*
* Get the last inode value, see if there's nothing to do.
/*
* Get the last inode value, see if there's nothing to do.
@@
-387,11
+378,13
@@
xfs_bulkstat(
}
ubcount = *ubcountp; /* statstruct's */
}
ubcount = *ubcountp; /* statstruct's */
- ubleft = ubcount * statstruct_size; /* bytes */
- *ubcountp = ubelem = 0;
+ ac.ac_ubuffer = &ubuffer;
+ ac.ac_ubleft = ubcount * statstruct_size; /* bytes */;
+ ac.ac_ubelem = 0;
+
+ *ubcountp = 0;
*done = 0;
*done = 0;
- fmterror = 0;
- ubufp = ubuffer;
+
irbuf = kmem_zalloc_greedy(&irbsize, PAGE_SIZE, PAGE_SIZE * 4);
if (!irbuf)
return -ENOMEM;
irbuf = kmem_zalloc_greedy(&irbsize, PAGE_SIZE, PAGE_SIZE * 4);
if (!irbuf)
return -ENOMEM;
@@
-403,7
+396,7
@@
xfs_bulkstat(
* inode returned; 0 means start of the allocation group.
*/
rval = 0;
* inode returned; 0 means start of the allocation group.
*/
rval = 0;
- while (XFS_BULKSTAT_UBLEFT(ubleft) && agno < mp->m_sb.sb_agcount) {
+ while (XFS_BULKSTAT_UBLEFT(
ac.ac_
ubleft) && agno < mp->m_sb.sb_agcount) {
cond_resched();
error = xfs_ialloc_read_agi(mp, NULL, agno, &agbp);
if (error)
cond_resched();
error = xfs_ialloc_read_agi(mp, NULL, agno, &agbp);
if (error)
@@
-427,7
+420,7
@@
xfs_bulkstat(
error = xfs_bulkstat_grab_ichunk(cur, agino, &icount, &r);
if (error)
error = xfs_bulkstat_grab_ichunk(cur, agino, &icount, &r);
if (error)
-
break
;
+
goto del_cursor
;
if (icount) {
irbp->ir_startino = r.ir_startino;
irbp->ir_freecount = r.ir_freecount;
if (icount) {
irbp->ir_startino = r.ir_startino;
irbp->ir_freecount = r.ir_freecount;
@@
-436,13
+429,15
@@
xfs_bulkstat(
agino = r.ir_startino + XFS_INODES_PER_CHUNK;
}
/* Increment to the next record */
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 */
} 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 || stat == 0) {
+ end_of_ag = 1;
+ goto del_cursor;
}
}
- if (error)
- break;
/*
* Loop through inode btree records in this ag,
/*
* Loop through inode btree records in this ag,
@@
-451,10
+446,10
@@
xfs_bulkstat(
while (irbp < irbufend && icount < ubcount) {
struct xfs_inobt_rec_incore r;
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;
end_of_ag = 1;
-
break
;
+
goto del_cursor
;
}
/*
}
/*
@@
-473,43
+468,44
@@
xfs_bulkstat(
* Set agino to after this chunk and bump the cursor.
*/
agino = r.ir_startino + XFS_INODES_PER_CHUNK;
* 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);
+ error = xfs_btree_increment(cur, 0, &stat);
+ if (error || stat == 0) {
+ end_of_ag = 1;
+ goto del_cursor;
+ }
cond_resched();
}
cond_resched();
}
+
/*
/*
- * Drop the btree buffers and the agi buffer
.
- *
We can't hold any of the locks these represent
- *
when calling iget
.
+ * Drop the btree buffers and the agi buffer
as we can't hold any
+ *
of the locks these represent when calling iget. If there is a
+ *
pending error, then we are done
.
*/
*/
+del_cursor:
xfs_btree_del_cursor(cur, XFS_BTREE_NOERROR);
xfs_buf_relse(agbp);
xfs_btree_del_cursor(cur, XFS_BTREE_NOERROR);
xfs_buf_relse(agbp);
+ if (error)
+ break;
/*
* Now format all the good inodes into the user's buffer.
*/
irbufend = irbp;
for (irbp = irbuf;
/*
* Now format all the good inodes into the user's buffer.
*/
irbufend = irbp;
for (irbp = irbuf;
- irbp < irbufend && XFS_BULKSTAT_UBLEFT(ubleft); irbp++) {
- struct xfs_bulkstat_agichunk ac;
-
- ac.ac_lastino = lastino;
- ac.ac_ubuffer = &ubuffer;
- ac.ac_ubleft = ubleft;
- ac.ac_ubelem = ubelem;
+ irbp < irbufend && XFS_BULKSTAT_UBLEFT(ac.ac_ubleft);
+ irbp++) {
error = xfs_bulkstat_ag_ichunk(mp, agno, irbp,
error = xfs_bulkstat_ag_ichunk(mp, agno, irbp,
- formatter, statstruct_size, &ac);
+ formatter, statstruct_size, &ac,
+ &lastino);
if (error)
rval = error;
if (error)
rval = error;
- lastino = ac.ac_lastino;
- ubleft = ac.ac_ubleft;
- ubelem = ac.ac_ubelem;
-
cond_resched();
}
cond_resched();
}
+
/*
* Set up for the next loop iteration.
*/
/*
* Set up for the next loop iteration.
*/
- if (XFS_BULKSTAT_UBLEFT(ubleft)) {
+ if (XFS_BULKSTAT_UBLEFT(
ac.ac_
ubleft)) {
if (end_of_ag) {
agno++;
agino = 0;
if (end_of_ag) {
agno++;
agino = 0;
@@
-522,11
+518,11
@@
xfs_bulkstat(
* Done, we're either out of filesystem or space to put the data.
*/
kmem_free(irbuf);
* Done, we're either out of filesystem or space to put the data.
*/
kmem_free(irbuf);
- *ubcountp = ubelem;
+ *ubcountp =
ac.ac_
ubelem;
/*
* Found some inodes, return them now and return the error next time.
*/
/*
* Found some inodes, return them now and return the error next time.
*/
- if (ubelem)
+ if (
ac.ac_
ubelem)
rval = 0;
if (agno >= mp->m_sb.sb_agcount) {
/*
rval = 0;
if (agno >= mp->m_sb.sb_agcount) {
/*