1*d73a4c4fSkn /* $OpenBSD: mdstore.c,v 1.12 2019/11/28 18:40:42 kn 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" 29*d73a4c4fSkn #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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 545bb93e559Skettenis TAILQ_HEAD(frag_head, frag) free_frags; 546bb93e559Skettenis 547bb93e559Skettenis uint64_t fragsize; 548bb93e559Skettenis 549bb93e559Skettenis 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"); 556bb93e559Skettenis md_get_prop_val(hvmd, node, "fragsize", &fragsize); 557bb93e559Skettenis TAILQ_INIT(&free_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 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); 573bb93e559Skettenis while (size > fragsize) { 574bb93e559Skettenis add_frag(base); 575bb93e559Skettenis size -= fragsize; 576bb93e559Skettenis base += fragsize; 577bb93e559Skettenis } 578bb93e559Skettenis 579bb93e559Skettenis delete_frag(hv_mdpa); 58097d8cafcSkettenis TAILQ_FOREACH(guest, &guest_list, link) 581bb93e559Skettenis delete_frag(guest->mdpa); 582bb93e559Skettenis } 583bb93e559Skettenis 584bb93e559Skettenis void 585bb93e559Skettenis add_frag(uint64_t base) 586bb93e559Skettenis { 587bb93e559Skettenis struct frag *frag; 588bb93e559Skettenis 589bb93e559Skettenis frag = xmalloc(sizeof(*frag)); 590bb93e559Skettenis frag->base = base; 591bb93e559Skettenis TAILQ_INSERT_TAIL(&free_frags, frag, link); 592bb93e559Skettenis } 593bb93e559Skettenis 594bb93e559Skettenis void 595bb93e559Skettenis delete_frag(uint64_t base) 596bb93e559Skettenis { 597bb93e559Skettenis struct frag *frag; 598bb93e559Skettenis struct frag *tmp; 599bb93e559Skettenis 600bb93e559Skettenis TAILQ_FOREACH_SAFE(frag, &free_frags, link, tmp) { 601bb93e559Skettenis if (frag->base == base) { 602bb93e559Skettenis TAILQ_REMOVE(&free_frags, frag, link); 603bb93e559Skettenis free(frag); 604bb93e559Skettenis } 605bb93e559Skettenis } 606bb93e559Skettenis } 607bb93e559Skettenis 608bb93e559Skettenis uint64_t 609bb93e559Skettenis alloc_frag(void) 610bb93e559Skettenis { 611bb93e559Skettenis struct frag *frag; 612bb93e559Skettenis uint64_t base; 613bb93e559Skettenis 614bb93e559Skettenis frag = TAILQ_FIRST(&free_frags); 615bb93e559Skettenis if (frag == NULL) 616bb93e559Skettenis return -1; 617bb93e559Skettenis 618bb93e559Skettenis TAILQ_REMOVE(&free_frags, frag, link); 619bb93e559Skettenis base = frag->base; 620bb93e559Skettenis free(frag); 621bb93e559Skettenis 622bb93e559Skettenis return base; 623dc8fdf3dSkettenis } 624