From: Brian Foster <bfoster@redhat.com>
To: "Darrick J. Wong" <darrick.wong@oracle.com>
Cc: linux-xfs@vger.kernel.org
Subject: Re: [PATCH 12/14] xfs: refactor INUMBERS to use iwalk functions
Date: Fri, 14 Jun 2019 10:05:02 -0400 [thread overview]
Message-ID: <20190614140502.GD26586@bfoster> (raw)
In-Reply-To: <156032212910.3774243.13112993369352430725.stgit@magnolia>
On Tue, Jun 11, 2019 at 11:48:49PM -0700, Darrick J. Wong wrote:
> From: Darrick J. Wong <darrick.wong@oracle.com>
>
> Now that we have generic functions to walk inode records, refactor the
> INUMBERS implementation to use it.
>
> Signed-off-by: Darrick J. Wong <darrick.wong@oracle.com>
> ---
Modulo the error code stuff:
Reviewed-by: Brian Foster <bfoster@redhat.com>
> fs/xfs/xfs_ioctl.c | 20 ++++--
> fs/xfs/xfs_ioctl.h | 2 +
> fs/xfs/xfs_ioctl32.c | 35 ++++-------
> fs/xfs/xfs_itable.c | 166 +++++++++++++++++++-------------------------------
> fs/xfs/xfs_itable.h | 22 +------
> 5 files changed, 95 insertions(+), 150 deletions(-)
>
>
> diff --git a/fs/xfs/xfs_ioctl.c b/fs/xfs/xfs_ioctl.c
> index 60595e61f2a6..04b661ff0799 100644
> --- a/fs/xfs/xfs_ioctl.c
> +++ b/fs/xfs/xfs_ioctl.c
> @@ -733,6 +733,16 @@ xfs_bulkstat_one_fmt(
> 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
> xfs_ioc_bulkstat(
> xfs_mount_t *mp,
> @@ -783,13 +793,9 @@ xfs_ioc_bulkstat(
> * in filesystem".
> */
> if (cmd == XFS_IOC_FSINUMBERS) {
> - int count = breq.icount;
> -
> - breq.startino = lastino;
> - error = xfs_inumbers(mp, &breq.startino, &count,
> - bulkreq.ubuffer, xfs_inumbers_fmt);
> - breq.ocount = count;
> - lastino = breq.startino;
> + breq.startino = lastino ? lastino + 1 : 0;
> + error = xfs_inumbers(&breq, xfs_inumbers_fmt);
> + lastino = breq.startino - 1;
> } else if (cmd == XFS_IOC_FSBULKSTAT_SINGLE) {
> breq.startino = lastino;
> breq.icount = 1;
> diff --git a/fs/xfs/xfs_ioctl.h b/fs/xfs/xfs_ioctl.h
> index f32c8aadfeba..fb303eaa8863 100644
> --- a/fs/xfs/xfs_ioctl.h
> +++ b/fs/xfs/xfs_ioctl.h
> @@ -79,7 +79,9 @@ xfs_set_dmattrs(
>
> struct xfs_ibulk;
> struct xfs_bstat;
> +struct xfs_inogrp;
>
> 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
> diff --git a/fs/xfs/xfs_ioctl32.c b/fs/xfs/xfs_ioctl32.c
> index 5d1c143bac18..3ca8ff9d4ac7 100644
> --- a/fs/xfs/xfs_ioctl32.c
> +++ b/fs/xfs/xfs_ioctl32.c
> @@ -87,22 +87,17 @@ xfs_compat_growfs_rt_copyin(
>
> STATIC int
> xfs_inumbers_fmt_compat(
> - void __user *ubuffer,
> - const struct xfs_inogrp *buffer,
> - long count,
> - long *written)
> + struct xfs_ibulk *breq,
> + const struct xfs_inogrp *igrp)
> {
> - compat_xfs_inogrp_t __user *p32 = ubuffer;
> - long i;
> + struct compat_xfs_inogrp __user *p32 = breq->ubuffer;
>
> - for (i = 0; i < count; i++) {
> - if (put_user(buffer[i].xi_startino, &p32[i].xi_startino) ||
> - put_user(buffer[i].xi_alloccount, &p32[i].xi_alloccount) ||
> - put_user(buffer[i].xi_allocmask, &p32[i].xi_allocmask))
> - return -EFAULT;
> - }
> - *written = count * sizeof(*p32);
> - return 0;
> + if (put_user(igrp->xi_startino, &p32->xi_startino) ||
> + put_user(igrp->xi_alloccount, &p32->xi_alloccount) ||
> + put_user(igrp->xi_allocmask, &p32->xi_allocmask))
> + return -EFAULT;
> +
> + return xfs_ibulk_advance(breq, sizeof(struct compat_xfs_inogrp));
> }
>
> #else
> @@ -228,7 +223,7 @@ xfs_compat_ioc_bulkstat(
> * to userpace memory via bulkreq.ubuffer. Normally the compat
> * 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;
>
> #ifdef CONFIG_X86_X32
> @@ -291,13 +286,9 @@ xfs_compat_ioc_bulkstat(
> * in filesystem".
> */
> if (cmd == XFS_IOC_FSINUMBERS_32) {
> - int count = breq.icount;
> -
> - breq.startino = lastino;
> - error = xfs_inumbers(mp, &breq.startino, &count,
> - bulkreq.ubuffer, inumbers_func);
> - breq.ocount = count;
> - lastino = breq.startino;
> + breq.startino = lastino ? lastino + 1 : 0;
> + error = xfs_inumbers(&breq, inumbers_func);
> + lastino = breq.startino - 1;
> } else if (cmd == XFS_IOC_FSBULKSTAT_SINGLE_32) {
> breq.startino = lastino;
> breq.icount = 1;
> diff --git a/fs/xfs/xfs_itable.c b/fs/xfs/xfs_itable.c
> index 1b3c9feb5f6f..b2f640ecb507 100644
> --- a/fs/xfs/xfs_itable.c
> +++ b/fs/xfs/xfs_itable.c
> @@ -269,121 +269,83 @@ xfs_bulkstat(
> return error;
> }
>
> -int
> -xfs_inumbers_fmt(
> - void __user *ubuffer, /* buffer to write to */
> - const struct xfs_inogrp *buffer, /* buffer to read from */
> - long count, /* # of elements to read */
> - long *written) /* # of bytes written */
> +struct xfs_inumbers_chunk {
> + inumbers_fmt_pf formatter;
> + struct xfs_ibulk *breq;
> +};
> +
> +/*
> + * 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)))
> - return -EFAULT;
> - *written = count * sizeof(*buffer);
> - return 0;
> + struct xfs_inogrp inogrp = {
> + .xi_startino = XFS_AGINO_TO_INO(mp, agno, irec->ir_startino),
> + .xi_alloccount = irec->ir_count - irec->ir_freecount,
> + .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_BUFFER_FULL)
> + return error;
> + if (error == XFS_IBULK_BUFFER_FULL)
> + error = XFS_INOBT_WALK_ABORT;
> +
> + 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.
> */
> -int /* error status */
> +int
> xfs_inumbers(
> - struct xfs_mount *mp,/* mount point for filesystem */
> - xfs_ino_t *lastino,/* last inode returned */
> - int *count,/* size of buffer/count returned */
> - void __user *ubuffer,/* buffer with inode descriptions */
> + struct xfs_ibulk *breq,
> inumbers_fmt_pf formatter)
> {
> - xfs_agnumber_t agno = XFS_INO_TO_AGNO(mp, *lastino);
> - xfs_agino_t agino = XFS_INO_TO_AGINO(mp, *lastino);
> - struct xfs_btree_cur *cur = NULL;
> - struct xfs_buf *agbp = NULL;
> - struct xfs_inogrp *buffer;
> - int bcount;
> - int left = *count;
> - int bufidx = 0;
> + struct xfs_inumbers_chunk ic = {
> + .formatter = formatter,
> + .breq = breq,
> + };
> int error = 0;
>
> - *count = 0;
> - if (agno >= mp->m_sb.sb_agcount ||
> - *lastino != XFS_AGINO_TO_INO(mp, agno, agino))
> - return error;
> + if (xfs_bulkstat_already_done(breq->mp, breq->startino))
> + return 0;
>
> - bcount = min(left, (int)(PAGE_SIZE / sizeof(*buffer)));
> - buffer = kmem_zalloc(bcount * sizeof(*buffer), KM_SLEEP);
> - 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);
> - }
> + error = xfs_inobt_walk(breq->mp, NULL, breq->startino,
> + xfs_inumbers_walk, breq->icount, &ic);
>
> - kmem_free(buffer);
> - if (cur)
> - xfs_btree_del_cursor(cur, error);
> - if (agbp)
> - xfs_buf_relse(agbp);
> + /*
> + * We found some inode groups, so clear the error status and return
> + * them. The lastino pointer will point directly at the inode that
> + * triggered any error that occurred, so on the next call the error
> + * 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;
> }
> diff --git a/fs/xfs/xfs_itable.h b/fs/xfs/xfs_itable.h
> index 328a161b8898..1e1a5bb9fd9f 100644
> --- a/fs/xfs/xfs_itable.h
> +++ b/fs/xfs/xfs_itable.h
> @@ -46,25 +46,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(struct xfs_ibulk *breq, bulkstat_one_fmt_pf formatter);
>
> -typedef int (*inumbers_fmt_pf)(
> - 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 */
> +typedef int (*inumbers_fmt_pf)(struct xfs_ibulk *breq,
> + const struct xfs_inogrp *igrp);
>
> -int
> -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);
> +int xfs_inumbers(struct xfs_ibulk *breq, inumbers_fmt_pf formatter);
>
> #endif /* __XFS_ITABLE_H__ */
>
next prev parent reply other threads:[~2019-06-14 14:05 UTC|newest]
Thread overview: 33+ messages / expand[flat|nested] mbox.gz Atom feed top
2019-06-12 6:47 [PATCH v5 00/14] xfs: refactor and improve inode iteration Darrick J. Wong
2019-06-12 6:47 ` [PATCH 01/14] xfs: create iterator error codes Darrick J. Wong
2019-06-13 16:24 ` Brian Foster
2019-06-12 6:47 ` [PATCH 02/14] xfs: create simplified inode walk function Darrick J. Wong
2019-06-13 16:27 ` Brian Foster
2019-06-13 18:06 ` Darrick J. Wong
2019-06-13 18:07 ` Darrick J. Wong
2019-06-12 6:47 ` [PATCH 03/14] xfs: convert quotacheck to use the new iwalk functions Darrick J. Wong
2019-06-12 6:47 ` [PATCH 04/14] xfs: bulkstat should copy lastip whenever userspace supplies one Darrick J. Wong
2019-06-12 6:48 ` [PATCH 05/14] xfs: remove unnecessary includes of xfs_itable.h Darrick J. Wong
2019-06-13 16:27 ` Brian Foster
2019-06-12 6:48 ` [PATCH 06/14] xfs: convert bulkstat to new iwalk infrastructure Darrick J. Wong
2019-06-13 16:31 ` Brian Foster
2019-06-13 18:12 ` Darrick J. Wong
2019-06-13 23:03 ` Darrick J. Wong
2019-06-14 11:10 ` Brian Foster
2019-06-14 16:45 ` Darrick J. Wong
2019-07-02 11:42 ` Brian Foster
2019-07-02 15:33 ` Darrick J. Wong
2019-06-12 6:48 ` [PATCH 07/14] xfs: move bulkstat ichunk helpers to iwalk code Darrick J. Wong
2019-06-12 6:48 ` [PATCH 08/14] xfs: change xfs_iwalk_grab_ichunk to use startino, not lastino Darrick J. Wong
2019-06-12 6:48 ` [PATCH 09/14] xfs: clean up long conditionals in xfs_iwalk_ichunk_ra Darrick J. Wong
2019-06-12 6:48 ` [PATCH 10/14] xfs: refactor xfs_iwalk_grab_ichunk Darrick J. Wong
2019-06-14 14:04 ` Brian Foster
2019-06-12 6:48 ` [PATCH 11/14] xfs: refactor iwalk code to handle walking inobt records Darrick J. Wong
2019-06-14 14:04 ` Brian Foster
2019-06-12 6:48 ` [PATCH 12/14] xfs: refactor INUMBERS to use iwalk functions Darrick J. Wong
2019-06-14 14:05 ` Brian Foster [this message]
2019-06-12 6:48 ` [PATCH 13/14] xfs: multithreaded iwalk implementation Darrick J. Wong
2019-06-14 14:06 ` Brian Foster
2019-06-18 18:17 ` Darrick J. Wong
2019-06-12 6:49 ` [PATCH 14/14] xfs: poll waiting for quotacheck Darrick J. Wong
2019-06-14 14:07 ` Brian Foster
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20190614140502.GD26586@bfoster \
--to=bfoster@redhat.com \
--cc=darrick.wong@oracle.com \
--cc=linux-xfs@vger.kernel.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox