]> git.proxmox.com Git - ceph.git/blame - ceph/src/client/SyntheticClient.cc
update sources to v12.1.0
[ceph.git] / ceph / src / client / SyntheticClient.cc
CommitLineData
7c673cae
FG
1// -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*-
2// vim: ts=8 sw=2 smarttab
3/*
4 * Ceph - scalable distributed file system
5 *
6 * Copyright (C) 2004-2006 Sage Weil <sage@newdream.net>
7 *
8 * This is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU Lesser General Public
10 * License version 2.1, as published by the Free Software
11 * Foundation. See file COPYING.
12 *
13 */
14
15#include "include/compat.h"
16
17#include <iostream>
18#include <sstream>
19using namespace std;
20
21
22#include "common/config.h"
23#include "SyntheticClient.h"
24#include "osdc/Objecter.h"
25#include "osdc/Filer.h"
26
27
28#include "include/filepath.h"
29#include "common/perf_counters.h"
30
31#include <sys/types.h>
32#include <sys/stat.h>
33#include <fcntl.h>
34#include <utime.h>
35#include <math.h>
36#include <sys/statvfs.h>
37
38#include "common/errno.h"
39#include "include/assert.h"
40#include "include/cephfs/ceph_statx.h"
41
42#define dout_context g_ceph_context
43#define dout_subsys ceph_subsys_client
44#undef dout_prefix
45#define dout_prefix *_dout << "client." << (whoami >= 0 ? whoami:client->get_nodeid()) << " "
46
47// traces
48//void trace_include(SyntheticClient *syn, Client *cl, string& prefix);
49//void trace_openssh(SyntheticClient *syn, Client *cl, string& prefix);
50
51
52list<int> syn_modes;
53list<int> syn_iargs;
54list<string> syn_sargs;
55int syn_filer_flags = 0;
56
57void parse_syn_options(vector<const char*>& args)
58{
59 vector<const char*> nargs;
60
61 for (unsigned i=0; i<args.size(); i++) {
62 if (strcmp(args[i],"--syn") == 0) {
63 ++i;
64
65 if (strcmp(args[i], "mksnap") == 0) {
66 syn_modes.push_back(SYNCLIENT_MODE_MKSNAP);
67 syn_sargs.push_back(args[++i]); // path
68 syn_sargs.push_back(args[++i]); // name
69 }
70 else if (strcmp(args[i], "rmsnap") == 0) {
71 syn_modes.push_back(SYNCLIENT_MODE_RMSNAP);
72 syn_sargs.push_back(args[++i]); // path
73 syn_sargs.push_back(args[++i]); // name
74 } else if (strcmp(args[i], "mksnapfile") == 0) {
75 syn_modes.push_back(SYNCLIENT_MODE_MKSNAPFILE);
76 syn_sargs.push_back(args[++i]); // path
77 } else if (strcmp(args[i],"rmfile") == 0) {
78 syn_modes.push_back( SYNCLIENT_MODE_RMFILE );
79 } else if (strcmp(args[i],"writefile") == 0) {
80 syn_modes.push_back( SYNCLIENT_MODE_WRITEFILE );
81 syn_iargs.push_back( atoi(args[++i]) );
82 syn_iargs.push_back( atoi(args[++i]) );
83 } else if (strcmp(args[i],"wrshared") == 0) {
84 syn_modes.push_back( SYNCLIENT_MODE_WRSHARED );
85 syn_iargs.push_back( atoi(args[++i]) );
86 syn_iargs.push_back( atoi(args[++i]) );
87 } else if (strcmp(args[i],"writebatch") == 0) {
88 syn_modes.push_back( SYNCLIENT_MODE_WRITEBATCH );
89 syn_iargs.push_back( atoi(args[++i]) );
90 syn_iargs.push_back( atoi(args[++i]) );
91 syn_iargs.push_back( atoi(args[++i]) );
92 } else if (strcmp(args[i],"readfile") == 0) {
93 syn_modes.push_back( SYNCLIENT_MODE_READFILE );
94 syn_iargs.push_back( atoi(args[++i]) );
95 syn_iargs.push_back( atoi(args[++i]) );
96 } else if (strcmp(args[i],"readwriterandom") == 0) {
97 syn_modes.push_back( SYNCLIENT_MODE_RDWRRANDOM );
98 syn_iargs.push_back( atoi(args[++i]) );
99 syn_iargs.push_back( atoi(args[++i]) );
100 } else if (strcmp(args[i],"readwriterandom_ex") == 0) {
101 syn_modes.push_back( SYNCLIENT_MODE_RDWRRANDOM_EX );
102 syn_iargs.push_back( atoi(args[++i]) );
103 syn_iargs.push_back( atoi(args[++i]) );
104 } else if (strcmp(args[i],"overloadosd0") == 0) {
105 syn_modes.push_back( SYNCLIENT_MODE_OVERLOAD_OSD_0 );
106 syn_iargs.push_back( atoi(args[++i]) );
107 syn_iargs.push_back( atoi(args[++i]) );
108 syn_iargs.push_back( atoi(args[++i]) );
109 } else if (strcmp(args[i],"readshared") == 0) {
110 syn_modes.push_back( SYNCLIENT_MODE_READSHARED );
111 syn_iargs.push_back( atoi(args[++i]) );
112 syn_iargs.push_back( atoi(args[++i]) );
113 } else if (strcmp(args[i],"rw") == 0) {
114 int a = atoi(args[++i]);
115 int b = atoi(args[++i]);
116 syn_modes.push_back( SYNCLIENT_MODE_WRITEFILE );
117 syn_iargs.push_back( a );
118 syn_iargs.push_back( b );
119 syn_modes.push_back( SYNCLIENT_MODE_READFILE );
120 syn_iargs.push_back( a );
121 syn_iargs.push_back( b );
122 } else if (strcmp(args[i],"dumpplacement") == 0) {
123 syn_modes.push_back( SYNCLIENT_MODE_DUMP );
124 syn_sargs.push_back( args[++i] );
125 } else if (strcmp(args[i],"dropcache") == 0) {
126 syn_modes.push_back( SYNCLIENT_MODE_DROPCACHE );
127 } else if (strcmp(args[i],"makedirs") == 0) {
128 syn_modes.push_back( SYNCLIENT_MODE_MAKEDIRS );
129 syn_iargs.push_back( atoi(args[++i]) );
130 syn_iargs.push_back( atoi(args[++i]) );
131 syn_iargs.push_back( atoi(args[++i]) );
132 } else if (strcmp(args[i],"makedirmess") == 0) {
133 syn_modes.push_back( SYNCLIENT_MODE_MAKEDIRMESS );
134 syn_iargs.push_back( atoi(args[++i]) );
135 } else if (strcmp(args[i],"statdirs") == 0) {
136 syn_modes.push_back( SYNCLIENT_MODE_STATDIRS );
137 syn_iargs.push_back( atoi(args[++i]) );
138 syn_iargs.push_back( atoi(args[++i]) );
139 syn_iargs.push_back( atoi(args[++i]) );
140 } else if (strcmp(args[i],"readdirs") == 0) {
141 syn_modes.push_back( SYNCLIENT_MODE_READDIRS );
142 syn_iargs.push_back( atoi(args[++i]) );
143 syn_iargs.push_back( atoi(args[++i]) );
144 syn_iargs.push_back( atoi(args[++i]) );
145 } else if (strcmp(args[i],"makefiles") == 0) {
146 syn_modes.push_back( SYNCLIENT_MODE_MAKEFILES );
147 syn_iargs.push_back( atoi(args[++i]) );
148 syn_iargs.push_back( atoi(args[++i]) );
149 syn_iargs.push_back( atoi(args[++i]) );
150 } else if (strcmp(args[i],"makefiles2") == 0) {
151 syn_modes.push_back( SYNCLIENT_MODE_MAKEFILES2 );
152 syn_iargs.push_back( atoi(args[++i]) );
153 syn_iargs.push_back( atoi(args[++i]) );
154 syn_iargs.push_back( atoi(args[++i]) );
155 } else if (strcmp(args[i],"linktest") == 0) {
156 syn_modes.push_back( SYNCLIENT_MODE_LINKTEST );
157 } else if (strcmp(args[i],"createshared") == 0) {
158 syn_modes.push_back( SYNCLIENT_MODE_CREATESHARED );
159 syn_iargs.push_back( atoi(args[++i]) );
160 } else if (strcmp(args[i],"openshared") == 0) {
161 syn_modes.push_back( SYNCLIENT_MODE_OPENSHARED );
162 syn_iargs.push_back( atoi(args[++i]) );
163 syn_iargs.push_back( atoi(args[++i]) );
164 } else if (strcmp(args[i],"createobjects") == 0) {
165 syn_modes.push_back( SYNCLIENT_MODE_CREATEOBJECTS );
166 syn_iargs.push_back( atoi(args[++i]) );
167 syn_iargs.push_back( atoi(args[++i]) );
168 syn_iargs.push_back( atoi(args[++i]) );
169 } else if (strcmp(args[i],"objectrw") == 0) {
170 syn_modes.push_back( SYNCLIENT_MODE_OBJECTRW );
171 syn_iargs.push_back( atoi(args[++i]) );
172 syn_iargs.push_back( atoi(args[++i]) );
173 syn_iargs.push_back( atoi(args[++i]) );
174 syn_iargs.push_back( atoi(args[++i]) );
175 syn_iargs.push_back( atoi(args[++i]) );
176 syn_iargs.push_back( atoi(args[++i]) );
177 } else if (strcmp(args[i],"walk") == 0) {
178 syn_modes.push_back( SYNCLIENT_MODE_FULLWALK );
179 //syn_sargs.push_back( atoi(args[++i]) );
180 } else if (strcmp(args[i],"randomwalk") == 0) {
181 syn_modes.push_back( SYNCLIENT_MODE_RANDOMWALK );
182 syn_iargs.push_back( atoi(args[++i]) );
183 } else if (strcmp(args[i],"trace") == 0) {
184 syn_modes.push_back( SYNCLIENT_MODE_TRACE );
185 syn_sargs.push_back( args[++i] );
186 syn_iargs.push_back( atoi(args[++i]) );
187 syn_iargs.push_back(1);// data
188 } else if (strcmp(args[i],"mtrace") == 0) {
189 syn_modes.push_back( SYNCLIENT_MODE_TRACE );
190 syn_sargs.push_back( args[++i] );
191 syn_iargs.push_back( atoi(args[++i]) );
192 syn_iargs.push_back(0);// no data
193 } else if (strcmp(args[i],"thrashlinks") == 0) {
194 syn_modes.push_back( SYNCLIENT_MODE_THRASHLINKS );
195 syn_iargs.push_back( atoi(args[++i]) );
196 syn_iargs.push_back( atoi(args[++i]) );
197 syn_iargs.push_back( atoi(args[++i]) );
198 syn_iargs.push_back( atoi(args[++i]) );
199 } else if (strcmp(args[i],"foo") == 0) {
200 syn_modes.push_back( SYNCLIENT_MODE_FOO );
201 } else if (strcmp(args[i],"until") == 0) {
202 syn_modes.push_back( SYNCLIENT_MODE_UNTIL );
203 syn_iargs.push_back( atoi(args[++i]) );
204 } else if (strcmp(args[i],"sleepuntil") == 0) {
205 syn_modes.push_back( SYNCLIENT_MODE_SLEEPUNTIL );
206 syn_iargs.push_back( atoi(args[++i]) );
207 } else if (strcmp(args[i],"only") == 0) {
208 syn_modes.push_back( SYNCLIENT_MODE_ONLY );
209 syn_iargs.push_back( atoi(args[++i]) );
210 } else if (strcmp(args[i],"onlyrange") == 0) {
211 syn_modes.push_back( SYNCLIENT_MODE_ONLYRANGE );
212 syn_iargs.push_back( atoi(args[++i]) );
213 syn_iargs.push_back( atoi(args[++i]) );
214 } else if (strcmp(args[i],"sleep") == 0) {
215 syn_modes.push_back( SYNCLIENT_MODE_SLEEP );
216 syn_iargs.push_back( atoi(args[++i]) );
217 } else if (strcmp(args[i],"randomsleep") == 0) {
218 syn_modes.push_back( SYNCLIENT_MODE_RANDOMSLEEP );
219 syn_iargs.push_back( atoi(args[++i]) );
220 } else if (strcmp(args[i],"opentest") == 0) {
221 syn_modes.push_back( SYNCLIENT_MODE_OPENTEST );
222 syn_iargs.push_back( atoi(args[++i]) );
223 } else if (strcmp(args[i],"optest") == 0) {
224 syn_modes.push_back( SYNCLIENT_MODE_OPTEST );
225 syn_iargs.push_back( atoi(args[++i]) );
226 } else if (strcmp(args[i],"truncate") == 0) {
227 syn_modes.push_back( SYNCLIENT_MODE_TRUNCATE );
228 syn_sargs.push_back(args[++i]);
229 syn_iargs.push_back(atoi(args[++i]));
230 } else if (strcmp(args[i],"importfind") == 0) {
231 syn_modes.push_back(SYNCLIENT_MODE_IMPORTFIND);
232 syn_sargs.push_back(args[++i]);
233 syn_sargs.push_back(args[++i]);
234 syn_iargs.push_back(atoi(args[++i]));
235 } else if (strcmp(args[i], "lookuphash") == 0) {
236 syn_modes.push_back(SYNCLIENT_MODE_LOOKUPHASH);
237 syn_sargs.push_back(args[++i]);
238 syn_sargs.push_back(args[++i]);
239 syn_sargs.push_back(args[++i]);
240 } else if (strcmp(args[i], "lookupino") == 0) {
241 syn_modes.push_back(SYNCLIENT_MODE_LOOKUPINO);
242 syn_sargs.push_back(args[++i]);
243 } else if (strcmp(args[i], "chunkfile") == 0) {
244 syn_modes.push_back(SYNCLIENT_MODE_CHUNK);
245 syn_sargs.push_back(args[++i]);
246 } else {
247 cerr << "unknown syn arg " << args[i] << std::endl;
248 ceph_abort();
249 }
250 }
251 else if (strcmp(args[i], "localize_reads") == 0) {
252 cerr << "set CEPH_OSD_FLAG_LOCALIZE_READS" << std::endl;
253 syn_filer_flags |= CEPH_OSD_FLAG_LOCALIZE_READS;
254 }
255 else {
256 nargs.push_back(args[i]);
257 }
258 }
259
260 args = nargs;
261}
262
263
31f18b77 264SyntheticClient::SyntheticClient(StandaloneClient *client, int w)
7c673cae
FG
265{
266 this->client = client;
267 whoami = w;
268 thread_id = 0;
269
270 did_readdir = false;
271
272 run_only = -1;
273 exclude = -1;
274
275 this->modes = syn_modes;
276 this->iargs = syn_iargs;
277 this->sargs = syn_sargs;
278
279 run_start = ceph_clock_now();
280}
281
282
283
284
285#define DBL 2
286
287void *synthetic_client_thread_entry(void *ptr)
288{
289 SyntheticClient *sc = static_cast<SyntheticClient*>(ptr);
290 //int r =
291 sc->run();
292 return 0;//(void*)r;
293}
294
295string SyntheticClient::get_sarg(int seq)
296{
297 string a;
298 if (!sargs.empty()) {
299 a = sargs.front();
300 sargs.pop_front();
301 }
302 if (a.length() == 0 || a == "~") {
303 char s[30];
304 snprintf(s, sizeof(s), "syn.%lld.%d", (long long)client->whoami.v, seq);
305 a = s;
306 }
307 return a;
308}
309
310int SyntheticClient::run()
311{
312 UserPerm perms = client->pick_my_perms();
313 dout(15) << "initing" << dendl;
314 int err = client->init();
315 if (err < 0) {
316 dout(0) << "failed to initialize: " << cpp_strerror(err) << dendl;
317 return -1;
318 }
319
320 dout(15) << "mounting" << dendl;
321 err = client->mount("", perms);
322 if (err < 0) {
323 dout(0) << "failed to mount: " << cpp_strerror(err) << dendl;
324 client->shutdown();
325 return -1;
326 }
327
328 //run_start = ceph_clock_now(client->cct);
329 run_until = utime_t(0,0);
330 dout(5) << "run" << dendl;
331
332 int seq = 0;
333
334 for (list<int>::iterator it = modes.begin();
335 it != modes.end();
336 ++it) {
337 int mode = *it;
338 dout(3) << "mode " << mode << dendl;
339
340 switch (mode) {
341
342
343 // WHO?
344
345 case SYNCLIENT_MODE_ONLY:
346 {
347 run_only = iargs.front();
348 iargs.pop_front();
349 if (run_only == client->get_nodeid())
350 dout(2) << "only " << run_only << dendl;
351 }
352 break;
353 case SYNCLIENT_MODE_ONLYRANGE:
354 {
355 int first = iargs.front();
356 iargs.pop_front();
357 int last = iargs.front();
358 iargs.pop_front();
359 if (first <= client->get_nodeid() &&
360 last > client->get_nodeid()) {
361 run_only = client->get_nodeid();
362 dout(2) << "onlyrange [" << first << ", " << last << ") includes me" << dendl;
363 } else
364 run_only = client->get_nodeid().v+1; // not me
365 }
366 break;
367 case SYNCLIENT_MODE_EXCLUDE:
368 {
369 exclude = iargs.front();
370 iargs.pop_front();
371 if (exclude == client->get_nodeid()) {
372 run_only = client->get_nodeid().v + 1;
373 dout(2) << "not running " << exclude << dendl;
374 } else
375 run_only = -1;
376 }
377 break;
378
379 // HOW LONG?
380
381 case SYNCLIENT_MODE_UNTIL:
382 {
383 int iarg1 = iargs.front();
384 iargs.pop_front();
385 if (run_me()) {
386 if (iarg1) {
387 dout(2) << "until " << iarg1 << dendl;
388 utime_t dur(iarg1,0);
389 run_until = run_start + dur;
390 } else {
391 dout(2) << "until " << iarg1 << " (no limit)" << dendl;
392 run_until = utime_t(0,0);
393 }
394 }
395 }
396 break;
397
398
399 // ...
400
401 case SYNCLIENT_MODE_FOO:
402 if (run_me()) {
403 foo();
404 }
405 did_run_me();
406 break;
407
408 case SYNCLIENT_MODE_RANDOMSLEEP:
409 {
410 int iarg1 = iargs.front();
411 iargs.pop_front();
412 if (run_me()) {
413 srand(time(0) + getpid() + client->whoami.v);
414 sleep(rand() % iarg1);
415 }
416 did_run_me();
417 }
418 break;
419
420 case SYNCLIENT_MODE_SLEEP:
421 {
422 int iarg1 = iargs.front();
423 iargs.pop_front();
424 if (run_me()) {
425 dout(2) << "sleep " << iarg1 << dendl;
426 sleep(iarg1);
427 }
428 did_run_me();
429 }
430 break;
431
432 case SYNCLIENT_MODE_SLEEPUNTIL:
433 {
434 int iarg1 = iargs.front();
435 iargs.pop_front();
436 if (iarg1 && run_me()) {
437 dout(2) << "sleepuntil " << iarg1 << dendl;
438 utime_t at = ceph_clock_now() - run_start;
439 if (at.sec() < iarg1)
440 sleep(iarg1 - at.sec());
441 }
442 did_run_me();
443 }
444 break;
445
446 case SYNCLIENT_MODE_RANDOMWALK:
447 {
448 int iarg1 = iargs.front();
449 iargs.pop_front();
450 if (run_me()) {
451 dout(2) << "randomwalk " << iarg1 << dendl;
452 random_walk(iarg1);
453 }
454 did_run_me();
455 }
456 break;
457
458
459 case SYNCLIENT_MODE_DROPCACHE:
460 {
461 client->sync_fs();
462 client->drop_caches();
463 }
464 break;
465
466 case SYNCLIENT_MODE_DUMP:
467 {
468 string sarg1 = get_sarg(0);
469 if (run_me()) {
470 dout(2) << "placement dump " << sarg1 << dendl;
471 dump_placement(sarg1);
472 }
473 did_run_me();
474 }
475 break;
476
477
478 case SYNCLIENT_MODE_MAKEDIRMESS:
479 {
480 string sarg1 = get_sarg(0);
481 int iarg1 = iargs.front(); iargs.pop_front();
482 if (run_me()) {
483 dout(2) << "makedirmess " << sarg1 << " " << iarg1 << dendl;
484 make_dir_mess(sarg1.c_str(), iarg1);
485 }
486 did_run_me();
487 }
488 break;
489 case SYNCLIENT_MODE_MAKEDIRS:
490 {
491 string sarg1 = get_sarg(seq++);
492 int iarg1 = iargs.front(); iargs.pop_front();
493 int iarg2 = iargs.front(); iargs.pop_front();
494 int iarg3 = iargs.front(); iargs.pop_front();
495 if (run_me()) {
496 dout(2) << "makedirs " << sarg1 << " " << iarg1 << " " << iarg2 << " " << iarg3 << dendl;
497 make_dirs(sarg1.c_str(), iarg1, iarg2, iarg3);
498 }
499 did_run_me();
500 }
501 break;
502 case SYNCLIENT_MODE_STATDIRS:
503 {
504 string sarg1 = get_sarg(0);
505 int iarg1 = iargs.front(); iargs.pop_front();
506 int iarg2 = iargs.front(); iargs.pop_front();
507 int iarg3 = iargs.front(); iargs.pop_front();
508 if (run_me()) {
509 dout(2) << "statdirs " << sarg1 << " " << iarg1 << " " << iarg2 << " " << iarg3 << dendl;
510 stat_dirs(sarg1.c_str(), iarg1, iarg2, iarg3);
511 }
512 did_run_me();
513 }
514 break;
515 case SYNCLIENT_MODE_READDIRS:
516 {
517 string sarg1 = get_sarg(0);
518 int iarg1 = iargs.front(); iargs.pop_front();
519 int iarg2 = iargs.front(); iargs.pop_front();
520 int iarg3 = iargs.front(); iargs.pop_front();
521 if (run_me()) {
522 dout(2) << "readdirs " << sarg1 << " " << iarg1 << " " << iarg2 << " " << iarg3 << dendl;
523 read_dirs(sarg1.c_str(), iarg1, iarg2, iarg3);
524 }
525 did_run_me();
526 }
527 break;
528
529
530 case SYNCLIENT_MODE_THRASHLINKS:
531 {
532 string sarg1 = get_sarg(0);
533 int iarg1 = iargs.front(); iargs.pop_front();
534 int iarg2 = iargs.front(); iargs.pop_front();
535 int iarg3 = iargs.front(); iargs.pop_front();
536 int iarg4 = iargs.front(); iargs.pop_front();
537 if (run_me()) {
538 dout(2) << "thrashlinks " << sarg1 << " " << iarg1 << " " << iarg2 << " " << iarg3 << dendl;
539 thrash_links(sarg1.c_str(), iarg1, iarg2, iarg3, iarg4);
540 }
541 did_run_me();
542 }
543 break;
544
545 case SYNCLIENT_MODE_LINKTEST:
546 {
547 if (run_me()) {
548 link_test();
549 }
550 did_run_me();
551 }
552 break;
553
554
555 case SYNCLIENT_MODE_MAKEFILES:
556 {
557 int num = iargs.front(); iargs.pop_front();
558 int count = iargs.front(); iargs.pop_front();
559 int priv = iargs.front(); iargs.pop_front();
560 if (run_me()) {
561 dout(2) << "makefiles " << num << " " << count << " " << priv << dendl;
562 make_files(num, count, priv, false);
563 }
564 did_run_me();
565 }
566 break;
567 case SYNCLIENT_MODE_MAKEFILES2:
568 {
569 int num = iargs.front(); iargs.pop_front();
570 int count = iargs.front(); iargs.pop_front();
571 int priv = iargs.front(); iargs.pop_front();
572 if (run_me()) {
573 dout(2) << "makefiles2 " << num << " " << count << " " << priv << dendl;
574 make_files(num, count, priv, true);
575 }
576 did_run_me();
577 }
578 break;
579 case SYNCLIENT_MODE_CREATESHARED:
580 {
581 string sarg1 = get_sarg(0);
582 int num = iargs.front(); iargs.pop_front();
583 if (run_me()) {
584 dout(2) << "createshared " << num << dendl;
585 create_shared(num);
586 }
587 did_run_me();
588 }
589 break;
590 case SYNCLIENT_MODE_OPENSHARED:
591 {
592 string sarg1 = get_sarg(0);
593 int num = iargs.front(); iargs.pop_front();
594 int count = iargs.front(); iargs.pop_front();
595 if (run_me()) {
596 dout(2) << "openshared " << num << dendl;
597 open_shared(num, count);
598 }
599 did_run_me();
600 }
601 break;
602
603 case SYNCLIENT_MODE_CREATEOBJECTS:
604 {
605 int count = iargs.front(); iargs.pop_front();
606 int size = iargs.front(); iargs.pop_front();
607 int inflight = iargs.front(); iargs.pop_front();
608 if (run_me()) {
609 dout(2) << "createobjects " << count << " of " << size << " bytes"
610 << ", " << inflight << " in flight" << dendl;
611 create_objects(count, size, inflight);
612 }
613 did_run_me();
614 }
615 break;
616 case SYNCLIENT_MODE_OBJECTRW:
617 {
618 int count = iargs.front(); iargs.pop_front();
619 int size = iargs.front(); iargs.pop_front();
620 int wrpc = iargs.front(); iargs.pop_front();
621 int overlap = iargs.front(); iargs.pop_front();
622 int rskew = iargs.front(); iargs.pop_front();
623 int wskew = iargs.front(); iargs.pop_front();
624 if (run_me()) {
625 dout(2) << "objectrw " << count << " " << size << " " << wrpc
626 << " " << overlap << " " << rskew << " " << wskew << dendl;
627 object_rw(count, size, wrpc, overlap, rskew, wskew);
628 }
629 did_run_me();
630 }
631 break;
632
633 case SYNCLIENT_MODE_FULLWALK:
634 {
635 string sarg1;// = get_sarg(0);
636 if (run_me()) {
637 dout(2) << "fullwalk" << sarg1 << dendl;
638 full_walk(sarg1);
639 }
640 did_run_me();
641 }
642 break;
643 case SYNCLIENT_MODE_REPEATWALK:
644 {
645 string sarg1 = get_sarg(0);
646 if (run_me()) {
647 dout(2) << "repeatwalk " << sarg1 << dendl;
648 while (full_walk(sarg1) == 0) ;
649 }
650 did_run_me();
651 }
652 break;
653
654 case SYNCLIENT_MODE_RMFILE:
655 {
656 string sarg1 = get_sarg(0);
657 if (run_me()) {
658 rm_file(sarg1);
659 }
660 did_run_me();
661 }
662 break;
663
664 case SYNCLIENT_MODE_WRITEFILE:
665 {
666 string sarg1 = get_sarg(0);
667 int iarg1 = iargs.front(); iargs.pop_front();
668 int iarg2 = iargs.front(); iargs.pop_front();
669 dout(1) << "WRITING SYN CLIENT" << dendl;
670 if (run_me()) {
671 write_file(sarg1, iarg1, iarg2);
672 }
673 did_run_me();
674 }
675 break;
676
677 case SYNCLIENT_MODE_CHUNK:
678 if (run_me()) {
679 string sarg1 = get_sarg(0);
680 chunk_file(sarg1);
681 }
682 did_run_me();
683 break;
684
685
686 case SYNCLIENT_MODE_OVERLOAD_OSD_0:
687 {
688 dout(1) << "OVERLOADING OSD 0" << dendl;
689 int iarg1 = iargs.front(); iargs.pop_front();
690 int iarg2 = iargs.front(); iargs.pop_front();
691 int iarg3 = iargs.front(); iargs.pop_front();
692 if (run_me()) {
693 overload_osd_0(iarg1, iarg2, iarg3);
694 }
695 did_run_me();
696 }
697 break;
698
699 case SYNCLIENT_MODE_WRSHARED:
700 {
701 string sarg1 = "shared";
702 int iarg1 = iargs.front(); iargs.pop_front();
703 int iarg2 = iargs.front(); iargs.pop_front();
704 if (run_me()) {
705 write_file(sarg1, iarg1, iarg2);
706 }
707 did_run_me();
708 }
709 break;
710 case SYNCLIENT_MODE_READSHARED:
711 {
712 string sarg1 = "shared";
713 int iarg1 = iargs.front(); iargs.pop_front();
714 int iarg2 = iargs.front(); iargs.pop_front();
715 if (run_me()) {
716 read_file(sarg1, iarg1, iarg2, true);
717 }
718 did_run_me();
719 }
720 break;
721 case SYNCLIENT_MODE_WRITEBATCH:
722 {
723 int iarg1 = iargs.front(); iargs.pop_front();
724 int iarg2 = iargs.front(); iargs.pop_front();
725 int iarg3 = iargs.front(); iargs.pop_front();
726
727 if (run_me()) {
728 write_batch(iarg1, iarg2, iarg3);
729 }
730 did_run_me();
731 }
732 break;
733
734 case SYNCLIENT_MODE_READFILE:
735 {
736 string sarg1 = get_sarg(0);
737 int iarg1 = iargs.front(); iargs.pop_front();
738 int iarg2 = iargs.front(); iargs.pop_front();
739
740 dout(1) << "READING SYN CLIENT" << dendl;
741 if (run_me()) {
742 read_file(sarg1, iarg1, iarg2);
743 }
744 did_run_me();
745 }
746 break;
747
748 case SYNCLIENT_MODE_RDWRRANDOM:
749 {
750 string sarg1 = get_sarg(0);
751 int iarg1 = iargs.front(); iargs.pop_front();
752 int iarg2 = iargs.front(); iargs.pop_front();
753
754 dout(1) << "RANDOM READ WRITE SYN CLIENT" << dendl;
755 if (run_me()) {
756 read_random(sarg1, iarg1, iarg2);
757 }
758 did_run_me();
759 }
760 break;
761
762 case SYNCLIENT_MODE_RDWRRANDOM_EX:
763 {
764 string sarg1 = get_sarg(0);
765 int iarg1 = iargs.front(); iargs.pop_front();
766 int iarg2 = iargs.front(); iargs.pop_front();
767
768 dout(1) << "RANDOM READ WRITE SYN CLIENT" << dendl;
769 if (run_me()) {
770 read_random_ex(sarg1, iarg1, iarg2);
771 }
772 did_run_me();
773 }
774 break;
775 case SYNCLIENT_MODE_TRACE:
776 {
777 string tfile = get_sarg(0);
778 sargs.push_front(string("~"));
779 int iarg1 = iargs.front(); iargs.pop_front();
780 int playdata = iargs.front(); iargs.pop_front();
781 string prefix = get_sarg(0);
782 char realtfile[100];
783 snprintf(realtfile, sizeof(realtfile), tfile.c_str(), (int)client->get_nodeid().v);
784
785 if (run_me()) {
786 dout(0) << "trace " << tfile << " prefix=" << prefix << " count=" << iarg1 << " data=" << playdata << dendl;
787
788 Trace t(realtfile);
789
790 if (iarg1 == 0) iarg1 = 1; // play trace at least once!
791
792 for (int i=0; i<iarg1; i++) {
793 utime_t start = ceph_clock_now();
794
795 if (time_to_stop()) break;
796 play_trace(t, prefix, !playdata);
797 if (time_to_stop()) break;
798 if (iarg1 > 1) clean_dir(prefix); // clean only if repeat
799
800 utime_t lat = ceph_clock_now();
801 lat -= start;
802
803 dout(0) << " trace " << tfile << " loop " << (i+1) << "/" << iarg1 << " done in " << (double)lat << " seconds" << dendl;
804 if (client->logger
805 && i > 0
806 && i < iarg1-1
807 ) {
808 //client->logger->finc("trsum", (double)lat);
809 //client->logger->inc("trnum");
810 }
811 }
812 dout(1) << "done " << dendl;
813 }
814 did_run_me();
815 }
816 break;
817
818
819 case SYNCLIENT_MODE_OPENTEST:
820 {
821 int count = iargs.front(); iargs.pop_front();
822 if (run_me()) {
823 for (int i=0; i<count; i++) {
824 int fd = client->open("test", (rand()%2) ?
825 (O_WRONLY|O_CREAT) : O_RDONLY,
826 perms);
827 if (fd > 0) client->close(fd);
828 }
829 }
830 did_run_me();
831 }
832 break;
833
834 case SYNCLIENT_MODE_OPTEST:
835 {
836 int count = iargs.front(); iargs.pop_front();
837 if (run_me()) {
838 client->mknod("test", 0777, perms);
839 struct stat st;
840 for (int i=0; i<count; i++) {
841 client->lstat("test", &st, perms);
842 client->chmod("test", 0777, perms);
843 }
844 }
845 did_run_me();
846 }
847 break;
848
849 case SYNCLIENT_MODE_TRUNCATE:
850 {
851 string file = get_sarg(0);
852 sargs.push_front(file);
853 int iarg1 = iargs.front(); iargs.pop_front();
854 if (run_me()) {
855 client->truncate(file.c_str(), iarg1, perms);
856 }
857 did_run_me();
858 }
859 break;
860
861
862 case SYNCLIENT_MODE_IMPORTFIND:
863 {
864 string base = get_sarg(0);
865 string find = get_sarg(0);
866 int data = get_iarg();
867 if (run_me()) {
868 import_find(base.c_str(), find.c_str(), data);
869 }
870 did_run_me();
871 }
872 break;
873
874 case SYNCLIENT_MODE_LOOKUPHASH:
875 {
876 inodeno_t ino;
877 string iname = get_sarg(0);
878 sscanf(iname.c_str(), "%llx", (long long unsigned*)&ino.val);
879 inodeno_t dirino;
880 string diname = get_sarg(0);
881 sscanf(diname.c_str(), "%llx", (long long unsigned*)&dirino.val);
882 string name = get_sarg(0);
883 if (run_me()) {
884 lookup_hash(ino, dirino, name.c_str(), perms);
885 }
886 }
887 break;
888 case SYNCLIENT_MODE_LOOKUPINO:
889 {
890 inodeno_t ino;
891 string iname = get_sarg(0);
892 sscanf(iname.c_str(), "%llx", (long long unsigned*)&ino.val);
893 if (run_me()) {
894 lookup_ino(ino, perms);
895 }
896 }
897 break;
898
899 case SYNCLIENT_MODE_MKSNAP:
900 {
901 string base = get_sarg(0);
902 string name = get_sarg(0);
903 if (run_me())
904 mksnap(base.c_str(), name.c_str(), perms);
905 did_run_me();
906 }
907 break;
908 case SYNCLIENT_MODE_RMSNAP:
909 {
910 string base = get_sarg(0);
911 string name = get_sarg(0);
912 if (run_me())
913 rmsnap(base.c_str(), name.c_str(), perms);
914 did_run_me();
915 }
916 break;
917 case SYNCLIENT_MODE_MKSNAPFILE:
918 {
919 string base = get_sarg(0);
920 if (run_me())
921 mksnapfile(base.c_str());
922 did_run_me();
923 }
924 break;
925
926 default:
927 ceph_abort();
928 }
929 }
930 dout(1) << "syn done, unmounting " << dendl;
931
932 client->unmount();
933 client->shutdown();
934 return 0;
935}
936
937
938int SyntheticClient::start_thread()
939{
940 assert(!thread_id);
941
942 pthread_create(&thread_id, NULL, synthetic_client_thread_entry, this);
943 assert(thread_id);
944 ceph_pthread_setname(thread_id, "client");
945 return 0;
946}
947
948int SyntheticClient::join_thread()
949{
950 assert(thread_id);
951 void *rv;
952 pthread_join(thread_id, &rv);
953 return 0;
954}
955
956
957bool roll_die(float p)
958{
959 float r = (float)(rand() % 100000) / 100000.0;
960 if (r < p)
961 return true;
962 else
963 return false;
964}
965
966void SyntheticClient::init_op_dist()
967{
968 op_dist.clear();
969#if 0
970 op_dist.add( CEPH_MDS_OP_STAT, 610 );
971 op_dist.add( CEPH_MDS_OP_UTIME, 0 );
972 op_dist.add( CEPH_MDS_OP_CHMOD, 1 );
973 op_dist.add( CEPH_MDS_OP_CHOWN, 1 );
974#endif
975
976 op_dist.add( CEPH_MDS_OP_READDIR, 2 );
977 op_dist.add( CEPH_MDS_OP_MKNOD, 30 );
978 op_dist.add( CEPH_MDS_OP_LINK, 0 );
979 op_dist.add( CEPH_MDS_OP_UNLINK, 20 );
980 op_dist.add( CEPH_MDS_OP_RENAME, 40 );
981
982 op_dist.add( CEPH_MDS_OP_MKDIR, 10 );
983 op_dist.add( CEPH_MDS_OP_RMDIR, 20 );
984 op_dist.add( CEPH_MDS_OP_SYMLINK, 20 );
985
986 op_dist.add( CEPH_MDS_OP_OPEN, 200 );
987 //op_dist.add( CEPH_MDS_OP_READ, 0 );
988 //op_dist.add( CEPH_MDS_OP_WRITE, 0 );
989 //op_dist.add( CEPH_MDS_OP_TRUNCATE, 0 );
990 //op_dist.add( CEPH_MDS_OP_FSYNC, 0 );
991 //op_dist.add( CEPH_MDS_OP_RELEASE, 200 );
992 op_dist.normalize();
993}
994
995void SyntheticClient::up()
996{
997 cwd = cwd.prefixpath(cwd.depth()-1);
998 dout(DBL) << "cd .. -> " << cwd << dendl;
999 clear_dir();
1000}
1001
1002int SyntheticClient::play_trace(Trace& t, string& prefix, bool metadata_only)
1003{
1004 dout(4) << "play trace prefix '" << prefix << "'" << dendl;
1005 UserPerm perms = client->pick_my_perms();
1006 t.start();
1007
1008 string buf;
1009 string buf2;
1010
1011 utime_t start = ceph_clock_now();
1012
1013 ceph::unordered_map<int64_t, int64_t> open_files;
1014 ceph::unordered_map<int64_t, dir_result_t*> open_dirs;
1015
1016 ceph::unordered_map<int64_t, Fh*> ll_files;
1017 ceph::unordered_map<int64_t, dir_result_t*> ll_dirs;
1018 ceph::unordered_map<uint64_t, int64_t> ll_inos;
1019
1020 Inode *i1, *i2;
1021
1022 ll_inos[1] = 1; // root inode is known.
1023
1024 // prefix?
1025 const char *p = prefix.c_str();
1026 if (prefix.length()) {
1027 client->mkdir(prefix.c_str(), 0755, perms);
1028 struct ceph_statx stx;
1029 i1 = client->ll_get_inode(vinodeno_t(1, CEPH_NOSNAP));
1030 if (client->ll_lookupx(i1, prefix.c_str(), &i2, &stx, CEPH_STATX_INO, 0, perms) == 0) {
1031 ll_inos[1] = stx.stx_ino;
1032 dout(5) << "'root' ino is " << inodeno_t(stx.stx_ino) << dendl;
1033 client->ll_put(i1);
1034 } else {
1035 dout(0) << "warning: play_trace couldn't lookup up my per-client directory" << dendl;
1036 }
1037 } else
1038 (void) client->ll_get_inode(vinodeno_t(1, CEPH_NOSNAP));
1039
1040 utime_t last_status = start;
1041
1042 int n = 0;
1043
1044 // for object traces
1045 Mutex lock("synclient foo");
1046 Cond cond;
1047 bool ack;
1048
1049 while (!t.end()) {
1050
1051 if (++n == 100) {
1052 n = 00;
1053 utime_t now = last_status;
1054 if (now - last_status > 1.0) {
1055 last_status = now;
1056 dout(1) << "play_trace at line " << t.get_line() << dendl;
1057 }
1058 }
1059
1060 if (time_to_stop()) break;
1061
1062 // op
1063 const char *op = t.get_string(buf, 0);
1064 dout(4) << (t.get_line()-1) << ": trace op " << op << dendl;
1065
1066 if (op[0] == '@') {
1067 // timestamp... ignore it!
1068 t.get_int(); // sec
1069 t.get_int(); // usec
1070 op = t.get_string(buf, 0);
1071 }
1072
1073 // high level ops ---------------------
1074 UserPerm perms = client->pick_my_perms();
1075 if (strcmp(op, "link") == 0) {
1076 const char *a = t.get_string(buf, p);
1077 const char *b = t.get_string(buf2, p);
1078 client->link(a, b, perms);
1079 } else if (strcmp(op, "unlink") == 0) {
1080 const char *a = t.get_string(buf, p);
1081 client->unlink(a, perms);
1082 } else if (strcmp(op, "rename") == 0) {
1083 const char *a = t.get_string(buf, p);
1084 const char *b = t.get_string(buf2, p);
1085 client->rename(a,b, perms);
1086 } else if (strcmp(op, "mkdir") == 0) {
1087 const char *a = t.get_string(buf, p);
1088 int64_t b = t.get_int();
1089 client->mkdir(a, b, perms);
1090 } else if (strcmp(op, "rmdir") == 0) {
1091 const char *a = t.get_string(buf, p);
1092 client->rmdir(a, perms);
1093 } else if (strcmp(op, "symlink") == 0) {
1094 const char *a = t.get_string(buf, p);
1095 const char *b = t.get_string(buf2, p);
1096 client->symlink(a, b, perms);
1097 } else if (strcmp(op, "readlink") == 0) {
1098 const char *a = t.get_string(buf, p);
1099 char buf[100];
1100 client->readlink(a, buf, 100, perms);
1101 } else if (strcmp(op, "lstat") == 0) {
1102 struct stat st;
1103 const char *a = t.get_string(buf, p);
1104 if (strcmp(a, p) != 0 &&
1105 strcmp(a, "/") != 0 &&
1106 strcmp(a, "/lib") != 0 && // or /lib.. that would be a lookup. hack.
1107 a[0] != 0) // stop stating the root directory already
1108 client->lstat(a, &st, perms);
1109 } else if (strcmp(op, "chmod") == 0) {
1110 const char *a = t.get_string(buf, p);
1111 int64_t b = t.get_int();
1112 client->chmod(a, b, perms);
1113 } else if (strcmp(op, "chown") == 0) {
1114 const char *a = t.get_string(buf, p);
1115 int64_t b = t.get_int();
1116 int64_t c = t.get_int();
1117 client->chown(a, b, c, perms);
1118 } else if (strcmp(op, "utime") == 0) {
1119 const char *a = t.get_string(buf, p);
1120 int64_t b = t.get_int();
1121 int64_t c = t.get_int();
1122 struct utimbuf u;
1123 u.actime = b;
1124 u.modtime = c;
1125 client->utime(a, &u, perms);
1126 } else if (strcmp(op, "mknod") == 0) {
1127 const char *a = t.get_string(buf, p);
1128 int64_t b = t.get_int();
1129 int64_t c = t.get_int();
1130 client->mknod(a, b, perms, c);
1131 } else if (strcmp(op, "oldmknod") == 0) {
1132 const char *a = t.get_string(buf, p);
1133 int64_t b = t.get_int();
1134 client->mknod(a, b, perms, 0);
1135 } else if (strcmp(op, "getdir") == 0) {
1136 const char *a = t.get_string(buf, p);
1137 list<string> contents;
1138 int r = client->getdir(a, contents, perms);
1139 if (r < 0) {
1140 dout(1) << "getdir on " << a << " returns " << r << dendl;
1141 }
1142 } else if (strcmp(op, "opendir") == 0) {
1143 const char *a = t.get_string(buf, p);
1144 int64_t b = t.get_int();
1145 dir_result_t *dirp;
1146 client->opendir(a, &dirp, perms);
1147 if (dirp) open_dirs[b] = dirp;
1148 } else if (strcmp(op, "closedir") == 0) {
1149 int64_t a = t.get_int();
1150 client->closedir(open_dirs[a]);
1151 open_dirs.erase(a);
1152 } else if (strcmp(op, "open") == 0) {
1153 const char *a = t.get_string(buf, p);
1154 int64_t b = t.get_int();
1155 int64_t c = t.get_int();
1156 int64_t d = t.get_int();
1157 int64_t fd = client->open(a, b, perms, c);
1158 if (fd > 0) open_files[d] = fd;
1159 } else if (strcmp(op, "oldopen") == 0) {
1160 const char *a = t.get_string(buf, p);
1161 int64_t b = t.get_int();
1162 int64_t d = t.get_int();
1163 int64_t fd = client->open(a, b, perms, 0755);
1164 if (fd > 0) open_files[d] = fd;
1165 } else if (strcmp(op, "close") == 0) {
1166 int64_t id = t.get_int();
1167 int64_t fh = open_files[id];
1168 if (fh > 0) client->close(fh);
1169 open_files.erase(id);
1170 } else if (strcmp(op, "lseek") == 0) {
1171 int64_t f = t.get_int();
1172 int fd = open_files[f];
1173 int64_t off = t.get_int();
1174 int64_t whence = t.get_int();
1175 client->lseek(fd, off, whence);
1176 } else if (strcmp(op, "read") == 0) {
1177 int64_t f = t.get_int();
1178 int64_t size = t.get_int();
1179 int64_t off = t.get_int();
1180 int64_t fd = open_files[f];
1181 if (!metadata_only) {
1182 char *b = new char[size];
1183 client->read(fd, b, size, off);
1184 delete[] b;
1185 }
1186 } else if (strcmp(op, "write") == 0) {
1187 int64_t f = t.get_int();
1188 int64_t fd = open_files[f];
1189 int64_t size = t.get_int();
1190 int64_t off = t.get_int();
1191 if (!metadata_only) {
1192 char *b = new char[size];
1193 memset(b, 1, size); // let's write 1's!
1194 client->write(fd, b, size, off);
1195 delete[] b;
1196 } else {
1197 client->write(fd, NULL, 0, size+off);
1198 }
1199 } else if (strcmp(op, "truncate") == 0) {
1200 const char *a = t.get_string(buf, p);
1201 int64_t l = t.get_int();
1202 client->truncate(a, l, perms);
1203 } else if (strcmp(op, "ftruncate") == 0) {
1204 int64_t f = t.get_int();
1205 int fd = open_files[f];
1206 int64_t l = t.get_int();
1207 client->ftruncate(fd, l, perms);
1208 } else if (strcmp(op, "fsync") == 0) {
1209 int64_t f = t.get_int();
1210 int64_t b = t.get_int();
1211 int fd = open_files[f];
1212 client->fsync(fd, b);
1213 } else if (strcmp(op, "chdir") == 0) {
1214 const char *a = t.get_string(buf, p);
1215 // Client users should remember their path, but since this
1216 // is just a synthetic client we ignore it.
1217 std::string ignore;
1218 client->chdir(a, ignore, perms);
1219 } else if (strcmp(op, "statfs") == 0) {
1220 struct statvfs stbuf;
1221 client->statfs("/", &stbuf, perms);
1222 }
1223
1224 // low level ops ---------------------
1225 else if (strcmp(op, "ll_lookup") == 0) {
1226 int64_t i = t.get_int();
1227 const char *name = t.get_string(buf, p);
1228 int64_t r = t.get_int();
1229 struct ceph_statx stx;
1230 if (ll_inos.count(i)) {
1231 i1 = client->ll_get_inode(vinodeno_t(ll_inos[i],CEPH_NOSNAP));
1232 if (client->ll_lookupx(i1, name, &i2, &stx, CEPH_STATX_INO, 0, perms) == 0)
1233 ll_inos[r] = stx.stx_ino;
1234 client->ll_put(i1);
1235 }
1236 } else if (strcmp(op, "ll_forget") == 0) {
1237 int64_t i = t.get_int();
1238 int64_t n = t.get_int();
1239 if (ll_inos.count(i) &&
1240 client->ll_forget(
1241 client->ll_get_inode(vinodeno_t(ll_inos[i],CEPH_NOSNAP)), n))
1242 ll_inos.erase(i);
1243 } else if (strcmp(op, "ll_getattr") == 0) {
1244 int64_t i = t.get_int();
1245 struct stat attr;
1246 if (ll_inos.count(i)) {
1247 i1 = client->ll_get_inode(vinodeno_t(ll_inos[i],CEPH_NOSNAP));
1248 client->ll_getattr(i1, &attr, perms);
1249 client->ll_put(i1);
1250 }
1251 } else if (strcmp(op, "ll_setattr") == 0) {
1252 int64_t i = t.get_int();
1253 struct stat attr;
1254 memset(&attr, 0, sizeof(attr));
1255 attr.st_mode = t.get_int();
1256 attr.st_uid = t.get_int();
1257 attr.st_gid = t.get_int();
1258 attr.st_size = t.get_int();
1259 attr.st_mtime = t.get_int();
1260 attr.st_atime = t.get_int();
1261 int mask = t.get_int();
1262 if (ll_inos.count(i)) {
1263 i1 = client->ll_get_inode(vinodeno_t(ll_inos[i],CEPH_NOSNAP));
1264 client->ll_setattr(i1, &attr, mask, perms);
1265 client->ll_put(i1);
1266 }
1267 } else if (strcmp(op, "ll_readlink") == 0) {
1268 int64_t i = t.get_int();
1269 if (ll_inos.count(i)) {
1270 char buf[PATH_MAX];
1271 i1 = client->ll_get_inode(vinodeno_t(ll_inos[i],CEPH_NOSNAP));
1272 client->ll_readlink(i1, buf, sizeof(buf), perms);
1273 client->ll_put(i1);
1274 }
1275 } else if (strcmp(op, "ll_mknod") == 0) {
1276 int64_t i = t.get_int();
1277 const char *n = t.get_string(buf, p);
1278 int m = t.get_int();
1279 int r = t.get_int();
1280 int64_t ri = t.get_int();
1281 struct stat attr;
1282 if (ll_inos.count(i)) {
1283 i1 = client->ll_get_inode(vinodeno_t(ll_inos[i],CEPH_NOSNAP));
1284 if (client->ll_mknod(i1, n, m, r, &attr, &i2, perms) == 0)
1285 ll_inos[ri] = attr.st_ino;
1286 client->ll_put(i1);
1287 }
1288 } else if (strcmp(op, "ll_mkdir") == 0) {
1289 int64_t i = t.get_int();
1290 const char *n = t.get_string(buf, p);
1291 int m = t.get_int();
1292 int64_t ri = t.get_int();
1293 struct stat attr;
1294 if (ll_inos.count(i)) {
1295 i1 = client->ll_get_inode(vinodeno_t(ll_inos[i],CEPH_NOSNAP));
1296 if (client->ll_mkdir(i1, n, m, &attr, &i2, perms) == 0)
1297 ll_inos[ri] = attr.st_ino;
1298 client->ll_put(i1);
1299 }
1300 } else if (strcmp(op, "ll_symlink") == 0) {
1301 int64_t i = t.get_int();
1302 const char *n = t.get_string(buf, p);
1303 const char *v = t.get_string(buf2, p);
1304 int64_t ri = t.get_int();
1305 struct stat attr;
1306 if (ll_inos.count(i)) {
1307 i1 = client->ll_get_inode(vinodeno_t(ll_inos[i],CEPH_NOSNAP));
1308 if (client->ll_symlink(i1, n, v, &attr, &i2, perms) == 0)
1309 ll_inos[ri] = attr.st_ino;
1310 client->ll_put(i1);
1311 }
1312 } else if (strcmp(op, "ll_unlink") == 0) {
1313 int64_t i = t.get_int();
1314 const char *n = t.get_string(buf, p);
1315 if (ll_inos.count(i)) {
1316 i1 = client->ll_get_inode(vinodeno_t(ll_inos[i],CEPH_NOSNAP));
1317 client->ll_unlink(i1, n, perms);
1318 client->ll_put(i1);
1319 }
1320 } else if (strcmp(op, "ll_rmdir") == 0) {
1321 int64_t i = t.get_int();
1322 const char *n = t.get_string(buf, p);
1323 if (ll_inos.count(i)) {
1324 i1 = client->ll_get_inode(vinodeno_t(ll_inos[i],CEPH_NOSNAP));
1325 client->ll_rmdir(i1, n, perms);
1326 client->ll_put(i1);
1327 }
1328 } else if (strcmp(op, "ll_rename") == 0) {
1329 int64_t i = t.get_int();
1330 const char *n = t.get_string(buf, p);
1331 int64_t ni = t.get_int();
1332 const char *nn = t.get_string(buf2, p);
1333 if (ll_inos.count(i) &&
1334 ll_inos.count(ni)) {
1335 i1 = client->ll_get_inode(vinodeno_t(ll_inos[i],CEPH_NOSNAP));
1336 i2 = client->ll_get_inode(vinodeno_t(ll_inos[ni],CEPH_NOSNAP));
1337 client->ll_rename(i1, n, i2, nn, perms);
1338 client->ll_put(i1);
1339 client->ll_put(i2);
1340 }
1341 } else if (strcmp(op, "ll_link") == 0) {
1342 int64_t i = t.get_int();
1343 int64_t ni = t.get_int();
1344 const char *nn = t.get_string(buf, p);
1345 if (ll_inos.count(i) &&
1346 ll_inos.count(ni)) {
1347 i1 = client->ll_get_inode(vinodeno_t(ll_inos[i],CEPH_NOSNAP));
1348 i2 = client->ll_get_inode(vinodeno_t(ll_inos[ni],CEPH_NOSNAP));
1349 client->ll_link(i1, i2, nn, perms);
1350 client->ll_put(i1);
1351 client->ll_put(i2);
1352 }
1353 } else if (strcmp(op, "ll_opendir") == 0) {
1354 int64_t i = t.get_int();
1355 int64_t r = t.get_int();
1356 dir_result_t *dirp;
1357 if (ll_inos.count(i)) {
1358 i1 = client->ll_get_inode(vinodeno_t(ll_inos[i],CEPH_NOSNAP));
1359 if (client->ll_opendir(i1, O_RDONLY, &dirp, perms) == 0)
1360 ll_dirs[r] = dirp;
1361 client->ll_put(i1);
1362 }
1363 } else if (strcmp(op, "ll_releasedir") == 0) {
1364 int64_t f = t.get_int();
1365 if (ll_dirs.count(f)) {
1366 client->ll_releasedir(ll_dirs[f]);
1367 ll_dirs.erase(f);
1368 }
1369 } else if (strcmp(op, "ll_open") == 0) {
1370 int64_t i = t.get_int();
1371 int64_t f = t.get_int();
1372 int64_t r = t.get_int();
1373 Fh *fhp;
1374 if (ll_inos.count(i)) {
1375 i1 = client->ll_get_inode(vinodeno_t(ll_inos[i],CEPH_NOSNAP));
1376 if (client->ll_open(i1, f, &fhp, perms) == 0)
1377 ll_files[r] = fhp;
1378 client->ll_put(i1);
1379 }
1380 } else if (strcmp(op, "ll_create") == 0) {
1381 int64_t i = t.get_int();
1382 const char *n = t.get_string(buf, p);
1383 int64_t m = t.get_int();
1384 int64_t f = t.get_int();
1385 int64_t r = t.get_int();
1386 int64_t ri = t.get_int();
1387 struct stat attr;
1388 if (ll_inos.count(i)) {
1389 Fh *fhp;
1390 i1 = client->ll_get_inode(vinodeno_t(ll_inos[i],CEPH_NOSNAP));
1391 if (client->ll_create(i1, n, m, f, &attr, NULL, &fhp, perms) == 0) {
1392 ll_inos[ri] = attr.st_ino;
1393 ll_files[r] = fhp;
1394 }
1395 client->ll_put(i1);
1396 }
1397 } else if (strcmp(op, "ll_read") == 0) {
1398 int64_t f = t.get_int();
1399 int64_t off = t.get_int();
1400 int64_t size = t.get_int();
1401 if (ll_files.count(f) &&
1402 !metadata_only) {
1403 bufferlist bl;
1404 client->ll_read(ll_files[f], off, size, &bl);
1405 }
1406 } else if (strcmp(op, "ll_write") == 0) {
1407 int64_t f = t.get_int();
1408 int64_t off = t.get_int();
1409 int64_t size = t.get_int();
1410 if (ll_files.count(f)) {
1411 if (!metadata_only) {
1412 bufferlist bl;
1413 bufferptr bp(size);
1414 bl.push_back(bp);
1415 bp.zero();
1416 client->ll_write(ll_files[f], off, size, bl.c_str());
1417 } else {
1418 client->ll_write(ll_files[f], off+size, 0, NULL);
1419 }
1420 }
1421 } else if (strcmp(op, "ll_flush") == 0) {
1422 int64_t f = t.get_int();
1423 if (!metadata_only &&
1424 ll_files.count(f))
1425 client->ll_flush(ll_files[f]);
1426 } else if (strcmp(op, "ll_fsync") == 0) {
1427 int64_t f = t.get_int();
1428 if (!metadata_only &&
1429 ll_files.count(f))
1430 client->ll_fsync(ll_files[f], false); // FIXME dataonly param
1431 } else if (strcmp(op, "ll_release") == 0) {
1432 int64_t f = t.get_int();
1433 if (ll_files.count(f)) {
1434 client->ll_release(ll_files[f]);
1435 ll_files.erase(f);
1436 }
1437 } else if (strcmp(op, "ll_statfs") == 0) {
1438 int64_t i = t.get_int();
1439 if (ll_inos.count(i))
1440 {} //client->ll_statfs(vinodeno_t(ll_inos[i],CEPH_NOSNAP), perms);
1441 }
1442
1443
1444 // object-level traces
1445
1446 else if (strcmp(op, "o_stat") == 0) {
1447 int64_t oh = t.get_int();
1448 int64_t ol = t.get_int();
1449 object_t oid = file_object_t(oh, ol);
1450 lock.Lock();
1451 object_locator_t oloc(SYNCLIENT_FIRST_POOL);
1452 uint64_t size;
1453 ceph::real_time mtime;
1454 client->objecter->stat(oid, oloc, CEPH_NOSNAP, &size, &mtime, 0,
1455 new C_SafeCond(&lock, &cond, &ack));
1456 while (!ack) cond.Wait(lock);
1457 lock.Unlock();
1458 }
1459 else if (strcmp(op, "o_read") == 0) {
1460 int64_t oh = t.get_int();
1461 int64_t ol = t.get_int();
1462 int64_t off = t.get_int();
1463 int64_t len = t.get_int();
1464 object_t oid = file_object_t(oh, ol);
1465 object_locator_t oloc(SYNCLIENT_FIRST_POOL);
1466 lock.Lock();
1467 bufferlist bl;
1468 client->objecter->read(oid, oloc, off, len, CEPH_NOSNAP, &bl, 0,
1469 new C_SafeCond(&lock, &cond, &ack));
1470 while (!ack) cond.Wait(lock);
1471 lock.Unlock();
1472 }
1473 else if (strcmp(op, "o_write") == 0) {
1474 int64_t oh = t.get_int();
1475 int64_t ol = t.get_int();
1476 int64_t off = t.get_int();
1477 int64_t len = t.get_int();
1478 object_t oid = file_object_t(oh, ol);
1479 object_locator_t oloc(SYNCLIENT_FIRST_POOL);
1480 lock.Lock();
1481 bufferptr bp(len);
1482 bufferlist bl;
1483 bl.push_back(bp);
1484 SnapContext snapc;
1485 client->objecter->write(oid, oloc, off, len, snapc, bl,
1486 ceph::real_clock::now(), 0,
1487 new C_SafeCond(&lock, &cond, &ack));
1488 while (!ack) cond.Wait(lock);
1489 lock.Unlock();
1490 }
1491 else if (strcmp(op, "o_zero") == 0) {
1492 int64_t oh = t.get_int();
1493 int64_t ol = t.get_int();
1494 int64_t off = t.get_int();
1495 int64_t len = t.get_int();
1496 object_t oid = file_object_t(oh, ol);
1497 object_locator_t oloc(SYNCLIENT_FIRST_POOL);
1498 lock.Lock();
1499 SnapContext snapc;
1500 client->objecter->zero(oid, oloc, off, len, snapc,
1501 ceph::real_clock::now(), 0,
1502 new C_SafeCond(&lock, &cond, &ack));
1503 while (!ack) cond.Wait(lock);
1504 lock.Unlock();
1505 }
1506
1507
1508 else {
1509 dout(0) << (t.get_line()-1) << ": *** trace hit unrecognized symbol '" << op << "' " << dendl;
1510 ceph_abort();
1511 }
1512 }
1513
1514 dout(10) << "trace finished on line " << t.get_line() << dendl;
1515
1516 // close open files
1517 for (ceph::unordered_map<int64_t, int64_t>::iterator fi = open_files.begin();
1518 fi != open_files.end();
1519 ++fi) {
1520 dout(1) << "leftover close " << fi->second << dendl;
1521 if (fi->second > 0) client->close(fi->second);
1522 }
1523 for (ceph::unordered_map<int64_t, dir_result_t*>::iterator fi = open_dirs.begin();
1524 fi != open_dirs.end();
1525 ++fi) {
1526 dout(1) << "leftover closedir " << fi->second << dendl;
1527 if (fi->second != 0) client->closedir(fi->second);
1528 }
1529 for (ceph::unordered_map<int64_t,Fh*>::iterator fi = ll_files.begin();
1530 fi != ll_files.end();
1531 ++fi) {
1532 dout(1) << "leftover ll_release " << fi->second << dendl;
1533 if (fi->second) client->ll_release(fi->second);
1534 }
1535 for (ceph::unordered_map<int64_t,dir_result_t*>::iterator fi = ll_dirs.begin();
1536 fi != ll_dirs.end();
1537 ++fi) {
1538 dout(1) << "leftover ll_releasedir " << fi->second << dendl;
1539 if (fi->second) client->ll_releasedir(fi->second);
1540 }
1541
1542 return 0;
1543}
1544
1545
1546
1547int SyntheticClient::clean_dir(string& basedir)
1548{
1549 // read dir
1550 list<string> contents;
1551 UserPerm perms = client->pick_my_perms();
1552 int r = client->getdir(basedir.c_str(), contents, perms);
1553 if (r < 0) {
1554 dout(1) << "getdir on " << basedir << " returns " << r << dendl;
1555 return r;
1556 }
1557
1558 for (list<string>::iterator it = contents.begin();
1559 it != contents.end();
1560 ++it) {
1561 if (*it == ".") continue;
1562 if (*it == "..") continue;
1563 string file = basedir + "/" + *it;
1564
1565 if (time_to_stop()) break;
1566
1567 struct stat st;
1568 int r = client->lstat(file.c_str(), &st, perms);
1569 if (r < 0) {
1570 dout(1) << "stat error on " << file << " r=" << r << dendl;
1571 continue;
1572 }
1573
1574 if ((st.st_mode & S_IFMT) == S_IFDIR) {
1575 clean_dir(file);
1576 client->rmdir(file.c_str(), perms);
1577 } else {
1578 client->unlink(file.c_str(), perms);
1579 }
1580 }
1581
1582 return 0;
1583
1584}
1585
1586
1587int SyntheticClient::full_walk(string& basedir)
1588{
1589 if (time_to_stop()) return -1;
1590
1591 list<string> dirq;
1592 list<frag_info_t> statq;
1593 dirq.push_back(basedir);
1594 frag_info_t empty;
1595 memset(&empty, 0, sizeof(empty));
1596 statq.push_back(empty);
1597
1598 ceph::unordered_map<inodeno_t, int> nlink;
1599 ceph::unordered_map<inodeno_t, int> nlink_seen;
1600
1601 UserPerm perms = client->pick_my_perms();
1602 while (!dirq.empty()) {
1603 string dir = dirq.front();
1604 frag_info_t expect = statq.front();
1605 dirq.pop_front();
1606 statq.pop_front();
1607
1608 frag_info_t actual = empty;
1609
1610 // read dir
1611 list<string> contents;
1612 int r = client->getdir(dir.c_str(), contents, perms);
1613 if (r < 0) {
1614 dout(1) << "getdir on " << dir << " returns " << r << dendl;
1615 continue;
1616 }
1617
1618 for (list<string>::iterator it = contents.begin();
1619 it != contents.end();
1620 ++it) {
1621 if (*it == "." ||
1622 *it == "..")
1623 continue;
1624 string file = dir + "/" + *it;
1625
1626 struct stat st;
1627 frag_info_t dirstat;
1628 int r = client->lstat(file.c_str(), &st, perms, &dirstat);
1629 if (r < 0) {
1630 dout(1) << "stat error on " << file << " r=" << r << dendl;
1631 continue;
1632 }
1633
1634 nlink_seen[st.st_ino]++;
1635 nlink[st.st_ino] = st.st_nlink;
1636
1637 if (S_ISDIR(st.st_mode))
1638 actual.nsubdirs++;
1639 else
1640 actual.nfiles++;
1641
1642 // print
1643 char *tm = ctime(&st.st_mtime);
1644 tm[strlen(tm)-1] = 0;
1645 printf("%llx %c%c%c%c%c%c%c%c%c%c %2d %5d %5d %8llu %12s %s\n",
1646 (long long)st.st_ino,
1647 S_ISDIR(st.st_mode) ? 'd':'-',
1648 (st.st_mode & 0400) ? 'r':'-',
1649 (st.st_mode & 0200) ? 'w':'-',
1650 (st.st_mode & 0100) ? 'x':'-',
1651 (st.st_mode & 040) ? 'r':'-',
1652 (st.st_mode & 020) ? 'w':'-',
1653 (st.st_mode & 010) ? 'x':'-',
1654 (st.st_mode & 04) ? 'r':'-',
1655 (st.st_mode & 02) ? 'w':'-',
1656 (st.st_mode & 01) ? 'x':'-',
1657 (int)st.st_nlink,
1658 (int)st.st_uid, (int)st.st_gid,
1659 (long long unsigned)st.st_size,
1660 tm,
1661 file.c_str());
1662
1663
1664 if ((st.st_mode & S_IFMT) == S_IFDIR) {
1665 dirq.push_back(file);
1666 statq.push_back(dirstat);
1667 }
1668 }
1669
1670 if (dir != "" &&
1671 (actual.nsubdirs != expect.nsubdirs ||
1672 actual.nfiles != expect.nfiles)) {
1673 dout(0) << dir << ": expected " << expect << dendl;
1674 dout(0) << dir << ": got " << actual << dendl;
1675 }
1676 }
1677
1678 for (ceph::unordered_map<inodeno_t,int>::iterator p = nlink.begin(); p != nlink.end(); ++p) {
1679 if (nlink_seen[p->first] != p->second)
1680 dout(0) << p->first << " nlink " << p->second << " != " << nlink_seen[p->first] << "seen" << dendl;
1681 }
1682
1683 return 0;
1684}
1685
1686
1687
1688int SyntheticClient::dump_placement(string& fn) {
1689
1690 UserPerm perms = client->pick_my_perms();
1691
1692 // open file
1693 int fd = client->open(fn.c_str(), O_RDONLY, perms);
1694 dout(5) << "reading from " << fn << " fd " << fd << dendl;
1695 if (fd < 0) return fd;
1696
1697
1698 // How big is it?
1699 struct stat stbuf;
1700 int lstat_result = client->lstat(fn.c_str(), &stbuf, perms);
1701 if (lstat_result < 0) {
1702 dout(0) << "lstat error for file " << fn << dendl;
1703 client->close(fd);
1704 return lstat_result;
1705 }
1706
1707 off_t filesize = stbuf.st_size;
1708
1709 // grab the placement info
1710 vector<ObjectExtent> extents;
1711 off_t offset = 0;
1712 client->enumerate_layout(fd, extents, filesize, offset);
1713 client->close(fd);
1714
1715
1716 // run through all the object extents
1717 dout(0) << "file size is " << filesize << dendl;
1718 dout(0) << "(osd, start, length) tuples for file " << fn << dendl;
1719 for (const auto& x : extents) {
1720 int osd = client->objecter->with_osdmap([&](const OSDMap& o) {
1721 return o.get_pg_acting_primary(o.object_locator_to_pg(x.oid, x.oloc));
1722 });
1723
1724 // run through all the buffer extents
1725 for (const auto& be : x.buffer_extents)
1726 dout(0) << "OSD " << osd << ", offset " << be.first
1727 << ", length " << be.second << dendl;
1728 }
1729 return 0;
1730}
1731
1732
1733
1734int SyntheticClient::make_dirs(const char *basedir, int dirs, int files, int depth)
1735{
1736 if (time_to_stop()) return 0;
1737
1738 UserPerm perms = client->pick_my_perms();
1739 // make sure base dir exists
1740 int r = client->mkdir(basedir, 0755, perms);
1741 if (r != 0) {
1742 dout(1) << "can't make base dir? " << basedir << dendl;
1743 //return -1;
1744 }
1745
1746 // children
1747 char d[500];
1748 dout(3) << "make_dirs " << basedir << " dirs " << dirs << " files " << files << " depth " << depth << dendl;
1749 for (int i=0; i<files; i++) {
1750 snprintf(d, sizeof(d), "%s/file.%d", basedir, i);
1751 client->mknod(d, 0644, perms);
1752 }
1753
1754 if (depth == 0) return 0;
1755
1756 for (int i=0; i<dirs; i++) {
1757 snprintf(d, sizeof(d), "%s/dir.%d", basedir, i);
1758 make_dirs(d, dirs, files, depth-1);
1759 }
1760
1761 return 0;
1762}
1763
1764int SyntheticClient::stat_dirs(const char *basedir, int dirs, int files, int depth)
1765{
1766 if (time_to_stop()) return 0;
1767
1768 UserPerm perms = client->pick_my_perms();
1769
1770 // make sure base dir exists
1771 struct stat st;
1772 int r = client->lstat(basedir, &st, perms);
1773 if (r != 0) {
1774 dout(1) << "can't make base dir? " << basedir << dendl;
1775 return -1;
1776 }
1777
1778 // children
1779 char d[500];
1780 dout(3) << "stat_dirs " << basedir << " dirs " << dirs << " files " << files << " depth " << depth << dendl;
1781 for (int i=0; i<files; i++) {
1782 snprintf(d, sizeof(d), "%s/file.%d", basedir, i);
1783 client->lstat(d, &st, perms);
1784 }
1785
1786 if (depth == 0) return 0;
1787
1788 for (int i=0; i<dirs; i++) {
1789 snprintf(d, sizeof(d), "%s/dir.%d", basedir, i);
1790 stat_dirs(d, dirs, files, depth-1);
1791 }
1792
1793 return 0;
1794}
1795int SyntheticClient::read_dirs(const char *basedir, int dirs, int files, int depth)
1796{
1797 if (time_to_stop()) return 0;
1798
1799 struct stat st;
1800
1801 // children
1802 char d[500];
1803 dout(3) << "read_dirs " << basedir << " dirs " << dirs << " files " << files << " depth " << depth << dendl;
1804
1805 list<string> contents;
1806 UserPerm perms = client->pick_my_perms();
1807 utime_t s = ceph_clock_now();
1808 int r = client->getdir(basedir, contents, perms);
1809 utime_t e = ceph_clock_now();
1810 e -= s;
1811 if (r < 0) {
1812 dout(0) << "getdir couldn't readdir " << basedir << ", stopping" << dendl;
1813 return -1;
1814 }
1815
1816 for (int i=0; i<files; i++) {
1817 snprintf(d, sizeof(d), "%s/file.%d", basedir, i);
1818 utime_t s = ceph_clock_now();
1819 if (client->lstat(d, &st, perms) < 0) {
1820 dout(2) << "read_dirs failed stat on " << d << ", stopping" << dendl;
1821 return -1;
1822 }
1823 utime_t e = ceph_clock_now();
1824 e -= s;
1825 }
1826
1827 if (depth > 0)
1828 for (int i=0; i<dirs; i++) {
1829 snprintf(d, sizeof(d), "%s/dir.%d", basedir, i);
1830 if (read_dirs(d, dirs, files, depth-1) < 0) return -1;
1831 }
1832
1833 return 0;
1834}
1835
1836
1837int SyntheticClient::make_files(int num, int count, int priv, bool more)
1838{
1839 int whoami = client->get_nodeid().v;
1840 char d[255];
1841 UserPerm perms = client->pick_my_perms();
1842
1843 if (priv) {
1844 for (int c=0; c<count; c++) {
1845 snprintf(d, sizeof(d), "dir.%d.run%d", whoami, c);
1846 client->mkdir(d, 0755, perms);
1847 }
1848 } else {
1849 // shared
1850 if (true || whoami == 0) {
1851 for (int c=0; c<count; c++) {
1852 snprintf(d, sizeof(d), "dir.%d.run%d", 0, c);
1853 client->mkdir(d, 0755, perms);
1854 }
1855 } else {
1856 sleep(2);
1857 }
1858 }
1859
1860 // files
1861 struct stat st;
1862 utime_t start = ceph_clock_now();
1863 for (int c=0; c<count; c++) {
1864 for (int n=0; n<num; n++) {
1865 snprintf(d, sizeof(d), "dir.%d.run%d/file.client%d.%d", priv ? whoami:0, c, whoami, n);
1866
1867 client->mknod(d, 0644, perms);
1868
1869 if (more) {
1870 client->lstat(d, &st, perms);
1871 int fd = client->open(d, O_RDONLY, perms);
1872 client->unlink(d, perms);
1873 client->close(fd);
1874 }
1875
1876 if (time_to_stop()) return 0;
1877 }
1878 }
1879 utime_t end = ceph_clock_now();
1880 end -= start;
1881 dout(0) << "makefiles time is " << end << " or " << ((double)end / (double)num) <<" per file" << dendl;
1882
1883 return 0;
1884}
1885
1886int SyntheticClient::link_test()
1887{
1888 char d[255];
1889 char e[255];
1890
1891 UserPerm perms = client->pick_my_perms();
1892
1893 // create files
1894 int num = 200;
1895
1896 client->mkdir("orig", 0755, perms);
1897 client->mkdir("copy", 0755, perms);
1898
1899 utime_t start = ceph_clock_now();
1900 for (int i=0; i<num; i++) {
1901 snprintf(d, sizeof(d), "orig/file.%d", i);
1902 client->mknod(d, 0755, perms);
1903 }
1904 utime_t end = ceph_clock_now();
1905 end -= start;
1906
1907 dout(0) << "orig " << end << dendl;
1908
1909 // link
1910 start = ceph_clock_now();
1911 for (int i=0; i<num; i++) {
1912 snprintf(d, sizeof(d), "orig/file.%d", i);
1913 snprintf(e, sizeof(e), "copy/file.%d", i);
1914 client->link(d, e, perms);
1915 }
1916 end = ceph_clock_now();
1917 end -= start;
1918 dout(0) << "copy " << end << dendl;
1919
1920 return 0;
1921}
1922
1923
1924int SyntheticClient::create_shared(int num)
1925{
1926 // files
1927 UserPerm perms = client->pick_my_perms();
1928 char d[255];
1929 client->mkdir("test", 0755, perms);
1930 for (int n=0; n<num; n++) {
1931 snprintf(d, sizeof(d), "test/file.%d", n);
1932 client->mknod(d, 0644, perms);
1933 }
1934
1935 return 0;
1936}
1937
1938int SyntheticClient::open_shared(int num, int count)
1939{
1940 // files
1941 char d[255];
1942 UserPerm perms = client->pick_my_perms();
1943 for (int c=0; c<count; c++) {
1944 // open
1945 list<int> fds;
1946 for (int n=0; n<num; n++) {
1947 snprintf(d, sizeof(d), "test/file.%d", n);
1948 int fd = client->open(d, O_RDONLY, perms);
1949 if (fd > 0) fds.push_back(fd);
1950 }
1951
1952 if (false && client->get_nodeid() == 0)
1953 for (int n=0; n<num; n++) {
1954 snprintf(d, sizeof(d), "test/file.%d", n);
1955 client->unlink(d, perms);
1956 }
1957
1958 while (!fds.empty()) {
1959 int fd = fds.front();
1960 fds.pop_front();
1961 client->close(fd);
1962 }
1963 }
1964
1965 return 0;
1966}
1967
1968
1969// Hits OSD 0 with writes to various files with OSD 0 as the primary.
1970int SyntheticClient::overload_osd_0(int n, int size, int wrsize) {
1971 UserPerm perms = client->pick_my_perms();
1972 // collect a bunch of files starting on OSD 0
1973 int left = n;
1974 int tried = 0;
1975 while (left < 0) {
1976
1977
1978 // pull open a file
1979 dout(0) << "in OSD overload" << dendl;
1980 string filename = get_sarg(tried);
1981 dout(1) << "OSD Overload workload: trying file " << filename << dendl;
1982 int fd = client->open(filename.c_str(), O_RDWR|O_CREAT, perms);
1983 ++tried;
1984
1985 // only use the file if its first primary is OSD 0
1986 int primary_osd = check_first_primary(fd);
1987 if (primary_osd != 0) {
1988 client->close(fd);
1989 dout(1) << "OSD Overload workload: SKIPPING file " << filename <<
1990 " with OSD " << primary_osd << " as first primary. " << dendl;
1991 continue;
1992 }
1993 dout(1) << "OSD Overload workload: USING file " << filename <<
1994 " with OSD 0 as first primary. " << dendl;
1995
1996
1997 --left;
1998 // do whatever operation we want to do on the file. How about a write?
1999 write_fd(fd, size, wrsize);
2000 }
2001 return 0;
2002}
2003
2004
2005// See what the primary is for the first object in this file.
2006int SyntheticClient::check_first_primary(int fh)
2007{
2008 vector<ObjectExtent> extents;
2009 client->enumerate_layout(fh, extents, 1, 0);
2010 return client->objecter->with_osdmap([&](const OSDMap& o) {
2011 return o.get_pg_acting_primary(
2012 o.object_locator_to_pg(extents.begin()->oid, extents.begin()->oloc));
2013 });
2014}
2015
2016int SyntheticClient::rm_file(string& fn)
2017{
2018 UserPerm perms = client->pick_my_perms();
2019 return client->unlink(fn.c_str(), perms);
2020}
2021
2022int SyntheticClient::write_file(string& fn, int size, loff_t wrsize) // size is in MB, wrsize in bytes
2023{
2024 //uint64_t wrsize = 1024*256;
2025 char *buf = new char[wrsize+100]; // 1 MB
2026 memset(buf, 7, wrsize);
2027 int64_t chunks = (uint64_t)size * (uint64_t)(1024*1024) / (uint64_t)wrsize;
2028 UserPerm perms = client->pick_my_perms();
2029
2030 int fd = client->open(fn.c_str(), O_RDWR|O_CREAT, perms);
2031 dout(5) << "writing to " << fn << " fd " << fd << dendl;
2032 if (fd < 0) {
2033 delete[] buf;
2034 return fd;
2035 }
2036
2037 utime_t from = ceph_clock_now();
2038 utime_t start = from;
2039 uint64_t bytes = 0, total = 0;
2040
2041
2042 for (loff_t i=0; i<chunks; i++) {
2043 if (time_to_stop()) {
2044 dout(0) << "stopping" << dendl;
2045 break;
2046 }
2047 dout(2) << "writing block " << i << "/" << chunks << dendl;
2048
2049 // fill buf with a 16 byte fingerprint
2050 // 64 bits : file offset
2051 // 64 bits : client id
2052 // = 128 bits (16 bytes)
2053 uint64_t *p = (uint64_t*)buf;
2054 while ((char*)p < buf + wrsize) {
2055 *p = (uint64_t)i*(uint64_t)wrsize + (uint64_t)((char*)p - buf);
2056 p++;
2057 *p = client->get_nodeid().v;
2058 p++;
2059 }
2060
2061 client->write(fd, buf, wrsize, i*wrsize);
2062 bytes += wrsize;
2063 total += wrsize;
2064
2065 utime_t now = ceph_clock_now();
2066 if (now - from >= 1.0) {
2067 double el = now - from;
2068 dout(0) << "write " << (bytes / el / 1048576.0) << " MB/sec" << dendl;
2069 from = now;
2070 bytes = 0;
2071 }
2072 }
2073
2074 client->fsync(fd, true);
2075
2076 utime_t stop = ceph_clock_now();
2077 double el = stop - start;
2078 dout(0) << "write total " << (total / el / 1048576.0) << " MB/sec ("
2079 << total << " bytes in " << el << " seconds)" << dendl;
2080
2081 client->close(fd);
2082 delete[] buf;
2083
2084 return 0;
2085}
2086
2087int SyntheticClient::write_fd(int fd, int size, int wrsize) // size is in MB, wrsize in bytes
2088{
2089 //uint64_t wrsize = 1024*256;
2090 char *buf = new char[wrsize+100]; // 1 MB
2091 memset(buf, 7, wrsize);
2092 uint64_t chunks = (uint64_t)size * (uint64_t)(1024*1024) / (uint64_t)wrsize;
2093
2094 //dout(5) << "SyntheticClient::write_fd: writing to fd " << fd << dendl;
2095 if (fd < 0) {
2096 delete[] buf;
2097 return fd;
2098 }
2099
2100 for (unsigned i=0; i<chunks; i++) {
2101 if (time_to_stop()) {
2102 dout(0) << "stopping" << dendl;
2103 break;
2104 }
2105 dout(2) << "writing block " << i << "/" << chunks << dendl;
2106
2107 // fill buf with a 16 byte fingerprint
2108 // 64 bits : file offset
2109 // 64 bits : client id
2110 // = 128 bits (16 bytes)
2111 uint64_t *p = (uint64_t*)buf;
2112 while ((char*)p < buf + wrsize) {
2113 *p = (uint64_t)i*(uint64_t)wrsize + (uint64_t)((char*)p - buf);
2114 p++;
2115 *p = client->get_nodeid().v;
2116 p++;
2117 }
2118
2119 client->write(fd, buf, wrsize, i*wrsize);
2120 }
2121 client->close(fd);
2122 delete[] buf;
2123
2124 return 0;
2125}
2126
2127
2128int SyntheticClient::write_batch(int nfile, int size, int wrsize)
2129{
2130 for (int i=0; i<nfile; i++) {
2131 string sarg1 = get_sarg(i);
2132 dout(0) << "Write file " << sarg1 << dendl;
2133 write_file(sarg1, size, wrsize);
2134 }
2135 return 0;
2136}
2137
2138// size is in MB, wrsize in bytes
2139int SyntheticClient::read_file(const std::string& fn, int size,
2140 int rdsize, bool ignoreprint)
2141{
2142 char *buf = new char[rdsize];
2143 memset(buf, 1, rdsize);
2144 uint64_t chunks = (uint64_t)size * (uint64_t)(1024*1024) / (uint64_t)rdsize;
2145 UserPerm perms = client->pick_my_perms();
2146
2147 int fd = client->open(fn.c_str(), O_RDONLY, perms);
2148 dout(5) << "reading from " << fn << " fd " << fd << dendl;
2149 if (fd < 0) {
2150 delete[] buf;
2151 return fd;
2152 }
2153
2154 utime_t from = ceph_clock_now();
2155 utime_t start = from;
2156 uint64_t bytes = 0, total = 0;
2157
2158 for (unsigned i=0; i<chunks; i++) {
2159 if (time_to_stop()) break;
2160 dout(2) << "reading block " << i << "/" << chunks << dendl;
2161 int r = client->read(fd, buf, rdsize, i*rdsize);
2162 if (r < rdsize) {
2163 dout(1) << "read_file got r = " << r << ", probably end of file" << dendl;
2164 break;
2165 }
2166
2167 bytes += rdsize;
2168 total += rdsize;
2169
2170 utime_t now = ceph_clock_now();
2171 if (now - from >= 1.0) {
2172 double el = now - from;
2173 dout(0) << "read " << (bytes / el / 1048576.0) << " MB/sec" << dendl;
2174 from = now;
2175 bytes = 0;
2176 }
2177
2178 // verify fingerprint
2179 int bad = 0;
2180 uint64_t *p = (uint64_t*)buf;
2181 while ((char*)p + 32 < buf + rdsize) {
2182 uint64_t readoff = *p;
2183 uint64_t wantoff = (uint64_t)i*(uint64_t)rdsize + (uint64_t)((char*)p - buf);
2184 p++;
2185 int64_t readclient = *p;
2186 p++;
2187 if (readoff != wantoff ||
2188 readclient != client->get_nodeid()) {
2189 if (!bad && !ignoreprint)
2190 dout(0) << "WARNING: wrong data from OSD, block says fileoffset=" << readoff << " client=" << readclient
2191 << ", should be offset " << wantoff << " client " << client->get_nodeid()
2192 << dendl;
2193 bad++;
2194 }
2195 }
2196 if (bad && !ignoreprint)
2197 dout(0) << " + " << (bad-1) << " other bad 16-byte bits in this block" << dendl;
2198 }
2199
2200 utime_t stop = ceph_clock_now();
2201 double el = stop - start;
2202 dout(0) << "read total " << (total / el / 1048576.0) << " MB/sec ("
2203 << total << " bytes in " << el << " seconds)" << dendl;
2204
2205 client->close(fd);
2206 delete[] buf;
2207
2208 return 0;
2209}
2210
2211
2212
2213
2214class C_Ref : public Context {
2215 Mutex& lock;
2216 Cond& cond;
2217 int *ref;
2218public:
2219 C_Ref(Mutex &l, Cond &c, int *r) : lock(l), cond(c), ref(r) {
2220 lock.Lock();
2221 (*ref)++;
2222 lock.Unlock();
2223 }
2224 void finish(int) override {
2225 lock.Lock();
2226 (*ref)--;
2227 cond.Signal();
2228 lock.Unlock();
2229 }
2230};
2231
2232int SyntheticClient::create_objects(int nobj, int osize, int inflight)
2233{
2234 // divy up
2235 int numc = client->cct->_conf->num_client ? client->cct->_conf->num_client : 1;
2236
2237 int start, inc, end;
2238
2239 if (1) {
2240 // strided
2241 start = client->get_nodeid().v; //nobjs % numc;
2242 inc = numc;
2243 end = start + nobj;
2244 } else {
2245 // segments
2246 start = nobj * client->get_nodeid().v / numc;
2247 inc = 1;
2248 end = nobj * (client->get_nodeid().v+1) / numc;
2249 }
2250
2251 dout(5) << "create_objects " << nobj << " size=" << osize
2252 << " .. doing [" << start << "," << end << ") inc " << inc
2253 << dendl;
2254
2255 bufferptr bp(osize);
2256 bp.zero();
2257 bufferlist bl;
2258 bl.push_back(bp);
2259
2260 Mutex lock("create_objects lock");
2261 Cond cond;
2262
2263 int unsafe = 0;
2264
2265 list<utime_t> starts;
2266
2267 for (int i=start; i<end; i += inc) {
2268 if (time_to_stop()) break;
2269
2270 object_t oid = file_object_t(999, i);
2271 object_locator_t oloc(SYNCLIENT_FIRST_POOL);
2272 SnapContext snapc;
2273
2274 if (i % inflight == 0) {
2275 dout(6) << "create_objects " << i << "/" << (nobj+1) << dendl;
2276 }
2277 dout(10) << "writing " << oid << dendl;
2278
2279 starts.push_back(ceph_clock_now());
2280 client->client_lock.Lock();
2281 client->objecter->write(oid, oloc, 0, osize, snapc, bl,
2282 ceph::real_clock::now(), 0,
2283 new C_Ref(lock, cond, &unsafe));
2284 client->client_lock.Unlock();
2285
2286 lock.Lock();
2287 while (unsafe > inflight) {
2288 dout(20) << "waiting for " << unsafe << " unsafe" << dendl;
2289 cond.Wait(lock);
2290 }
2291 lock.Unlock();
2292
2293 utime_t lat = ceph_clock_now();
2294 lat -= starts.front();
2295 starts.pop_front();
2296 }
2297
2298 lock.Lock();
2299 while (unsafe > 0) {
2300 dout(10) << "waiting for " << unsafe << " unsafe" << dendl;
2301 cond.Wait(lock);
2302 }
2303 lock.Unlock();
2304
2305 dout(5) << "create_objects done" << dendl;
2306 return 0;
2307}
2308
2309int SyntheticClient::object_rw(int nobj, int osize, int wrpc,
2310 int overlappc,
2311 double rskew, double wskew)
2312{
2313 dout(5) << "object_rw " << nobj << " size=" << osize << " with "
2314 << wrpc << "% writes"
2315 << ", " << overlappc << "% overlap"
2316 << ", rskew = " << rskew
2317 << ", wskew = " << wskew
2318 << dendl;
2319
2320 bufferptr bp(osize);
2321 bp.zero();
2322 bufferlist bl;
2323 bl.push_back(bp);
2324
2325 // start with odd number > nobj
2326 rjhash<uint32_t> h;
2327 unsigned prime = nobj + 1; // this is the minimum!
2328 prime += h(nobj) % (3*nobj); // bump it up some
2329 prime |= 1; // make it odd
2330
2331 while (true) {
2332 unsigned j;
2333 for (j=2; j*j<=prime; j++)
2334 if (prime % j == 0) break;
2335 if (j*j > prime) {
2336 break;
2337 //cout << "prime " << prime << endl;
2338 }
2339 prime += 2;
2340 }
2341
2342 Mutex lock("lock");
2343 Cond cond;
2344
2345 int unack = 0;
2346
2347 while (1) {
2348 if (time_to_stop()) break;
2349
2350 // read or write?
2351 bool write = (rand() % 100) < wrpc;
2352
2353 // choose object
2354 double r = drand48(); // [0..1)
2355 long o;
2356 if (write) {
2357 o = (long)trunc(pow(r, wskew) * (double)nobj); // exponentially skew towards 0
2358 int pnoremap = (long)(r * 100.0);
2359 if (pnoremap >= overlappc)
2360 o = (o*prime) % nobj; // remap
2361 } else {
2362 o = (long)trunc(pow(r, rskew) * (double)nobj); // exponentially skew towards 0
2363 }
2364 object_t oid = file_object_t(999, o);
2365 object_locator_t oloc(SYNCLIENT_FIRST_POOL);
2366 SnapContext snapc;
2367
2368 client->client_lock.Lock();
2369 utime_t start = ceph_clock_now();
2370 if (write) {
2371 dout(10) << "write to " << oid << dendl;
2372
2373 ObjectOperation m;
2374 OSDOp op;
2375 op.op.op = CEPH_OSD_OP_WRITE;
2376 op.op.extent.offset = 0;
2377 op.op.extent.length = osize;
2378 op.indata = bl;
2379 m.ops.push_back(op);
2380 client->objecter->mutate(oid, oloc, m, snapc,
2381 ceph::real_clock::now(), 0,
2382 new C_Ref(lock, cond, &unack));
2383 } else {
2384 dout(10) << "read from " << oid << dendl;
2385 bufferlist inbl;
2386 client->objecter->read(oid, oloc, 0, osize, CEPH_NOSNAP, &inbl, 0,
2387 new C_Ref(lock, cond, &unack));
2388 }
2389 client->client_lock.Unlock();
2390
2391 lock.Lock();
2392 while (unack > 0) {
2393 dout(20) << "waiting for " << unack << " unack" << dendl;
2394 cond.Wait(lock);
2395 }
2396 lock.Unlock();
2397
2398 utime_t lat = ceph_clock_now();
2399 lat -= start;
2400 }
2401
2402 return 0;
2403}
2404
2405
2406
2407
2408
2409int SyntheticClient::read_random(string& fn, int size, int rdsize) // size is in MB, wrsize in bytes
2410{
2411 UserPerm perms = client->pick_my_perms();
2412 uint64_t chunks = (uint64_t)size * (uint64_t)(1024*1024) / (uint64_t)rdsize;
2413 int fd = client->open(fn.c_str(), O_RDWR, perms);
2414 dout(5) << "reading from " << fn << " fd " << fd << dendl;
2415
2416 if (fd < 0) return fd;
2417 int offset = 0;
2418 char * buf = NULL;
2419
2420 for (unsigned i=0; i<2000; i++) {
2421 if (time_to_stop()) break;
2422
2423 bool read=false;
2424
2425 time_t seconds;
2426 time( &seconds);
2427 srand(seconds);
2428
2429 // use rand instead ??
2430 double x = drand48();
2431
2432 // cleanup before call 'new'
2433 if (buf != NULL) {
2434 delete[] buf;
2435 buf = NULL;
2436 }
2437 if (x < 0.5) {
2438 buf = new char[rdsize];
2439 memset(buf, 1, rdsize);
2440 read=true;
2441 } else {
2442 buf = new char[rdsize+100]; // 1 MB
2443 memset(buf, 7, rdsize);
2444 }
2445
2446 if (read) {
2447 offset=(rand())%(chunks+1);
2448 dout(2) << "reading block " << offset << "/" << chunks << dendl;
2449
2450 int r = client->read(fd, buf, rdsize, offset*rdsize);
2451 if (r < rdsize) {
2452 dout(1) << "read_file got r = " << r << ", probably end of file" << dendl;
2453 }
2454 } else {
2455 dout(2) << "writing block " << offset << "/" << chunks << dendl;
2456
2457 // fill buf with a 16 byte fingerprint
2458 // 64 bits : file offset
2459 // 64 bits : client id
2460 // = 128 bits (16 bytes)
2461
2462 offset=(rand())%(chunks+1);
2463 uint64_t *p = (uint64_t*)buf;
2464 while ((char*)p < buf + rdsize) {
2465 *p = offset*rdsize + (char*)p - buf;
2466 p++;
2467 *p = client->get_nodeid().v;
2468 p++;
2469 }
2470
2471 client->write(fd, buf, rdsize,
2472 offset*rdsize);
2473 }
2474
2475 // verify fingerprint
2476 if (read) {
2477 int bad = 0;
2478 int64_t *p = (int64_t*)buf;
2479 while ((char*)p + 32 < buf + rdsize) {
2480 int64_t readoff = *p;
2481 int64_t wantoff = offset*rdsize + (int64_t)((char*)p - buf);
2482 p++;
2483 int64_t readclient = *p;
2484 p++;
2485 if (readoff != wantoff || readclient != client->get_nodeid()) {
2486 if (!bad)
2487 dout(0) << "WARNING: wrong data from OSD, block says fileoffset=" << readoff << " client=" << readclient
2488 << ", should be offset " << wantoff << " client " << client->get_nodeid()
2489 << dendl;
2490 bad++;
2491 }
2492 }
2493 if (bad)
2494 dout(0) << " + " << (bad-1) << " other bad 16-byte bits in this block" << dendl;
2495 }
2496 }
2497
2498 client->close(fd);
2499 delete[] buf;
2500
2501 return 0;
2502}
2503
2504int normdist(int min, int max, int stdev) /* specifies input values */
2505{
2506 /* min: Minimum value; max: Maximum value; stdev: degree of deviation */
2507
2508 //int min, max, stdev; {
2509 time_t seconds;
2510 time( &seconds);
2511 srand(seconds);
2512
2513 int range, iterate, result;
2514 /* declare range, iterate and result as integers, to avoid the need for
2515 floating point math*/
2516
2517 result = 0;
2518 /* ensure result is initialized to 0 */
2519
2520 range = max -min;
2521 /* calculate range of possible values between the max and min values */
2522
2523 iterate = range / stdev;
2524 /* this number of iterations ensures the proper shape of the resulting
2525 curve */
2526
2527 stdev += 1; /* compensation for integer vs. floating point math */
2528 for (int c = iterate; c != 0; c--) /* loop through iterations */
2529 {
2530 // result += (uniform (1, 100) * stdev) / 100; /* calculate and
2531 result += ( (rand()%100 + 1) * stdev) / 100;
2532 // printf("result=%d\n", result );
2533 }
2534 printf("\n final result=%d\n", result );
2535 return result + min; /* send final result back */
2536}
2537
2538int SyntheticClient::read_random_ex(string& fn, int size, int rdsize) // size is in MB, wrsize in bytes
2539{
2540 uint64_t chunks = (uint64_t)size * (uint64_t)(1024*1024) / (uint64_t)rdsize;
2541 UserPerm perms = client->pick_my_perms();
2542 int fd = client->open(fn.c_str(), O_RDWR, perms);
2543 dout(5) << "reading from " << fn << " fd " << fd << dendl;
2544
2545 if (fd < 0) return fd;
2546 int offset = 0;
2547 char * buf = NULL;
2548
2549 for (unsigned i=0; i<2000; i++) {
2550 if (time_to_stop()) break;
2551
2552 bool read=false;
2553
2554 time_t seconds;
2555 time( &seconds);
2556 srand(seconds);
2557
2558 // use rand instead ??
2559 double x = drand48();
2560
2561 // cleanup before call 'new'
2562 if (buf != NULL) {
2563 delete[] buf;
2564 buf = NULL;
2565 }
2566 if (x < 0.5) {
2567 buf = new char[rdsize];
2568 memset(buf, 1, rdsize);
2569 read=true;
2570 } else {
2571 buf = new char[rdsize+100]; // 1 MB
2572 memset(buf, 7, rdsize);
2573 }
2574
2575 if (read) {
2576 dout(2) << "reading block " << offset << "/" << chunks << dendl;
2577
2578 int r = client->read(fd, buf, rdsize,
2579 offset*rdsize);
2580 if (r < rdsize) {
2581 dout(1) << "read_file got r = " << r << ", probably end of file" << dendl;
2582 }
2583 } else {
2584 dout(2) << "writing block " << offset << "/" << chunks << dendl;
2585
2586 // fill buf with a 16 byte fingerprint
2587 // 64 bits : file offset
2588 // 64 bits : client id
2589 // = 128 bits (16 bytes)
2590
2591 int count = rand()%10;
2592
2593 for ( int j=0;j<count; j++ ) {
2594 offset=(rand())%(chunks+1);
2595 uint64_t *p = (uint64_t*)buf;
2596 while ((char*)p < buf + rdsize) {
2597 *p = offset*rdsize + (char*)p - buf;
2598 p++;
2599 *p = client->get_nodeid().v;
2600 p++;
2601 }
2602
2603 client->write(fd, buf, rdsize, offset*rdsize);
2604 }
2605 }
2606
2607 // verify fingerprint
2608 if (read) {
2609 int bad = 0;
2610 int64_t *p = (int64_t*)buf;
2611 while ((char*)p + 32 < buf + rdsize) {
2612 int64_t readoff = *p;
2613 int64_t wantoff = offset*rdsize + (int64_t)((char*)p - buf);
2614 p++;
2615 int64_t readclient = *p;
2616 p++;
2617 if (readoff != wantoff || readclient != client->get_nodeid()) {
2618 if (!bad)
2619 dout(0) << "WARNING: wrong data from OSD, block says fileoffset=" << readoff << " client=" << readclient
2620 << ", should be offset " << wantoff << " client " << client->get_nodeid()
2621 << dendl;
2622 bad++;
2623 }
2624 }
2625 if (bad)
2626 dout(0) << " + " << (bad-1) << " other bad 16-byte bits in this block" << dendl;
2627 }
2628 }
2629
2630 client->close(fd);
2631 delete[] buf;
2632
2633 return 0;
2634}
2635
2636
2637int SyntheticClient::random_walk(int num_req)
2638{
2639 int left = num_req;
2640
2641 //dout(1) << "random_walk() will do " << left << " ops" << dendl;
2642
2643 init_op_dist(); // set up metadata op distribution
2644
2645 UserPerm perms = client->pick_my_perms();
2646 while (left > 0) {
2647 left--;
2648
2649 if (time_to_stop()) break;
2650
2651 // ascend?
2652 if (cwd.depth() && !roll_die(::pow((double).9, (double)cwd.depth()))) {
2653 dout(DBL) << "die says up" << dendl;
2654 up();
2655 continue;
2656 }
2657
2658 // descend?
2659 if (roll_die(::pow((double).9,(double)cwd.depth())) && !subdirs.empty()) {
2660 string s = get_random_subdir();
2661 cwd.push_dentry( s );
2662 dout(DBL) << "cd " << s << " -> " << cwd << dendl;
2663 clear_dir();
2664 continue;
2665 }
2666
2667 int op = 0;
2668 filepath path;
2669
2670 if (contents.empty() && roll_die(.3)) {
2671 if (did_readdir) {
2672 dout(DBL) << "empty dir, up" << dendl;
2673 up();
2674 } else
2675 op = CEPH_MDS_OP_READDIR;
2676 } else {
2677 op = op_dist.sample();
2678 }
2679 //dout(DBL) << "op is " << op << dendl;
2680
2681 int r = 0;
2682
2683 // do op
2684 if (op == CEPH_MDS_OP_UNLINK) {
2685 if (contents.empty())
2686 op = CEPH_MDS_OP_READDIR;
2687 else
2688 r = client->unlink(get_random_sub(), perms); // will fail on dirs
2689 }
2690
2691 if (op == CEPH_MDS_OP_RENAME) {
2692 if (contents.empty())
2693 op = CEPH_MDS_OP_READDIR;
2694 else {
2695 r = client->rename(get_random_sub(), make_sub("ren"), perms);
2696 }
2697 }
2698
2699 if (op == CEPH_MDS_OP_MKDIR) {
2700 r = client->mkdir(make_sub("mkdir"), 0755, perms);
2701 }
2702
2703 if (op == CEPH_MDS_OP_RMDIR) {
2704 if (!subdirs.empty())
2705 r = client->rmdir(get_random_subdir(), perms);
2706 else
2707 r = client->rmdir(cwd.c_str(), perms); // will pbly fail
2708 }
2709
2710 if (op == CEPH_MDS_OP_SYMLINK) {
2711 }
2712 /*
2713 if (op == CEPH_MDS_OP_CHMOD) {
2714 if (contents.empty())
2715 op = CEPH_MDS_OP_READDIR;
2716 else
2717 r = client->chmod(get_random_sub(), rand() & 0755, perms);
2718 }
2719
2720 if (op == CEPH_MDS_OP_CHOWN) {
2721 if (contents.empty()) r = client->chown(cwd.c_str(), rand(), rand(), perms);
2722 else
2723 r = client->chown(get_random_sub(), rand(), rand(), perms);
2724 }
2725
2726 if (op == CEPH_MDS_OP_UTIME) {
2727 struct utimbuf b;
2728 memset(&b, 1, sizeof(b));
2729 if (contents.empty())
2730 r = client->utime(cwd.c_str(), &b, perms);
2731 else
2732 r = client->utime(get_random_sub(), &b, perms);
2733 }
2734 */
2735 if (op == CEPH_MDS_OP_LINK) {
2736 }
2737
2738 if (op == CEPH_MDS_OP_MKNOD) {
2739 r = client->mknod(make_sub("mknod"), 0644, perms);
2740 }
2741
2742 if (op == CEPH_MDS_OP_OPEN) {
2743 if (contents.empty())
2744 op = CEPH_MDS_OP_READDIR;
2745 else {
2746 r = client->open(get_random_sub(), O_RDONLY, perms);
2747 if (r > 0) {
2748 assert(open_files.count(r) == 0);
2749 open_files.insert(r);
2750 }
2751 }
2752 }
2753
2754 /*if (op == CEPH_MDS_OP_RELEASE) { // actually, close
2755 if (open_files.empty())
2756 op = CEPH_MDS_OP_STAT;
2757 else {
2758 int fh = get_random_fh();
2759 r = client->close( fh );
2760 if (r == 0) open_files.erase(fh);
2761 }
2762 }
2763 */
2764
2765 if (op == CEPH_MDS_OP_GETATTR) {
2766 struct stat st;
2767 if (contents.empty()) {
2768 if (did_readdir) {
2769 if (roll_die(.1)) {
2770 dout(DBL) << "stat in empty dir, up" << dendl;
2771 up();
2772 } else {
2773 op = CEPH_MDS_OP_MKNOD;
2774 }
2775 } else
2776 op = CEPH_MDS_OP_READDIR;
2777 } else
2778 r = client->lstat(get_random_sub(), &st, perms);
2779 }
2780
2781 if (op == CEPH_MDS_OP_READDIR) {
2782 clear_dir();
2783
2784 list<string> c;
2785 r = client->getdir(cwd.c_str(), c, perms);
2786
2787 for (list<string>::iterator it = c.begin();
2788 it != c.end();
2789 ++it) {
2790 //dout(DBL) << " got " << *it << dendl;
2791 ceph_abort();
2792 /*contents[*it] = it->second;
2793 if (it->second &&
2794 S_ISDIR(it->second->st_mode))
2795 subdirs.insert(*it);
2796 */
2797 }
2798
2799 did_readdir = true;
2800 }
2801
2802 // errors?
2803 if (r < 0) {
2804 // reevaluate cwd.
2805 //while (cwd.depth()) {
2806 //if (client->lookup(cwd)) break; // it's in the cache
2807
2808 //dout(DBL) << "r = " << r << ", client doesn't have " << cwd << ", cd .." << dendl;
2809 dout(DBL) << "r = " << r << ", client may not have " << cwd << ", cd .." << dendl;
2810 up();
2811 //}
2812 }
2813 }
2814
2815 // close files
2816 dout(DBL) << "closing files" << dendl;
2817 while (!open_files.empty()) {
2818 int fh = get_random_fh();
2819 int r = client->close( fh );
2820 if (r == 0) open_files.erase(fh);
2821 }
2822
2823 dout(DBL) << "done" << dendl;
2824 return 0;
2825}
2826
2827
2828
2829
2830void SyntheticClient::make_dir_mess(const char *basedir, int n)
2831{
2832 UserPerm perms = client->pick_my_perms();
2833 vector<string> dirs;
2834
2835 dirs.push_back(basedir);
2836 dirs.push_back(basedir);
2837
2838 client->mkdir(basedir, 0755, perms);
2839
2840 // motivation:
2841 // P(dir) ~ subdirs_of(dir) + 2
2842 // from 5-year metadata workload paper in fast'07
2843
2844 // create dirs
2845 for (int i=0; i<n; i++) {
2846 // pick a dir
2847 int k = rand() % dirs.size();
2848 string parent = dirs[k];
2849
2850 // pick a name
2851 std::stringstream ss;
2852 ss << parent << "/" << i;
2853 string dir = ss.str();
2854
2855 // update dirs
2856 dirs.push_back(parent);
2857 dirs.push_back(dir);
2858 dirs.push_back(dir);
2859
2860 // do it
2861 client->mkdir(dir.c_str(), 0755, perms);
2862 }
2863
2864
2865}
2866
2867
2868
2869void SyntheticClient::foo()
2870{
2871 UserPerm perms = client->pick_my_perms();
2872
2873 if (1) {
2874 // make 2 parallel dirs, link/unlink between them.
2875 char a[100], b[100];
2876 client->mkdir("/a", 0755, perms);
2877 client->mkdir("/b", 0755, perms);
2878 for (int i=0; i<10; i++) {
2879 snprintf(a, sizeof(a), "/a/%d", i);
2880 client->mknod(a, 0644, perms);
2881 }
2882 while (1) {
2883 for (int i=0; i<10; i++) {
2884 snprintf(a, sizeof(a), "/a/%d", i);
2885 snprintf(b, sizeof(b), "/b/%d", i);
2886 client->link(a, b, perms);
2887 }
2888 for (int i=0; i<10; i++) {
2889 snprintf(b, sizeof(b), "/b/%d", i);
2890 client->unlink(b, perms);
2891 }
2892 }
2893 return;
2894 }
2895 if (1) {
2896 // bug1.cpp
2897 const char *fn = "blah";
2898 char buffer[8192];
2899 client->unlink(fn, perms);
2900 int handle = client->open(fn, O_CREAT|O_RDWR, perms, S_IRWXU);
2901 assert(handle>=0);
2902 int r=client->write(handle,buffer,8192);
2903 assert(r>=0);
2904 r=client->close(handle);
2905 assert(r>=0);
2906
2907 handle = client->open(fn, O_RDWR, perms); // open the same file, it must have some data already
2908 assert(handle>=0);
2909 r=client->read(handle,buffer,8192);
2910 assert(r==8192); // THIS ASSERTION FAILS with disabled cache
2911 r=client->close(handle);
2912 assert(r>=0);
2913
2914 return;
2915 }
2916 if (1) {
2917 dout(0) << "first" << dendl;
2918 int fd = client->open("tester", O_WRONLY|O_CREAT, perms);
2919 client->write(fd, "hi there", 0, 8);
2920 client->close(fd);
2921 dout(0) << "sleep" << dendl;
2922 sleep(10);
2923 dout(0) << "again" << dendl;
2924 fd = client->open("tester", O_WRONLY|O_CREAT, perms);
2925 client->write(fd, "hi there", 0, 8);
2926 client->close(fd);
2927 return;
2928 }
2929 if (1) {
2930 // open some files
2931 srand(0);
2932 for (int i=0; i<20; i++) {
2933 int s = 5;
2934 int a = rand() % s;
2935 int b = rand() % s;
2936 int c = rand() % s;
2937 char src[80];
2938 snprintf(src, sizeof(src), "syn.0.0/dir.%d/dir.%d/file.%d", a, b, c);
2939 //int fd =
2940 client->open(src, O_RDONLY, perms);
2941 }
2942
2943 return;
2944 }
2945
2946 if (0) {
2947 // rename fun
2948 for (int i=0; i<100; i++) {
2949 int s = 5;
2950 int a = rand() % s;
2951 int b = rand() % s;
2952 int c = rand() % s;
2953 int d = rand() % s;
2954 int e = rand() % s;
2955 int f = rand() % s;
2956 char src[80];
2957 char dst[80];
2958 snprintf(src, sizeof(src), "syn.0.0/dir.%d/dir.%d/file.%d", a, b, c);
2959 snprintf(dst, sizeof(dst), "syn.0.0/dir.%d/dir.%d/file.%d", d, e, f);
2960 client->rename(src, dst, perms);
2961 }
2962 return;
2963 }
2964
2965 if (1) {
2966 // link fun
2967 srand(0);
2968 for (int i=0; i<100; i++) {
2969 int s = 5;
2970 int a = rand() % s;
2971 int b = rand() % s;
2972 int c = rand() % s;
2973 int d = rand() % s;
2974 int e = rand() % s;
2975 int f = rand() % s;
2976 char src[80];
2977 char dst[80];
2978 snprintf(src, sizeof(src), "syn.0.0/dir.%d/dir.%d/file.%d", a, b, c);
2979 snprintf(dst, sizeof(dst), "syn.0.0/dir.%d/dir.%d/newlink.%d", d, e, f);
2980 client->link(src, dst, perms);
2981 }
2982 srand(0);
2983 for (int i=0; i<100; i++) {
2984 int s = 5;
2985 int a = rand() % s;
2986 int b = rand() % s;
2987 int c = rand() % s;
2988 int d = rand() % s;
2989 int e = rand() % s;
2990 int f = rand() % s;
2991 char src[80];
2992 char dst[80];
2993 snprintf(src, sizeof(src), "syn.0.0/dir.%d/dir.%d/file.%d", a, b, c);
2994 snprintf(dst, sizeof(dst), "syn.0.0/dir.%d/dir.%d/newlink.%d", d, e, f);
2995 client->unlink(dst, perms);
2996 }
2997
2998
2999 return;
3000 }
3001
3002 // link fun
3003 client->mknod("one", 0755, perms);
3004 client->mknod("two", 0755, perms);
3005 client->link("one", "three", perms);
3006 client->mkdir("dir", 0755, perms);
3007 client->link("two", "/dir/twolink", perms);
3008 client->link("dir/twolink", "four", perms);
3009
3010 // unlink fun
3011 client->mknod("a", 0644, perms);
3012 client->unlink("a", perms);
3013 client->mknod("b", 0644, perms);
3014 client->link("b", "c", perms);
3015 client->unlink("c", perms);
3016 client->mkdir("d", 0755, perms);
3017 client->unlink("d", perms);
3018 client->rmdir("d", perms);
3019
3020 // rename fun
3021 client->mknod("p1", 0644, perms);
3022 client->mknod("p2", 0644, perms);
3023 client->rename("p1","p2", perms);
3024 client->mknod("p3", 0644, perms);
3025 client->rename("p3","p4", perms);
3026
3027 // check dest dir ambiguity thing
3028 client->mkdir("dir1", 0755, perms);
3029 client->mkdir("dir2", 0755, perms);
3030 client->rename("p2", "dir1/p2", perms);
3031 client->rename("dir1/p2", "dir2/p2", perms);
3032 client->rename("dir2/p2", "/p2", perms);
3033
3034 // check primary+remote link merging
3035 client->link("p2","p2.l", perms);
3036 client->link("p4","p4.l", perms);
3037 client->rename("p2.l", "p2", perms);
3038 client->rename("p4", "p4.l", perms);
3039
3040 // check anchor updates
3041 client->mknod("dir1/a", 0644, perms);
3042 client->link("dir1/a", "da1", perms);
3043 client->link("dir1/a", "da2", perms);
3044 client->link("da2","da3", perms);
3045 client->rename("dir1/a", "dir2/a", perms);
3046 client->rename("dir2/a", "da2", perms);
3047 client->rename("da1", "da2", perms);
3048 client->rename("da2", "da3", perms);
3049
3050 // check directory renames
3051 client->mkdir("dir3", 0755, perms);
3052 client->mknod("dir3/asdf", 0644, perms);
3053 client->mkdir("dir4", 0755, perms);
3054 client->mkdir("dir5", 0755, perms);
3055 client->mknod("dir5/asdf", 0644, perms);
3056 client->rename("dir3", "dir4", perms); // ok
3057 client->rename("dir4", "dir5", perms); // fail
3058}
3059
3060int SyntheticClient::thrash_links(const char *basedir, int dirs, int files, int depth, int n)
3061{
3062 dout(1) << "thrash_links " << basedir << " " << dirs << " " << files << " " << depth
3063 << " links " << n
3064 << dendl;
3065
3066 if (time_to_stop()) return 0;
3067
3068 UserPerm perms = client->pick_my_perms();
3069
3070 srand(0);
3071 if (1) {
3072 bool renames = true; // thrash renames too?
3073 for (int k=0; k<n; k++) {
3074
3075 if (renames && rand() % 10 == 0) {
3076 // rename some directories. whee!
3077 int dep = (rand() % depth) + 1;
3078 string src = basedir;
3079 {
3080 char t[80];
3081 for (int d=0; d<dep; d++) {
3082 int a = rand() % dirs;
3083 snprintf(t, sizeof(t), "/dir.%d", a);
3084 src += t;
3085 }
3086 }
3087 string dst = basedir;
3088 {
3089 char t[80];
3090 for (int d=0; d<dep; d++) {
3091 int a = rand() % dirs;
3092 snprintf(t, sizeof(t), "/dir.%d", a);
3093 dst += t;
3094 }
3095 }
3096
3097 if (client->rename(dst.c_str(), "/tmp", perms) == 0) {
3098 client->rename(src.c_str(), dst.c_str(), perms);
3099 client->rename("/tmp", src.c_str(), perms);
3100 }
3101 continue;
3102 }
3103
3104 // pick a dest dir
3105 string src = basedir;
3106 {
3107 char t[80];
3108 for (int d=0; d<depth; d++) {
3109 int a = rand() % dirs;
3110 snprintf(t, sizeof(t), "/dir.%d", a);
3111 src += t;
3112 }
3113 int a = rand() % files;
3114 snprintf(t, sizeof(t), "/file.%d", a);
3115 src += t;
3116 }
3117 string dst = basedir;
3118 {
3119 char t[80];
3120 for (int d=0; d<depth; d++) {
3121 int a = rand() % dirs;
3122 snprintf(t, sizeof(t), "/dir.%d", a);
3123 dst += t;
3124 }
3125 int a = rand() % files;
3126 snprintf(t, sizeof(t), "/file.%d", a);
3127 dst += t;
3128 }
3129
3130 int o = rand() % 4;
3131 switch (o) {
3132 case 0:
3133 client->mknod(src.c_str(), 0755, perms);
3134 if (renames) client->rename(src.c_str(), dst.c_str(), perms);
3135 break;
3136 case 1:
3137 client->mknod(src.c_str(), 0755, perms);
3138 client->unlink(dst.c_str(), perms);
3139 client->link(src.c_str(), dst.c_str(), perms);
3140 break;
3141 case 2: client->unlink(src.c_str(), perms); break;
3142 case 3: client->unlink(dst.c_str(), perms); break;
3143 //case 4: client->mknod(src.c_str(), 0755, perms); break;
3144 //case 5: client->mknod(dst.c_str(), 0755, perms); break;
3145 }
3146 }
3147 return 0;
3148 }
3149
3150 if (1) {
3151 // now link shit up
3152 for (int i=0; i<n; i++) {
3153 if (time_to_stop()) return 0;
3154
3155 char f[20];
3156
3157 // pick a file
3158 string file = basedir;
3159
3160 if (depth) {
3161 int d = rand() % (depth+1);
3162 for (int k=0; k<d; k++) {
3163 snprintf(f, sizeof(f), "/dir.%d", rand() % dirs);
3164 file += f;
3165 }
3166 }
3167 snprintf(f, sizeof(f), "/file.%d", rand() % files);
3168 file += f;
3169
3170 // pick a dir for our link
3171 string ln = basedir;
3172 if (depth) {
3173 int d = rand() % (depth+1);
3174 for (int k=0; k<d; k++) {
3175 snprintf(f, sizeof(f), "/dir.%d", rand() % dirs);
3176 ln += f;
3177 }
3178 }
3179 snprintf(f, sizeof(f), "/ln.%d", i);
3180 ln += f;
3181
3182 client->link(file.c_str(), ln.c_str(), perms);
3183 }
3184 }
3185 return 0;
3186}
3187
3188
3189
3190
3191void SyntheticClient::import_find(const char *base, const char *find, bool data)
3192{
3193 dout(1) << "import_find " << base << " from " << find << " data=" << data << dendl;
3194
3195 /* use this to gather the static trace:
3196 *
3197 * find . -exec ls -dilsn --time-style=+%s \{\} \;
3198 * or if it's wafl,
3199 * find . -path ./.snapshot -prune -o -exec ls -dilsn --time-style=+%s \{\} \;
3200 *
3201 */
3202
3203 UserPerm process_perms = client->pick_my_perms();
3204
3205 if (base[0] != '-')
3206 client->mkdir(base, 0755, process_perms);
3207
3208 ifstream f(find);
3209 assert(f.is_open());
3210
3211 int dirnum = 0;
3212
3213 while (!f.eof()) {
3214 uint64_t ino;
3215 int dunno, nlink;
3216 string modestring;
3217 int uid, gid;
3218 off_t size;
3219 time_t mtime;
3220 string filename;
3221 f >> ino;
3222 if (f.eof()) break;
3223 f >> dunno;
3224 f >> modestring;
3225 f >> nlink;
3226 f >> uid;
3227 f >> gid;
3228 f >> size;
3229 f >> mtime;
3230 f.seekg(1, ios::cur);
3231 getline(f, filename);
3232 UserPerm perms(uid, gid);
3233
3234 // ignore "."
3235 if (filename == ".") continue;
3236
3237 // remove leading ./
3238 assert(filename[0] == '.' && filename[1] == '/');
3239 filename = filename.substr(2);
3240
3241 // new leading dir?
3242 int sp = filename.find("/");
3243 if (sp < 0) dirnum++;
3244
3245 //dout(0) << "leading dir " << filename << " " << dirnum << dendl;
3246 if (dirnum % client->cct->_conf->num_client != client->get_nodeid()) {
3247 dout(20) << "skipping leading dir " << dirnum << " " << filename << dendl;
3248 continue;
3249 }
3250
3251 // parse the mode
3252 assert(modestring.length() == 10);
3253 mode_t mode = 0;
3254 switch (modestring[0]) {
3255 case 'd': mode |= S_IFDIR; break;
3256 case 'l': mode |= S_IFLNK; break;
3257 default:
3258 case '-': mode |= S_IFREG; break;
3259 }
3260 if (modestring[1] == 'r') mode |= 0400;
3261 if (modestring[2] == 'w') mode |= 0200;
3262 if (modestring[3] == 'x') mode |= 0100;
3263 if (modestring[4] == 'r') mode |= 040;
3264 if (modestring[5] == 'w') mode |= 020;
3265 if (modestring[6] == 'x') mode |= 010;
3266 if (modestring[7] == 'r') mode |= 04;
3267 if (modestring[8] == 'w') mode |= 02;
3268 if (modestring[9] == 'x') mode |= 01;
3269
3270 dout(20) << " mode " << modestring << " to " << oct << mode << dec << dendl;
3271
3272 if (S_ISLNK(mode)) {
3273 // target vs destination
3274 int pos = filename.find(" -> ");
3275 assert(pos > 0);
3276 string link;
3277 if (base[0] != '-') {
3278 link = base;
3279 link += "/";
3280 }
3281 link += filename.substr(0, pos);
3282 string target;
3283 if (filename[pos+4] == '/') {
3284 if (base[0] != '-')
3285 target = base;
3286 target += filename.substr(pos + 4);
3287 } else {
3288 target = filename.substr(pos + 4);
3289 }
3290 dout(10) << "symlink from '" << link << "' -> '" << target << "'" << dendl;
3291 client->symlink(target.c_str(), link.c_str(), perms);
3292 } else {
3293 string f;
3294 if (base[0] != '-') {
3295 f = base;
3296 f += "/";
3297 }
3298 f += filename;
3299 if (S_ISDIR(mode)) {
3300 client->mkdir(f.c_str(), mode, perms);
3301 } else {
3302 int fd = client->open(f.c_str(), O_WRONLY|O_CREAT, perms, mode & 0777);
3303 assert(fd > 0);
3304 if (data) {
3305 client->write(fd, "", 0, size);
3306 } else {
3307 client->truncate(f.c_str(), size, perms);
3308 }
3309 client->close(fd);
3310
3311 //client->chmod(f.c_str(), mode & 0777, perms, process_perms);
3312 client->chown(f.c_str(), uid, gid, process_perms);
3313
3314 struct utimbuf ut;
3315 ut.modtime = mtime;
3316 ut.actime = mtime;
3317 client->utime(f.c_str(), &ut, perms);
3318 }
3319 }
3320 }
3321
3322
3323}
3324
3325
3326int SyntheticClient::lookup_hash(inodeno_t ino, inodeno_t dirino,
3327 const char *name, const UserPerm& perms)
3328{
3329 int r = client->lookup_hash(ino, dirino, name, perms);
3330 dout(0) << "lookup_hash(" << ino << ", #" << dirino << "/" << name << ") = " << r << dendl;
3331 return r;
3332}
3333
3334int SyntheticClient::lookup_ino(inodeno_t ino, const UserPerm& perms)
3335{
3336 int r = client->lookup_ino(ino, perms);
3337 dout(0) << "lookup_ino(" << ino << ") = " << r << dendl;
3338 return r;
3339}
3340
3341int SyntheticClient::chunk_file(string &filename)
3342{
3343 UserPerm perms = client->pick_my_perms();
3344 int fd = client->open(filename.c_str(), O_RDONLY, perms);
3345 if (fd < 0)
3346 return fd;
3347
3348 struct stat st;
3349 int ret = client->fstat(fd, &st, perms);
3350 if (ret < 0) {
3351 client->close(fd);
3352 return ret;
3353 }
3354 uint64_t size = st.st_size;
3355 dout(0) << "file " << filename << " size is " << size << dendl;
3356
7c673cae
FG
3357 inode_t inode;
3358 memset(&inode, 0, sizeof(inode));
3359 inode.ino = st.st_ino;
3360 ret = client->fdescribe_layout(fd, &inode.layout);
3361 assert(ret == 0); // otherwise fstat did a bad thing
3362
3363 uint64_t pos = 0;
3364 bufferlist from_before;
3365 while (pos < size) {
3366 int get = MIN(size-pos, 1048576);
3367
3368 Mutex flock("synclient chunk_file lock");
3369 Cond cond;
3370 bool done;
3371 bufferlist bl;
3372
3373 flock.Lock();
3374 Context *onfinish = new C_SafeCond(&flock, &cond, &done);
3375 client->filer->read(inode.ino, &inode.layout, CEPH_NOSNAP, pos, get, &bl, 0,
3376 onfinish);
3377 while (!done)
3378 cond.Wait(flock);
3379 flock.Unlock();
3380
3381 dout(0) << "got " << bl.length() << " bytes at " << pos << dendl;
3382
3383 if (from_before.length()) {
3384 dout(0) << " including bit from previous block" << dendl;
3385 pos -= from_before.length();
3386 from_before.claim_append(bl);
3387 bl.swap(from_before);
3388 }
3389
3390 // ....
3391
3392 // keep last 32 bytes around
3393 from_before.clear();
3394 from_before.substr_of(bl, bl.length()-32, 32);
3395
3396 pos += bl.length();
3397 }
3398
3399 client->close(fd);
3400 return 0;
3401}
3402
3403
3404
3405void SyntheticClient::mksnap(const char *base, const char *name, const UserPerm& perms)
3406{
3407 client->mksnap(base, name, perms);
3408}
3409
3410void SyntheticClient::rmsnap(const char *base, const char *name, const UserPerm& perms)
3411{
3412 client->rmsnap(base, name, perms);
3413}
3414
3415void SyntheticClient::mksnapfile(const char *dir)
3416{
3417 UserPerm perms = client->pick_my_perms();
3418 client->mkdir(dir, 0755, perms);
3419
3420 string f = dir;
3421 f += "/foo";
3422 int fd = client->open(f.c_str(), O_WRONLY|O_CREAT|O_TRUNC, perms);
3423
3424 char buf[1048576*4];
3425 client->write(fd, buf, sizeof(buf), 0);
3426 client->fsync(fd, true);
3427 client->close(fd);
3428
3429 string s = dir;
3430 s += "/.snap/1";
3431 client->mkdir(s.c_str(), 0755, perms);
3432
3433 fd = client->open(f.c_str(), O_WRONLY, perms);
3434 client->write(fd, buf, 1048576*2, 1048576);
3435 client->fsync(fd, true);
3436 client->close(fd);
3437}