From mboxrd@z Thu Jan 1 00:00:00 1970 Received: from mailman by lists.gnu.org with tmda-scanned (Exim 4.43) id 1HGTr3-0003oH-5F for qemu-devel@nongnu.org; Mon, 12 Feb 2007 00:35:57 -0500 Received: from exim by lists.gnu.org with spam-scanned (Exim 4.43) id 1HGTr2-0003mm-9Q for qemu-devel@nongnu.org; Mon, 12 Feb 2007 00:35:56 -0500 Received: from [199.232.76.173] (helo=monty-python.gnu.org) by lists.gnu.org with esmtp (Exim 4.43) id 1HGTr1-0003mQ-Ti for qemu-devel@nongnu.org; Mon, 12 Feb 2007 00:35:55 -0500 Received: from wasp.net.au ([203.190.192.17]) by monty-python.gnu.org with esmtp (Exim 4.52) id 1HGTr0-00042o-Tr for qemu-devel@nongnu.org; Mon, 12 Feb 2007 00:35:55 -0500 Message-ID: <45CFFCAF.9020800@wasp.net.au> Date: Mon, 12 Feb 2007 09:35:43 +0400 From: Brad Campbell MIME-Version: 1.0 Content-Type: text/plain; charset=ISO-8859-1; format=flowed Content-Transfer-Encoding: 7bit Subject: [Qemu-devel] RFC: No write zero patch with new AIO 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 This is not a real patch, it's been hand edited and badly whitespace damaged to remove some of my braindamaged/commented out debugging code that just muddies things up. Simply posted for comment. I've tested it with WinXP and Ubuntu 6.06 and it appears to do what it's supposed to with no ill effects. I'd like someone familiar with the AIO system to comment if you have time.. particularly the way I'm skipping clusters and ending the AIO transaction. It has been *heavily* tested though. This is a very loose "adaption" of the zero-wipe patch by Frediano.Ziglio@vodafone.com Index: block-qcow2.c =================================================================== RCS file: /cvsroot/qemu/qemu/block-qcow2.c,v retrieving revision 1.4 diff -u -r1.4 block-qcow2.c --- block-qcow2.c 7 Aug 2006 02:38:06 -0000 1.4 +++ block-qcow2.c 12 Feb 2007 05:25:14 -0000 @@ -756,23 +756,58 @@ return 0; } + +static int is_not_zero(const uint8_t *data, int len) +{ + int left; + while (len && (((unsigned int) data) & 3) != 0) { + if (*data++) + return 1; + --len; + } + left = len & 3; + len >>= 2; + while (len) { + if (*((uint32_t *)data) != 0) + return 1; + data += 4; + --len; + } + while (left) { + if (*data++) + return 1; + --left; + } + return 0; +} + + @@ -928,6 +964,7 @@ int index_in_cluster; uint64_t cluster_offset; const uint8_t *src_buf; + int not_zero; acb->hd_aiocb = NULL; @@ -937,29 +974,42 @@ qemu_aio_release(acb); return; } - +next: acb->nb_sectors -= acb->n; acb->sector_num += acb->n; acb->buf += acb->n * 512; if (acb->nb_sectors == 0) { /* request completed */ acb->common.cb(acb->common.opaque, 0); qemu_aio_release(acb); return; } index_in_cluster = acb->sector_num & (s->cluster_sectors - 1); acb->n = s->cluster_sectors - index_in_cluster; if (acb->n > acb->nb_sectors) acb->n = acb->nb_sectors; - cluster_offset = get_cluster_offset(bs, acb->sector_num << 9, 1, 0, + + not_zero = is_not_zero(acb->buf, acb->n * 512); + cluster_offset = get_cluster_offset(bs, acb->sector_num << 9, not_zero, 0, index_in_cluster, index_in_cluster + acb->n); + if (!cluster_offset || (cluster_offset & 511) != 0) { - ret = -EIO; + if (not_zero) + ret = -EIO; + else + if (acb->nb_sectors - acb->n == 0) { + acb->common.cb(acb->common.opaque, 0); + qemu_aio_release(acb); + return; + } + goto next; goto fail; } + if (s->crypt_method) { if (!acb->cluster_data) { acb->cluster_data = qemu_mallocz(s->cluster_size); -- "Human beings, who are almost unique in having the ability to learn from the experience of others, are also remarkable for their apparent disinclination to do so." -- Douglas Adams