public inbox for linux-xfs@vger.kernel.org
 help / color / mirror / Atom feed
From: Eric Sandeen <sandeen@sandeen.net>
To: Dave Chinner <david@fromorbit.com>
Cc: xfs@oss.sgi.com
Subject: Re: [PATCH 6/6] xfstests: add a multithreaded mode to bstat
Date: Thu, 17 Oct 2013 16:29:16 -0500	[thread overview]
Message-ID: <526056AC.4000307@sandeen.net> (raw)
In-Reply-To: <1370610398-14630-7-git-send-email-david@fromorbit.com>

On 6/7/13 8:06 AM, Dave Chinner wrote:
> From: Dave Chinner <dchinner@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@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;
>  }
> 

_______________________________________________
xfs mailing list
xfs@oss.sgi.com
http://oss.sgi.com/mailman/listinfo/xfs

  reply	other threads:[~2013-10-17 21:29 UTC|newest]

Thread overview: 14+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2013-06-07 13:06 [PATCH 0/6] xfstests: various fixes Dave Chinner
2013-06-07 13:06 ` [PATCH 1/6] xfstests: generic/193 runs tests in wrong location Dave Chinner
2013-06-25 19:49   ` Ben Myers
2013-06-07 13:06 ` [PATCH 2/6] xfstests: ensure all mkfs output is redirected properly Dave Chinner
2013-06-07 13:06 ` [PATCH 3/6] xfstests: xfs/253 doesn't use seqres correctly Dave Chinner
2013-06-25 20:27   ` Ben Myers
2013-06-07 13:06 ` [PATCH 4/6] xfstests: Make 204 work with different block and inode sizes Dave Chinner
2013-06-07 13:06 ` [PATCH 5/6] xfstests: New _require_* tests for CRC enabled filesystems Dave Chinner
2013-10-17 21:24   ` Eric Sandeen
2013-10-18  2:58     ` Dave Chinner
2013-06-07 13:06 ` [PATCH 6/6] xfstests: add a multithreaded mode to bstat Dave Chinner
2013-10-17 21:29   ` Eric Sandeen [this message]
2013-10-18  3:00     ` Dave Chinner
2013-10-18  3:39       ` Eric Sandeen

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=526056AC.4000307@sandeen.net \
    --to=sandeen@sandeen.net \
    --cc=david@fromorbit.com \
    --cc=xfs@oss.sgi.com \
    /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