Commit 677717fb authored by Darrick J. Wong's avatar Darrick J. Wong

xfs: refactor INUMBERS to use iwalk functions

Now that we have generic functions to walk inode records, refactor the
INUMBERS implementation to use it.
Signed-off-by: default avatarDarrick J. Wong <darrick.wong@oracle.com>
Reviewed-by: default avatarBrian Foster <bfoster@redhat.com>
parent 04b8fba2
...@@ -724,6 +724,16 @@ xfs_bulkstat_one_fmt( ...@@ -724,6 +724,16 @@ xfs_bulkstat_one_fmt(
return xfs_ibulk_advance(breq, sizeof(struct xfs_bstat)); return xfs_ibulk_advance(breq, sizeof(struct xfs_bstat));
} }
int
xfs_inumbers_fmt(
struct xfs_ibulk *breq,
const struct xfs_inogrp *igrp)
{
if (copy_to_user(breq->ubuffer, igrp, sizeof(*igrp)))
return -EFAULT;
return xfs_ibulk_advance(breq, sizeof(struct xfs_inogrp));
}
STATIC int STATIC int
xfs_ioc_bulkstat( xfs_ioc_bulkstat(
xfs_mount_t *mp, xfs_mount_t *mp,
...@@ -774,13 +784,9 @@ xfs_ioc_bulkstat( ...@@ -774,13 +784,9 @@ xfs_ioc_bulkstat(
* in filesystem". * in filesystem".
*/ */
if (cmd == XFS_IOC_FSINUMBERS) { if (cmd == XFS_IOC_FSINUMBERS) {
int count = breq.icount; breq.startino = lastino ? lastino + 1 : 0;
error = xfs_inumbers(&breq, xfs_inumbers_fmt);
breq.startino = lastino; lastino = breq.startino - 1;
error = xfs_inumbers(mp, &breq.startino, &count,
bulkreq.ubuffer, xfs_inumbers_fmt);
breq.ocount = count;
lastino = breq.startino;
} else if (cmd == XFS_IOC_FSBULKSTAT_SINGLE) { } else if (cmd == XFS_IOC_FSBULKSTAT_SINGLE) {
breq.startino = lastino; breq.startino = lastino;
breq.icount = 1; breq.icount = 1;
......
...@@ -79,7 +79,9 @@ xfs_set_dmattrs( ...@@ -79,7 +79,9 @@ xfs_set_dmattrs(
struct xfs_ibulk; struct xfs_ibulk;
struct xfs_bstat; struct xfs_bstat;
struct xfs_inogrp;
int xfs_bulkstat_one_fmt(struct xfs_ibulk *breq, const struct xfs_bstat *bstat); int xfs_bulkstat_one_fmt(struct xfs_ibulk *breq, const struct xfs_bstat *bstat);
int xfs_inumbers_fmt(struct xfs_ibulk *breq, const struct xfs_inogrp *igrp);
#endif #endif
...@@ -81,22 +81,17 @@ xfs_compat_growfs_rt_copyin( ...@@ -81,22 +81,17 @@ xfs_compat_growfs_rt_copyin(
STATIC int STATIC int
xfs_inumbers_fmt_compat( xfs_inumbers_fmt_compat(
void __user *ubuffer, struct xfs_ibulk *breq,
const struct xfs_inogrp *buffer, const struct xfs_inogrp *igrp)
long count,
long *written)
{ {
compat_xfs_inogrp_t __user *p32 = ubuffer; struct compat_xfs_inogrp __user *p32 = breq->ubuffer;
long i;
for (i = 0; i < count; i++) { if (put_user(igrp->xi_startino, &p32->xi_startino) ||
if (put_user(buffer[i].xi_startino, &p32[i].xi_startino) || put_user(igrp->xi_alloccount, &p32->xi_alloccount) ||
put_user(buffer[i].xi_alloccount, &p32[i].xi_alloccount) || put_user(igrp->xi_allocmask, &p32->xi_allocmask))
put_user(buffer[i].xi_allocmask, &p32[i].xi_allocmask)) return -EFAULT;
return -EFAULT;
} return xfs_ibulk_advance(breq, sizeof(struct compat_xfs_inogrp));
*written = count * sizeof(*p32);
return 0;
} }
#else #else
...@@ -222,7 +217,7 @@ xfs_compat_ioc_bulkstat( ...@@ -222,7 +217,7 @@ xfs_compat_ioc_bulkstat(
* to userpace memory via bulkreq.ubuffer. Normally the compat * to userpace memory via bulkreq.ubuffer. Normally the compat
* functions and structure size are the correct ones to use ... * functions and structure size are the correct ones to use ...
*/ */
inumbers_fmt_pf inumbers_func = xfs_inumbers_fmt_compat; inumbers_fmt_pf inumbers_func = xfs_inumbers_fmt_compat;
bulkstat_one_fmt_pf bs_one_func = xfs_bulkstat_one_fmt_compat; bulkstat_one_fmt_pf bs_one_func = xfs_bulkstat_one_fmt_compat;
#ifdef CONFIG_X86_X32 #ifdef CONFIG_X86_X32
...@@ -284,13 +279,9 @@ xfs_compat_ioc_bulkstat( ...@@ -284,13 +279,9 @@ xfs_compat_ioc_bulkstat(
* in filesystem". * in filesystem".
*/ */
if (cmd == XFS_IOC_FSINUMBERS_32) { if (cmd == XFS_IOC_FSINUMBERS_32) {
int count = breq.icount; breq.startino = lastino ? lastino + 1 : 0;
error = xfs_inumbers(&breq, inumbers_func);
breq.startino = lastino; lastino = breq.startino - 1;
error = xfs_inumbers(mp, &breq.startino, &count,
bulkreq.ubuffer, inumbers_func);
breq.ocount = count;
lastino = breq.startino;
} else if (cmd == XFS_IOC_FSBULKSTAT_SINGLE_32) { } else if (cmd == XFS_IOC_FSBULKSTAT_SINGLE_32) {
breq.startino = lastino; breq.startino = lastino;
breq.icount = 1; breq.icount = 1;
......
...@@ -265,121 +265,81 @@ xfs_bulkstat( ...@@ -265,121 +265,81 @@ xfs_bulkstat(
return error; return error;
} }
int struct xfs_inumbers_chunk {
xfs_inumbers_fmt( inumbers_fmt_pf formatter;
void __user *ubuffer, /* buffer to write to */ struct xfs_ibulk *breq;
const struct xfs_inogrp *buffer, /* buffer to read from */ };
long count, /* # of elements to read */
long *written) /* # of bytes written */ /*
* INUMBERS
* ========
* This is how we export inode btree records to userspace, so that XFS tools
* can figure out where inodes are allocated.
*/
/*
* Format the inode group structure and report it somewhere.
*
* Similar to xfs_bulkstat_one_int, lastino is the inode cursor as we walk
* through the filesystem so we move it forward unless there was a runtime
* error. If the formatter tells us the buffer is now full we also move the
* cursor forward and abort the walk.
*/
STATIC int
xfs_inumbers_walk(
struct xfs_mount *mp,
struct xfs_trans *tp,
xfs_agnumber_t agno,
const struct xfs_inobt_rec_incore *irec,
void *data)
{ {
if (copy_to_user(ubuffer, buffer, count * sizeof(*buffer))) struct xfs_inogrp inogrp = {
return -EFAULT; .xi_startino = XFS_AGINO_TO_INO(mp, agno, irec->ir_startino),
*written = count * sizeof(*buffer); .xi_alloccount = irec->ir_count - irec->ir_freecount,
return 0; .xi_allocmask = ~irec->ir_free,
};
struct xfs_inumbers_chunk *ic = data;
xfs_agino_t agino;
int error;
error = ic->formatter(ic->breq, &inogrp);
if (error && error != XFS_IBULK_ABORT)
return error;
agino = irec->ir_startino + XFS_INODES_PER_CHUNK;
ic->breq->startino = XFS_AGINO_TO_INO(mp, agno, agino);
return error;
} }
/* /*
* Return inode number table for the filesystem. * Return inode number table for the filesystem.
*/ */
int /* error status */ int
xfs_inumbers( xfs_inumbers(
struct xfs_mount *mp,/* mount point for filesystem */ struct xfs_ibulk *breq,
xfs_ino_t *lastino,/* last inode returned */
int *count,/* size of buffer/count returned */
void __user *ubuffer,/* buffer with inode descriptions */
inumbers_fmt_pf formatter) inumbers_fmt_pf formatter)
{ {
xfs_agnumber_t agno = XFS_INO_TO_AGNO(mp, *lastino); struct xfs_inumbers_chunk ic = {
xfs_agino_t agino = XFS_INO_TO_AGINO(mp, *lastino); .formatter = formatter,
struct xfs_btree_cur *cur = NULL; .breq = breq,
struct xfs_buf *agbp = NULL; };
struct xfs_inogrp *buffer;
int bcount;
int left = *count;
int bufidx = 0;
int error = 0; int error = 0;
*count = 0; if (xfs_bulkstat_already_done(breq->mp, breq->startino))
if (agno >= mp->m_sb.sb_agcount || return 0;
*lastino != XFS_AGINO_TO_INO(mp, agno, agino))
return error;
bcount = min(left, (int)(PAGE_SIZE / sizeof(*buffer))); error = xfs_inobt_walk(breq->mp, NULL, breq->startino,
buffer = kmem_zalloc(bcount * sizeof(*buffer), KM_SLEEP); xfs_inumbers_walk, breq->icount, &ic);
do {
struct xfs_inobt_rec_incore r;
int stat;
if (!agbp) {
error = xfs_ialloc_read_agi(mp, NULL, agno, &agbp);
if (error)
break;
cur = xfs_inobt_init_cursor(mp, NULL, agbp, agno,
XFS_BTNUM_INO);
error = xfs_inobt_lookup(cur, agino, XFS_LOOKUP_GE,
&stat);
if (error)
break;
if (!stat)
goto next_ag;
}
error = xfs_inobt_get_rec(cur, &r, &stat);
if (error)
break;
if (!stat)
goto next_ag;
agino = r.ir_startino + XFS_INODES_PER_CHUNK - 1;
buffer[bufidx].xi_startino =
XFS_AGINO_TO_INO(mp, agno, r.ir_startino);
buffer[bufidx].xi_alloccount = r.ir_count - r.ir_freecount;
buffer[bufidx].xi_allocmask = ~r.ir_free;
if (++bufidx == bcount) {
long written;
error = formatter(ubuffer, buffer, bufidx, &written);
if (error)
break;
ubuffer += written;
*count += bufidx;
bufidx = 0;
}
if (!--left)
break;
error = xfs_btree_increment(cur, 0, &stat);
if (error)
break;
if (stat)
continue;
next_ag:
xfs_btree_del_cursor(cur, XFS_BTREE_ERROR);
cur = NULL;
xfs_buf_relse(agbp);
agbp = NULL;
agino = 0;
agno++;
} while (agno < mp->m_sb.sb_agcount);
if (!error) {
if (bufidx) {
long written;
error = formatter(ubuffer, buffer, bufidx, &written);
if (!error)
*count += bufidx;
}
*lastino = XFS_AGINO_TO_INO(mp, agno, agino);
}
kmem_free(buffer); /*
if (cur) * We found some inode groups, so clear the error status and return
xfs_btree_del_cursor(cur, error); * them. The lastino pointer will point directly at the inode that
if (agbp) * triggered any error that occurred, so on the next call the error
xfs_buf_relse(agbp); * will be triggered again and propagated to userspace as there will be
* no formatted inode groups in the buffer.
*/
if (breq->ocount > 0)
error = 0;
return error; return error;
} }
...@@ -43,25 +43,9 @@ typedef int (*bulkstat_one_fmt_pf)(struct xfs_ibulk *breq, ...@@ -43,25 +43,9 @@ typedef int (*bulkstat_one_fmt_pf)(struct xfs_ibulk *breq,
int xfs_bulkstat_one(struct xfs_ibulk *breq, bulkstat_one_fmt_pf formatter); int xfs_bulkstat_one(struct xfs_ibulk *breq, bulkstat_one_fmt_pf formatter);
int xfs_bulkstat(struct xfs_ibulk *breq, bulkstat_one_fmt_pf formatter); int xfs_bulkstat(struct xfs_ibulk *breq, bulkstat_one_fmt_pf formatter);
typedef int (*inumbers_fmt_pf)( typedef int (*inumbers_fmt_pf)(struct xfs_ibulk *breq,
void __user *ubuffer, /* buffer to write to */ const struct xfs_inogrp *igrp);
const xfs_inogrp_t *buffer, /* buffer to read from */
long count, /* # of elements to read */
long *written); /* # of bytes written */
int int xfs_inumbers(struct xfs_ibulk *breq, inumbers_fmt_pf formatter);
xfs_inumbers_fmt(
void __user *ubuffer, /* buffer to write to */
const xfs_inogrp_t *buffer, /* buffer to read from */
long count, /* # of elements to read */
long *written); /* # of bytes written */
int /* error status */
xfs_inumbers(
xfs_mount_t *mp, /* mount point for filesystem */
xfs_ino_t *last, /* last inode returned */
int *count, /* size of buffer/count returned */
void __user *buffer, /* buffer with inode info */
inumbers_fmt_pf formatter);
#endif /* __XFS_ITABLE_H__ */ #endif /* __XFS_ITABLE_H__ */
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment