void tapdisk_vbd_close_vdi(td_vbd_t *vbd) { int err; err = vbd_stats_destroy(vbd); if (err) { EPRINTF("failed to destroy RRD stats file: %s (error ignored)\n", strerror(-err)); } tapdisk_image_close_chain(&vbd->images); if (vbd->secondary && vbd->secondary_mode != TD_VBD_SECONDARY_MIRROR) { tapdisk_image_close(vbd->secondary); vbd->secondary = NULL; } if (vbd->retired) { tapdisk_image_close(vbd->retired); vbd->retired = NULL; } td_flag_set(vbd->state, TD_VBD_CLOSED); }
static void vhd_index_complete_meta_read(void *arg, struct tiocb *tiocb, int err) { int i; uint32_t blk; td_request_t treq; vhd_index_t *index; vhd_index_block_t *block; vhd_index_request_t *req, *r, *tmp; req = (vhd_index_request_t *)arg; index = req->index; blk = req->treq.sec / index->vhdi.spb; block = vhd_index_get_block(index, blk); ASSERT(block && td_flag_test(block->state, VHD_INDEX_BLOCK_READ_PENDING)); td_flag_clear(block->state, VHD_INDEX_BLOCK_READ_PENDING); if (err) { memset(block->vhdi_block.table, 0, block->table_size); vhd_index_block_for_each_request(block, r, tmp) vhd_index_signal_completion(index, r, err); return; } for (i = 0; i < block->vhdi_block.entries; i++) vhdi_entry_in(block->vhdi_block.table + i); td_flag_set(block->state, VHD_INDEX_BLOCK_VALID); vhd_index_block_for_each_request(block, r, tmp) { treq = r->treq; vhd_index_free_request(index, r); vhd_index_queue_read(index->driver, treq); }
static int vhd_index_schedule_meta_read(vhd_index_t *index, uint32_t blk) { int err; off64_t offset; vhd_index_block_t *block; vhd_index_request_t *req; ASSERT(index->bat.table[blk] != DD_BLK_UNUSED); block = vhd_index_get_block(index, blk); if (!block) { err = vhd_index_install_block(index, &block, blk); if (err) return err; } offset = vhd_sectors_to_bytes(index->bat.table[blk]); req = &block->req; req->index = index; req->treq.sec = blk * index->vhdi.spb; req->treq.secs = block->table_size >> VHD_SECTOR_SHIFT; td_prep_read(&req->tiocb, index->vhdi.fd, (char *)block->vhdi_block.table, block->table_size, offset, vhd_index_complete_meta_read, req); td_queue_tiocb(index->driver, &req->tiocb); td_flag_set(block->state, VHD_INDEX_BLOCK_READ_PENDING); return 0; }
void tapdisk_vbd_close_vdi(td_vbd_t *vbd) { tapdisk_image_close_chain(&vbd->images); if (vbd->secondary && vbd->secondary_mode != TD_VBD_SECONDARY_MIRROR) { tapdisk_image_close(vbd->secondary); vbd->secondary = NULL; } if (vbd->retired) { tapdisk_image_close(vbd->retired); vbd->retired = NULL; } td_flag_set(vbd->state, TD_VBD_CLOSED); }
int __td_open(td_image_t *image, td_disk_info_t *info) { int err; td_driver_t *driver; driver = image->driver; if (!driver) { driver = tapdisk_driver_allocate(image->type, image->name, image->flags); if (!driver) return -ENOMEM; if (info) /* pre-seed driver->info for virtual drivers */ driver->info = *info; } if (!td_flag_test(driver->state, TD_DRIVER_OPEN)) { err = driver->ops->td_open(driver, image->name, image->flags); if (err) { if (!image->driver) tapdisk_driver_free(driver); return err; } td_flag_set(driver->state, TD_DRIVER_OPEN); DPRINTF("opened image %s (%d users, state: 0x%08x, type: %d, %s)\n", driver->name, driver->refcnt + 1, driver->state, driver->type, td_flag_test(image->flags, TD_OPEN_RDONLY) ? "ro" : "rw"); } image->driver = driver; image->info = driver->info; driver->refcnt++; return 0; }
/* * TODO provide ring stats in raw format (the same way I/O stats are provided). * xen-ringwatch will have to be modified accordingly. */ static int tapdisk_xenblkif_stats_create(struct td_xenblkif *blkif) { int err = 0, len; char *_path = NULL; len = asprintf(&blkif->xenvbd_stats.root, "/dev/shm/vbd3-%d-%d", blkif->domid, blkif->devid); if (unlikely(len == -1)) { err = errno; blkif->xenvbd_stats.root = NULL; goto out; } err = mkdir(blkif->xenvbd_stats.root, S_IRUSR | S_IWUSR); if (unlikely(err)) { err = errno; if (err != EEXIST) { EPRINTF("failed to create %s: %s\n", blkif->xenvbd_stats.root, strerror(err)); goto out; } err = 0; } len = asprintf(&blkif->xenvbd_stats.io_ring.path, "%s/io_ring~", blkif->xenvbd_stats.root); if (unlikely(len == -1)) { err = errno; blkif->xenvbd_stats.io_ring.path = NULL; goto out; } blkif->xenvbd_stats.io_ring.size = PAGE_SIZE; err = shm_create(&blkif->xenvbd_stats.io_ring); if (unlikely(err)) { err = errno; EPRINTF("failed to create shm ring stats file: %s\n", strerror(err)); goto out; } err = asprintf(&blkif->xenvbd_stats.stats.path, "%s/statistics", blkif->xenvbd_stats.root); if (unlikely(err == -1)) { err = errno; blkif->xenvbd_stats.stats.path = NULL; goto out; } blkif->xenvbd_stats.stats.size = PAGE_SIZE; err = shm_create(&blkif->xenvbd_stats.stats); if (unlikely(err)) goto out; blkif->xenvbd_stats.last = 0; blkif->stats.xenvbd = blkif->xenvbd_stats.stats.mem; if (tapdisk_server_mem_mode()) { td_flag_set(blkif->stats.xenvbd->flags, BT3_LOW_MEMORY_MODE); } err = tapdisk_xenblkif_ring_stats_update(blkif); if (unlikely(err)) { EPRINTF("failed to generate shared I/O ring stats: %s\n", strerror(-err)); goto out; } _path = strndup(blkif->xenvbd_stats.io_ring.path, len - 1); if (unlikely(!_path)) { err = errno; goto out; } err = rename(blkif->xenvbd_stats.io_ring.path, _path); if (unlikely(err)) { err = errno; goto out; } free(blkif->xenvbd_stats.io_ring.path); blkif->xenvbd_stats.io_ring.path = _path; _path = NULL; out: free(_path); if (err) { int err2 = tapdisk_xenblkif_stats_destroy(blkif); if (err2) EPRINTF("failed to clean up failed stats file: " "%s (error ignored)\n", strerror(-err2)); } return -err; }