1 /* 2 * Replication Block filter 3 * 4 * Copyright (c) 2016 HUAWEI TECHNOLOGIES CO., LTD. 5 * Copyright (c) 2016 Intel Corporation 6 * Copyright (c) 2016 FUJITSU LIMITED 7 * 8 * Author: 9 * Wen Congyang <wency@cn.fujitsu.com> 10 * 11 * This work is licensed under the terms of the GNU GPL, version 2 or later. 12 * See the COPYING file in the top-level directory. 13 */ 14 15 #include "qemu/osdep.h" 16 #include "qemu/module.h" 17 #include "qemu/option.h" 18 #include "block/nbd.h" 19 #include "block/blockjob.h" 20 #include "block/block_int.h" 21 #include "block/block_backup.h" 22 #include "sysemu/block-backend.h" 23 #include "qapi/error.h" 24 #include "qapi/qmp/qdict.h" 25 #include "replication.h" 26 27 typedef enum { 28 BLOCK_REPLICATION_NONE, /* block replication is not started */ 29 BLOCK_REPLICATION_RUNNING, /* block replication is running */ 30 BLOCK_REPLICATION_FAILOVER, /* failover is running in background */ 31 BLOCK_REPLICATION_FAILOVER_FAILED, /* failover failed */ 32 BLOCK_REPLICATION_DONE, /* block replication is done */ 33 } ReplicationStage; 34 35 typedef struct BDRVReplicationState { 36 ReplicationMode mode; 37 ReplicationStage stage; 38 BdrvChild *active_disk; 39 BlockJob *commit_job; 40 BdrvChild *hidden_disk; 41 BdrvChild *secondary_disk; 42 BlockJob *backup_job; 43 char *top_id; 44 ReplicationState *rs; 45 Error *blocker; 46 bool orig_hidden_read_only; 47 bool orig_secondary_read_only; 48 int error; 49 } BDRVReplicationState; 50 51 static void replication_start(ReplicationState *rs, ReplicationMode mode, 52 Error **errp); 53 static void replication_do_checkpoint(ReplicationState *rs, Error **errp); 54 static void replication_get_error(ReplicationState *rs, Error **errp); 55 static void replication_stop(ReplicationState *rs, bool failover, 56 Error **errp); 57 58 #define REPLICATION_MODE "mode" 59 #define REPLICATION_TOP_ID "top-id" 60 static QemuOptsList replication_runtime_opts = { 61 .name = "replication", 62 .head = QTAILQ_HEAD_INITIALIZER(replication_runtime_opts.head), 63 .desc = { 64 { 65 .name = REPLICATION_MODE, 66 .type = QEMU_OPT_STRING, 67 }, 68 { 69 .name = REPLICATION_TOP_ID, 70 .type = QEMU_OPT_STRING, 71 }, 72 { /* end of list */ } 73 }, 74 }; 75 76 static ReplicationOps replication_ops = { 77 .start = replication_start, 78 .checkpoint = replication_do_checkpoint, 79 .get_error = replication_get_error, 80 .stop = replication_stop, 81 }; 82 83 static int replication_open(BlockDriverState *bs, QDict *options, 84 int flags, Error **errp) 85 { 86 int ret; 87 BDRVReplicationState *s = bs->opaque; 88 Error *local_err = NULL; 89 QemuOpts *opts = NULL; 90 const char *mode; 91 const char *top_id; 92 93 bs->file = bdrv_open_child(NULL, options, "file", bs, &child_file, 94 false, errp); 95 if (!bs->file) { 96 return -EINVAL; 97 } 98 99 ret = -EINVAL; 100 opts = qemu_opts_create(&replication_runtime_opts, NULL, 0, &error_abort); 101 qemu_opts_absorb_qdict(opts, options, &local_err); 102 if (local_err) { 103 goto fail; 104 } 105 106 mode = qemu_opt_get(opts, REPLICATION_MODE); 107 if (!mode) { 108 error_setg(&local_err, "Missing the option mode"); 109 goto fail; 110 } 111 112 if (!strcmp(mode, "primary")) { 113 s->mode = REPLICATION_MODE_PRIMARY; 114 top_id = qemu_opt_get(opts, REPLICATION_TOP_ID); 115 if (top_id) { 116 error_setg(&local_err, "The primary side does not support option top-id"); 117 goto fail; 118 } 119 } else if (!strcmp(mode, "secondary")) { 120 s->mode = REPLICATION_MODE_SECONDARY; 121 top_id = qemu_opt_get(opts, REPLICATION_TOP_ID); 122 s->top_id = g_strdup(top_id); 123 if (!s->top_id) { 124 error_setg(&local_err, "Missing the option top-id"); 125 goto fail; 126 } 127 } else { 128 error_setg(&local_err, 129 "The option mode's value should be primary or secondary"); 130 goto fail; 131 } 132 133 s->rs = replication_new(bs, &replication_ops); 134 135 ret = 0; 136 137 fail: 138 qemu_opts_del(opts); 139 error_propagate(errp, local_err); 140 141 return ret; 142 } 143 144 static void replication_close(BlockDriverState *bs) 145 { 146 BDRVReplicationState *s = bs->opaque; 147 Job *commit_job; 148 149 if (s->stage == BLOCK_REPLICATION_RUNNING) { 150 replication_stop(s->rs, false, NULL); 151 } 152 if (s->stage == BLOCK_REPLICATION_FAILOVER) { 153 commit_job = &s->commit_job->job; 154 assert(commit_job->aio_context == qemu_get_current_aio_context()); 155 job_cancel_sync(commit_job); 156 } 157 158 if (s->mode == REPLICATION_MODE_SECONDARY) { 159 g_free(s->top_id); 160 } 161 162 replication_remove(s->rs); 163 } 164 165 static void replication_child_perm(BlockDriverState *bs, BdrvChild *c, 166 const BdrvChildRole *role, 167 BlockReopenQueue *reopen_queue, 168 uint64_t perm, uint64_t shared, 169 uint64_t *nperm, uint64_t *nshared) 170 { 171 *nperm = BLK_PERM_CONSISTENT_READ; 172 if ((bs->open_flags & (BDRV_O_INACTIVE | BDRV_O_RDWR)) == BDRV_O_RDWR) { 173 *nperm |= BLK_PERM_WRITE; 174 } 175 *nshared = BLK_PERM_CONSISTENT_READ 176 | BLK_PERM_WRITE 177 | BLK_PERM_WRITE_UNCHANGED; 178 return; 179 } 180 181 static int64_t replication_getlength(BlockDriverState *bs) 182 { 183 return bdrv_getlength(bs->file->bs); 184 } 185 186 static int replication_get_io_status(BDRVReplicationState *s) 187 { 188 switch (s->stage) { 189 case BLOCK_REPLICATION_NONE: 190 return -EIO; 191 case BLOCK_REPLICATION_RUNNING: 192 return 0; 193 case BLOCK_REPLICATION_FAILOVER: 194 return s->mode == REPLICATION_MODE_PRIMARY ? -EIO : 0; 195 case BLOCK_REPLICATION_FAILOVER_FAILED: 196 return s->mode == REPLICATION_MODE_PRIMARY ? -EIO : 1; 197 case BLOCK_REPLICATION_DONE: 198 /* 199 * active commit job completes, and active disk and secondary_disk 200 * is swapped, so we can operate bs->file directly 201 */ 202 return s->mode == REPLICATION_MODE_PRIMARY ? -EIO : 0; 203 default: 204 abort(); 205 } 206 } 207 208 static int replication_return_value(BDRVReplicationState *s, int ret) 209 { 210 if (s->mode == REPLICATION_MODE_SECONDARY) { 211 return ret; 212 } 213 214 if (ret < 0) { 215 s->error = ret; 216 ret = 0; 217 } 218 219 return ret; 220 } 221 222 static coroutine_fn int replication_co_readv(BlockDriverState *bs, 223 int64_t sector_num, 224 int remaining_sectors, 225 QEMUIOVector *qiov) 226 { 227 BDRVReplicationState *s = bs->opaque; 228 int ret; 229 230 if (s->mode == REPLICATION_MODE_PRIMARY) { 231 /* We only use it to forward primary write requests */ 232 return -EIO; 233 } 234 235 ret = replication_get_io_status(s); 236 if (ret < 0) { 237 return ret; 238 } 239 240 ret = bdrv_co_preadv(bs->file, sector_num * BDRV_SECTOR_SIZE, 241 remaining_sectors * BDRV_SECTOR_SIZE, qiov, 0); 242 243 return replication_return_value(s, ret); 244 } 245 246 static coroutine_fn int replication_co_writev(BlockDriverState *bs, 247 int64_t sector_num, 248 int remaining_sectors, 249 QEMUIOVector *qiov, 250 int flags) 251 { 252 BDRVReplicationState *s = bs->opaque; 253 QEMUIOVector hd_qiov; 254 uint64_t bytes_done = 0; 255 BdrvChild *top = bs->file; 256 BdrvChild *base = s->secondary_disk; 257 BdrvChild *target; 258 int ret; 259 int64_t n; 260 261 assert(!flags); 262 ret = replication_get_io_status(s); 263 if (ret < 0) { 264 goto out; 265 } 266 267 if (ret == 0) { 268 ret = bdrv_co_pwritev(top, sector_num * BDRV_SECTOR_SIZE, 269 remaining_sectors * BDRV_SECTOR_SIZE, qiov, 0); 270 return replication_return_value(s, ret); 271 } 272 273 /* 274 * Failover failed, only write to active disk if the sectors 275 * have already been allocated in active disk/hidden disk. 276 */ 277 qemu_iovec_init(&hd_qiov, qiov->niov); 278 while (remaining_sectors > 0) { 279 int64_t count; 280 281 ret = bdrv_is_allocated_above(top->bs, base->bs, false, 282 sector_num * BDRV_SECTOR_SIZE, 283 remaining_sectors * BDRV_SECTOR_SIZE, 284 &count); 285 if (ret < 0) { 286 goto out1; 287 } 288 289 assert(QEMU_IS_ALIGNED(count, BDRV_SECTOR_SIZE)); 290 n = count >> BDRV_SECTOR_BITS; 291 qemu_iovec_reset(&hd_qiov); 292 qemu_iovec_concat(&hd_qiov, qiov, bytes_done, count); 293 294 target = ret ? top : base; 295 ret = bdrv_co_pwritev(target, sector_num * BDRV_SECTOR_SIZE, 296 n * BDRV_SECTOR_SIZE, &hd_qiov, 0); 297 if (ret < 0) { 298 goto out1; 299 } 300 301 remaining_sectors -= n; 302 sector_num += n; 303 bytes_done += count; 304 } 305 306 out1: 307 qemu_iovec_destroy(&hd_qiov); 308 out: 309 return ret; 310 } 311 312 static void secondary_do_checkpoint(BDRVReplicationState *s, Error **errp) 313 { 314 Error *local_err = NULL; 315 int ret; 316 317 if (!s->backup_job) { 318 error_setg(errp, "Backup job was cancelled unexpectedly"); 319 return; 320 } 321 322 backup_do_checkpoint(s->backup_job, &local_err); 323 if (local_err) { 324 error_propagate(errp, local_err); 325 return; 326 } 327 328 if (!s->active_disk->bs->drv) { 329 error_setg(errp, "Active disk %s is ejected", 330 s->active_disk->bs->node_name); 331 return; 332 } 333 334 ret = s->active_disk->bs->drv->bdrv_make_empty(s->active_disk->bs); 335 if (ret < 0) { 336 error_setg(errp, "Cannot make active disk empty"); 337 return; 338 } 339 340 if (!s->hidden_disk->bs->drv) { 341 error_setg(errp, "Hidden disk %s is ejected", 342 s->hidden_disk->bs->node_name); 343 return; 344 } 345 346 ret = s->hidden_disk->bs->drv->bdrv_make_empty(s->hidden_disk->bs); 347 if (ret < 0) { 348 error_setg(errp, "Cannot make hidden disk empty"); 349 return; 350 } 351 } 352 353 /* This function is supposed to be called twice: 354 * first with writable = true, then with writable = false. 355 * The first call puts s->hidden_disk and s->secondary_disk in 356 * r/w mode, and the second puts them back in their original state. 357 */ 358 static void reopen_backing_file(BlockDriverState *bs, bool writable, 359 Error **errp) 360 { 361 BDRVReplicationState *s = bs->opaque; 362 BlockReopenQueue *reopen_queue = NULL; 363 Error *local_err = NULL; 364 365 if (writable) { 366 s->orig_hidden_read_only = bdrv_is_read_only(s->hidden_disk->bs); 367 s->orig_secondary_read_only = bdrv_is_read_only(s->secondary_disk->bs); 368 } 369 370 bdrv_subtree_drained_begin(s->hidden_disk->bs); 371 bdrv_subtree_drained_begin(s->secondary_disk->bs); 372 373 if (s->orig_hidden_read_only) { 374 QDict *opts = qdict_new(); 375 qdict_put_bool(opts, BDRV_OPT_READ_ONLY, !writable); 376 reopen_queue = bdrv_reopen_queue(reopen_queue, s->hidden_disk->bs, 377 opts, true); 378 } 379 380 if (s->orig_secondary_read_only) { 381 QDict *opts = qdict_new(); 382 qdict_put_bool(opts, BDRV_OPT_READ_ONLY, !writable); 383 reopen_queue = bdrv_reopen_queue(reopen_queue, s->secondary_disk->bs, 384 opts, true); 385 } 386 387 if (reopen_queue) { 388 bdrv_reopen_multiple(reopen_queue, &local_err); 389 error_propagate(errp, local_err); 390 } 391 392 bdrv_subtree_drained_end(s->hidden_disk->bs); 393 bdrv_subtree_drained_end(s->secondary_disk->bs); 394 } 395 396 static void backup_job_cleanup(BlockDriverState *bs) 397 { 398 BDRVReplicationState *s = bs->opaque; 399 BlockDriverState *top_bs; 400 401 top_bs = bdrv_lookup_bs(s->top_id, s->top_id, NULL); 402 if (!top_bs) { 403 return; 404 } 405 bdrv_op_unblock_all(top_bs, s->blocker); 406 error_free(s->blocker); 407 reopen_backing_file(bs, false, NULL); 408 } 409 410 static void backup_job_completed(void *opaque, int ret) 411 { 412 BlockDriverState *bs = opaque; 413 BDRVReplicationState *s = bs->opaque; 414 415 if (s->stage != BLOCK_REPLICATION_FAILOVER) { 416 /* The backup job is cancelled unexpectedly */ 417 s->error = -EIO; 418 } 419 420 backup_job_cleanup(bs); 421 } 422 423 static bool check_top_bs(BlockDriverState *top_bs, BlockDriverState *bs) 424 { 425 BdrvChild *child; 426 427 /* The bs itself is the top_bs */ 428 if (top_bs == bs) { 429 return true; 430 } 431 432 /* Iterate over top_bs's children */ 433 QLIST_FOREACH(child, &top_bs->children, next) { 434 if (child->bs == bs || check_top_bs(child->bs, bs)) { 435 return true; 436 } 437 } 438 439 return false; 440 } 441 442 static void replication_start(ReplicationState *rs, ReplicationMode mode, 443 Error **errp) 444 { 445 BlockDriverState *bs = rs->opaque; 446 BDRVReplicationState *s; 447 BlockDriverState *top_bs; 448 int64_t active_length, hidden_length, disk_length; 449 AioContext *aio_context; 450 Error *local_err = NULL; 451 452 aio_context = bdrv_get_aio_context(bs); 453 aio_context_acquire(aio_context); 454 s = bs->opaque; 455 456 if (s->stage == BLOCK_REPLICATION_DONE || 457 s->stage == BLOCK_REPLICATION_FAILOVER) { 458 /* 459 * This case happens when a secondary is promoted to primary. 460 * Ignore the request because the secondary side of replication 461 * doesn't have to do anything anymore. 462 */ 463 aio_context_release(aio_context); 464 return; 465 } 466 467 if (s->stage != BLOCK_REPLICATION_NONE) { 468 error_setg(errp, "Block replication is running or done"); 469 aio_context_release(aio_context); 470 return; 471 } 472 473 if (s->mode != mode) { 474 error_setg(errp, "The parameter mode's value is invalid, needs %d," 475 " but got %d", s->mode, mode); 476 aio_context_release(aio_context); 477 return; 478 } 479 480 switch (s->mode) { 481 case REPLICATION_MODE_PRIMARY: 482 break; 483 case REPLICATION_MODE_SECONDARY: 484 s->active_disk = bs->file; 485 if (!s->active_disk || !s->active_disk->bs || 486 !s->active_disk->bs->backing) { 487 error_setg(errp, "Active disk doesn't have backing file"); 488 aio_context_release(aio_context); 489 return; 490 } 491 492 s->hidden_disk = s->active_disk->bs->backing; 493 if (!s->hidden_disk->bs || !s->hidden_disk->bs->backing) { 494 error_setg(errp, "Hidden disk doesn't have backing file"); 495 aio_context_release(aio_context); 496 return; 497 } 498 499 s->secondary_disk = s->hidden_disk->bs->backing; 500 if (!s->secondary_disk->bs || !bdrv_has_blk(s->secondary_disk->bs)) { 501 error_setg(errp, "The secondary disk doesn't have block backend"); 502 aio_context_release(aio_context); 503 return; 504 } 505 506 /* verify the length */ 507 active_length = bdrv_getlength(s->active_disk->bs); 508 hidden_length = bdrv_getlength(s->hidden_disk->bs); 509 disk_length = bdrv_getlength(s->secondary_disk->bs); 510 if (active_length < 0 || hidden_length < 0 || disk_length < 0 || 511 active_length != hidden_length || hidden_length != disk_length) { 512 error_setg(errp, "Active disk, hidden disk, secondary disk's length" 513 " are not the same"); 514 aio_context_release(aio_context); 515 return; 516 } 517 518 /* Must be true, or the bdrv_getlength() calls would have failed */ 519 assert(s->active_disk->bs->drv && s->hidden_disk->bs->drv); 520 521 if (!s->active_disk->bs->drv->bdrv_make_empty || 522 !s->hidden_disk->bs->drv->bdrv_make_empty) { 523 error_setg(errp, 524 "Active disk or hidden disk doesn't support make_empty"); 525 aio_context_release(aio_context); 526 return; 527 } 528 529 /* reopen the backing file in r/w mode */ 530 reopen_backing_file(bs, true, &local_err); 531 if (local_err) { 532 error_propagate(errp, local_err); 533 aio_context_release(aio_context); 534 return; 535 } 536 537 /* start backup job now */ 538 error_setg(&s->blocker, 539 "Block device is in use by internal backup job"); 540 541 top_bs = bdrv_lookup_bs(s->top_id, s->top_id, NULL); 542 if (!top_bs || !bdrv_is_root_node(top_bs) || 543 !check_top_bs(top_bs, bs)) { 544 error_setg(errp, "No top_bs or it is invalid"); 545 reopen_backing_file(bs, false, NULL); 546 aio_context_release(aio_context); 547 return; 548 } 549 bdrv_op_block_all(top_bs, s->blocker); 550 bdrv_op_unblock(top_bs, BLOCK_OP_TYPE_DATAPLANE, s->blocker); 551 552 s->backup_job = backup_job_create( 553 NULL, s->secondary_disk->bs, s->hidden_disk->bs, 554 0, MIRROR_SYNC_MODE_NONE, NULL, 0, false, NULL, 555 BLOCKDEV_ON_ERROR_REPORT, 556 BLOCKDEV_ON_ERROR_REPORT, JOB_INTERNAL, 557 backup_job_completed, bs, NULL, &local_err); 558 if (local_err) { 559 error_propagate(errp, local_err); 560 backup_job_cleanup(bs); 561 aio_context_release(aio_context); 562 return; 563 } 564 job_start(&s->backup_job->job); 565 break; 566 default: 567 aio_context_release(aio_context); 568 abort(); 569 } 570 571 s->stage = BLOCK_REPLICATION_RUNNING; 572 573 if (s->mode == REPLICATION_MODE_SECONDARY) { 574 secondary_do_checkpoint(s, errp); 575 } 576 577 s->error = 0; 578 aio_context_release(aio_context); 579 } 580 581 static void replication_do_checkpoint(ReplicationState *rs, Error **errp) 582 { 583 BlockDriverState *bs = rs->opaque; 584 BDRVReplicationState *s; 585 AioContext *aio_context; 586 587 aio_context = bdrv_get_aio_context(bs); 588 aio_context_acquire(aio_context); 589 s = bs->opaque; 590 591 if (s->stage == BLOCK_REPLICATION_DONE || 592 s->stage == BLOCK_REPLICATION_FAILOVER) { 593 /* 594 * This case happens when a secondary was promoted to primary. 595 * Ignore the request because the secondary side of replication 596 * doesn't have to do anything anymore. 597 */ 598 aio_context_release(aio_context); 599 return; 600 } 601 602 if (s->mode == REPLICATION_MODE_SECONDARY) { 603 secondary_do_checkpoint(s, errp); 604 } 605 aio_context_release(aio_context); 606 } 607 608 static void replication_get_error(ReplicationState *rs, Error **errp) 609 { 610 BlockDriverState *bs = rs->opaque; 611 BDRVReplicationState *s; 612 AioContext *aio_context; 613 614 aio_context = bdrv_get_aio_context(bs); 615 aio_context_acquire(aio_context); 616 s = bs->opaque; 617 618 if (s->stage == BLOCK_REPLICATION_NONE) { 619 error_setg(errp, "Block replication is not running"); 620 aio_context_release(aio_context); 621 return; 622 } 623 624 if (s->error) { 625 error_setg(errp, "I/O error occurred"); 626 aio_context_release(aio_context); 627 return; 628 } 629 aio_context_release(aio_context); 630 } 631 632 static void replication_done(void *opaque, int ret) 633 { 634 BlockDriverState *bs = opaque; 635 BDRVReplicationState *s = bs->opaque; 636 637 if (ret == 0) { 638 s->stage = BLOCK_REPLICATION_DONE; 639 640 s->active_disk = NULL; 641 s->secondary_disk = NULL; 642 s->hidden_disk = NULL; 643 s->error = 0; 644 } else { 645 s->stage = BLOCK_REPLICATION_FAILOVER_FAILED; 646 s->error = -EIO; 647 } 648 } 649 650 static void replication_stop(ReplicationState *rs, bool failover, Error **errp) 651 { 652 BlockDriverState *bs = rs->opaque; 653 BDRVReplicationState *s; 654 AioContext *aio_context; 655 656 aio_context = bdrv_get_aio_context(bs); 657 aio_context_acquire(aio_context); 658 s = bs->opaque; 659 660 if (s->stage == BLOCK_REPLICATION_DONE || 661 s->stage == BLOCK_REPLICATION_FAILOVER) { 662 /* 663 * This case happens when a secondary was promoted to primary. 664 * Ignore the request because the secondary side of replication 665 * doesn't have to do anything anymore. 666 */ 667 aio_context_release(aio_context); 668 return; 669 } 670 671 if (s->stage != BLOCK_REPLICATION_RUNNING) { 672 error_setg(errp, "Block replication is not running"); 673 aio_context_release(aio_context); 674 return; 675 } 676 677 switch (s->mode) { 678 case REPLICATION_MODE_PRIMARY: 679 s->stage = BLOCK_REPLICATION_DONE; 680 s->error = 0; 681 break; 682 case REPLICATION_MODE_SECONDARY: 683 /* 684 * This BDS will be closed, and the job should be completed 685 * before the BDS is closed, because we will access hidden 686 * disk, secondary disk in backup_job_completed(). 687 */ 688 if (s->backup_job) { 689 job_cancel_sync(&s->backup_job->job); 690 } 691 692 if (!failover) { 693 secondary_do_checkpoint(s, errp); 694 s->stage = BLOCK_REPLICATION_DONE; 695 aio_context_release(aio_context); 696 return; 697 } 698 699 s->stage = BLOCK_REPLICATION_FAILOVER; 700 s->commit_job = commit_active_start( 701 NULL, s->active_disk->bs, s->secondary_disk->bs, 702 JOB_INTERNAL, 0, BLOCKDEV_ON_ERROR_REPORT, 703 NULL, replication_done, bs, true, errp); 704 break; 705 default: 706 aio_context_release(aio_context); 707 abort(); 708 } 709 aio_context_release(aio_context); 710 } 711 712 static const char *const replication_strong_runtime_opts[] = { 713 REPLICATION_MODE, 714 REPLICATION_TOP_ID, 715 716 NULL 717 }; 718 719 static BlockDriver bdrv_replication = { 720 .format_name = "replication", 721 .instance_size = sizeof(BDRVReplicationState), 722 723 .bdrv_open = replication_open, 724 .bdrv_close = replication_close, 725 .bdrv_child_perm = replication_child_perm, 726 727 .bdrv_getlength = replication_getlength, 728 .bdrv_co_readv = replication_co_readv, 729 .bdrv_co_writev = replication_co_writev, 730 731 .is_filter = true, 732 733 .has_variable_length = true, 734 .strong_runtime_opts = replication_strong_runtime_opts, 735 }; 736 737 static void bdrv_replication_init(void) 738 { 739 bdrv_register(&bdrv_replication); 740 } 741 742 block_init(bdrv_replication_init); 743