1*97d8cafcSkettenis /* $OpenBSD: mdstore.c,v 1.5 2012/11/24 11:50:45 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> 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) { 146cceaa36bSkettenis DPRINTF(("Unexpected result 0x%x\n", mr->result)); 147cceaa36bSkettenis return; 148cceaa36bSkettenis } 149cceaa36bSkettenis 1506aace0ceSkettenis switch (mdstore_command) { 1516aace0ceSkettenis case MDSET_LIST_REQUEST: 1526aace0ceSkettenis for (idx = 0, len = 0; len < mr->payload_len - 24; idx++) { 153cceaa36bSkettenis set = xmalloc(sizeof(*set)); 154cceaa36bSkettenis set->name = xstrdup(&mr->sets[len]); 155cceaa36bSkettenis set->booted_set = (idx == mr->booted_set); 156cceaa36bSkettenis set->boot_set = (idx == mr->boot_set); 157cceaa36bSkettenis TAILQ_INSERT_TAIL(&mdstore_sets, set, link); 158cceaa36bSkettenis len += strlen(&mr->sets[len]) + 1; 159cceaa36bSkettenis } 1606aace0ceSkettenis break; 1616aace0ceSkettenis } 162dc8fdf3dSkettenis 163dc8fdf3dSkettenis mdstore_command = 0; 164dc8fdf3dSkettenis } 165dc8fdf3dSkettenis 166dc8fdf3dSkettenis void 167bb93e559Skettenis mdstore_begin(struct ds_conn *dc, uint64_t svc_handle, const char *name, 168bb93e559Skettenis int nmds) 169dc8fdf3dSkettenis { 170dc8fdf3dSkettenis struct mdstore_begin_end_req *mr; 171dc8fdf3dSkettenis size_t len = sizeof(*mr) + strlen(name); 172dc8fdf3dSkettenis 173dc8fdf3dSkettenis mr = xzalloc(len); 174dc8fdf3dSkettenis mr->msg_type = DS_DATA; 175dc8fdf3dSkettenis mr->payload_len = len - 8; 176dc8fdf3dSkettenis mr->svc_handle = svc_handle; 177dc8fdf3dSkettenis mr->reqnum = mdstore_reqnum++; 178dc8fdf3dSkettenis mr->command = mdstore_command = MDSET_BEGIN_REQUEST; 179bb93e559Skettenis mr->nmds = nmds; 180dc8fdf3dSkettenis mr->namelen = strlen(name); 181dc8fdf3dSkettenis memcpy(mr->name, name, strlen(name)); 182dc8fdf3dSkettenis 183dc8fdf3dSkettenis ds_send_msg(&dc->lc, mr, len); 184dc8fdf3dSkettenis free(mr); 185dc8fdf3dSkettenis 186dc8fdf3dSkettenis while (mdstore_command == MDSET_BEGIN_REQUEST) 187dc8fdf3dSkettenis ds_conn_handle(dc); 188dc8fdf3dSkettenis } 189dc8fdf3dSkettenis 190dc8fdf3dSkettenis void 191dc8fdf3dSkettenis mdstore_transfer(struct ds_conn *dc, uint64_t svc_handle, const char *path, 192dc8fdf3dSkettenis uint16_t type, uint64_t offset) 193dc8fdf3dSkettenis { 194dc8fdf3dSkettenis struct mdstore_transfer_req *mr; 195dc8fdf3dSkettenis uint32_t size; 196dc8fdf3dSkettenis size_t len; 197dc8fdf3dSkettenis FILE *fp; 198dc8fdf3dSkettenis 199dc8fdf3dSkettenis fp = fopen(path, "r"); 200dc8fdf3dSkettenis if (fp == NULL) 201dc8fdf3dSkettenis err(1, "fopen"); 202dc8fdf3dSkettenis 203dc8fdf3dSkettenis fseek(fp, 0, SEEK_END); 204dc8fdf3dSkettenis size = ftell(fp); 205dc8fdf3dSkettenis fseek(fp, 0, SEEK_SET); 206dc8fdf3dSkettenis 207dc8fdf3dSkettenis len = sizeof(*mr) + size; 208dc8fdf3dSkettenis mr = xzalloc(len); 209dc8fdf3dSkettenis 210dc8fdf3dSkettenis mr->msg_type = DS_DATA; 211dc8fdf3dSkettenis mr->payload_len = len - 8; 212dc8fdf3dSkettenis mr->svc_handle = svc_handle; 213dc8fdf3dSkettenis mr->reqnum = mdstore_reqnum++; 214dc8fdf3dSkettenis mr->command = mdstore_command = MD_TRANSFER_REQUEST; 215dc8fdf3dSkettenis mr->type = type; 216dc8fdf3dSkettenis mr->size = size; 217dc8fdf3dSkettenis mr->offset = offset; 218dc8fdf3dSkettenis if (fread(&mr->md, size, 1, fp) != 1) 219dc8fdf3dSkettenis err(1, "fread"); 220dc8fdf3dSkettenis ds_send_msg(&dc->lc, mr, len); 221dc8fdf3dSkettenis free(mr); 222dc8fdf3dSkettenis 223dc8fdf3dSkettenis fclose(fp); 224dc8fdf3dSkettenis 225dc8fdf3dSkettenis while (mdstore_command == MD_TRANSFER_REQUEST) 226dc8fdf3dSkettenis ds_conn_handle(dc); 227dc8fdf3dSkettenis } 228dc8fdf3dSkettenis 229dc8fdf3dSkettenis void 230bb93e559Skettenis mdstore_end(struct ds_conn *dc, uint64_t svc_handle, const char *name, 231bb93e559Skettenis int nmds) 232dc8fdf3dSkettenis { 233dc8fdf3dSkettenis struct mdstore_begin_end_req *mr; 234dc8fdf3dSkettenis size_t len = sizeof(*mr) + strlen(name); 235dc8fdf3dSkettenis 236dc8fdf3dSkettenis mr = xzalloc(len); 237dc8fdf3dSkettenis mr->msg_type = DS_DATA; 238dc8fdf3dSkettenis mr->payload_len = len - 8; 239dc8fdf3dSkettenis mr->svc_handle = svc_handle; 240dc8fdf3dSkettenis mr->reqnum = mdstore_reqnum++; 241dc8fdf3dSkettenis mr->command = mdstore_command = MDSET_END_REQUEST; 242bb93e559Skettenis mr->nmds = nmds; 243dc8fdf3dSkettenis mr->namelen = strlen(name); 244dc8fdf3dSkettenis memcpy(mr->name, name, strlen(name)); 245dc8fdf3dSkettenis 246dc8fdf3dSkettenis ds_send_msg(&dc->lc, mr, len); 247dc8fdf3dSkettenis free(mr); 248dc8fdf3dSkettenis 249dc8fdf3dSkettenis while (mdstore_command == MDSET_END_REQUEST) 250dc8fdf3dSkettenis ds_conn_handle(dc); 2516aace0ceSkettenis } 2526aace0ceSkettenis 2536aace0ceSkettenis void 2546aace0ceSkettenis mdstore_select(struct ds_conn *dc, const char *name) 2556aace0ceSkettenis { 2566aace0ceSkettenis struct ds_conn_svc *dcs; 2576aace0ceSkettenis struct mdstore_sel_del_req *mr; 258dc8fdf3dSkettenis size_t len = sizeof(*mr) + strlen(name); 2596aace0ceSkettenis 2606aace0ceSkettenis TAILQ_FOREACH(dcs, &dc->services, link) 2616aace0ceSkettenis if (strcmp(dcs->service->ds_svc_id, "mdstore") == 0) 2626aace0ceSkettenis break; 2636aace0ceSkettenis assert(dcs != TAILQ_END(&dc->services)); 2646aace0ceSkettenis 2656aace0ceSkettenis mr = xzalloc(len); 2666aace0ceSkettenis mr->msg_type = DS_DATA; 2676aace0ceSkettenis mr->payload_len = len - 8; 2686aace0ceSkettenis mr->svc_handle = dcs->svc_handle; 2696aace0ceSkettenis mr->reqnum = mdstore_reqnum++; 2706aace0ceSkettenis mr->command = mdstore_command = MDSET_SELECT_REQUEST; 2716aace0ceSkettenis mr->namelen = strlen(name); 2726aace0ceSkettenis memcpy(mr->name, name, strlen(name)); 2736aace0ceSkettenis 2746aace0ceSkettenis ds_send_msg(&dc->lc, mr, len); 2756aace0ceSkettenis free(mr); 2766aace0ceSkettenis 2776aace0ceSkettenis while (mdstore_command == MDSET_SELECT_REQUEST) 2786aace0ceSkettenis ds_conn_handle(dc); 279cceaa36bSkettenis } 280dc8fdf3dSkettenis 281dc8fdf3dSkettenis void 282dc8fdf3dSkettenis mdstore_delete(struct ds_conn *dc, const char *name) 283dc8fdf3dSkettenis { 284dc8fdf3dSkettenis struct ds_conn_svc *dcs; 285dc8fdf3dSkettenis struct mdstore_sel_del_req *mr; 286dc8fdf3dSkettenis size_t len = sizeof(*mr) + strlen(name); 287dc8fdf3dSkettenis 288dc8fdf3dSkettenis TAILQ_FOREACH(dcs, &dc->services, link) 289dc8fdf3dSkettenis if (strcmp(dcs->service->ds_svc_id, "mdstore") == 0) 290dc8fdf3dSkettenis break; 291dc8fdf3dSkettenis assert(dcs != TAILQ_END(&dc->services)); 292dc8fdf3dSkettenis 293dc8fdf3dSkettenis mr = xzalloc(len); 294dc8fdf3dSkettenis mr->msg_type = DS_DATA; 295dc8fdf3dSkettenis mr->payload_len = len - 8; 296dc8fdf3dSkettenis mr->svc_handle = dcs->svc_handle; 297dc8fdf3dSkettenis mr->reqnum = mdstore_reqnum++; 298dc8fdf3dSkettenis mr->command = mdstore_command = MDSET_DELETE_REQUEST; 299dc8fdf3dSkettenis mr->namelen = strlen(name); 300dc8fdf3dSkettenis memcpy(mr->name, name, strlen(name)); 301dc8fdf3dSkettenis 302dc8fdf3dSkettenis ds_send_msg(&dc->lc, mr, len); 303dc8fdf3dSkettenis free(mr); 304dc8fdf3dSkettenis 305dc8fdf3dSkettenis while (mdstore_command == MDSET_DELETE_REQUEST) 306dc8fdf3dSkettenis ds_conn_handle(dc); 307dc8fdf3dSkettenis } 308dc8fdf3dSkettenis 309bb93e559Skettenis void frag_init(void); 310bb93e559Skettenis void add_frag_mblock(struct md_node *); 311bb93e559Skettenis void add_frag(uint64_t); 312bb93e559Skettenis void delete_frag(uint64_t); 313bb93e559Skettenis uint64_t alloc_frag(void); 314bb93e559Skettenis 315dc8fdf3dSkettenis void 316dc8fdf3dSkettenis mdstore_download(struct ds_conn *dc, const char *name) 317dc8fdf3dSkettenis { 318dc8fdf3dSkettenis struct ds_conn_svc *dcs; 319bb93e559Skettenis struct md_node *node; 320bb93e559Skettenis struct md_prop *prop; 321bb93e559Skettenis struct guest *guest; 322bb93e559Skettenis int nmds = 2; 323bb93e559Skettenis char *path; 324bb93e559Skettenis uint16_t type; 325dc8fdf3dSkettenis 326dc8fdf3dSkettenis TAILQ_FOREACH(dcs, &dc->services, link) 327dc8fdf3dSkettenis if (strcmp(dcs->service->ds_svc_id, "mdstore") == 0) 328dc8fdf3dSkettenis break; 329dc8fdf3dSkettenis assert(dcs != TAILQ_END(&dc->services)); 330dc8fdf3dSkettenis 331bb93e559Skettenis if (asprintf(&path, "%s/hv.md", name) == -1) 332bb93e559Skettenis err(1, "asprintf"); 333bb93e559Skettenis hvmd = md_read(path); 334bb93e559Skettenis free(path); 335bb93e559Skettenis 336bb93e559Skettenis if (hvmd == NULL) 337bb93e559Skettenis err(1, "%s", name); 338bb93e559Skettenis 339bb93e559Skettenis node = md_find_node(hvmd, "guests"); 340*97d8cafcSkettenis TAILQ_INIT(&guest_list); 341bb93e559Skettenis TAILQ_FOREACH(prop, &node->prop_list, link) { 342bb93e559Skettenis if (prop->tag == MD_PROP_ARC && 343bb93e559Skettenis strcmp(prop->name->str, "fwd") == 0) { 344bb93e559Skettenis add_guest(prop->d.arc.node); 345bb93e559Skettenis nmds++; 346bb93e559Skettenis } 347bb93e559Skettenis } 348bb93e559Skettenis 349bb93e559Skettenis frag_init(); 350bb93e559Skettenis hv_mdpa = alloc_frag(); 351bb93e559Skettenis 352bb93e559Skettenis mdstore_begin(dc, dcs->svc_handle, name, nmds); 353*97d8cafcSkettenis TAILQ_FOREACH(guest, &guest_list, link) { 354bb93e559Skettenis if (asprintf(&path, "%s/%s.md", name, guest->name) == -1) 355bb93e559Skettenis err(1, "asprintf"); 356bb93e559Skettenis type = 0; 357bb93e559Skettenis if (strcmp(guest->name, "primary") == 0) 358bb93e559Skettenis type = MDSTORE_CTL_DOM_MD_TYPE; 359bb93e559Skettenis mdstore_transfer(dc, dcs->svc_handle, path, type, guest->mdpa); 360bb93e559Skettenis free(path); 361bb93e559Skettenis } 362bb93e559Skettenis if (asprintf(&path, "%s/hv.md", name) == -1) 363bb93e559Skettenis err(1, "asprintf"); 364bb93e559Skettenis mdstore_transfer(dc, dcs->svc_handle, path, 365bb93e559Skettenis MDSTORE_HV_MD_TYPE, hv_mdpa); 366bb93e559Skettenis free(path); 367bb93e559Skettenis if (asprintf(&path, "%s/pri", name) == -1) 368bb93e559Skettenis err(1, "asprintf"); 369bb93e559Skettenis mdstore_transfer(dc, dcs->svc_handle, path, 370dc8fdf3dSkettenis MDSTORE_PRI_TYPE, 0); 371bb93e559Skettenis free(path); 372bb93e559Skettenis mdstore_end(dc, dcs->svc_handle, name, nmds); 373bb93e559Skettenis } 374bb93e559Skettenis 375bb93e559Skettenis struct frag { 376bb93e559Skettenis TAILQ_ENTRY(frag) link; 377bb93e559Skettenis uint64_t base; 378bb93e559Skettenis }; 379bb93e559Skettenis 380bb93e559Skettenis TAILQ_HEAD(frag_head, frag) free_frags; 381bb93e559Skettenis 382bb93e559Skettenis uint64_t fragsize; 383bb93e559Skettenis 384bb93e559Skettenis void 385bb93e559Skettenis frag_init(void) 386bb93e559Skettenis { 387bb93e559Skettenis struct md_node *node; 388bb93e559Skettenis struct md_prop *prop; 389bb93e559Skettenis 390bb93e559Skettenis node = md_find_node(hvmd, "frag_space"); 391bb93e559Skettenis md_get_prop_val(hvmd, node, "fragsize", &fragsize); 392bb93e559Skettenis TAILQ_INIT(&free_frags); 393bb93e559Skettenis TAILQ_FOREACH(prop, &node->prop_list, link) { 394bb93e559Skettenis if (prop->tag == MD_PROP_ARC && 395bb93e559Skettenis strcmp(prop->name->str, "fwd") == 0) 396bb93e559Skettenis add_frag_mblock(prop->d.arc.node); 397bb93e559Skettenis } 398bb93e559Skettenis } 399bb93e559Skettenis 400bb93e559Skettenis void 401bb93e559Skettenis add_frag_mblock(struct md_node *node) 402bb93e559Skettenis { 403bb93e559Skettenis uint64_t base, size; 404bb93e559Skettenis struct guest *guest; 405bb93e559Skettenis 406bb93e559Skettenis md_get_prop_val(hvmd, node, "base", &base); 407bb93e559Skettenis md_get_prop_val(hvmd, node, "size", &size); 408bb93e559Skettenis while (size > fragsize) { 409bb93e559Skettenis add_frag(base); 410bb93e559Skettenis size -= fragsize; 411bb93e559Skettenis base += fragsize; 412bb93e559Skettenis } 413bb93e559Skettenis 414bb93e559Skettenis delete_frag(hv_mdpa); 415*97d8cafcSkettenis TAILQ_FOREACH(guest, &guest_list, link) 416bb93e559Skettenis delete_frag(guest->mdpa); 417bb93e559Skettenis } 418bb93e559Skettenis 419bb93e559Skettenis void 420bb93e559Skettenis add_frag(uint64_t base) 421bb93e559Skettenis { 422bb93e559Skettenis struct frag *frag; 423bb93e559Skettenis 424bb93e559Skettenis frag = xmalloc(sizeof(*frag)); 425bb93e559Skettenis frag->base = base; 426bb93e559Skettenis TAILQ_INSERT_TAIL(&free_frags, frag, link); 427bb93e559Skettenis } 428bb93e559Skettenis 429bb93e559Skettenis void 430bb93e559Skettenis delete_frag(uint64_t base) 431bb93e559Skettenis { 432bb93e559Skettenis struct frag *frag; 433bb93e559Skettenis struct frag *tmp; 434bb93e559Skettenis 435bb93e559Skettenis TAILQ_FOREACH_SAFE(frag, &free_frags, link, tmp) { 436bb93e559Skettenis if (frag->base == base) { 437bb93e559Skettenis TAILQ_REMOVE(&free_frags, frag, link); 438bb93e559Skettenis free(frag); 439bb93e559Skettenis } 440bb93e559Skettenis } 441bb93e559Skettenis } 442bb93e559Skettenis 443bb93e559Skettenis uint64_t 444bb93e559Skettenis alloc_frag(void) 445bb93e559Skettenis { 446bb93e559Skettenis struct frag *frag; 447bb93e559Skettenis uint64_t base; 448bb93e559Skettenis 449bb93e559Skettenis frag = TAILQ_FIRST(&free_frags); 450bb93e559Skettenis if (frag == NULL) 451bb93e559Skettenis return -1; 452bb93e559Skettenis 453bb93e559Skettenis TAILQ_REMOVE(&free_frags, frag, link); 454bb93e559Skettenis base = frag->base; 455bb93e559Skettenis free(frag); 456bb93e559Skettenis 457bb93e559Skettenis return base; 458dc8fdf3dSkettenis } 459