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

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



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

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




[Index of Archives]     [Linux XFS Devel]     [Linux Filesystem Development]     [Filesystem Testing]     [Linux USB Devel]     [Linux Audio Users]     [Yosemite News]     [Linux Kernel]     [Linux SCSI]

  Powered by Linux