static int tapdisk_image_open_parent(td_image_t *image, td_image_t **_parent) { td_image_t *parent = NULL; td_disk_id_t id; int err; memset(&id, 0, sizeof(id)); id.flags = image->flags; err = td_get_parent_id(image, &id); if (err == TD_NO_PARENT) { err = 0; goto out; } if (err) return err; err = tapdisk_image_open(id.type, id.name, id.flags, &parent); if (err) return err; out: *_parent = parent; return 0; }
static int __tapdisk_image_open_chain(int type, const char *name, int flags, struct list_head *_head, int prt_devnum) { struct list_head head = LIST_HEAD_INIT(head); td_image_t *image; int err; err = tapdisk_image_open(type, name, flags, &image); if (err) goto fail; list_add_tail(&image->next, &head); if (unlikely(prt_devnum >= 0)) { char dev[32]; snprintf(dev, sizeof(dev), "%s%d", BLKTAP2_IO_DEVICE, prt_devnum); err = tapdisk_image_open(DISK_TYPE_AIO, dev, flags|TD_OPEN_RDONLY, &image); if (err) goto fail; list_add_tail(&image->next, &head); goto done; } err = tapdisk_image_open_parents(image); if (err) goto fail; done: list_splice(&head, _head); return 0; fail: tapdisk_image_close_chain(&head); return err; }
int tapdisk_vbd_add_secondary(td_vbd_t *vbd) { td_image_t *leaf, *second = NULL; const char *path; int type, err; DPRINTF("Adding secondary image: %s\n", vbd->secondary_name); type = tapdisk_disktype_parse_params(vbd->secondary_name, &path); if (type < 0) return type; leaf = tapdisk_vbd_first_image(vbd); if (!leaf) { err = -EINVAL; goto fail; } err = tapdisk_image_open(type, path, leaf->flags, &second); if (err) goto fail; if (second->info.size != leaf->info.size) { EPRINTF("Secondary image size %"PRIu64" != image size %"PRIu64"\n", second->info.size, leaf->info.size); err = -EINVAL; goto fail; } vbd->secondary = second; leaf->flags |= TD_IGNORE_ENOSPC; if (td_flag_test(vbd->flags, TD_OPEN_STANDBY)) { DPRINTF("In standby mode\n"); vbd->secondary_mode = TD_VBD_SECONDARY_STANDBY; } else { DPRINTF("In mirror mode\n"); vbd->secondary_mode = TD_VBD_SECONDARY_MIRROR; /* we actually need this image to also be part of the chain, * since it may already contain data */ list_add(&second->next, &leaf->next); } DPRINTF("Added secondary image\n"); return 0; fail: if (second) tapdisk_image_close(second); return err; }
static int tapdisk_image_open_x_chain(const char *path, struct list_head *_head) { struct list_head head = LIST_HEAD_INIT(head); td_image_t *image = NULL, *next; regex_t _im, *im = NULL, _ws, *ws = NULL; FILE *s; int err; s = fopen(path, "r"); if (!s) { err = -errno; goto fail; } err = regcomp(&_ws, "^[:space:]*$", REG_NOSUB); if (err) goto fail; ws = &_ws; err = regcomp(&_im, "^([^:]+):([^ \t]+)([ \t]+([a-z,]+))?", REG_EXTENDED|REG_NEWLINE); if (err) goto fail; im = &_im; do { char line[512], *l; regmatch_t match[5]; char *typename, *path, *args = NULL; unsigned long flags; int type; l = fgets(line, sizeof(line), s); if (!l) break; err = regexec(im, line, ARRAY_SIZE(match), match, 0); if (err) { err = regexec(ws, line, ARRAY_SIZE(match), match, 0); if (!err) continue; err = -EINVAL; goto fail; } line[match[1].rm_eo] = 0; typename = line + match[1].rm_so; line[match[2].rm_eo] = 0; path = line + match[2].rm_so; if (match[4].rm_so >= 0) { line[match[4].rm_eo] = 0; args = line + match[4].rm_so; } type = tapdisk_disktype_find(typename); if (type < 0) { err = type; goto fail; } flags = 0; if (args) { err = tapdisk_image_parse_flags(args, &flags); if (err) goto fail; } err = tapdisk_image_open(type, path, flags, &image); if (err) goto fail; list_add_tail(&image->next, &head); } while (1); if (!image) { err = -EINVAL; goto fail; } err = tapdisk_image_open_parents(image); if (err) goto fail; list_splice(&head, _head); out: if (im) regfree(im); if (ws) regfree(ws); if (s) fclose(s); return err; fail: tapdisk_for_each_image_safe(image, next, &head) tapdisk_image_free(image); goto out; }