]> git.proxmox.com Git - ceph.git/blob - ceph/src/client/SyntheticClient.cc
import 15.2.4
[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_ll_client.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 ceph::mutex lock = ceph::make_mutex("synclient foo");
1049 ceph::condition_variable 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 std::unique_lock locker{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 cond.wait(locker, [&ack] { return ack; });
1460 }
1461 else if (strcmp(op, "o_read") == 0) {
1462 int64_t oh = t.get_int();
1463 int64_t ol = t.get_int();
1464 int64_t off = t.get_int();
1465 int64_t len = t.get_int();
1466 object_t oid = file_object_t(oh, ol);
1467 object_locator_t oloc(SYNCLIENT_FIRST_POOL);
1468 std::unique_lock locker{lock};
1469 bufferlist bl;
1470 client->objecter->read(oid, oloc, off, len, CEPH_NOSNAP, &bl, 0,
1471 new C_SafeCond(lock, cond, &ack));
1472 cond.wait(locker, [&ack] { return ack; });
1473 }
1474 else if (strcmp(op, "o_write") == 0) {
1475 int64_t oh = t.get_int();
1476 int64_t ol = t.get_int();
1477 int64_t off = t.get_int();
1478 int64_t len = t.get_int();
1479 object_t oid = file_object_t(oh, ol);
1480 object_locator_t oloc(SYNCLIENT_FIRST_POOL);
1481 std::unique_lock locker{lock};
1482 bufferptr bp(len);
1483 bufferlist bl;
1484 bl.push_back(bp);
1485 SnapContext snapc;
1486 client->objecter->write(oid, oloc, off, len, snapc, bl,
1487 ceph::real_clock::now(), 0,
1488 new C_SafeCond(lock, cond, &ack));
1489 cond.wait(locker, [&ack] { return ack; });
1490 }
1491 else if (strcmp(op, "o_zero") == 0) {
1492 int64_t oh = t.get_int();
1493 int64_t ol = t.get_int();
1494 int64_t off = t.get_int();
1495 int64_t len = t.get_int();
1496 object_t oid = file_object_t(oh, ol);
1497 object_locator_t oloc(SYNCLIENT_FIRST_POOL);
1498 std::unique_lock locker{lock};
1499 SnapContext snapc;
1500 client->objecter->zero(oid, oloc, off, len, snapc,
1501 ceph::real_clock::now(), 0,
1502 new C_SafeCond(lock, cond, &ack));
1503 cond.wait(locker, [&ack] { return ack; });
1504 }
1505
1506
1507 else {
1508 dout(0) << (t.get_line()-1) << ": *** trace hit unrecognized symbol '" << op << "' " << dendl;
1509 ceph_abort();
1510 }
1511 }
1512
1513 dout(10) << "trace finished on line " << t.get_line() << dendl;
1514
1515 // close open files
1516 for (ceph::unordered_map<int64_t, int64_t>::iterator fi = open_files.begin();
1517 fi != open_files.end();
1518 ++fi) {
1519 dout(1) << "leftover close " << fi->second << dendl;
1520 if (fi->second > 0) client->close(fi->second);
1521 }
1522 for (ceph::unordered_map<int64_t, dir_result_t*>::iterator fi = open_dirs.begin();
1523 fi != open_dirs.end();
1524 ++fi) {
1525 dout(1) << "leftover closedir " << fi->second << dendl;
1526 if (fi->second != 0) client->closedir(fi->second);
1527 }
1528 for (ceph::unordered_map<int64_t,Fh*>::iterator fi = ll_files.begin();
1529 fi != ll_files.end();
1530 ++fi) {
1531 dout(1) << "leftover ll_release " << fi->second << dendl;
1532 if (fi->second) client->ll_release(fi->second);
1533 }
1534 for (ceph::unordered_map<int64_t,dir_result_t*>::iterator fi = ll_dirs.begin();
1535 fi != ll_dirs.end();
1536 ++fi) {
1537 dout(1) << "leftover ll_releasedir " << fi->second << dendl;
1538 if (fi->second) client->ll_releasedir(fi->second);
1539 }
1540
1541 return 0;
1542 }
1543
1544
1545
1546 int SyntheticClient::clean_dir(string& basedir)
1547 {
1548 // read dir
1549 list<string> contents;
1550 UserPerm perms = client->pick_my_perms();
1551 int r = client->getdir(basedir.c_str(), contents, perms);
1552 if (r < 0) {
1553 dout(1) << "getdir on " << basedir << " returns " << r << dendl;
1554 return r;
1555 }
1556
1557 for (list<string>::iterator it = contents.begin();
1558 it != contents.end();
1559 ++it) {
1560 if (*it == ".") continue;
1561 if (*it == "..") continue;
1562 string file = basedir + "/" + *it;
1563
1564 if (time_to_stop()) break;
1565
1566 struct stat st;
1567 int r = client->lstat(file.c_str(), &st, perms);
1568 if (r < 0) {
1569 dout(1) << "stat error on " << file << " r=" << r << dendl;
1570 continue;
1571 }
1572
1573 if ((st.st_mode & S_IFMT) == S_IFDIR) {
1574 clean_dir(file);
1575 client->rmdir(file.c_str(), perms);
1576 } else {
1577 client->unlink(file.c_str(), perms);
1578 }
1579 }
1580
1581 return 0;
1582
1583 }
1584
1585
1586 int SyntheticClient::full_walk(string& basedir)
1587 {
1588 if (time_to_stop()) return -1;
1589
1590 list<string> dirq;
1591 list<frag_info_t> statq;
1592 dirq.push_back(basedir);
1593 frag_info_t empty;
1594 statq.push_back(empty);
1595
1596 ceph::unordered_map<inodeno_t, int> nlink;
1597 ceph::unordered_map<inodeno_t, int> nlink_seen;
1598
1599 UserPerm perms = client->pick_my_perms();
1600 while (!dirq.empty()) {
1601 string dir = dirq.front();
1602 frag_info_t expect = statq.front();
1603 dirq.pop_front();
1604 statq.pop_front();
1605
1606 frag_info_t actual = empty;
1607
1608 // read dir
1609 list<string> contents;
1610 int r = client->getdir(dir.c_str(), contents, perms);
1611 if (r < 0) {
1612 dout(1) << "getdir on " << dir << " returns " << r << dendl;
1613 continue;
1614 }
1615
1616 for (list<string>::iterator it = contents.begin();
1617 it != contents.end();
1618 ++it) {
1619 if (*it == "." ||
1620 *it == "..")
1621 continue;
1622 string file = dir + "/" + *it;
1623
1624 struct stat st;
1625 frag_info_t dirstat;
1626 int r = client->lstat(file.c_str(), &st, perms, &dirstat);
1627 if (r < 0) {
1628 dout(1) << "stat error on " << file << " r=" << r << dendl;
1629 continue;
1630 }
1631
1632 nlink_seen[st.st_ino]++;
1633 nlink[st.st_ino] = st.st_nlink;
1634
1635 if (S_ISDIR(st.st_mode))
1636 actual.nsubdirs++;
1637 else
1638 actual.nfiles++;
1639
1640 // print
1641 char *tm = ctime(&st.st_mtime);
1642 tm[strlen(tm)-1] = 0;
1643 printf("%llx %c%c%c%c%c%c%c%c%c%c %2d %5d %5d %8llu %12s %s\n",
1644 (long long)st.st_ino,
1645 S_ISDIR(st.st_mode) ? 'd':'-',
1646 (st.st_mode & 0400) ? 'r':'-',
1647 (st.st_mode & 0200) ? 'w':'-',
1648 (st.st_mode & 0100) ? 'x':'-',
1649 (st.st_mode & 040) ? 'r':'-',
1650 (st.st_mode & 020) ? 'w':'-',
1651 (st.st_mode & 010) ? 'x':'-',
1652 (st.st_mode & 04) ? 'r':'-',
1653 (st.st_mode & 02) ? 'w':'-',
1654 (st.st_mode & 01) ? 'x':'-',
1655 (int)st.st_nlink,
1656 (int)st.st_uid, (int)st.st_gid,
1657 (long long unsigned)st.st_size,
1658 tm,
1659 file.c_str());
1660
1661
1662 if ((st.st_mode & S_IFMT) == S_IFDIR) {
1663 dirq.push_back(file);
1664 statq.push_back(dirstat);
1665 }
1666 }
1667
1668 if (dir != "" &&
1669 (actual.nsubdirs != expect.nsubdirs ||
1670 actual.nfiles != expect.nfiles)) {
1671 dout(0) << dir << ": expected " << expect << dendl;
1672 dout(0) << dir << ": got " << actual << dendl;
1673 }
1674 }
1675
1676 for (ceph::unordered_map<inodeno_t,int>::iterator p = nlink.begin(); p != nlink.end(); ++p) {
1677 if (nlink_seen[p->first] != p->second)
1678 dout(0) << p->first << " nlink " << p->second << " != " << nlink_seen[p->first] << "seen" << dendl;
1679 }
1680
1681 return 0;
1682 }
1683
1684
1685
1686 int SyntheticClient::dump_placement(string& fn) {
1687
1688 UserPerm perms = client->pick_my_perms();
1689
1690 // open file
1691 int fd = client->open(fn.c_str(), O_RDONLY, perms);
1692 dout(5) << "reading from " << fn << " fd " << fd << dendl;
1693 if (fd < 0) return fd;
1694
1695
1696 // How big is it?
1697 struct stat stbuf;
1698 int lstat_result = client->lstat(fn.c_str(), &stbuf, perms);
1699 if (lstat_result < 0) {
1700 dout(0) << "lstat error for file " << fn << dendl;
1701 client->close(fd);
1702 return lstat_result;
1703 }
1704
1705 off_t filesize = stbuf.st_size;
1706
1707 // grab the placement info
1708 vector<ObjectExtent> extents;
1709 off_t offset = 0;
1710 client->enumerate_layout(fd, extents, filesize, offset);
1711 client->close(fd);
1712
1713
1714 // run through all the object extents
1715 dout(0) << "file size is " << filesize << dendl;
1716 dout(0) << "(osd, start, length) tuples for file " << fn << dendl;
1717 for (const auto& x : extents) {
1718 int osd = client->objecter->with_osdmap([&](const OSDMap& o) {
1719 return o.get_pg_acting_primary(o.object_locator_to_pg(x.oid, x.oloc));
1720 });
1721
1722 // run through all the buffer extents
1723 for (const auto& be : x.buffer_extents)
1724 dout(0) << "OSD " << osd << ", offset " << be.first
1725 << ", length " << be.second << dendl;
1726 }
1727 return 0;
1728 }
1729
1730
1731
1732 int SyntheticClient::make_dirs(const char *basedir, int dirs, int files, int depth)
1733 {
1734 if (time_to_stop()) return 0;
1735
1736 UserPerm perms = client->pick_my_perms();
1737 // make sure base dir exists
1738 int r = client->mkdir(basedir, 0755, perms);
1739 if (r != 0) {
1740 dout(1) << "can't make base dir? " << basedir << dendl;
1741 //return -1;
1742 }
1743
1744 // children
1745 char d[500];
1746 dout(3) << "make_dirs " << basedir << " dirs " << dirs << " files " << files << " depth " << depth << dendl;
1747 for (int i=0; i<files; i++) {
1748 snprintf(d, sizeof(d), "%s/file.%d", basedir, i);
1749 client->mknod(d, 0644, perms);
1750 }
1751
1752 if (depth == 0) return 0;
1753
1754 for (int i=0; i<dirs; i++) {
1755 snprintf(d, sizeof(d), "%s/dir.%d", basedir, i);
1756 make_dirs(d, dirs, files, depth-1);
1757 }
1758
1759 return 0;
1760 }
1761
1762 int SyntheticClient::stat_dirs(const char *basedir, int dirs, int files, int depth)
1763 {
1764 if (time_to_stop()) return 0;
1765
1766 UserPerm perms = client->pick_my_perms();
1767
1768 // make sure base dir exists
1769 struct stat st;
1770 int r = client->lstat(basedir, &st, perms);
1771 if (r != 0) {
1772 dout(1) << "can't make base dir? " << basedir << dendl;
1773 return -1;
1774 }
1775
1776 // children
1777 char d[500];
1778 dout(3) << "stat_dirs " << basedir << " dirs " << dirs << " files " << files << " depth " << depth << dendl;
1779 for (int i=0; i<files; i++) {
1780 snprintf(d, sizeof(d), "%s/file.%d", basedir, i);
1781 client->lstat(d, &st, perms);
1782 }
1783
1784 if (depth == 0) return 0;
1785
1786 for (int i=0; i<dirs; i++) {
1787 snprintf(d, sizeof(d), "%s/dir.%d", basedir, i);
1788 stat_dirs(d, dirs, files, depth-1);
1789 }
1790
1791 return 0;
1792 }
1793 int SyntheticClient::read_dirs(const char *basedir, int dirs, int files, int depth)
1794 {
1795 if (time_to_stop()) return 0;
1796
1797 struct stat st;
1798
1799 // children
1800 char d[500];
1801 dout(3) << "read_dirs " << basedir << " dirs " << dirs << " files " << files << " depth " << depth << dendl;
1802
1803 list<string> contents;
1804 UserPerm perms = client->pick_my_perms();
1805 utime_t s = ceph_clock_now();
1806 int r = client->getdir(basedir, contents, perms);
1807 utime_t e = ceph_clock_now();
1808 e -= s;
1809 if (r < 0) {
1810 dout(0) << "getdir couldn't readdir " << basedir << ", stopping" << dendl;
1811 return -1;
1812 }
1813
1814 for (int i=0; i<files; i++) {
1815 snprintf(d, sizeof(d), "%s/file.%d", basedir, i);
1816 utime_t s = ceph_clock_now();
1817 if (client->lstat(d, &st, perms) < 0) {
1818 dout(2) << "read_dirs failed stat on " << d << ", stopping" << dendl;
1819 return -1;
1820 }
1821 utime_t e = ceph_clock_now();
1822 e -= s;
1823 }
1824
1825 if (depth > 0)
1826 for (int i=0; i<dirs; i++) {
1827 snprintf(d, sizeof(d), "%s/dir.%d", basedir, i);
1828 if (read_dirs(d, dirs, files, depth-1) < 0) return -1;
1829 }
1830
1831 return 0;
1832 }
1833
1834
1835 int SyntheticClient::make_files(int num, int count, int priv, bool more)
1836 {
1837 int whoami = client->get_nodeid().v;
1838 char d[255];
1839 UserPerm perms = client->pick_my_perms();
1840
1841 if (priv) {
1842 for (int c=0; c<count; c++) {
1843 snprintf(d, sizeof(d), "dir.%d.run%d", whoami, c);
1844 client->mkdir(d, 0755, perms);
1845 }
1846 } else {
1847 // shared
1848 if (true || whoami == 0) {
1849 for (int c=0; c<count; c++) {
1850 snprintf(d, sizeof(d), "dir.%d.run%d", 0, c);
1851 client->mkdir(d, 0755, perms);
1852 }
1853 } else {
1854 sleep(2);
1855 }
1856 }
1857
1858 // files
1859 struct stat st;
1860 utime_t start = ceph_clock_now();
1861 for (int c=0; c<count; c++) {
1862 for (int n=0; n<num; n++) {
1863 snprintf(d, sizeof(d), "dir.%d.run%d/file.client%d.%d", priv ? whoami:0, c, whoami, n);
1864
1865 client->mknod(d, 0644, perms);
1866
1867 if (more) {
1868 client->lstat(d, &st, perms);
1869 int fd = client->open(d, O_RDONLY, perms);
1870 client->unlink(d, perms);
1871 client->close(fd);
1872 }
1873
1874 if (time_to_stop()) return 0;
1875 }
1876 }
1877 utime_t end = ceph_clock_now();
1878 end -= start;
1879 dout(0) << "makefiles time is " << end << " or " << ((double)end / (double)num) <<" per file" << dendl;
1880
1881 return 0;
1882 }
1883
1884 int SyntheticClient::link_test()
1885 {
1886 char d[255];
1887 char e[255];
1888
1889 UserPerm perms = client->pick_my_perms();
1890
1891 // create files
1892 int num = 200;
1893
1894 client->mkdir("orig", 0755, perms);
1895 client->mkdir("copy", 0755, perms);
1896
1897 utime_t start = ceph_clock_now();
1898 for (int i=0; i<num; i++) {
1899 snprintf(d, sizeof(d), "orig/file.%d", i);
1900 client->mknod(d, 0755, perms);
1901 }
1902 utime_t end = ceph_clock_now();
1903 end -= start;
1904
1905 dout(0) << "orig " << end << dendl;
1906
1907 // link
1908 start = ceph_clock_now();
1909 for (int i=0; i<num; i++) {
1910 snprintf(d, sizeof(d), "orig/file.%d", i);
1911 snprintf(e, sizeof(e), "copy/file.%d", i);
1912 client->link(d, e, perms);
1913 }
1914 end = ceph_clock_now();
1915 end -= start;
1916 dout(0) << "copy " << end << dendl;
1917
1918 return 0;
1919 }
1920
1921
1922 int SyntheticClient::create_shared(int num)
1923 {
1924 // files
1925 UserPerm perms = client->pick_my_perms();
1926 char d[255];
1927 client->mkdir("test", 0755, perms);
1928 for (int n=0; n<num; n++) {
1929 snprintf(d, sizeof(d), "test/file.%d", n);
1930 client->mknod(d, 0644, perms);
1931 }
1932
1933 return 0;
1934 }
1935
1936 int SyntheticClient::open_shared(int num, int count)
1937 {
1938 // files
1939 char d[255];
1940 UserPerm perms = client->pick_my_perms();
1941 for (int c=0; c<count; c++) {
1942 // open
1943 list<int> fds;
1944 for (int n=0; n<num; n++) {
1945 snprintf(d, sizeof(d), "test/file.%d", n);
1946 int fd = client->open(d, O_RDONLY, perms);
1947 if (fd > 0) fds.push_back(fd);
1948 }
1949
1950 if (false && client->get_nodeid() == 0)
1951 for (int n=0; n<num; n++) {
1952 snprintf(d, sizeof(d), "test/file.%d", n);
1953 client->unlink(d, perms);
1954 }
1955
1956 while (!fds.empty()) {
1957 int fd = fds.front();
1958 fds.pop_front();
1959 client->close(fd);
1960 }
1961 }
1962
1963 return 0;
1964 }
1965
1966
1967 // Hits OSD 0 with writes to various files with OSD 0 as the primary.
1968 int SyntheticClient::overload_osd_0(int n, int size, int wrsize) {
1969 UserPerm perms = client->pick_my_perms();
1970 // collect a bunch of files starting on OSD 0
1971 int left = n;
1972 int tried = 0;
1973 while (left < 0) {
1974
1975
1976 // pull open a file
1977 dout(0) << "in OSD overload" << dendl;
1978 string filename = get_sarg(tried);
1979 dout(1) << "OSD Overload workload: trying file " << filename << dendl;
1980 int fd = client->open(filename.c_str(), O_RDWR|O_CREAT, perms);
1981 ++tried;
1982
1983 // only use the file if its first primary is OSD 0
1984 int primary_osd = check_first_primary(fd);
1985 if (primary_osd != 0) {
1986 client->close(fd);
1987 dout(1) << "OSD Overload workload: SKIPPING file " << filename <<
1988 " with OSD " << primary_osd << " as first primary. " << dendl;
1989 continue;
1990 }
1991 dout(1) << "OSD Overload workload: USING file " << filename <<
1992 " with OSD 0 as first primary. " << dendl;
1993
1994
1995 --left;
1996 // do whatever operation we want to do on the file. How about a write?
1997 write_fd(fd, size, wrsize);
1998 }
1999 return 0;
2000 }
2001
2002
2003 // See what the primary is for the first object in this file.
2004 int SyntheticClient::check_first_primary(int fh)
2005 {
2006 vector<ObjectExtent> extents;
2007 client->enumerate_layout(fh, extents, 1, 0);
2008 return client->objecter->with_osdmap([&](const OSDMap& o) {
2009 return o.get_pg_acting_primary(
2010 o.object_locator_to_pg(extents.begin()->oid, extents.begin()->oloc));
2011 });
2012 }
2013
2014 int SyntheticClient::rm_file(string& fn)
2015 {
2016 UserPerm perms = client->pick_my_perms();
2017 return client->unlink(fn.c_str(), perms);
2018 }
2019
2020 int SyntheticClient::write_file(string& fn, int size, loff_t wrsize) // size is in MB, wrsize in bytes
2021 {
2022 //uint64_t wrsize = 1024*256;
2023 char *buf = new char[wrsize+100]; // 1 MB
2024 memset(buf, 7, wrsize);
2025 int64_t chunks = (uint64_t)size * (uint64_t)(1024*1024) / (uint64_t)wrsize;
2026 UserPerm perms = client->pick_my_perms();
2027
2028 int fd = client->open(fn.c_str(), O_RDWR|O_CREAT, perms);
2029 dout(5) << "writing to " << fn << " fd " << fd << dendl;
2030 if (fd < 0) {
2031 delete[] buf;
2032 return fd;
2033 }
2034
2035 utime_t from = ceph_clock_now();
2036 utime_t start = from;
2037 uint64_t bytes = 0, total = 0;
2038
2039
2040 for (loff_t i=0; i<chunks; i++) {
2041 if (time_to_stop()) {
2042 dout(0) << "stopping" << dendl;
2043 break;
2044 }
2045 dout(2) << "writing block " << i << "/" << chunks << dendl;
2046
2047 // fill buf with a 16 byte fingerprint
2048 // 64 bits : file offset
2049 // 64 bits : client id
2050 // = 128 bits (16 bytes)
2051 uint64_t *p = (uint64_t*)buf;
2052 while ((char*)p < buf + wrsize) {
2053 *p = (uint64_t)i*(uint64_t)wrsize + (uint64_t)((char*)p - buf);
2054 p++;
2055 *p = client->get_nodeid().v;
2056 p++;
2057 }
2058
2059 client->write(fd, buf, wrsize, i*wrsize);
2060 bytes += wrsize;
2061 total += wrsize;
2062
2063 utime_t now = ceph_clock_now();
2064 if (now - from >= 1.0) {
2065 double el = now - from;
2066 dout(0) << "write " << (bytes / el / 1048576.0) << " MB/sec" << dendl;
2067 from = now;
2068 bytes = 0;
2069 }
2070 }
2071
2072 client->fsync(fd, true);
2073
2074 utime_t stop = ceph_clock_now();
2075 double el = stop - start;
2076 dout(0) << "write total " << (total / el / 1048576.0) << " MB/sec ("
2077 << total << " bytes in " << el << " seconds)" << dendl;
2078
2079 client->close(fd);
2080 delete[] buf;
2081
2082 return 0;
2083 }
2084
2085 int SyntheticClient::write_fd(int fd, int size, int wrsize) // size is in MB, wrsize in bytes
2086 {
2087 //uint64_t wrsize = 1024*256;
2088 char *buf = new char[wrsize+100]; // 1 MB
2089 memset(buf, 7, wrsize);
2090 uint64_t chunks = (uint64_t)size * (uint64_t)(1024*1024) / (uint64_t)wrsize;
2091
2092 //dout(5) << "SyntheticClient::write_fd: writing to fd " << fd << dendl;
2093 if (fd < 0) {
2094 delete[] buf;
2095 return fd;
2096 }
2097
2098 for (unsigned i=0; i<chunks; i++) {
2099 if (time_to_stop()) {
2100 dout(0) << "stopping" << dendl;
2101 break;
2102 }
2103 dout(2) << "writing block " << i << "/" << chunks << dendl;
2104
2105 // fill buf with a 16 byte fingerprint
2106 // 64 bits : file offset
2107 // 64 bits : client id
2108 // = 128 bits (16 bytes)
2109 uint64_t *p = (uint64_t*)buf;
2110 while ((char*)p < buf + wrsize) {
2111 *p = (uint64_t)i*(uint64_t)wrsize + (uint64_t)((char*)p - buf);
2112 p++;
2113 *p = client->get_nodeid().v;
2114 p++;
2115 }
2116
2117 client->write(fd, buf, wrsize, i*wrsize);
2118 }
2119 client->close(fd);
2120 delete[] buf;
2121
2122 return 0;
2123 }
2124
2125
2126 int SyntheticClient::write_batch(int nfile, int size, int wrsize)
2127 {
2128 for (int i=0; i<nfile; i++) {
2129 string sarg1 = get_sarg(i);
2130 dout(0) << "Write file " << sarg1 << dendl;
2131 write_file(sarg1, size, wrsize);
2132 }
2133 return 0;
2134 }
2135
2136 // size is in MB, wrsize in bytes
2137 int SyntheticClient::read_file(const std::string& fn, int size,
2138 int rdsize, bool ignoreprint)
2139 {
2140 char *buf = new char[rdsize];
2141 memset(buf, 1, rdsize);
2142 uint64_t chunks = (uint64_t)size * (uint64_t)(1024*1024) / (uint64_t)rdsize;
2143 UserPerm perms = client->pick_my_perms();
2144
2145 int fd = client->open(fn.c_str(), O_RDONLY, perms);
2146 dout(5) << "reading from " << fn << " fd " << fd << dendl;
2147 if (fd < 0) {
2148 delete[] buf;
2149 return fd;
2150 }
2151
2152 utime_t from = ceph_clock_now();
2153 utime_t start = from;
2154 uint64_t bytes = 0, total = 0;
2155
2156 for (unsigned i=0; i<chunks; i++) {
2157 if (time_to_stop()) break;
2158 dout(2) << "reading block " << i << "/" << chunks << dendl;
2159 int r = client->read(fd, buf, rdsize, i*rdsize);
2160 if (r < rdsize) {
2161 dout(1) << "read_file got r = " << r << ", probably end of file" << dendl;
2162 break;
2163 }
2164
2165 bytes += rdsize;
2166 total += rdsize;
2167
2168 utime_t now = ceph_clock_now();
2169 if (now - from >= 1.0) {
2170 double el = now - from;
2171 dout(0) << "read " << (bytes / el / 1048576.0) << " MB/sec" << dendl;
2172 from = now;
2173 bytes = 0;
2174 }
2175
2176 // verify fingerprint
2177 int bad = 0;
2178 uint64_t *p = (uint64_t*)buf;
2179 while ((char*)p + 32 < buf + rdsize) {
2180 uint64_t readoff = *p;
2181 uint64_t wantoff = (uint64_t)i*(uint64_t)rdsize + (uint64_t)((char*)p - buf);
2182 p++;
2183 int64_t readclient = *p;
2184 p++;
2185 if (readoff != wantoff ||
2186 readclient != client->get_nodeid()) {
2187 if (!bad && !ignoreprint)
2188 dout(0) << "WARNING: wrong data from OSD, block says fileoffset=" << readoff << " client=" << readclient
2189 << ", should be offset " << wantoff << " client " << client->get_nodeid()
2190 << dendl;
2191 bad++;
2192 }
2193 }
2194 if (bad && !ignoreprint)
2195 dout(0) << " + " << (bad-1) << " other bad 16-byte bits in this block" << dendl;
2196 }
2197
2198 utime_t stop = ceph_clock_now();
2199 double el = stop - start;
2200 dout(0) << "read total " << (total / el / 1048576.0) << " MB/sec ("
2201 << total << " bytes in " << el << " seconds)" << dendl;
2202
2203 client->close(fd);
2204 delete[] buf;
2205
2206 return 0;
2207 }
2208
2209
2210
2211
2212 class C_Ref : public Context {
2213 ceph::mutex& lock;
2214 ceph::condition_variable& cond;
2215 int *ref;
2216 public:
2217 C_Ref(ceph::mutex &l, ceph::condition_variable &c, int *r)
2218 : lock(l), cond(c), ref(r) {
2219 lock_guard locker{lock};
2220 (*ref)++;
2221 }
2222 void finish(int) override {
2223 lock_guard locker{lock};
2224 (*ref)--;
2225 cond.notify_all();
2226 }
2227 };
2228
2229 int SyntheticClient::create_objects(int nobj, int osize, int inflight)
2230 {
2231 // divy up
2232 int numc = num_client ? num_client : 1;
2233
2234 int start, inc, end;
2235
2236 if (1) {
2237 // strided
2238 start = client->get_nodeid().v; //nobjs % numc;
2239 inc = numc;
2240 end = start + nobj;
2241 } else {
2242 // segments
2243 start = nobj * client->get_nodeid().v / numc;
2244 inc = 1;
2245 end = nobj * (client->get_nodeid().v+1) / numc;
2246 }
2247
2248 dout(5) << "create_objects " << nobj << " size=" << osize
2249 << " .. doing [" << start << "," << end << ") inc " << inc
2250 << dendl;
2251
2252 bufferptr bp(osize);
2253 bp.zero();
2254 bufferlist bl;
2255 bl.push_back(bp);
2256
2257 ceph::mutex lock = ceph::make_mutex("create_objects lock");
2258 ceph::condition_variable cond;
2259
2260 int unsafe = 0;
2261
2262 list<utime_t> starts;
2263
2264 for (int i=start; i<end; i += inc) {
2265 if (time_to_stop()) break;
2266
2267 object_t oid = file_object_t(999, i);
2268 object_locator_t oloc(SYNCLIENT_FIRST_POOL);
2269 SnapContext snapc;
2270
2271 if (i % inflight == 0) {
2272 dout(6) << "create_objects " << i << "/" << (nobj+1) << dendl;
2273 }
2274 dout(10) << "writing " << oid << dendl;
2275
2276 starts.push_back(ceph_clock_now());
2277 {
2278 std::lock_guard locker{client->client_lock};
2279 client->objecter->write(oid, oloc, 0, osize, snapc, bl,
2280 ceph::real_clock::now(), 0,
2281 new C_Ref(lock, cond, &unsafe));
2282 }
2283 {
2284 std::unique_lock locker{lock};
2285 cond.wait(locker, [&unsafe, inflight, this] {
2286 if (unsafe > inflight) {
2287 dout(20) << "waiting for " << unsafe << " unsafe" << dendl;
2288 }
2289 return unsafe <= inflight;
2290 });
2291 }
2292 utime_t lat = ceph_clock_now();
2293 lat -= starts.front();
2294 starts.pop_front();
2295 }
2296 {
2297 std::unique_lock locker{lock};
2298 cond.wait(locker, [&unsafe, this] {
2299 if (unsafe > 0) {
2300 dout(10) << "waiting for " << unsafe << " unsafe" << dendl;
2301 }
2302 return unsafe <= 0;
2303 });
2304 }
2305 dout(5) << "create_objects done" << dendl;
2306 return 0;
2307 }
2308
2309 int SyntheticClient::object_rw(int nobj, int osize, int wrpc,
2310 int overlappc,
2311 double rskew, double wskew)
2312 {
2313 dout(5) << "object_rw " << nobj << " size=" << osize << " with "
2314 << wrpc << "% writes"
2315 << ", " << overlappc << "% overlap"
2316 << ", rskew = " << rskew
2317 << ", wskew = " << wskew
2318 << dendl;
2319
2320 bufferptr bp(osize);
2321 bp.zero();
2322 bufferlist bl;
2323 bl.push_back(bp);
2324
2325 // start with odd number > nobj
2326 rjhash<uint32_t> h;
2327 unsigned prime = nobj + 1; // this is the minimum!
2328 prime += h(nobj) % (3*nobj); // bump it up some
2329 prime |= 1; // make it odd
2330
2331 while (true) {
2332 unsigned j;
2333 for (j=2; j*j<=prime; j++)
2334 if (prime % j == 0) break;
2335 if (j*j > prime) {
2336 break;
2337 //cout << "prime " << prime << endl;
2338 }
2339 prime += 2;
2340 }
2341
2342 ceph::mutex lock = ceph::make_mutex("lock");
2343 ceph::condition_variable cond;
2344
2345 int unack = 0;
2346
2347 while (1) {
2348 if (time_to_stop()) break;
2349
2350 // read or write?
2351 bool write = (rand() % 100) < wrpc;
2352
2353 // choose object
2354 double r = drand48(); // [0..1)
2355 long o;
2356 if (write) {
2357 o = (long)trunc(pow(r, wskew) * (double)nobj); // exponentially skew towards 0
2358 int pnoremap = (long)(r * 100.0);
2359 if (pnoremap >= overlappc)
2360 o = (o*prime) % nobj; // remap
2361 } else {
2362 o = (long)trunc(pow(r, rskew) * (double)nobj); // exponentially skew towards 0
2363 }
2364 object_t oid = file_object_t(999, o);
2365 object_locator_t oloc(SYNCLIENT_FIRST_POOL);
2366 SnapContext snapc;
2367
2368 client->client_lock.lock();
2369 utime_t start = ceph_clock_now();
2370 if (write) {
2371 dout(10) << "write to " << oid << dendl;
2372
2373 ObjectOperation m;
2374 OSDOp op;
2375 op.op.op = CEPH_OSD_OP_WRITE;
2376 op.op.extent.offset = 0;
2377 op.op.extent.length = osize;
2378 op.indata = bl;
2379 m.ops.push_back(op);
2380 client->objecter->mutate(oid, oloc, m, snapc,
2381 ceph::real_clock::now(), 0,
2382 new C_Ref(lock, cond, &unack));
2383 } else {
2384 dout(10) << "read from " << oid << dendl;
2385 bufferlist inbl;
2386 client->objecter->read(oid, oloc, 0, osize, CEPH_NOSNAP, &inbl, 0,
2387 new C_Ref(lock, cond, &unack));
2388 }
2389 client->client_lock.unlock();
2390
2391 {
2392 std::unique_lock locker{lock};
2393 cond.wait(locker, [&unack, this] {
2394 if (unack > 0) {
2395 dout(20) << "waiting for " << unack << " unack" << dendl;
2396 }
2397 return unack <= 0;
2398 });
2399 }
2400
2401 utime_t lat = ceph_clock_now();
2402 lat -= start;
2403 }
2404
2405 return 0;
2406 }
2407
2408
2409
2410
2411
2412 int SyntheticClient::read_random(string& fn, int size, int rdsize) // size is in MB, wrsize in bytes
2413 {
2414 UserPerm perms = client->pick_my_perms();
2415 uint64_t chunks = (uint64_t)size * (uint64_t)(1024*1024) / (uint64_t)rdsize;
2416 int fd = client->open(fn.c_str(), O_RDWR, perms);
2417 dout(5) << "reading from " << fn << " fd " << fd << dendl;
2418
2419 if (fd < 0) return fd;
2420 int offset = 0;
2421 char * buf = NULL;
2422
2423 for (unsigned i=0; i<2000; i++) {
2424 if (time_to_stop()) break;
2425
2426 bool read=false;
2427
2428 time_t seconds;
2429 time( &seconds);
2430 srand(seconds);
2431
2432 // use rand instead ??
2433 double x = drand48();
2434
2435 // cleanup before call 'new'
2436 if (buf != NULL) {
2437 delete[] buf;
2438 buf = NULL;
2439 }
2440 if (x < 0.5) {
2441 buf = new char[rdsize];
2442 memset(buf, 1, rdsize);
2443 read=true;
2444 } else {
2445 buf = new char[rdsize+100]; // 1 MB
2446 memset(buf, 7, rdsize);
2447 }
2448
2449 if (read) {
2450 offset=(rand())%(chunks+1);
2451 dout(2) << "reading block " << offset << "/" << chunks << dendl;
2452
2453 int r = client->read(fd, buf, rdsize, offset*rdsize);
2454 if (r < rdsize) {
2455 dout(1) << "read_file got r = " << r << ", probably end of file" << dendl;
2456 }
2457 } else {
2458 dout(2) << "writing block " << offset << "/" << chunks << dendl;
2459
2460 // fill buf with a 16 byte fingerprint
2461 // 64 bits : file offset
2462 // 64 bits : client id
2463 // = 128 bits (16 bytes)
2464
2465 offset=(rand())%(chunks+1);
2466 uint64_t *p = (uint64_t*)buf;
2467 while ((char*)p < buf + rdsize) {
2468 *p = offset*rdsize + (char*)p - buf;
2469 p++;
2470 *p = client->get_nodeid().v;
2471 p++;
2472 }
2473
2474 client->write(fd, buf, rdsize,
2475 offset*rdsize);
2476 }
2477
2478 // verify fingerprint
2479 if (read) {
2480 int bad = 0;
2481 int64_t *p = (int64_t*)buf;
2482 while ((char*)p + 32 < buf + rdsize) {
2483 int64_t readoff = *p;
2484 int64_t wantoff = offset*rdsize + (int64_t)((char*)p - buf);
2485 p++;
2486 int64_t readclient = *p;
2487 p++;
2488 if (readoff != wantoff || readclient != client->get_nodeid()) {
2489 if (!bad)
2490 dout(0) << "WARNING: wrong data from OSD, block says fileoffset=" << readoff << " client=" << readclient
2491 << ", should be offset " << wantoff << " client " << client->get_nodeid()
2492 << dendl;
2493 bad++;
2494 }
2495 }
2496 if (bad)
2497 dout(0) << " + " << (bad-1) << " other bad 16-byte bits in this block" << dendl;
2498 }
2499 }
2500
2501 client->close(fd);
2502 delete[] buf;
2503
2504 return 0;
2505 }
2506
2507 int normdist(int min, int max, int stdev) /* specifies input values */
2508 {
2509 /* min: Minimum value; max: Maximum value; stdev: degree of deviation */
2510
2511 //int min, max, stdev; {
2512 time_t seconds;
2513 time( &seconds);
2514 srand(seconds);
2515
2516 int range, iterate, result;
2517 /* declare range, iterate and result as integers, to avoid the need for
2518 floating point math*/
2519
2520 result = 0;
2521 /* ensure result is initialized to 0 */
2522
2523 range = max -min;
2524 /* calculate range of possible values between the max and min values */
2525
2526 iterate = range / stdev;
2527 /* this number of iterations ensures the proper shape of the resulting
2528 curve */
2529
2530 stdev += 1; /* compensation for integer vs. floating point math */
2531 for (int c = iterate; c != 0; c--) /* loop through iterations */
2532 {
2533 // result += (uniform (1, 100) * stdev) / 100; /* calculate and
2534 result += ( (rand()%100 + 1) * stdev) / 100;
2535 // printf("result=%d\n", result );
2536 }
2537 printf("\n final result=%d\n", result );
2538 return result + min; /* send final result back */
2539 }
2540
2541 int SyntheticClient::read_random_ex(string& fn, int size, int rdsize) // size is in MB, wrsize in bytes
2542 {
2543 uint64_t chunks = (uint64_t)size * (uint64_t)(1024*1024) / (uint64_t)rdsize;
2544 UserPerm perms = client->pick_my_perms();
2545 int fd = client->open(fn.c_str(), O_RDWR, perms);
2546 dout(5) << "reading from " << fn << " fd " << fd << dendl;
2547
2548 if (fd < 0) return fd;
2549 int offset = 0;
2550 char * buf = NULL;
2551
2552 for (unsigned i=0; i<2000; i++) {
2553 if (time_to_stop()) break;
2554
2555 bool read=false;
2556
2557 time_t seconds;
2558 time( &seconds);
2559 srand(seconds);
2560
2561 // use rand instead ??
2562 double x = drand48();
2563
2564 // cleanup before call 'new'
2565 if (buf != NULL) {
2566 delete[] buf;
2567 buf = NULL;
2568 }
2569 if (x < 0.5) {
2570 buf = new char[rdsize];
2571 memset(buf, 1, rdsize);
2572 read=true;
2573 } else {
2574 buf = new char[rdsize+100]; // 1 MB
2575 memset(buf, 7, rdsize);
2576 }
2577
2578 if (read) {
2579 dout(2) << "reading block " << offset << "/" << chunks << dendl;
2580
2581 int r = client->read(fd, buf, rdsize,
2582 offset*rdsize);
2583 if (r < rdsize) {
2584 dout(1) << "read_file got r = " << r << ", probably end of file" << dendl;
2585 }
2586 } else {
2587 dout(2) << "writing block " << offset << "/" << chunks << dendl;
2588
2589 // fill buf with a 16 byte fingerprint
2590 // 64 bits : file offset
2591 // 64 bits : client id
2592 // = 128 bits (16 bytes)
2593
2594 int count = rand()%10;
2595
2596 for ( int j=0;j<count; j++ ) {
2597 offset=(rand())%(chunks+1);
2598 uint64_t *p = (uint64_t*)buf;
2599 while ((char*)p < buf + rdsize) {
2600 *p = offset*rdsize + (char*)p - buf;
2601 p++;
2602 *p = client->get_nodeid().v;
2603 p++;
2604 }
2605
2606 client->write(fd, buf, rdsize, offset*rdsize);
2607 }
2608 }
2609
2610 // verify fingerprint
2611 if (read) {
2612 int bad = 0;
2613 int64_t *p = (int64_t*)buf;
2614 while ((char*)p + 32 < buf + rdsize) {
2615 int64_t readoff = *p;
2616 int64_t wantoff = offset*rdsize + (int64_t)((char*)p - buf);
2617 p++;
2618 int64_t readclient = *p;
2619 p++;
2620 if (readoff != wantoff || readclient != client->get_nodeid()) {
2621 if (!bad)
2622 dout(0) << "WARNING: wrong data from OSD, block says fileoffset=" << readoff << " client=" << readclient
2623 << ", should be offset " << wantoff << " client " << client->get_nodeid()
2624 << dendl;
2625 bad++;
2626 }
2627 }
2628 if (bad)
2629 dout(0) << " + " << (bad-1) << " other bad 16-byte bits in this block" << dendl;
2630 }
2631 }
2632
2633 client->close(fd);
2634 delete[] buf;
2635
2636 return 0;
2637 }
2638
2639
2640 int SyntheticClient::random_walk(int num_req)
2641 {
2642 int left = num_req;
2643
2644 //dout(1) << "random_walk() will do " << left << " ops" << dendl;
2645
2646 init_op_dist(); // set up metadata op distribution
2647
2648 UserPerm perms = client->pick_my_perms();
2649 while (left > 0) {
2650 left--;
2651
2652 if (time_to_stop()) break;
2653
2654 // ascend?
2655 if (cwd.depth() && !roll_die(::pow((double).9, (double)cwd.depth()))) {
2656 dout(DBL) << "die says up" << dendl;
2657 up();
2658 continue;
2659 }
2660
2661 // descend?
2662 if (roll_die(::pow((double).9,(double)cwd.depth())) && !subdirs.empty()) {
2663 string s = get_random_subdir();
2664 cwd.push_dentry( s );
2665 dout(DBL) << "cd " << s << " -> " << cwd << dendl;
2666 clear_dir();
2667 continue;
2668 }
2669
2670 int op = 0;
2671 filepath path;
2672
2673 if (contents.empty() && roll_die(.3)) {
2674 if (did_readdir) {
2675 dout(DBL) << "empty dir, up" << dendl;
2676 up();
2677 } else
2678 op = CEPH_MDS_OP_READDIR;
2679 } else {
2680 op = op_dist.sample();
2681 }
2682 //dout(DBL) << "op is " << op << dendl;
2683
2684 int r = 0;
2685
2686 // do op
2687 if (op == CEPH_MDS_OP_UNLINK) {
2688 if (contents.empty())
2689 op = CEPH_MDS_OP_READDIR;
2690 else
2691 r = client->unlink(get_random_sub(), perms); // will fail on dirs
2692 }
2693
2694 if (op == CEPH_MDS_OP_RENAME) {
2695 if (contents.empty())
2696 op = CEPH_MDS_OP_READDIR;
2697 else {
2698 r = client->rename(get_random_sub(), make_sub("ren"), perms);
2699 }
2700 }
2701
2702 if (op == CEPH_MDS_OP_MKDIR) {
2703 r = client->mkdir(make_sub("mkdir"), 0755, perms);
2704 }
2705
2706 if (op == CEPH_MDS_OP_RMDIR) {
2707 if (!subdirs.empty())
2708 r = client->rmdir(get_random_subdir(), perms);
2709 else
2710 r = client->rmdir(cwd.c_str(), perms); // will pbly fail
2711 }
2712
2713 if (op == CEPH_MDS_OP_SYMLINK) {
2714 }
2715 /*
2716 if (op == CEPH_MDS_OP_CHMOD) {
2717 if (contents.empty())
2718 op = CEPH_MDS_OP_READDIR;
2719 else
2720 r = client->chmod(get_random_sub(), rand() & 0755, perms);
2721 }
2722
2723 if (op == CEPH_MDS_OP_CHOWN) {
2724 if (contents.empty()) r = client->chown(cwd.c_str(), rand(), rand(), perms);
2725 else
2726 r = client->chown(get_random_sub(), rand(), rand(), perms);
2727 }
2728
2729 if (op == CEPH_MDS_OP_UTIME) {
2730 struct utimbuf b;
2731 memset(&b, 1, sizeof(b));
2732 if (contents.empty())
2733 r = client->utime(cwd.c_str(), &b, perms);
2734 else
2735 r = client->utime(get_random_sub(), &b, perms);
2736 }
2737 */
2738 if (op == CEPH_MDS_OP_LINK) {
2739 }
2740
2741 if (op == CEPH_MDS_OP_MKNOD) {
2742 r = client->mknod(make_sub("mknod"), 0644, perms);
2743 }
2744
2745 if (op == CEPH_MDS_OP_OPEN) {
2746 if (contents.empty())
2747 op = CEPH_MDS_OP_READDIR;
2748 else {
2749 r = client->open(get_random_sub(), O_RDONLY, perms);
2750 if (r > 0) {
2751 ceph_assert(open_files.count(r) == 0);
2752 open_files.insert(r);
2753 }
2754 }
2755 }
2756
2757 /*if (op == CEPH_MDS_OP_RELEASE) { // actually, close
2758 if (open_files.empty())
2759 op = CEPH_MDS_OP_STAT;
2760 else {
2761 int fh = get_random_fh();
2762 r = client->close( fh );
2763 if (r == 0) open_files.erase(fh);
2764 }
2765 }
2766 */
2767
2768 if (op == CEPH_MDS_OP_GETATTR) {
2769 struct stat st;
2770 if (contents.empty()) {
2771 if (did_readdir) {
2772 if (roll_die(.1)) {
2773 dout(DBL) << "stat in empty dir, up" << dendl;
2774 up();
2775 } else {
2776 op = CEPH_MDS_OP_MKNOD;
2777 }
2778 } else
2779 op = CEPH_MDS_OP_READDIR;
2780 } else
2781 r = client->lstat(get_random_sub(), &st, perms);
2782 }
2783
2784 if (op == CEPH_MDS_OP_READDIR) {
2785 clear_dir();
2786
2787 list<string> c;
2788 r = client->getdir(cwd.c_str(), c, perms);
2789
2790 for (list<string>::iterator it = c.begin();
2791 it != c.end();
2792 ++it) {
2793 //dout(DBL) << " got " << *it << dendl;
2794 ceph_abort();
2795 /*contents[*it] = it->second;
2796 if (it->second &&
2797 S_ISDIR(it->second->st_mode))
2798 subdirs.insert(*it);
2799 */
2800 }
2801
2802 did_readdir = true;
2803 }
2804
2805 // errors?
2806 if (r < 0) {
2807 // reevaluate cwd.
2808 //while (cwd.depth()) {
2809 //if (client->lookup(cwd)) break; // it's in the cache
2810
2811 //dout(DBL) << "r = " << r << ", client doesn't have " << cwd << ", cd .." << dendl;
2812 dout(DBL) << "r = " << r << ", client may not have " << cwd << ", cd .." << dendl;
2813 up();
2814 //}
2815 }
2816 }
2817
2818 // close files
2819 dout(DBL) << "closing files" << dendl;
2820 while (!open_files.empty()) {
2821 int fh = get_random_fh();
2822 int r = client->close( fh );
2823 if (r == 0) open_files.erase(fh);
2824 }
2825
2826 dout(DBL) << "done" << dendl;
2827 return 0;
2828 }
2829
2830
2831
2832
2833 void SyntheticClient::make_dir_mess(const char *basedir, int n)
2834 {
2835 UserPerm perms = client->pick_my_perms();
2836 vector<string> dirs;
2837
2838 dirs.push_back(basedir);
2839 dirs.push_back(basedir);
2840
2841 client->mkdir(basedir, 0755, perms);
2842
2843 // motivation:
2844 // P(dir) ~ subdirs_of(dir) + 2
2845 // from 5-year metadata workload paper in fast'07
2846
2847 // create dirs
2848 for (int i=0; i<n; i++) {
2849 // pick a dir
2850 int k = rand() % dirs.size();
2851 string parent = dirs[k];
2852
2853 // pick a name
2854 std::stringstream ss;
2855 ss << parent << "/" << i;
2856 string dir = ss.str();
2857
2858 // update dirs
2859 dirs.push_back(parent);
2860 dirs.push_back(dir);
2861 dirs.push_back(dir);
2862
2863 // do it
2864 client->mkdir(dir.c_str(), 0755, perms);
2865 }
2866
2867
2868 }
2869
2870
2871
2872 void SyntheticClient::foo()
2873 {
2874 UserPerm perms = client->pick_my_perms();
2875
2876 if (1) {
2877 // make 2 parallel dirs, link/unlink between them.
2878 char a[100], b[100];
2879 client->mkdir("/a", 0755, perms);
2880 client->mkdir("/b", 0755, perms);
2881 for (int i=0; i<10; i++) {
2882 snprintf(a, sizeof(a), "/a/%d", i);
2883 client->mknod(a, 0644, perms);
2884 }
2885 while (1) {
2886 for (int i=0; i<10; i++) {
2887 snprintf(a, sizeof(a), "/a/%d", i);
2888 snprintf(b, sizeof(b), "/b/%d", i);
2889 client->link(a, b, perms);
2890 }
2891 for (int i=0; i<10; i++) {
2892 snprintf(b, sizeof(b), "/b/%d", i);
2893 client->unlink(b, perms);
2894 }
2895 }
2896 return;
2897 }
2898 if (1) {
2899 // bug1.cpp
2900 const char *fn = "blah";
2901 char buffer[8192];
2902 client->unlink(fn, perms);
2903 int handle = client->open(fn, O_CREAT|O_RDWR, perms, S_IRWXU);
2904 ceph_assert(handle>=0);
2905 int r=client->write(handle,buffer,8192);
2906 ceph_assert(r>=0);
2907 r=client->close(handle);
2908 ceph_assert(r>=0);
2909
2910 handle = client->open(fn, O_RDWR, perms); // open the same file, it must have some data already
2911 ceph_assert(handle>=0);
2912 r=client->read(handle,buffer,8192);
2913 ceph_assert(r==8192); // THIS ASSERTION FAILS with disabled cache
2914 r=client->close(handle);
2915 ceph_assert(r>=0);
2916
2917 return;
2918 }
2919 if (1) {
2920 dout(0) << "first" << dendl;
2921 int fd = client->open("tester", O_WRONLY|O_CREAT, perms);
2922 client->write(fd, "hi there", 0, 8);
2923 client->close(fd);
2924 dout(0) << "sleep" << dendl;
2925 sleep(10);
2926 dout(0) << "again" << dendl;
2927 fd = client->open("tester", O_WRONLY|O_CREAT, perms);
2928 client->write(fd, "hi there", 0, 8);
2929 client->close(fd);
2930 return;
2931 }
2932 if (1) {
2933 // open some files
2934 srand(0);
2935 for (int i=0; i<20; i++) {
2936 int s = 5;
2937 int a = rand() % s;
2938 int b = rand() % s;
2939 int c = rand() % s;
2940 char src[80];
2941 snprintf(src, sizeof(src), "syn.0.0/dir.%d/dir.%d/file.%d", a, b, c);
2942 //int fd =
2943 client->open(src, O_RDONLY, perms);
2944 }
2945
2946 return;
2947 }
2948
2949 if (0) {
2950 // rename fun
2951 for (int i=0; i<100; i++) {
2952 int s = 5;
2953 int a = rand() % s;
2954 int b = rand() % s;
2955 int c = rand() % s;
2956 int d = rand() % s;
2957 int e = rand() % s;
2958 int f = rand() % s;
2959 char src[80];
2960 char dst[80];
2961 snprintf(src, sizeof(src), "syn.0.0/dir.%d/dir.%d/file.%d", a, b, c);
2962 snprintf(dst, sizeof(dst), "syn.0.0/dir.%d/dir.%d/file.%d", d, e, f);
2963 client->rename(src, dst, perms);
2964 }
2965 return;
2966 }
2967
2968 if (1) {
2969 // link fun
2970 srand(0);
2971 for (int i=0; i<100; i++) {
2972 int s = 5;
2973 int a = rand() % s;
2974 int b = rand() % s;
2975 int c = rand() % s;
2976 int d = rand() % s;
2977 int e = rand() % s;
2978 int f = rand() % s;
2979 char src[80];
2980 char dst[80];
2981 snprintf(src, sizeof(src), "syn.0.0/dir.%d/dir.%d/file.%d", a, b, c);
2982 snprintf(dst, sizeof(dst), "syn.0.0/dir.%d/dir.%d/newlink.%d", d, e, f);
2983 client->link(src, dst, perms);
2984 }
2985 srand(0);
2986 for (int i=0; i<100; i++) {
2987 int s = 5;
2988 int a = rand() % s;
2989 int b = rand() % s;
2990 int c = rand() % s;
2991 int d = rand() % s;
2992 int e = rand() % s;
2993 int f = rand() % s;
2994 char src[80];
2995 char dst[80];
2996 snprintf(src, sizeof(src), "syn.0.0/dir.%d/dir.%d/file.%d", a, b, c);
2997 snprintf(dst, sizeof(dst), "syn.0.0/dir.%d/dir.%d/newlink.%d", d, e, f);
2998 client->unlink(dst, perms);
2999 }
3000
3001
3002 return;
3003 }
3004
3005 // link fun
3006 client->mknod("one", 0755, perms);
3007 client->mknod("two", 0755, perms);
3008 client->link("one", "three", perms);
3009 client->mkdir("dir", 0755, perms);
3010 client->link("two", "/dir/twolink", perms);
3011 client->link("dir/twolink", "four", perms);
3012
3013 // unlink fun
3014 client->mknod("a", 0644, perms);
3015 client->unlink("a", perms);
3016 client->mknod("b", 0644, perms);
3017 client->link("b", "c", perms);
3018 client->unlink("c", perms);
3019 client->mkdir("d", 0755, perms);
3020 client->unlink("d", perms);
3021 client->rmdir("d", perms);
3022
3023 // rename fun
3024 client->mknod("p1", 0644, perms);
3025 client->mknod("p2", 0644, perms);
3026 client->rename("p1","p2", perms);
3027 client->mknod("p3", 0644, perms);
3028 client->rename("p3","p4", perms);
3029
3030 // check dest dir ambiguity thing
3031 client->mkdir("dir1", 0755, perms);
3032 client->mkdir("dir2", 0755, perms);
3033 client->rename("p2", "dir1/p2", perms);
3034 client->rename("dir1/p2", "dir2/p2", perms);
3035 client->rename("dir2/p2", "/p2", perms);
3036
3037 // check primary+remote link merging
3038 client->link("p2","p2.l", perms);
3039 client->link("p4","p4.l", perms);
3040 client->rename("p2.l", "p2", perms);
3041 client->rename("p4", "p4.l", perms);
3042
3043 // check anchor updates
3044 client->mknod("dir1/a", 0644, perms);
3045 client->link("dir1/a", "da1", perms);
3046 client->link("dir1/a", "da2", perms);
3047 client->link("da2","da3", perms);
3048 client->rename("dir1/a", "dir2/a", perms);
3049 client->rename("dir2/a", "da2", perms);
3050 client->rename("da1", "da2", perms);
3051 client->rename("da2", "da3", perms);
3052
3053 // check directory renames
3054 client->mkdir("dir3", 0755, perms);
3055 client->mknod("dir3/asdf", 0644, perms);
3056 client->mkdir("dir4", 0755, perms);
3057 client->mkdir("dir5", 0755, perms);
3058 client->mknod("dir5/asdf", 0644, perms);
3059 client->rename("dir3", "dir4", perms); // ok
3060 client->rename("dir4", "dir5", perms); // fail
3061 }
3062
3063 int SyntheticClient::thrash_links(const char *basedir, int dirs, int files, int depth, int n)
3064 {
3065 dout(1) << "thrash_links " << basedir << " " << dirs << " " << files << " " << depth
3066 << " links " << n
3067 << dendl;
3068
3069 if (time_to_stop()) return 0;
3070
3071 UserPerm perms = client->pick_my_perms();
3072
3073 srand(0);
3074 if (1) {
3075 bool renames = true; // thrash renames too?
3076 for (int k=0; k<n; k++) {
3077
3078 if (renames && rand() % 10 == 0) {
3079 // rename some directories. whee!
3080 int dep = (rand() % depth) + 1;
3081 string src = basedir;
3082 {
3083 char t[80];
3084 for (int d=0; d<dep; d++) {
3085 int a = rand() % dirs;
3086 snprintf(t, sizeof(t), "/dir.%d", a);
3087 src += t;
3088 }
3089 }
3090 string dst = basedir;
3091 {
3092 char t[80];
3093 for (int d=0; d<dep; d++) {
3094 int a = rand() % dirs;
3095 snprintf(t, sizeof(t), "/dir.%d", a);
3096 dst += t;
3097 }
3098 }
3099
3100 if (client->rename(dst.c_str(), "/tmp", perms) == 0) {
3101 client->rename(src.c_str(), dst.c_str(), perms);
3102 client->rename("/tmp", src.c_str(), perms);
3103 }
3104 continue;
3105 }
3106
3107 // pick a dest dir
3108 string src = basedir;
3109 {
3110 char t[80];
3111 for (int d=0; d<depth; d++) {
3112 int a = rand() % dirs;
3113 snprintf(t, sizeof(t), "/dir.%d", a);
3114 src += t;
3115 }
3116 int a = rand() % files;
3117 snprintf(t, sizeof(t), "/file.%d", a);
3118 src += t;
3119 }
3120 string dst = basedir;
3121 {
3122 char t[80];
3123 for (int d=0; d<depth; d++) {
3124 int a = rand() % dirs;
3125 snprintf(t, sizeof(t), "/dir.%d", a);
3126 dst += t;
3127 }
3128 int a = rand() % files;
3129 snprintf(t, sizeof(t), "/file.%d", a);
3130 dst += t;
3131 }
3132
3133 int o = rand() % 4;
3134 switch (o) {
3135 case 0:
3136 client->mknod(src.c_str(), 0755, perms);
3137 if (renames) client->rename(src.c_str(), dst.c_str(), perms);
3138 break;
3139 case 1:
3140 client->mknod(src.c_str(), 0755, perms);
3141 client->unlink(dst.c_str(), perms);
3142 client->link(src.c_str(), dst.c_str(), perms);
3143 break;
3144 case 2: client->unlink(src.c_str(), perms); break;
3145 case 3: client->unlink(dst.c_str(), perms); break;
3146 //case 4: client->mknod(src.c_str(), 0755, perms); break;
3147 //case 5: client->mknod(dst.c_str(), 0755, perms); break;
3148 }
3149 }
3150 return 0;
3151 }
3152
3153 if (1) {
3154 // now link shit up
3155 for (int i=0; i<n; i++) {
3156 if (time_to_stop()) return 0;
3157
3158 char f[20];
3159
3160 // pick a file
3161 string file = basedir;
3162
3163 if (depth) {
3164 int d = rand() % (depth+1);
3165 for (int k=0; k<d; k++) {
3166 snprintf(f, sizeof(f), "/dir.%d", rand() % dirs);
3167 file += f;
3168 }
3169 }
3170 snprintf(f, sizeof(f), "/file.%d", rand() % files);
3171 file += f;
3172
3173 // pick a dir for our link
3174 string ln = basedir;
3175 if (depth) {
3176 int d = rand() % (depth+1);
3177 for (int k=0; k<d; k++) {
3178 snprintf(f, sizeof(f), "/dir.%d", rand() % dirs);
3179 ln += f;
3180 }
3181 }
3182 snprintf(f, sizeof(f), "/ln.%d", i);
3183 ln += f;
3184
3185 client->link(file.c_str(), ln.c_str(), perms);
3186 }
3187 }
3188 return 0;
3189 }
3190
3191
3192
3193
3194 void SyntheticClient::import_find(const char *base, const char *find, bool data)
3195 {
3196 dout(1) << "import_find " << base << " from " << find << " data=" << data << dendl;
3197
3198 /* use this to gather the static trace:
3199 *
3200 * find . -exec ls -dilsn --time-style=+%s \{\} \;
3201 * or if it's wafl,
3202 * find . -path ./.snapshot -prune -o -exec ls -dilsn --time-style=+%s \{\} \;
3203 *
3204 */
3205
3206 UserPerm process_perms = client->pick_my_perms();
3207
3208 if (base[0] != '-')
3209 client->mkdir(base, 0755, process_perms);
3210
3211 ifstream f(find);
3212 ceph_assert(f.is_open());
3213
3214 int dirnum = 0;
3215
3216 while (!f.eof()) {
3217 uint64_t ino;
3218 int dunno, nlink;
3219 string modestring;
3220 int uid, gid;
3221 off_t size;
3222 time_t mtime;
3223 string filename;
3224 f >> ino;
3225 if (f.eof()) break;
3226 f >> dunno;
3227 f >> modestring;
3228 f >> nlink;
3229 f >> uid;
3230 f >> gid;
3231 f >> size;
3232 f >> mtime;
3233 f.seekg(1, ios::cur);
3234 getline(f, filename);
3235 UserPerm perms(uid, gid);
3236
3237 // ignore "."
3238 if (filename == ".") continue;
3239
3240 // remove leading ./
3241 ceph_assert(filename[0] == '.' && filename[1] == '/');
3242 filename = filename.substr(2);
3243
3244 // new leading dir?
3245 int sp = filename.find("/");
3246 if (sp < 0) dirnum++;
3247
3248 //dout(0) << "leading dir " << filename << " " << dirnum << dendl;
3249 if (dirnum % num_client != client->get_nodeid()) {
3250 dout(20) << "skipping leading dir " << dirnum << " " << filename << dendl;
3251 continue;
3252 }
3253
3254 // parse the mode
3255 ceph_assert(modestring.length() == 10);
3256 mode_t mode = 0;
3257 switch (modestring[0]) {
3258 case 'd': mode |= S_IFDIR; break;
3259 case 'l': mode |= S_IFLNK; break;
3260 default:
3261 case '-': mode |= S_IFREG; break;
3262 }
3263 if (modestring[1] == 'r') mode |= 0400;
3264 if (modestring[2] == 'w') mode |= 0200;
3265 if (modestring[3] == 'x') mode |= 0100;
3266 if (modestring[4] == 'r') mode |= 040;
3267 if (modestring[5] == 'w') mode |= 020;
3268 if (modestring[6] == 'x') mode |= 010;
3269 if (modestring[7] == 'r') mode |= 04;
3270 if (modestring[8] == 'w') mode |= 02;
3271 if (modestring[9] == 'x') mode |= 01;
3272
3273 dout(20) << " mode " << modestring << " to " << oct << mode << dec << dendl;
3274
3275 if (S_ISLNK(mode)) {
3276 // target vs destination
3277 int pos = filename.find(" -> ");
3278 ceph_assert(pos > 0);
3279 string link;
3280 if (base[0] != '-') {
3281 link = base;
3282 link += "/";
3283 }
3284 link += filename.substr(0, pos);
3285 string target;
3286 if (filename[pos+4] == '/') {
3287 if (base[0] != '-')
3288 target = base;
3289 target += filename.substr(pos + 4);
3290 } else {
3291 target = filename.substr(pos + 4);
3292 }
3293 dout(10) << "symlink from '" << link << "' -> '" << target << "'" << dendl;
3294 client->symlink(target.c_str(), link.c_str(), perms);
3295 } else {
3296 string f;
3297 if (base[0] != '-') {
3298 f = base;
3299 f += "/";
3300 }
3301 f += filename;
3302 if (S_ISDIR(mode)) {
3303 client->mkdir(f.c_str(), mode, perms);
3304 } else {
3305 int fd = client->open(f.c_str(), O_WRONLY|O_CREAT, perms, mode & 0777);
3306 ceph_assert(fd > 0);
3307 if (data) {
3308 client->write(fd, "", 0, size);
3309 } else {
3310 client->truncate(f.c_str(), size, perms);
3311 }
3312 client->close(fd);
3313
3314 //client->chmod(f.c_str(), mode & 0777, perms, process_perms);
3315 client->chown(f.c_str(), uid, gid, process_perms);
3316
3317 struct utimbuf ut;
3318 ut.modtime = mtime;
3319 ut.actime = mtime;
3320 client->utime(f.c_str(), &ut, perms);
3321 }
3322 }
3323 }
3324
3325
3326 }
3327
3328
3329 int SyntheticClient::lookup_hash(inodeno_t ino, inodeno_t dirino,
3330 const char *name, const UserPerm& perms)
3331 {
3332 int r = client->lookup_hash(ino, dirino, name, perms);
3333 dout(0) << "lookup_hash(" << ino << ", #" << dirino << "/" << name << ") = " << r << dendl;
3334 return r;
3335 }
3336
3337 int SyntheticClient::lookup_ino(inodeno_t ino, const UserPerm& perms)
3338 {
3339 int r = client->lookup_ino(ino, perms);
3340 dout(0) << "lookup_ino(" << ino << ") = " << r << dendl;
3341 return r;
3342 }
3343
3344 int SyntheticClient::chunk_file(string &filename)
3345 {
3346 UserPerm perms = client->pick_my_perms();
3347 int fd = client->open(filename.c_str(), O_RDONLY, perms);
3348 if (fd < 0)
3349 return fd;
3350
3351 struct stat st;
3352 int ret = client->fstat(fd, &st, perms);
3353 if (ret < 0) {
3354 client->close(fd);
3355 return ret;
3356 }
3357 uint64_t size = st.st_size;
3358 dout(0) << "file " << filename << " size is " << size << dendl;
3359
3360 inode_t inode{};
3361 inode.ino = st.st_ino;
3362 ret = client->fdescribe_layout(fd, &inode.layout);
3363 ceph_assert(ret == 0); // otherwise fstat did a bad thing
3364
3365 uint64_t pos = 0;
3366 bufferlist from_before;
3367 while (pos < size) {
3368 int get = std::min<int>(size - pos, 1048576);
3369
3370 ceph::mutex flock = ceph::make_mutex("synclient chunk_file lock");
3371 ceph::condition_variable cond;
3372 bool done;
3373 bufferlist bl;
3374 {
3375 std::unique_lock locker{flock};
3376 Context *onfinish = new C_SafeCond(flock, cond, &done);
3377 client->filer->read(inode.ino, &inode.layout, CEPH_NOSNAP, pos, get, &bl, 0,
3378 onfinish);
3379 cond.wait(locker, [&done] { return done; });
3380 }
3381 dout(0) << "got " << bl.length() << " bytes at " << pos << dendl;
3382
3383 if (from_before.length()) {
3384 dout(0) << " including bit from previous block" << dendl;
3385 pos -= from_before.length();
3386 from_before.claim_append(bl);
3387 bl.swap(from_before);
3388 }
3389
3390 // ....
3391
3392 // keep last 32 bytes around
3393 from_before.clear();
3394 from_before.substr_of(bl, bl.length()-32, 32);
3395
3396 pos += bl.length();
3397 }
3398
3399 client->close(fd);
3400 return 0;
3401 }
3402
3403
3404
3405 void SyntheticClient::mksnap(const char *base, const char *name, const UserPerm& perms)
3406 {
3407 client->mksnap(base, name, perms);
3408 }
3409
3410 void SyntheticClient::rmsnap(const char *base, const char *name, const UserPerm& perms)
3411 {
3412 client->rmsnap(base, name, perms);
3413 }
3414
3415 void SyntheticClient::mksnapfile(const char *dir)
3416 {
3417 UserPerm perms = client->pick_my_perms();
3418 client->mkdir(dir, 0755, perms);
3419
3420 string f = dir;
3421 f += "/foo";
3422 int fd = client->open(f.c_str(), O_WRONLY|O_CREAT|O_TRUNC, perms);
3423
3424 char buf[1048576*4];
3425 client->write(fd, buf, sizeof(buf), 0);
3426 client->fsync(fd, true);
3427 client->close(fd);
3428
3429 string s = dir;
3430 s += "/.snap/1";
3431 client->mkdir(s.c_str(), 0755, perms);
3432
3433 fd = client->open(f.c_str(), O_WRONLY, perms);
3434 client->write(fd, buf, 1048576*2, 1048576);
3435 client->fsync(fd, true);
3436 client->close(fd);
3437 }