qemu-devel
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: [Qemu-devel] [RFC PATCH v4 4/4] qcow2: Add full image preallocation


From: Hu Tao
Subject: Re: [Qemu-devel] [RFC PATCH v4 4/4] qcow2: Add full image preallocation option
Date: Mon, 20 Jan 2014 10:16:23 +0800
User-agent: Mutt/1.5.21 (2010-09-15)

Stefan, 

On Fri, Jan 17, 2014 at 04:48:16PM +0800, Stefan Hajnoczi wrote:
> On Fri, Dec 27, 2013 at 11:05:54AM +0800, Hu Tao wrote:
> 
> This approach seems okay but the calculation isn't quite right yet.
> 
> On Windows an error would be raised since we don't have preallocate=full
> support.  That's okay.
> 
> > @@ -1477,16 +1478,53 @@ static int qcow2_create2(const char *filename, 
> > int64_t total_size,
> >      Error *local_err = NULL;
> >      int ret;
> >  
> > +    if (prealloc == PREALLOC_MODE_FULL) {
> > +        int64_t meta_size = 0;
> > +        unsigned nrefe, nl2e;
> > +        BlockDriver *drv;
> > +
> > +        drv = bdrv_find_protocol(filename, true);
> > +        if (drv == NULL) {
> > +            error_setg(errp, "Could not find protocol for file '%s'", 
> > filename);
> > +            return -ENOENT;
> > +        }
> > +
> > +        alloc_options = append_option_parameters(alloc_options,
> > +                                                 drv->create_options);
> > +        alloc_options = append_option_parameters(alloc_options, options);
> > +
> > +        /* header: 1 cluster */
> > +        meta_size += cluster_size;
> > +        /* total size of refblocks */
> > +        nrefe = (total_size / cluster_size);
> > +        nrefe = align_offset(nrefe, cluster_size / sizeof(uint16_t));
> > +        meta_size += nrefe * sizeof(uint16_t);
> 
> Every host cluster is reference-counted, including metadata (even
> refcount blocks are recursively included).  This calculation is wrong
> because it only considers data clusters.

Right. I'll fix this.

> 
> > +        /* total size of reftables */
> > +        meta_size += nrefe * sizeof(uint16_t) * sizeof(uint16_t) / 
> > cluster_size;
> 
> I don't understand this calculation.  The refcount table consists of
> contiguous clusters where each element is a 64-bit offset to a refcount
> block.
> 
> > +        /* total size of L2 tables */
> > +        nl2e = total_size / cluster_size;
> > +        nl2e = align_offset(nl2e, cluster_size / sizeof(uint64_t));
> > +        meta_size += nl2e * sizeof(uint64_t);
> > +        /* total size of L1 tables */
> > +        meta_size += nl2e * sizeof(uint64_t) * sizeof(uint64_t) / 
> > cluster_size;
> 
> Another strange calculation.  The L1 table consists of contiguous
> clusters where each element is a 64-bit offset to an L1 table.

I guest you mean "...offset to an L2 table" here.

Given the number of total L2 table entries nl2e, the number of L2 tables
is:

  nl2table = nl2e * sizeof(l2e) / cluster_size

because each L1 table entry points to a L2 table, so this is also the
number of L1 table entries. So the total size of L1 tables is:

  l1table_size = nl2table * sizeof(l1e)
               = nl2e * sizeof(l2e) * sizeof(l1e) / cluster_size
               = nl2e * sizeof(uint64_t) * sizeof(uint64_t) / cluster_size

I still can't see what's wrong here. But you're welcome to fix me.


The caculation of reftable size above is wrong because of the two problem
you've pointed out. Thanks!



reply via email to

[Prev in Thread] Current Thread [Next in Thread]