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