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