static void mirror_drain(BlockJob *job) { MirrorBlockJob *s = container_of(job, MirrorBlockJob, common); /* Need to keep a reference in case blk_drain triggers execution * of mirror_complete... */ if (s->target) { BlockBackend *target = s->target; blk_ref(target); blk_drain(target); blk_unref(target); } }
static int blk_connect(struct XenDevice *xendev) { struct XenBlkDev *blkdev = container_of(xendev, struct XenBlkDev, xendev); int index, qflags; bool readonly = true; bool writethrough = true; int order, ring_ref; unsigned int ring_size, max_grants; unsigned int i; trace_xen_disk_connect(xendev->name); /* read-only ? */ if (blkdev->directiosafe) { qflags = BDRV_O_NOCACHE | BDRV_O_NATIVE_AIO; } else { qflags = 0; writethrough = false; } if (strcmp(blkdev->mode, "w") == 0) { qflags |= BDRV_O_RDWR; readonly = false; } if (blkdev->feature_discard) { qflags |= BDRV_O_UNMAP; } /* init qemu block driver */ index = (xendev->dev - 202 * 256) / 16; blkdev->dinfo = drive_get(IF_XEN, 0, index); if (!blkdev->dinfo) { Error *local_err = NULL; QDict *options = NULL; if (strcmp(blkdev->fileproto, "<unset>")) { options = qdict_new(); qdict_put_str(options, "driver", blkdev->fileproto); } /* setup via xenbus -> create new block driver instance */ xen_pv_printf(xendev, 2, "create new bdrv (xenbus setup)\n"); blkdev->blk = blk_new_open(blkdev->filename, NULL, options, qflags, &local_err); if (!blkdev->blk) { xen_pv_printf(xendev, 0, "error: %s\n", error_get_pretty(local_err)); error_free(local_err); return -1; } blk_set_enable_write_cache(blkdev->blk, !writethrough); } else { /* setup via qemu cmdline -> already setup for us */ xen_pv_printf(xendev, 2, "get configured bdrv (cmdline setup)\n"); blkdev->blk = blk_by_legacy_dinfo(blkdev->dinfo); if (blk_is_read_only(blkdev->blk) && !readonly) { xen_pv_printf(xendev, 0, "Unexpected read-only drive"); blkdev->blk = NULL; return -1; } /* blkdev->blk is not create by us, we get a reference * so we can blk_unref() unconditionally */ blk_ref(blkdev->blk); } blk_attach_dev_legacy(blkdev->blk, blkdev); blkdev->file_size = blk_getlength(blkdev->blk); if (blkdev->file_size < 0) { BlockDriverState *bs = blk_bs(blkdev->blk); const char *drv_name = bs ? bdrv_get_format_name(bs) : NULL; xen_pv_printf(xendev, 1, "blk_getlength: %d (%s) | drv %s\n", (int)blkdev->file_size, strerror(-blkdev->file_size), drv_name ?: "-"); blkdev->file_size = 0; }