1*abcbcc4dSdoug /* $OpenBSD: mdstore.c,v 1.7 2014/09/13 16:06:37 doug 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> 24cceaa36bSkettenis 25cceaa36bSkettenis #include "ds.h" 26bb93e559Skettenis #include "mdesc.h" 27cceaa36bSkettenis #include "mdstore.h" 28cceaa36bSkettenis #include "util.h" 29bb93e559Skettenis #include "ldomctl.h" 30cceaa36bSkettenis 31cceaa36bSkettenis void mdstore_start(struct ldc_conn *, uint64_t); 32cceaa36bSkettenis void mdstore_rx_data(struct ldc_conn *, uint64_t, void *, size_t); 33cceaa36bSkettenis 34cceaa36bSkettenis struct ds_service mdstore_service = { 35cceaa36bSkettenis "mdstore", 1, 0, mdstore_start, mdstore_rx_data 36cceaa36bSkettenis }; 37cceaa36bSkettenis 38dc8fdf3dSkettenis #define MDSET_BEGIN_REQUEST 0x0001 39dc8fdf3dSkettenis #define MDSET_END_REQUEST 0x0002 40dc8fdf3dSkettenis #define MD_TRANSFER_REQUEST 0x0003 41cceaa36bSkettenis #define MDSET_LIST_REQUEST 0x0004 426aace0ceSkettenis #define MDSET_SELECT_REQUEST 0x0005 436aace0ceSkettenis #define MDSET_DELETE_REQUEST 0x0006 446aace0ceSkettenis #define MDSET_RETREIVE_REQUEST 0x0007 45cceaa36bSkettenis 46cceaa36bSkettenis struct mdstore_msg { 47cceaa36bSkettenis uint32_t msg_type; 48cceaa36bSkettenis uint32_t payload_len; 49cceaa36bSkettenis uint64_t svc_handle; 50cceaa36bSkettenis uint64_t reqnum; 51cceaa36bSkettenis uint16_t command; 52cceaa36bSkettenis } __packed; 53cceaa36bSkettenis 54dc8fdf3dSkettenis struct mdstore_begin_end_req { 55dc8fdf3dSkettenis uint32_t msg_type; 56dc8fdf3dSkettenis uint32_t payload_len; 57dc8fdf3dSkettenis uint64_t svc_handle; 58dc8fdf3dSkettenis uint64_t reqnum; 59dc8fdf3dSkettenis uint16_t command; 60dc8fdf3dSkettenis uint16_t nmds; 61dc8fdf3dSkettenis uint32_t namelen; 62dc8fdf3dSkettenis char name[1]; 63dc8fdf3dSkettenis } __packed; 64dc8fdf3dSkettenis 65dc8fdf3dSkettenis struct mdstore_transfer_req { 66dc8fdf3dSkettenis uint32_t msg_type; 67dc8fdf3dSkettenis uint32_t payload_len; 68dc8fdf3dSkettenis uint64_t svc_handle; 69dc8fdf3dSkettenis uint64_t reqnum; 70dc8fdf3dSkettenis uint16_t command; 71dc8fdf3dSkettenis uint16_t type; 72dc8fdf3dSkettenis uint32_t size; 73dc8fdf3dSkettenis uint64_t offset; 74dc8fdf3dSkettenis char md[]; 75dc8fdf3dSkettenis } __packed; 76dc8fdf3dSkettenis 77dc8fdf3dSkettenis #define MDSTORE_PRI_TYPE 0x01 78dc8fdf3dSkettenis #define MDSTORE_HV_MD_TYPE 0x02 79dc8fdf3dSkettenis #define MDSTORE_CTL_DOM_MD_TYPE 0x04 80dc8fdf3dSkettenis #define MDSTORE_SVC_DOM_MD_TYPE 0x08 81dc8fdf3dSkettenis 826aace0ceSkettenis struct mdstore_sel_del_req { 836aace0ceSkettenis uint32_t msg_type; 846aace0ceSkettenis uint32_t payload_len; 856aace0ceSkettenis uint64_t svc_handle; 866aace0ceSkettenis uint64_t reqnum; 876aace0ceSkettenis uint16_t command; 886aace0ceSkettenis uint16_t reserved; 896aace0ceSkettenis uint32_t namelen; 906aace0ceSkettenis char name[1]; 916aace0ceSkettenis } __packed; 926aace0ceSkettenis 93cceaa36bSkettenis #define MDSET_LIST_REPLY 0x0104 94cceaa36bSkettenis 95cceaa36bSkettenis struct mdstore_list_resp { 96cceaa36bSkettenis uint32_t msg_type; 97cceaa36bSkettenis uint32_t payload_len; 98cceaa36bSkettenis uint64_t svc_handle; 99cceaa36bSkettenis uint64_t reqnum; 100cceaa36bSkettenis uint32_t result; 101cceaa36bSkettenis uint16_t booted_set; 102cceaa36bSkettenis uint16_t boot_set; 103cceaa36bSkettenis char sets[1]; 104cceaa36bSkettenis } __packed; 105cceaa36bSkettenis 106cceaa36bSkettenis #define MDST_SUCCESS 0x0 107cceaa36bSkettenis #define MDST_FAILURE 0x1 108cceaa36bSkettenis #define MDST_INVALID_MSG 0x2 109cceaa36bSkettenis #define MDST_MAX_MDS_ERR 0x3 110cceaa36bSkettenis #define MDST_BAD_NAME_ERR 0x4 111cceaa36bSkettenis #define MDST_SET_EXISTS_ERR 0x5 112cceaa36bSkettenis #define MDST_ALLOC_SET_ERR 0x6 113cceaa36bSkettenis #define MDST_ALLOC_MD_ERR 0x7 114cceaa36bSkettenis #define MDST_MD_COUNT_ERR 0x8 115cceaa36bSkettenis #define MDST_MD_SIZE_ERR 0x9 116cceaa36bSkettenis #define MDST_MD_TYPE_ERR 0xa 117cceaa36bSkettenis #define MDST_NOT_EXIST_ERR 0xb 118cceaa36bSkettenis 119cceaa36bSkettenis struct mdstore_set_head mdstore_sets = TAILQ_HEAD_INITIALIZER(mdstore_sets); 1206aace0ceSkettenis uint64_t mdstore_reqnum; 1216aace0ceSkettenis uint64_t mdstore_command; 122cceaa36bSkettenis 123cceaa36bSkettenis void 124cceaa36bSkettenis mdstore_start(struct ldc_conn *lc, uint64_t svc_handle) 125cceaa36bSkettenis { 126cceaa36bSkettenis struct mdstore_msg mm; 127cceaa36bSkettenis 128cceaa36bSkettenis bzero(&mm, sizeof(mm)); 129cceaa36bSkettenis mm.msg_type = DS_DATA; 130cceaa36bSkettenis mm.payload_len = sizeof(mm) - 8; 131cceaa36bSkettenis mm.svc_handle = svc_handle; 1326aace0ceSkettenis mm.reqnum = mdstore_reqnum++; 1336aace0ceSkettenis mm.command = mdstore_command = MDSET_LIST_REQUEST; 134cceaa36bSkettenis ds_send_msg(lc, &mm, sizeof(mm)); 135cceaa36bSkettenis } 136cceaa36bSkettenis 137cceaa36bSkettenis void 138cceaa36bSkettenis mdstore_rx_data(struct ldc_conn *lc, uint64_t svc_handle, void *data, 139cceaa36bSkettenis size_t len) 140cceaa36bSkettenis { 141cceaa36bSkettenis struct mdstore_list_resp *mr = data; 142cceaa36bSkettenis struct mdstore_set *set; 143cceaa36bSkettenis int idx; 144cceaa36bSkettenis 145cceaa36bSkettenis if (mr->result != MDST_SUCCESS) { 146a2ea7dabSkettenis switch (mr->result) { 147a2ea7dabSkettenis case MDST_SET_EXISTS_ERR: 148a2ea7dabSkettenis errx(1, "Configuration already exists"); 149a2ea7dabSkettenis break; 150a2ea7dabSkettenis case MDST_NOT_EXIST_ERR: 151a2ea7dabSkettenis errx(1, "No such configuration"); 152a2ea7dabSkettenis break; 153a2ea7dabSkettenis default: 154a2ea7dabSkettenis errx(1, "Unexpected result 0x%x\n", mr->result); 155a2ea7dabSkettenis break; 156a2ea7dabSkettenis } 157cceaa36bSkettenis } 158cceaa36bSkettenis 1596aace0ceSkettenis switch (mdstore_command) { 1606aace0ceSkettenis case MDSET_LIST_REQUEST: 1616aace0ceSkettenis for (idx = 0, len = 0; len < mr->payload_len - 24; idx++) { 162cceaa36bSkettenis set = xmalloc(sizeof(*set)); 163cceaa36bSkettenis set->name = xstrdup(&mr->sets[len]); 164cceaa36bSkettenis set->booted_set = (idx == mr->booted_set); 165cceaa36bSkettenis set->boot_set = (idx == mr->boot_set); 166cceaa36bSkettenis TAILQ_INSERT_TAIL(&mdstore_sets, set, link); 167cceaa36bSkettenis len += strlen(&mr->sets[len]) + 1; 168cceaa36bSkettenis } 1696aace0ceSkettenis break; 1706aace0ceSkettenis } 171dc8fdf3dSkettenis 172dc8fdf3dSkettenis mdstore_command = 0; 173dc8fdf3dSkettenis } 174dc8fdf3dSkettenis 175dc8fdf3dSkettenis void 176bb93e559Skettenis mdstore_begin(struct ds_conn *dc, uint64_t svc_handle, const char *name, 177bb93e559Skettenis int nmds) 178dc8fdf3dSkettenis { 179dc8fdf3dSkettenis struct mdstore_begin_end_req *mr; 180dc8fdf3dSkettenis size_t len = sizeof(*mr) + strlen(name); 181dc8fdf3dSkettenis 182dc8fdf3dSkettenis mr = xzalloc(len); 183dc8fdf3dSkettenis mr->msg_type = DS_DATA; 184dc8fdf3dSkettenis mr->payload_len = len - 8; 185dc8fdf3dSkettenis mr->svc_handle = svc_handle; 186dc8fdf3dSkettenis mr->reqnum = mdstore_reqnum++; 187dc8fdf3dSkettenis mr->command = mdstore_command = MDSET_BEGIN_REQUEST; 188bb93e559Skettenis mr->nmds = nmds; 189dc8fdf3dSkettenis mr->namelen = strlen(name); 190dc8fdf3dSkettenis memcpy(mr->name, name, strlen(name)); 191dc8fdf3dSkettenis 192dc8fdf3dSkettenis ds_send_msg(&dc->lc, mr, len); 193dc8fdf3dSkettenis free(mr); 194dc8fdf3dSkettenis 195dc8fdf3dSkettenis while (mdstore_command == MDSET_BEGIN_REQUEST) 196dc8fdf3dSkettenis ds_conn_handle(dc); 197dc8fdf3dSkettenis } 198dc8fdf3dSkettenis 199dc8fdf3dSkettenis void 200dc8fdf3dSkettenis mdstore_transfer(struct ds_conn *dc, uint64_t svc_handle, const char *path, 201dc8fdf3dSkettenis uint16_t type, uint64_t offset) 202dc8fdf3dSkettenis { 203dc8fdf3dSkettenis struct mdstore_transfer_req *mr; 204dc8fdf3dSkettenis uint32_t size; 205dc8fdf3dSkettenis size_t len; 206dc8fdf3dSkettenis FILE *fp; 207dc8fdf3dSkettenis 208dc8fdf3dSkettenis fp = fopen(path, "r"); 209dc8fdf3dSkettenis if (fp == NULL) 210dc8fdf3dSkettenis err(1, "fopen"); 211dc8fdf3dSkettenis 212dc8fdf3dSkettenis fseek(fp, 0, SEEK_END); 213dc8fdf3dSkettenis size = ftell(fp); 214dc8fdf3dSkettenis fseek(fp, 0, SEEK_SET); 215dc8fdf3dSkettenis 216dc8fdf3dSkettenis len = sizeof(*mr) + size; 217dc8fdf3dSkettenis mr = xzalloc(len); 218dc8fdf3dSkettenis 219dc8fdf3dSkettenis mr->msg_type = DS_DATA; 220dc8fdf3dSkettenis mr->payload_len = len - 8; 221dc8fdf3dSkettenis mr->svc_handle = svc_handle; 222dc8fdf3dSkettenis mr->reqnum = mdstore_reqnum++; 223dc8fdf3dSkettenis mr->command = mdstore_command = MD_TRANSFER_REQUEST; 224dc8fdf3dSkettenis mr->type = type; 225dc8fdf3dSkettenis mr->size = size; 226dc8fdf3dSkettenis mr->offset = offset; 227dc8fdf3dSkettenis if (fread(&mr->md, size, 1, fp) != 1) 228dc8fdf3dSkettenis err(1, "fread"); 229dc8fdf3dSkettenis ds_send_msg(&dc->lc, mr, len); 230dc8fdf3dSkettenis free(mr); 231dc8fdf3dSkettenis 232dc8fdf3dSkettenis fclose(fp); 233dc8fdf3dSkettenis 234dc8fdf3dSkettenis while (mdstore_command == MD_TRANSFER_REQUEST) 235dc8fdf3dSkettenis ds_conn_handle(dc); 236dc8fdf3dSkettenis } 237dc8fdf3dSkettenis 238dc8fdf3dSkettenis void 239bb93e559Skettenis mdstore_end(struct ds_conn *dc, uint64_t svc_handle, const char *name, 240bb93e559Skettenis int nmds) 241dc8fdf3dSkettenis { 242dc8fdf3dSkettenis struct mdstore_begin_end_req *mr; 243dc8fdf3dSkettenis size_t len = sizeof(*mr) + strlen(name); 244dc8fdf3dSkettenis 245dc8fdf3dSkettenis mr = xzalloc(len); 246dc8fdf3dSkettenis mr->msg_type = DS_DATA; 247dc8fdf3dSkettenis mr->payload_len = len - 8; 248dc8fdf3dSkettenis mr->svc_handle = svc_handle; 249dc8fdf3dSkettenis mr->reqnum = mdstore_reqnum++; 250dc8fdf3dSkettenis mr->command = mdstore_command = MDSET_END_REQUEST; 251bb93e559Skettenis mr->nmds = nmds; 252dc8fdf3dSkettenis mr->namelen = strlen(name); 253dc8fdf3dSkettenis memcpy(mr->name, name, strlen(name)); 254dc8fdf3dSkettenis 255dc8fdf3dSkettenis ds_send_msg(&dc->lc, mr, len); 256dc8fdf3dSkettenis free(mr); 257dc8fdf3dSkettenis 258dc8fdf3dSkettenis while (mdstore_command == MDSET_END_REQUEST) 259dc8fdf3dSkettenis ds_conn_handle(dc); 2606aace0ceSkettenis } 2616aace0ceSkettenis 2626aace0ceSkettenis void 2636aace0ceSkettenis mdstore_select(struct ds_conn *dc, const char *name) 2646aace0ceSkettenis { 2656aace0ceSkettenis struct ds_conn_svc *dcs; 2666aace0ceSkettenis struct mdstore_sel_del_req *mr; 267dc8fdf3dSkettenis size_t len = sizeof(*mr) + strlen(name); 2686aace0ceSkettenis 2696aace0ceSkettenis TAILQ_FOREACH(dcs, &dc->services, link) 2706aace0ceSkettenis if (strcmp(dcs->service->ds_svc_id, "mdstore") == 0) 2716aace0ceSkettenis break; 272*abcbcc4dSdoug assert(dcs != NULL); 2736aace0ceSkettenis 2746aace0ceSkettenis mr = xzalloc(len); 2756aace0ceSkettenis mr->msg_type = DS_DATA; 2766aace0ceSkettenis mr->payload_len = len - 8; 2776aace0ceSkettenis mr->svc_handle = dcs->svc_handle; 2786aace0ceSkettenis mr->reqnum = mdstore_reqnum++; 2796aace0ceSkettenis mr->command = mdstore_command = MDSET_SELECT_REQUEST; 2806aace0ceSkettenis mr->namelen = strlen(name); 2816aace0ceSkettenis memcpy(mr->name, name, strlen(name)); 2826aace0ceSkettenis 2836aace0ceSkettenis ds_send_msg(&dc->lc, mr, len); 2846aace0ceSkettenis free(mr); 2856aace0ceSkettenis 2866aace0ceSkettenis while (mdstore_command == MDSET_SELECT_REQUEST) 2876aace0ceSkettenis ds_conn_handle(dc); 288cceaa36bSkettenis } 289dc8fdf3dSkettenis 290dc8fdf3dSkettenis void 291dc8fdf3dSkettenis mdstore_delete(struct ds_conn *dc, const char *name) 292dc8fdf3dSkettenis { 293dc8fdf3dSkettenis struct ds_conn_svc *dcs; 294dc8fdf3dSkettenis struct mdstore_sel_del_req *mr; 295dc8fdf3dSkettenis size_t len = sizeof(*mr) + strlen(name); 296dc8fdf3dSkettenis 297dc8fdf3dSkettenis TAILQ_FOREACH(dcs, &dc->services, link) 298dc8fdf3dSkettenis if (strcmp(dcs->service->ds_svc_id, "mdstore") == 0) 299dc8fdf3dSkettenis break; 300*abcbcc4dSdoug assert(dcs != NULL); 301dc8fdf3dSkettenis 302dc8fdf3dSkettenis mr = xzalloc(len); 303dc8fdf3dSkettenis mr->msg_type = DS_DATA; 304dc8fdf3dSkettenis mr->payload_len = len - 8; 305dc8fdf3dSkettenis mr->svc_handle = dcs->svc_handle; 306dc8fdf3dSkettenis mr->reqnum = mdstore_reqnum++; 307dc8fdf3dSkettenis mr->command = mdstore_command = MDSET_DELETE_REQUEST; 308dc8fdf3dSkettenis mr->namelen = strlen(name); 309dc8fdf3dSkettenis memcpy(mr->name, name, strlen(name)); 310dc8fdf3dSkettenis 311dc8fdf3dSkettenis ds_send_msg(&dc->lc, mr, len); 312dc8fdf3dSkettenis free(mr); 313dc8fdf3dSkettenis 314dc8fdf3dSkettenis while (mdstore_command == MDSET_DELETE_REQUEST) 315dc8fdf3dSkettenis ds_conn_handle(dc); 316dc8fdf3dSkettenis } 317dc8fdf3dSkettenis 318bb93e559Skettenis void frag_init(void); 319bb93e559Skettenis void add_frag_mblock(struct md_node *); 320bb93e559Skettenis void add_frag(uint64_t); 321bb93e559Skettenis void delete_frag(uint64_t); 322bb93e559Skettenis uint64_t alloc_frag(void); 323bb93e559Skettenis 324dc8fdf3dSkettenis void 325dc8fdf3dSkettenis mdstore_download(struct ds_conn *dc, const char *name) 326dc8fdf3dSkettenis { 327dc8fdf3dSkettenis struct ds_conn_svc *dcs; 328bb93e559Skettenis struct md_node *node; 329bb93e559Skettenis struct md_prop *prop; 330bb93e559Skettenis struct guest *guest; 331bb93e559Skettenis int nmds = 2; 332bb93e559Skettenis char *path; 333bb93e559Skettenis uint16_t type; 334dc8fdf3dSkettenis 335dc8fdf3dSkettenis TAILQ_FOREACH(dcs, &dc->services, link) 336dc8fdf3dSkettenis if (strcmp(dcs->service->ds_svc_id, "mdstore") == 0) 337dc8fdf3dSkettenis break; 338*abcbcc4dSdoug assert(dcs != NULL); 339dc8fdf3dSkettenis 340bb93e559Skettenis if (asprintf(&path, "%s/hv.md", name) == -1) 341bb93e559Skettenis err(1, "asprintf"); 342bb93e559Skettenis hvmd = md_read(path); 343bb93e559Skettenis free(path); 344bb93e559Skettenis 345bb93e559Skettenis if (hvmd == NULL) 346bb93e559Skettenis err(1, "%s", name); 347bb93e559Skettenis 348bb93e559Skettenis node = md_find_node(hvmd, "guests"); 34997d8cafcSkettenis TAILQ_INIT(&guest_list); 350bb93e559Skettenis TAILQ_FOREACH(prop, &node->prop_list, link) { 351bb93e559Skettenis if (prop->tag == MD_PROP_ARC && 352bb93e559Skettenis strcmp(prop->name->str, "fwd") == 0) { 353bb93e559Skettenis add_guest(prop->d.arc.node); 354bb93e559Skettenis nmds++; 355bb93e559Skettenis } 356bb93e559Skettenis } 357bb93e559Skettenis 358bb93e559Skettenis frag_init(); 359bb93e559Skettenis hv_mdpa = alloc_frag(); 360bb93e559Skettenis 361bb93e559Skettenis mdstore_begin(dc, dcs->svc_handle, name, nmds); 36297d8cafcSkettenis TAILQ_FOREACH(guest, &guest_list, link) { 363bb93e559Skettenis if (asprintf(&path, "%s/%s.md", name, guest->name) == -1) 364bb93e559Skettenis err(1, "asprintf"); 365bb93e559Skettenis type = 0; 366bb93e559Skettenis if (strcmp(guest->name, "primary") == 0) 367bb93e559Skettenis type = MDSTORE_CTL_DOM_MD_TYPE; 368bb93e559Skettenis mdstore_transfer(dc, dcs->svc_handle, path, type, guest->mdpa); 369bb93e559Skettenis free(path); 370bb93e559Skettenis } 371bb93e559Skettenis if (asprintf(&path, "%s/hv.md", name) == -1) 372bb93e559Skettenis err(1, "asprintf"); 373bb93e559Skettenis mdstore_transfer(dc, dcs->svc_handle, path, 374bb93e559Skettenis MDSTORE_HV_MD_TYPE, hv_mdpa); 375bb93e559Skettenis free(path); 376bb93e559Skettenis if (asprintf(&path, "%s/pri", name) == -1) 377bb93e559Skettenis err(1, "asprintf"); 378bb93e559Skettenis mdstore_transfer(dc, dcs->svc_handle, path, 379dc8fdf3dSkettenis MDSTORE_PRI_TYPE, 0); 380bb93e559Skettenis free(path); 381bb93e559Skettenis mdstore_end(dc, dcs->svc_handle, name, nmds); 382bb93e559Skettenis } 383bb93e559Skettenis 384bb93e559Skettenis struct frag { 385bb93e559Skettenis TAILQ_ENTRY(frag) link; 386bb93e559Skettenis uint64_t base; 387bb93e559Skettenis }; 388bb93e559Skettenis 389bb93e559Skettenis TAILQ_HEAD(frag_head, frag) free_frags; 390bb93e559Skettenis 391bb93e559Skettenis uint64_t fragsize; 392bb93e559Skettenis 393bb93e559Skettenis void 394bb93e559Skettenis frag_init(void) 395bb93e559Skettenis { 396bb93e559Skettenis struct md_node *node; 397bb93e559Skettenis struct md_prop *prop; 398bb93e559Skettenis 399bb93e559Skettenis node = md_find_node(hvmd, "frag_space"); 400bb93e559Skettenis md_get_prop_val(hvmd, node, "fragsize", &fragsize); 401bb93e559Skettenis TAILQ_INIT(&free_frags); 402bb93e559Skettenis TAILQ_FOREACH(prop, &node->prop_list, link) { 403bb93e559Skettenis if (prop->tag == MD_PROP_ARC && 404bb93e559Skettenis strcmp(prop->name->str, "fwd") == 0) 405bb93e559Skettenis add_frag_mblock(prop->d.arc.node); 406bb93e559Skettenis } 407bb93e559Skettenis } 408bb93e559Skettenis 409bb93e559Skettenis void 410bb93e559Skettenis add_frag_mblock(struct md_node *node) 411bb93e559Skettenis { 412bb93e559Skettenis uint64_t base, size; 413bb93e559Skettenis struct guest *guest; 414bb93e559Skettenis 415bb93e559Skettenis md_get_prop_val(hvmd, node, "base", &base); 416bb93e559Skettenis md_get_prop_val(hvmd, node, "size", &size); 417bb93e559Skettenis while (size > fragsize) { 418bb93e559Skettenis add_frag(base); 419bb93e559Skettenis size -= fragsize; 420bb93e559Skettenis base += fragsize; 421bb93e559Skettenis } 422bb93e559Skettenis 423bb93e559Skettenis delete_frag(hv_mdpa); 42497d8cafcSkettenis TAILQ_FOREACH(guest, &guest_list, link) 425bb93e559Skettenis delete_frag(guest->mdpa); 426bb93e559Skettenis } 427bb93e559Skettenis 428bb93e559Skettenis void 429bb93e559Skettenis add_frag(uint64_t base) 430bb93e559Skettenis { 431bb93e559Skettenis struct frag *frag; 432bb93e559Skettenis 433bb93e559Skettenis frag = xmalloc(sizeof(*frag)); 434bb93e559Skettenis frag->base = base; 435bb93e559Skettenis TAILQ_INSERT_TAIL(&free_frags, frag, link); 436bb93e559Skettenis } 437bb93e559Skettenis 438bb93e559Skettenis void 439bb93e559Skettenis delete_frag(uint64_t base) 440bb93e559Skettenis { 441bb93e559Skettenis struct frag *frag; 442bb93e559Skettenis struct frag *tmp; 443bb93e559Skettenis 444bb93e559Skettenis TAILQ_FOREACH_SAFE(frag, &free_frags, link, tmp) { 445bb93e559Skettenis if (frag->base == base) { 446bb93e559Skettenis TAILQ_REMOVE(&free_frags, frag, link); 447bb93e559Skettenis free(frag); 448bb93e559Skettenis } 449bb93e559Skettenis } 450bb93e559Skettenis } 451bb93e559Skettenis 452bb93e559Skettenis uint64_t 453bb93e559Skettenis alloc_frag(void) 454bb93e559Skettenis { 455bb93e559Skettenis struct frag *frag; 456bb93e559Skettenis uint64_t base; 457bb93e559Skettenis 458bb93e559Skettenis frag = TAILQ_FIRST(&free_frags); 459bb93e559Skettenis if (frag == NULL) 460bb93e559Skettenis return -1; 461bb93e559Skettenis 462bb93e559Skettenis TAILQ_REMOVE(&free_frags, frag, link); 463bb93e559Skettenis base = frag->base; 464bb93e559Skettenis free(frag); 465bb93e559Skettenis 466bb93e559Skettenis return base; 467dc8fdf3dSkettenis } 468