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. > + /* 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.