added speer skeletor
[archipelago] / xseg / peers / user / vlmc-tool.c
1 #define _GNU_SOURCE
2 #include <stdio.h>
3 #include <stdlib.h>
4 #include <string.h>
5 #include <stdint.h>
6 #include <ctype.h>
7 #include <sys/stat.h>
8 #include <sys/types.h>
9 #include <fcntl.h>
10 #include <unistd.h>
11
12 #include <xseg/xseg.h>
13 #include <xseg/protocol.h>
14
15 #define MAX_ARG_LEN 255
16 int safe_strlen(char *s)
17 {
18         int i;
19         if (!s)
20                 return -1;
21
22         for (i = 0; i < MAX_ARG_LEN; i++) {
23                 if (!*s) 
24                         return i;
25                 s++;
26         }
27         return -1;
28 }
29
30 int validate_alphanumeric(char *s)
31 {
32         int i;
33         int len = safe_strlen(s);
34         if (len <= 0){
35                 return 0;
36         }
37
38         for (i = 0; i < len; i++) {
39                 if (!isalnum(*s)&&*s!='-'&&*s!='.')
40                         return 0;
41                 s++;
42         }
43         return 1;
44 }
45
46 int validate_numeric(char *s)
47 {
48         int i;
49         int len = safe_strlen(s);
50         if (len <= 0)
51                 return 0;
52
53         for (i = 0; i < len; i++) {
54                 if (!isdigit(*s))
55                         return 0;
56                 s++;
57         }
58         return 1;
59 }
60
61 char *spec = "segdev:xsegbd:16:1024:12";
62 struct xseg *xseg;
63 struct xseg_config cfg;
64 xport srcport = NoPort;
65 xport sport = NoPort;
66 struct xseg_port *port;
67 xport mportno;
68
69 static void init_local_signal() 
70 {
71         if (xseg && sport != srcport){
72                 xseg_init_local_signal(xseg, srcport);
73                 sport = srcport;
74         }
75 }
76
77 int wait_reply(struct xseg_request *expected_req)
78 {
79         struct xseg_request *rec;
80         xseg_prepare_wait(xseg, srcport);
81         while(1) {
82                 rec = xseg_receive(xseg, srcport, 0);
83                 if (rec) {
84                         if (rec != expected_req) {
85                                 fprintf(stderr, "Unknown received req. Putting req.\n");
86                                 xseg_put_request(xseg, rec, srcport);
87                         } else  if (!(rec->state & XS_SERVED)) {
88                                 fprintf(stderr, "Failed req\n");
89                                 return -1;
90                         } else {
91                                 break;
92                         }
93                 }
94                 xseg_wait_signal(xseg, 1000000UL);
95         }
96         xseg_cancel_wait(xseg, srcport);
97
98         return 0;
99 }
100
101 int vlmc_create(char *name, uint64_t size, char *snap)
102 {
103         int ret;
104         int targetlen = safe_strlen(name);
105         int snaplen = safe_strlen(snap);
106         if (targetlen <= 0) {
107                 fprintf(stderr, "Invalid name\n");
108                 return -1;
109         }
110         if (snaplen <= 0 && size == -1) {
111                 fprintf(stderr, "Size or snap must be provided in create\n");
112                 return -1;
113         }
114         XSEGLOG("Name: %s", name);
115         XSEGLOG("Snap: %s", snap);
116
117         struct xseg_request *req = xseg_get_request(xseg, srcport, mportno, X_ALLOC);
118         if (!req) {
119                 fprintf(stderr, "Couldn't allocate xseg request\n");
120                 return -1;
121         }
122         int r = xseg_prep_request(xseg, req, targetlen, sizeof(struct xseg_request_clone));
123         if (r < 0){
124                 fprintf(stderr, "Couldn't prep xseg request\n");
125                 xseg_put_request(xseg, req, srcport);
126                 return -1;
127         }
128         char *target = xseg_get_target(xseg, req);
129         strncpy(target, name, targetlen);
130         struct xseg_request_clone *xclone = (struct xseg_request_clone *) xseg_get_data(xseg, req);
131         if (snaplen <= 0){
132                 memset(xclone->target, 0, XSEG_MAX_TARGETLEN);
133                 xclone->targetlen = 0;
134         }
135         else {
136                 strncpy(xclone->target, snap, snaplen);
137                 xclone->targetlen = snaplen;
138         }
139         xclone->size = size;
140         req->offset = 0;
141         req->size = req->datalen;
142         req->op = X_CLONE;
143
144         xport p = xseg_submit(xseg, req, srcport, X_ALLOC);
145         if (p == NoPort){
146                 fprintf(stderr, "couldn't submit req\n");
147                 xseg_put_request(xseg, req, srcport);
148                 return -1;
149         }
150         xseg_signal(xseg, p);
151
152         ret = wait_reply(req);
153         
154         xseg_put_request(xseg, req, srcport);
155
156         return ret;
157 }
158
159 int vlmc_snapshot(char *name)
160 {
161         return -1;
162 }
163
164 int vlmc_remove(char *name)
165 {
166         int targetlen = safe_strlen(name);
167         if (targetlen <= 0) {
168                 fprintf(stderr, "Invalid name\n");
169                 return -1;
170         }
171
172         struct xseg_request *req = xseg_get_request(xseg, srcport, mportno, X_ALLOC);
173         if (!req) {
174                 fprintf(stderr, "Couldn't allocate xseg request\n");
175                 return -1;
176         }
177         int r = xseg_prep_request(xseg, req, targetlen, 0);
178         if (r < 0){
179                 fprintf(stderr, "Couldn't prep xseg request\n");
180                 xseg_put_request(xseg, req, srcport);
181                 return -1;
182         }
183         char *target = xseg_get_target(xseg, req);
184         strncpy(target, name, targetlen);
185         req->offset = 0;
186         req->size = req->datalen;
187         req->op = X_DELETE;
188         
189         xport p = xseg_submit(xseg, req, srcport, X_ALLOC);
190         if (p == NoPort){
191                 fprintf(stderr, "couldn't submit req\n");
192                 xseg_put_request(xseg, req, srcport);
193                 return -1;
194         }
195         xseg_signal(xseg, p);
196         
197         wait_reply(req);
198         
199         xseg_put_request(xseg, req, srcport);
200
201         return 0;
202 }
203
204 int vlmc_resize(char *name, uint64_t size)
205 {
206         return 0;
207 }
208
209 int vlmc_map(char *name)
210 {
211         /*
212         char cmd[1024];
213         char buf[1024];
214         int fd;
215         xport p;
216
217
218         for (p = 2; p < cfg.nr_ports; p++) {
219                 sprintf(buf, "%sdevices/%u/srcport", XSEGBD_SYSFS, p);
220                 fd = open(buf, O_RDONLY);
221                 if (fd < 0 && errno == ENOENT)
222                         break;
223         }
224         if (p == cfg.nr_ports){
225                 fprintf(stderr, "No available port\n");
226                 return -1;
227         }
228
229         sprintf(cmd, "%s %u:%u:%u", name, p, VPORT, REQS);      
230         sprintf(buf, "%sadd", XSEGBD_SYSFS);
231         fd = open(add, O_WRONLY);
232         if (fd < 0) {
233                 fprintf(stderr, "Cannot open sysfs add\n");
234                 return -1;
235         }
236         r = write(fd, cmd, strlen(cmd));
237         if (r < 0){
238                 fprintf(stderr, "write error\n");
239                 return -1;
240         }
241         */
242
243         return 0;
244 }
245
246 int vlmc_unmap(char *name)
247 {
248         return 0;
249 }
250
251 int vlmc_list()
252 {
253         return 0;
254 }
255
256 #define err_in_arg(__i, __arg) do {                                     \
257         fprintf(stderr, "Error in argument %d (%s)\n", __i, __arg);     \
258         exit(-1);                                                       \
259         } while(0)
260
261 int main(int argc, char *argv[])
262 {
263         int i;
264         if (argc < 6){
265                 fprintf(stderr, "insufficient arguments\n");
266                 return -1;
267         }
268
269         spec = argv[1];
270         if (xseg_parse_spec(spec, &cfg)) {
271                 fprintf(stderr, "Cannot parse spec\n");
272                 return -1;
273         }
274
275         if (xseg_initialize()) {
276                 fprintf(stderr, "cannot initialize!\n");
277                 return -1;
278         }
279
280         xseg = xseg_join(cfg.type, cfg.name, "posix", NULL);
281         if (!xseg) {
282                 fprintf(stderr, "cannot join segment!\n");
283                 return -1;
284         }
285         init_local_signal();
286
287         char *name = NULL;
288         char *snap = NULL;
289         uint64_t size = -1;
290         //char *pool = NULL;
291         char *config = NULL;
292
293         for (i = 3; i < argc; i++) {
294                 if ((!strcmp(argv[i], "-s") || !strcmp(argv[i], "--size")) && i+1 < argc){
295                         if (!validate_numeric(argv[i+1])){
296                                 err_in_arg(i, argv[i]);
297                         } else {
298                                 size = atol(argv[i+1]);
299                                 i++;
300                         }
301                 }else if ((!strcmp(argv[i], "-c") || !strcmp(argv[i], "--config")) && i+1 < argc){
302                         if (!validate_alphanumeric(argv[i+1])){
303                                 err_in_arg(i, argv[i]);
304                         } else {
305                                 config = argv[i+1];
306                                 i++;
307                         }
308                 } else if (!strcmp(argv[i], "--snap") && i+1 < argc){
309                         if (!validate_alphanumeric(argv[i+1])){
310                                 err_in_arg(i, argv[i]);
311                         } else {
312                                 snap = argv[i+1];
313                                 i++;
314                         }
315                 } else if (!strcmp(argv[i], "-mp") && i+1 < argc){
316                         if (!validate_numeric(argv[i+1])){
317                                 err_in_arg(i, argv[i]);
318                         } else {
319                                 mportno = atol(argv[i+1]);
320                                 i++;
321                         }
322                 } else if (!strcmp(argv[i], "-p") && i+1 < argc){
323                         if (!validate_alphanumeric(argv[i+1])){
324                                 err_in_arg(i, argv[i]);
325                         } else {
326                                 srcport = atol(argv[i+1]);
327                                 i++;
328                         }
329                 } else if (!strcmp(argv[i], "--name") && i+1 < argc){
330                         if (!validate_alphanumeric(argv[i+1])){
331                                 err_in_arg(i, argv[i]);
332                         } else {
333                                 name = argv[i+1];
334                                 i++;
335                         }
336                 } else {
337                         err_in_arg(i, argv[i]);
338                 }
339         }
340
341         if (srcport > cfg.nr_ports || mportno > cfg.nr_ports) {
342                 fprintf(stderr, "Invalid port\n");
343                 return -1;
344         }
345
346         port = xseg_bind_port(xseg, srcport, NULL);
347         if (!port) {
348                 fprintf(stderr, "Error binding port %u\n", srcport);
349                 exit(-1);
350         }
351
352         int ret = -1;
353
354         if (!strcmp(argv[2], "create")) 
355                 ret = vlmc_create(name, size, snap);
356         else if (!strcmp(argv[2], "remove"))
357                 ret = vlmc_remove(name);
358 /*
359         else if (!strcmp(argv[2], "map"))
360                 ret = vlmc_map(name);
361         else if (!strcmp(argv[2], "unmap"))
362                 ret = vlmc_unmap(name);
363         else if (!strcmp(argv[2], "showmapped"))
364                 ret = vlmc_showmapped();
365         else if (!strcmp(argv[2], "list") || !(strcmp(argv[2], "ls"))
366                 ret = vlmc_list();
367 */
368         else if (!strcmp(argv[2], "resize"))
369                 ret = vlmc_resize(name, size);
370         else
371                 fprintf(stderr, "unknown action (%s)\n", argv[2]);
372
373         return ret;
374 }
375