root / xseg / peers / user / bench-utils.c @ 7e21df56
History | View | Annotate | Download (14.8 kB)
1 |
/*
|
---|---|
2 |
* Copyright 2012 GRNET S.A. All rights reserved.
|
3 |
*
|
4 |
* Redistribution and use in source and binary forms, with or
|
5 |
* without modification, are permitted provided that the following
|
6 |
* conditions are met:
|
7 |
*
|
8 |
* 1. Redistributions of source code must retain the above
|
9 |
* copyright notice, this list of conditions and the following
|
10 |
* disclaimer.
|
11 |
* 2. Redistributions in binary form must reproduce the above
|
12 |
* copyright notice, this list of conditions and the following
|
13 |
* disclaimer in the documentation and/or other materials
|
14 |
* provided with the distribution.
|
15 |
*
|
16 |
* THIS SOFTWARE IS PROVIDED BY GRNET S.A. ``AS IS'' AND ANY EXPRESS
|
17 |
* OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
18 |
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
19 |
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL GRNET S.A OR
|
20 |
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
21 |
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
22 |
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
|
23 |
* USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
|
24 |
* AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
25 |
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
|
26 |
* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
27 |
* POSSIBILITY OF SUCH DAMAGE.
|
28 |
*
|
29 |
* The views and conclusions contained in the software and
|
30 |
* documentation are those of the authors and should not be
|
31 |
* interpreted as representing official policies, either expressed
|
32 |
* or implied, of GRNET S.A.
|
33 |
*/
|
34 |
|
35 |
#define _GNU_SOURCE
|
36 |
#include <stdio.h> |
37 |
#include <stdlib.h> |
38 |
#include <unistd.h> |
39 |
#include <sys/syscall.h> |
40 |
#include <sys/types.h> |
41 |
#include <pthread.h> |
42 |
#include <xseg/xseg.h> |
43 |
#include <peer.h> |
44 |
#include <time.h> |
45 |
#include <sys/util.h> |
46 |
#include <signal.h> |
47 |
#include <bench-xseg.h> |
48 |
|
49 |
#include <math.h> |
50 |
#include <string.h> |
51 |
|
52 |
#define PRINT_SIG(__who, __sig) \
|
53 |
fprintf(stdout, "%s (%lu): id %lu, object %lu, offset %lu\n", \
|
54 |
#__who, (uint64_t)(__sig), \
|
55 |
((struct signature *)__sig)->id, \
|
56 |
((struct signature *)__sig)->object, \
|
57 |
((struct signature *)__sig)->offset);
|
58 |
|
59 |
struct timespec delay = {0, 4000000}; |
60 |
|
61 |
/******************************\
|
62 |
* Static miscellaneous tools *
|
63 |
\******************************/
|
64 |
static inline uint64_t __get_id() |
65 |
{ |
66 |
return atol(global_id + 6); /* cut the "bench-" part*/ |
67 |
} |
68 |
|
69 |
static inline uint64_t __get_object_from_name(char *name) |
70 |
{ |
71 |
return atol(name + IDLEN); /* cut the "bench-908135-" part*/ |
72 |
} |
73 |
|
74 |
static inline uint64_t __get_object(struct bench *prefs, uint64_t new) |
75 |
{ |
76 |
if (prefs->ts > 0) |
77 |
new = new / (prefs->os / prefs->bs); |
78 |
return new;
|
79 |
} |
80 |
|
81 |
static inline int __snap_to_bound8(uint64_t space) |
82 |
{ |
83 |
return space > 8 ? 8 : space; |
84 |
} |
85 |
|
86 |
static inline double __timespec2double(struct timespec num) |
87 |
{ |
88 |
return (double) (num.tv_sec * pow(10, 9) + num.tv_nsec); |
89 |
} |
90 |
|
91 |
static inline void __write_sig(struct bench_lfsr *sg, uint64_t *d, uint64_t s, |
92 |
int pos)
|
93 |
{ |
94 |
uint64_t i; |
95 |
uint64_t last_val; |
96 |
uint64_t space_left; |
97 |
|
98 |
/* Write random numbers (based on global_id) every 24 bytes */
|
99 |
/* TODO: Should we use memcpy? */
|
100 |
for (i = pos; i < (s / 8) - (3 - pos); i += 3) |
101 |
*(d + i) = lfsr_next(sg); |
102 |
|
103 |
/* special care for last chunk */
|
104 |
last_val = lfsr_next(sg); |
105 |
space_left = s - (i * 8);
|
106 |
memcpy(d + i, &last_val, __snap_to_bound8(space_left)); |
107 |
} |
108 |
|
109 |
static inline int __read_sig(struct bench_lfsr *sg, uint64_t *d, uint64_t s, |
110 |
int pos)
|
111 |
{ |
112 |
uint64_t i; |
113 |
uint64_t last_val; |
114 |
uint64_t space_left; |
115 |
|
116 |
/* TODO: Should we use memcmp? */
|
117 |
for (i = pos; i < (s / 8) - (3 - pos); i += 3) { |
118 |
if (*(d + i) != lfsr_next(sg))
|
119 |
return 1; |
120 |
} |
121 |
/* special care for last chunk */
|
122 |
last_val = lfsr_next(sg); |
123 |
space_left = s - (i * 8);
|
124 |
if (memcmp(d + i, &last_val, __snap_to_bound8(space_left)))
|
125 |
return 1; |
126 |
|
127 |
return 0; |
128 |
} |
129 |
|
130 |
/*
|
131 |
* Seperates a double number in seconds, msec, usec, nsec
|
132 |
* Expects a number in nanoseconds (e.g. a number from timespec2double)
|
133 |
*/
|
134 |
static struct tm_result __separate_by_order(double num) |
135 |
{ |
136 |
struct tm_result res;
|
137 |
|
138 |
//The format we expect is the following:
|
139 |
//
|
140 |
// |-s-|-ms-|-us-|-ns|
|
141 |
//num = 123 456 789 012 . 000000000000
|
142 |
res.s = num / pow(10,9); |
143 |
num = fmod(num, pow(10,9)); |
144 |
res.ms = num / pow(10,6); |
145 |
num = fmod(num, pow(10,6)); |
146 |
res.us = num / 1000;
|
147 |
res.ns = fmod(num, 1000);
|
148 |
|
149 |
return res;
|
150 |
} |
151 |
|
152 |
static void __calculate_bw(struct bench *prefs, double iops, struct bw *bw) |
153 |
{ |
154 |
bw->val = iops * prefs->bs; |
155 |
strcpy(bw->unit, "B/s");
|
156 |
|
157 |
if (bw->val < 1024) |
158 |
return;
|
159 |
|
160 |
bw->val = bw->val / 1024;
|
161 |
strcpy(bw->unit, "KB/s");
|
162 |
|
163 |
if (bw->val < 1024) |
164 |
return;
|
165 |
|
166 |
bw->val = bw->val / 1024;
|
167 |
strcpy(bw->unit, "MB/s");
|
168 |
|
169 |
if (bw->val < 1024) |
170 |
return;
|
171 |
|
172 |
bw->val = bw->val / 1024;
|
173 |
strcpy(bw->unit, "GB/s");
|
174 |
} |
175 |
|
176 |
static double __calculate_iops(struct bench *prefs, double elapsed_ns) |
177 |
{ |
178 |
/* elapsed_ns is in nanoseconds, so we convert it to seconds */
|
179 |
double elapsed = elapsed_ns / pow(10,9); |
180 |
return (prefs->status->received / elapsed);
|
181 |
} |
182 |
|
183 |
/******************************\
|
184 |
* Argument-parsing functions *
|
185 |
\******************************/
|
186 |
|
187 |
/*
|
188 |
* Convert string to size in bytes.
|
189 |
* If syntax is invalid, return 0. Values such as zero and non-integer
|
190 |
* multiples of segment's page size should not be accepted.
|
191 |
*/
|
192 |
uint64_t str2num(char *str)
|
193 |
{ |
194 |
char *unit;
|
195 |
uint64_t num; |
196 |
|
197 |
num = strtoll(str, &unit, 10);
|
198 |
if (strlen(unit) > 1) //Invalid syntax |
199 |
return 0; |
200 |
else if (strlen(unit) < 1) //Plain number in bytes |
201 |
return num;
|
202 |
|
203 |
switch (*unit) {
|
204 |
case 'g': |
205 |
case 'G': |
206 |
num *= 1024;
|
207 |
case 'm': |
208 |
case 'M': |
209 |
num *= 1024;
|
210 |
case 'k': |
211 |
case 'K': |
212 |
num *= 1024;
|
213 |
break;
|
214 |
default:
|
215 |
num = 0;
|
216 |
} |
217 |
return num;
|
218 |
} |
219 |
|
220 |
/*
|
221 |
* Converts struct timespec to double (units in nanoseconds)
|
222 |
*/
|
223 |
int read_insanity(char *insanity) |
224 |
{ |
225 |
if (strncmp(insanity, "sane", MAX_ARG_LEN + 1) == 0) |
226 |
return INSANITY_SANE;
|
227 |
if (strncmp(insanity, "eccentric", MAX_ARG_LEN + 1) == 0) |
228 |
return INSANITY_ECCENTRIC;
|
229 |
if (strncmp(insanity, "manic", MAX_ARG_LEN + 1) == 0) |
230 |
return INSANITY_MANIC;
|
231 |
if (strncmp(insanity, "paranoid", MAX_ARG_LEN + 1) == 0) |
232 |
return INSANITY_PARANOID;
|
233 |
return -1; |
234 |
} |
235 |
|
236 |
int read_op(char *op) |
237 |
{ |
238 |
if (strncmp(op, "read", MAX_ARG_LEN + 1) == 0) |
239 |
return X_READ;
|
240 |
if (strncmp(op, "write", MAX_ARG_LEN + 1) == 0) |
241 |
return X_WRITE;
|
242 |
if (strncmp(op, "info", MAX_ARG_LEN + 1) == 0) |
243 |
return X_INFO;
|
244 |
if (strncmp(op, "delete", MAX_ARG_LEN + 1) == 0) |
245 |
return X_DELETE;
|
246 |
return -1; |
247 |
} |
248 |
|
249 |
int read_verify(char *verify) |
250 |
{ |
251 |
if (strncmp(verify, "no", MAX_ARG_LEN + 1) == 0) |
252 |
return VERIFY_NO;
|
253 |
if (strncmp(verify, "meta", MAX_ARG_LEN + 1) == 0) |
254 |
return VERIFY_META;
|
255 |
if (strncmp(verify, "full", MAX_ARG_LEN + 1) == 0) |
256 |
return VERIFY_FULL;
|
257 |
return -1; |
258 |
} |
259 |
|
260 |
int read_progress(char *progress) |
261 |
{ |
262 |
if (strncmp(progress, "no", MAX_ARG_LEN + 1) == 0) |
263 |
return PROGRESS_NO;
|
264 |
if (strncmp(progress, "yes", MAX_ARG_LEN + 1) == 0) |
265 |
return PROGRESS_YES;
|
266 |
return -1; |
267 |
} |
268 |
|
269 |
int read_pattern(char *pattern) |
270 |
{ |
271 |
if (strncmp(pattern, "seq", MAX_ARG_LEN + 1) == 0) |
272 |
return PATTERN_SEQ;
|
273 |
if (strncmp(pattern, "rand", MAX_ARG_LEN + 1) == 0) |
274 |
return PATTERN_RAND;
|
275 |
return -1; |
276 |
} |
277 |
|
278 |
/*******************\
|
279 |
* Print functions *
|
280 |
\*******************/
|
281 |
|
282 |
void print_io_stats(struct bench *prefs, double elapsed) |
283 |
{ |
284 |
struct bw bw;
|
285 |
double iops;
|
286 |
|
287 |
/*
|
288 |
* We could malloc struct bw in __calculate_bw, but it's safer in cases when
|
289 |
* there is no memory left.
|
290 |
*/
|
291 |
iops = __calculate_iops(prefs, elapsed); |
292 |
__calculate_bw(prefs, iops, &bw); |
293 |
|
294 |
fprintf(stdout, " ~~~~~~~~~~~~~~~~~~~~~~~~\n");
|
295 |
fprintf(stdout, "Bandwidth: %.3lf %s\n", bw.val, bw.unit);
|
296 |
fprintf(stdout, "IOPS: %.3lf\n", iops);
|
297 |
fflush(stdout); |
298 |
} |
299 |
|
300 |
void print_stats(struct bench *prefs) |
301 |
{ |
302 |
fprintf(stdout, "\n"
|
303 |
"Requests total: %10lu\n"
|
304 |
"Requests submitted: %10lu\n"
|
305 |
"Requests received: %10lu\n"
|
306 |
"Requests failed: %10lu\n",
|
307 |
prefs->status->max, |
308 |
prefs->status->submitted, |
309 |
prefs->status->received, |
310 |
prefs->status->failed); |
311 |
if ((prefs->op == X_READ) && (GET_FLAG(VERIFY, prefs->flags) != VERIFY_NO))
|
312 |
fprintf(stdout, "Requests corrupted: %10lu\n", prefs->status->corrupted);
|
313 |
fprintf(stdout, "\n");
|
314 |
fflush(stdout); |
315 |
} |
316 |
|
317 |
void print_remaining(struct bench *prefs) |
318 |
{ |
319 |
uint64_t remaining; |
320 |
|
321 |
remaining = prefs->status->max - prefs->status->received; |
322 |
if (remaining)
|
323 |
fprintf(stdout, "Requests remaining: %10lu\n", remaining);
|
324 |
else
|
325 |
fprintf(stdout, "All requests have been served.\n");
|
326 |
fflush(stdout); |
327 |
} |
328 |
|
329 |
void print_res(struct bench *prefs, struct timer *tm, char *type) |
330 |
{ |
331 |
struct tm_result res;
|
332 |
double sum;
|
333 |
|
334 |
sum = __timespec2double(tm->sum); |
335 |
res = __separate_by_order(sum); |
336 |
|
337 |
fprintf(stdout, "\n");
|
338 |
fprintf(stdout, " %s\n", type);
|
339 |
fprintf(stdout, " ========================\n");
|
340 |
fprintf(stdout, " |-s-||-ms-|-us-|-ns-|\n");
|
341 |
fprintf(stdout, "Total time: %3u. %03u %03u %03u\n",
|
342 |
res.s, res.ms, res.us, res.ns); |
343 |
fflush(stdout); |
344 |
|
345 |
if (!prefs->status->received)
|
346 |
return;
|
347 |
|
348 |
res = __separate_by_order(sum / prefs->status->received); |
349 |
|
350 |
fprintf(stdout, "Mean Time: %3u. %03u %03u %03u\n",
|
351 |
res.s, res.ms, res.us, res.ns); |
352 |
fflush(stdout); |
353 |
|
354 |
//TODO: Add std
|
355 |
|
356 |
print_io_stats(prefs, sum); |
357 |
} |
358 |
|
359 |
void print_progress(struct bench *prefs) |
360 |
{ |
361 |
int lines = 6; |
362 |
|
363 |
if ((prefs->op == X_READ) && (GET_FLAG(VERIFY, prefs->flags) != VERIFY_NO))
|
364 |
lines++; |
365 |
|
366 |
fprintf(stdout, "\033[%dA\033[J", lines);
|
367 |
print_stats(prefs); |
368 |
} |
369 |
|
370 |
/**************************\
|
371 |
* Benchmarking functions *
|
372 |
\**************************/
|
373 |
|
374 |
void create_id(unsigned long seed) |
375 |
{ |
376 |
if (seed > pow(10, 9)) |
377 |
XSEGLOG2(&lc, W, "Seed larger than 10^9, only its first 9 digits will "
|
378 |
"be used\n");
|
379 |
|
380 |
//nanoseconds can't be more than 9 digits
|
381 |
snprintf(global_id, IDLEN + 1, "bench-%09lu", seed); |
382 |
} |
383 |
|
384 |
void create_target(struct bench *prefs, struct xseg_request *req, |
385 |
uint64_t new) |
386 |
{ |
387 |
struct xseg *xseg = prefs->peer->xseg;
|
388 |
char *req_target;
|
389 |
char buf[TARGETLEN + 1]; |
390 |
|
391 |
req_target = xseg_get_target(xseg, req); |
392 |
|
393 |
//For read/write, the target object may not correspond to `new`, which is
|
394 |
//actually the chunk number.
|
395 |
new = __get_object(prefs, new); |
396 |
snprintf(buf, TARGETLEN + 1, "%s-%016lu", global_id, new); |
397 |
strncpy(req_target, buf, TARGETLEN); |
398 |
XSEGLOG2(&lc, D, "Target name of request is %s\n", buf);
|
399 |
} |
400 |
|
401 |
|
402 |
uint64_t determine_next(struct bench *prefs)
|
403 |
{ |
404 |
if (GET_FLAG(PATTERN, prefs->flags) == PATTERN_SEQ)
|
405 |
return prefs->status->submitted;
|
406 |
else
|
407 |
return lfsr_next(prefs->lfsr);
|
408 |
} |
409 |
|
410 |
uint64_t calculate_offset(struct bench *prefs, uint64_t new)
|
411 |
{ |
412 |
if (prefs->ts > 0) |
413 |
return (new * prefs->bs) % prefs->os;
|
414 |
else
|
415 |
return 0; |
416 |
} |
417 |
|
418 |
uint64_t calculate_prog_quantum(struct bench *prefs)
|
419 |
{ |
420 |
return round((double)prefs->status->max / 20.0); |
421 |
} |
422 |
|
423 |
|
424 |
/*
|
425 |
* ***********************************************
|
426 |
* `create_chunk` handles 3 identifiers:
|
427 |
* 1. The benchmark's global_id
|
428 |
* 2. The object's number
|
429 |
* 3. The chunk offset in the object
|
430 |
*
|
431 |
* ************************************************
|
432 |
* `_create_chunk_full` takes the above 3 identifiers and feeds them as seeds
|
433 |
* in 63-bit LFSRs. The numbers generated are written consecutively in chunk's
|
434 |
* memory range. For example, for a 72-byte chunk:
|
435 |
*
|
436 |
* || 1 | 2 | 3 | 1 | 2 | 3 | 1 | 2 | 3 ||
|
437 |
* ^ 8 16 24 32 40 48 56 64 ^
|
438 |
* | |
|
439 |
* | |
|
440 |
* start end
|
441 |
*
|
442 |
* 1,2,3 differ between each iteration
|
443 |
*
|
444 |
* **************************************************
|
445 |
* `_create_chunk_meta` simply writes the above 3 ids in the start and end of
|
446 |
* the chunk's memory range, so it should be much faster (but less safe)
|
447 |
*
|
448 |
* **************************************************
|
449 |
* In both cases, special care is taken not to exceed the chunk's memory range.
|
450 |
* Also, the bare minimum chunk to verify should be 48 bytes. This limit is set
|
451 |
* by _create_chunk_meta, which expects to write in a memory at least this big.
|
452 |
*/
|
453 |
static int _readwrite_chunk_full(struct xseg *xseg, struct xseg_request *req, |
454 |
uint64_t id, uint64_t object) |
455 |
{ |
456 |
struct bench_lfsr id_lfsr;
|
457 |
struct bench_lfsr obj_lfsr;
|
458 |
struct bench_lfsr off_lfsr;
|
459 |
uint64_t *d = (uint64_t *)xseg_get_data(xseg, req); |
460 |
uint64_t s = req->size; |
461 |
|
462 |
/* Create 63-bit LFSRs */
|
463 |
lfsr_init(&id_lfsr, 0x7FFFFFFF, id, 0); |
464 |
lfsr_init(&obj_lfsr, 0x7FFFFFFF, object, 0); |
465 |
lfsr_init(&off_lfsr, 0x7FFFFFFF, req->offset, 0); |
466 |
|
467 |
if (s < sizeof(struct signature)) { |
468 |
XSEGLOG2(&lc, E, "Too small chunk size (%lu butes). Leaving.", s);
|
469 |
return 1; |
470 |
} |
471 |
|
472 |
/*
|
473 |
* Every write operation has its read counterpart which, if it finds any
|
474 |
* corruption, returns 1
|
475 |
*/
|
476 |
|
477 |
if (req->op == X_WRITE) {
|
478 |
__write_sig(&id_lfsr, d, s, 0);
|
479 |
__write_sig(&obj_lfsr, d, s, 1);
|
480 |
__write_sig(&off_lfsr, d, s, 2);
|
481 |
} else {
|
482 |
if (__read_sig(&id_lfsr, d, s, 0)) |
483 |
return 1; |
484 |
if (__read_sig(&obj_lfsr, d, s, 1)) |
485 |
return 1; |
486 |
if(__read_sig(&off_lfsr, d, s, 2)) |
487 |
return 1; |
488 |
} |
489 |
|
490 |
return 0; |
491 |
} |
492 |
|
493 |
static int _readwrite_chunk_meta(struct xseg *xseg, struct xseg_request *req, |
494 |
uint64_t id, uint64_t object) |
495 |
{ |
496 |
char *d = xseg_get_data(xseg, req);
|
497 |
uint64_t s = req->size; |
498 |
struct signature sig;
|
499 |
int sig_s = sizeof(struct signature); |
500 |
int r = 0; |
501 |
|
502 |
sig.id = id; |
503 |
sig.object = object; |
504 |
sig.offset = req->offset; |
505 |
|
506 |
if (s < sig_s) {
|
507 |
XSEGLOG2(&lc, E, "Too small chunk size (%lu butes). Leaving.", s);
|
508 |
return 1; |
509 |
} |
510 |
|
511 |
//PRINT_SIG(expected, (&sig));
|
512 |
/* Read/Write chunk signature both at its start and at its end */
|
513 |
if (req->op == X_WRITE) {
|
514 |
memcpy(d, &sig, sig_s); |
515 |
memcpy(d + s - sig_s, &sig, sig_s); |
516 |
} else {
|
517 |
if (memcmp(d, &sig, sig_s))
|
518 |
r = 1;
|
519 |
else if (memcmp(d + s - sig_s, &sig, sig_s)) |
520 |
r = 1;
|
521 |
} |
522 |
//PRINT_SIG(start, d);
|
523 |
//PRINT_SIG(end, (d + s - sig_s));
|
524 |
return r;
|
525 |
} |
526 |
|
527 |
/*
|
528 |
* We want these functions to be as fast as possible in case we haven't asked
|
529 |
* for verification
|
530 |
* TODO: Make them prettier but keep the speed of this implementation
|
531 |
*/
|
532 |
void create_chunk(struct bench *prefs, struct xseg_request *req, uint64_t new) |
533 |
{ |
534 |
struct xseg *xseg = prefs->peer->xseg;
|
535 |
uint64_t id; |
536 |
uint64_t object; |
537 |
int verify;
|
538 |
|
539 |
verify = GET_FLAG(VERIFY, prefs->flags); |
540 |
switch (verify) {
|
541 |
case VERIFY_NO:
|
542 |
break;
|
543 |
case VERIFY_META:
|
544 |
id = __get_id(); |
545 |
object = __get_object(prefs, new); |
546 |
_readwrite_chunk_meta(xseg, req, id, object); |
547 |
break;
|
548 |
case VERIFY_FULL:
|
549 |
id = __get_id(); |
550 |
object = __get_object(prefs, new); |
551 |
_readwrite_chunk_full(xseg, req, id, object); |
552 |
break;
|
553 |
default:
|
554 |
XSEGLOG2(&lc, W, "Unexpected verification mode: %d\n", verify);
|
555 |
} |
556 |
} |
557 |
|
558 |
int read_chunk(struct bench *prefs, struct xseg_request *req) |
559 |
{ |
560 |
struct xseg *xseg = prefs->peer->xseg;
|
561 |
uint64_t id; |
562 |
uint64_t object; |
563 |
char *target;
|
564 |
int verify;
|
565 |
int r = 0; |
566 |
|
567 |
verify = GET_FLAG(VERIFY, prefs->flags); |
568 |
switch (verify) {
|
569 |
case VERIFY_NO:
|
570 |
break;
|
571 |
case VERIFY_META:
|
572 |
id = __get_id(); |
573 |
target = xseg_get_target(xseg, req); |
574 |
object = __get_object_from_name(target); |
575 |
r = _readwrite_chunk_meta(xseg, req, id, object); |
576 |
break;
|
577 |
case VERIFY_FULL:
|
578 |
id = __get_id(); |
579 |
target = xseg_get_target(xseg, req); |
580 |
object = __get_object_from_name(target); |
581 |
r = _readwrite_chunk_full(xseg, req, id, object); |
582 |
break;
|
583 |
default:
|
584 |
XSEGLOG2(&lc, W, "Unexpected verification mode: %d\n", verify);
|
585 |
} |
586 |
return r;
|
587 |
} |