2 * Copyright 2012 GRNET S.A. All rights reserved.
4 * Redistribution and use in source and binary forms, with or
5 * without modification, are permitted provided that the following
8 * 1. Redistributions of source code must retain the above
9 * copyright notice, this list of conditions and the following
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.
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.
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.
42 #include <sys/types.h>
46 #include <xtypes/xhash.h>
47 #include <xtypes/xobj.h>
48 #include <xseg/xseg.h>
49 #include <xseg/protocol.h>
52 printf("xseg <spec> [[[<src_port>]:[<dst_port>]] [<command> <arg>*] ]*\n"
54 " <type:name:nr_ports:nr_requests:request_size:extra_size:page_shift>\n"
61 " bridge <portno1> <portno2> <logfile> {full|summary|stats}\n"
64 " alloc_requests (to source) <nr>\n"
65 " free_requests (from source) <nr>\n"
66 " put_requests (all from dest)\n"
67 " put_replies (all from dest)\n"
68 " wait <nr_replies>\n"
69 " complete <nr_requests>\n"
70 " fail <nr_requests>\n"
71 " rndwrite <nr_loops> <seed> <targetlen> <datalen> <objectsize>\n"
72 " rndread <nr_loops> <seed> <targetlen> <datalen> <objectsize>\n"
73 " submit_reqs <nr_loops> <concurrent_reqs>\n"
75 " read <target> <offset> <size>\n"
76 " write <target> <offset> < data\n"
77 " truncate <target> <size>\n"
82 " clone <src> <dst>\n"
102 struct xseg_config cfg;
104 uint32_t srcport, dstport;
106 #define mkname mkname_heavy
107 /* heavy distributes duplicates much more widely than light
108 * ./xseg-tool random 100000 | cut -d' ' -f2- | sort | uniq -d -c |wc -l
111 xport sport = NoPort;
112 static void init_local_signal()
114 if (xseg && sport != srcport){
115 xseg_init_local_signal(xseg, srcport);
120 void mkname_heavy(char *name, uint32_t namelen, uint32_t seed)
124 for (i = 0; i < namelen; i += 1) {
125 c = seed + (seed >> 8) + (seed >> 16) + (seed >> 24);
126 c = '0' + ((c + (c >> 4)) & 0xf);
130 seed *= ((seed % 137911) | 1) * 137911;
134 void mkname_light(char *name, uint32_t namelen, uint32_t seed)
138 for (i = 0; i < namelen; i += 1) {
140 name[i] = 'A' + (c & 0xf);
145 uint64_t pick(uint64_t size)
147 return (uint64_t)((double)(RAND_MAX) / random());
150 void mkchunk( char *chunk, uint32_t datalen,
151 char *target, uint32_t targetlen, uint64_t offset)
153 long i, r, bufsize = targetlen + 16;
155 r = datalen % bufsize;
156 snprintf(buf, bufsize, "%016llx%s", (unsigned long long)offset, target);
158 for (i = 0; i <= (long)datalen - bufsize; i += bufsize)
159 memcpy(chunk + i, buf, bufsize);
161 memcpy(chunk + datalen - r, buf, r);
164 int chkchunk( char *chunk, uint32_t datalen,
165 char *target, uint32_t targetlen, uint64_t offset)
168 int bufsize = targetlen + 16;
170 r = datalen % targetlen;
171 snprintf(buf, bufsize, "%016llx%s", (unsigned long long)offset, target);
173 for (i = 0; i <= (long)datalen - bufsize; i += bufsize)
174 if (memcmp(chunk + i, buf, bufsize)) {
175 /*printf("mismatch: '%*s'* vs '%*s'\n",
176 bufsize, buf, datalen, chunk);
181 if (memcmp(chunk + datalen - r, buf, r))
188 #define ALLOC_MIN 4096
189 #define ALLOC_MAX 1048576
191 void inputbuf(FILE *fp, char **retbuf, uint64_t *retsize)
193 static uint64_t alloc_size;
199 if (alloc_size < ALLOC_MIN)
200 alloc_size = ALLOC_MIN;
202 if (alloc_size > ALLOC_MAX)
203 alloc_size = ALLOC_MAX;
205 p = realloc(buf, alloc_size);
216 r = fread(buf + size, 1, alloc_size - size, fp);
220 if (size >= alloc_size) {
221 p = realloc(buf, alloc_size * 2);
239 void report_request(struct xseg_request *req)
241 char target[64], data[64];
242 char *req_target, *req_data;
243 unsigned int end = (req->targetlen> 63) ? 63 : req->targetlen;
244 req_target = xseg_get_target(xseg, req);
245 req_data = xseg_get_data(xseg, req);
247 strncpy(target, req_target, end);
249 strncpy(data, req_data, 63);
252 "Request %lx: target[%u](xptr: %llu): %s, data[%llu](xptr: %llu): %s \n\t"
253 "offset: %llu, size: %llu, serviced; %llu, op: %u, state: %u, flags: %u \n\t"
254 "src: %u, transit: %u, dst: %u, effective dst: %u\n",
255 (unsigned long) req, req->targetlen, (unsigned long long)req->target,
257 (unsigned long long) req->datalen, (unsigned long long) req->data,
259 (unsigned long long) req->offset, (unsigned long long) req->size,
260 (unsigned long long) req->serviced, req->op, req->state, req->flags,
261 (unsigned int) req->src_portno, (unsigned int) req->transit_portno,
262 (unsigned int) req->dst_portno, (unsigned int) req->effective_dst_portno);
267 int cmd_info(char *target)
269 uint32_t targetlen = strlen(target);
270 size_t size = sizeof(uint64_t);
273 struct xseg_request *req;
276 req = xseg_get_request(xseg, srcport, dstport, X_ALLOC);
278 fprintf(stderr, "No request!\n");
282 r = xseg_prep_request(xseg, req, targetlen, size);
284 fprintf(stderr, "Cannot prepare request! (%lu, %lu)\n",
285 (unsigned long) targetlen, (unsigned long) size);
286 xseg_put_request(xseg, req, srcport);
290 req_target = xseg_get_target(xseg, req);
291 strncpy(req_target, target, targetlen);
296 p = xseg_submit(xseg, req, srcport, X_ALLOC);
300 xseg_signal(xseg, p);
305 int cmd_read(char *target, uint64_t offset, uint64_t size)
307 uint32_t targetlen = strlen(target);
311 struct xseg_request *req = xseg_get_request(xseg, srcport, dstport, X_ALLOC);
313 fprintf(stderr, "No request\n");
317 r = xseg_prep_request(xseg, req, targetlen, size);
319 fprintf(stderr, "Cannot prepare request! (%lu, %llu)\n",
320 (unsigned long)targetlen, (unsigned long long)size);
321 xseg_put_request(xseg, req, srcport);
325 req_target = xseg_get_target(xseg, req);
326 strncpy(req_target, target, targetlen);
327 req->offset = offset;
331 p = xseg_submit(xseg, req, srcport, X_ALLOC);
335 xseg_signal(xseg, p);
339 int cmd_write(char *target, uint64_t offset)
345 char *req_target, *req_data;
346 uint32_t targetlen = strlen(target);
347 struct xseg_request *req;
349 inputbuf(stdin, &buf, &size);
351 fprintf(stderr, "No input\n");
355 req = xseg_get_request(xseg, srcport, dstport, X_ALLOC);
357 fprintf(stderr, "No request\n");
361 r = xseg_prep_request(xseg, req, targetlen, size);
363 fprintf(stderr, "Cannot prepare request! (%lu, %llu)\n",
364 (unsigned long)targetlen, (unsigned long long)size);
365 xseg_put_request(xseg, req, srcport);
369 req_target = xseg_get_target(xseg, req);
370 strncpy(req_target, target, targetlen);
372 req_data = xseg_get_data(xseg, req);
373 memcpy(req_data, buf, size);
374 req->offset = offset;
378 p = xseg_submit(xseg, req, srcport, X_ALLOC);
380 fprintf(stderr, "Cannot submit\n");
383 xseg_signal(xseg, p);
388 int cmd_truncate(char *target, uint64_t offset)
393 int cmd_delete(char *target)
395 uint32_t targetlen = strlen(target);
397 struct xseg_request *req;
399 xseg_bind_port(xseg, srcport, NULL);
401 req = xseg_get_request(xseg, srcport, dstport, X_ALLOC);
403 fprintf(stderr, "No request!\n");
407 r = xseg_prep_request(xseg, req, targetlen, 0);
409 fprintf(stderr, "Cannot prepare request! (%lu, %lu)\n",
410 (unsigned long) targetlen, (unsigned long) req->bufferlen - targetlen);
411 xseg_put_request(xseg, req, srcport);
415 char *reqtarget = xseg_get_target(xseg, req);
416 strncpy(reqtarget, target, targetlen);
419 xport p = xseg_submit(xseg, req, srcport, X_ALLOC);
421 fprintf(stderr, "Couldn't submit request\n");
422 xseg_put_request(xseg, req, srcport);
426 xseg_signal(xseg, p);
431 int cmd_acquire(char *target)
433 uint32_t targetlen = strlen(target);
437 struct xseg_request *req = xseg_get_request(xseg, srcport, dstport, X_ALLOC);
439 fprintf(stderr, "No request\n");
443 r = xseg_prep_request(xseg, req, targetlen, 0);
445 fprintf(stderr, "Cannot prepare request! (%lu, 0)\n",
446 (unsigned long)targetlen);
447 xseg_put_request(xseg, req, srcport);
451 req_target = xseg_get_target(xseg, req);
452 strncpy(req_target, target, targetlen);
456 p = xseg_submit(xseg, req, srcport, X_ALLOC);
460 xseg_signal(xseg, p);
464 int cmd_release(char *target)
466 uint32_t targetlen = strlen(target);
470 struct xseg_request *req = xseg_get_request(xseg, srcport, dstport, X_ALLOC);
472 fprintf(stderr, "No request\n");
476 r = xseg_prep_request(xseg, req, targetlen, 0);
478 fprintf(stderr, "Cannot prepare request! (%lu, 0)\n",
479 (unsigned long)targetlen);
480 xseg_put_request(xseg, req, srcport);
484 req_target = xseg_get_target(xseg, req);
485 strncpy(req_target, target, targetlen);
489 req->flags = XF_FORCE;
490 p = xseg_submit(xseg, req, srcport, X_ALLOC);
494 xseg_signal(xseg, p);
499 int cmd_copy(char *src, char *dst)
501 uint32_t targetlen = strlen(dst);
502 uint32_t parentlen = strlen(src);
503 struct xseg_request *req;
504 struct xseg_request_copy *xcopy;
505 req = xseg_get_request(xseg, srcport, dstport, X_ALLOC);
507 fprintf(stderr, "No request\n");
511 int r = xseg_prep_request(xseg, req, targetlen,
512 sizeof(struct xseg_request_copy));
514 fprintf(stderr, "Cannot prepare request!\n");
515 xseg_put_request(xseg, req, srcport);
519 char *target = xseg_get_target(xseg, req);
520 char *data = xseg_get_data(xseg, req);
522 strncpy(target, dst, targetlen);
523 xcopy = (struct xseg_request_copy *) data;
524 strncpy(xcopy->target, src, parentlen);
525 xcopy->targetlen = parentlen;
527 req->size = sizeof(struct xseg_request_copy);
530 xport p = xseg_submit(xseg, req, srcport, X_ALLOC);
532 fprintf(stderr, "Cannot submit request\n");
535 xseg_signal(xseg, p);
541 int cmd_clone(char *src, char *dst)
544 uint32_t targetlen = strlen(dst);
545 uint32_t parentlen = strlen(src);
546 struct xseg_request *req;
547 struct xseg_request_clone *xclone;
548 xseg_bind_port(xseg, srcport, NULL);
549 req = xseg_get_request(xseg, srcport, dstport, X_ALLOC);
551 fprintf(stderr, "No request\n");
555 int r = xseg_prep_request(xseg, req, targetlen, sizeof(struct xseg_request_clone));
557 fprintf(stderr, "Cannot prepare request!\n");
558 xseg_put_request(xseg, req, srcport);
562 char *target = xseg_get_target(xseg, req);
563 char *data = xseg_get_data(xseg, req);
565 strncpy(target, dst, targetlen);
566 xclone = (struct xseg_request_clone *) data;
567 strncpy(xclone->target, src, parentlen);
568 xclone->targetlen = parentlen;
571 req->size = sizeof(struct xseg_request_clone);
574 xport p = xseg_submit(xseg, req, srcport, X_ALLOC);
576 fprintf(stderr, "Cannot submit request\n");
579 xseg_signal(xseg, p);
584 int cmd_snapshot(char *src, char *dst, long block_size)
587 uint32_t targetlen = strlen(src);
588 uint32_t parentlen = strlen(dst);
589 struct xseg_request *req;
590 struct xseg_request_snapshot *xsnapshot;
591 xseg_bind_port(xseg, srcport, NULL);
592 req = xseg_get_request(xseg, srcport, dstport, X_ALLOC);
594 fprintf(stderr, "No request\n");
598 int r = xseg_prep_request(xseg, req, targetlen, sizeof(struct xseg_request_snapshot));
600 fprintf(stderr, "Cannot prepare request!\n");
601 xseg_put_request(xseg, req, srcport);
605 char *target = xseg_get_target(xseg, req);
606 char *data = xseg_get_data(xseg, req);
608 strncpy(target, src, targetlen);
609 xsnapshot = (struct xseg_request_snapshot *) data;
610 strncpy(xsnapshot->target, dst, parentlen);
611 xsnapshot->targetlen = parentlen;
613 req->size = (uint64_t) block_size;
614 req->op = X_SNAPSHOT;
616 xport p = xseg_submit(xseg, req, srcport, X_ALLOC);
618 fprintf(stderr, "Cannot submit request\n");
621 xseg_signal(xseg, p);
626 void log_req(int logfd, uint32_t portno2, uint32_t portno1, int op, int method,
627 struct xseg_request *req)
630 char target[64], data[64];
631 char *req_target, *req_data;
632 /* null terminate name in case of req->target is less than 63 characters,
633 * and next character after name (aka first byte of next buffer) is not
636 unsigned int end = (req->targetlen > 63) ? 63 : req->targetlen;
638 req_target = xseg_get_target(xseg, req);
639 req_data = xseg_get_data(xseg, req);
641 logfp = fdopen(logfd, "a");
647 strncpy(target, req_target, end);
649 strncpy(data, req_data, 63);
653 "src port: %u, dst port: %u, op:%u offset: %llu size: %lu, reqstate: %u\n"
654 "target[%u]: '%s', data[%llu]:\n%s------------------\n\n",
655 (unsigned int)portno1,
656 (unsigned int)portno2,
657 (unsigned int)req->op,
658 (unsigned long long)req->offset,
659 (unsigned long)req->size,
660 (unsigned int)req->state,
661 (unsigned int)req->targetlen, target,
662 (unsigned long long)req->datalen, data);
666 "src port: %u, dst port: %u, op: %u\n",
667 (unsigned int)portno1,
668 (unsigned int)portno2,
669 (unsigned int)req->op);
672 fprintf(logfp, "src port: %u, dst port: %u, reqs: %llu\n",
673 (unsigned int)portno1,
674 (unsigned int)portno2,
675 (unsigned long long)++reqs);
683 #define LOG_RECEIVE 1
685 int cmd_bridge(uint32_t portno1, uint32_t portno2, char *logfile, char *how)
687 struct xseg_request *req;
689 if (!strcmp(logfile, "-"))
692 logfd = open(logfile, O_WRONLY|O_APPEND|O_CREAT, 0600);
699 if (!strcmp(how, "full"))
701 else if (!strcmp(how, "summary"))
707 int reloop = 0, active;
708 xseg_prepare_wait(xseg, portno1);
709 xseg_prepare_wait(xseg, portno2);
716 req = xseg_accept(xseg, portno1, 0);
718 xseg_submit(xseg, req, portno2, X_ALLOC);
719 log_req(logfd, portno1, portno2, LOG_ACCEPT, method, req);
723 req = xseg_accept(xseg, portno2, 0);
725 xseg_submit(xseg, req, portno1, X_ALLOC);
726 log_req(logfd, portno2, portno1, LOG_ACCEPT, method, req);
730 req = xseg_receive(xseg, portno1, 0);
732 xseg_respond(xseg, req, portno2, X_ALLOC);
733 log_req(logfd, portno1, portno2, LOG_RECEIVE, method, req);
737 req = xseg_receive(xseg, portno2, 0);
739 xseg_respond(xseg, req, portno1, X_ALLOC);
740 log_req(logfd, portno2, portno1, LOG_RECEIVE, method, req);
747 /* wait on multiple queues? */
748 xseg_wait_signal(xseg, 100000);
751 xseg_cancel_wait(xseg, portno1);
752 xseg_cancel_wait(xseg, portno2);
763 int cmd_rndwrite(long loops, int32_t seed, uint32_t targetlen, uint32_t chunksize, uint64_t size)
768 if (targetlen >= chunksize) {
769 fprintf(stderr, "targetlen >= chunksize\n");
773 char *p = realloc(namebuf, targetlen+1);
775 fprintf(stderr, "Cannot allocate memory\n");
780 p = realloc(chunk, chunksize);
782 fprintf(stderr, "Cannot allocate memory\n");
786 memset(chunk, 0, chunksize);
790 struct xseg_request *submitted = NULL, *received;
791 long nr_submitted = 0, nr_received = 0, nr_failed = 0;
795 char *req_data, *req_target;
800 xseg_prepare_wait(xseg, srcport);
801 if (nr_submitted < loops &&
802 (submitted = xseg_get_request(xseg, srcport, dstport, X_ALLOC))) {
803 xseg_cancel_wait(xseg, srcport);
804 r = xseg_prep_request(xseg, submitted, targetlen, chunksize);
806 fprintf(stderr, "Cannot prepare request! (%u, %u)\n",
807 targetlen, chunksize);
808 xseg_put_request(xseg, submitted, srcport);
812 req_target = xseg_get_target(xseg, submitted);
813 req_data = xseg_get_data(xseg, submitted);
816 mkname(namebuf, targetlen, seed);
817 namebuf[targetlen] = 0;
818 //printf("%ld: %s\n", nr_submitted, namebuf);
819 strncpy(req_target, namebuf, targetlen);
820 offset = 0;// pick(size);
821 mkchunk(req_data, chunksize, namebuf, targetlen, offset);
823 submitted->offset = offset;
824 submitted->size = chunksize;
825 submitted->op = X_WRITE;
826 submitted->flags |= XF_NOSYNC;
828 port = xseg_submit(xseg, submitted, srcport, X_ALLOC);
829 if (port == NoPort) {
830 xseg_put_request(xseg, submitted, srcport);
834 xseg_signal(xseg, port);
838 received = xseg_receive(xseg, srcport, 0);
840 xseg_cancel_wait(xseg, srcport);
842 if (!(received->state & XS_SERVED)) {
844 report_request(received);
846 if (xseg_put_request(xseg, received, srcport))
847 fprintf(stderr, "Cannot put request at port %u\n", received->src_portno);
850 if (!submitted && !received)
851 xseg_wait_signal(xseg, 1000000);
853 if (nr_submitted % 1000 == 0 && !reported) {
855 fprintf(stderr, "submitted %ld, received %ld, failed %ld\n",
856 nr_submitted, nr_received, nr_failed);
859 if (nr_received >= loops)
863 fprintf(stderr, "submitted %ld, received %ld, failed %ld\n",
864 nr_submitted, nr_received, nr_failed);
868 int cmd_rnddelete(long loops, int32_t seed, uint32_t targetlen)
872 char *p = realloc(namebuf, targetlen+1);
874 fprintf(stderr, "Cannot allocate memory\n");
881 struct xseg_request *submitted = NULL, *received;
882 long nr_submitted = 0, nr_received = 0, nr_failed = 0;
890 xseg_prepare_wait(xseg, srcport);
891 if (nr_submitted < loops &&
892 (submitted = xseg_get_request(xseg, srcport, dstport, X_ALLOC))) {
893 xseg_cancel_wait(xseg, srcport);
894 r = xseg_prep_request(xseg, submitted, targetlen, 0);
896 fprintf(stderr, "Cannot prepare request! (%u, %u)\n",
898 xseg_put_request(xseg, submitted, srcport);
902 req_target = xseg_get_target(xseg, submitted);
905 mkname(namebuf, targetlen, seed);
906 namebuf[targetlen] = 0;
907 //printf("%ld: %s\n", nr_submitted, namebuf);
908 strncpy(req_target, namebuf, targetlen);
909 submitted->offset = 0;
911 submitted->op = X_DELETE;
912 submitted->flags = 0;
914 port = xseg_submit(xseg, submitted, srcport, X_ALLOC);
915 if (port == NoPort) {
916 xseg_put_request(xseg, submitted, srcport);
920 xseg_signal(xseg, port);
924 received = xseg_receive(xseg, srcport, 0);
926 xseg_cancel_wait(xseg, srcport);
928 if (!(received->state & XS_SERVED)) {
930 report_request(received);
932 if (xseg_put_request(xseg, received, srcport))
933 fprintf(stderr, "Cannot put request at port %u\n", received->src_portno);
936 if (!submitted && !received)
937 xseg_wait_signal(xseg, 1000000);
939 if (nr_submitted % 1000 == 0 && !reported) {
941 fprintf(stderr, "submitted %ld, received %ld, failed %ld\n",
942 nr_submitted, nr_received, nr_failed);
945 if (nr_received >= loops)
949 fprintf(stderr, "submitted %ld, received %ld, failed %ld\n",
950 nr_submitted, nr_received, nr_failed);
954 * prepare/wait rhythm,
955 * files are converted to independent chunk access patterns,
958 int cmd_rndread(long loops, int32_t seed, uint32_t targetlen, uint32_t chunksize, uint64_t size)
963 if (targetlen >= chunksize) {
964 fprintf(stderr, "targetlen >= chunksize\n");
968 char *p = realloc(namebuf, targetlen+1);
970 fprintf(stderr, "Cannot allocate memory\n");
975 p = realloc(chunk, chunksize);
977 fprintf(stderr, "Cannot allocate memory\n");
981 memset(chunk, 0, chunksize);
985 struct xseg_request *submitted = NULL, *received;
986 long nr_submitted = 0, nr_received = 0, nr_failed = 0, nr_mismatch = 0;
990 char *req_data, *req_target;
996 xseg_prepare_wait(xseg, srcport);
997 if (nr_submitted < loops &&
998 (submitted = xseg_get_request(xseg, srcport, dstport, X_ALLOC))) {
999 xseg_cancel_wait(xseg, srcport);
1000 r = xseg_prep_request(xseg, submitted, targetlen, chunksize);
1002 fprintf(stderr, "Cannot prepare request! (%u, %u)\n",
1003 targetlen, chunksize);
1004 xseg_put_request(xseg, submitted, srcport);
1008 req_target = xseg_get_target(xseg, submitted);
1010 mkname(namebuf, targetlen, seed);
1011 namebuf[targetlen] = 0;
1012 //printf("%ld: %s\n", nr_submitted, namebuf);
1013 offset = 0;//pick(size);
1015 strncpy(req_target, namebuf, targetlen);
1016 submitted->offset = offset;
1017 submitted->size = chunksize;
1018 submitted->op = X_READ;
1019 port = xseg_submit(xseg, submitted, srcport, X_ALLOC);
1020 if (port == NoPort) {
1021 xseg_put_request(xseg, submitted, srcport);
1025 xseg_signal(xseg, port);
1029 received = xseg_receive(xseg, srcport, 0);
1031 xseg_cancel_wait(xseg, srcport);
1033 req_target = xseg_get_target(xseg, received);
1034 req_data = xseg_get_data(xseg, received);
1035 if (!(received->state & XS_SERVED)) {
1037 report_request(received);
1038 } else if (!chkchunk(req_data, received->datalen,
1039 req_target, received->targetlen, received->offset)) {
1040 // report_request(received);
1044 if (xseg_put_request(xseg, received, srcport))
1045 fprintf(stderr, "Cannot put request at port %u\n", received->src_portno);
1048 if (!submitted && !received)
1049 xseg_wait_signal(xseg, 1000000);
1051 if (nr_submitted % 1000 == 0 && !reported) {
1053 fprintf(stderr, "submitted %ld, received %ld, failed %ld, mismatched %ld\n",
1054 nr_submitted, nr_received, nr_failed, nr_mismatch);
1057 if (nr_received >= loops)
1061 fprintf(stderr, "submitted %ld, received %ld, failed %ld, mismatched %ld\n",
1062 nr_submitted, nr_received, nr_failed, nr_mismatch);
1066 int cmd_submit_reqs(long loops, long concurrent_reqs, int op)
1071 struct xseg_request *submitted = NULL, *received;
1072 long nr_submitted = 0, nr_received = 0, nr_failed = 0, nr_mismatch = 0, nr_flying = 0;
1075 uint32_t targetlen = 10, chunksize = 4096;
1076 struct timeval tv1, tv2;
1078 char *req_data, *req_target;
1080 xseg_bind_port(xseg, srcport, NULL);
1082 gettimeofday(&tv1, NULL);
1085 xseg_prepare_wait(xseg, srcport);
1086 if (nr_submitted < loops && nr_flying < concurrent_reqs &&
1087 (submitted = xseg_get_request(xseg, srcport, dstport, X_ALLOC))) {
1088 xseg_cancel_wait(xseg, srcport);
1089 r = xseg_prep_request(xseg, submitted, targetlen, chunksize);
1091 fprintf(stderr, "Cannot prepare request! (%u, %u)\n",
1092 targetlen, chunksize);
1093 xseg_put_request(xseg, submitted, srcport);
1100 offset = 0;//pick(size);
1102 submitted->offset = offset;
1103 submitted->size = chunksize;
1104 req_target = xseg_get_target(xseg, submitted);
1105 req_data = xseg_get_data(xseg, submitted);
1108 submitted->op = X_INFO;
1110 submitted->op = X_READ;
1112 submitted->op = X_WRITE;
1113 mkchunk(req_data, submitted->datalen, req_target, submitted->targetlen, submitted->offset);
1116 p = xseg_submit(xseg, submitted, srcport, X_ALLOC);
1118 if (xseg_signal(xseg, p) < 0)
1119 perror("Cannot signal peer");
1122 received = xseg_receive(xseg, srcport, 0);
1124 xseg_cancel_wait(xseg, srcport);
1126 if (nr_received == 0)
1127 fprintf(stderr, "latency (time for the first req to complete): %llu usecs\n",
1128 (unsigned long long)received->elapsed);
1130 if (!(received->state & XS_SERVED)) {
1132 //report_request(received);
1135 if (xseg_put_request(xseg, received, srcport))
1136 fprintf(stderr, "Cannot put request at port %u\n", received->src_portno);
1139 if (!submitted && !received)
1140 xseg_wait_signal(xseg, 10000000L);
1142 if (nr_received >= loops)
1145 gettimeofday(&tv2, NULL);
1147 fprintf(stderr, "submitted %ld, received %ld, failed %ld, mismatched %ld\n",
1148 nr_submitted, nr_received, nr_failed, nr_mismatch);
1149 long t = (tv2.tv_sec - tv1.tv_sec)*1000000 + (tv2.tv_usec - tv1.tv_usec);
1150 fprintf(stderr, "elpased time: %lf secs, throughput: %lf reqs/sec\n", (double) t / 1000000.0, (double) nr_submitted / (t / 1000000.0));
1155 static void lock_status(struct xlock *lock, char *buf, int len)
1158 if (lock->owner == Noone)
1159 r = snprintf(buf, len, "Locked: No");
1161 r = snprintf(buf, len, "Locked: Yes (Owner: %lu)", lock->owner);
1166 int cmd_report(uint32_t portno)
1168 char fls[64], rls[64], pls[64]; // buffer to store lock status
1169 struct xseg_port *port = xseg_get_port(xseg, portno);
1171 printf("port %u is not assigned\n", portno);
1174 struct xq *fq, *rq, *pq;
1175 fq = xseg_get_queue(xseg, port, free_queue);
1176 rq = xseg_get_queue(xseg, port, request_queue);
1177 pq = xseg_get_queue(xseg, port, reply_queue);
1178 lock_status(&port->fq_lock, fls, 64);
1179 lock_status(&port->rq_lock, rls, 64);
1180 lock_status(&port->pq_lock, pls, 64);
1181 fprintf(stderr, "port %u:\n"
1182 " requests: %llu/%llu next: %u dst gw: %u\n"
1183 " free_queue [%p] count : %4llu | %s\n"
1184 " request_queue [%p] count : %4llu | %s\n"
1185 " reply_queue [%p] count : %4llu | %s\n",
1186 portno, (unsigned long long)port->alloc_reqs,
1187 (unsigned long long)port->max_alloc_reqs,
1188 xseg->path_next[portno],
1189 xseg->dst_gw[portno],
1190 (void *)fq, (unsigned long long)xq_count(fq), fls,
1191 (void *)rq, (unsigned long long)xq_count(rq), rls,
1192 (void *)pq, (unsigned long long)xq_count(pq), pls);
1201 xseg = xseg_join(cfg.type, cfg.name, "posix", NULL);
1203 fprintf(stderr, "cannot join segment!\n");
1208 static void print_hanlder(char *name, struct xobject_h *obj_h)
1211 lock_status(&obj_h->lock, ls, 64);
1212 fprintf(stderr, "%20s: free: %4llu, allocated: %4llu, allocated space: %7llu (object size: %llu), Lock %s\n",
1214 (unsigned long long) obj_h->nr_free,
1215 (unsigned long long) obj_h->nr_allocated,
1216 (unsigned long long) obj_h->allocated_space,
1217 (unsigned long long) obj_h->obj_size, ls);
1221 static void print_heap(struct xseg *xseg)
1231 MULT[2] = 1024*1024;
1232 MULT[3] = 1024*1024*1024;
1236 fprintf(stderr, "Heap usage: ");
1238 t = xseg->heap->cur;
1245 t = xseg->heap->cur / MULT[u];
1247 float tf = ((float)(xseg->heap->cur))/((float)MULT[u]);
1248 fprintf(stderr, "%2.1f %s/", tf, UNIT[u]);
1251 unsigned int tu = xseg->heap->cur / MULT[u];
1252 fprintf(stderr, "%3u %s/", tu, UNIT[u]);
1256 t = xseg->config.heap_size;
1263 t = xseg->config.heap_size/MULT[u];
1265 float tf = ((float)(xseg->config.heap_size))/(float)MULT[u];
1266 fprintf(stderr, "%2.1f %s ", tf, UNIT[u]);
1269 unsigned int tu = xseg->config.heap_size / MULT[u];
1270 fprintf(stderr, "%3u %s ", tu, UNIT[u]);
1273 lock_status(&xseg->heap->lock, ls, 64);
1274 fprintf(stderr, "(%llu / %llu), %s\n",
1275 (unsigned long long)xseg->heap->cur,
1276 (unsigned long long)xseg->config.heap_size,
1280 int cmd_reportall(void)
1287 fprintf(stderr, "Segment lock: %s\n",
1288 (xseg->shared->flags & XSEG_F_LOCK) ? "Locked" : "Unlocked");
1290 /* fprintf(stderr, "Heap usage: %llu / %llu\n", */
1291 /* (unsigned long long)xseg->heap->cur, */
1292 /* (unsigned long long)xseg->config.heap_size); */
1293 fprintf(stderr, "Handlers: \n");
1294 print_hanlder("Requests handler", xseg->request_h);
1295 print_hanlder("Ports handler", xseg->port_h);
1296 print_hanlder("Objects handler", xseg->object_handlers);
1297 fprintf(stderr, "\n");
1299 for (t = 0; t < xseg->config.nr_ports; t++)
1306 int finish_req(struct xseg_request *req, enum req_action action)
1308 if (action == COMPLETE){
1309 req->state &= ~XS_FAILED;
1310 req->state |= XS_SERVED;
1312 req->state |= XS_FAILED;
1313 req->state &= ~XS_SERVED;
1316 xport p = xseg_respond(xseg, req, srcport, X_ALLOC);
1318 xseg_put_request(xseg, req, srcport);
1320 xseg_signal(xseg, p);
1324 //FIXME this should be in xseg lib?
1325 static int isDangling(struct xseg_request *req)
1328 struct xseg_port *port;
1329 for (i = 0; i < xseg->config.nr_ports; i++) {
1330 if (xseg->ports[i]){
1331 port = xseg_get_port(xseg, i);
1333 fprintf(stderr, "Inconsisten port <-> portno mapping %u", i);
1336 struct xq *fq, *rq, *pq;
1337 fq = xseg_get_queue(xseg, port, free_queue);
1338 rq = xseg_get_queue(xseg, port, request_queue);
1339 pq = xseg_get_queue(xseg, port, reply_queue);
1340 xlock_acquire(&port->fq_lock, srcport);
1341 if (__xq_check(fq, XPTR_MAKE(req, xseg->segment))){
1342 xlock_release(&port->fq_lock);
1345 xlock_release(&port->fq_lock);
1346 xlock_acquire(&port->rq_lock, srcport);
1347 if (__xq_check(rq, XPTR_MAKE(req, xseg->segment))){
1348 xlock_release(&port->rq_lock);
1351 xlock_release(&port->rq_lock);
1352 xlock_acquire(&port->pq_lock, srcport);
1353 if (__xq_check(pq, XPTR_MAKE(req, xseg->segment))){
1354 xlock_release(&port->pq_lock);
1357 xlock_release(&port->pq_lock);
1363 int prompt_user(char *msg)
1366 printf("%s [y/n]: ", msg);
1369 if (c == 'y' || c == 'Y')
1371 else if (c == 'n' || c == 'N')
1373 else if (c == '\n'){
1375 printf("%s [y/n]: ", msg);
1383 //FIXME this should be in xseg lib?
1384 int cmd_verify(int fix)
1389 if (xseg->shared->flags & XSEG_F_LOCK){
1390 fprintf(stderr, "Segment lock: Locked\n");
1391 if (fix && prompt_user("Unlock it ?"))
1392 xseg->shared->flags &= ~XSEG_F_LOCK;
1395 if (xseg->heap->lock.owner != Noone){
1396 fprintf(stderr, "Heap lock: Locked (Owner: %llu)\n",
1397 (unsigned long long)xseg->heap->lock.owner);
1398 if (fix && prompt_user("Unlock it ?"))
1399 xlock_release(&xseg->heap->lock);
1402 if (xseg->request_h->lock.owner != Noone){
1403 fprintf(stderr, "Requests handler lock: Locked (Owner: %llu)\n",
1404 (unsigned long long)xseg->request_h->lock.owner);
1405 if (fix && prompt_user("Unlock it ?"))
1406 xlock_release(&xseg->request_h->lock);
1408 if (xseg->port_h->lock.owner != Noone){
1409 fprintf(stderr, "Ports handler lock: Locked (Owner: %llu)\n",
1410 (unsigned long long)xseg->port_h->lock.owner);
1411 if (fix && prompt_user("Unlock it ?"))
1412 xlock_release(&xseg->port_h->lock);
1414 if (xseg->object_handlers->lock.owner != Noone){
1415 fprintf(stderr, "Objects handler lock: Locked (Owner: %llu)\n",
1416 (unsigned long long)xseg->object_handlers->lock.owner);
1417 if (fix && prompt_user("Unlock it ?"))
1418 xlock_release(&xseg->object_handlers->lock);
1420 //take segment lock?
1422 struct xseg_port *port;
1423 for (i = 0; i < xseg->config.nr_ports; i++) {
1424 if (xseg->ports[i]){
1425 port = xseg_get_port(xseg, i);
1427 fprintf(stderr, "Inconsisten port <-> portno mapping %u", i);
1430 if (port->fq_lock.owner != Noone) {
1431 fprintf(stderr, "Free queue lock of port %u locked (Owner %llu)\n",
1432 i, (unsigned long long)port->fq_lock.owner);
1433 if (fix && prompt_user("Unlock it ?"))
1434 xlock_release(&port->fq_lock);
1436 if (port->rq_lock.owner != Noone) {
1437 fprintf(stderr, "Request queue lock of port %u locked (Owner %llu)\n",
1438 i, (unsigned long long)port->rq_lock.owner);
1439 if (fix && prompt_user("Unlock it ?"))
1440 xlock_release(&port->rq_lock);
1442 if (port->pq_lock.owner != Noone) {
1443 fprintf(stderr, "Reply queue lock of port %u locked (Owner %llu)\n",
1444 i, (unsigned long long)port->pq_lock.owner);
1445 if (fix && prompt_user("Unlock it ?"))
1446 xlock_release(&port->pq_lock);
1451 struct xobject_h *obj_h = xseg->request_h;
1452 struct xobject_iter it;
1454 struct xseg_request *req;
1455 xlock_acquire(&obj_h->lock, srcport);
1456 xobj_iter_init(obj_h, &it);
1457 while (xobj_iterate(obj_h, &it, (void **)&req)){
1458 //FIXME this will not work cause obj->magic - req->serial is not
1459 //touched when a request is get
1460 /* if (obj->magic != MAGIC_REQ && t->src_portno == portno){ */
1461 if (isDangling(req) && !__xobj_isFree(obj_h, req)){
1462 report_request(req);
1463 if (fix && prompt_user("Fail it ?")){
1464 printf("Finishing ...\n");
1465 finish_req(req, FAIL);
1469 xlock_release(&obj_h->lock);
1473 int cmd_inspectq(xport portno, enum queue qt)
1480 struct xseg_port *port = xseg_get_port(xseg, portno);
1483 if (qt == FREE_QUEUE){
1484 q = xseg_get_queue(xseg, port, free_queue);
1487 else if (qt == REQUEST_QUEUE){
1488 q = xseg_get_queue(xseg, port, request_queue);
1491 else if (qt == REPLY_QUEUE) {
1492 q = xseg_get_queue(xseg, port, reply_queue);
1497 xlock_acquire(l, srcport);
1498 xqindex i,c = xq_count(q);
1500 struct xseg_request *req;
1502 for (i = 0; i < c; i++) {
1503 xqi = __xq_pop_head(q);
1504 req = XPTR_TAKE(xqi, xseg->segment);
1505 report_request(req);
1506 __xq_append_tail(q, xqi);
1510 fprintf(stderr, "Queue is empty\n\n");
1517 int cmd_request(struct xseg_request *req, enum req_action action)
1522 struct xobject_h *obj_h = xseg->request_h;
1523 if (!xobj_check(obj_h, req))
1526 if (action == REPORT)
1527 report_request(req);
1528 else if (action == FAIL){
1529 report_request(req);
1530 if (prompt_user("fail it ?")){
1531 printf("Finishing ...\n");
1532 finish_req(req, FAIL);
1535 else if (action == COMPLETE){
1536 report_request(req);
1537 if (prompt_user("Complete it ?")){
1538 printf("Finishing ...\n");
1539 finish_req(req, COMPLETE);
1545 int cmd_create(void)
1547 int r = xseg_create(&cfg);
1549 fprintf(stderr, "cannot create segment!\n");
1553 fprintf(stderr, "Segment initialized.\n");
1557 int cmd_destroy(void)
1559 if (!xseg && cmd_join())
1564 fprintf(stderr, "Segment destroyed.\n");
1568 int cmd_alloc_requests(unsigned long nr)
1570 return xseg_alloc_requests(xseg, srcport, nr);
1573 int cmd_free_requests(unsigned long nr)
1575 return xseg_free_requests(xseg, srcport, nr);
1578 int cmd_put_requests(void)
1580 struct xseg_request *req;
1583 req = xseg_accept(xseg, dstport, 0);
1586 if (xseg_put_request(xseg, req, srcport))
1587 fprintf(stderr, "Cannot put request at port %u\n", req->src_portno);
1593 int cmd_finish(unsigned long nr, int fail)
1595 struct xseg_request *req;
1596 char *buf = malloc(sizeof(char) * 8128);
1597 char *req_target, *req_data;
1598 xseg_bind_port(xseg, srcport, NULL);
1602 xseg_prepare_wait(xseg, srcport);
1603 req = xseg_accept(xseg, srcport, 0);
1605 req_target = xseg_get_target(xseg, req);
1606 req_data = xseg_get_data(xseg, req);
1607 xseg_cancel_wait(xseg, srcport);
1609 req->state &= ~XS_SERVED;
1611 if (req->op == X_READ)
1612 mkchunk(req_data, req->datalen, req_target, req->targetlen, req->offset);
1613 else if (req->op == X_WRITE)
1614 memcpy(buf, req_data, (sizeof(*buf) > req->datalen) ? req->datalen : sizeof(*buf));
1615 else if (req->op == X_INFO)
1616 *((uint64_t *) req->data) = 4294967296;
1618 req->state |= XS_SERVED;
1619 req->serviced = req->size;
1622 p = xseg_respond(xseg, req, srcport, X_ALLOC);
1623 xseg_signal(xseg, p);
1627 xseg_wait_signal(xseg, 10000000L);
1635 void handle_reply(struct xseg_request *req)
1637 char *req_data = xseg_get_data(xseg, req);
1638 char *req_target = xseg_get_target(xseg, req);
1639 if (!(req->state & XS_SERVED)) {
1640 report_request(req);
1646 fwrite(req_data, 1, req->datalen, stdout);
1650 fprintf(stdout, "wrote: ");
1651 fwrite(req_data, 1, req->datalen, stdout);
1655 fprintf(stderr, "deleted %s\n", req_target);
1660 fprintf(stderr, "cloned %s\n", ((struct xseg_request_clone *)req_data)->target);
1663 fprintf(stderr, "size: %llu\n", (unsigned long long)*((uint64_t *)req_data));
1666 fprintf(stderr, "copied %s\n", ((struct xseg_request_copy *)req_data)->target);
1669 fprintf(stderr, "Closed %s\n", req_target);
1672 fprintf(stderr, "Opened %s\n", req_target);
1675 fprintf(stderr, "Snapshotted %s\n", req_target);
1682 if (xseg_put_request(xseg, req, srcport))
1683 fprintf(stderr, "Cannot put reply at port %u\n", req->src_portno);
1686 int cmd_wait(uint32_t nr)
1688 struct xseg_request *req;
1690 init_local_signal();
1693 req = xseg_receive(xseg, srcport, 0);
1702 ret = xseg_prepare_wait(xseg, srcport);
1706 ret = xseg_wait_signal(xseg, 1000000);
1707 ret = xseg_cancel_wait(xseg, srcport);
1715 int cmd_put_replies(void)
1717 struct xseg_request *req;
1720 req = xseg_receive(xseg, dstport, 0);
1723 fprintf(stderr, "request: %08llx%08llx\n"
1726 0LL, (unsigned long long)req->serial,
1729 report_request(req);
1731 //fwrite(req->buffer, 1, req->bufferlen, stdout);
1733 if (xseg_put_request(xseg, req, srcport))
1734 fprintf(stderr, "Cannot put reply\n");
1740 int cmd_bind(long portno)
1742 struct xseg_port *port = xseg_bind_port(xseg, portno, NULL);
1744 fprintf(stderr, "failed to bind port %ld\n", portno);
1748 fprintf(stderr, "bound port %u\n", xseg_portno(xseg, port));
1752 int cmd_signal(uint32_t portno)
1754 return xseg_signal(xseg, portno);
1757 int cmd_set_next(xport portno, xport next)
1759 xseg->path_next[portno] = next;
1763 int parse_ports(char *str)
1774 if ((s > str) && isdigit(str[0])) {
1775 srcport = atol(str);
1788 if ((s > str) && isdigit(str[0])) {
1789 dstport = atol(str);
1800 int main(int argc, char **argv)
1812 if (xseg_parse_spec(spec, &cfg)) {
1813 fprintf(stderr, "Cannot parse spec\n");
1817 if (xseg_initialize()) {
1818 fprintf(stderr, "cannot initialize!\n");
1822 for (i = 2; i < argc; i++) {
1824 if (!strcmp(argv[i], "create")) {
1829 if (!strcmp(argv[i], "join")) {
1832 fprintf(stderr, "Segment joined.\n");
1836 if (!strcmp(argv[i], "destroy")) {
1837 ret = cmd_destroy();
1844 if (!strcmp(argv[i], "reportall")) {
1845 ret = cmd_reportall();
1849 if (!strcmp(argv[i], "bind") && (i + 1 < argc)) {
1850 ret = cmd_bind(atol(argv[i+1]));
1855 if (!strcmp(argv[i], "set-next") && (i + 2 < argc)) {
1856 ret = cmd_set_next(atol(argv[i+1]), atol(argv[i+2]));
1861 if (!strcmp(argv[i], "signal") && (i + 1 < argc)) {
1862 ret = cmd_signal(atol(argv[i+1]));
1867 if (!strcmp(argv[i], "bridge") && (i + 4 < argc)) {
1868 ret = cmd_bridge(atol(argv[i+1]),
1876 if (srcport == -1) {
1877 if (!parse_ports(argv[i]))
1878 fprintf(stderr, "source port undefined: %s\n", argv[i]);
1882 if (dstport == -1) {
1883 if (!parse_ports(argv[i]))
1884 fprintf(stderr, "destination port undefined: %s\n", argv[i]);
1888 if (!strcmp(argv[i], "verify")) {
1889 ret = cmd_verify(0);
1893 if (!strcmp(argv[i], "verify-fix")) {
1894 ret = cmd_verify(1);
1898 if (!strcmp(argv[i], "failreq") && (i + 1 < argc)) {
1899 struct xseg_request *req;
1900 sscanf(argv[i+1], "%lx", (unsigned long *)&req);
1901 ret = cmd_request(req, FAIL);
1906 if (!strcmp(argv[i], "inspect-freeq") && (i + 1 < argc)) {
1907 ret = cmd_inspectq(atol(argv[i+1]), FREE_QUEUE);
1912 if (!strcmp(argv[i], "inspect-requestq") && (i + 1 < argc)) {
1913 ret = cmd_inspectq(atol(argv[i+1]), REQUEST_QUEUE);
1918 if (!strcmp(argv[i], "inspect-replyq") && (i + 1 < argc)) {
1919 ret = cmd_inspectq(atol(argv[i+1]), REPLY_QUEUE);
1924 if (!strcmp(argv[i], "report")) {
1925 ret = cmd_report(dstport);
1929 if (!strcmp(argv[i], "alloc_requests") && (i + 1 < argc)) {
1930 ret = cmd_alloc_requests(atol(argv[i+1]));
1935 if (!strcmp(argv[i], "free_requests") && (i + 1 < argc)) {
1936 ret = cmd_free_requests(atol(argv[i+1]));
1941 if (!strcmp(argv[i], "put_requests")) {
1942 ret = cmd_put_requests();
1946 if (!strcmp(argv[i], "put_replies")) {
1947 ret = cmd_put_replies();
1951 if (!strcmp(argv[i], "complete") && (i + 1 < argc)) {
1952 ret = cmd_finish(atol(argv[i+1]), 0);
1957 if (!strcmp(argv[i], "fail") && (i + 1 < argc)) {
1958 ret = cmd_finish(atol(argv[i+1]), 1);
1963 if (!strcmp(argv[i], "wait") && (i + 1 < argc)) {
1964 ret = cmd_wait(atol(argv[i+1]));
1969 if (!strcmp(argv[i], "rndwrite") && (i + 5 < argc)) {
1970 long nr_loops = atol(argv[i+1]);
1971 unsigned int seed = atoi(argv[i+2]);
1972 unsigned int targetlen = atoi(argv[i+3]);
1973 unsigned int chunksize = atoi(argv[i+4]);
1974 unsigned long objectsize = atol(argv[i+5]);
1975 ret = cmd_rndwrite(nr_loops, seed, targetlen, chunksize, objectsize);
1980 if (!strcmp(argv[i], "rnddelete") && (i + 3 < argc)) {
1981 long nr_loops = atol(argv[i+1]);
1982 unsigned int seed = atoi(argv[i+2]);
1983 unsigned int targetlen = atoi(argv[i+3]);
1984 ret = cmd_rnddelete(nr_loops, seed, targetlen);
1989 if (!strcmp(argv[i], "rndread") && (i + 5 < argc)) {
1990 long nr_loops = atol(argv[i+1]);
1991 unsigned int seed = atoi(argv[i+2]);
1992 unsigned int targetlen = atoi(argv[i+3]);
1993 unsigned int chunksize = atoi(argv[i+4]);
1994 unsigned long objectsize = atol(argv[i+5]);
1995 ret = cmd_rndread(nr_loops, seed, targetlen, chunksize, objectsize);
2000 if (!strcmp(argv[i], "submit_reqs") && (i + 3 < argc)) {
2001 long nr_loops = atol(argv[i+1]);
2002 long concurrent_reqs = atol(argv[i+2]);
2003 int op = atoi(argv[i+3]);
2004 ret = cmd_submit_reqs(nr_loops, concurrent_reqs, op);
2009 if (!strcmp(argv[i], "read") && (i + 3 < argc)) {
2010 char *target = argv[i+1];
2011 uint64_t offset = atol(argv[i+2]);
2012 uint64_t size = atol(argv[i+3]);
2013 ret = cmd_read(target, offset, size);
2018 if (!strcmp(argv[i], "write") && (i + 2 < argc)) {
2019 char *target = argv[i+1];
2020 uint64_t offset = atol(argv[i+2]);
2021 ret = cmd_write(target, offset);
2026 if (!strcmp(argv[i], "truncate") && (i + 2 < argc)) {
2027 char *target = argv[i+1];
2028 uint64_t offset = atol(argv[i+2]);
2029 ret = cmd_truncate(target, offset);
2034 if (!strcmp(argv[i], "delete") && (i + 1 < argc)) {
2035 char *target = argv[i+1];
2036 ret = cmd_delete(target);
2041 if (!strcmp(argv[i], "acquire") && (i + 1 < argc)) {
2042 char *target = argv[i+1];
2043 ret = cmd_acquire(target);
2048 if (!strcmp(argv[i], "release") && (i + 1 < argc)) {
2049 char *target = argv[i+1];
2050 ret = cmd_release(target);
2055 if (!strcmp(argv[i], "copy") && (i + 2) < argc) {
2056 char *src = argv[i+1];
2057 char *dst = argv[i+2];
2058 ret = cmd_copy(src, dst);
2063 if (!strcmp(argv[i], "clone") && (i + 2 < argc)) {
2064 char *src = argv[i+1];
2065 char *dst = argv[i+2];
2066 ret = cmd_clone(src, dst);
2070 if (!strcmp(argv[i], "snapshot") && (i + 2 < argc)) {
2071 char *src = argv[i+1];
2072 char *dst = argv[i+2];
2073 ret = cmd_snapshot(src, dst, 4096*1024);
2078 if (!strcmp(argv[i], "info") && (i + 1 < argc)) {
2079 char *target = argv[i+1];
2080 ret = cmd_info(target);
2086 if (!parse_ports(argv[i]))
2087 fprintf(stderr, "invalid argument: %s\n", argv[i]);