1*06b192deSkettenis /* $OpenBSD: mdstore.c,v 1.9 2019/07/06 21:12: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> 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" 29cceaa36bSkettenis #include "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); 34cceaa36bSkettenis void mdstore_rx_data(struct ldc_conn *, uint64_t, void *, size_t); 35cceaa36bSkettenis 36cceaa36bSkettenis struct ds_service mdstore_service = { 37cceaa36bSkettenis "mdstore", 1, 0, mdstore_start, mdstore_rx_data 38cceaa36bSkettenis }; 39cceaa36bSkettenis 40a0709405Skettenis struct ds_service mdstore_service_v2 = { 41a0709405Skettenis "mdstore", 2, 0, mdstore_start_v2, mdstore_rx_data 42a0709405Skettenis }; 43a0709405Skettenis 44dc8fdf3dSkettenis #define MDSET_BEGIN_REQUEST 0x0001 45dc8fdf3dSkettenis #define MDSET_END_REQUEST 0x0002 46dc8fdf3dSkettenis #define MD_TRANSFER_REQUEST 0x0003 47cceaa36bSkettenis #define MDSET_LIST_REQUEST 0x0004 486aace0ceSkettenis #define MDSET_SELECT_REQUEST 0x0005 496aace0ceSkettenis #define MDSET_DELETE_REQUEST 0x0006 506aace0ceSkettenis #define MDSET_RETREIVE_REQUEST 0x0007 51cceaa36bSkettenis 52cceaa36bSkettenis struct mdstore_msg { 53cceaa36bSkettenis uint32_t msg_type; 54cceaa36bSkettenis uint32_t payload_len; 55cceaa36bSkettenis uint64_t svc_handle; 56cceaa36bSkettenis uint64_t reqnum; 57cceaa36bSkettenis uint16_t command; 58*06b192deSkettenis uint8_t reserved[6]; 59cceaa36bSkettenis } __packed; 60cceaa36bSkettenis 61dc8fdf3dSkettenis struct mdstore_begin_end_req { 62dc8fdf3dSkettenis uint32_t msg_type; 63dc8fdf3dSkettenis uint32_t payload_len; 64dc8fdf3dSkettenis uint64_t svc_handle; 65dc8fdf3dSkettenis uint64_t reqnum; 66dc8fdf3dSkettenis uint16_t command; 67dc8fdf3dSkettenis uint16_t nmds; 68dc8fdf3dSkettenis uint32_t namelen; 69dc8fdf3dSkettenis char name[1]; 70dc8fdf3dSkettenis } __packed; 71dc8fdf3dSkettenis 72a0709405Skettenis struct mdstore_begin_req_v2 { 73a0709405Skettenis uint32_t msg_type; 74a0709405Skettenis uint32_t payload_len; 75a0709405Skettenis uint64_t svc_handle; 76a0709405Skettenis uint64_t reqnum; 77a0709405Skettenis uint16_t command; 78a0709405Skettenis uint16_t nmds; 79a0709405Skettenis uint32_t config_size; 80a0709405Skettenis uint64_t timestamp; 81a0709405Skettenis uint32_t namelen; 82a0709405Skettenis char name[1]; 83a0709405Skettenis } __packed; 84a0709405Skettenis 85dc8fdf3dSkettenis struct mdstore_transfer_req { 86dc8fdf3dSkettenis uint32_t msg_type; 87dc8fdf3dSkettenis uint32_t payload_len; 88dc8fdf3dSkettenis uint64_t svc_handle; 89dc8fdf3dSkettenis uint64_t reqnum; 90dc8fdf3dSkettenis uint16_t command; 91dc8fdf3dSkettenis uint16_t type; 92dc8fdf3dSkettenis uint32_t size; 93dc8fdf3dSkettenis uint64_t offset; 94dc8fdf3dSkettenis char md[]; 95dc8fdf3dSkettenis } __packed; 96dc8fdf3dSkettenis 97dc8fdf3dSkettenis #define MDSTORE_PRI_TYPE 0x01 98dc8fdf3dSkettenis #define MDSTORE_HV_MD_TYPE 0x02 99dc8fdf3dSkettenis #define MDSTORE_CTL_DOM_MD_TYPE 0x04 100dc8fdf3dSkettenis #define MDSTORE_SVC_DOM_MD_TYPE 0x08 101dc8fdf3dSkettenis 1026aace0ceSkettenis struct mdstore_sel_del_req { 1036aace0ceSkettenis uint32_t msg_type; 1046aace0ceSkettenis uint32_t payload_len; 1056aace0ceSkettenis uint64_t svc_handle; 1066aace0ceSkettenis uint64_t reqnum; 1076aace0ceSkettenis uint16_t command; 108*06b192deSkettenis uint8_t reserved[2]; 1096aace0ceSkettenis uint32_t namelen; 1106aace0ceSkettenis char name[1]; 1116aace0ceSkettenis } __packed; 1126aace0ceSkettenis 113cceaa36bSkettenis #define MDSET_LIST_REPLY 0x0104 114cceaa36bSkettenis 115cceaa36bSkettenis struct mdstore_list_resp { 116cceaa36bSkettenis uint32_t msg_type; 117cceaa36bSkettenis uint32_t payload_len; 118cceaa36bSkettenis uint64_t svc_handle; 119cceaa36bSkettenis uint64_t reqnum; 120cceaa36bSkettenis uint32_t result; 121cceaa36bSkettenis uint16_t booted_set; 122cceaa36bSkettenis uint16_t boot_set; 123cceaa36bSkettenis char sets[1]; 124cceaa36bSkettenis } __packed; 125cceaa36bSkettenis 126cceaa36bSkettenis #define MDST_SUCCESS 0x0 127cceaa36bSkettenis #define MDST_FAILURE 0x1 128cceaa36bSkettenis #define MDST_INVALID_MSG 0x2 129cceaa36bSkettenis #define MDST_MAX_MDS_ERR 0x3 130cceaa36bSkettenis #define MDST_BAD_NAME_ERR 0x4 131cceaa36bSkettenis #define MDST_SET_EXISTS_ERR 0x5 132cceaa36bSkettenis #define MDST_ALLOC_SET_ERR 0x6 133cceaa36bSkettenis #define MDST_ALLOC_MD_ERR 0x7 134cceaa36bSkettenis #define MDST_MD_COUNT_ERR 0x8 135cceaa36bSkettenis #define MDST_MD_SIZE_ERR 0x9 136cceaa36bSkettenis #define MDST_MD_TYPE_ERR 0xa 137cceaa36bSkettenis #define MDST_NOT_EXIST_ERR 0xb 138cceaa36bSkettenis 139cceaa36bSkettenis struct mdstore_set_head mdstore_sets = TAILQ_HEAD_INITIALIZER(mdstore_sets); 1406aace0ceSkettenis uint64_t mdstore_reqnum; 1416aace0ceSkettenis uint64_t mdstore_command; 142a0709405Skettenis uint16_t mdstore_major; 143a0709405Skettenis 144a0709405Skettenis void 145a0709405Skettenis mdstore_register(struct ds_conn *dc) 146a0709405Skettenis { 147a0709405Skettenis ds_conn_register_service(dc, &mdstore_service); 148a0709405Skettenis ds_conn_register_service(dc, &mdstore_service_v2); 149a0709405Skettenis } 150cceaa36bSkettenis 151cceaa36bSkettenis void 152cceaa36bSkettenis mdstore_start(struct ldc_conn *lc, uint64_t svc_handle) 153cceaa36bSkettenis { 154cceaa36bSkettenis struct mdstore_msg mm; 155cceaa36bSkettenis 156cceaa36bSkettenis bzero(&mm, sizeof(mm)); 157cceaa36bSkettenis mm.msg_type = DS_DATA; 158cceaa36bSkettenis mm.payload_len = sizeof(mm) - 8; 159cceaa36bSkettenis mm.svc_handle = svc_handle; 1606aace0ceSkettenis mm.reqnum = mdstore_reqnum++; 1616aace0ceSkettenis mm.command = mdstore_command = MDSET_LIST_REQUEST; 162cceaa36bSkettenis ds_send_msg(lc, &mm, sizeof(mm)); 163cceaa36bSkettenis } 164cceaa36bSkettenis 165cceaa36bSkettenis void 166a0709405Skettenis mdstore_start_v2(struct ldc_conn *lc, uint64_t svc_handle) 167a0709405Skettenis { 168a0709405Skettenis mdstore_major = 2; 169a0709405Skettenis mdstore_start(lc, svc_handle); 170a0709405Skettenis } 171a0709405Skettenis 172a0709405Skettenis void 173cceaa36bSkettenis mdstore_rx_data(struct ldc_conn *lc, uint64_t svc_handle, void *data, 174cceaa36bSkettenis size_t len) 175cceaa36bSkettenis { 176cceaa36bSkettenis struct mdstore_list_resp *mr = data; 177cceaa36bSkettenis struct mdstore_set *set; 178cceaa36bSkettenis int idx; 179cceaa36bSkettenis 180cceaa36bSkettenis if (mr->result != MDST_SUCCESS) { 181a2ea7dabSkettenis switch (mr->result) { 182a2ea7dabSkettenis case MDST_SET_EXISTS_ERR: 183a2ea7dabSkettenis errx(1, "Configuration already exists"); 184a2ea7dabSkettenis break; 185a2ea7dabSkettenis case MDST_NOT_EXIST_ERR: 186a2ea7dabSkettenis errx(1, "No such configuration"); 187a2ea7dabSkettenis break; 188a2ea7dabSkettenis default: 189a2ea7dabSkettenis errx(1, "Unexpected result 0x%x\n", mr->result); 190a2ea7dabSkettenis break; 191a2ea7dabSkettenis } 192cceaa36bSkettenis } 193cceaa36bSkettenis 1946aace0ceSkettenis switch (mdstore_command) { 1956aace0ceSkettenis case MDSET_LIST_REQUEST: 1966aace0ceSkettenis for (idx = 0, len = 0; len < mr->payload_len - 24; idx++) { 197cceaa36bSkettenis set = xmalloc(sizeof(*set)); 198cceaa36bSkettenis set->name = xstrdup(&mr->sets[len]); 199cceaa36bSkettenis set->booted_set = (idx == mr->booted_set); 200cceaa36bSkettenis set->boot_set = (idx == mr->boot_set); 201cceaa36bSkettenis TAILQ_INSERT_TAIL(&mdstore_sets, set, link); 202cceaa36bSkettenis len += strlen(&mr->sets[len]) + 1; 203a0709405Skettenis if (mdstore_major == 2) 204a0709405Skettenis len += sizeof(uint64_t); /* skip timestamp */ 205cceaa36bSkettenis } 2066aace0ceSkettenis break; 2076aace0ceSkettenis } 208dc8fdf3dSkettenis 209dc8fdf3dSkettenis mdstore_command = 0; 210dc8fdf3dSkettenis } 211dc8fdf3dSkettenis 212dc8fdf3dSkettenis void 213a0709405Skettenis mdstore_begin_v1(struct ds_conn *dc, uint64_t svc_handle, const char *name, 214bb93e559Skettenis int nmds) 215dc8fdf3dSkettenis { 216dc8fdf3dSkettenis struct mdstore_begin_end_req *mr; 217dc8fdf3dSkettenis size_t len = sizeof(*mr) + strlen(name); 218dc8fdf3dSkettenis 219dc8fdf3dSkettenis mr = xzalloc(len); 220dc8fdf3dSkettenis mr->msg_type = DS_DATA; 221dc8fdf3dSkettenis mr->payload_len = len - 8; 222dc8fdf3dSkettenis mr->svc_handle = svc_handle; 223dc8fdf3dSkettenis mr->reqnum = mdstore_reqnum++; 224dc8fdf3dSkettenis mr->command = mdstore_command = MDSET_BEGIN_REQUEST; 225bb93e559Skettenis mr->nmds = nmds; 226dc8fdf3dSkettenis mr->namelen = strlen(name); 227dc8fdf3dSkettenis memcpy(mr->name, name, strlen(name)); 228dc8fdf3dSkettenis 229dc8fdf3dSkettenis ds_send_msg(&dc->lc, mr, len); 230dc8fdf3dSkettenis free(mr); 231dc8fdf3dSkettenis 232dc8fdf3dSkettenis while (mdstore_command == MDSET_BEGIN_REQUEST) 233dc8fdf3dSkettenis ds_conn_handle(dc); 234dc8fdf3dSkettenis } 235dc8fdf3dSkettenis 236dc8fdf3dSkettenis void 237a0709405Skettenis mdstore_begin_v2(struct ds_conn *dc, uint64_t svc_handle, const char *name, 238a0709405Skettenis int nmds, uint32_t config_size) 239a0709405Skettenis { 240a0709405Skettenis struct mdstore_begin_req_v2 *mr; 241a0709405Skettenis size_t len = sizeof(*mr) + strlen(name); 242a0709405Skettenis 243a0709405Skettenis mr = xzalloc(len); 244a0709405Skettenis mr->msg_type = DS_DATA; 245a0709405Skettenis mr->payload_len = len - 8; 246a0709405Skettenis mr->svc_handle = svc_handle; 247a0709405Skettenis mr->reqnum = mdstore_reqnum++; 248a0709405Skettenis mr->command = mdstore_command = MDSET_BEGIN_REQUEST; 249a0709405Skettenis mr->config_size = config_size; 250a0709405Skettenis mr->timestamp = time(NULL); 251a0709405Skettenis mr->nmds = nmds; 252a0709405Skettenis mr->namelen = strlen(name); 253a0709405Skettenis memcpy(mr->name, name, strlen(name)); 254a0709405Skettenis 255a0709405Skettenis ds_send_msg(&dc->lc, mr, len); 256a0709405Skettenis free(mr); 257a0709405Skettenis 258a0709405Skettenis while (mdstore_command == MDSET_BEGIN_REQUEST) 259a0709405Skettenis ds_conn_handle(dc); 260a0709405Skettenis } 261a0709405Skettenis 262a0709405Skettenis void 263a0709405Skettenis mdstore_begin(struct ds_conn *dc, uint64_t svc_handle, const char *name, 264a0709405Skettenis int nmds, uint32_t config_size) 265a0709405Skettenis { 266a0709405Skettenis if (mdstore_major == 2) 267a0709405Skettenis mdstore_begin_v2(dc, svc_handle, name, nmds, config_size); 268a0709405Skettenis else 269a0709405Skettenis mdstore_begin_v1(dc, svc_handle, name, nmds); 270a0709405Skettenis } 271a0709405Skettenis 272a0709405Skettenis void 273dc8fdf3dSkettenis mdstore_transfer(struct ds_conn *dc, uint64_t svc_handle, const char *path, 274dc8fdf3dSkettenis uint16_t type, uint64_t offset) 275dc8fdf3dSkettenis { 276dc8fdf3dSkettenis struct mdstore_transfer_req *mr; 277dc8fdf3dSkettenis uint32_t size; 278dc8fdf3dSkettenis size_t len; 279dc8fdf3dSkettenis FILE *fp; 280dc8fdf3dSkettenis 281dc8fdf3dSkettenis fp = fopen(path, "r"); 282dc8fdf3dSkettenis if (fp == NULL) 283dc8fdf3dSkettenis err(1, "fopen"); 284dc8fdf3dSkettenis 285dc8fdf3dSkettenis fseek(fp, 0, SEEK_END); 286dc8fdf3dSkettenis size = ftell(fp); 287dc8fdf3dSkettenis fseek(fp, 0, SEEK_SET); 288dc8fdf3dSkettenis 289dc8fdf3dSkettenis len = sizeof(*mr) + size; 290dc8fdf3dSkettenis mr = xzalloc(len); 291dc8fdf3dSkettenis 292dc8fdf3dSkettenis mr->msg_type = DS_DATA; 293dc8fdf3dSkettenis mr->payload_len = len - 8; 294dc8fdf3dSkettenis mr->svc_handle = svc_handle; 295dc8fdf3dSkettenis mr->reqnum = mdstore_reqnum++; 296dc8fdf3dSkettenis mr->command = mdstore_command = MD_TRANSFER_REQUEST; 297dc8fdf3dSkettenis mr->type = type; 298dc8fdf3dSkettenis mr->size = size; 299dc8fdf3dSkettenis mr->offset = offset; 300dc8fdf3dSkettenis if (fread(&mr->md, size, 1, fp) != 1) 301dc8fdf3dSkettenis err(1, "fread"); 302dc8fdf3dSkettenis ds_send_msg(&dc->lc, mr, len); 303dc8fdf3dSkettenis free(mr); 304dc8fdf3dSkettenis 305dc8fdf3dSkettenis fclose(fp); 306dc8fdf3dSkettenis 307dc8fdf3dSkettenis while (mdstore_command == MD_TRANSFER_REQUEST) 308dc8fdf3dSkettenis ds_conn_handle(dc); 309dc8fdf3dSkettenis } 310dc8fdf3dSkettenis 311dc8fdf3dSkettenis void 312bb93e559Skettenis mdstore_end(struct ds_conn *dc, uint64_t svc_handle, const char *name, 313bb93e559Skettenis int nmds) 314dc8fdf3dSkettenis { 315dc8fdf3dSkettenis struct mdstore_begin_end_req *mr; 316dc8fdf3dSkettenis size_t len = sizeof(*mr) + strlen(name); 317dc8fdf3dSkettenis 318dc8fdf3dSkettenis mr = xzalloc(len); 319dc8fdf3dSkettenis mr->msg_type = DS_DATA; 320dc8fdf3dSkettenis mr->payload_len = len - 8; 321dc8fdf3dSkettenis mr->svc_handle = svc_handle; 322dc8fdf3dSkettenis mr->reqnum = mdstore_reqnum++; 323dc8fdf3dSkettenis mr->command = mdstore_command = MDSET_END_REQUEST; 324bb93e559Skettenis mr->nmds = nmds; 325dc8fdf3dSkettenis mr->namelen = strlen(name); 326dc8fdf3dSkettenis memcpy(mr->name, name, strlen(name)); 327dc8fdf3dSkettenis 328dc8fdf3dSkettenis ds_send_msg(&dc->lc, mr, len); 329dc8fdf3dSkettenis free(mr); 330dc8fdf3dSkettenis 331dc8fdf3dSkettenis while (mdstore_command == MDSET_END_REQUEST) 332dc8fdf3dSkettenis ds_conn_handle(dc); 3336aace0ceSkettenis } 3346aace0ceSkettenis 3356aace0ceSkettenis void 3366aace0ceSkettenis mdstore_select(struct ds_conn *dc, const char *name) 3376aace0ceSkettenis { 3386aace0ceSkettenis struct ds_conn_svc *dcs; 3396aace0ceSkettenis struct mdstore_sel_del_req *mr; 340dc8fdf3dSkettenis size_t len = sizeof(*mr) + strlen(name); 3416aace0ceSkettenis 3426aace0ceSkettenis TAILQ_FOREACH(dcs, &dc->services, link) 3436aace0ceSkettenis if (strcmp(dcs->service->ds_svc_id, "mdstore") == 0) 3446aace0ceSkettenis break; 345abcbcc4dSdoug assert(dcs != NULL); 3466aace0ceSkettenis 3476aace0ceSkettenis mr = xzalloc(len); 3486aace0ceSkettenis mr->msg_type = DS_DATA; 3496aace0ceSkettenis mr->payload_len = len - 8; 3506aace0ceSkettenis mr->svc_handle = dcs->svc_handle; 3516aace0ceSkettenis mr->reqnum = mdstore_reqnum++; 3526aace0ceSkettenis mr->command = mdstore_command = MDSET_SELECT_REQUEST; 3536aace0ceSkettenis mr->namelen = strlen(name); 3546aace0ceSkettenis memcpy(mr->name, name, strlen(name)); 3556aace0ceSkettenis 3566aace0ceSkettenis ds_send_msg(&dc->lc, mr, len); 3576aace0ceSkettenis free(mr); 3586aace0ceSkettenis 3596aace0ceSkettenis while (mdstore_command == MDSET_SELECT_REQUEST) 3606aace0ceSkettenis ds_conn_handle(dc); 361cceaa36bSkettenis } 362dc8fdf3dSkettenis 363dc8fdf3dSkettenis void 364dc8fdf3dSkettenis mdstore_delete(struct ds_conn *dc, const char *name) 365dc8fdf3dSkettenis { 366dc8fdf3dSkettenis struct ds_conn_svc *dcs; 367dc8fdf3dSkettenis struct mdstore_sel_del_req *mr; 368dc8fdf3dSkettenis size_t len = sizeof(*mr) + strlen(name); 369dc8fdf3dSkettenis 370dc8fdf3dSkettenis TAILQ_FOREACH(dcs, &dc->services, link) 371dc8fdf3dSkettenis if (strcmp(dcs->service->ds_svc_id, "mdstore") == 0) 372dc8fdf3dSkettenis break; 373abcbcc4dSdoug assert(dcs != NULL); 374dc8fdf3dSkettenis 375dc8fdf3dSkettenis mr = xzalloc(len); 376dc8fdf3dSkettenis mr->msg_type = DS_DATA; 377dc8fdf3dSkettenis mr->payload_len = len - 8; 378dc8fdf3dSkettenis mr->svc_handle = dcs->svc_handle; 379dc8fdf3dSkettenis mr->reqnum = mdstore_reqnum++; 380dc8fdf3dSkettenis mr->command = mdstore_command = MDSET_DELETE_REQUEST; 381dc8fdf3dSkettenis mr->namelen = strlen(name); 382dc8fdf3dSkettenis memcpy(mr->name, name, strlen(name)); 383dc8fdf3dSkettenis 384dc8fdf3dSkettenis ds_send_msg(&dc->lc, mr, len); 385dc8fdf3dSkettenis free(mr); 386dc8fdf3dSkettenis 387dc8fdf3dSkettenis while (mdstore_command == MDSET_DELETE_REQUEST) 388dc8fdf3dSkettenis ds_conn_handle(dc); 389dc8fdf3dSkettenis } 390dc8fdf3dSkettenis 391bb93e559Skettenis void frag_init(void); 392bb93e559Skettenis void add_frag_mblock(struct md_node *); 393bb93e559Skettenis void add_frag(uint64_t); 394bb93e559Skettenis void delete_frag(uint64_t); 395bb93e559Skettenis uint64_t alloc_frag(void); 396bb93e559Skettenis 397dc8fdf3dSkettenis void 398dc8fdf3dSkettenis mdstore_download(struct ds_conn *dc, const char *name) 399dc8fdf3dSkettenis { 400dc8fdf3dSkettenis struct ds_conn_svc *dcs; 401bb93e559Skettenis struct md_node *node; 402bb93e559Skettenis struct md_prop *prop; 403bb93e559Skettenis struct guest *guest; 404bb93e559Skettenis int nmds = 2; 405bb93e559Skettenis char *path; 406a0709405Skettenis uint32_t total_size = 0; 407bb93e559Skettenis uint16_t type; 408dc8fdf3dSkettenis 409dc8fdf3dSkettenis TAILQ_FOREACH(dcs, &dc->services, link) 410dc8fdf3dSkettenis if (strcmp(dcs->service->ds_svc_id, "mdstore") == 0) 411dc8fdf3dSkettenis break; 412abcbcc4dSdoug assert(dcs != NULL); 413dc8fdf3dSkettenis 414bb93e559Skettenis if (asprintf(&path, "%s/hv.md", name) == -1) 415bb93e559Skettenis err(1, "asprintf"); 416bb93e559Skettenis hvmd = md_read(path); 417bb93e559Skettenis free(path); 418bb93e559Skettenis 419bb93e559Skettenis if (hvmd == NULL) 420bb93e559Skettenis err(1, "%s", name); 421bb93e559Skettenis 422bb93e559Skettenis node = md_find_node(hvmd, "guests"); 42397d8cafcSkettenis TAILQ_INIT(&guest_list); 424bb93e559Skettenis TAILQ_FOREACH(prop, &node->prop_list, link) { 425bb93e559Skettenis if (prop->tag == MD_PROP_ARC && 426bb93e559Skettenis strcmp(prop->name->str, "fwd") == 0) { 427bb93e559Skettenis add_guest(prop->d.arc.node); 428bb93e559Skettenis nmds++; 429bb93e559Skettenis } 430bb93e559Skettenis } 431bb93e559Skettenis 432bb93e559Skettenis frag_init(); 433bb93e559Skettenis hv_mdpa = alloc_frag(); 434bb93e559Skettenis 435a0709405Skettenis TAILQ_FOREACH(guest, &guest_list, link) { 436a0709405Skettenis if (asprintf(&path, "%s/%s.md", name, guest->name) == -1) 437a0709405Skettenis err(1, "asprintf"); 438a0709405Skettenis total_size += md_size(path); 439a0709405Skettenis } 440a0709405Skettenis if (asprintf(&path, "%s/hv.md", name) == -1) 441a0709405Skettenis err(1, "asprintf"); 442a0709405Skettenis total_size += md_size(path); 443a0709405Skettenis if (asprintf(&path, "%s/pri", name) == -1) 444a0709405Skettenis err(1, "asprintf"); 445a0709405Skettenis total_size += md_size(path); 446a0709405Skettenis 447a0709405Skettenis mdstore_begin(dc, dcs->svc_handle, name, nmds, total_size); 44897d8cafcSkettenis TAILQ_FOREACH(guest, &guest_list, link) { 449bb93e559Skettenis if (asprintf(&path, "%s/%s.md", name, guest->name) == -1) 450bb93e559Skettenis err(1, "asprintf"); 451bb93e559Skettenis type = 0; 452bb93e559Skettenis if (strcmp(guest->name, "primary") == 0) 453bb93e559Skettenis type = MDSTORE_CTL_DOM_MD_TYPE; 454bb93e559Skettenis mdstore_transfer(dc, dcs->svc_handle, path, type, guest->mdpa); 455bb93e559Skettenis free(path); 456bb93e559Skettenis } 457bb93e559Skettenis if (asprintf(&path, "%s/hv.md", name) == -1) 458bb93e559Skettenis err(1, "asprintf"); 459bb93e559Skettenis mdstore_transfer(dc, dcs->svc_handle, path, 460bb93e559Skettenis MDSTORE_HV_MD_TYPE, hv_mdpa); 461bb93e559Skettenis free(path); 462bb93e559Skettenis if (asprintf(&path, "%s/pri", name) == -1) 463bb93e559Skettenis err(1, "asprintf"); 464bb93e559Skettenis mdstore_transfer(dc, dcs->svc_handle, path, 465dc8fdf3dSkettenis MDSTORE_PRI_TYPE, 0); 466bb93e559Skettenis free(path); 467bb93e559Skettenis mdstore_end(dc, dcs->svc_handle, name, nmds); 468bb93e559Skettenis } 469bb93e559Skettenis 470bb93e559Skettenis struct frag { 471bb93e559Skettenis TAILQ_ENTRY(frag) link; 472bb93e559Skettenis uint64_t base; 473bb93e559Skettenis }; 474bb93e559Skettenis 475bb93e559Skettenis TAILQ_HEAD(frag_head, frag) free_frags; 476bb93e559Skettenis 477bb93e559Skettenis uint64_t fragsize; 478bb93e559Skettenis 479bb93e559Skettenis void 480bb93e559Skettenis frag_init(void) 481bb93e559Skettenis { 482bb93e559Skettenis struct md_node *node; 483bb93e559Skettenis struct md_prop *prop; 484bb93e559Skettenis 485bb93e559Skettenis node = md_find_node(hvmd, "frag_space"); 486bb93e559Skettenis md_get_prop_val(hvmd, node, "fragsize", &fragsize); 487bb93e559Skettenis TAILQ_INIT(&free_frags); 488bb93e559Skettenis TAILQ_FOREACH(prop, &node->prop_list, link) { 489bb93e559Skettenis if (prop->tag == MD_PROP_ARC && 490bb93e559Skettenis strcmp(prop->name->str, "fwd") == 0) 491bb93e559Skettenis add_frag_mblock(prop->d.arc.node); 492bb93e559Skettenis } 493bb93e559Skettenis } 494bb93e559Skettenis 495bb93e559Skettenis void 496bb93e559Skettenis add_frag_mblock(struct md_node *node) 497bb93e559Skettenis { 498bb93e559Skettenis uint64_t base, size; 499bb93e559Skettenis struct guest *guest; 500bb93e559Skettenis 501bb93e559Skettenis md_get_prop_val(hvmd, node, "base", &base); 502bb93e559Skettenis md_get_prop_val(hvmd, node, "size", &size); 503bb93e559Skettenis while (size > fragsize) { 504bb93e559Skettenis add_frag(base); 505bb93e559Skettenis size -= fragsize; 506bb93e559Skettenis base += fragsize; 507bb93e559Skettenis } 508bb93e559Skettenis 509bb93e559Skettenis delete_frag(hv_mdpa); 51097d8cafcSkettenis TAILQ_FOREACH(guest, &guest_list, link) 511bb93e559Skettenis delete_frag(guest->mdpa); 512bb93e559Skettenis } 513bb93e559Skettenis 514bb93e559Skettenis void 515bb93e559Skettenis add_frag(uint64_t base) 516bb93e559Skettenis { 517bb93e559Skettenis struct frag *frag; 518bb93e559Skettenis 519bb93e559Skettenis frag = xmalloc(sizeof(*frag)); 520bb93e559Skettenis frag->base = base; 521bb93e559Skettenis TAILQ_INSERT_TAIL(&free_frags, frag, link); 522bb93e559Skettenis } 523bb93e559Skettenis 524bb93e559Skettenis void 525bb93e559Skettenis delete_frag(uint64_t base) 526bb93e559Skettenis { 527bb93e559Skettenis struct frag *frag; 528bb93e559Skettenis struct frag *tmp; 529bb93e559Skettenis 530bb93e559Skettenis TAILQ_FOREACH_SAFE(frag, &free_frags, link, tmp) { 531bb93e559Skettenis if (frag->base == base) { 532bb93e559Skettenis TAILQ_REMOVE(&free_frags, frag, link); 533bb93e559Skettenis free(frag); 534bb93e559Skettenis } 535bb93e559Skettenis } 536bb93e559Skettenis } 537bb93e559Skettenis 538bb93e559Skettenis uint64_t 539bb93e559Skettenis alloc_frag(void) 540bb93e559Skettenis { 541bb93e559Skettenis struct frag *frag; 542bb93e559Skettenis uint64_t base; 543bb93e559Skettenis 544bb93e559Skettenis frag = TAILQ_FIRST(&free_frags); 545bb93e559Skettenis if (frag == NULL) 546bb93e559Skettenis return -1; 547bb93e559Skettenis 548bb93e559Skettenis TAILQ_REMOVE(&free_frags, frag, link); 549bb93e559Skettenis base = frag->base; 550bb93e559Skettenis free(frag); 551bb93e559Skettenis 552bb93e559Skettenis return base; 553dc8fdf3dSkettenis } 554