[PATCH 6/6] xfstests: add a multithreaded mode to bstat
Eric Sandeen
sandeen at sandeen.net
Thu Oct 17 16:29:16 CDT 2013
On 6/7/13 8:06 AM, Dave Chinner wrote:
> From: Dave Chinner <dchinner at redhat.com>
>
> For benchmarking of bulkstat, add a multithreaded mode that spawns a
> thread per AG and runs bulkstat on every AG in parallel. There is a
> small amount of overlap between each AG because of the way the
> interface works only on inode numbers, so some inodes are reported
> twice. A real implementation of this sort of parallelism would be
> greatly helped by adding an AG parameter to the bulkstat interface.
>
> Signed-off-by: Dave Chinner <dchinner at redhat.com>
At least w/ older xfsprogs[[qa]-devel] packages, I get:
bstat.c:41: error: redefinition of 'fls'
/usr/include/xfs/bitops.h:8: note: previous definition of 'fls' was here
bstat.c:70: error: redefinition of 'xfs_highbit32'
/usr/include/xfs/xfs_bit.h:50: note: previous definition of 'xfs_highbit32' was here
w/ the new functions you've added here...
-Eric
> ---
> src/Makefile | 2 +-
> src/bstat.c | 388 +++++++++++++++++++++++++++++++++++++++++++++-------------
> 2 files changed, 302 insertions(+), 88 deletions(-)
>
> diff --git a/src/Makefile b/src/Makefile
> index c18ffc9..243a432 100644
> --- a/src/Makefile
> +++ b/src/Makefile
> @@ -22,7 +22,7 @@ LINUX_TARGETS = xfsctl bstat t_mtab getdevicesize preallo_rw_pattern_reader \
>
> SUBDIRS =
>
> -LLDLIBS = $(LIBATTR) $(LIBHANDLE) $(LIBACL)
> +LLDLIBS = $(LIBATTR) $(LIBHANDLE) $(LIBACL) -lpthread
>
> ifeq ($(HAVE_XLOG_ASSIGN_LSN), true)
> LINUX_TARGETS += loggen
> diff --git a/src/bstat.c b/src/bstat.c
> index 4e22ecd..0fc7d9d 100644
> --- a/src/bstat.c
> +++ b/src/bstat.c
> @@ -18,6 +18,60 @@
>
> #include "global.h"
> #include <xfs/jdm.h>
> +#include <pthread.h>
> +
> +
> +int debug;
> +int quiet;
> +int statit;
> +int verbose;
> +int threaded;
> +
> +unsigned int
> +libxfs_log2_roundup(unsigned int i)
> +{
> + unsigned int rval;
> +
> + for (rval = 0; rval < NBBY * sizeof(i); rval++) {
> + if ((1 << rval) >= i)
> + break;
> + }
> + return rval;
> +}
> +static inline int fls(int x)
> +{
> + int r = 32;
> +
> + if (!x)
> + return 0;
> + if (!(x & 0xffff0000u)) {
> + x <<= 16;
> + r -= 16;
> + }
> + if (!(x & 0xff000000u)) {
> + x <<= 8;
> + r -= 8;
> + }
> + if (!(x & 0xf0000000u)) {
> + x <<= 4;
> + r -= 4;
> + }
> + if (!(x & 0xc0000000u)) {
> + x <<= 2;
> + r -= 2;
> + }
> + if (!(x & 0x80000000u)) {
> + x <<= 1;
> + r -= 1;
> + }
> + return r;
> +}
> +
> +static inline int xfs_highbit32(__uint32_t v)
> +{
> + return fls(v) - 1;
> +}
> +
>
> void
> dotime(void *ti, char *s)
> @@ -62,87 +116,21 @@ printstat(struct stat64 *sp)
> dotime(&sp->st_ctime, "ctime");
> }
>
> -int
> -main(int argc, char **argv)
> +static int
> +do_bstat(
> + int fsfd,
> + jdm_fshandle_t *fshandlep,
> + char *name,
> + int nent,
> + __u64 first,
> + __u64 last)
> {
> __s32 count;
> int total = 0;
> - int fsfd;
> - int i;
> - __u64 last = 0;
> - char *name;
> - int nent;
> - int debug = 0;
> - int quiet = 0;
> - int statit = 0;
> - int verbose = 0;
> xfs_bstat_t *t;
> int ret;
> - jdm_fshandle_t *fshandlep = NULL;
> - int fd;
> - struct stat64 sb;
> - int nread;
> - char *cc_readlinkbufp;
> - int cc_readlinkbufsz;
> - int c;
> xfs_fsop_bulkreq_t bulkreq;
> -
> - while ((c = getopt(argc, argv, "cdl:qv")) != -1) {
> - switch (c) {
> - case 'q':
> - quiet = 1;
> - break;
> - case 'v':
> - verbose = 1;
> - break;
> - case 'c':
> - statit = 1;
> - break;
> - case 'd':
> - debug = 1;
> - break;
> - case 'l':
> - last = atoi(optarg);
> - break;
> - case '?':
> - printf("usage: xfs_bstat [-c] [-q] [-v] [ dir [ batch_size ]]\n");
> - printf(" -c Check the results against stat(3) output\n");
> - printf(" -q Quiet\n");
> - printf(" -l _num_ Inode to start with\n");
> - printf(" -v Verbose output\n");
> - exit(1);
> - }
> - }
> - argc -= optind;
> - argv += optind;
> -
> - if (argc < 1)
> - name = ".";
> - else
> - name = *argv;
> -
> - fsfd = open(name, O_RDONLY);
> - if (fsfd < 0) {
> - perror(name);
> - exit(1);
> - }
> - if (argc < 2)
> - nent = 4096;
> - else
> - nent = atoi(*++argv);
> -
> - if (verbose)
> - printf("Bulkstat test on %s, batch size=%d statcheck=%d\n",
> - name, nent, statit);
> -
> - if (statit) {
> - fshandlep = jdm_getfshandle( name );
> - if (! fshandlep) {
> - printf("unable to construct sys handle for %s: %s\n",
> - name, strerror(errno));
> - return -1;
> - }
> - }
> + __u64 ino;
>
> t = malloc(nent * sizeof(*t));
>
> @@ -150,23 +138,27 @@ main(int argc, char **argv)
> printf(
> "XFS_IOC_FSBULKSTAT test: last=%lld nent=%d\n", (long long)last, nent);
>
> - bulkreq.lastip = &last;
> + ino = first;
> +
> + bulkreq.lastip = &ino;
> bulkreq.icount = nent;
> bulkreq.ubuffer = t;
> bulkreq.ocount = &count;
>
> while ((ret = xfsctl(name, fsfd, XFS_IOC_FSBULKSTAT, &bulkreq)) == 0) {
> + int i;
> +
> total += count;
>
> if (verbose)
> printf(
> - "XFS_IOC_FSBULKSTAT test: last=%lld ret=%d count=%d total=%d\n",
> - (long long)last, ret, count, total);
> + "XFS_IOC_FSBULKSTAT test: first/last/ino=%lld/%lld/%lld ret=%d count=%d total=%d\n",
> + (long long)first, (long long)last, (long long)ino, ret, count, total);
> if (count == 0)
> - exit(0);
> + break;
>
> if ( quiet && ! statit )
> - continue;
> + goto next;
>
> for (i = 0; i < count; i++) {
> if (! quiet) {
> @@ -174,6 +166,12 @@ main(int argc, char **argv)
> }
>
> if (statit) {
> + char *cc_readlinkbufp;
> + int cc_readlinkbufsz;
> + struct stat64 sb;
> + int nread;
> + int fd;
> +
> switch(t[i].bs_mode & S_IFMT) {
> case S_IFLNK:
> cc_readlinkbufsz = MAXPATHLEN;
> @@ -244,10 +242,231 @@ main(int argc, char **argv)
> }
> }
> }
> -
> +next:
> if (debug)
> break;
> +
> + if (ino >= last)
> + break;
> }
> + if (verbose)
> + printf(
> + "XFS_IOC_FSBULKSTAT test: last=%lld nent=%d ret=%d count=%d\n",
> + (long long)last, nent, ret, count);
> +
> + return total;
> +}
> +
> +struct thread_args {
> + pthread_t tid;
> + int fsfd;
> + jdm_fshandle_t *fshandlep;
> + char *name;
> + int nent;
> + __u64 first;
> + __u64 last;
> + int ret;
> +};
> +
> +static void *
> +do_bstat_thread(
> + void *args)
> +{
> + struct thread_args *targs = args;
> +
> + targs->ret = do_bstat(targs->fsfd, targs->fshandlep, targs->name,
> + targs->nent, targs->first, targs->last);
> + return NULL;
> +}
> +
> +/*
> + * XFS_AGINO_TO_INO(mp,a,i) \
> + * (((xfs_ino_t)(a) << XFS_INO_AGINO_BITS(mp)) | (i))
> + *
> + * i always zero, so:
> + * a << XFS_INO_AGINO_BITS(mp)
> + *
> + * XFS_INO_AGINO_BITS(mp) (mp)->m_agino_log
> + *
> + * mp->m_agino_log = sbp->sb_inopblog + sbp->sb_agblklog
> + *
> + * sb_inopblog = fsgeom.blocksize / fsgeom.inodesize
> + * sb_agblklog = (__uint8_t)libxfs_log2_roundup((unsigned int)fsgeom.agblocks);
> + *
> + * a << (libxfs_highbit32(fsgeom.blocksize /fsgeom.inodesize) +
> + * libxfs_log2_roundup(fsgeom.agblocks));
> + */
> +#define FSGEOM_INOPBLOG(fsg) \
> + (xfs_highbit32((fsg).blocksize / (fsg).inodesize))
> +#define FSGEOM_AGINO_TO_INO(fsg, a, i) \
> + (((__u64)(a) << (FSGEOM_INOPBLOG(fsg) + \
> + libxfs_log2_roundup((fsg).agblocks))) | (i))
> +
> +/*
> + * XFS_OFFBNO_TO_AGINO(mp,b,o) \
> + * ((xfs_agino_t)(((b) << XFS_INO_OFFSET_BITS(mp)) | (o)))
> + *
> + * i always zero, so:
> + * b << XFS_INO_OFFSET_BITS(mp)
> + *
> + * XFS_INO_OFFSET_BITS(mp) (mp)->m_sb.sb_inopblog
> + */
> +#define FSGEOM_OFFBNO_TO_AGINO(fsg, b, o) \
> + ((__u32)(((b) << FSGEOM_INOPBLOG(fsg)) | (o)))
> +static int
> +do_threads(
> + int fsfd,
> + jdm_fshandle_t *fshandlep,
> + char *name,
> + int nent,
> + __u64 first)
> +{
> + struct xfs_fsop_geom geom;
> + struct thread_args *targs;
> + int ret;
> + int i;
> + int numthreads;
> + int total = 0;
> +
> +
> + /* get number of AGs */
> + ret = ioctl(fsfd, XFS_IOC_FSGEOMETRY, &geom);
> + if (ret) {
> + perror("XFS_IOC_FSGEOMETRY");
> + exit(1);
> + }
> +
> + /* allocate thread array */
> + targs = malloc(geom.agcount * sizeof(*targs));
> + if (ret) {
> + perror("malloc(targs)");
> + exit(1);
> + }
> +
> + for (i = 0; i < geom.agcount; i++) {
> + __u64 last;
> +
> + last = FSGEOM_AGINO_TO_INO(geom, i,
> + FSGEOM_OFFBNO_TO_AGINO(geom,
> + geom.agblocks - 1, 0));
> +
> + if (first > last) {
> + i--;
> + continue;
> + }
> + first = MAX(first, FSGEOM_AGINO_TO_INO(geom, i, 0));
> +
> + targs[i].fsfd = fsfd;
> + targs[i].fshandlep = fshandlep;
> + targs[i].name = name;
> + targs[i].nent = nent;
> + targs[i].first = first;
> + targs[i].last = last;
> + targs[i].ret = 0;
> + }
> + numthreads = i;
> +
> + /* start threads */
> + for (i = 0; i< numthreads; i++) {
> + ret = pthread_create(&targs[i].tid, NULL, do_bstat_thread, &targs[i]);
> + if (ret) {
> + perror("pthread-create");
> + exit(1);
> + }
> + }
> +
> +
> + /* join threads */
> + for (i = 0; i < numthreads; i++) {
> + if (targs[i].tid) {
> + pthread_join(targs[i].tid, NULL);
> + total += targs[i].ret;
> + }
> + }
> +
> + /* die */
> + return total;
> +}
> +
> +
> +int
> +main(int argc, char **argv)
> +{
> + int fsfd;
> + __u64 first = 0;
> + char *name;
> + int nent;
> + int ret;
> + jdm_fshandle_t *fshandlep = NULL;
> + int c;
> +
> + while ((c = getopt(argc, argv, "cdl:qtv")) != -1) {
> + switch (c) {
> + case 'q':
> + quiet = 1;
> + break;
> + case 'v':
> + verbose = 1;
> + break;
> + case 'c':
> + statit = 1;
> + break;
> + case 'd':
> + debug = 1;
> + break;
> + case 'l':
> + first = atoi(optarg);
> + break;
> + case 't':
> + threaded = 1;
> + break;
> + case '?':
> + printf("usage: xfs_bstat [-c] [-q] [-v] [ dir [ batch_size ]]\n");
> + printf(" -c Check the results against stat(3) output\n");
> + printf(" -q Quiet\n");
> + printf(" -l _num_ Inode to start with\n");
> + printf(" -v Verbose output\n");
> + exit(1);
> + }
> + }
> + argc -= optind;
> + argv += optind;
> +
> + if (argc < 1)
> + name = ".";
> + else
> + name = *argv;
> +
> + fsfd = open(name, O_RDONLY);
> + if (fsfd < 0) {
> + perror(name);
> + exit(1);
> + }
> + if (argc < 2)
> + nent = 4096;
> + else
> + nent = atoi(*++argv);
> +
> + if (verbose)
> + printf("Bulkstat test on %s, batch size=%d statcheck=%d\n",
> + name, nent, statit);
> +
> + if (statit) {
> + fshandlep = jdm_getfshandle( name );
> + if (! fshandlep) {
> + printf("unable to construct sys handle for %s: %s\n",
> + name, strerror(errno));
> + return -1;
> + }
> + }
> +
> + if (threaded)
> + ret = do_threads(fsfd, fshandlep, name, nent, first);
> + else
> + ret = do_bstat(fsfd, fshandlep, name, nent, first, -1LL);
> +
> + if (verbose)
> + printf("Bulkstat found %d inodes\n", ret);
>
> if (fsfd)
> close(fsfd);
> @@ -255,10 +474,5 @@ main(int argc, char **argv)
> if (ret < 0 )
> perror("xfsctl(XFS_IOC_FSBULKSTAT)");
>
> - if (verbose)
> - printf(
> - "XFS_IOC_FSBULKSTAT test: last=%lld nent=%d ret=%d count=%d\n",
> - (long long)last, nent, ret, count);
> -
> - return 1;
> + return 0;
> }
>
More information about the xfs
mailing list