static int vhd_index_allocate_cache(vhd_index_t *index) { void *buf; int i, err; size_t size; size = vhd_bytes_padded(index->vhdi.spb * sizeof(vhdi_entry_t)); for (i = 0; i < VHD_INDEX_CACHE_SIZE; i++) { err = posix_memalign(&buf, VHD_SECTOR_SIZE, size); if (err) goto fail; memset(buf, 0, size); index->cache_list[i].vhdi_block.table = (vhdi_entry_t *)buf; index->cache_list[i].vhdi_block.entries = index->vhdi.spb; index->cache_list[i].table_size = size; } return 0; fail: for (i = 0; i < VHD_INDEX_CACHE_SIZE; i++) { free(index->cache_list[i].vhdi_block.table); index->cache_list[i].vhdi_block.table = NULL; } return -ENOMEM; }
static int vhd_journal_read_batmap_header(vhd_journal_t *j, vhd_batmap_t *batmap) { int err; void *buf; size_t size; vhd_journal_entry_t entry; size = vhd_bytes_padded(sizeof(struct dd_batmap_hdr)); err = vhd_journal_read_entry(j, &entry); if (err) return err; if (entry.type != VHD_JOURNAL_ENTRY_TYPE_BATMAP_H) return -EINVAL; if (entry.size != size) return -EINVAL; err = posix_memalign(&buf, VHD_SECTOR_SIZE, size); if (err) return err; err = vhd_journal_read(j, buf, entry.size); if (err) { free(buf); return err; } memcpy(&batmap->header, buf, sizeof(batmap->header)); vhd_batmap_header_in(batmap); return vhd_validate_batmap_header(batmap); }
static int vhd_journal_add_bat(vhd_journal_t *j) { int err; off64_t off; size_t size; vhd_bat_t bat; vhd_context_t *vhd; vhd = &j->vhd; err = vhd_get_header(vhd); if (err) return err; err = vhd_read_bat(vhd, &bat); if (err) return err; off = vhd->header.table_offset; size = vhd_bytes_padded(bat.entries * sizeof(uint32_t)); vhd_bat_out(&bat); err = vhd_journal_update(j, off, (char *)bat.bat, size, VHD_JOURNAL_ENTRY_TYPE_BAT); free(bat.bat); return err; }
int get_header(server *srv, chunkqueue *cq, vhd_state_t *state, off_t *curr_off) { int err; vhd_context_t *vhd; off_t off; uint32_t vhd_blks; vhd = &state->vhd; off = vhd->footer.data_offset; err = fill(srv, cq, &vhd->header, sizeof(vhd_header_t), off, curr_off); if (err) return err; if (*curr_off < off + sizeof(vhd_header_t)) return 0; DEBUGLOG("s", "Header all in"); vhd_header_in(&vhd->header); err = vhd_validate_header(&vhd->header); if (err) { LOG("sd", "ERROR: VHD header invalid:", err); return err; } vhd->spb = vhd->header.block_size >> VHD_SECTOR_SHIFT; vhd->bm_secs = secs_round_up_no_zero(vhd->spb >> 3); vhd_blks = vhd->footer.curr_size >> VHD_BLOCK_SHIFT; vhd->bat.spb = vhd->header.block_size >> VHD_SECTOR_SHIFT; vhd->bat.entries = vhd_blks; LOG("sOsDsd", "VHD virt size:", vhd->footer.curr_size, "; blocks:", vhd_blks, "; max BAT size:", vhd->header.max_bat_size); if (vhd->header.max_bat_size < vhd_blks) { LOG("s", "ERROR: BAT smaller than VHD size!"); return -EINVAL; } state->bat_buf_size = vhd_bytes_padded(vhd_blks * sizeof(uint32_t)); err = posix_memalign((void **)&vhd->bat.bat, VHD_SECTOR_SIZE, state->bat_buf_size); if (err) { LOG("sd", "ERROR: failed to allocate BAT buffer:", err); return err; } state->curr_bitmap = malloc(vhd->bm_secs << VHD_SECTOR_SHIFT); if (!state->curr_bitmap) { LOG("sd", "ERROR: failed to allocate bitmap buffer!"); return -ENOMEM; } return 0; }
static int vhd_journal_read_bat(vhd_journal_t *j, vhd_bat_t *bat) { int err; size_t size; vhd_context_t *vhd; vhd_journal_entry_t entry; void *_bat; vhd = &j->vhd; size = vhd_bytes_padded(vhd->header.max_bat_size * sizeof(uint32_t)); err = vhd_journal_read_entry(j, &entry); if (err) return err; if (entry.type != VHD_JOURNAL_ENTRY_TYPE_BAT) return -EINVAL; if (entry.size != size) return -EINVAL; if (entry.offset != vhd->header.table_offset) return -EINVAL; err = posix_memalign(&_bat, VHD_SECTOR_SIZE, size); if (err) return -err; bat->bat = _bat; err = vhd_journal_read(j, bat->bat, entry.size); if (err) goto fail; bat->spb = vhd->header.block_size >> VHD_SECTOR_SHIFT; bat->entries = vhd->header.max_bat_size; vhd_bat_in(bat); return 0; fail: free(bat->bat); bat->bat = NULL; return err; }
static int vhd_journal_add_batmap(vhd_journal_t *j) { int err; off64_t off; size_t size; vhd_context_t *vhd; vhd_batmap_t batmap; vhd = &j->vhd; err = vhd_batmap_header_offset(vhd, &off); if (err) return err; err = vhd_read_batmap(vhd, &batmap); if (err) return err; size = vhd_bytes_padded(sizeof(struct dd_batmap_hdr)); vhd_batmap_header_out(&batmap); err = vhd_journal_update(j, off, (char *)&batmap.header, size, VHD_JOURNAL_ENTRY_TYPE_BATMAP_H); if (err) goto out; vhd_batmap_header_in(&batmap); off = batmap.header.batmap_offset; size = vhd_sectors_to_bytes(batmap.header.batmap_size); err = vhd_journal_update(j, off, batmap.map, size, VHD_JOURNAL_ENTRY_TYPE_BATMAP_M); out: free(batmap.map); return err; }