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