• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  *   Copyright (c) International Business Machines Corp., 2001-2004
3  *
4  *   This program is free software;  you can redistribute it and/or modify
5  *   it under the terms of the GNU General Public License as published by
6  *   the Free Software Foundation; either version 2 of the License, or
7  *   (at your option) any later version.
8  *
9  *   This program is distributed in the hope that it will be useful,
10  *   but WITHOUT ANY WARRANTY;  without even the implied warranty of
11  *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See
12  *   the GNU General Public License for more details.
13  *
14  *   You should have received a copy of the GNU General Public License
15  *   along with this program;  if not, write to the Free Software
16  *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
17  */
18 #include <string.h>
19 #include <stdio.h>
20 #include <assert.h>
21 #include <pthread.h>
22 
23 #include "ffsb_tg.h"
24 #include "util.h"
25 
init_ffsb_tg(ffsb_tg_t * tg,unsigned num_threads,unsigned tg_num)26 void init_ffsb_tg(ffsb_tg_t * tg, unsigned num_threads, unsigned tg_num)
27 {
28 	int i;
29 	memset(tg, 0, sizeof(ffsb_tg_t));
30 
31 	tg->threads = ffsb_malloc(sizeof(ffsb_thread_t) * num_threads);
32 	tg->tg_num = tg_num;
33 	tg->num_threads = num_threads;
34 
35 	tg->bindfs = -1;	/* default is not bound */
36 
37 	tg->thread_bufsize = 0;
38 	for (i = 0; i < num_threads; i++)
39 		init_ffsb_thread(tg->threads + i, tg, 0, tg_num, i);
40 }
41 
destroy_ffsb_tg(ffsb_tg_t * tg)42 void destroy_ffsb_tg(ffsb_tg_t * tg)
43 {
44 	int i;
45 	for (i = 0; i < tg->num_threads; i++)
46 		destroy_ffsb_thread(tg->threads + i);
47 	free(tg->threads);
48 	if (tg_needs_stats(tg))
49 		ffsb_statsc_destroy(&tg->fsc);
50 }
51 
tg_run(void * data)52 void *tg_run(void *data)
53 {
54 	tg_run_params_t *params = (tg_run_params_t *) data;
55 	ffsb_tg_t *tg = params->tg;
56 	int i;
57 	pthread_attr_t attr;
58 
59 	pthread_attr_init(&attr);
60 	pthread_attr_setscope(&attr, PTHREAD_SCOPE_SYSTEM);
61 
62 	tg->start_barrier = params->thread_barrier;
63 
64 	/* Sum up the weights for use later by tg_get_op() */
65 	tg->sum_weights = 0;
66 	for (i = 0; i < FFSB_NUMOPS; i++)
67 		tg->sum_weights += tg->op_weights[i];
68 
69 	tg->fc = params->fc;
70 	tg->flagval = -1;
71 	tg->stopval = 1;
72 
73 	/* spawn threads */
74 	for (i = 0; i < tg->num_threads; i++) {
75 		ffsb_thread_t *ft = &tg->threads[i];
76 		pthread_create(&ft->ptid, &attr, ft_run, ft);
77 	}
78 
79 	if (params->tg_barrier)
80 		ffsb_barrier_wait(params->tg_barrier);
81 
82 	/* wait for termination condition to be true */
83 	do {
84 		ffsb_sleep(params->wait_time);
85 	} while (params->poll_fn(params->poll_data) == 0);
86 
87 	/* set flag value */
88 	tg->flagval = tg->stopval;
89 
90 	/* wait on theads to finish */
91 	for (i = 0; i < tg->num_threads; i++)
92 		pthread_join(tg->threads[i].ptid, NULL);
93 
94 	return NULL;
95 }
96 
97 /* Needs to set params->opnum and params->fs */
tg_get_op(ffsb_tg_t * tg,randdata_t * rd,tg_op_params_t * params)98 void tg_get_op(ffsb_tg_t * tg, randdata_t * rd, tg_op_params_t * params)
99 {
100 	unsigned curop;
101 	int num;
102 	int fsnum;
103 
104 	num = 1 + getrandom(rd, tg->sum_weights);
105 	curop = 0;
106 
107 	while (tg->op_weights[curop] < num) {
108 		num -= tg->op_weights[curop];
109 		curop++;
110 	}
111 
112 	params->opnum = curop;
113 
114 	/* If we're bound to a particular filesystem, use that,
115 	 * otherwise, pick one at random.
116 	 */
117 	fsnum = tg->bindfs;
118 	if (fsnum < 0)
119 		fsnum = getrandom(rd, tg->fc->num_filesys);
120 
121 	params->fs = fc_get_fs(tg->fc, fsnum);
122 }
123 
tg_set_op_weight(ffsb_tg_t * tg,char * opname,unsigned weight)124 void tg_set_op_weight(ffsb_tg_t * tg, char *opname, unsigned weight)
125 {
126 	int opnum = ops_find_op(opname);
127 	assert(opnum >= 0);
128 	tg->op_weights[opnum] = weight;
129 }
130 
tg_get_op_weight(ffsb_tg_t * tg,char * opname)131 unsigned tg_get_op_weight(ffsb_tg_t * tg, char *opname)
132 {
133 	int opnum = ops_find_op(opname);
134 	assert(opnum >= 0);
135 	return tg->op_weights[opnum];
136 }
137 
tg_set_bindfs(ffsb_tg_t * tg,int fsnum)138 void tg_set_bindfs(ffsb_tg_t * tg, int fsnum)
139 {
140 	tg->bindfs = fsnum;
141 }
142 
tg_get_bindfs(ffsb_tg_t * tg)143 int tg_get_bindfs(ffsb_tg_t * tg)
144 {
145 	return tg->bindfs;
146 }
147 
tg_get_numthreads(ffsb_tg_t * tg)148 unsigned tg_get_numthreads(ffsb_tg_t * tg)
149 {
150 	return tg->num_threads;
151 }
152 
update_bufsize(ffsb_tg_t * tg)153 static void update_bufsize(ffsb_tg_t * tg)
154 {
155 	int i;
156 	uint32_t newmax = max(tg->read_blocksize, tg->write_blocksize);
157 
158 	if (newmax == max(newmax, tg->thread_bufsize))
159 		for (i = 0; i < tg->num_threads; i++)
160 			ft_alter_bufsize(tg->threads + i, newmax);
161 }
162 
tg_set_read_random(ffsb_tg_t * tg,int rr)163 void tg_set_read_random(ffsb_tg_t * tg, int rr)
164 {
165 	tg->read_random = rr;
166 }
167 
tg_set_write_random(ffsb_tg_t * tg,int wr)168 void tg_set_write_random(ffsb_tg_t * tg, int wr)
169 {
170 	tg->write_random = wr;
171 }
172 
tg_set_fsync_file(ffsb_tg_t * tg,int fsync)173 void tg_set_fsync_file(ffsb_tg_t * tg, int fsync)
174 {
175 	tg->fsync_file = fsync;
176 }
177 
tg_set_read_size(ffsb_tg_t * tg,uint64_t rs)178 void tg_set_read_size(ffsb_tg_t * tg, uint64_t rs)
179 {
180 	tg->read_size = rs;
181 }
182 
tg_set_read_blocksize(ffsb_tg_t * tg,uint32_t rs)183 void tg_set_read_blocksize(ffsb_tg_t * tg, uint32_t rs)
184 {
185 	tg->read_blocksize = rs;
186 	update_bufsize(tg);
187 }
188 
tg_set_read_skip(ffsb_tg_t * tg,int rs)189 void tg_set_read_skip(ffsb_tg_t * tg, int rs)
190 {
191 	tg->read_skip = rs;
192 }
193 
tg_set_read_skipsize(ffsb_tg_t * tg,uint32_t rs)194 void tg_set_read_skipsize(ffsb_tg_t * tg, uint32_t rs)
195 {
196 	tg->read_skipsize = rs;
197 }
198 
tg_set_write_size(ffsb_tg_t * tg,uint64_t ws)199 void tg_set_write_size(ffsb_tg_t * tg, uint64_t ws)
200 {
201 	tg->write_size = ws;
202 }
203 
tg_set_write_blocksize(ffsb_tg_t * tg,uint32_t ws)204 void tg_set_write_blocksize(ffsb_tg_t * tg, uint32_t ws)
205 {
206 	tg->write_blocksize = ws;
207 	update_bufsize(tg);
208 }
209 
tg_get_read_random(ffsb_tg_t * tg)210 int tg_get_read_random(ffsb_tg_t * tg)
211 {
212 	return tg->read_random;
213 }
214 
tg_get_write_random(ffsb_tg_t * tg)215 int tg_get_write_random(ffsb_tg_t * tg)
216 {
217 	return tg->write_random;
218 }
219 
tg_get_fsync_file(ffsb_tg_t * tg)220 int tg_get_fsync_file(ffsb_tg_t * tg)
221 {
222 	return tg->fsync_file;
223 }
224 
tg_get_read_size(ffsb_tg_t * tg)225 uint64_t tg_get_read_size(ffsb_tg_t * tg)
226 {
227 	return tg->read_size;
228 }
229 
tg_get_read_blocksize(ffsb_tg_t * tg)230 uint32_t tg_get_read_blocksize(ffsb_tg_t * tg)
231 {
232 	return tg->read_blocksize;
233 }
234 
tg_get_read_skip(ffsb_tg_t * tg)235 int tg_get_read_skip(ffsb_tg_t * tg)
236 {
237 	return tg->read_skip;
238 }
239 
tg_get_read_skipsize(ffsb_tg_t * tg)240 uint32_t tg_get_read_skipsize(ffsb_tg_t * tg)
241 {
242 	return tg->read_skipsize;
243 }
244 
tg_get_write_size(ffsb_tg_t * tg)245 uint64_t tg_get_write_size(ffsb_tg_t * tg)
246 {
247 	return tg->write_size;
248 }
249 
tg_get_write_blocksize(ffsb_tg_t * tg)250 uint32_t tg_get_write_blocksize(ffsb_tg_t * tg)
251 {
252 	return tg->write_blocksize;
253 }
254 
tg_get_stopval(ffsb_tg_t * tg)255 int tg_get_stopval(ffsb_tg_t * tg)
256 {
257 	return tg->stopval;
258 }
259 
tg_get_start_barrier(ffsb_tg_t * tg)260 ffsb_barrier_t *tg_get_start_barrier(ffsb_tg_t * tg)
261 {
262 	return tg->start_barrier;
263 }
264 
tg_print_config_helper(ffsb_tg_t * tg)265 static void tg_print_config_helper(ffsb_tg_t * tg)
266 {
267 	int i;
268 	int sumweights = 0;
269 	char buf[256];
270 
271 	printf("\t num_threads      = %d\n", tg->num_threads);
272 	printf("\t\n");
273 	printf("\t read_random      = %s\n", (tg->read_random) ? "on" : "off");
274 	printf("\t read_size        = %llu\t(%s)\n", tg->read_size,
275 	       ffsb_printsize(buf, tg->read_size, 256));
276 	printf("\t read_blocksize   = %u\t(%s)\n", tg->read_blocksize,
277 	       ffsb_printsize(buf, tg->read_blocksize, 256));
278 	printf("\t read_skip        = %s\n", (tg->read_skip) ? "on" : "off");
279 	printf("\t read_skipsize    = %u\t(%s)\n", tg->read_skipsize,
280 	       ffsb_printsize(buf, tg->read_skipsize, 256));
281 	printf("\t\n");
282 	printf("\t write_random     = %s\n", (tg->write_random) ? "on" : "off");
283 	printf("\t write_size       = %llu\t(%s)\n", tg->write_size,
284 	       ffsb_printsize(buf, tg->write_size, 256));
285 	printf("\t fsync_file       = %d\n", tg->fsync_file);
286 	printf("\t write_blocksize  = %u\t(%s)\n", tg->write_blocksize,
287 	       ffsb_printsize(buf, tg->write_blocksize, 256));
288 	printf("\t wait time        = %u\n", tg->wait_time);
289 	if (tg->bindfs >= 0) {
290 		printf("\t\n");
291 		printf("\t bound to fs %d\n", tg->bindfs);
292 	}
293 	printf("\t\n");
294 	printf("\t op weights\n");
295 
296 	for (i = 0; i < FFSB_NUMOPS; i++)
297 		sumweights += tg->op_weights[i];
298 
299 	for (i = 0; i < FFSB_NUMOPS; i++)
300 		printf("\t %20s = %d (%.2f%%)\n", op_get_name(i),
301 		       tg->op_weights[i], 100 * (float)tg->op_weights[i] /
302 		       (float)sumweights);
303 	printf("\t\n");
304 }
305 
tg_print_config(ffsb_tg_t * tg)306 void tg_print_config(ffsb_tg_t * tg)
307 {
308 	printf("ThreadGroup %d\n", tg->tg_num);
309 	printf("================\n");
310 	tg_print_config_helper(tg);
311 }
312 
tg_print_config_aging(ffsb_tg_t * tg,char * fsname)313 void tg_print_config_aging(ffsb_tg_t * tg, char *fsname)
314 {
315 	printf("\t Aging ThreadGroup for fs %s\n", fsname);
316 	printf("\t ================\n");
317 	tg_print_config_helper(tg);
318 }
319 
tg_collect_results(ffsb_tg_t * tg,ffsb_op_results_t * r)320 void tg_collect_results(ffsb_tg_t * tg, ffsb_op_results_t * r)
321 {
322 	int i;
323 	for (i = 0; i < tg_get_numthreads(tg); i++)
324 		add_results(r, ft_get_results(tg->threads + i));
325 }
326 
tg_set_waittime(ffsb_tg_t * tg,unsigned time)327 void tg_set_waittime(ffsb_tg_t * tg, unsigned time)
328 {
329 	tg->wait_time = time;
330 }
331 
tg_get_waittime(ffsb_tg_t * tg)332 unsigned tg_get_waittime(ffsb_tg_t * tg)
333 {
334 	return tg->wait_time;
335 }
336 
tg_get_flagval(ffsb_tg_t * tg)337 int tg_get_flagval(ffsb_tg_t * tg)
338 {
339 	return tg->flagval;
340 }
341 
tg_set_statsc(ffsb_tg_t * tg,ffsb_statsc_t * fsc)342 void tg_set_statsc(ffsb_tg_t * tg, ffsb_statsc_t * fsc)
343 {
344 	if (fsc) {
345 		int i;
346 
347 		tg->need_stats = 1;
348 		ffsb_statsc_copy(&tg->fsc, fsc);
349 
350 		for (i = 0; i < tg->num_threads; i++)
351 			ft_set_statsc(tg->threads + i, &tg->fsc);
352 	}
353 }
354 
tg_collect_stats(ffsb_tg_t * tg,ffsb_statsd_t * fsd)355 void tg_collect_stats(ffsb_tg_t * tg, ffsb_statsd_t * fsd)
356 {
357 	int i;
358 
359 	assert(tg->need_stats);
360 	ffsb_statsd_init(fsd, &tg->fsc);
361 
362 	for (i = 0; i < tg_get_numthreads(tg); i++)
363 		ffsb_statsd_add(fsd, ft_get_stats_data(tg->threads + i));
364 }
365 
tg_needs_stats(ffsb_tg_t * tg)366 int tg_needs_stats(ffsb_tg_t * tg)
367 {
368 	return tg->need_stats;
369 }
370