summary refs log tree commit diff stats
diff options
context:
space:
mode:
authorbellard <bellard@c046a42c-6fe2-441c-8c8c-71466251a162>2005-12-18 18:28:15 +0000
committerbellard <bellard@c046a42c-6fe2-441c-8c8c-71466251a162>2005-12-18 18:28:15 +0000
commit95389c8681d4e52f9192fb15e12dba29c6807545 (patch)
tree4a76ad301f9c01366418ff92e60b8a151028e4c9
parent1658b44bf506464cc811e421ac41372ee400371a (diff)
downloadfocaccia-qemu-95389c8681d4e52f9192fb15e12dba29c6807545.tar.gz
focaccia-qemu-95389c8681d4e52f9192fb15e12dba29c6807545.zip
qcow_make_empty() support (Johannes Schindelin)
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1716 c046a42c-6fe2-441c-8c8c-71466251a162
-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 */