s->sector_count = s->faked_sectors + s->sectors_per_cluster*s->cluster_count;
- if (s->first_sectors_number == 0x40) {
- init_mbr(s, cyls, heads, secs);
- }
-
- // assert(is_consistent(s));
- qemu_co_mutex_init(&s->lock);
-
/* Disable migration when vvfat is used rw */
if (s->qcow) {
error_setg(&s->migration_blocker,
"The vvfat (rw) format used by node '%s' "
"does not support live migration",
bdrv_get_device_or_node_name(bs));
- migrate_add_blocker(s->migration_blocker);
+ ret = migrate_add_blocker(s->migration_blocker, &local_err);
+ if (local_err) {
+ error_propagate(errp, local_err);
+ error_free(s->migration_blocker);
+ goto fail;
+ }
}
+ if (s->first_sectors_number == 0x40) {
+ init_mbr(s, cyls, heads, secs);
+ }
+
+ qemu_co_mutex_init(&s->lock);
+
ret = 0;
fail:
qemu_opts_del(opts);
return -1;
if (s->qcow) {
int n;
- if (bdrv_is_allocated(s->qcow->bs, sector_num, nb_sectors-i, &n)) {
+ int ret;
+ ret = bdrv_is_allocated(s->qcow->bs, sector_num,
+ nb_sectors - i, &n);
+ if (ret < 0) {
+ return ret;
+ }
+ if (ret) {
DLOG(fprintf(stderr, "sectors %d+%d allocated\n",
(int)sector_num, n));
if (bdrv_read(s->qcow, sector_num, buf + i * 0x200, n)) {
}
}
-static inline int cluster_was_modified(BDRVVVFATState* s, uint32_t cluster_num)
+static inline bool cluster_was_modified(BDRVVVFATState *s,
+ uint32_t cluster_num)
{
int was_modified = 0;
int i, dummy;
1, &dummy);
}
- return was_modified;
+ /*
+ * Note that this treats failures to learn allocation status the
+ * same as if an allocation has occurred. It's as safe as
+ * anything else, given that a failure to learn allocation status
+ * will probably result in more failures.
+ */
+ return !!was_modified;
}
static const char* get_basename(const char* path)
int res;
res = bdrv_is_allocated(s->qcow->bs, offset + i, 1, &dummy);
+ if (res < 0) {
+ return -1;
+ }
if (!res) {
res = vvfat_read(s->bs, offset, s->cluster_buffer, 1);
if (res) {
static BlockDriver vvfat_write_target = {
.format_name = "vvfat_write_target",
+ .instance_size = sizeof(void*),
.bdrv_co_pwritev = write_target_commit,
.bdrv_close = write_target_close,
};
static void vvfat_qcow_options(int *child_flags, QDict *child_options,
int parent_flags, QDict *parent_options)
{
- *child_flags = BDRV_O_RDWR | BDRV_O_NO_FLUSH;
+ qdict_set_default_str(child_options, BDRV_OPT_READ_ONLY, "off");
+ *child_flags = BDRV_O_NO_FLUSH;
}
static const BdrvChildRole child_vvfat_qcow = {
}
options = qdict_new();
- qdict_put(options, "driver", qstring_from_str("qcow"));
+ qdict_put(options, "write-target.driver", qstring_from_str("qcow"));
s->qcow = bdrv_open_child(s->qcow_filename, options, "write-target", bs,
&child_vvfat_qcow, false, errp);
+ QDECREF(options);
if (!s->qcow) {
ret = -EINVAL;
goto err;
unlink(s->qcow_filename);
#endif
- backing = bdrv_new();
- bdrv_set_backing_hd(s->bs, backing);
- bdrv_unref(backing);
+ backing = bdrv_new_open_driver(&vvfat_write_target, NULL, BDRV_O_ALLOW_RDWR,
+ &error_abort);
+ *(void**) backing->opaque = s;
- s->bs->backing->bs->drv = &vvfat_write_target;
- s->bs->backing->bs->opaque = g_new(void *, 1);
- *(void**)s->bs->backing->bs->opaque = s;
+ bdrv_set_backing_hd(s->bs, backing, &error_abort);
+ bdrv_unref(backing);
return 0;
return ret;
}
+static void vvfat_child_perm(BlockDriverState *bs, BdrvChild *c,
+ const BdrvChildRole *role,
+ uint64_t perm, uint64_t shared,
+ uint64_t *nperm, uint64_t *nshared)
+{
+ BDRVVVFATState *s = bs->opaque;
+
+ assert(c == s->qcow || role == &child_backing);
+
+ if (c == s->qcow) {
+ /* This is a private node, nobody should try to attach to it */
+ *nperm = BLK_PERM_CONSISTENT_READ | BLK_PERM_WRITE;
+ *nshared = BLK_PERM_WRITE_UNCHANGED;
+ } else {
+ /* The backing file is there so 'commit' can use it. vvfat doesn't
+ * access it in any way. */
+ *nperm = 0;
+ *nshared = BLK_PERM_ALL;
+ }
+}
+
static void vvfat_close(BlockDriverState *bs)
{
BDRVVVFATState *s = bs->opaque;
.bdrv_file_open = vvfat_open,
.bdrv_refresh_limits = vvfat_refresh_limits,
.bdrv_close = vvfat_close,
+ .bdrv_child_perm = vvfat_child_perm,
.bdrv_co_preadv = vvfat_co_preadv,
.bdrv_co_pwritev = vvfat_co_pwritev,