1*72b890efSkettenis /* $OpenBSD: mdstore.c,v 1.14 2021/02/01 16:27:06 kettenis Exp $ */
2cceaa36bSkettenis
3cceaa36bSkettenis /*
4cceaa36bSkettenis * Copyright (c) 2012 Mark Kettenis
5cceaa36bSkettenis *
6cceaa36bSkettenis * Permission to use, copy, modify, and distribute this software for any
7cceaa36bSkettenis * purpose with or without fee is hereby granted, provided that the above
8cceaa36bSkettenis * copyright notice and this permission notice appear in all copies.
9cceaa36bSkettenis *
10cceaa36bSkettenis * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
11cceaa36bSkettenis * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
12cceaa36bSkettenis * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
13cceaa36bSkettenis * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
14cceaa36bSkettenis * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
15cceaa36bSkettenis * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
16cceaa36bSkettenis * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
17cceaa36bSkettenis */
18cceaa36bSkettenis
196aace0ceSkettenis #include <assert.h>
20dc8fdf3dSkettenis #include <err.h>
21cceaa36bSkettenis #include <stdio.h>
226aace0ceSkettenis #include <stdlib.h>
23cceaa36bSkettenis #include <string.h>
24a0709405Skettenis #include <time.h>
25cceaa36bSkettenis
26cceaa36bSkettenis #include "ds.h"
27bb93e559Skettenis #include "mdesc.h"
28cceaa36bSkettenis #include "mdstore.h"
29d73a4c4fSkn #include "ldom_util.h"
30bb93e559Skettenis #include "ldomctl.h"
31cceaa36bSkettenis
32cceaa36bSkettenis void mdstore_start(struct ldc_conn *, uint64_t);
33a0709405Skettenis void mdstore_start_v2(struct ldc_conn *, uint64_t);
344b9ab11dSkettenis void mdstore_start_v3(struct ldc_conn *, uint64_t);
35cceaa36bSkettenis void mdstore_rx_data(struct ldc_conn *, uint64_t, void *, size_t);
36cceaa36bSkettenis
37cceaa36bSkettenis struct ds_service mdstore_service = {
38cceaa36bSkettenis "mdstore", 1, 0, mdstore_start, mdstore_rx_data
39cceaa36bSkettenis };
40cceaa36bSkettenis
41a0709405Skettenis struct ds_service mdstore_service_v2 = {
42a0709405Skettenis "mdstore", 2, 0, mdstore_start_v2, mdstore_rx_data
43a0709405Skettenis };
44a0709405Skettenis
454b9ab11dSkettenis struct ds_service mdstore_service_v3 = {
464b9ab11dSkettenis "mdstore", 3, 0, mdstore_start_v3, mdstore_rx_data
474b9ab11dSkettenis };
484b9ab11dSkettenis
49dc8fdf3dSkettenis #define MDSET_BEGIN_REQUEST 0x0001
50dc8fdf3dSkettenis #define MDSET_END_REQUEST 0x0002
51dc8fdf3dSkettenis #define MD_TRANSFER_REQUEST 0x0003
52cceaa36bSkettenis #define MDSET_LIST_REQUEST 0x0004
536aace0ceSkettenis #define MDSET_SELECT_REQUEST 0x0005
546aace0ceSkettenis #define MDSET_DELETE_REQUEST 0x0006
556aace0ceSkettenis #define MDSET_RETREIVE_REQUEST 0x0007
56cceaa36bSkettenis
57cceaa36bSkettenis struct mdstore_msg {
58cceaa36bSkettenis uint32_t msg_type;
59cceaa36bSkettenis uint32_t payload_len;
60cceaa36bSkettenis uint64_t svc_handle;
61cceaa36bSkettenis uint64_t reqnum;
62cceaa36bSkettenis uint16_t command;
6306b192deSkettenis uint8_t reserved[6];
64cceaa36bSkettenis } __packed;
65cceaa36bSkettenis
66dc8fdf3dSkettenis struct mdstore_begin_end_req {
67dc8fdf3dSkettenis uint32_t msg_type;
68dc8fdf3dSkettenis uint32_t payload_len;
69dc8fdf3dSkettenis uint64_t svc_handle;
70dc8fdf3dSkettenis uint64_t reqnum;
71dc8fdf3dSkettenis uint16_t command;
72dc8fdf3dSkettenis uint16_t nmds;
73dc8fdf3dSkettenis uint32_t namelen;
74dc8fdf3dSkettenis char name[1];
75dc8fdf3dSkettenis } __packed;
76dc8fdf3dSkettenis
77a0709405Skettenis struct mdstore_begin_req_v2 {
78a0709405Skettenis uint32_t msg_type;
79a0709405Skettenis uint32_t payload_len;
80a0709405Skettenis uint64_t svc_handle;
81a0709405Skettenis uint64_t reqnum;
82a0709405Skettenis uint16_t command;
83a0709405Skettenis uint16_t nmds;
84a0709405Skettenis uint32_t config_size;
85a0709405Skettenis uint64_t timestamp;
86a0709405Skettenis uint32_t namelen;
87a0709405Skettenis char name[1];
88a0709405Skettenis } __packed;
89a0709405Skettenis
904b9ab11dSkettenis struct mdstore_begin_req_v3 {
914b9ab11dSkettenis uint32_t msg_type;
924b9ab11dSkettenis uint32_t payload_len;
934b9ab11dSkettenis uint64_t svc_handle;
944b9ab11dSkettenis uint64_t reqnum;
954b9ab11dSkettenis uint16_t command;
964b9ab11dSkettenis uint16_t nmds;
974b9ab11dSkettenis uint32_t config_size;
984b9ab11dSkettenis uint64_t timestamp;
994b9ab11dSkettenis uint8_t degraded;
1004b9ab11dSkettenis uint8_t active_config;
1014b9ab11dSkettenis uint8_t reserved[2];
1024b9ab11dSkettenis uint32_t namelen;
1034b9ab11dSkettenis char name[1];
1044b9ab11dSkettenis } __packed;
1054b9ab11dSkettenis
1064b9ab11dSkettenis #define CONFIG_NORMAL 0x00
1074b9ab11dSkettenis #define CONFIG_DEGRADED 0x01
1084b9ab11dSkettenis
1094b9ab11dSkettenis #define CONFIG_EXISTING 0x00
1104b9ab11dSkettenis #define CONFIG_ACTIVE 0x01
1114b9ab11dSkettenis
112dc8fdf3dSkettenis struct mdstore_transfer_req {
113dc8fdf3dSkettenis uint32_t msg_type;
114dc8fdf3dSkettenis uint32_t payload_len;
115dc8fdf3dSkettenis uint64_t svc_handle;
116dc8fdf3dSkettenis uint64_t reqnum;
117dc8fdf3dSkettenis uint16_t command;
118dc8fdf3dSkettenis uint16_t type;
119dc8fdf3dSkettenis uint32_t size;
120dc8fdf3dSkettenis uint64_t offset;
121dc8fdf3dSkettenis char md[];
122dc8fdf3dSkettenis } __packed;
123dc8fdf3dSkettenis
124dc8fdf3dSkettenis #define MDSTORE_PRI_TYPE 0x01
125dc8fdf3dSkettenis #define MDSTORE_HV_MD_TYPE 0x02
126dc8fdf3dSkettenis #define MDSTORE_CTL_DOM_MD_TYPE 0x04
127dc8fdf3dSkettenis #define MDSTORE_SVC_DOM_MD_TYPE 0x08
128dc8fdf3dSkettenis
1296aace0ceSkettenis struct mdstore_sel_del_req {
1306aace0ceSkettenis uint32_t msg_type;
1316aace0ceSkettenis uint32_t payload_len;
1326aace0ceSkettenis uint64_t svc_handle;
1336aace0ceSkettenis uint64_t reqnum;
1346aace0ceSkettenis uint16_t command;
13506b192deSkettenis uint8_t reserved[2];
1366aace0ceSkettenis uint32_t namelen;
1376aace0ceSkettenis char name[1];
1386aace0ceSkettenis } __packed;
1396aace0ceSkettenis
140cceaa36bSkettenis #define MDSET_LIST_REPLY 0x0104
141cceaa36bSkettenis
142cceaa36bSkettenis struct mdstore_list_resp {
143cceaa36bSkettenis uint32_t msg_type;
144cceaa36bSkettenis uint32_t payload_len;
145cceaa36bSkettenis uint64_t svc_handle;
146cceaa36bSkettenis uint64_t reqnum;
147cceaa36bSkettenis uint32_t result;
148cceaa36bSkettenis uint16_t booted_set;
149cceaa36bSkettenis uint16_t boot_set;
150cceaa36bSkettenis char sets[1];
151cceaa36bSkettenis } __packed;
152cceaa36bSkettenis
153cceaa36bSkettenis #define MDST_SUCCESS 0x0
154cceaa36bSkettenis #define MDST_FAILURE 0x1
155cceaa36bSkettenis #define MDST_INVALID_MSG 0x2
156cceaa36bSkettenis #define MDST_MAX_MDS_ERR 0x3
157cceaa36bSkettenis #define MDST_BAD_NAME_ERR 0x4
158cceaa36bSkettenis #define MDST_SET_EXISTS_ERR 0x5
159cceaa36bSkettenis #define MDST_ALLOC_SET_ERR 0x6
160cceaa36bSkettenis #define MDST_ALLOC_MD_ERR 0x7
161cceaa36bSkettenis #define MDST_MD_COUNT_ERR 0x8
162cceaa36bSkettenis #define MDST_MD_SIZE_ERR 0x9
163cceaa36bSkettenis #define MDST_MD_TYPE_ERR 0xa
164cceaa36bSkettenis #define MDST_NOT_EXIST_ERR 0xb
165cceaa36bSkettenis
166cceaa36bSkettenis struct mdstore_set_head mdstore_sets = TAILQ_HEAD_INITIALIZER(mdstore_sets);
1676aace0ceSkettenis uint64_t mdstore_reqnum;
1686aace0ceSkettenis uint64_t mdstore_command;
169a0709405Skettenis uint16_t mdstore_major;
170a0709405Skettenis
171a0709405Skettenis void
mdstore_register(struct ds_conn * dc)172a0709405Skettenis mdstore_register(struct ds_conn *dc)
173a0709405Skettenis {
174a0709405Skettenis ds_conn_register_service(dc, &mdstore_service);
175a0709405Skettenis ds_conn_register_service(dc, &mdstore_service_v2);
1764b9ab11dSkettenis ds_conn_register_service(dc, &mdstore_service_v3);
177a0709405Skettenis }
178cceaa36bSkettenis
179cceaa36bSkettenis void
mdstore_start(struct ldc_conn * lc,uint64_t svc_handle)180cceaa36bSkettenis mdstore_start(struct ldc_conn *lc, uint64_t svc_handle)
181cceaa36bSkettenis {
182cceaa36bSkettenis struct mdstore_msg mm;
183cceaa36bSkettenis
184cceaa36bSkettenis bzero(&mm, sizeof(mm));
185cceaa36bSkettenis mm.msg_type = DS_DATA;
186cceaa36bSkettenis mm.payload_len = sizeof(mm) - 8;
187cceaa36bSkettenis mm.svc_handle = svc_handle;
1886aace0ceSkettenis mm.reqnum = mdstore_reqnum++;
1896aace0ceSkettenis mm.command = mdstore_command = MDSET_LIST_REQUEST;
190cceaa36bSkettenis ds_send_msg(lc, &mm, sizeof(mm));
191cceaa36bSkettenis }
192cceaa36bSkettenis
193cceaa36bSkettenis void
mdstore_start_v2(struct ldc_conn * lc,uint64_t svc_handle)194a0709405Skettenis mdstore_start_v2(struct ldc_conn *lc, uint64_t svc_handle)
195a0709405Skettenis {
196a0709405Skettenis mdstore_major = 2;
197a0709405Skettenis mdstore_start(lc, svc_handle);
198a0709405Skettenis }
199a0709405Skettenis
200a0709405Skettenis void
mdstore_start_v3(struct ldc_conn * lc,uint64_t svc_handle)2014b9ab11dSkettenis mdstore_start_v3(struct ldc_conn *lc, uint64_t svc_handle)
2024b9ab11dSkettenis {
2034b9ab11dSkettenis mdstore_major = 3;
2044b9ab11dSkettenis mdstore_start(lc, svc_handle);
2054b9ab11dSkettenis }
2064b9ab11dSkettenis
2074b9ab11dSkettenis void
mdstore_rx_data(struct ldc_conn * lc,uint64_t svc_handle,void * data,size_t len)208cceaa36bSkettenis mdstore_rx_data(struct ldc_conn *lc, uint64_t svc_handle, void *data,
209cceaa36bSkettenis size_t len)
210cceaa36bSkettenis {
211cceaa36bSkettenis struct mdstore_list_resp *mr = data;
212cceaa36bSkettenis struct mdstore_set *set;
213cceaa36bSkettenis int idx;
214cceaa36bSkettenis
215cceaa36bSkettenis if (mr->result != MDST_SUCCESS) {
216a2ea7dabSkettenis switch (mr->result) {
217a2ea7dabSkettenis case MDST_SET_EXISTS_ERR:
218a2ea7dabSkettenis errx(1, "Configuration already exists");
219a2ea7dabSkettenis break;
220a2ea7dabSkettenis case MDST_NOT_EXIST_ERR:
221a2ea7dabSkettenis errx(1, "No such configuration");
222a2ea7dabSkettenis break;
223a2ea7dabSkettenis default:
224a2ea7dabSkettenis errx(1, "Unexpected result 0x%x\n", mr->result);
225a2ea7dabSkettenis break;
226a2ea7dabSkettenis }
227cceaa36bSkettenis }
228cceaa36bSkettenis
2296aace0ceSkettenis switch (mdstore_command) {
2306aace0ceSkettenis case MDSET_LIST_REQUEST:
2316aace0ceSkettenis for (idx = 0, len = 0; len < mr->payload_len - 24; idx++) {
232cceaa36bSkettenis set = xmalloc(sizeof(*set));
233cceaa36bSkettenis set->name = xstrdup(&mr->sets[len]);
234cceaa36bSkettenis set->booted_set = (idx == mr->booted_set);
235cceaa36bSkettenis set->boot_set = (idx == mr->boot_set);
236cceaa36bSkettenis TAILQ_INSERT_TAIL(&mdstore_sets, set, link);
237cceaa36bSkettenis len += strlen(&mr->sets[len]) + 1;
2384b9ab11dSkettenis if (mdstore_major >= 2)
239a0709405Skettenis len += sizeof(uint64_t); /* skip timestamp */
2404b9ab11dSkettenis if (mdstore_major >= 3)
2414b9ab11dSkettenis len += sizeof(uint8_t); /* skip has_degraded */
242cceaa36bSkettenis }
2436aace0ceSkettenis break;
2446aace0ceSkettenis }
245dc8fdf3dSkettenis
246dc8fdf3dSkettenis mdstore_command = 0;
247dc8fdf3dSkettenis }
248dc8fdf3dSkettenis
249dc8fdf3dSkettenis void
mdstore_begin_v1(struct ds_conn * dc,uint64_t svc_handle,const char * name,int nmds)250a0709405Skettenis mdstore_begin_v1(struct ds_conn *dc, uint64_t svc_handle, const char *name,
251bb93e559Skettenis int nmds)
252dc8fdf3dSkettenis {
253dc8fdf3dSkettenis struct mdstore_begin_end_req *mr;
254dc8fdf3dSkettenis size_t len = sizeof(*mr) + strlen(name);
255dc8fdf3dSkettenis
256dc8fdf3dSkettenis mr = xzalloc(len);
257dc8fdf3dSkettenis mr->msg_type = DS_DATA;
258dc8fdf3dSkettenis mr->payload_len = len - 8;
259dc8fdf3dSkettenis mr->svc_handle = svc_handle;
260dc8fdf3dSkettenis mr->reqnum = mdstore_reqnum++;
261dc8fdf3dSkettenis mr->command = mdstore_command = MDSET_BEGIN_REQUEST;
262bb93e559Skettenis mr->nmds = nmds;
263dc8fdf3dSkettenis mr->namelen = strlen(name);
264dc8fdf3dSkettenis memcpy(mr->name, name, strlen(name));
265dc8fdf3dSkettenis
266dc8fdf3dSkettenis ds_send_msg(&dc->lc, mr, len);
267dc8fdf3dSkettenis free(mr);
268dc8fdf3dSkettenis
269dc8fdf3dSkettenis while (mdstore_command == MDSET_BEGIN_REQUEST)
270dc8fdf3dSkettenis ds_conn_handle(dc);
271dc8fdf3dSkettenis }
272dc8fdf3dSkettenis
273dc8fdf3dSkettenis void
mdstore_begin_v2(struct ds_conn * dc,uint64_t svc_handle,const char * name,int nmds,uint32_t config_size)274a0709405Skettenis mdstore_begin_v2(struct ds_conn *dc, uint64_t svc_handle, const char *name,
275a0709405Skettenis int nmds, uint32_t config_size)
276a0709405Skettenis {
277a0709405Skettenis struct mdstore_begin_req_v2 *mr;
278a0709405Skettenis size_t len = sizeof(*mr) + strlen(name);
279a0709405Skettenis
280a0709405Skettenis mr = xzalloc(len);
281a0709405Skettenis mr->msg_type = DS_DATA;
282a0709405Skettenis mr->payload_len = len - 8;
283a0709405Skettenis mr->svc_handle = svc_handle;
284a0709405Skettenis mr->reqnum = mdstore_reqnum++;
285a0709405Skettenis mr->command = mdstore_command = MDSET_BEGIN_REQUEST;
286a0709405Skettenis mr->config_size = config_size;
287a0709405Skettenis mr->timestamp = time(NULL);
288a0709405Skettenis mr->nmds = nmds;
289a0709405Skettenis mr->namelen = strlen(name);
290a0709405Skettenis memcpy(mr->name, name, strlen(name));
291a0709405Skettenis
292a0709405Skettenis ds_send_msg(&dc->lc, mr, len);
293a0709405Skettenis free(mr);
294a0709405Skettenis
295a0709405Skettenis while (mdstore_command == MDSET_BEGIN_REQUEST)
296a0709405Skettenis ds_conn_handle(dc);
297a0709405Skettenis }
298a0709405Skettenis
299a0709405Skettenis void
mdstore_begin_v3(struct ds_conn * dc,uint64_t svc_handle,const char * name,int nmds,uint32_t config_size)3004b9ab11dSkettenis mdstore_begin_v3(struct ds_conn *dc, uint64_t svc_handle, const char *name,
3014b9ab11dSkettenis int nmds, uint32_t config_size)
3024b9ab11dSkettenis {
3034b9ab11dSkettenis struct mdstore_begin_req_v3 *mr;
3044b9ab11dSkettenis size_t len = sizeof(*mr) + strlen(name);
3054b9ab11dSkettenis
3064b9ab11dSkettenis mr = xzalloc(len);
3074b9ab11dSkettenis mr->msg_type = DS_DATA;
3084b9ab11dSkettenis mr->payload_len = len - 8;
3094b9ab11dSkettenis mr->svc_handle = svc_handle;
3104b9ab11dSkettenis mr->reqnum = mdstore_reqnum++;
3114b9ab11dSkettenis mr->command = mdstore_command = MDSET_BEGIN_REQUEST;
3124b9ab11dSkettenis mr->config_size = config_size;
3134b9ab11dSkettenis mr->timestamp = time(NULL);
3144b9ab11dSkettenis mr->degraded = CONFIG_NORMAL;
3154b9ab11dSkettenis mr->active_config = CONFIG_EXISTING;
3164b9ab11dSkettenis mr->nmds = nmds;
3174b9ab11dSkettenis mr->namelen = strlen(name);
3184b9ab11dSkettenis memcpy(mr->name, name, strlen(name));
3194b9ab11dSkettenis
3204b9ab11dSkettenis ds_send_msg(&dc->lc, mr, len);
3214b9ab11dSkettenis free(mr);
3224b9ab11dSkettenis
3234b9ab11dSkettenis while (mdstore_command == MDSET_BEGIN_REQUEST)
3244b9ab11dSkettenis ds_conn_handle(dc);
3254b9ab11dSkettenis }
3264b9ab11dSkettenis
3274b9ab11dSkettenis void
mdstore_begin(struct ds_conn * dc,uint64_t svc_handle,const char * name,int nmds,uint32_t config_size)328a0709405Skettenis mdstore_begin(struct ds_conn *dc, uint64_t svc_handle, const char *name,
329a0709405Skettenis int nmds, uint32_t config_size)
330a0709405Skettenis {
3314b9ab11dSkettenis if (mdstore_major == 3)
3324b9ab11dSkettenis mdstore_begin_v3(dc, svc_handle, name, nmds, config_size);
3334b9ab11dSkettenis else if (mdstore_major == 2)
334a0709405Skettenis mdstore_begin_v2(dc, svc_handle, name, nmds, config_size);
335a0709405Skettenis else
336a0709405Skettenis mdstore_begin_v1(dc, svc_handle, name, nmds);
337a0709405Skettenis }
338a0709405Skettenis
339a0709405Skettenis void
mdstore_transfer(struct ds_conn * dc,uint64_t svc_handle,const char * path,uint16_t type,uint64_t offset)340dc8fdf3dSkettenis mdstore_transfer(struct ds_conn *dc, uint64_t svc_handle, const char *path,
341dc8fdf3dSkettenis uint16_t type, uint64_t offset)
342dc8fdf3dSkettenis {
343dc8fdf3dSkettenis struct mdstore_transfer_req *mr;
344dc8fdf3dSkettenis uint32_t size;
345dc8fdf3dSkettenis size_t len;
346dc8fdf3dSkettenis FILE *fp;
347dc8fdf3dSkettenis
348dc8fdf3dSkettenis fp = fopen(path, "r");
349dc8fdf3dSkettenis if (fp == NULL)
350dc8fdf3dSkettenis err(1, "fopen");
351dc8fdf3dSkettenis
352dc8fdf3dSkettenis fseek(fp, 0, SEEK_END);
353dc8fdf3dSkettenis size = ftell(fp);
354dc8fdf3dSkettenis fseek(fp, 0, SEEK_SET);
355dc8fdf3dSkettenis
356dc8fdf3dSkettenis len = sizeof(*mr) + size;
357dc8fdf3dSkettenis mr = xzalloc(len);
358dc8fdf3dSkettenis
359dc8fdf3dSkettenis mr->msg_type = DS_DATA;
360dc8fdf3dSkettenis mr->payload_len = len - 8;
361dc8fdf3dSkettenis mr->svc_handle = svc_handle;
362dc8fdf3dSkettenis mr->reqnum = mdstore_reqnum++;
363dc8fdf3dSkettenis mr->command = mdstore_command = MD_TRANSFER_REQUEST;
364dc8fdf3dSkettenis mr->type = type;
365dc8fdf3dSkettenis mr->size = size;
366dc8fdf3dSkettenis mr->offset = offset;
367dc8fdf3dSkettenis if (fread(&mr->md, size, 1, fp) != 1)
368dc8fdf3dSkettenis err(1, "fread");
369dc8fdf3dSkettenis ds_send_msg(&dc->lc, mr, len);
370dc8fdf3dSkettenis free(mr);
371dc8fdf3dSkettenis
372dc8fdf3dSkettenis fclose(fp);
373dc8fdf3dSkettenis
374dc8fdf3dSkettenis while (mdstore_command == MD_TRANSFER_REQUEST)
375dc8fdf3dSkettenis ds_conn_handle(dc);
376dc8fdf3dSkettenis }
377dc8fdf3dSkettenis
378dc8fdf3dSkettenis void
mdstore_end(struct ds_conn * dc,uint64_t svc_handle,const char * name,int nmds)379bb93e559Skettenis mdstore_end(struct ds_conn *dc, uint64_t svc_handle, const char *name,
380bb93e559Skettenis int nmds)
381dc8fdf3dSkettenis {
382dc8fdf3dSkettenis struct mdstore_begin_end_req *mr;
383dc8fdf3dSkettenis size_t len = sizeof(*mr) + strlen(name);
384dc8fdf3dSkettenis
385dc8fdf3dSkettenis mr = xzalloc(len);
386dc8fdf3dSkettenis mr->msg_type = DS_DATA;
387dc8fdf3dSkettenis mr->payload_len = len - 8;
388dc8fdf3dSkettenis mr->svc_handle = svc_handle;
389dc8fdf3dSkettenis mr->reqnum = mdstore_reqnum++;
390dc8fdf3dSkettenis mr->command = mdstore_command = MDSET_END_REQUEST;
391bb93e559Skettenis mr->nmds = nmds;
392dc8fdf3dSkettenis mr->namelen = strlen(name);
393dc8fdf3dSkettenis memcpy(mr->name, name, strlen(name));
394dc8fdf3dSkettenis
395dc8fdf3dSkettenis ds_send_msg(&dc->lc, mr, len);
396dc8fdf3dSkettenis free(mr);
397dc8fdf3dSkettenis
398dc8fdf3dSkettenis while (mdstore_command == MDSET_END_REQUEST)
399dc8fdf3dSkettenis ds_conn_handle(dc);
4006aace0ceSkettenis }
4016aace0ceSkettenis
4026aace0ceSkettenis void
mdstore_select(struct ds_conn * dc,const char * name)4036aace0ceSkettenis mdstore_select(struct ds_conn *dc, const char *name)
4046aace0ceSkettenis {
4056aace0ceSkettenis struct ds_conn_svc *dcs;
4066aace0ceSkettenis struct mdstore_sel_del_req *mr;
407dc8fdf3dSkettenis size_t len = sizeof(*mr) + strlen(name);
4086aace0ceSkettenis
4096aace0ceSkettenis TAILQ_FOREACH(dcs, &dc->services, link)
410b2093b6cSkettenis if (strcmp(dcs->service->ds_svc_id, "mdstore") == 0 &&
411b2093b6cSkettenis dcs->svc_handle != 0)
4126aace0ceSkettenis break;
413abcbcc4dSdoug assert(dcs != NULL);
4146aace0ceSkettenis
4156aace0ceSkettenis mr = xzalloc(len);
4166aace0ceSkettenis mr->msg_type = DS_DATA;
4176aace0ceSkettenis mr->payload_len = len - 8;
4186aace0ceSkettenis mr->svc_handle = dcs->svc_handle;
4196aace0ceSkettenis mr->reqnum = mdstore_reqnum++;
4206aace0ceSkettenis mr->command = mdstore_command = MDSET_SELECT_REQUEST;
4216aace0ceSkettenis mr->namelen = strlen(name);
4226aace0ceSkettenis memcpy(mr->name, name, strlen(name));
4236aace0ceSkettenis
4246aace0ceSkettenis ds_send_msg(&dc->lc, mr, len);
4256aace0ceSkettenis free(mr);
4266aace0ceSkettenis
4276aace0ceSkettenis while (mdstore_command == MDSET_SELECT_REQUEST)
4286aace0ceSkettenis ds_conn_handle(dc);
429cceaa36bSkettenis }
430dc8fdf3dSkettenis
431dc8fdf3dSkettenis void
mdstore_delete(struct ds_conn * dc,const char * name)432dc8fdf3dSkettenis mdstore_delete(struct ds_conn *dc, const char *name)
433dc8fdf3dSkettenis {
434dc8fdf3dSkettenis struct ds_conn_svc *dcs;
435dc8fdf3dSkettenis struct mdstore_sel_del_req *mr;
436dc8fdf3dSkettenis size_t len = sizeof(*mr) + strlen(name);
437dc8fdf3dSkettenis
438dc8fdf3dSkettenis TAILQ_FOREACH(dcs, &dc->services, link)
439b2093b6cSkettenis if (strcmp(dcs->service->ds_svc_id, "mdstore") == 0 &&
440b2093b6cSkettenis dcs->svc_handle != 0)
441dc8fdf3dSkettenis break;
442abcbcc4dSdoug assert(dcs != NULL);
443dc8fdf3dSkettenis
444dc8fdf3dSkettenis mr = xzalloc(len);
445dc8fdf3dSkettenis mr->msg_type = DS_DATA;
446dc8fdf3dSkettenis mr->payload_len = len - 8;
447dc8fdf3dSkettenis mr->svc_handle = dcs->svc_handle;
448dc8fdf3dSkettenis mr->reqnum = mdstore_reqnum++;
449dc8fdf3dSkettenis mr->command = mdstore_command = MDSET_DELETE_REQUEST;
450dc8fdf3dSkettenis mr->namelen = strlen(name);
451dc8fdf3dSkettenis memcpy(mr->name, name, strlen(name));
452dc8fdf3dSkettenis
453dc8fdf3dSkettenis ds_send_msg(&dc->lc, mr, len);
454dc8fdf3dSkettenis free(mr);
455dc8fdf3dSkettenis
456dc8fdf3dSkettenis while (mdstore_command == MDSET_DELETE_REQUEST)
457dc8fdf3dSkettenis ds_conn_handle(dc);
458dc8fdf3dSkettenis }
459dc8fdf3dSkettenis
460bb93e559Skettenis void frag_init(void);
461bb93e559Skettenis void add_frag_mblock(struct md_node *);
462bb93e559Skettenis void add_frag(uint64_t);
463bb93e559Skettenis void delete_frag(uint64_t);
464bb93e559Skettenis uint64_t alloc_frag(void);
465bb93e559Skettenis
466dc8fdf3dSkettenis void
mdstore_download(struct ds_conn * dc,const char * name)467dc8fdf3dSkettenis mdstore_download(struct ds_conn *dc, const char *name)
468dc8fdf3dSkettenis {
469dc8fdf3dSkettenis struct ds_conn_svc *dcs;
470bb93e559Skettenis struct md_node *node;
471bb93e559Skettenis struct md_prop *prop;
472bb93e559Skettenis struct guest *guest;
473bb93e559Skettenis int nmds = 2;
474bb93e559Skettenis char *path;
475a0709405Skettenis uint32_t total_size = 0;
476bb93e559Skettenis uint16_t type;
477dc8fdf3dSkettenis
478dc8fdf3dSkettenis TAILQ_FOREACH(dcs, &dc->services, link)
479b2093b6cSkettenis if (strcmp(dcs->service->ds_svc_id, "mdstore") == 0 &&
480b2093b6cSkettenis dcs->svc_handle != 0)
481dc8fdf3dSkettenis break;
482abcbcc4dSdoug assert(dcs != NULL);
483dc8fdf3dSkettenis
484bb93e559Skettenis if (asprintf(&path, "%s/hv.md", name) == -1)
485bb93e559Skettenis err(1, "asprintf");
486bb93e559Skettenis hvmd = md_read(path);
487bb93e559Skettenis free(path);
488bb93e559Skettenis
489bb93e559Skettenis if (hvmd == NULL)
490bb93e559Skettenis err(1, "%s", name);
491bb93e559Skettenis
492bb93e559Skettenis node = md_find_node(hvmd, "guests");
49397d8cafcSkettenis TAILQ_INIT(&guest_list);
494bb93e559Skettenis TAILQ_FOREACH(prop, &node->prop_list, link) {
495bb93e559Skettenis if (prop->tag == MD_PROP_ARC &&
496bb93e559Skettenis strcmp(prop->name->str, "fwd") == 0) {
497bb93e559Skettenis add_guest(prop->d.arc.node);
498bb93e559Skettenis nmds++;
499bb93e559Skettenis }
500bb93e559Skettenis }
501bb93e559Skettenis
502bb93e559Skettenis frag_init();
503bb93e559Skettenis hv_mdpa = alloc_frag();
504bb93e559Skettenis
505a0709405Skettenis TAILQ_FOREACH(guest, &guest_list, link) {
506a0709405Skettenis if (asprintf(&path, "%s/%s.md", name, guest->name) == -1)
507a0709405Skettenis err(1, "asprintf");
508a0709405Skettenis total_size += md_size(path);
509a0709405Skettenis }
510a0709405Skettenis if (asprintf(&path, "%s/hv.md", name) == -1)
511a0709405Skettenis err(1, "asprintf");
512a0709405Skettenis total_size += md_size(path);
513a0709405Skettenis if (asprintf(&path, "%s/pri", name) == -1)
514a0709405Skettenis err(1, "asprintf");
515a0709405Skettenis total_size += md_size(path);
516a0709405Skettenis
517a0709405Skettenis mdstore_begin(dc, dcs->svc_handle, name, nmds, total_size);
51897d8cafcSkettenis TAILQ_FOREACH(guest, &guest_list, link) {
519bb93e559Skettenis if (asprintf(&path, "%s/%s.md", name, guest->name) == -1)
520bb93e559Skettenis err(1, "asprintf");
521bb93e559Skettenis type = 0;
522bb93e559Skettenis if (strcmp(guest->name, "primary") == 0)
523bb93e559Skettenis type = MDSTORE_CTL_DOM_MD_TYPE;
524bb93e559Skettenis mdstore_transfer(dc, dcs->svc_handle, path, type, guest->mdpa);
525bb93e559Skettenis free(path);
526bb93e559Skettenis }
527bb93e559Skettenis if (asprintf(&path, "%s/hv.md", name) == -1)
528bb93e559Skettenis err(1, "asprintf");
529bb93e559Skettenis mdstore_transfer(dc, dcs->svc_handle, path,
530bb93e559Skettenis MDSTORE_HV_MD_TYPE, hv_mdpa);
531bb93e559Skettenis free(path);
532bb93e559Skettenis if (asprintf(&path, "%s/pri", name) == -1)
533bb93e559Skettenis err(1, "asprintf");
534bb93e559Skettenis mdstore_transfer(dc, dcs->svc_handle, path,
535dc8fdf3dSkettenis MDSTORE_PRI_TYPE, 0);
536bb93e559Skettenis free(path);
537bb93e559Skettenis mdstore_end(dc, dcs->svc_handle, name, nmds);
538bb93e559Skettenis }
539bb93e559Skettenis
540bb93e559Skettenis struct frag {
541bb93e559Skettenis TAILQ_ENTRY(frag) link;
542bb93e559Skettenis uint64_t base;
543bb93e559Skettenis };
544bb93e559Skettenis
545*72b890efSkettenis TAILQ_HEAD(frag_head, frag) mdstore_frags;
546bb93e559Skettenis
547*72b890efSkettenis uint64_t mdstore_fragsize;
548bb93e559Skettenis
549bb93e559Skettenis void
frag_init(void)550bb93e559Skettenis frag_init(void)
551bb93e559Skettenis {
552bb93e559Skettenis struct md_node *node;
553bb93e559Skettenis struct md_prop *prop;
554bb93e559Skettenis
555bb93e559Skettenis node = md_find_node(hvmd, "frag_space");
556*72b890efSkettenis md_get_prop_val(hvmd, node, "fragsize", &mdstore_fragsize);
557*72b890efSkettenis TAILQ_INIT(&mdstore_frags);
558bb93e559Skettenis TAILQ_FOREACH(prop, &node->prop_list, link) {
559bb93e559Skettenis if (prop->tag == MD_PROP_ARC &&
560bb93e559Skettenis strcmp(prop->name->str, "fwd") == 0)
561bb93e559Skettenis add_frag_mblock(prop->d.arc.node);
562bb93e559Skettenis }
563bb93e559Skettenis }
564bb93e559Skettenis
565bb93e559Skettenis void
add_frag_mblock(struct md_node * node)566bb93e559Skettenis add_frag_mblock(struct md_node *node)
567bb93e559Skettenis {
568bb93e559Skettenis uint64_t base, size;
569bb93e559Skettenis struct guest *guest;
570bb93e559Skettenis
571bb93e559Skettenis md_get_prop_val(hvmd, node, "base", &base);
572bb93e559Skettenis md_get_prop_val(hvmd, node, "size", &size);
573*72b890efSkettenis while (size > mdstore_fragsize) {
574bb93e559Skettenis add_frag(base);
575*72b890efSkettenis size -= mdstore_fragsize;
576*72b890efSkettenis base += mdstore_fragsize;
577bb93e559Skettenis }
578bb93e559Skettenis
579bb93e559Skettenis delete_frag(hv_mdpa);
58097d8cafcSkettenis TAILQ_FOREACH(guest, &guest_list, link)
581bb93e559Skettenis delete_frag(guest->mdpa);
582bb93e559Skettenis }
583bb93e559Skettenis
584bb93e559Skettenis void
add_frag(uint64_t base)585bb93e559Skettenis add_frag(uint64_t base)
586bb93e559Skettenis {
587bb93e559Skettenis struct frag *frag;
588bb93e559Skettenis
589bb93e559Skettenis frag = xmalloc(sizeof(*frag));
590bb93e559Skettenis frag->base = base;
591*72b890efSkettenis TAILQ_INSERT_TAIL(&mdstore_frags, frag, link);
592bb93e559Skettenis }
593bb93e559Skettenis
594bb93e559Skettenis void
delete_frag(uint64_t base)595bb93e559Skettenis delete_frag(uint64_t base)
596bb93e559Skettenis {
597bb93e559Skettenis struct frag *frag;
598bb93e559Skettenis struct frag *tmp;
599bb93e559Skettenis
600*72b890efSkettenis TAILQ_FOREACH_SAFE(frag, &mdstore_frags, link, tmp) {
601bb93e559Skettenis if (frag->base == base) {
602*72b890efSkettenis TAILQ_REMOVE(&mdstore_frags, frag, link);
603bb93e559Skettenis free(frag);
604bb93e559Skettenis }
605bb93e559Skettenis }
606bb93e559Skettenis }
607bb93e559Skettenis
608bb93e559Skettenis uint64_t
alloc_frag(void)609bb93e559Skettenis alloc_frag(void)
610bb93e559Skettenis {
611bb93e559Skettenis struct frag *frag;
612bb93e559Skettenis uint64_t base;
613bb93e559Skettenis
614*72b890efSkettenis frag = TAILQ_FIRST(&mdstore_frags);
615bb93e559Skettenis if (frag == NULL)
616bb93e559Skettenis return -1;
617bb93e559Skettenis
618*72b890efSkettenis TAILQ_REMOVE(&mdstore_frags, frag, link);
619bb93e559Skettenis base = frag->base;
620bb93e559Skettenis free(frag);
621bb93e559Skettenis
622bb93e559Skettenis return base;
623dc8fdf3dSkettenis }
624