summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--block-qcow.c58
-rw-r--r--block.c16
-rw-r--r--block_int.h3
3 files changed, 56 insertions, 21 deletions
diff --git a/block-qcow.c b/block-qcow.c
index ca05be88b0..34026a4f2c 100644
--- a/block-qcow.c
+++ b/block-qcow.c
@@ -552,25 +552,28 @@ static int qcow_create(const char *filename, int64_t total_size,
header_size = sizeof(header);
backing_filename_len = 0;
if (backing_file) {
- const char *p;
- /* XXX: this is a hack: we do not attempt to check for URL
- like syntax */
- p = strchr(backing_file, ':');
- if (p && (p - backing_file) >= 2) {
- /* URL like but exclude "c:" like filenames */
- pstrcpy(backing_filename, sizeof(backing_filename),
- backing_file);
- } else {
- realpath(backing_file, backing_filename);
- if (stat(backing_filename, &st) != 0) {
- return -1;
- }
- }
+ if (strcmp(backing_file, "fat:")) {
+ const char *p;
+ /* XXX: this is a hack: we do not attempt to check for URL
+ like syntax */
+ p = strchr(backing_file, ':');
+ if (p && (p - backing_file) >= 2) {
+ /* URL like but exclude "c:" like filenames */
+ pstrcpy(backing_filename, sizeof(backing_filename),
+ backing_file);
+ } else {
+ realpath(backing_file, backing_filename);
+ if (stat(backing_filename, &st) != 0) {
+ return -1;
+ }
+ }
+ header.backing_file_offset = cpu_to_be64(header_size);
+ backing_filename_len = strlen(backing_filename);
+ header.backing_file_size = cpu_to_be32(backing_filename_len);
+ header_size += backing_filename_len;
+ } else
+ backing_file = NULL;
header.mtime = cpu_to_be32(st.st_mtime);
- header.backing_file_offset = cpu_to_be64(header_size);
- backing_filename_len = strlen(backing_filename);
- header.backing_file_size = cpu_to_be32(backing_filename_len);
- header_size += backing_filename_len;
header.cluster_bits = 9; /* 512 byte cluster to avoid copying
unmodifyed sectors */
header.l2_bits = 12; /* 32 KB L2 tables */
@@ -603,6 +606,24 @@ static int qcow_create(const char *filename, int64_t total_size,
return 0;
}
+int qcow_make_empty(BlockDriverState *bs)
+{
+ BDRVQcowState *s = bs->opaque;
+ uint32_t l1_length = s->l1_size * sizeof(uint64_t);
+
+ memset(s->l1_table, 0, l1_length);
+ lseek(s->fd, s->l1_table_offset, SEEK_SET);
+ if (write(s->fd, s->l1_table, l1_length) < 0)
+ return -1;
+ ftruncate(s->fd, s->l1_table_offset + l1_length);
+
+ memset(s->l2_cache, 0, s->l2_size * L2_CACHE_SIZE * sizeof(uint64_t));
+ memset(s->l2_cache_offsets, 0, L2_CACHE_SIZE * sizeof(uint64_t));
+ memset(s->l2_cache_counts, 0, L2_CACHE_SIZE * sizeof(uint32_t));
+
+ return 0;
+}
+
int qcow_get_cluster_size(BlockDriverState *bs)
{
BDRVQcowState *s = bs->opaque;
@@ -683,6 +704,7 @@ BlockDriver bdrv_qcow = {
qcow_create,
qcow_is_allocated,
qcow_set_key,
+ qcow_make_empty
};
diff --git a/block.c b/block.c
index efd96e637f..6924cee67d 100644
--- a/block.c
+++ b/block.c
@@ -150,13 +150,19 @@ int bdrv_create(BlockDriver *drv,
}
#ifdef _WIN32
-static void get_tmp_filename(char *filename, int size)
+void get_tmp_filename(char *filename, int size)
{
+ char* p = strrchr(filename, '/');
+
+ if (p == NULL)
+ return;
+
/* XXX: find a better function */
- tmpnam(filename);
+ tmpnam(p);
+ *p = '/';
}
#else
-static void get_tmp_filename(char *filename, int size)
+void get_tmp_filename(char *filename, int size)
{
int fd;
/* XXX: race condition possible */
@@ -394,6 +400,10 @@ int bdrv_commit(BlockDriverState *bs)
i += n;
}
}
+
+ if (bs->drv->bdrv_make_empty)
+ return bs->drv->bdrv_make_empty(bs);
+
return 0;
}
diff --git a/block_int.h b/block_int.h
index 03744f7340..e3038160e6 100644
--- a/block_int.h
+++ b/block_int.h
@@ -39,6 +39,7 @@ struct BlockDriver {
int (*bdrv_is_allocated)(BlockDriverState *bs, int64_t sector_num,
int nb_sectors, int *pnum);
int (*bdrv_set_key)(BlockDriverState *bs, const char *key);
+ int (*bdrv_make_empty)(BlockDriverState *bs);
struct BlockDriver *next;
};
@@ -74,4 +75,6 @@ struct BlockDriverState {
BlockDriverState *next;
};
+void get_tmp_filename(char *filename, int size);
+
#endif /* BLOCK_INT_H */