From mboxrd@z Thu Jan 1 00:00:00 1970 Received: from mailman by lists.gnu.org with tmda-scanned (Exim 4.43) id 1KThGR-0002xD-IP for qemu-devel@nongnu.org; Thu, 14 Aug 2008 14:09:35 -0400 Received: from exim by lists.gnu.org with spam-scanned (Exim 4.43) id 1KThGQ-0002wG-Nc for qemu-devel@nongnu.org; Thu, 14 Aug 2008 14:09:35 -0400 Received: from [199.232.76.173] (port=59427 helo=monty-python.gnu.org) by lists.gnu.org with esmtp (Exim 4.43) id 1KThGQ-0002wA-H5 for qemu-devel@nongnu.org; Thu, 14 Aug 2008 14:09:34 -0400 Received: from savannah.gnu.org ([199.232.41.3]:52012 helo=sv.gnu.org) by monty-python.gnu.org with esmtps (TLS-1.0:RSA_AES_256_CBC_SHA1:32) (Exim 4.60) (envelope-from ) id 1KThGP-0000ZO-Uk for qemu-devel@nongnu.org; Thu, 14 Aug 2008 14:09:34 -0400 Received: from cvs.savannah.gnu.org ([199.232.41.69]) by sv.gnu.org with esmtp (Exim 4.63) (envelope-from ) id 1KThGP-0001yf-4J for qemu-devel@nongnu.org; Thu, 14 Aug 2008 18:09:33 +0000 Received: from aliguori by cvs.savannah.gnu.org with local (Exim 4.63) (envelope-from ) id 1KThGO-0001ya-Uz for qemu-devel@nongnu.org; Thu, 14 Aug 2008 18:09:33 +0000 MIME-Version: 1.0 Errors-To: aliguori Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit From: Anthony Liguori Message-Id: Date: Thu, 14 Aug 2008 18:09:32 +0000 Subject: [Qemu-devel] [5005] Extract compressing part from alloc_cluster_offset() (Laurent Vivier ) Reply-To: qemu-devel@nongnu.org List-Id: qemu-devel.nongnu.org List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , To: qemu-devel@nongnu.org Revision: 5005 http://svn.sv.gnu.org/viewvc/?view=rev&root=qemu&revision=5005 Author: aliguori Date: 2008-08-14 18:09:32 +0000 (Thu, 14 Aug 2008) Log Message: ----------- Extract compressing part from alloc_cluster_offset() (Laurent Vivier) Divide alloc_cluster_offset() into alloc_cluster_offset() and alloc_compressed_cluster_offset(). Common parts are moved to free_any_clusters() and get_cluster_table(); Signed-off-by: Laurent Vivier Signed-off-by: Anthony Liguori Modified Paths: -------------- trunk/block-qcow2.c Modified: trunk/block-qcow2.c =================================================================== --- trunk/block-qcow2.c 2008-08-14 18:08:21 UTC (rev 5004) +++ trunk/block-qcow2.c 2008-08-14 18:09:32 UTC (rev 5005) @@ -652,26 +652,53 @@ } /* - * alloc_cluster_offset + * free_any_clusters * - * For a given offset of the disk image, return cluster offset in - * qcow2 file. + * free clusters according to its type: compressed or not * - * If the offset is not found, allocate a new cluster. + */ + +static void free_any_clusters(BlockDriverState *bs, + uint64_t cluster_offset) +{ + BDRVQcowState *s = bs->opaque; + + if (cluster_offset == 0) + return; + + /* free the cluster */ + + if (cluster_offset & QCOW_OFLAG_COMPRESSED) { + int nb_csectors; + nb_csectors = ((cluster_offset >> s->csize_shift) & + s->csize_mask) + 1; + free_clusters(bs, (cluster_offset & s->cluster_offset_mask) & ~511, + nb_csectors * 512); + return; + } + + free_clusters(bs, cluster_offset, s->cluster_size); +} + +/* + * get_cluster_table * - * Return the cluster offset if successful, - * Return 0, otherwise. + * for a given disk offset, load (and allocate if needed) + * the l2 table. * + * the l2 table offset in the qcow2 file and the cluster index + * in the l2 table are given to the caller. + * */ -static uint64_t alloc_cluster_offset(BlockDriverState *bs, - uint64_t offset, - int compressed_size, - int n_start, int n_end) +static int get_cluster_table(BlockDriverState *bs, uint64_t offset, + uint64_t **new_l2_table, + uint64_t *new_l2_offset, + int *new_l2_index) { BDRVQcowState *s = bs->opaque; int l1_index, l2_index, ret; - uint64_t l2_offset, *l2_table, cluster_offset; + uint64_t l2_offset, *l2_table; /* seek the the l2 offset in the l1 table */ @@ -703,48 +730,98 @@ /* find the cluster offset for the given disk offset */ l2_index = (offset >> s->cluster_bits) & (s->l2_size - 1); + + *new_l2_table = l2_table; + *new_l2_offset = l2_offset; + *new_l2_index = l2_index; + + return 1; +} + +/* + * alloc_compressed_cluster_offset + * + * For a given offset of the disk image, return cluster offset in + * qcow2 file. + * + * If the offset is not found, allocate a new compressed cluster. + * + * Return the cluster offset if successful, + * Return 0, otherwise. + * + */ + +static uint64_t alloc_compressed_cluster_offset(BlockDriverState *bs, + uint64_t offset, + int compressed_size) +{ + BDRVQcowState *s = bs->opaque; + int l2_index, ret; + uint64_t l2_offset, *l2_table, cluster_offset; + int nb_csectors; + + ret = get_cluster_table(bs, offset, &l2_table, &l2_offset, &l2_index); + if (ret == 0) + return 0; + cluster_offset = be64_to_cpu(l2_table[l2_index]); - if (cluster_offset & QCOW_OFLAG_COPIED) return cluster_offset & ~QCOW_OFLAG_COPIED; - if (cluster_offset) { - /* free the cluster */ - if (cluster_offset & QCOW_OFLAG_COMPRESSED) { - int nb_csectors; - nb_csectors = ((cluster_offset >> s->csize_shift) & - s->csize_mask) + 1; - free_clusters(bs, (cluster_offset & s->cluster_offset_mask) & ~511, - nb_csectors * 512); - } else { - free_clusters(bs, cluster_offset, s->cluster_size); - } - } + free_any_clusters(bs, cluster_offset); - if (compressed_size) { - int nb_csectors; + cluster_offset = alloc_bytes(bs, compressed_size); + nb_csectors = ((cluster_offset + compressed_size - 1) >> 9) - + (cluster_offset >> 9); - cluster_offset = alloc_bytes(bs, compressed_size); - nb_csectors = ((cluster_offset + compressed_size - 1) >> 9) - - (cluster_offset >> 9); + cluster_offset |= QCOW_OFLAG_COMPRESSED | + ((uint64_t)nb_csectors << s->csize_shift); - cluster_offset |= QCOW_OFLAG_COMPRESSED | - ((uint64_t)nb_csectors << s->csize_shift); + /* update L2 table */ - /* update L2 table */ + /* compressed clusters never have the copied flag */ - /* compressed clusters never have the copied flag */ + l2_table[l2_index] = cpu_to_be64(cluster_offset); + if (bdrv_pwrite(s->hd, + l2_offset + l2_index * sizeof(uint64_t), + l2_table + l2_index, + sizeof(uint64_t)) != sizeof(uint64_t)) + return 0; - l2_table[l2_index] = cpu_to_be64(cluster_offset); - if (bdrv_pwrite(s->hd, - l2_offset + l2_index * sizeof(uint64_t), - l2_table + l2_index, - sizeof(uint64_t)) != sizeof(uint64_t)) - return 0; + return cluster_offset; +} - return cluster_offset; - } +/* + * alloc_cluster_offset + * + * For a given offset of the disk image, return cluster offset in + * qcow2 file. + * + * If the offset is not found, allocate a new cluster. + * + * Return the cluster offset if successful, + * Return 0, otherwise. + * + */ +static uint64_t alloc_cluster_offset(BlockDriverState *bs, + uint64_t offset, + int n_start, int n_end) +{ + BDRVQcowState *s = bs->opaque; + int l2_index, ret; + uint64_t l2_offset, *l2_table, cluster_offset; + + ret = get_cluster_table(bs, offset, &l2_table, &l2_offset, &l2_index); + if (ret == 0) + return 0; + + cluster_offset = be64_to_cpu(l2_table[l2_index]); + if (cluster_offset & QCOW_OFLAG_COPIED) + return cluster_offset & ~QCOW_OFLAG_COPIED; + + free_any_clusters(bs, cluster_offset); + /* allocate a new cluster */ cluster_offset = alloc_clusters(bs, s->cluster_size); @@ -916,7 +993,7 @@ n = s->cluster_sectors - index_in_cluster; if (n > nb_sectors) n = nb_sectors; - cluster_offset = alloc_cluster_offset(bs, sector_num << 9, 0, + cluster_offset = alloc_cluster_offset(bs, sector_num << 9, index_in_cluster, index_in_cluster + n); if (!cluster_offset) @@ -1100,7 +1177,7 @@ acb->n = s->cluster_sectors - index_in_cluster; if (acb->n > acb->nb_sectors) acb->n = acb->nb_sectors; - cluster_offset = alloc_cluster_offset(bs, acb->sector_num << 9, 0, + cluster_offset = alloc_cluster_offset(bs, acb->sector_num << 9, index_in_cluster, index_in_cluster + acb->n); if (!cluster_offset || (cluster_offset & 511) != 0) { @@ -1362,8 +1439,10 @@ /* could not compress: write normal cluster */ qcow_write(bs, sector_num, buf, s->cluster_sectors); } else { - cluster_offset = alloc_cluster_offset(bs, sector_num << 9, - out_len, 0, 0); + cluster_offset = alloc_compressed_cluster_offset(bs, sector_num << 9, + out_len); + if (!cluster_offset) + return -1; cluster_offset &= s->cluster_offset_mask; if (bdrv_pwrite(s->hd, cluster_offset, out_buf, out_len) != out_len) { qemu_free(out_buf);