int bdrv_commit(BlockDriverState *bs) { BlockDriver *drv = bs->drv; int64_t sector, total_sectors; int n, ro, open_flags; int ret = 0; uint8_t *buf; char filename[1024]; if (!drv) return -ENOMEDIUM; if (!bs->backing_hd) { return -ENOTSUP; } if (bdrv_in_use(bs) || bdrv_in_use(bs->backing_hd)) { return -EBUSY; } ro = bs->backing_hd->read_only; strncpy(filename, bs->backing_hd->filename, sizeof(filename)); open_flags = bs->backing_hd->open_flags; if (ro) { if (bdrv_reopen(bs->backing_hd, open_flags | BDRV_O_RDWR, NULL)) { return -EACCES; } } total_sectors = bdrv_getlength(bs) >> BDRV_SECTOR_BITS; buf = g_malloc(COMMIT_BUF_SECTORS * BDRV_SECTOR_SIZE); for (sector = 0; sector < total_sectors; sector += n) { if (bdrv_is_allocated(bs, sector, COMMIT_BUF_SECTORS, &n)) { if (bdrv_read(bs, sector, buf, n) != 0) { ret = -EIO; goto ro_cleanup; } if (bdrv_write(bs->backing_hd, sector, buf, n) != 0) { ret = -EIO; goto ro_cleanup; } } } if (drv->bdrv_make_empty) { ret = drv->bdrv_make_empty(bs); bdrv_flush(bs); } /* * Make sure all data we wrote to the backing device is actually * stable on disk. */ if (bs->backing_hd) bdrv_flush(bs->backing_hd); ro_cleanup: g_free(buf); if (ro) { /* ignoring error return here */ bdrv_reopen(bs->backing_hd, open_flags & ~BDRV_O_RDWR, NULL); } return ret; }