xref: /openbsd/usr.sbin/ldomctl/mdstore.c (revision dc8fdf3d)
1*dc8fdf3dSkettenis /*	$OpenBSD: mdstore.c,v 1.3 2012/11/04 23:30:38 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>
20*dc8fdf3dSkettenis #include <err.h>
21cceaa36bSkettenis #include <stdio.h>
226aace0ceSkettenis #include <stdlib.h>
23cceaa36bSkettenis #include <string.h>
24cceaa36bSkettenis 
25cceaa36bSkettenis #include "ds.h"
26cceaa36bSkettenis #include "mdstore.h"
27cceaa36bSkettenis #include "util.h"
28cceaa36bSkettenis 
29cceaa36bSkettenis void	mdstore_start(struct ldc_conn *, uint64_t);
30cceaa36bSkettenis void	mdstore_rx_data(struct ldc_conn *, uint64_t, void *, size_t);
31cceaa36bSkettenis 
32cceaa36bSkettenis struct ds_service mdstore_service = {
33cceaa36bSkettenis 	"mdstore", 1, 0, mdstore_start, mdstore_rx_data
34cceaa36bSkettenis };
35cceaa36bSkettenis 
36*dc8fdf3dSkettenis #define MDSET_BEGIN_REQUEST	0x0001
37*dc8fdf3dSkettenis #define MDSET_END_REQUEST	0x0002
38*dc8fdf3dSkettenis #define MD_TRANSFER_REQUEST	0x0003
39cceaa36bSkettenis #define MDSET_LIST_REQUEST	0x0004
406aace0ceSkettenis #define MDSET_SELECT_REQUEST	0x0005
416aace0ceSkettenis #define MDSET_DELETE_REQUEST	0x0006
426aace0ceSkettenis #define MDSET_RETREIVE_REQUEST	0x0007
43cceaa36bSkettenis 
44cceaa36bSkettenis struct mdstore_msg {
45cceaa36bSkettenis 	uint32_t	msg_type;
46cceaa36bSkettenis 	uint32_t	payload_len;
47cceaa36bSkettenis 	uint64_t	svc_handle;
48cceaa36bSkettenis 	uint64_t	reqnum;
49cceaa36bSkettenis 	uint16_t	command;
50cceaa36bSkettenis } __packed;
51cceaa36bSkettenis 
52*dc8fdf3dSkettenis struct mdstore_begin_end_req {
53*dc8fdf3dSkettenis 	uint32_t	msg_type;
54*dc8fdf3dSkettenis 	uint32_t	payload_len;
55*dc8fdf3dSkettenis 	uint64_t	svc_handle;
56*dc8fdf3dSkettenis 	uint64_t	reqnum;
57*dc8fdf3dSkettenis 	uint16_t	command;
58*dc8fdf3dSkettenis 	uint16_t	nmds;
59*dc8fdf3dSkettenis 	uint32_t	namelen;
60*dc8fdf3dSkettenis 	char		name[1];
61*dc8fdf3dSkettenis } __packed;
62*dc8fdf3dSkettenis 
63*dc8fdf3dSkettenis struct mdstore_transfer_req {
64*dc8fdf3dSkettenis 	uint32_t	msg_type;
65*dc8fdf3dSkettenis 	uint32_t	payload_len;
66*dc8fdf3dSkettenis 	uint64_t	svc_handle;
67*dc8fdf3dSkettenis 	uint64_t	reqnum;
68*dc8fdf3dSkettenis 	uint16_t	command;
69*dc8fdf3dSkettenis 	uint16_t	type;
70*dc8fdf3dSkettenis 	uint32_t	size;
71*dc8fdf3dSkettenis 	uint64_t	offset;
72*dc8fdf3dSkettenis 	char		md[];
73*dc8fdf3dSkettenis } __packed;
74*dc8fdf3dSkettenis 
75*dc8fdf3dSkettenis #define MDSTORE_PRI_TYPE	0x01
76*dc8fdf3dSkettenis #define MDSTORE_HV_MD_TYPE	0x02
77*dc8fdf3dSkettenis #define MDSTORE_CTL_DOM_MD_TYPE	0x04
78*dc8fdf3dSkettenis #define MDSTORE_SVC_DOM_MD_TYPE	0x08
79*dc8fdf3dSkettenis 
806aace0ceSkettenis struct mdstore_sel_del_req {
816aace0ceSkettenis 	uint32_t	msg_type;
826aace0ceSkettenis 	uint32_t	payload_len;
836aace0ceSkettenis 	uint64_t	svc_handle;
846aace0ceSkettenis 	uint64_t	reqnum;
856aace0ceSkettenis 	uint16_t	command;
866aace0ceSkettenis 	uint16_t	reserved;
876aace0ceSkettenis 	uint32_t	namelen;
886aace0ceSkettenis 	char		name[1];
896aace0ceSkettenis } __packed;
906aace0ceSkettenis 
91cceaa36bSkettenis #define MDSET_LIST_REPLY	0x0104
92cceaa36bSkettenis 
93cceaa36bSkettenis struct mdstore_list_resp {
94cceaa36bSkettenis 	uint32_t	msg_type;
95cceaa36bSkettenis 	uint32_t	payload_len;
96cceaa36bSkettenis 	uint64_t	svc_handle;
97cceaa36bSkettenis 	uint64_t	reqnum;
98cceaa36bSkettenis 	uint32_t	result;
99cceaa36bSkettenis 	uint16_t	booted_set;
100cceaa36bSkettenis 	uint16_t	boot_set;
101cceaa36bSkettenis 	char		sets[1];
102cceaa36bSkettenis } __packed;
103cceaa36bSkettenis 
104cceaa36bSkettenis #define MDST_SUCCESS		0x0
105cceaa36bSkettenis #define MDST_FAILURE		0x1
106cceaa36bSkettenis #define MDST_INVALID_MSG	0x2
107cceaa36bSkettenis #define MDST_MAX_MDS_ERR	0x3
108cceaa36bSkettenis #define MDST_BAD_NAME_ERR	0x4
109cceaa36bSkettenis #define MDST_SET_EXISTS_ERR	0x5
110cceaa36bSkettenis #define MDST_ALLOC_SET_ERR	0x6
111cceaa36bSkettenis #define MDST_ALLOC_MD_ERR	0x7
112cceaa36bSkettenis #define MDST_MD_COUNT_ERR	0x8
113cceaa36bSkettenis #define MDST_MD_SIZE_ERR	0x9
114cceaa36bSkettenis #define MDST_MD_TYPE_ERR	0xa
115cceaa36bSkettenis #define MDST_NOT_EXIST_ERR	0xb
116cceaa36bSkettenis 
117cceaa36bSkettenis struct mdstore_set_head mdstore_sets = TAILQ_HEAD_INITIALIZER(mdstore_sets);
1186aace0ceSkettenis uint64_t mdstore_reqnum;
1196aace0ceSkettenis uint64_t mdstore_command;
120cceaa36bSkettenis 
121cceaa36bSkettenis void
122cceaa36bSkettenis mdstore_start(struct ldc_conn *lc, uint64_t svc_handle)
123cceaa36bSkettenis {
124cceaa36bSkettenis 	struct mdstore_msg mm;
125cceaa36bSkettenis 
126cceaa36bSkettenis 	bzero(&mm, sizeof(mm));
127cceaa36bSkettenis 	mm.msg_type = DS_DATA;
128cceaa36bSkettenis 	mm.payload_len = sizeof(mm) - 8;
129cceaa36bSkettenis 	mm.svc_handle = svc_handle;
1306aace0ceSkettenis 	mm.reqnum = mdstore_reqnum++;
1316aace0ceSkettenis 	mm.command = mdstore_command = MDSET_LIST_REQUEST;
132cceaa36bSkettenis 	ds_send_msg(lc, &mm, sizeof(mm));
133cceaa36bSkettenis }
134cceaa36bSkettenis 
135cceaa36bSkettenis void
136cceaa36bSkettenis mdstore_rx_data(struct ldc_conn *lc, uint64_t svc_handle, void *data,
137cceaa36bSkettenis     size_t len)
138cceaa36bSkettenis {
139cceaa36bSkettenis 	struct mdstore_list_resp *mr = data;
140cceaa36bSkettenis 	struct mdstore_set *set;
141cceaa36bSkettenis 	int idx;
142cceaa36bSkettenis 
143cceaa36bSkettenis 	if (mr->result != MDST_SUCCESS) {
144cceaa36bSkettenis 		DPRINTF(("Unexpected result 0x%x\n", mr->result));
145cceaa36bSkettenis 		return;
146cceaa36bSkettenis 	}
147cceaa36bSkettenis 
1486aace0ceSkettenis 	switch (mdstore_command) {
1496aace0ceSkettenis 	case MDSET_LIST_REQUEST:
1506aace0ceSkettenis 		for (idx = 0, len = 0; len < mr->payload_len - 24; idx++) {
151cceaa36bSkettenis 			set = xmalloc(sizeof(*set));
152cceaa36bSkettenis 			set->name = xstrdup(&mr->sets[len]);
153cceaa36bSkettenis 			set->booted_set = (idx == mr->booted_set);
154cceaa36bSkettenis 			set->boot_set = (idx == mr->boot_set);
155cceaa36bSkettenis 			TAILQ_INSERT_TAIL(&mdstore_sets, set, link);
156cceaa36bSkettenis 			len += strlen(&mr->sets[len]) + 1;
157cceaa36bSkettenis 		}
1586aace0ceSkettenis 		break;
1596aace0ceSkettenis 	}
160*dc8fdf3dSkettenis 
161*dc8fdf3dSkettenis 	mdstore_command = 0;
162*dc8fdf3dSkettenis }
163*dc8fdf3dSkettenis 
164*dc8fdf3dSkettenis void
165*dc8fdf3dSkettenis mdstore_begin(struct ds_conn *dc, uint64_t svc_handle, const char *name)
166*dc8fdf3dSkettenis {
167*dc8fdf3dSkettenis 	struct mdstore_begin_end_req *mr;
168*dc8fdf3dSkettenis 	size_t len = sizeof(*mr) + strlen(name);
169*dc8fdf3dSkettenis 
170*dc8fdf3dSkettenis 	mr = xzalloc(len);
171*dc8fdf3dSkettenis 	mr->msg_type = DS_DATA;
172*dc8fdf3dSkettenis 	mr->payload_len = len - 8;
173*dc8fdf3dSkettenis 	mr->svc_handle = svc_handle;
174*dc8fdf3dSkettenis 	mr->reqnum = mdstore_reqnum++;
175*dc8fdf3dSkettenis 	mr->command = mdstore_command = MDSET_BEGIN_REQUEST;
176*dc8fdf3dSkettenis 	mr->nmds = 3;		/* XXX */
177*dc8fdf3dSkettenis 	mr->namelen = strlen(name);
178*dc8fdf3dSkettenis 	memcpy(mr->name, name, strlen(name));
179*dc8fdf3dSkettenis 
180*dc8fdf3dSkettenis 	ds_send_msg(&dc->lc, mr, len);
181*dc8fdf3dSkettenis 	free(mr);
182*dc8fdf3dSkettenis 
183*dc8fdf3dSkettenis 	while (mdstore_command == MDSET_BEGIN_REQUEST)
184*dc8fdf3dSkettenis 		ds_conn_handle(dc);
185*dc8fdf3dSkettenis }
186*dc8fdf3dSkettenis 
187*dc8fdf3dSkettenis void
188*dc8fdf3dSkettenis mdstore_transfer(struct ds_conn *dc, uint64_t svc_handle, const char *path,
189*dc8fdf3dSkettenis     uint16_t type, uint64_t offset)
190*dc8fdf3dSkettenis {
191*dc8fdf3dSkettenis 	struct mdstore_transfer_req *mr;
192*dc8fdf3dSkettenis 	uint32_t size;
193*dc8fdf3dSkettenis 	size_t len;
194*dc8fdf3dSkettenis 	FILE *fp;
195*dc8fdf3dSkettenis 
196*dc8fdf3dSkettenis 	fp = fopen(path, "r");
197*dc8fdf3dSkettenis 	if (fp == NULL)
198*dc8fdf3dSkettenis 		err(1, "fopen");
199*dc8fdf3dSkettenis 
200*dc8fdf3dSkettenis 	fseek(fp, 0, SEEK_END);
201*dc8fdf3dSkettenis 	size = ftell(fp);
202*dc8fdf3dSkettenis 	fseek(fp, 0, SEEK_SET);
203*dc8fdf3dSkettenis 
204*dc8fdf3dSkettenis 	len = sizeof(*mr) + size;
205*dc8fdf3dSkettenis 	mr = xzalloc(len);
206*dc8fdf3dSkettenis 
207*dc8fdf3dSkettenis 	mr->msg_type = DS_DATA;
208*dc8fdf3dSkettenis 	mr->payload_len = len - 8;
209*dc8fdf3dSkettenis 	mr->svc_handle = svc_handle;
210*dc8fdf3dSkettenis 	mr->reqnum = mdstore_reqnum++;
211*dc8fdf3dSkettenis 	mr->command = mdstore_command = MD_TRANSFER_REQUEST;
212*dc8fdf3dSkettenis 	mr->type = type;
213*dc8fdf3dSkettenis 	mr->size = size;
214*dc8fdf3dSkettenis 	mr->offset = offset;
215*dc8fdf3dSkettenis 	if (fread(&mr->md, size, 1, fp) != 1)
216*dc8fdf3dSkettenis 		err(1, "fread");
217*dc8fdf3dSkettenis 	ds_send_msg(&dc->lc, mr, len);
218*dc8fdf3dSkettenis 	free(mr);
219*dc8fdf3dSkettenis 
220*dc8fdf3dSkettenis 	fclose(fp);
221*dc8fdf3dSkettenis 
222*dc8fdf3dSkettenis 	while (mdstore_command == MD_TRANSFER_REQUEST)
223*dc8fdf3dSkettenis 		ds_conn_handle(dc);
224*dc8fdf3dSkettenis }
225*dc8fdf3dSkettenis 
226*dc8fdf3dSkettenis void
227*dc8fdf3dSkettenis mdstore_end(struct ds_conn *dc, uint64_t svc_handle, const char *name)
228*dc8fdf3dSkettenis {
229*dc8fdf3dSkettenis 	struct mdstore_begin_end_req *mr;
230*dc8fdf3dSkettenis 	size_t len = sizeof(*mr) + strlen(name);
231*dc8fdf3dSkettenis 
232*dc8fdf3dSkettenis 	mr = xzalloc(len);
233*dc8fdf3dSkettenis 	mr->msg_type = DS_DATA;
234*dc8fdf3dSkettenis 	mr->payload_len = len - 8;
235*dc8fdf3dSkettenis 	mr->svc_handle = svc_handle;
236*dc8fdf3dSkettenis 	mr->reqnum = mdstore_reqnum++;
237*dc8fdf3dSkettenis 	mr->command = mdstore_command = MDSET_END_REQUEST;
238*dc8fdf3dSkettenis 	mr->nmds = 3;
239*dc8fdf3dSkettenis 	mr->namelen = strlen(name);
240*dc8fdf3dSkettenis 	memcpy(mr->name, name, strlen(name));
241*dc8fdf3dSkettenis 
242*dc8fdf3dSkettenis 	ds_send_msg(&dc->lc, mr, len);
243*dc8fdf3dSkettenis 	free(mr);
244*dc8fdf3dSkettenis 
245*dc8fdf3dSkettenis 	while (mdstore_command == MDSET_END_REQUEST)
246*dc8fdf3dSkettenis 		ds_conn_handle(dc);
2476aace0ceSkettenis }
2486aace0ceSkettenis 
2496aace0ceSkettenis void
2506aace0ceSkettenis mdstore_select(struct ds_conn *dc, const char *name)
2516aace0ceSkettenis {
2526aace0ceSkettenis 	struct ds_conn_svc *dcs;
2536aace0ceSkettenis 	struct mdstore_sel_del_req *mr;
254*dc8fdf3dSkettenis 	size_t len = sizeof(*mr) + strlen(name);
2556aace0ceSkettenis 
2566aace0ceSkettenis 	TAILQ_FOREACH(dcs, &dc->services, link)
2576aace0ceSkettenis 		if (strcmp(dcs->service->ds_svc_id, "mdstore") == 0)
2586aace0ceSkettenis 			break;
2596aace0ceSkettenis 	assert(dcs != TAILQ_END(&dc->services));
2606aace0ceSkettenis 
2616aace0ceSkettenis 	mr = xzalloc(len);
2626aace0ceSkettenis 	mr->msg_type = DS_DATA;
2636aace0ceSkettenis 	mr->payload_len = len - 8;
2646aace0ceSkettenis 	mr->svc_handle = dcs->svc_handle;
2656aace0ceSkettenis 	mr->reqnum = mdstore_reqnum++;
2666aace0ceSkettenis 	mr->command = mdstore_command = MDSET_SELECT_REQUEST;
2676aace0ceSkettenis 	mr->namelen = strlen(name);
2686aace0ceSkettenis 	memcpy(mr->name, name, strlen(name));
2696aace0ceSkettenis 
2706aace0ceSkettenis 	ds_send_msg(&dc->lc, mr, len);
2716aace0ceSkettenis 	free(mr);
2726aace0ceSkettenis 
2736aace0ceSkettenis 	while (mdstore_command == MDSET_SELECT_REQUEST)
2746aace0ceSkettenis 		ds_conn_handle(dc);
275cceaa36bSkettenis }
276*dc8fdf3dSkettenis 
277*dc8fdf3dSkettenis void
278*dc8fdf3dSkettenis mdstore_delete(struct ds_conn *dc, const char *name)
279*dc8fdf3dSkettenis {
280*dc8fdf3dSkettenis 	struct ds_conn_svc *dcs;
281*dc8fdf3dSkettenis 	struct mdstore_sel_del_req *mr;
282*dc8fdf3dSkettenis 	size_t len = sizeof(*mr) + strlen(name);
283*dc8fdf3dSkettenis 
284*dc8fdf3dSkettenis 	TAILQ_FOREACH(dcs, &dc->services, link)
285*dc8fdf3dSkettenis 		if (strcmp(dcs->service->ds_svc_id, "mdstore") == 0)
286*dc8fdf3dSkettenis 			break;
287*dc8fdf3dSkettenis 	assert(dcs != TAILQ_END(&dc->services));
288*dc8fdf3dSkettenis 
289*dc8fdf3dSkettenis 	mr = xzalloc(len);
290*dc8fdf3dSkettenis 	mr->msg_type = DS_DATA;
291*dc8fdf3dSkettenis 	mr->payload_len = len - 8;
292*dc8fdf3dSkettenis 	mr->svc_handle = dcs->svc_handle;
293*dc8fdf3dSkettenis 	mr->reqnum = mdstore_reqnum++;
294*dc8fdf3dSkettenis 	mr->command = mdstore_command = MDSET_DELETE_REQUEST;
295*dc8fdf3dSkettenis 	mr->namelen = strlen(name);
296*dc8fdf3dSkettenis 	memcpy(mr->name, name, strlen(name));
297*dc8fdf3dSkettenis 
298*dc8fdf3dSkettenis 	ds_send_msg(&dc->lc, mr, len);
299*dc8fdf3dSkettenis 	free(mr);
300*dc8fdf3dSkettenis 
301*dc8fdf3dSkettenis 	while (mdstore_command == MDSET_DELETE_REQUEST)
302*dc8fdf3dSkettenis 		ds_conn_handle(dc);
303*dc8fdf3dSkettenis }
304*dc8fdf3dSkettenis 
305*dc8fdf3dSkettenis void
306*dc8fdf3dSkettenis mdstore_download(struct ds_conn *dc, const char *name)
307*dc8fdf3dSkettenis {
308*dc8fdf3dSkettenis 	struct ds_conn_svc *dcs;
309*dc8fdf3dSkettenis 
310*dc8fdf3dSkettenis 	TAILQ_FOREACH(dcs, &dc->services, link)
311*dc8fdf3dSkettenis 		if (strcmp(dcs->service->ds_svc_id, "mdstore") == 0)
312*dc8fdf3dSkettenis 			break;
313*dc8fdf3dSkettenis 	assert(dcs != TAILQ_END(&dc->services));
314*dc8fdf3dSkettenis 
315*dc8fdf3dSkettenis 	printf("begin\n");
316*dc8fdf3dSkettenis 	mdstore_begin(dc, dcs->svc_handle, name);
317*dc8fdf3dSkettenis 	printf("transfer 0\n");
318*dc8fdf3dSkettenis 	mdstore_transfer(dc, dcs->svc_handle, "primary.md",
319*dc8fdf3dSkettenis 	    MDSTORE_CTL_DOM_MD_TYPE, 0x100000);
320*dc8fdf3dSkettenis 	printf("transfer 1\n");
321*dc8fdf3dSkettenis 	mdstore_transfer(dc, dcs->svc_handle, "hv.md",
322*dc8fdf3dSkettenis 	    MDSTORE_HV_MD_TYPE, 0x80000);
323*dc8fdf3dSkettenis 	printf("transfer 2\n");
324*dc8fdf3dSkettenis 	mdstore_transfer(dc, dcs->svc_handle, "pri",
325*dc8fdf3dSkettenis 	    MDSTORE_PRI_TYPE, 0);
326*dc8fdf3dSkettenis 	printf("end\n");
327*dc8fdf3dSkettenis 	mdstore_end(dc, dcs->svc_handle, name);
328*dc8fdf3dSkettenis 	printf("done\n");
329*dc8fdf3dSkettenis }
330