Complete unification of thread_loop/peerd_loop
[archipelago] / xseg / peers / user / vlmc-tool.c
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 <string.h>
39 #include <stdint.h>
40 #include <ctype.h>
41 #include <sys/stat.h>
42 #include <sys/types.h>
43 #include <fcntl.h>
44 #include <unistd.h>
45
46 #include <xseg/xseg.h>
47 #include <xseg/protocol.h>
48
49 #define MAX_ARG_LEN 255
50 int safe_strlen(char *s)
51 {
52         int i;
53         if (!s)
54                 return -1;
55
56         for (i = 0; i < MAX_ARG_LEN; i++) {
57                 if (!*s) 
58                         return i;
59                 s++;
60         }
61         return -1;
62 }
63
64 int validate_alphanumeric(char *s)
65 {
66         int i;
67         int len = safe_strlen(s);
68         if (len <= 0){
69                 return 0;
70         }
71
72         for (i = 0; i < len; i++) {
73                 if (!isalnum(*s)&&*s!='-'&&*s!='.')
74                         return 0;
75                 s++;
76         }
77         return 1;
78 }
79
80 int validate_numeric(char *s)
81 {
82         int i;
83         int len = safe_strlen(s);
84         if (len <= 0)
85                 return 0;
86
87         for (i = 0; i < len; i++) {
88                 if (!isdigit(*s))
89                         return 0;
90                 s++;
91         }
92         return 1;
93 }
94
95 char *spec = "segdev:xsegbd:16:1024:12";
96 struct xseg *xseg;
97 struct xseg_config cfg;
98 xport srcport = NoPort;
99 xport sport = NoPort;
100 struct xseg_port *port;
101 xport mportno = NoPort;
102 xport vportno = NoPort;
103
104 static void init_local_signal() 
105 {
106         if (xseg && sport != srcport){
107                 xseg_init_local_signal(xseg, srcport);
108                 sport = srcport;
109         }
110 }
111
112 int wait_reply(struct xseg_request *expected_req)
113 {
114         struct xseg_request *rec;
115         xseg_prepare_wait(xseg, srcport);
116         while(1) {
117                 rec = xseg_receive(xseg, srcport, 0);
118                 if (rec) {
119                         if (rec != expected_req) {
120                                 fprintf(stderr, "Unknown received req. Putting req.\n");
121                                 xseg_put_request(xseg, rec, srcport);
122                         } else  if (!(rec->state & XS_SERVED)) {
123                                 fprintf(stderr, "Failed req\n");
124                                 return -1;
125                         } else {
126                                 break;
127                         }
128                 }
129                 xseg_wait_signal(xseg, 1000000UL);
130         }
131         xseg_cancel_wait(xseg, srcport);
132
133         return 0;
134 }
135
136 int vlmc_create(char *name, uint64_t size, char *snap)
137 {
138         int ret;
139         int targetlen = safe_strlen(name);
140         int snaplen = safe_strlen(snap);
141         if (targetlen <= 0) {
142                 fprintf(stderr, "Invalid name\n");
143                 return -1;
144         }
145         if (snaplen <= 0 && size == -1) {
146                 fprintf(stderr, "Size or snap must be provided in create\n");
147                 return -1;
148         }
149         XSEGLOG("Name: %s", name);
150         XSEGLOG("Snap: %s", snap);
151
152         struct xseg_request *req = xseg_get_request(xseg, srcport, mportno, X_ALLOC);
153         if (!req) {
154                 fprintf(stderr, "Couldn't allocate xseg request\n");
155                 return -1;
156         }
157         int r = xseg_prep_request(xseg, req, targetlen, sizeof(struct xseg_request_clone));
158         if (r < 0){
159                 fprintf(stderr, "Couldn't prep xseg request\n");
160                 xseg_put_request(xseg, req, srcport);
161                 return -1;
162         }
163         //FIXME what to do if no snap ? how do i send mapper to create a non copy up volume?
164         char *target = xseg_get_target(xseg, req);
165         strncpy(target, name, targetlen);
166         struct xseg_request_clone *xclone = (struct xseg_request_clone *) xseg_get_data(xseg, req);
167         if (snaplen <= 0){
168                 memset(xclone->target, 0, XSEG_MAX_TARGETLEN);
169                 xclone->targetlen = 0;
170         }
171         else {
172                 strncpy(xclone->target, snap, snaplen);
173                 xclone->targetlen = snaplen;
174         }
175         xclone->size = size;
176         req->offset = 0;
177         req->size = req->datalen;
178         req->op = X_CLONE;
179
180         xport p = xseg_submit(xseg, req, srcport, X_ALLOC);
181         if (p == NoPort){
182                 fprintf(stderr, "couldn't submit req\n");
183                 xseg_put_request(xseg, req, srcport);
184                 return -1;
185         }
186         xseg_signal(xseg, p);
187
188         ret = wait_reply(req);
189         
190         xseg_put_request(xseg, req, srcport);
191
192         return ret;
193 }
194
195 int vlmc_snapshot(char *name)
196 {
197         int targetlen = safe_strlen(name);
198         if (targetlen <= 0) {
199                 fprintf(stderr, "Invalid name\n");
200                 return -1;
201         }
202
203         struct xseg_request *req = xseg_get_request(xseg, srcport, vportno, X_ALLOC);
204         if (!req) {
205                 fprintf(stderr, "Couldn't allocate xseg request\n");
206                 return -1;
207         }
208         int r = xseg_prep_request(xseg, req, targetlen, sizeof(struct xseg_request_snapshot));
209         if (r < 0){
210                 fprintf(stderr, "Couldn't prep xseg request\n");
211                 xseg_put_request(xseg, req, srcport);
212                 return -1;
213         }
214         char *target = xseg_get_target(xseg, req);
215         strncpy(target, name, targetlen);
216         struct xseg_request_snapshot *xsnapshot = (struct xseg_request_snapshot *) xseg_get_data(xseg, req);
217         xsnapshot->target[0] = 0;
218         xsnapshot->targetlen = 0;
219         req->offset = 0;
220         req->size = req->datalen;
221         req->op = X_SNAPSHOT;
222
223         xport p = xseg_submit(xseg, req, srcport, X_ALLOC);
224         if (p == NoPort){
225                 fprintf(stderr, "couldn't submit req\n");
226                 xseg_put_request(xseg, req, srcport);
227                 return -1;
228         }
229         xseg_signal(xseg, p);
230
231         r = wait_reply(req);
232         if (!r){
233                 struct xseg_reply_snapshot *xreply = (struct xseg_reply_snapshot *) xseg_get_data(xseg, req);
234                 char buf[XSEG_MAX_TARGETLEN + 1];
235                 strncpy(buf, xreply->target, xreply->targetlen);
236                 buf[xreply->targetlen] = 0;
237                 fprintf(stdout, "Snapshot name: %s\n", buf);
238         }
239
240         xseg_put_request(xseg, req, srcport);
241
242         return r;
243 }
244
245 int vlmc_remove(char *name)
246 {
247         int targetlen = safe_strlen(name);
248         if (targetlen <= 0) {
249                 fprintf(stderr, "Invalid name\n");
250                 return -1;
251         }
252
253         struct xseg_request *req = xseg_get_request(xseg, srcport, mportno, X_ALLOC);
254         if (!req) {
255                 fprintf(stderr, "Couldn't allocate xseg request\n");
256                 return -1;
257         }
258         int r = xseg_prep_request(xseg, req, targetlen, 0);
259         if (r < 0){
260                 fprintf(stderr, "Couldn't prep xseg request\n");
261                 xseg_put_request(xseg, req, srcport);
262                 return -1;
263         }
264         char *target = xseg_get_target(xseg, req);
265         strncpy(target, name, targetlen);
266         req->offset = 0;
267         req->size = req->datalen;
268         req->op = X_DELETE;
269         
270         xport p = xseg_submit(xseg, req, srcport, X_ALLOC);
271         if (p == NoPort){
272                 fprintf(stderr, "couldn't submit req\n");
273                 xseg_put_request(xseg, req, srcport);
274                 return -1;
275         }
276         xseg_signal(xseg, p);
277         
278         wait_reply(req);
279         
280         xseg_put_request(xseg, req, srcport);
281
282         return 0;
283 }
284
285 int vlmc_resize(char *name, uint64_t size)
286 {
287         return 0;
288 }
289
290 int vlmc_map(char *name)
291 {
292         /*
293         char cmd[1024];
294         char buf[1024];
295         int fd;
296         xport p;
297
298
299         for (p = 2; p < cfg.nr_ports; p++) {
300                 sprintf(buf, "%sdevices/%u/srcport", XSEGBD_SYSFS, p);
301                 fd = open(buf, O_RDONLY);
302                 if (fd < 0 && errno == ENOENT)
303                         break;
304         }
305         if (p == cfg.nr_ports){
306                 fprintf(stderr, "No available port\n");
307                 return -1;
308         }
309
310         sprintf(cmd, "%s %u:%u:%u", name, p, VPORT, REQS);      
311         sprintf(buf, "%sadd", XSEGBD_SYSFS);
312         fd = open(add, O_WRONLY);
313         if (fd < 0) {
314                 fprintf(stderr, "Cannot open sysfs add\n");
315                 return -1;
316         }
317         r = write(fd, cmd, strlen(cmd));
318         if (r < 0){
319                 fprintf(stderr, "write error\n");
320                 return -1;
321         }
322         */
323
324         return 0;
325 }
326
327 int vlmc_unmap(char *name)
328 {
329         return 0;
330 }
331
332 int vlmc_list()
333 {
334         return 0;
335 }
336
337 #define err_in_arg(__i, __arg) do {                                     \
338         fprintf(stderr, "Error in argument %d (%s)\n", __i, __arg);     \
339         exit(-1);                                                       \
340         } while(0)
341
342 int main(int argc, char *argv[])
343 {
344         int i;
345         if (argc < 6){
346                 fprintf(stderr, "insufficient arguments\n");
347                 return -1;
348         }
349
350         spec = argv[1];
351         if (xseg_parse_spec(spec, &cfg)) {
352                 fprintf(stderr, "Cannot parse spec\n");
353                 return -1;
354         }
355
356         if (xseg_initialize()) {
357                 fprintf(stderr, "cannot initialize!\n");
358                 return -1;
359         }
360
361         xseg = xseg_join(cfg.type, cfg.name, "posix", NULL);
362         if (!xseg) {
363                 fprintf(stderr, "cannot join segment!\n");
364                 return -1;
365         }
366         init_local_signal();
367
368         char *name = NULL;
369         char *snap = NULL;
370         uint64_t size = -1;
371         //char *pool = NULL;
372 //      char *config = NULL;
373
374         for (i = 3; i < argc; i++) {
375                 if ((!strcmp(argv[i], "-s") || !strcmp(argv[i], "--size")) && i+1 < argc){
376                         if (!validate_numeric(argv[i+1])){
377                                 err_in_arg(i, argv[i]);
378                         } else {
379                                 size = atol(argv[i+1]);
380                                 i++;
381                         }
382 /*
383                 }else if ((!strcmp(argv[i], "-c") || !strcmp(argv[i], "--config")) && i+1 < argc){
384                         if (!validate_alphanumeric(argv[i+1])){
385                                 err_in_arg(i, argv[i]);
386                         } else {
387                                 config = argv[i+1];
388                                 i++;
389                         }
390 */
391                 } else if (!strcmp(argv[i], "--snap") && i+1 < argc){
392                         if (!validate_alphanumeric(argv[i+1])){
393                                 err_in_arg(i, argv[i]);
394                         } else {
395                                 snap = argv[i+1];
396                                 i++;
397                         }
398                 } else if (!strcmp(argv[i], "-mp") && i+1 < argc){
399                         if (!validate_numeric(argv[i+1])){
400                                 err_in_arg(i, argv[i]);
401                         } else {
402                                 mportno = atol(argv[i+1]);
403                                 i++;
404                         }
405                 } else if (!strcmp(argv[i], "-vp") && i+1 < argc){
406                         if (!validate_numeric(argv[i+1])){
407                                 err_in_arg(i, argv[i]);
408                         } else {
409                                 vportno = atol(argv[i+1]);
410                                 i++;
411                         }
412                 } else if (!strcmp(argv[i], "-p") && i+1 < argc){
413                         if (!validate_alphanumeric(argv[i+1])){
414                                 err_in_arg(i, argv[i]);
415                         } else {
416                                 srcport = atol(argv[i+1]);
417                                 i++;
418                         }
419                 } else if (!strcmp(argv[i], "--name") && i+1 < argc){
420                         if (!validate_alphanumeric(argv[i+1])){
421                                 err_in_arg(i, argv[i]);
422                         } else {
423                                 name = argv[i+1];
424                                 i++;
425                         }
426                 } else {
427                         err_in_arg(i, argv[i]);
428                 }
429         }
430
431         if (srcport > cfg.nr_ports || mportno > cfg.nr_ports || vportno > cfg.nr_ports) {
432                 fprintf(stderr, "Invalid port\n");
433                 return -1;
434         }
435
436         port = xseg_bind_port(xseg, srcport, NULL);
437         if (!port) {
438                 fprintf(stderr, "Error binding port %u\n", srcport);
439                 exit(-1);
440         }
441
442         int ret = -1;
443
444         if (!strcmp(argv[2], "create")) 
445                 ret = vlmc_create(name, size, snap);
446         else if (!strcmp(argv[2], "remove"))
447                 ret = vlmc_remove(name);
448 /*
449         else if (!strcmp(argv[2], "map"))
450                 ret = vlmc_map(name);
451         else if (!strcmp(argv[2], "unmap"))
452                 ret = vlmc_unmap(name);
453         else if (!strcmp(argv[2], "showmapped"))
454                 ret = vlmc_showmapped();
455         else if (!strcmp(argv[2], "list") || !(strcmp(argv[2], "ls"))
456                 ret = vlmc_list();
457 */
458         else if (!strcmp(argv[2], "resize"))
459                 ret = vlmc_resize(name, size);
460         else if (!strcmp(argv[2], "snapshot"))
461                 ret = vlmc_snapshot(name);
462         else
463                 fprintf(stderr, "unknown action (%s)\n", argv[2]);
464
465         return ret;
466 }
467