12 #include <xseg/xseg.h>
16 printf("xseg <spec> [[[<src_port>]:[<dst_port>]] [<command> <arg>*] ]*\n"
18 " <type:name:nr_ports:nr_requests:request_size:extra_size:page_shift>\n"
25 " bridge <portno1> <portno2> <logfile> {full|summary|stats}\n"
28 " alloc_requests (to source) <nr>\n"
29 " free_requests (from source) <nr>\n"
30 " put_requests (all from dest)\n"
31 " put_replies (all from dest)\n"
32 " wait <nr_replies>\n"
33 " complete <nr_requests>\n"
34 " fail <nr_requests>\n"
35 " rndwrite <nr_loops> <seed> <targetlen> <datalen> <objectsize>\n"
36 " rndread <nr_loops> <seed> <targetlen> <datalen> <objectsize>\n"
37 " submit_reqs <nr_loops> <concurrent_reqs>\n"
39 " read <target> <offset> <size>\n"
40 " write <target> <offset> < data\n"
41 " truncate <target> <size>\n"
46 " clone <src> <dst>\n"
53 struct xseg_config cfg;
55 uint32_t srcport, dstport;
57 #define mkname mkname_heavy
58 /* heavy distributes duplicates much more widely than light
59 * ./xseg-tool random 100000 | cut -d' ' -f2- | sort | uniq -d -c |wc -l
62 void mkname_heavy(char *name, uint32_t namelen, uint32_t seed)
66 for (i = 0; i < namelen; i += 1) {
67 c = seed + (seed >> 8) + (seed >> 16) + (seed >> 24);
68 c = '0' + ((c + (c >> 4)) & 0xf);
72 seed *= ((seed % 137911) | 1) * 137911;
76 void mkname_light(char *name, uint32_t namelen, uint32_t seed)
80 for (i = 0; i < namelen; i += 1) {
82 name[i] = 'A' + (c & 0xf);
87 uint64_t pick(uint64_t size)
89 return (uint64_t)((double)(RAND_MAX) / random());
92 void mkchunk( char *chunk, uint32_t datalen,
93 char *target, uint32_t targetlen, uint64_t offset)
95 long i, r, bufsize = targetlen + 16;
97 r = datalen % bufsize;
98 snprintf(buf, bufsize, "%016llx%s", (unsigned long long)offset, target);
100 for (i = 0; i <= (long)datalen - bufsize; i += bufsize)
101 memcpy(chunk + i, buf, bufsize);
103 memcpy(chunk + datalen - r, buf, r);
106 int chkchunk( char *chunk, uint32_t datalen,
107 char *target, uint32_t targetlen, uint64_t offset)
110 int bufsize = targetlen + 16;
112 r = datalen % targetlen;
113 snprintf(buf, bufsize, "%016llx%s", (unsigned long long)offset, target);
115 for (i = 0; i <= (long)datalen - bufsize; i += bufsize)
116 if (memcmp(chunk + i, buf, bufsize)) {
117 /*printf("mismatch: '%*s'* vs '%*s'\n",
118 bufsize, buf, datalen, chunk);
123 if (memcmp(chunk + datalen - r, buf, r))
130 #define ALLOC_MIN 4096
131 #define ALLOC_MAX 1048576
133 void inputbuf(FILE *fp, char **retbuf, uint64_t *retsize)
135 static uint64_t alloc_size;
141 if (alloc_size < ALLOC_MIN)
142 alloc_size = ALLOC_MIN;
144 if (alloc_size > ALLOC_MAX)
145 alloc_size = ALLOC_MAX;
147 p = realloc(buf, alloc_size);
158 r = fread(buf + size, 1, alloc_size - size, fp);
162 if (size >= alloc_size) {
163 p = realloc(buf, alloc_size * 2);
181 void report_request(struct xseg_request *req)
183 uint32_t max = req->datalen;
186 req->data[max-1] = 0;
187 fprintf(stderr, "request %llu state %u\n", (unsigned long long)req->serial, req->state);
188 fprintf(stderr, "data: %s\n", req->data);
191 int cmd_info(char *target)
193 uint32_t targetlen = strlen(target);
194 size_t size = sizeof(uint64_t);
197 struct xseg_request *req;
199 req = xseg_get_request(xseg, srcport);
201 fprintf(stderr, "No request!\n");
205 r = xseg_prep_request(req, targetlen, size);
207 fprintf(stderr, "Cannot prepare request! (%lu, %lu)\n",
208 (unsigned long) targetlen, (unsigned long) size);
209 xseg_put_request(xseg, srcport, req);
213 strncpy(req->target, target, targetlen);
218 srl = xseg_submit(xseg, dstport, req);
222 xseg_signal(xseg, dstport);
227 int cmd_read(char *target, uint64_t offset, uint64_t size)
229 uint32_t targetlen = strlen(target);
232 struct xseg_request *req = xseg_get_request(xseg, srcport);
234 fprintf(stderr, "No request\n");
238 r = xseg_prep_request(req, targetlen, size);
240 fprintf(stderr, "Cannot prepare request! (%lu, %llu)\n",
241 (unsigned long)targetlen, (unsigned long long)size);
242 xseg_put_request(xseg, srcport, req);
246 strncpy(req->target, target, targetlen);
247 req->offset = offset;
251 srl = xseg_submit(xseg, dstport, req);
255 xseg_signal(xseg, dstport);
259 int cmd_write(char *target, uint64_t offset)
265 uint32_t targetlen = strlen(target);
266 struct xseg_request *req;
268 inputbuf(stdin, &buf, &size);
270 fprintf(stderr, "No input\n");
274 req = xseg_get_request(xseg, srcport);
276 fprintf(stderr, "No request\n");
280 r = xseg_prep_request(req, targetlen, size);
282 fprintf(stderr, "Cannot prepare request! (%lu, %llu)\n",
283 (unsigned long)targetlen, (unsigned long long)size);
284 xseg_put_request(xseg, srcport, req);
288 strncpy(req->target, target, targetlen);
289 memcpy(req->buffer, buf, size);
290 req->offset = offset;
294 srl = xseg_submit(xseg, dstport, req);
295 if (srl == Noneidx) {
296 fprintf(stderr, "Cannot submit\n");
303 int cmd_truncate(char *target, uint64_t offset)
308 int cmd_delete(char *target)
313 int cmd_acquire(char *target)
318 int cmd_release(char *target)
323 int cmd_copy(char *src, char *dst)
328 int cmd_clone(char *src, char *dst)
333 void log_req(int logfd, uint32_t portno2, uint32_t portno1, int op, int method,
334 struct xseg_request *req)
337 char target[64], data[64];
338 /* null terminate name in case of req->target is less than 63 characters,
339 * and next character after name (aka first byte of next buffer) is not
342 unsigned int end = (req->targetlen > 63) ? 63 : req->targetlen;
344 logfp = fdopen(logfd, "a");
350 strncpy(target, req->target, end);
352 strncpy(data, req->data, 63);
356 "src port: %u, dst port: %u, op:%u offset: %llu size: %lu, reqstate: %u\n"
357 "target[%u]: '%s', data[%llu]:\n%s------------------\n\n",
358 (unsigned int)portno1,
359 (unsigned int)portno2,
360 (unsigned int)req->op,
361 (unsigned long long)req->offset,
362 (unsigned long)req->size,
363 (unsigned int)req->state,
364 (unsigned int)req->targetlen, target,
365 (unsigned long long)req->datalen, data);
369 "src port: %u, dst port: %u, op: %u\n",
370 (unsigned int)portno1,
371 (unsigned int)portno2,
372 (unsigned int)req->op);
375 fprintf(logfp, "src port: %u, dst port: %u, reqs: %llu\n",
376 (unsigned int)portno1,
377 (unsigned int)portno2,
378 (unsigned long long)++reqs);
386 #define LOG_RECEIVE 1
388 int cmd_bridge(uint32_t portno1, uint32_t portno2, char *logfile, char *how)
390 struct xseg_request *req;
392 if (!strcmp(logfile, "-"))
395 logfd = open(logfile, O_WRONLY|O_APPEND|O_CREAT, 0600);
402 if (!strcmp(how, "full"))
404 else if (!strcmp(how, "summary"))
410 int reloop = 0, active;
411 xseg_prepare_wait(xseg, portno1);
412 xseg_prepare_wait(xseg, portno2);
418 req = xseg_accept(xseg, portno1);
420 xseg_submit(xseg, portno2, req);
421 log_req(logfd, portno1, portno2, LOG_ACCEPT, method, req);
425 req = xseg_accept(xseg, portno2);
427 xseg_submit(xseg, portno1, req);
428 log_req(logfd, portno2, portno1, LOG_ACCEPT, method, req);
432 req = xseg_receive(xseg, portno1);
434 xseg_respond(xseg, portno2, req);
435 log_req(logfd, portno1, portno2, LOG_RECEIVE, method, req);
439 req = xseg_receive(xseg, portno2);
441 xseg_respond(xseg, portno1, req);
442 log_req(logfd, portno2, portno1, LOG_RECEIVE, method, req);
449 /* wait on multiple queues? */
450 xseg_wait_signal(xseg, 100000);
453 xseg_cancel_wait(xseg, portno1);
454 xseg_cancel_wait(xseg, portno2);
465 int cmd_rndwrite(long loops, int32_t seed, uint32_t targetlen, uint32_t chunksize, uint64_t size)
470 if (targetlen >= chunksize) {
471 fprintf(stderr, "targetlen >= chunksize\n");
475 char *p = realloc(namebuf, targetlen+1);
477 fprintf(stderr, "Cannot allocate memory\n");
482 p = realloc(chunk, chunksize);
484 fprintf(stderr, "Cannot allocate memory\n");
488 memset(chunk, 0, chunksize);
492 struct xseg_request *submitted = NULL, *received;
493 long nr_submitted = 0, nr_received = 0, nr_failed = 0;
499 xseg_prepare_wait(xseg, srcport);
500 if (nr_submitted < loops &&
501 (submitted = xseg_get_request(xseg, srcport))) {
502 xseg_cancel_wait(xseg, srcport);
503 r = xseg_prep_request(submitted, targetlen, chunksize);
505 fprintf(stderr, "Cannot prepare request! (%u, %u)\n",
506 targetlen, chunksize);
507 xseg_put_request(xseg, submitted->portno, submitted);
514 mkname(namebuf, targetlen, seed);
515 namebuf[targetlen] = 0;
516 //printf("%ld: %s\n", nr_submitted, namebuf);
517 strncpy(submitted->target, namebuf, targetlen);
518 offset = 0;// pick(size);
519 mkchunk(submitted->buffer, chunksize, namebuf, targetlen, offset);
521 submitted->offset = offset;
522 submitted->size = chunksize;
523 submitted->op = X_WRITE;
524 submitted->flags |= XF_NOSYNC;
526 srl = xseg_submit(xseg, dstport, submitted);
528 xseg_signal(xseg, dstport);
531 received = xseg_receive(xseg, srcport);
533 xseg_cancel_wait(xseg, srcport);
535 if (!(received->state & XS_SERVED)) {
537 report_request(received);
539 if (xseg_put_request(xseg, received->portno, received))
540 fprintf(stderr, "Cannot put request at port %u\n", received->portno);
543 if (!submitted && !received)
544 xseg_wait_signal(xseg, 1000000);
546 if (nr_submitted % 1000 == 0 && !reported) {
548 fprintf(stderr, "submitted %ld, received %ld, failed %ld\n",
549 nr_submitted, nr_received, nr_failed);
552 if (nr_received >= loops)
556 fprintf(stderr, "submitted %ld, received %ld, failed %ld\n",
557 nr_submitted, nr_received, nr_failed);
562 * prepare/wait rhythm,
563 * files are converted to independent chunk access patterns,
566 int cmd_rndread(long loops, int32_t seed, uint32_t targetlen, uint32_t chunksize, uint64_t size)
571 if (targetlen >= chunksize) {
572 fprintf(stderr, "targetlen >= chunksize\n");
576 char *p = realloc(namebuf, targetlen+1);
578 fprintf(stderr, "Cannot allocate memory\n");
583 p = realloc(chunk, chunksize);
585 fprintf(stderr, "Cannot allocate memory\n");
589 memset(chunk, 0, chunksize);
593 struct xseg_request *submitted = NULL, *received;
594 long nr_submitted = 0, nr_received = 0, nr_failed = 0, nr_mismatch = 0;
601 xseg_prepare_wait(xseg, srcport);
602 if (nr_submitted < loops &&
603 (submitted = xseg_get_request(xseg, srcport))) {
604 xseg_cancel_wait(xseg, srcport);
605 r = xseg_prep_request(submitted, targetlen, chunksize);
607 fprintf(stderr, "Cannot prepare request! (%u, %u)\n",
608 targetlen, chunksize);
609 xseg_put_request(xseg, submitted->portno, submitted);
616 mkname(namebuf, targetlen, seed);
617 namebuf[targetlen] = 0;
618 //printf("%ld: %s\n", nr_submitted, namebuf);
619 offset = 0;//pick(size);
621 strncpy(submitted->target, namebuf, targetlen);
622 submitted->offset = offset;
623 submitted->size = chunksize;
624 submitted->op = X_READ;
626 srl = xseg_submit(xseg, dstport, submitted);
628 xseg_signal(xseg, dstport);
631 received = xseg_receive(xseg, srcport);
633 xseg_cancel_wait(xseg, srcport);
635 if (!(received->state & XS_SERVED)) {
637 report_request(received);
638 } else if (!chkchunk(received->data, received->datalen,
639 received->target, received->targetlen, received->offset)) {
643 if (xseg_put_request(xseg, received->portno, received))
644 fprintf(stderr, "Cannot put request at port %u\n", received->portno);
647 if (!submitted && !received)
648 xseg_wait_signal(xseg, 1000000);
650 if (nr_submitted % 1000 == 0 && !reported) {
652 fprintf(stderr, "submitted %ld, received %ld, failed %ld, mismatched %ld\n",
653 nr_submitted, nr_received, nr_failed, nr_mismatch);
656 if (nr_received >= loops)
660 fprintf(stderr, "submitted %ld, received %ld, failed %ld, mismatched %ld\n",
661 nr_submitted, nr_received, nr_failed, nr_mismatch);
665 int cmd_submit_reqs(long loops, long concurrent_reqs, int op)
670 struct xseg_request *submitted = NULL, *received;
671 long nr_submitted = 0, nr_received = 0, nr_failed = 0, nr_mismatch = 0, nr_flying = 0;
674 uint32_t targetlen = 10, chunksize = 4096;
675 struct timeval tv1, tv2;
678 xseg_bind_port(xseg, srcport);
680 gettimeofday(&tv1, NULL);
683 xseg_prepare_wait(xseg, srcport);
684 if (nr_submitted < loops && nr_flying < concurrent_reqs &&
685 (submitted = xseg_get_request(xseg, srcport))) {
686 xseg_cancel_wait(xseg, srcport);
687 r = xseg_prep_request(submitted, targetlen, chunksize);
689 fprintf(stderr, "Cannot prepare request! (%u, %u)\n",
690 targetlen, chunksize);
691 xseg_put_request(xseg, submitted->portno, submitted);
698 offset = 0;//pick(size);
700 submitted->offset = offset;
701 submitted->size = chunksize;
704 submitted->op = X_INFO;
706 submitted->op = X_READ;
708 submitted->op = X_WRITE;
709 mkchunk(submitted->buffer, submitted->datalen, submitted->target, submitted->targetlen, submitted->offset);
712 srl = xseg_submit(xseg, dstport, submitted);
714 if (xseg_signal(xseg, dstport) < 0)
715 perror("Cannot signal peer");
717 received = xseg_receive(xseg, srcport);
719 xseg_cancel_wait(xseg, srcport);
721 if (nr_received == 0)
722 fprintf(stderr, "latency (time for the first req to complete): %llu usecs\n",
723 (unsigned long long)received->elapsed);
725 if (!(received->state & XS_SERVED)) {
727 //report_request(received);
730 if (xseg_put_request(xseg, received->portno, received))
731 fprintf(stderr, "Cannot put request at port %u\n", received->portno);
734 if (!submitted && !received)
735 xseg_wait_signal(xseg, 10000000L);
737 if (nr_received >= loops)
740 gettimeofday(&tv2, NULL);
742 fprintf(stderr, "submitted %ld, received %ld, failed %ld, mismatched %ld\n",
743 nr_submitted, nr_received, nr_failed, nr_mismatch);
744 long t = (tv2.tv_sec - tv1.tv_sec)*1000000 + (tv2.tv_usec - tv1.tv_usec);
745 fprintf(stderr, "elpased time: %lf secs, throughput: %lf reqs/sec\n", (double) t / 1000000.0, (double) nr_submitted / (t / 1000000.0));
750 int cmd_report(uint32_t port)
752 struct xq *fq, *rq, *pq;
753 fq = &xseg->ports[port].free_queue;
754 rq = &xseg->ports[port].request_queue;
755 pq = &xseg->ports[port].reply_queue;
756 fprintf(stderr, "port %u:\n"
757 " free_queue [%p] count : %u\n"
758 " request_queue [%p] count : %u\n"
759 " reply_queue [%p] count : %u\n",
761 (void *)fq, xq_count(fq),
762 (void *)rq, xq_count(rq),
763 (void *)pq, xq_count(pq));
772 xseg = xseg_join(cfg.type, cfg.name, "posix", NULL);
774 fprintf(stderr, "cannot join segment!\n");
780 int cmd_reportall(void)
787 fprintf(stderr, "global free requests: %u\n", xq_count(xseg->free_requests));
788 for (t = 0; t < xseg->config.nr_ports; t++)
796 int r = xseg_create(&cfg);
798 fprintf(stderr, "cannot create segment!\n");
802 fprintf(stderr, "Segment initialized.\n");
806 int cmd_destroy(void)
808 if (!xseg && cmd_join())
813 fprintf(stderr, "Segment destroyed.\n");
817 int cmd_alloc_requests(unsigned long nr)
819 return xseg_alloc_requests(xseg, srcport, nr);
822 int cmd_free_requests(unsigned long nr)
824 return xseg_free_requests(xseg, srcport, nr);
827 int cmd_put_requests(void)
829 struct xseg_request *req;
832 req = xseg_accept(xseg, dstport);
835 if (xseg_put_request(xseg, req->portno, req))
836 fprintf(stderr, "Cannot put request at port %u\n", req->portno);
842 int cmd_finish(unsigned long nr, int fail)
844 struct xseg_request *req;
845 char *buf = malloc(sizeof(char) * 8128);
847 xseg_bind_port(xseg, srcport);
850 xseg_prepare_wait(xseg, srcport);
851 req = xseg_accept(xseg, srcport);
853 xseg_cancel_wait(xseg, srcport);
855 req->state &= ~XS_SERVED;
857 if (req->op == X_READ)
858 mkchunk(req->buffer, req->datalen, req->target, req->targetlen, req->offset);
859 else if (req->op == X_WRITE)
860 memcpy(buf, req->data, (sizeof(*buf) > req->datalen) ? req->datalen : sizeof(*buf));
861 else if (req->op == X_INFO)
862 *((uint64_t *) req->data) = 4294967296;
864 req->state |= XS_SERVED;
865 req->serviced = req->size;
868 xseg_respond(xseg, dstport, req);
869 xseg_signal(xseg, dstport);
873 xseg_wait_signal(xseg, 10000000L);
881 void handle_reply(struct xseg_request *req)
883 if (!(req->state & XS_SERVED)) {
890 fwrite(req->data, 1, req->datalen, stdout);
900 fprintf(stderr, "size: %llu\n", (unsigned long long)*((uint64_t *)req->data));
908 if (xseg_put_request(xseg, req->portno, req))
909 fprintf(stderr, "Cannot put reply at port %u\n", req->portno);
912 int cmd_wait(uint32_t nr)
914 struct xseg_request *req;
918 req = xseg_receive(xseg, srcport);
927 ret = xseg_prepare_wait(xseg, srcport);
931 ret = xseg_wait_signal(xseg, 1000000);
932 ret = xseg_cancel_wait(xseg, srcport);
940 int cmd_put_replies(void)
942 struct xseg_request *req;
945 req = xseg_receive(xseg, dstport);
948 fprintf(stderr, "request: %08llx%08llx\n"
951 0LL, (unsigned long long)req->serial,
956 //fwrite(req->buffer, 1, req->bufferlen, stdout);
958 if (xseg_put_request(xseg, req->portno, req))
959 fprintf(stderr, "Cannot put reply\n");
965 int cmd_bind(long portno)
967 struct xseg_port *port = xseg_bind_port(xseg, portno);
969 fprintf(stderr, "failed to bind port %ld\n", portno);
973 fprintf(stderr, "bound port %u\n", xseg_portno(xseg, port));
977 int cmd_signal(uint32_t portno)
979 return xseg_signal(xseg, portno);
982 int parse_ports(char *str)
993 if ((s > str) && isdigit(str[0])) {
1007 if ((s > str) && isdigit(str[0])) {
1008 dstport = atol(str);
1019 int main(int argc, char **argv)
1031 if (xseg_parse_spec(spec, &cfg)) {
1032 fprintf(stderr, "Cannot parse spec\n");
1036 if (xseg_initialize()) {
1037 fprintf(stderr, "cannot initialize!\n");
1041 for (i = 2; i < argc; i++) {
1043 if (!strcmp(argv[i], "create")) {
1048 if (!strcmp(argv[i], "join")) {
1051 fprintf(stderr, "Segment joined.\n");
1055 if (!strcmp(argv[i], "destroy")) {
1056 ret = cmd_destroy();
1063 if (!strcmp(argv[i], "reportall")) {
1064 ret = cmd_reportall();
1068 if (!strcmp(argv[i], "bind") && (i + 1 < argc)) {
1069 ret = cmd_bind(atol(argv[i+1]));
1074 if (!strcmp(argv[i], "signal") && (i + 1 < argc)) {
1075 ret = cmd_signal(atol(argv[i+1]));
1080 if (!strcmp(argv[i], "bridge") && (i + 4 < argc)) {
1081 ret = cmd_bridge(atol(argv[i+1]),
1089 if (srcport == -1) {
1090 if (!parse_ports(argv[i]))
1091 fprintf(stderr, "source port undefined: %s\n", argv[i]);
1095 if (dstport == -1) {
1096 if (!parse_ports(argv[i]))
1097 fprintf(stderr, "destination port undefined: %s\n", argv[i]);
1101 if (!strcmp(argv[i], "report")) {
1102 ret = cmd_report(dstport);
1106 if (!strcmp(argv[i], "alloc_requests") && (i + 1 < argc)) {
1107 ret = cmd_alloc_requests(atol(argv[i+1]));
1112 if (!strcmp(argv[i], "free_requests") && (i + 1 < argc)) {
1113 ret = cmd_free_requests(atol(argv[i+1]));
1118 if (!strcmp(argv[i], "put_requests")) {
1119 ret = cmd_put_requests();
1123 if (!strcmp(argv[i], "put_replies")) {
1124 ret = cmd_put_replies();
1128 if (!strcmp(argv[i], "complete") && (i + 1 < argc)) {
1129 ret = cmd_finish(atol(argv[i+1]), 0);
1134 if (!strcmp(argv[i], "fail") && (i + 1 < argc)) {
1135 ret = cmd_finish(atol(argv[i+1]), 1);
1140 if (!strcmp(argv[i], "wait") && (i + 1 < argc)) {
1141 ret = cmd_wait(atol(argv[i+1]));
1146 if (!strcmp(argv[i], "rndwrite") && (i + 5 < argc)) {
1147 long nr_loops = atol(argv[i+1]);
1148 unsigned int seed = atoi(argv[i+2]);
1149 unsigned int targetlen = atoi(argv[i+3]);
1150 unsigned int chunksize = atoi(argv[i+4]);
1151 unsigned long objectsize = atol(argv[i+5]);
1152 ret = cmd_rndwrite(nr_loops, seed, targetlen, chunksize, objectsize);
1157 if (!strcmp(argv[i], "rndread") && (i + 5 < argc)) {
1158 long nr_loops = atol(argv[i+1]);
1159 unsigned int seed = atoi(argv[i+2]);
1160 unsigned int targetlen = atoi(argv[i+3]);
1161 unsigned int chunksize = atoi(argv[i+4]);
1162 unsigned long objectsize = atol(argv[i+5]);
1163 ret = cmd_rndread(nr_loops, seed, targetlen, chunksize, objectsize);
1168 if (!strcmp(argv[i], "submit_reqs") && (i + 3 < argc)) {
1169 long nr_loops = atol(argv[i+1]);
1170 long concurrent_reqs = atol(argv[i+2]);
1171 int op = atoi(argv[i+3]);
1172 ret = cmd_submit_reqs(nr_loops, concurrent_reqs, op);
1177 if (!strcmp(argv[i], "read") && (i + 3 < argc)) {
1178 char *target = argv[i+1];
1179 uint64_t offset = atol(argv[i+2]);
1180 uint64_t size = atol(argv[i+3]);
1181 ret = cmd_read(target, offset, size);
1186 if (!strcmp(argv[i], "write") && (i + 2 < argc)) {
1187 char *target = argv[i+1];
1188 uint64_t offset = atol(argv[i+2]);
1189 ret = cmd_write(target, offset);
1194 if (!strcmp(argv[i], "truncate") && (i + 2 < argc)) {
1195 char *target = argv[i+1];
1196 uint64_t offset = atol(argv[i+2]);
1197 ret = cmd_truncate(target, offset);
1202 if (!strcmp(argv[i], "delete") && (i + 1 < argc)) {
1203 char *target = argv[i+1];
1204 ret = cmd_delete(target);
1209 if (!strcmp(argv[i], "acquire") && (i + 1 < argc)) {
1210 char *target = argv[i+1];
1211 ret = cmd_acquire(target);
1216 if (!strcmp(argv[i], "release") && (i + 1 < argc)) {
1217 char *target = argv[i+1];
1218 ret = cmd_release(target);
1223 if (!strcmp(argv[i], "copy") && (i + 2) < argc) {
1224 char *src = argv[i+1];
1225 char *dst = argv[i+2];
1226 ret = cmd_copy(src, dst);
1231 if (!strcmp(argv[i], "clone") && (i + 2 < argc)) {
1232 char *src = argv[i+1];
1233 char *dst = argv[i+2];
1234 ret = cmd_clone(src, dst);
1239 if (!strcmp(argv[i], "info") && (i + 1 < argc)) {
1240 char *target = argv[i+1];
1241 ret = cmd_info(target);
1247 if (!parse_ports(argv[i]))
1248 fprintf(stderr, "invalid argument: %s\n", argv[i]);