+ log_append = qemu_opt_get_bool(opts, "log-append", false);
+
+ if (log_append) {
+ struct log_write_super log_sb = { 0, 0, 0, 0 };
+
+ if (qemu_opt_find(opts, "log-sector-size")) {
+ ret = -EINVAL;
+ error_setg(errp, "log-append and log-sector-size are mutually "
+ "exclusive");
+ goto fail_log;
+ }
+
+ /* Read log superblock or fake one for an empty log */
+ if (!bdrv_getlength(s->log_file->bs)) {
+ log_sb.magic = cpu_to_le64(WRITE_LOG_MAGIC);
+ log_sb.version = cpu_to_le64(WRITE_LOG_VERSION);
+ log_sb.nr_entries = cpu_to_le64(0);
+ log_sb.sectorsize = cpu_to_le32(BDRV_SECTOR_SIZE);
+ } else {
+ ret = bdrv_pread(s->log_file, 0, &log_sb, sizeof(log_sb));
+ if (ret < 0) {
+ error_setg_errno(errp, -ret, "Could not read log superblock");
+ goto fail_log;
+ }
+ }
+
+ if (log_sb.magic != cpu_to_le64(WRITE_LOG_MAGIC)) {
+ ret = -EINVAL;
+ error_setg(errp, "Invalid log superblock magic");
+ goto fail_log;
+ }
+
+ if (log_sb.version != cpu_to_le64(WRITE_LOG_VERSION)) {
+ ret = -EINVAL;
+ error_setg(errp, "Unsupported log version %"PRIu64,
+ le64_to_cpu(log_sb.version));
+ goto fail_log;
+ }
+
+ log_sector_size = le32_to_cpu(log_sb.sectorsize);
+ s->cur_log_sector = 1;
+ s->nr_entries = 0;
+
+ if (blk_log_writes_sector_size_valid(log_sector_size)) {
+ s->cur_log_sector =
+ blk_log_writes_find_cur_log_sector(s->log_file, log_sector_size,
+ le64_to_cpu(log_sb.nr_entries), &local_err);
+ if (local_err) {
+ ret = -EINVAL;
+ error_propagate(errp, local_err);
+ goto fail_log;
+ }
+
+ s->nr_entries = le64_to_cpu(log_sb.nr_entries);
+ }
+ } else {
+ log_sector_size = qemu_opt_get_size(opts, "log-sector-size",
+ BDRV_SECTOR_SIZE);
+ s->cur_log_sector = 1;
+ s->nr_entries = 0;
+ }
+
+ if (!blk_log_writes_sector_size_valid(log_sector_size)) {
+ ret = -EINVAL;
+ error_setg(errp, "Invalid log sector size %"PRIu64, log_sector_size);
+ goto fail_log;
+ }
+
+ s->sectorsize = log_sector_size;
+ s->sectorbits = blk_log_writes_log2(log_sector_size);
+