mirror of
https://github.com/izzy2lost/xemu.git
synced 2026-07-06 00:20:22 -07:00
Merge remote-tracking branch 'kwolf/for-anthony' into staging
# By Max Reitz (11) and others # Via Kevin Wolf * kwolf/for-anthony: (26 commits) qemu-iotests: Overlapping cluster allocations qcow2_check: Mark image consistent qcow2-refcount: Repair shared refcount blocks qcow2-refcount: Repair OFLAG_COPIED errors qcow2-refcount: Move OFLAG_COPIED checks qcow2: Employ metadata overlap checks qcow2: Metadata overlap checks qcow2: Add corrupt bit qemu-iotests: Snapshotting zero clusters qcow2-refcount: Snapshot update for zero clusters option: Add assigned flag to QEMUOptionParameter gluster: Abort on AIO completion failure block: Remove old raw driver switch raw block driver from "raw.o" to "raw_bsd.o" raw_bsd: register bdrv_raw raw_bsd: add raw_create_options raw_bsd: introduce "special members" raw_bsd: add raw_create() raw_bsd: emit debug events in bdrv_co_readv() and bdrv_co_writev() add skeleton for BSD licensed "raw" BlockDriver ... Message-id: 1378111792-20436-1-git-send-email-kwolf@redhat.com Signed-off-by: Anthony Liguori <anthony@codemonkey.ws>
This commit is contained in:
@@ -743,7 +743,6 @@ static int bdrv_open_common(BlockDriverState *bs, BlockDriverState *file,
|
||||
ret = -EINVAL;
|
||||
goto free_and_fail;
|
||||
}
|
||||
assert(file != NULL);
|
||||
bs->file = file;
|
||||
ret = drv->bdrv_open(bs, options, open_flags);
|
||||
}
|
||||
|
||||
+1
-1
@@ -1,4 +1,4 @@
|
||||
block-obj-y += raw.o cow.o qcow.o vdi.o vmdk.o cloop.o dmg.o bochs.o vpc.o vvfat.o
|
||||
block-obj-y += raw_bsd.o cow.o qcow.o vdi.o vmdk.o cloop.o dmg.o bochs.o vpc.o vvfat.o
|
||||
block-obj-y += qcow2.o qcow2-refcount.o qcow2-cluster.o qcow2-snapshot.o qcow2-cache.o
|
||||
block-obj-y += qed.o qed-gencb.o qed-l2-cache.o qed-table.o qed-cluster.o
|
||||
block-obj-y += qed-check.o
|
||||
|
||||
@@ -168,6 +168,7 @@ static const char *event_names[BLKDBG_EVENT_MAX] = {
|
||||
|
||||
[BLKDBG_REFTABLE_LOAD] = "reftable_load",
|
||||
[BLKDBG_REFTABLE_GROW] = "reftable_grow",
|
||||
[BLKDBG_REFTABLE_UPDATE] = "reftable_update",
|
||||
|
||||
[BLKDBG_REFBLOCK_LOAD] = "refblock_load",
|
||||
[BLKDBG_REFBLOCK_UPDATE] = "refblock_update",
|
||||
|
||||
+2
-13
@@ -427,20 +427,9 @@ static void gluster_finish_aiocb(struct glfs_fd *fd, ssize_t ret, void *arg)
|
||||
/*
|
||||
* Gluster AIO callback thread failed to notify the waiting
|
||||
* QEMU thread about IO completion.
|
||||
*
|
||||
* Complete this IO request and make the disk inaccessible for
|
||||
* subsequent reads and writes.
|
||||
*/
|
||||
error_report("Gluster failed to notify QEMU about IO completion");
|
||||
|
||||
qemu_mutex_lock_iothread(); /* We are in gluster thread context */
|
||||
acb->common.cb(acb->common.opaque, -EIO);
|
||||
qemu_aio_release(acb);
|
||||
close(s->fds[GLUSTER_FD_READ]);
|
||||
close(s->fds[GLUSTER_FD_WRITE]);
|
||||
qemu_aio_set_fd_handler(s->fds[GLUSTER_FD_READ], NULL, NULL, NULL);
|
||||
bs->drv = NULL; /* Make the disk inaccessible */
|
||||
qemu_mutex_unlock_iothread();
|
||||
error_report("Gluster AIO completion failed: %s", strerror(errno));
|
||||
abort();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -114,6 +114,23 @@ static int qcow2_cache_entry_flush(BlockDriverState *bs, Qcow2Cache *c, int i)
|
||||
return ret;
|
||||
}
|
||||
|
||||
if (c == s->refcount_block_cache) {
|
||||
ret = qcow2_pre_write_overlap_check(bs,
|
||||
QCOW2_OL_DEFAULT & ~QCOW2_OL_REFCOUNT_BLOCK,
|
||||
c->entries[i].offset, s->cluster_size);
|
||||
} else if (c == s->l2_table_cache) {
|
||||
ret = qcow2_pre_write_overlap_check(bs,
|
||||
QCOW2_OL_DEFAULT & ~QCOW2_OL_ACTIVE_L2,
|
||||
c->entries[i].offset, s->cluster_size);
|
||||
} else {
|
||||
ret = qcow2_pre_write_overlap_check(bs, QCOW2_OL_DEFAULT,
|
||||
c->entries[i].offset, s->cluster_size);
|
||||
}
|
||||
|
||||
if (ret < 0) {
|
||||
return ret;
|
||||
}
|
||||
|
||||
if (c == s->refcount_block_cache) {
|
||||
BLKDBG_EVENT(bs->file, BLKDBG_REFBLOCK_UPDATE_PART);
|
||||
} else if (c == s->l2_table_cache) {
|
||||
|
||||
+23
-2
@@ -80,6 +80,14 @@ int qcow2_grow_l1_table(BlockDriverState *bs, uint64_t min_size,
|
||||
goto fail;
|
||||
}
|
||||
|
||||
/* the L1 position has not yet been updated, so these clusters must
|
||||
* indeed be completely free */
|
||||
ret = qcow2_pre_write_overlap_check(bs, QCOW2_OL_DEFAULT,
|
||||
new_l1_table_offset, new_l1_size2);
|
||||
if (ret < 0) {
|
||||
goto fail;
|
||||
}
|
||||
|
||||
BLKDBG_EVENT(bs->file, BLKDBG_L1_GROW_WRITE_TABLE);
|
||||
for(i = 0; i < s->l1_size; i++)
|
||||
new_l1_table[i] = cpu_to_be64(new_l1_table[i]);
|
||||
@@ -137,7 +145,7 @@ static int l2_load(BlockDriverState *bs, uint64_t l2_offset,
|
||||
* and we really don't want bdrv_pread to perform a read-modify-write)
|
||||
*/
|
||||
#define L1_ENTRIES_PER_SECTOR (512 / 8)
|
||||
static int write_l1_entry(BlockDriverState *bs, int l1_index)
|
||||
int qcow2_write_l1_entry(BlockDriverState *bs, int l1_index)
|
||||
{
|
||||
BDRVQcowState *s = bs->opaque;
|
||||
uint64_t buf[L1_ENTRIES_PER_SECTOR];
|
||||
@@ -149,6 +157,13 @@ static int write_l1_entry(BlockDriverState *bs, int l1_index)
|
||||
buf[i] = cpu_to_be64(s->l1_table[l1_start_index + i]);
|
||||
}
|
||||
|
||||
ret = qcow2_pre_write_overlap_check(bs,
|
||||
QCOW2_OL_DEFAULT & ~QCOW2_OL_ACTIVE_L1,
|
||||
s->l1_table_offset + 8 * l1_start_index, sizeof(buf));
|
||||
if (ret < 0) {
|
||||
return ret;
|
||||
}
|
||||
|
||||
BLKDBG_EVENT(bs->file, BLKDBG_L1_UPDATE);
|
||||
ret = bdrv_pwrite_sync(bs->file, s->l1_table_offset + 8 * l1_start_index,
|
||||
buf, sizeof(buf));
|
||||
@@ -239,7 +254,7 @@ static int l2_allocate(BlockDriverState *bs, int l1_index, uint64_t **table)
|
||||
/* update the L1 entry */
|
||||
trace_qcow2_l2_allocate_write_l1(bs, l1_index);
|
||||
s->l1_table[l1_index] = l2_offset | QCOW_OFLAG_COPIED;
|
||||
ret = write_l1_entry(bs, l1_index);
|
||||
ret = qcow2_write_l1_entry(bs, l1_index);
|
||||
if (ret < 0) {
|
||||
goto fail;
|
||||
}
|
||||
@@ -368,6 +383,12 @@ static int coroutine_fn copy_sectors(BlockDriverState *bs,
|
||||
&s->aes_encrypt_key);
|
||||
}
|
||||
|
||||
ret = qcow2_pre_write_overlap_check(bs, QCOW2_OL_DEFAULT,
|
||||
cluster_offset + n_start * BDRV_SECTOR_SIZE, n * BDRV_SECTOR_SIZE);
|
||||
if (ret < 0) {
|
||||
goto out;
|
||||
}
|
||||
|
||||
BLKDBG_EVENT(bs->file, BLKDBG_COW_WRITE);
|
||||
ret = bdrv_co_writev(bs->file, (cluster_offset >> 9) + n_start, n, &qiov);
|
||||
if (ret < 0) {
|
||||
|
||||
+481
-52
File diff suppressed because it is too large
Load Diff
@@ -189,6 +189,15 @@ static int qcow2_write_snapshots(BlockDriverState *bs)
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* The snapshot list position has not yet been updated, so these clusters
|
||||
* must indeed be completely free */
|
||||
ret = qcow2_pre_write_overlap_check(bs, QCOW2_OL_DEFAULT, offset,
|
||||
s->snapshots_size);
|
||||
if (ret < 0) {
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
/* Write all snapshots to the new list */
|
||||
for(i = 0; i < s->nb_snapshots; i++) {
|
||||
sn = s->snapshots + i;
|
||||
@@ -363,6 +372,12 @@ int qcow2_snapshot_create(BlockDriverState *bs, QEMUSnapshotInfo *sn_info)
|
||||
l1_table[i] = cpu_to_be64(s->l1_table[i]);
|
||||
}
|
||||
|
||||
ret = qcow2_pre_write_overlap_check(bs, QCOW2_OL_DEFAULT,
|
||||
sn->l1_table_offset, s->l1_size * sizeof(uint64_t));
|
||||
if (ret < 0) {
|
||||
goto fail;
|
||||
}
|
||||
|
||||
ret = bdrv_pwrite(bs->file, sn->l1_table_offset, l1_table,
|
||||
s->l1_size * sizeof(uint64_t));
|
||||
if (ret < 0) {
|
||||
@@ -475,6 +490,13 @@ int qcow2_snapshot_goto(BlockDriverState *bs, const char *snapshot_id)
|
||||
goto fail;
|
||||
}
|
||||
|
||||
ret = qcow2_pre_write_overlap_check(bs,
|
||||
QCOW2_OL_DEFAULT & ~QCOW2_OL_ACTIVE_L1,
|
||||
s->l1_table_offset, cur_l1_bytes);
|
||||
if (ret < 0) {
|
||||
goto fail;
|
||||
}
|
||||
|
||||
ret = bdrv_pwrite_sync(bs->file, s->l1_table_offset, sn_l1_table,
|
||||
cur_l1_bytes);
|
||||
if (ret < 0) {
|
||||
|
||||
+81
-2
@@ -272,6 +272,37 @@ static int qcow2_mark_clean(BlockDriverState *bs)
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Marks the image as corrupt.
|
||||
*/
|
||||
int qcow2_mark_corrupt(BlockDriverState *bs)
|
||||
{
|
||||
BDRVQcowState *s = bs->opaque;
|
||||
|
||||
s->incompatible_features |= QCOW2_INCOMPAT_CORRUPT;
|
||||
return qcow2_update_header(bs);
|
||||
}
|
||||
|
||||
/*
|
||||
* Marks the image as consistent, i.e., unsets the corrupt bit, and flushes
|
||||
* before if necessary.
|
||||
*/
|
||||
int qcow2_mark_consistent(BlockDriverState *bs)
|
||||
{
|
||||
BDRVQcowState *s = bs->opaque;
|
||||
|
||||
if (s->incompatible_features & QCOW2_INCOMPAT_CORRUPT) {
|
||||
int ret = bdrv_flush(bs);
|
||||
if (ret < 0) {
|
||||
return ret;
|
||||
}
|
||||
|
||||
s->incompatible_features &= ~QCOW2_INCOMPAT_CORRUPT;
|
||||
return qcow2_update_header(bs);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int qcow2_check(BlockDriverState *bs, BdrvCheckResult *result,
|
||||
BdrvCheckMode fix)
|
||||
{
|
||||
@@ -281,7 +312,11 @@ static int qcow2_check(BlockDriverState *bs, BdrvCheckResult *result,
|
||||
}
|
||||
|
||||
if (fix && result->check_errors == 0 && result->corruptions == 0) {
|
||||
return qcow2_mark_clean(bs);
|
||||
ret = qcow2_mark_clean(bs);
|
||||
if (ret < 0) {
|
||||
return ret;
|
||||
}
|
||||
return qcow2_mark_consistent(bs);
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
@@ -402,6 +437,17 @@ static int qcow2_open(BlockDriverState *bs, QDict *options, int flags)
|
||||
goto fail;
|
||||
}
|
||||
|
||||
if (s->incompatible_features & QCOW2_INCOMPAT_CORRUPT) {
|
||||
/* Corrupt images may not be written to unless they are being repaired
|
||||
*/
|
||||
if ((flags & BDRV_O_RDWR) && !(flags & BDRV_O_CHECK)) {
|
||||
error_report("qcow2: Image is corrupt; cannot be opened "
|
||||
"read/write.");
|
||||
ret = -EACCES;
|
||||
goto fail;
|
||||
}
|
||||
}
|
||||
|
||||
/* Check support for various header values */
|
||||
if (header.refcount_order != 4) {
|
||||
report_unsupported(bs, "%d bit reference counts",
|
||||
@@ -582,6 +628,8 @@ static int qcow2_open(BlockDriverState *bs, QDict *options, int flags)
|
||||
qcow2_free_snapshots(bs);
|
||||
qcow2_refcount_close(bs);
|
||||
g_free(s->l1_table);
|
||||
/* else pre-write overlap checks in cache_destroy may crash */
|
||||
s->l1_table = NULL;
|
||||
if (s->l2_table_cache) {
|
||||
qcow2_cache_destroy(bs, s->l2_table_cache);
|
||||
}
|
||||
@@ -881,6 +929,13 @@ static coroutine_fn int qcow2_co_writev(BlockDriverState *bs,
|
||||
cur_nr_sectors * 512);
|
||||
}
|
||||
|
||||
ret = qcow2_pre_write_overlap_check(bs, QCOW2_OL_DEFAULT,
|
||||
cluster_offset + index_in_cluster * BDRV_SECTOR_SIZE,
|
||||
cur_nr_sectors * BDRV_SECTOR_SIZE);
|
||||
if (ret < 0) {
|
||||
goto fail;
|
||||
}
|
||||
|
||||
qemu_co_mutex_unlock(&s->lock);
|
||||
BLKDBG_EVENT(bs->file, BLKDBG_WRITE_AIO);
|
||||
trace_qcow2_writev_data(qemu_coroutine_self(),
|
||||
@@ -947,6 +1002,8 @@ static void qcow2_close(BlockDriverState *bs)
|
||||
{
|
||||
BDRVQcowState *s = bs->opaque;
|
||||
g_free(s->l1_table);
|
||||
/* else pre-write overlap checks in cache_destroy may crash */
|
||||
s->l1_table = NULL;
|
||||
|
||||
qcow2_cache_flush(bs, s->l2_table_cache);
|
||||
qcow2_cache_flush(bs, s->refcount_block_cache);
|
||||
@@ -1129,6 +1186,11 @@ int qcow2_update_header(BlockDriverState *bs)
|
||||
.bit = QCOW2_INCOMPAT_DIRTY_BITNR,
|
||||
.name = "dirty bit",
|
||||
},
|
||||
{
|
||||
.type = QCOW2_FEAT_TYPE_INCOMPATIBLE,
|
||||
.bit = QCOW2_INCOMPAT_CORRUPT_BITNR,
|
||||
.name = "corrupt bit",
|
||||
},
|
||||
{
|
||||
.type = QCOW2_FEAT_TYPE_COMPATIBLE,
|
||||
.bit = QCOW2_COMPAT_LAZY_REFCOUNTS_BITNR,
|
||||
@@ -1429,7 +1491,9 @@ static int qcow2_create(const char *filename, QEMUOptionParameter *options)
|
||||
return -EINVAL;
|
||||
}
|
||||
} else if (!strcmp(options->name, BLOCK_OPT_COMPAT_LEVEL)) {
|
||||
if (!options->value.s || !strcmp(options->value.s, "0.10")) {
|
||||
if (!options->value.s) {
|
||||
/* keep the default */
|
||||
} else if (!strcmp(options->value.s, "0.10")) {
|
||||
version = 2;
|
||||
} else if (!strcmp(options->value.s, "1.1")) {
|
||||
version = 3;
|
||||
@@ -1619,6 +1683,14 @@ static int qcow2_write_compressed(BlockDriverState *bs, int64_t sector_num,
|
||||
|
||||
if (ret != Z_STREAM_END || out_len >= s->cluster_size) {
|
||||
/* could not compress: write normal cluster */
|
||||
|
||||
ret = qcow2_pre_write_overlap_check(bs, QCOW2_OL_DEFAULT,
|
||||
sector_num * BDRV_SECTOR_SIZE,
|
||||
s->cluster_sectors * BDRV_SECTOR_SIZE);
|
||||
if (ret < 0) {
|
||||
goto fail;
|
||||
}
|
||||
|
||||
ret = bdrv_write(bs, sector_num, buf, s->cluster_sectors);
|
||||
if (ret < 0) {
|
||||
goto fail;
|
||||
@@ -1631,6 +1703,13 @@ static int qcow2_write_compressed(BlockDriverState *bs, int64_t sector_num,
|
||||
goto fail;
|
||||
}
|
||||
cluster_offset &= s->cluster_offset_mask;
|
||||
|
||||
ret = qcow2_pre_write_overlap_check(bs, QCOW2_OL_DEFAULT,
|
||||
cluster_offset, out_len);
|
||||
if (ret < 0) {
|
||||
goto fail;
|
||||
}
|
||||
|
||||
BLKDBG_EVENT(bs->file, BLKDBG_WRITE_COMPRESSED);
|
||||
ret = bdrv_pwrite(bs->file, cluster_offset, out_buf, out_len);
|
||||
if (ret < 0) {
|
||||
|
||||
+49
-4
@@ -40,11 +40,11 @@
|
||||
#define QCOW_MAX_CRYPT_CLUSTERS 32
|
||||
|
||||
/* indicate that the refcount of the referenced cluster is exactly one. */
|
||||
#define QCOW_OFLAG_COPIED (1LL << 63)
|
||||
#define QCOW_OFLAG_COPIED (1ULL << 63)
|
||||
/* indicate that the cluster is compressed (they never have the copied flag) */
|
||||
#define QCOW_OFLAG_COMPRESSED (1LL << 62)
|
||||
#define QCOW_OFLAG_COMPRESSED (1ULL << 62)
|
||||
/* The cluster reads as all zeros */
|
||||
#define QCOW_OFLAG_ZERO (1LL << 0)
|
||||
#define QCOW_OFLAG_ZERO (1ULL << 0)
|
||||
|
||||
#define REFCOUNT_SHIFT 1 /* refcount size is 2 bytes */
|
||||
|
||||
@@ -119,9 +119,12 @@ enum {
|
||||
/* Incompatible feature bits */
|
||||
enum {
|
||||
QCOW2_INCOMPAT_DIRTY_BITNR = 0,
|
||||
QCOW2_INCOMPAT_CORRUPT_BITNR = 1,
|
||||
QCOW2_INCOMPAT_DIRTY = 1 << QCOW2_INCOMPAT_DIRTY_BITNR,
|
||||
QCOW2_INCOMPAT_CORRUPT = 1 << QCOW2_INCOMPAT_CORRUPT_BITNR,
|
||||
|
||||
QCOW2_INCOMPAT_MASK = QCOW2_INCOMPAT_DIRTY,
|
||||
QCOW2_INCOMPAT_MASK = QCOW2_INCOMPAT_DIRTY
|
||||
| QCOW2_INCOMPAT_CORRUPT,
|
||||
};
|
||||
|
||||
/* Compatible feature bits */
|
||||
@@ -286,6 +289,40 @@ enum {
|
||||
QCOW2_CLUSTER_ZERO
|
||||
};
|
||||
|
||||
typedef enum QCow2MetadataOverlap {
|
||||
QCOW2_OL_MAIN_HEADER_BITNR = 0,
|
||||
QCOW2_OL_ACTIVE_L1_BITNR = 1,
|
||||
QCOW2_OL_ACTIVE_L2_BITNR = 2,
|
||||
QCOW2_OL_REFCOUNT_TABLE_BITNR = 3,
|
||||
QCOW2_OL_REFCOUNT_BLOCK_BITNR = 4,
|
||||
QCOW2_OL_SNAPSHOT_TABLE_BITNR = 5,
|
||||
QCOW2_OL_INACTIVE_L1_BITNR = 6,
|
||||
QCOW2_OL_INACTIVE_L2_BITNR = 7,
|
||||
|
||||
QCOW2_OL_MAX_BITNR = 8,
|
||||
|
||||
QCOW2_OL_NONE = 0,
|
||||
QCOW2_OL_MAIN_HEADER = (1 << QCOW2_OL_MAIN_HEADER_BITNR),
|
||||
QCOW2_OL_ACTIVE_L1 = (1 << QCOW2_OL_ACTIVE_L1_BITNR),
|
||||
QCOW2_OL_ACTIVE_L2 = (1 << QCOW2_OL_ACTIVE_L2_BITNR),
|
||||
QCOW2_OL_REFCOUNT_TABLE = (1 << QCOW2_OL_REFCOUNT_TABLE_BITNR),
|
||||
QCOW2_OL_REFCOUNT_BLOCK = (1 << QCOW2_OL_REFCOUNT_BLOCK_BITNR),
|
||||
QCOW2_OL_SNAPSHOT_TABLE = (1 << QCOW2_OL_SNAPSHOT_TABLE_BITNR),
|
||||
QCOW2_OL_INACTIVE_L1 = (1 << QCOW2_OL_INACTIVE_L1_BITNR),
|
||||
/* NOTE: Checking overlaps with inactive L2 tables will result in bdrv
|
||||
* reads. */
|
||||
QCOW2_OL_INACTIVE_L2 = (1 << QCOW2_OL_INACTIVE_L2_BITNR),
|
||||
} QCow2MetadataOverlap;
|
||||
|
||||
/* Perform all overlap checks which don't require disk access */
|
||||
#define QCOW2_OL_CACHED \
|
||||
(QCOW2_OL_MAIN_HEADER | QCOW2_OL_ACTIVE_L1 | QCOW2_OL_ACTIVE_L2 | \
|
||||
QCOW2_OL_REFCOUNT_TABLE | QCOW2_OL_REFCOUNT_BLOCK | \
|
||||
QCOW2_OL_SNAPSHOT_TABLE | QCOW2_OL_INACTIVE_L1)
|
||||
|
||||
/* The default checks to perform */
|
||||
#define QCOW2_OL_DEFAULT QCOW2_OL_CACHED
|
||||
|
||||
#define L1E_OFFSET_MASK 0x00ffffffffffff00ULL
|
||||
#define L2E_OFFSET_MASK 0x00ffffffffffff00ULL
|
||||
#define L2E_COMPRESSED_OFFSET_SIZE_MASK 0x3fffffffffffffffULL
|
||||
@@ -361,6 +398,8 @@ int qcow2_backing_read1(BlockDriverState *bs, QEMUIOVector *qiov,
|
||||
int64_t sector_num, int nb_sectors);
|
||||
|
||||
int qcow2_mark_dirty(BlockDriverState *bs);
|
||||
int qcow2_mark_corrupt(BlockDriverState *bs);
|
||||
int qcow2_mark_consistent(BlockDriverState *bs);
|
||||
int qcow2_update_header(BlockDriverState *bs);
|
||||
|
||||
/* qcow2-refcount.c functions */
|
||||
@@ -385,9 +424,15 @@ int qcow2_check_refcounts(BlockDriverState *bs, BdrvCheckResult *res,
|
||||
|
||||
void qcow2_process_discards(BlockDriverState *bs, int ret);
|
||||
|
||||
int qcow2_check_metadata_overlap(BlockDriverState *bs, int chk, int64_t offset,
|
||||
int64_t size);
|
||||
int qcow2_pre_write_overlap_check(BlockDriverState *bs, int chk, int64_t offset,
|
||||
int64_t size);
|
||||
|
||||
/* qcow2-cluster.c functions */
|
||||
int qcow2_grow_l1_table(BlockDriverState *bs, uint64_t min_size,
|
||||
bool exact_size);
|
||||
int qcow2_write_l1_entry(BlockDriverState *bs, int l1_index);
|
||||
void qcow2_l2_cache_reset(BlockDriverState *bs);
|
||||
int qcow2_decompress_cluster(BlockDriverState *bs, uint64_t cluster_offset);
|
||||
void qcow2_encrypt_sectors(BDRVQcowState *s, int64_t sector_num,
|
||||
|
||||
@@ -1,13 +1,17 @@
|
||||
/*
|
||||
* Block driver for RAW format
|
||||
/* BlockDriver implementation for "raw"
|
||||
*
|
||||
* Copyright (c) 2006 Fabrice Bellard
|
||||
* Copyright (C) 2010, 2013, Red Hat, Inc.
|
||||
* Copyright (C) 2010, Blue Swirl <blauwirbel@gmail.com>
|
||||
* Copyright (C) 2009, Anthony Liguori <aliguori@us.ibm.com>
|
||||
*
|
||||
* Author:
|
||||
* Laszlo Ersek <lersek@redhat.com>
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* of this software and associated documentation files (the "Software"), to
|
||||
* deal in the Software without restriction, including without limitation the
|
||||
* rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
|
||||
* sell copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
@@ -15,27 +19,27 @@
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
||||
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
|
||||
* IN THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#include "qemu-common.h"
|
||||
#include "block/block_int.h"
|
||||
#include "qemu/module.h"
|
||||
#include "qemu/option.h"
|
||||
|
||||
static int raw_open(BlockDriverState *bs, QDict *options, int flags)
|
||||
{
|
||||
bs->sg = bs->file->sg;
|
||||
return 0;
|
||||
}
|
||||
static QEMUOptionParameter raw_create_options[] = {
|
||||
{
|
||||
.name = BLOCK_OPT_SIZE,
|
||||
.type = OPT_SIZE,
|
||||
.help = "Virtual disk size"
|
||||
},
|
||||
{ 0 }
|
||||
};
|
||||
|
||||
/* We have nothing to do for raw reopen, stubs just return
|
||||
* success */
|
||||
static int raw_reopen_prepare(BDRVReopenState *state,
|
||||
BlockReopenQueue *queue, Error **errp)
|
||||
static int raw_reopen_prepare(BDRVReopenState *reopen_state,
|
||||
BlockReopenQueue *queue, Error **errp)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
@@ -54,45 +58,40 @@ static int coroutine_fn raw_co_writev(BlockDriverState *bs, int64_t sector_num,
|
||||
return bdrv_co_writev(bs->file, sector_num, nb_sectors, qiov);
|
||||
}
|
||||
|
||||
static void raw_close(BlockDriverState *bs)
|
||||
{
|
||||
}
|
||||
|
||||
static int coroutine_fn raw_co_is_allocated(BlockDriverState *bs,
|
||||
int64_t sector_num,
|
||||
int nb_sectors, int *pnum)
|
||||
int64_t sector_num, int nb_sectors,
|
||||
int *pnum)
|
||||
{
|
||||
return bdrv_co_is_allocated(bs->file, sector_num, nb_sectors, pnum);
|
||||
}
|
||||
|
||||
static int coroutine_fn raw_co_write_zeroes(BlockDriverState *bs,
|
||||
int64_t sector_num,
|
||||
int nb_sectors)
|
||||
int64_t sector_num, int nb_sectors)
|
||||
{
|
||||
return bdrv_co_write_zeroes(bs->file, sector_num, nb_sectors);
|
||||
}
|
||||
|
||||
static int coroutine_fn raw_co_discard(BlockDriverState *bs,
|
||||
int64_t sector_num, int nb_sectors)
|
||||
{
|
||||
return bdrv_co_discard(bs->file, sector_num, nb_sectors);
|
||||
}
|
||||
|
||||
static int64_t raw_getlength(BlockDriverState *bs)
|
||||
{
|
||||
return bdrv_getlength(bs->file);
|
||||
}
|
||||
|
||||
static int raw_get_info(BlockDriverState *bs, BlockDriverInfo *bdi)
|
||||
{
|
||||
return bdrv_get_info(bs->file, bdi);
|
||||
}
|
||||
|
||||
static int raw_truncate(BlockDriverState *bs, int64_t offset)
|
||||
{
|
||||
return bdrv_truncate(bs->file, offset);
|
||||
}
|
||||
|
||||
static int raw_probe(const uint8_t *buf, int buf_size, const char *filename)
|
||||
{
|
||||
return 1; /* everything can be opened as raw image */
|
||||
}
|
||||
|
||||
static int coroutine_fn raw_co_discard(BlockDriverState *bs,
|
||||
int64_t sector_num, int nb_sectors)
|
||||
{
|
||||
return bdrv_co_discard(bs->file, sector_num, nb_sectors);
|
||||
}
|
||||
|
||||
static int raw_is_inserted(BlockDriverState *bs)
|
||||
{
|
||||
return bdrv_is_inserted(bs->file);
|
||||
@@ -115,14 +114,20 @@ static void raw_lock_medium(BlockDriverState *bs, bool locked)
|
||||
|
||||
static int raw_ioctl(BlockDriverState *bs, unsigned long int req, void *buf)
|
||||
{
|
||||
return bdrv_ioctl(bs->file, req, buf);
|
||||
return bdrv_ioctl(bs->file, req, buf);
|
||||
}
|
||||
|
||||
static BlockDriverAIOCB *raw_aio_ioctl(BlockDriverState *bs,
|
||||
unsigned long int req, void *buf,
|
||||
BlockDriverCompletionFunc *cb, void *opaque)
|
||||
unsigned long int req, void *buf,
|
||||
BlockDriverCompletionFunc *cb,
|
||||
void *opaque)
|
||||
{
|
||||
return bdrv_aio_ioctl(bs->file, req, buf, cb, opaque);
|
||||
return bdrv_aio_ioctl(bs->file, req, buf, cb, opaque);
|
||||
}
|
||||
|
||||
static int raw_has_zero_init(BlockDriverState *bs)
|
||||
{
|
||||
return bdrv_has_zero_init(bs->file);
|
||||
}
|
||||
|
||||
static int raw_create(const char *filename, QEMUOptionParameter *options)
|
||||
@@ -130,58 +135,47 @@ static int raw_create(const char *filename, QEMUOptionParameter *options)
|
||||
return bdrv_create_file(filename, options);
|
||||
}
|
||||
|
||||
static QEMUOptionParameter raw_create_options[] = {
|
||||
{
|
||||
.name = BLOCK_OPT_SIZE,
|
||||
.type = OPT_SIZE,
|
||||
.help = "Virtual disk size"
|
||||
},
|
||||
{ NULL }
|
||||
};
|
||||
|
||||
static int raw_has_zero_init(BlockDriverState *bs)
|
||||
static int raw_open(BlockDriverState *bs, QDict *options, int flags)
|
||||
{
|
||||
return bdrv_has_zero_init(bs->file);
|
||||
bs->sg = bs->file->sg;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int raw_get_info(BlockDriverState *bs, BlockDriverInfo *bdi)
|
||||
static void raw_close(BlockDriverState *bs)
|
||||
{
|
||||
return bdrv_get_info(bs->file, bdi);
|
||||
}
|
||||
|
||||
static int raw_probe(const uint8_t *buf, int buf_size, const char *filename)
|
||||
{
|
||||
/* smallest possible positive score so that raw is used if and only if no
|
||||
* other block driver works
|
||||
*/
|
||||
return 1;
|
||||
}
|
||||
|
||||
static BlockDriver bdrv_raw = {
|
||||
.format_name = "raw",
|
||||
|
||||
/* It's really 0, but we need to make g_malloc() happy */
|
||||
.instance_size = 1,
|
||||
|
||||
.bdrv_open = raw_open,
|
||||
.bdrv_close = raw_close,
|
||||
|
||||
.bdrv_reopen_prepare = raw_reopen_prepare,
|
||||
|
||||
.bdrv_co_readv = raw_co_readv,
|
||||
.bdrv_co_writev = raw_co_writev,
|
||||
.bdrv_co_is_allocated = raw_co_is_allocated,
|
||||
.bdrv_co_write_zeroes = raw_co_write_zeroes,
|
||||
.bdrv_co_discard = raw_co_discard,
|
||||
|
||||
.bdrv_probe = raw_probe,
|
||||
.bdrv_getlength = raw_getlength,
|
||||
.bdrv_get_info = raw_get_info,
|
||||
.bdrv_truncate = raw_truncate,
|
||||
|
||||
.bdrv_is_inserted = raw_is_inserted,
|
||||
.bdrv_media_changed = raw_media_changed,
|
||||
.bdrv_eject = raw_eject,
|
||||
.bdrv_lock_medium = raw_lock_medium,
|
||||
|
||||
.bdrv_ioctl = raw_ioctl,
|
||||
.bdrv_aio_ioctl = raw_aio_ioctl,
|
||||
|
||||
.bdrv_create = raw_create,
|
||||
.create_options = raw_create_options,
|
||||
.bdrv_has_zero_init = raw_has_zero_init,
|
||||
.format_name = "raw",
|
||||
.bdrv_probe = &raw_probe,
|
||||
.bdrv_reopen_prepare = &raw_reopen_prepare,
|
||||
.bdrv_open = &raw_open,
|
||||
.bdrv_close = &raw_close,
|
||||
.bdrv_create = &raw_create,
|
||||
.bdrv_co_readv = &raw_co_readv,
|
||||
.bdrv_co_writev = &raw_co_writev,
|
||||
.bdrv_co_write_zeroes = &raw_co_write_zeroes,
|
||||
.bdrv_co_discard = &raw_co_discard,
|
||||
.bdrv_co_is_allocated = &raw_co_is_allocated,
|
||||
.bdrv_truncate = &raw_truncate,
|
||||
.bdrv_getlength = &raw_getlength,
|
||||
.bdrv_get_info = &raw_get_info,
|
||||
.bdrv_is_inserted = &raw_is_inserted,
|
||||
.bdrv_media_changed = &raw_media_changed,
|
||||
.bdrv_eject = &raw_eject,
|
||||
.bdrv_lock_medium = &raw_lock_medium,
|
||||
.bdrv_ioctl = &raw_ioctl,
|
||||
.bdrv_aio_ioctl = &raw_aio_ioctl,
|
||||
.create_options = &raw_create_options[0],
|
||||
.bdrv_has_zero_init = &raw_has_zero_init
|
||||
};
|
||||
|
||||
static void bdrv_raw_init(void)
|
||||
-143
@@ -46,7 +46,6 @@
|
||||
|
||||
static QTAILQ_HEAD(drivelist, DriveInfo) drives = QTAILQ_HEAD_INITIALIZER(drives);
|
||||
extern QemuOptsList qemu_common_drive_opts;
|
||||
extern QemuOptsList qemu_old_drive_opts;
|
||||
|
||||
static const char *const if_name[IF_COUNT] = {
|
||||
[IF_NONE] = "none",
|
||||
@@ -755,26 +754,6 @@ DriveInfo *drive_init(QemuOpts *all_opts, BlockInterfaceType block_default_type)
|
||||
{
|
||||
const char *value;
|
||||
|
||||
/*
|
||||
* Check that only old options are used by copying into a QemuOpts with
|
||||
* stricter checks. Going through a QDict seems to be the easiest way to
|
||||
* achieve this...
|
||||
*/
|
||||
QemuOpts* check_opts;
|
||||
QDict *qdict;
|
||||
Error *local_err = NULL;
|
||||
|
||||
qdict = qemu_opts_to_qdict(all_opts, NULL);
|
||||
check_opts = qemu_opts_from_qdict(&qemu_old_drive_opts, qdict, &local_err);
|
||||
QDECREF(qdict);
|
||||
|
||||
if (error_is_set(&local_err)) {
|
||||
qerror_report_err(local_err);
|
||||
error_free(local_err);
|
||||
return NULL;
|
||||
}
|
||||
qemu_opts_del(check_opts);
|
||||
|
||||
/* Change legacy command line options into QMP ones */
|
||||
qemu_opt_rename(all_opts, "iops", "throttling.iops-total");
|
||||
qemu_opt_rename(all_opts, "iops_rd", "throttling.iops-read");
|
||||
@@ -2001,128 +1980,6 @@ QemuOptsList qemu_common_drive_opts = {
|
||||
},
|
||||
};
|
||||
|
||||
QemuOptsList qemu_old_drive_opts = {
|
||||
.name = "drive",
|
||||
.head = QTAILQ_HEAD_INITIALIZER(qemu_old_drive_opts.head),
|
||||
.desc = {
|
||||
{
|
||||
.name = "bus",
|
||||
.type = QEMU_OPT_NUMBER,
|
||||
.help = "bus number",
|
||||
},{
|
||||
.name = "unit",
|
||||
.type = QEMU_OPT_NUMBER,
|
||||
.help = "unit number (i.e. lun for scsi)",
|
||||
},{
|
||||
.name = "if",
|
||||
.type = QEMU_OPT_STRING,
|
||||
.help = "interface (ide, scsi, sd, mtd, floppy, pflash, virtio)",
|
||||
},{
|
||||
.name = "index",
|
||||
.type = QEMU_OPT_NUMBER,
|
||||
.help = "index number",
|
||||
},{
|
||||
.name = "cyls",
|
||||
.type = QEMU_OPT_NUMBER,
|
||||
.help = "number of cylinders (ide disk geometry)",
|
||||
},{
|
||||
.name = "heads",
|
||||
.type = QEMU_OPT_NUMBER,
|
||||
.help = "number of heads (ide disk geometry)",
|
||||
},{
|
||||
.name = "secs",
|
||||
.type = QEMU_OPT_NUMBER,
|
||||
.help = "number of sectors (ide disk geometry)",
|
||||
},{
|
||||
.name = "trans",
|
||||
.type = QEMU_OPT_STRING,
|
||||
.help = "chs translation (auto, lba. none)",
|
||||
},{
|
||||
.name = "media",
|
||||
.type = QEMU_OPT_STRING,
|
||||
.help = "media type (disk, cdrom)",
|
||||
},{
|
||||
.name = "snapshot",
|
||||
.type = QEMU_OPT_BOOL,
|
||||
.help = "enable/disable snapshot mode",
|
||||
},{
|
||||
.name = "file",
|
||||
.type = QEMU_OPT_STRING,
|
||||
.help = "disk image",
|
||||
},{
|
||||
.name = "discard",
|
||||
.type = QEMU_OPT_STRING,
|
||||
.help = "discard operation (ignore/off, unmap/on)",
|
||||
},{
|
||||
.name = "cache",
|
||||
.type = QEMU_OPT_STRING,
|
||||
.help = "host cache usage (none, writeback, writethrough, "
|
||||
"directsync, unsafe)",
|
||||
},{
|
||||
.name = "aio",
|
||||
.type = QEMU_OPT_STRING,
|
||||
.help = "host AIO implementation (threads, native)",
|
||||
},{
|
||||
.name = "format",
|
||||
.type = QEMU_OPT_STRING,
|
||||
.help = "disk format (raw, qcow2, ...)",
|
||||
},{
|
||||
.name = "serial",
|
||||
.type = QEMU_OPT_STRING,
|
||||
.help = "disk serial number",
|
||||
},{
|
||||
.name = "rerror",
|
||||
.type = QEMU_OPT_STRING,
|
||||
.help = "read error action",
|
||||
},{
|
||||
.name = "werror",
|
||||
.type = QEMU_OPT_STRING,
|
||||
.help = "write error action",
|
||||
},{
|
||||
.name = "addr",
|
||||
.type = QEMU_OPT_STRING,
|
||||
.help = "pci address (virtio only)",
|
||||
},{
|
||||
.name = "readonly",
|
||||
.type = QEMU_OPT_BOOL,
|
||||
.help = "open drive file as read-only",
|
||||
},{
|
||||
.name = "iops",
|
||||
.type = QEMU_OPT_NUMBER,
|
||||
.help = "limit total I/O operations per second",
|
||||
},{
|
||||
.name = "iops_rd",
|
||||
.type = QEMU_OPT_NUMBER,
|
||||
.help = "limit read operations per second",
|
||||
},{
|
||||
.name = "iops_wr",
|
||||
.type = QEMU_OPT_NUMBER,
|
||||
.help = "limit write operations per second",
|
||||
},{
|
||||
.name = "bps",
|
||||
.type = QEMU_OPT_NUMBER,
|
||||
.help = "limit total bytes per second",
|
||||
},{
|
||||
.name = "bps_rd",
|
||||
.type = QEMU_OPT_NUMBER,
|
||||
.help = "limit read bytes per second",
|
||||
},{
|
||||
.name = "bps_wr",
|
||||
.type = QEMU_OPT_NUMBER,
|
||||
.help = "limit write bytes per second",
|
||||
},{
|
||||
.name = "copy-on-read",
|
||||
.type = QEMU_OPT_BOOL,
|
||||
.help = "copy read data from backing file into image file",
|
||||
},{
|
||||
.name = "boot",
|
||||
.type = QEMU_OPT_BOOL,
|
||||
.help = "(deprecated, ignored)",
|
||||
},
|
||||
{ /* end of list */ }
|
||||
},
|
||||
};
|
||||
|
||||
QemuOptsList qemu_drive_opts = {
|
||||
.name = "drive",
|
||||
.head = QTAILQ_HEAD_INITIALIZER(qemu_drive_opts.head),
|
||||
|
||||
@@ -80,7 +80,12 @@ in the description of a field.
|
||||
tables to repair refcounts before accessing the
|
||||
image.
|
||||
|
||||
Bits 1-63: Reserved (set to 0)
|
||||
Bit 1: Corrupt bit. If this bit is set then any data
|
||||
structure may be corrupt and the image must not
|
||||
be written to (unless for regaining
|
||||
consistency).
|
||||
|
||||
Bits 2-63: Reserved (set to 0)
|
||||
|
||||
80 - 87: compatible_features
|
||||
Bitmask of compatible features. An implementation can
|
||||
|
||||
@@ -413,6 +413,7 @@ typedef enum {
|
||||
|
||||
BLKDBG_REFTABLE_LOAD,
|
||||
BLKDBG_REFTABLE_GROW,
|
||||
BLKDBG_REFTABLE_UPDATE,
|
||||
|
||||
BLKDBG_REFBLOCK_LOAD,
|
||||
BLKDBG_REFBLOCK_UPDATE,
|
||||
|
||||
@@ -48,6 +48,7 @@ typedef enum MonitorEvent {
|
||||
QEVENT_BALLOON_CHANGE,
|
||||
QEVENT_SPICE_MIGRATE_COMPLETED,
|
||||
QEVENT_GUEST_PANICKED,
|
||||
QEVENT_BLOCK_IMAGE_CORRUPTED,
|
||||
|
||||
/* Add to 'monitor_event_names' array in monitor.c when
|
||||
* defining new events here */
|
||||
|
||||
@@ -46,6 +46,7 @@ typedef struct QEMUOptionParameter {
|
||||
char* s;
|
||||
} value;
|
||||
const char *help;
|
||||
bool assigned;
|
||||
} QEMUOptionParameter;
|
||||
|
||||
|
||||
|
||||
@@ -506,6 +506,7 @@ static const char *monitor_event_names[] = {
|
||||
[QEVENT_BALLOON_CHANGE] = "BALLOON_CHANGE",
|
||||
[QEVENT_SPICE_MIGRATE_COMPLETED] = "SPICE_MIGRATE_COMPLETED",
|
||||
[QEVENT_GUEST_PANICKED] = "GUEST_PANICKED",
|
||||
[QEVENT_BLOCK_IMAGE_CORRUPTED] = "BLOCK_IMAGE_CORRUPTED",
|
||||
};
|
||||
QEMU_BUILD_BUG_ON(ARRAY_SIZE(monitor_event_names) != QEVENT_MAX)
|
||||
|
||||
|
||||
+13
-6
@@ -57,12 +57,8 @@ typedef struct %(name)sList
|
||||
''',
|
||||
name=name)
|
||||
|
||||
def generate_struct(structname, fieldname, members):
|
||||
ret = mcgen('''
|
||||
struct %(name)s
|
||||
{
|
||||
''',
|
||||
name=structname)
|
||||
def generate_struct_fields(members):
|
||||
ret = ''
|
||||
|
||||
for argname, argentry, optional, structured in parse_args(members):
|
||||
if optional:
|
||||
@@ -80,6 +76,17 @@ struct %(name)s
|
||||
''',
|
||||
c_type=c_type(argentry), c_name=c_var(argname))
|
||||
|
||||
return ret
|
||||
|
||||
def generate_struct(structname, fieldname, members):
|
||||
ret = mcgen('''
|
||||
struct %(name)s
|
||||
{
|
||||
''',
|
||||
name=structname)
|
||||
|
||||
ret += generate_struct_fields(members)
|
||||
|
||||
if len(fieldname):
|
||||
fieldname = " " + fieldname
|
||||
ret += mcgen('''
|
||||
|
||||
@@ -54,7 +54,7 @@ header_length 72
|
||||
|
||||
Header extension:
|
||||
magic 0x6803f857
|
||||
length 96
|
||||
length 144
|
||||
data <binary>
|
||||
|
||||
Header extension:
|
||||
@@ -68,7 +68,7 @@ No errors were found on the image.
|
||||
|
||||
magic 0x514649fb
|
||||
version 2
|
||||
backing_file_offset 0xf8
|
||||
backing_file_offset 0x128
|
||||
backing_file_size 0x17
|
||||
cluster_bits 16
|
||||
size 67108864
|
||||
@@ -92,7 +92,7 @@ data 'host_device'
|
||||
|
||||
Header extension:
|
||||
magic 0x6803f857
|
||||
length 96
|
||||
length 144
|
||||
data <binary>
|
||||
|
||||
Header extension:
|
||||
@@ -155,7 +155,7 @@ header_length 104
|
||||
|
||||
Header extension:
|
||||
magic 0x6803f857
|
||||
length 96
|
||||
length 144
|
||||
data <binary>
|
||||
|
||||
Header extension:
|
||||
@@ -169,7 +169,7 @@ No errors were found on the image.
|
||||
|
||||
magic 0x514649fb
|
||||
version 3
|
||||
backing_file_offset 0x118
|
||||
backing_file_offset 0x148
|
||||
backing_file_size 0x17
|
||||
cluster_bits 16
|
||||
size 67108864
|
||||
@@ -193,7 +193,7 @@ data 'host_device'
|
||||
|
||||
Header extension:
|
||||
magic 0x6803f857
|
||||
length 96
|
||||
length 144
|
||||
data <binary>
|
||||
|
||||
Header extension:
|
||||
|
||||
@@ -46,7 +46,7 @@ header_length 104
|
||||
|
||||
Header extension:
|
||||
magic 0x6803f857
|
||||
length 96
|
||||
length 144
|
||||
data <binary>
|
||||
|
||||
*** done
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user