add mt-sosd stat before writing in snapshotting
[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;
102
103 static void init_local_signal() 
104 {
105         if (xseg && sport != srcport){
106                 xseg_init_local_signal(xseg, srcport);
107                 sport = srcport;
108         }
109 }
110
111 int wait_reply(struct xseg_request *expected_req)
112 {
113         struct xseg_request *rec;
114         xseg_prepare_wait(xseg, srcport);
115         while(1) {
116                 rec = xseg_receive(xseg, srcport, 0);
117                 if (rec) {
118                         if (rec != expected_req) {
119                                 fprintf(stderr, "Unknown received req. Putting req.\n");
120                                 xseg_put_request(xseg, rec, srcport);
121                         } else  if (!(rec->state & XS_SERVED)) {
122                                 fprintf(stderr, "Failed req\n");
123                                 return -1;
124                         } else {
125                                 break;
126                         }
127                 }
128                 xseg_wait_signal(xseg, 1000000UL);
129         }
130         xseg_cancel_wait(xseg, srcport);
131
132         return 0;
133 }
134
135 int vlmc_create(char *name, uint64_t size, char *snap)
136 {
137         int ret;
138         int targetlen = safe_strlen(name);
139         int snaplen = safe_strlen(snap);
140         if (targetlen <= 0) {
141                 fprintf(stderr, "Invalid name\n");
142                 return -1;
143         }
144         if (snaplen <= 0 && size == -1) {
145                 fprintf(stderr, "Size or snap must be provided in create\n");
146                 return -1;
147         }
148         XSEGLOG("Name: %s", name);
149         XSEGLOG("Snap: %s", snap);
150
151         struct xseg_request *req = xseg_get_request(xseg, srcport, mportno, X_ALLOC);
152         if (!req) {
153                 fprintf(stderr, "Couldn't allocate xseg request\n");
154                 return -1;
155         }
156         int r = xseg_prep_request(xseg, req, targetlen, sizeof(struct xseg_request_clone));
157         if (r < 0){
158                 fprintf(stderr, "Couldn't prep xseg request\n");
159                 xseg_put_request(xseg, req, srcport);
160                 return -1;
161         }
162         //FIXME what to do if no snap ? how do i send mapper to create a non copy up volume?
163         char *target = xseg_get_target(xseg, req);
164         strncpy(target, name, targetlen);
165         struct xseg_request_clone *xclone = (struct xseg_request_clone *) xseg_get_data(xseg, req);
166         if (snaplen <= 0){
167                 memset(xclone->target, 0, XSEG_MAX_TARGETLEN);
168                 xclone->targetlen = 0;
169         }
170         else {
171                 strncpy(xclone->target, snap, snaplen);
172                 xclone->targetlen = snaplen;
173         }
174         xclone->size = size;
175         req->offset = 0;
176         req->size = req->datalen;
177         req->op = X_CLONE;
178
179         xport p = xseg_submit(xseg, req, srcport, X_ALLOC);
180         if (p == NoPort){
181                 fprintf(stderr, "couldn't submit req\n");
182                 xseg_put_request(xseg, req, srcport);
183                 return -1;
184         }
185         xseg_signal(xseg, p);
186
187         ret = wait_reply(req);
188         
189         xseg_put_request(xseg, req, srcport);
190
191         return ret;
192 }
193
194 int vlmc_snapshot(char *name)
195 {
196         return -1;
197 }
198
199 int vlmc_remove(char *name)
200 {
201         int targetlen = safe_strlen(name);
202         if (targetlen <= 0) {
203                 fprintf(stderr, "Invalid name\n");
204                 return -1;
205         }
206
207         struct xseg_request *req = xseg_get_request(xseg, srcport, mportno, X_ALLOC);
208         if (!req) {
209                 fprintf(stderr, "Couldn't allocate xseg request\n");
210                 return -1;
211         }
212         int r = xseg_prep_request(xseg, req, targetlen, 0);
213         if (r < 0){
214                 fprintf(stderr, "Couldn't prep xseg request\n");
215                 xseg_put_request(xseg, req, srcport);
216                 return -1;
217         }
218         char *target = xseg_get_target(xseg, req);
219         strncpy(target, name, targetlen);
220         req->offset = 0;
221         req->size = req->datalen;
222         req->op = X_DELETE;
223         
224         xport p = xseg_submit(xseg, req, srcport, X_ALLOC);
225         if (p == NoPort){
226                 fprintf(stderr, "couldn't submit req\n");
227                 xseg_put_request(xseg, req, srcport);
228                 return -1;
229         }
230         xseg_signal(xseg, p);
231         
232         wait_reply(req);
233         
234         xseg_put_request(xseg, req, srcport);
235
236         return 0;
237 }
238
239 int vlmc_resize(char *name, uint64_t size)
240 {
241         return 0;
242 }
243
244 int vlmc_map(char *name)
245 {
246         /*
247         char cmd[1024];
248         char buf[1024];
249         int fd;
250         xport p;
251
252
253         for (p = 2; p < cfg.nr_ports; p++) {
254                 sprintf(buf, "%sdevices/%u/srcport", XSEGBD_SYSFS, p);
255                 fd = open(buf, O_RDONLY);
256                 if (fd < 0 && errno == ENOENT)
257                         break;
258         }
259         if (p == cfg.nr_ports){
260                 fprintf(stderr, "No available port\n");
261                 return -1;
262         }
263
264         sprintf(cmd, "%s %u:%u:%u", name, p, VPORT, REQS);      
265         sprintf(buf, "%sadd", XSEGBD_SYSFS);
266         fd = open(add, O_WRONLY);
267         if (fd < 0) {
268                 fprintf(stderr, "Cannot open sysfs add\n");
269                 return -1;
270         }
271         r = write(fd, cmd, strlen(cmd));
272         if (r < 0){
273                 fprintf(stderr, "write error\n");
274                 return -1;
275         }
276         */
277
278         return 0;
279 }
280
281 int vlmc_unmap(char *name)
282 {
283         return 0;
284 }
285
286 int vlmc_list()
287 {
288         return 0;
289 }
290
291 #define err_in_arg(__i, __arg) do {                                     \
292         fprintf(stderr, "Error in argument %d (%s)\n", __i, __arg);     \
293         exit(-1);                                                       \
294         } while(0)
295
296 int main(int argc, char *argv[])
297 {
298         int i;
299         if (argc < 6){
300                 fprintf(stderr, "insufficient arguments\n");
301                 return -1;
302         }
303
304         spec = argv[1];
305         if (xseg_parse_spec(spec, &cfg)) {
306                 fprintf(stderr, "Cannot parse spec\n");
307                 return -1;
308         }
309
310         if (xseg_initialize()) {
311                 fprintf(stderr, "cannot initialize!\n");
312                 return -1;
313         }
314
315         xseg = xseg_join(cfg.type, cfg.name, "posix", NULL);
316         if (!xseg) {
317                 fprintf(stderr, "cannot join segment!\n");
318                 return -1;
319         }
320         init_local_signal();
321
322         char *name = NULL;
323         char *snap = NULL;
324         uint64_t size = -1;
325         //char *pool = NULL;
326 //      char *config = NULL;
327
328         for (i = 3; i < argc; i++) {
329                 if ((!strcmp(argv[i], "-s") || !strcmp(argv[i], "--size")) && i+1 < argc){
330                         if (!validate_numeric(argv[i+1])){
331                                 err_in_arg(i, argv[i]);
332                         } else {
333                                 size = atol(argv[i+1]);
334                                 i++;
335                         }
336 /*
337                 }else if ((!strcmp(argv[i], "-c") || !strcmp(argv[i], "--config")) && i+1 < argc){
338                         if (!validate_alphanumeric(argv[i+1])){
339                                 err_in_arg(i, argv[i]);
340                         } else {
341                                 config = argv[i+1];
342                                 i++;
343                         }
344 */
345                 } else if (!strcmp(argv[i], "--snap") && i+1 < argc){
346                         if (!validate_alphanumeric(argv[i+1])){
347                                 err_in_arg(i, argv[i]);
348                         } else {
349                                 snap = argv[i+1];
350                                 i++;
351                         }
352                 } else if (!strcmp(argv[i], "-mp") && i+1 < argc){
353                         if (!validate_numeric(argv[i+1])){
354                                 err_in_arg(i, argv[i]);
355                         } else {
356                                 mportno = atol(argv[i+1]);
357                                 i++;
358                         }
359                 } else if (!strcmp(argv[i], "-p") && i+1 < argc){
360                         if (!validate_alphanumeric(argv[i+1])){
361                                 err_in_arg(i, argv[i]);
362                         } else {
363                                 srcport = atol(argv[i+1]);
364                                 i++;
365                         }
366                 } else if (!strcmp(argv[i], "--name") && i+1 < argc){
367                         if (!validate_alphanumeric(argv[i+1])){
368                                 err_in_arg(i, argv[i]);
369                         } else {
370                                 name = argv[i+1];
371                                 i++;
372                         }
373                 } else {
374                         err_in_arg(i, argv[i]);
375                 }
376         }
377
378         if (srcport > cfg.nr_ports || mportno > cfg.nr_ports) {
379                 fprintf(stderr, "Invalid port\n");
380                 return -1;
381         }
382
383         port = xseg_bind_port(xseg, srcport, NULL);
384         if (!port) {
385                 fprintf(stderr, "Error binding port %u\n", srcport);
386                 exit(-1);
387         }
388
389         int ret = -1;
390
391         if (!strcmp(argv[2], "create")) 
392                 ret = vlmc_create(name, size, snap);
393         else if (!strcmp(argv[2], "remove"))
394                 ret = vlmc_remove(name);
395 /*
396         else if (!strcmp(argv[2], "map"))
397                 ret = vlmc_map(name);
398         else if (!strcmp(argv[2], "unmap"))
399                 ret = vlmc_unmap(name);
400         else if (!strcmp(argv[2], "showmapped"))
401                 ret = vlmc_showmapped();
402         else if (!strcmp(argv[2], "list") || !(strcmp(argv[2], "ls"))
403                 ret = vlmc_list();
404 */
405         else if (!strcmp(argv[2], "resize"))
406                 ret = vlmc_resize(name, size);
407         else
408                 fprintf(stderr, "unknown action (%s)\n", argv[2]);
409
410         return ret;
411 }
412