All of lore.kernel.org
 help / color / mirror / Atom feed
From: Kevin Wolf <kwolf@redhat.com>
To: "lan,Tianyu" <tianyu.lan@intel.com>
Cc: "penberg@kernel.org" <penberg@kernel.org>,
	"kvm@vger.kernel.org" <kvm@vger.kernel.org>,
	"asias.hejun@gmail.com" <asias.hejun@gmail.com>,
	"levinsasha928@gmail.com" <levinsasha928@gmail.com>,
	"prasadjoshi124@gmail.com" <prasadjoshi124@gmail.com>
Subject: Re: [RFC PATCH] kvm tools, qcow: Add support for growing refcount blocks
Date: Tue, 13 Dec 2011 10:03:25 +0100	[thread overview]
Message-ID: <4EE714DD.5090004@redhat.com> (raw)
In-Reply-To: <1323745557.2585.62.camel@lantianyu-ws>

Am 13.12.2011 04:05, schrieb lan,Tianyu:
> Thanks for your review.
> On 一, 2011-12-12 at 17:55 +0800, Kevin Wolf wrote:
>> Am 12.12.2011 03:03, schrieb Lan Tianyu:
>>> This patch enables allocating new refcount blocks and so then kvm tools
>>> could expand qcow2 image much larger.
>>>
>>> Signed-off-by: Lan Tianyu <tianyu.lan@intel.com>
>>> ---
>>>  tools/kvm/disk/qcow.c |  105 +++++++++++++++++++++++++++++++++++++++++-------
>>>  1 files changed, 89 insertions(+), 16 deletions(-)
>>>
>>> diff --git a/tools/kvm/disk/qcow.c b/tools/kvm/disk/qcow.c
>>> index e139fa5..929ba69 100644
>>> --- a/tools/kvm/disk/qcow.c
>>> +++ b/tools/kvm/disk/qcow.c
>>> @@ -12,6 +12,7 @@
>>>  #include <string.h>
>>>  #include <unistd.h>
>>>  #include <fcntl.h>
>>> +#include <errno.h>
>>>  #ifdef CONFIG_HAS_ZLIB
>>>  #include <zlib.h>
>>>  #endif
>>> @@ -20,6 +21,10 @@
>>>  #include <linux/kernel.h>
>>>  #include <linux/types.h>
>>>  
>>> +static int update_cluster_refcount(struct qcow *q, u64 clust_idx, u16 append);
>>> +static int qcow_write_refcount_table(struct qcow *q);
>>> +static u64 qcow_alloc_clusters(struct qcow *q, u64 size, int update_ref);
>>> +static void  qcow_free_clusters(struct qcow *q, u64 clust_start, u64 size);
>>>  
>>>  static inline int qcow_pwrite_sync(int fd,
>>>  	void *buf, size_t count, off_t offset)
>>> @@ -657,6 +662,56 @@ static struct qcow_refcount_block *refcount_block_search(struct qcow *q, u64 off
>>>  	return rfb;
>>>  }
>>>  
>>> +static struct qcow_refcount_block *qcow_grow_refcount_block(struct qcow *q,
>>> +	u64 clust_idx)
>>> +{
>>> +	struct qcow_header *header = q->header;
>>> +	struct qcow_refcount_table *rft = &q->refcount_table;
>>> +	struct qcow_refcount_block *rfb;
>>> +	u64 new_block_offset;
>>> +	u64 rft_idx;
>>> +
>>> +	rft_idx = clust_idx >> (header->cluster_bits -
>>> +		QCOW_REFCOUNT_BLOCK_SHIFT);
>>> +
>>> +	if (rft_idx >= rft->rf_size) {
>>> +		pr_warning("Don't support grow refcount block table");
>>> +		return NULL;
>>> +	}
>>> +
>>> +	new_block_offset = qcow_alloc_clusters(q, q->cluster_size, 0);
>>> +	if (new_block_offset < 0)
>>> +		return NULL;
>>> +
>>> +	rfb = new_refcount_block(q, new_block_offset);
>>> +	if (!rfb)
>>> +		return NULL;
>>> +
>>> +	memset(rfb->entries, 0x00, q->cluster_size);
>>> +	rfb->dirty = 1;
>>> +
>>> +	/* write refcount block */
>>> +	if (write_refcount_block(q, rfb) < 0)
>>> +		goto free_rfb;
>>> +
>>> +	if (cache_refcount_block(q, rfb) < 0)
>>> +		goto free_rfb;
>>> +
>>> +	rft->rf_table[rft_idx] = cpu_to_be64(new_block_offset);
>>> +	if (qcow_write_refcount_table(q) < 0)
>>> +		goto free_rfb;
>>> +
>>> +	if (update_cluster_refcount(q, new_block_offset >>
>>> +		    header->cluster_bits, 1) < 0)
>>> +		goto free_rfb;
>>
>> This order is unsafe, you could end up with a refcount block that is
>> already in use, but still has a refcount of 0.
> How about following?
> rft->rf_table[rft_idx] = cpu_to_be64(new_block_offset);
> 
> if (update_cluster_refcount(q, new_block_offset >>
> 	header->cluster_bits, 1) < 0) {
> 	rft->rf_table[rft_idx] =  0;
> 	goto free_rfb;
> }
> 
> if (qcow_write_refcount_table(q) < 0) {
> 	rft->rf_table[rft_idx] =  0;
> 	qcow_free_clusters(q, new_block_offset, q->cluster_size);
> 	goto free_rfb;
> }
> 
> update_cluster_refcount() will use the rft->rf_table. So updating the rft->rf_table
> must be before update_cluster_refcount().

Yes, something like this should work.

Kevin

      reply	other threads:[~2011-12-13  9:00 UTC|newest]

Thread overview: 13+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2011-12-12  2:03 [RFC PATCH] kvm tools, qcow: Add support for growing refcount blocks Lan Tianyu
2011-12-12  9:55 ` Kevin Wolf
2011-12-12 10:58   ` Pekka Enberg
2011-12-12 11:15     ` Kevin Wolf
2011-12-12 11:17       ` Kevin Wolf
2011-12-13  3:41       ` lan,Tianyu
2011-12-13  8:57         ` Kevin Wolf
2011-12-13  9:14           ` Pekka Enberg
2011-12-14  1:22           ` lan,Tianyu
2011-12-13  3:16     ` lan,Tianyu
2011-12-13  9:13       ` Pekka Enberg
2011-12-13  3:05   ` lan,Tianyu
2011-12-13  9:03     ` Kevin Wolf [this message]

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=4EE714DD.5090004@redhat.com \
    --to=kwolf@redhat.com \
    --cc=asias.hejun@gmail.com \
    --cc=kvm@vger.kernel.org \
    --cc=levinsasha928@gmail.com \
    --cc=penberg@kernel.org \
    --cc=prasadjoshi124@gmail.com \
    --cc=tianyu.lan@intel.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.