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