Revision bfe8043e block/qcow2.c
b/block/qcow2.c | ||
---|---|---|
215 | 215 |
} |
216 | 216 |
|
217 | 217 |
/* |
218 |
* Sets the dirty bit and flushes afterwards if necessary. |
|
219 |
* |
|
220 |
* The incompatible_features bit is only set if the image file header was |
|
221 |
* updated successfully. Therefore it is not required to check the return |
|
222 |
* value of this function. |
|
223 |
*/ |
|
224 |
static int qcow2_mark_dirty(BlockDriverState *bs) |
|
225 |
{ |
|
226 |
BDRVQcowState *s = bs->opaque; |
|
227 |
uint64_t val; |
|
228 |
int ret; |
|
229 |
|
|
230 |
assert(s->qcow_version >= 3); |
|
231 |
|
|
232 |
if (s->incompatible_features & QCOW2_INCOMPAT_DIRTY) { |
|
233 |
return 0; /* already dirty */ |
|
234 |
} |
|
235 |
|
|
236 |
val = cpu_to_be64(s->incompatible_features | QCOW2_INCOMPAT_DIRTY); |
|
237 |
ret = bdrv_pwrite(bs->file, offsetof(QCowHeader, incompatible_features), |
|
238 |
&val, sizeof(val)); |
|
239 |
if (ret < 0) { |
|
240 |
return ret; |
|
241 |
} |
|
242 |
ret = bdrv_flush(bs->file); |
|
243 |
if (ret < 0) { |
|
244 |
return ret; |
|
245 |
} |
|
246 |
|
|
247 |
/* Only treat image as dirty if the header was updated successfully */ |
|
248 |
s->incompatible_features |= QCOW2_INCOMPAT_DIRTY; |
|
249 |
return 0; |
|
250 |
} |
|
251 |
|
|
252 |
/* |
|
218 | 253 |
* Clears the dirty bit and flushes before if necessary. Only call this |
219 | 254 |
* function when there are no pending requests, it does not guard against |
220 | 255 |
* concurrent requests dirtying the image. |
... | ... | |
752 | 787 |
goto fail; |
753 | 788 |
} |
754 | 789 |
|
790 |
if (l2meta.nb_clusters > 0 && |
|
791 |
(s->compatible_features & QCOW2_COMPAT_LAZY_REFCOUNTS)) { |
|
792 |
qcow2_mark_dirty(bs); |
|
793 |
} |
|
794 |
|
|
755 | 795 |
cluster_offset = l2meta.cluster_offset; |
756 | 796 |
assert((cluster_offset & 511) == 0); |
757 | 797 |
|
... | ... | |
994 | 1034 |
.bit = QCOW2_INCOMPAT_DIRTY_BITNR, |
995 | 1035 |
.name = "dirty bit", |
996 | 1036 |
}, |
1037 |
{ |
|
1038 |
.type = QCOW2_FEAT_TYPE_COMPATIBLE, |
|
1039 |
.bit = QCOW2_COMPAT_LAZY_REFCOUNTS_BITNR, |
|
1040 |
.name = "lazy refcounts", |
|
1041 |
}, |
|
997 | 1042 |
}; |
998 | 1043 |
|
999 | 1044 |
ret = header_ext_add(buf, QCOW2_EXT_MAGIC_FEATURE_TABLE, |
... | ... | |
1176 | 1221 |
header.crypt_method = cpu_to_be32(QCOW_CRYPT_NONE); |
1177 | 1222 |
} |
1178 | 1223 |
|
1224 |
if (flags & BLOCK_FLAG_LAZY_REFCOUNTS) { |
|
1225 |
header.compatible_features |= |
|
1226 |
cpu_to_be64(QCOW2_COMPAT_LAZY_REFCOUNTS); |
|
1227 |
} |
|
1228 |
|
|
1179 | 1229 |
ret = bdrv_pwrite(bs, 0, &header, sizeof(header)); |
1180 | 1230 |
if (ret < 0) { |
1181 | 1231 |
goto out; |
... | ... | |
1289 | 1339 |
options->value.s); |
1290 | 1340 |
return -EINVAL; |
1291 | 1341 |
} |
1342 |
} else if (!strcmp(options->name, BLOCK_OPT_LAZY_REFCOUNTS)) { |
|
1343 |
flags |= options->value.n ? BLOCK_FLAG_LAZY_REFCOUNTS : 0; |
|
1292 | 1344 |
} |
1293 | 1345 |
options++; |
1294 | 1346 |
} |
... | ... | |
1299 | 1351 |
return -EINVAL; |
1300 | 1352 |
} |
1301 | 1353 |
|
1354 |
if (version < 3 && (flags & BLOCK_FLAG_LAZY_REFCOUNTS)) { |
|
1355 |
fprintf(stderr, "Lazy refcounts only supported with compatibility " |
|
1356 |
"level 1.1 and above (use compat=1.1 or greater)\n"); |
|
1357 |
return -EINVAL; |
|
1358 |
} |
|
1359 |
|
|
1302 | 1360 |
return qcow2_create2(filename, sectors, backing_file, backing_fmt, flags, |
1303 | 1361 |
cluster_size, prealloc, options, version); |
1304 | 1362 |
} |
... | ... | |
1485 | 1543 |
return ret; |
1486 | 1544 |
} |
1487 | 1545 |
|
1488 |
ret = qcow2_cache_flush(bs, s->refcount_block_cache); |
|
1489 |
if (ret < 0) { |
|
1490 |
qemu_co_mutex_unlock(&s->lock); |
|
1491 |
return ret; |
|
1546 |
if (qcow2_need_accurate_refcounts(s)) { |
|
1547 |
ret = qcow2_cache_flush(bs, s->refcount_block_cache); |
|
1548 |
if (ret < 0) { |
|
1549 |
qemu_co_mutex_unlock(&s->lock); |
|
1550 |
return ret; |
|
1551 |
} |
|
1492 | 1552 |
} |
1493 | 1553 |
qemu_co_mutex_unlock(&s->lock); |
1494 | 1554 |
|
... | ... | |
1603 | 1663 |
.type = OPT_STRING, |
1604 | 1664 |
.help = "Preallocation mode (allowed values: off, metadata)" |
1605 | 1665 |
}, |
1666 |
{ |
|
1667 |
.name = BLOCK_OPT_LAZY_REFCOUNTS, |
|
1668 |
.type = OPT_FLAG, |
|
1669 |
.help = "Postpone refcount updates", |
|
1670 |
}, |
|
1606 | 1671 |
{ NULL } |
1607 | 1672 |
}; |
1608 | 1673 |
|
Also available in: Unified diff