xfs
[Top] [All Lists]

Re: [PATCH 6/6] xfstests: add a multithreaded mode to bstat

To: Dave Chinner <david@xxxxxxxxxxxxx>
Subject: Re: [PATCH 6/6] xfstests: add a multithreaded mode to bstat
From: Eric Sandeen <sandeen@xxxxxxxxxxx>
Date: Thu, 17 Oct 2013 16:29:16 -0500
Cc: xfs@xxxxxxxxxxx
Delivered-to: xfs@xxxxxxxxxxx
In-reply-to: <1370610398-14630-7-git-send-email-david@xxxxxxxxxxxxx>
References: <1370610398-14630-1-git-send-email-david@xxxxxxxxxxxxx> <1370610398-14630-7-git-send-email-david@xxxxxxxxxxxxx>
User-agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10.8; rv:17.0) Gecko/20130801 Thunderbird/17.0.8
On 6/7/13 8:06 AM, Dave Chinner wrote:
> From: Dave Chinner <dchinner@xxxxxxxxxx>
> 
> 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@xxxxxxxxxx>

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;
>  }
> 

<Prev in Thread] Current Thread [Next in Thread>