Patchwork [1/4] block: Move external snapshot image creation in the block drivers.

login
register
mail settings
Submitter Benoît Canet
Date Jan. 28, 2013, 1:22 p.m.
Message ID <1359379338-5974-2-git-send-email-benoit@irqsave.net>
Download mbox | patch
Permalink /patch/216211/
State New
Headers show

Comments

Benoît Canet - Jan. 28, 2013, 1:22 p.m.
This patch will allow protocols to implements snapshots as the image creation
is now delegated to the block driver.

Signed-off-by: Benoit Canet <benoit@irqsave.net>
---
 block.c                   |   42 ++++++++++++++++++++++++++++++++++++++++++
 block/blkdebug.c          |    2 ++
 block/blkverify.c         |    2 ++
 block/bochs.c             |    2 ++
 block/cloop.c             |    2 ++
 block/cow.c               |    2 ++
 block/curl.c              |   10 ++++++++++
 block/dmg.c               |    2 ++
 block/gluster.c           |    8 ++++++++
 block/iscsi.c             |    2 ++
 block/nbd.c               |    6 ++++++
 block/parallels.c         |    2 ++
 block/qcow.c              |    2 ++
 block/qcow2.c             |    2 ++
 block/qed.c               |    2 ++
 block/raw-posix.c         |   10 ++++++++++
 block/raw-win32.c         |    6 ++++++
 block/raw.c               |    2 ++
 block/rbd.c               |    2 ++
 block/sheepdog.c          |    2 ++
 block/vdi.c               |    2 ++
 block/vmdk.c              |    2 ++
 block/vpc.c               |    2 ++
 block/vvfat.c             |    2 ++
 blockdev.c                |    8 ++++----
 include/block/block.h     |   15 +++++++++++++++
 include/block/block_int.h |    8 ++++++++
 27 files changed, 145 insertions(+), 4 deletions(-)
Stefan Hajnoczi - Jan. 28, 2013, 3:44 p.m.
On Mon, Jan 28, 2013 at 02:22:15PM +0100, Benoît Canet wrote:
> diff --git a/block.c b/block.c
> index 6fa7c90..af22ee8 100644
> --- a/block.c
> +++ b/block.c
> @@ -4626,3 +4626,45 @@ out:
>          bdrv_delete(bs);
>      }
>  }
> +
> +void bdrv_generic_ext_snapshot_img_create(BlockDriverState *bs,
> +                                          const char *filename,
> +                                          const char *fmt,
> +                                          const char *base_filename,
> +                                          const char *base_fmt,
> +                                          char *options,
> +                                          uint64_t img_size,
> +                                          int flags,
> +                                          Error **errp)
> +{
> +    bdrv_img_create(filename, fmt, base_filename, base_fmt, options, img_size,
> +                    flags, errp);
> +}

It would be easier to inline the bdrv_img_create() call into
bdrv_ext_snapshot_img_create() so that BlockDriver structs do not need
to explicitly reference bdrv_generic_ext_snapshot_img_create().

That way folks writing new block drivers don't need to worry about
.bdrv_ext_snapshot_img_create().

> +
> +void bdrv_ext_snapshot_img_create(BlockDriverState *old_bs,
> +                                  const char *filename, const char *fmt,
> +                                  const char *base_filename,
> +                                  const char *base_fmt,
> +                                  char *options, uint64_t img_size,
> +                                  int flags, Error **errp)
> +{
> +    if (!old_bs || !old_bs->file || !old_bs->file->drv) {
> +        error_setg(errp, "Block driver not reachable.");
> +        return;
> +    }
> +
> +    if (!old_bs->file->drv->bdrv_ext_snapshot_img_create) {
> +        error_set(errp, QERR_BLOCK_FORMAT_FEATURE_NOT_SUPPORTED,
> +                  bdrv_get_format_name(old_bs->file),
> +                  bdrv_get_device_name(old_bs),
> +                  "external snapshots");
> +        return;
> +    }
> +
> +    old_bs->file->drv->bdrv_ext_snapshot_img_create(old_bs->file,
> +                                                    filename, fmt,
> +                                                    base_filename,
> +                                                    base_fmt,
> +                                                    options, img_size,
> +                                                    flags, errp);

Why old_bs->file?  This means the function cannot be called on a
protocol BlockDriverState.

Patch

diff --git a/block.c b/block.c
index 6fa7c90..af22ee8 100644
--- a/block.c
+++ b/block.c
@@ -4626,3 +4626,45 @@  out:
         bdrv_delete(bs);
     }
 }
+
+void bdrv_generic_ext_snapshot_img_create(BlockDriverState *bs,
+                                          const char *filename,
+                                          const char *fmt,
+                                          const char *base_filename,
+                                          const char *base_fmt,
+                                          char *options,
+                                          uint64_t img_size,
+                                          int flags,
+                                          Error **errp)
+{
+    bdrv_img_create(filename, fmt, base_filename, base_fmt, options, img_size,
+                    flags, errp);
+}
+
+void bdrv_ext_snapshot_img_create(BlockDriverState *old_bs,
+                                  const char *filename, const char *fmt,
+                                  const char *base_filename,
+                                  const char *base_fmt,
+                                  char *options, uint64_t img_size,
+                                  int flags, Error **errp)
+{
+    if (!old_bs || !old_bs->file || !old_bs->file->drv) {
+        error_setg(errp, "Block driver not reachable.");
+        return;
+    }
+
+    if (!old_bs->file->drv->bdrv_ext_snapshot_img_create) {
+        error_set(errp, QERR_BLOCK_FORMAT_FEATURE_NOT_SUPPORTED,
+                  bdrv_get_format_name(old_bs->file),
+                  bdrv_get_device_name(old_bs),
+                  "external snapshots");
+        return;
+    }
+
+    old_bs->file->drv->bdrv_ext_snapshot_img_create(old_bs->file,
+                                                    filename, fmt,
+                                                    base_filename,
+                                                    base_fmt,
+                                                    options, img_size,
+                                                    flags, errp);
+}
diff --git a/block/blkdebug.c b/block/blkdebug.c
index 6f74637..dc99401 100644
--- a/block/blkdebug.c
+++ b/block/blkdebug.c
@@ -584,6 +584,8 @@  static BlockDriver bdrv_blkdebug = {
     .bdrv_debug_breakpoint      = blkdebug_debug_breakpoint,
     .bdrv_debug_resume          = blkdebug_debug_resume,
     .bdrv_debug_is_suspended    = blkdebug_debug_is_suspended,
+
+    .bdrv_ext_snapshot_img_create = bdrv_generic_ext_snapshot_img_create,
 };
 
 static void bdrv_blkdebug_init(void)
diff --git a/block/blkverify.c b/block/blkverify.c
index a7dd459..2726ed0 100644
--- a/block/blkverify.c
+++ b/block/blkverify.c
@@ -356,6 +356,8 @@  static BlockDriver bdrv_blkverify = {
     .bdrv_aio_readv     = blkverify_aio_readv,
     .bdrv_aio_writev    = blkverify_aio_writev,
     .bdrv_aio_flush     = blkverify_aio_flush,
+
+    .bdrv_ext_snapshot_img_create = bdrv_generic_ext_snapshot_img_create,
 };
 
 static void bdrv_blkverify_init(void)
diff --git a/block/bochs.c b/block/bochs.c
index 1b1d9cd..baea957 100644
--- a/block/bochs.c
+++ b/block/bochs.c
@@ -233,6 +233,8 @@  static BlockDriver bdrv_bochs = {
     .bdrv_open		= bochs_open,
     .bdrv_read          = bochs_co_read,
     .bdrv_close		= bochs_close,
+
+    .bdrv_ext_snapshot_img_create = bdrv_generic_ext_snapshot_img_create,
 };
 
 static void bdrv_bochs_init(void)
diff --git a/block/cloop.c b/block/cloop.c
index 5a0d0d8..a74d9aa 100644
--- a/block/cloop.c
+++ b/block/cloop.c
@@ -185,6 +185,8 @@  static BlockDriver bdrv_cloop = {
     .bdrv_open      = cloop_open,
     .bdrv_read      = cloop_co_read,
     .bdrv_close     = cloop_close,
+
+    .bdrv_ext_snapshot_img_create = bdrv_generic_ext_snapshot_img_create,
 };
 
 static void bdrv_cloop_init(void)
diff --git a/block/cow.c b/block/cow.c
index a33ce95..ba69f35 100644
--- a/block/cow.c
+++ b/block/cow.c
@@ -346,6 +346,8 @@  static BlockDriver bdrv_cow = {
     .bdrv_co_is_allocated   = cow_co_is_allocated,
 
     .create_options = cow_create_options,
+
+    .bdrv_ext_snapshot_img_create = bdrv_generic_ext_snapshot_img_create,
 };
 
 static void bdrv_cow_init(void)
diff --git a/block/curl.c b/block/curl.c
index 47df952..0151a21 100644
--- a/block/curl.c
+++ b/block/curl.c
@@ -561,6 +561,8 @@  static BlockDriver bdrv_http = {
     .bdrv_getlength  = curl_getlength,
 
     .bdrv_aio_readv  = curl_aio_readv,
+
+    .bdrv_ext_snapshot_img_create = bdrv_generic_ext_snapshot_img_create,
 };
 
 static BlockDriver bdrv_https = {
@@ -573,6 +575,8 @@  static BlockDriver bdrv_https = {
     .bdrv_getlength  = curl_getlength,
 
     .bdrv_aio_readv  = curl_aio_readv,
+
+    .bdrv_ext_snapshot_img_create = bdrv_generic_ext_snapshot_img_create,
 };
 
 static BlockDriver bdrv_ftp = {
@@ -585,6 +589,8 @@  static BlockDriver bdrv_ftp = {
     .bdrv_getlength  = curl_getlength,
 
     .bdrv_aio_readv  = curl_aio_readv,
+
+    .bdrv_ext_snapshot_img_create = bdrv_generic_ext_snapshot_img_create,
 };
 
 static BlockDriver bdrv_ftps = {
@@ -597,6 +603,8 @@  static BlockDriver bdrv_ftps = {
     .bdrv_getlength  = curl_getlength,
 
     .bdrv_aio_readv  = curl_aio_readv,
+
+    .bdrv_ext_snapshot_img_create = bdrv_generic_ext_snapshot_img_create,
 };
 
 static BlockDriver bdrv_tftp = {
@@ -609,6 +617,8 @@  static BlockDriver bdrv_tftp = {
     .bdrv_getlength  = curl_getlength,
 
     .bdrv_aio_readv  = curl_aio_readv,
+
+    .bdrv_ext_snapshot_img_create = bdrv_generic_ext_snapshot_img_create,
 };
 
 static void curl_block_init(void)
diff --git a/block/dmg.c b/block/dmg.c
index ac397dc..773e9d5 100644
--- a/block/dmg.c
+++ b/block/dmg.c
@@ -315,6 +315,8 @@  static BlockDriver bdrv_dmg = {
     .bdrv_open		= dmg_open,
     .bdrv_read          = dmg_co_read,
     .bdrv_close		= dmg_close,
+
+    .bdrv_ext_snapshot_img_create = bdrv_generic_ext_snapshot_img_create,
 };
 
 static void bdrv_dmg_init(void)
diff --git a/block/gluster.c b/block/gluster.c
index 0f2c32a..297a096 100644
--- a/block/gluster.c
+++ b/block/gluster.c
@@ -566,6 +566,8 @@  static BlockDriver bdrv_gluster = {
     .bdrv_aio_writev              = qemu_gluster_aio_writev,
     .bdrv_aio_flush               = qemu_gluster_aio_flush,
     .create_options               = qemu_gluster_create_options,
+
+    .bdrv_ext_snapshot_img_create = bdrv_generic_ext_snapshot_img_create,
 };
 
 static BlockDriver bdrv_gluster_tcp = {
@@ -581,6 +583,8 @@  static BlockDriver bdrv_gluster_tcp = {
     .bdrv_aio_writev              = qemu_gluster_aio_writev,
     .bdrv_aio_flush               = qemu_gluster_aio_flush,
     .create_options               = qemu_gluster_create_options,
+
+    .bdrv_ext_snapshot_img_create = bdrv_generic_ext_snapshot_img_create,
 };
 
 static BlockDriver bdrv_gluster_unix = {
@@ -596,6 +600,8 @@  static BlockDriver bdrv_gluster_unix = {
     .bdrv_aio_writev              = qemu_gluster_aio_writev,
     .bdrv_aio_flush               = qemu_gluster_aio_flush,
     .create_options               = qemu_gluster_create_options,
+
+    .bdrv_ext_snapshot_img_create = bdrv_generic_ext_snapshot_img_create,
 };
 
 static BlockDriver bdrv_gluster_rdma = {
@@ -611,6 +617,8 @@  static BlockDriver bdrv_gluster_rdma = {
     .bdrv_aio_writev              = qemu_gluster_aio_writev,
     .bdrv_aio_flush               = qemu_gluster_aio_flush,
     .create_options               = qemu_gluster_create_options,
+
+    .bdrv_ext_snapshot_img_create = bdrv_generic_ext_snapshot_img_create,
 };
 
 static void bdrv_gluster_init(void)
diff --git a/block/iscsi.c b/block/iscsi.c
index f08cf96..c8e4eb8 100644
--- a/block/iscsi.c
+++ b/block/iscsi.c
@@ -978,6 +978,8 @@  static BlockDriver bdrv_iscsi = {
     .bdrv_ioctl       = iscsi_ioctl,
     .bdrv_aio_ioctl   = iscsi_aio_ioctl,
 #endif
+
+    .bdrv_ext_snapshot_img_create = bdrv_generic_ext_snapshot_img_create,
 };
 
 static QemuOptsList qemu_iscsi_opts = {
diff --git a/block/nbd.c b/block/nbd.c
index a581294..a3e821d 100644
--- a/block/nbd.c
+++ b/block/nbd.c
@@ -572,6 +572,8 @@  static BlockDriver bdrv_nbd = {
     .bdrv_co_flush_to_os = nbd_co_flush,
     .bdrv_co_discard     = nbd_co_discard,
     .bdrv_getlength      = nbd_getlength,
+
+    .bdrv_ext_snapshot_img_create = bdrv_generic_ext_snapshot_img_create,
 };
 
 static BlockDriver bdrv_nbd_tcp = {
@@ -585,6 +587,8 @@  static BlockDriver bdrv_nbd_tcp = {
     .bdrv_co_flush_to_os = nbd_co_flush,
     .bdrv_co_discard     = nbd_co_discard,
     .bdrv_getlength      = nbd_getlength,
+
+    .bdrv_ext_snapshot_img_create = bdrv_generic_ext_snapshot_img_create,
 };
 
 static BlockDriver bdrv_nbd_unix = {
@@ -598,6 +602,8 @@  static BlockDriver bdrv_nbd_unix = {
     .bdrv_co_flush_to_os = nbd_co_flush,
     .bdrv_co_discard     = nbd_co_discard,
     .bdrv_getlength      = nbd_getlength,
+
+    .bdrv_ext_snapshot_img_create = bdrv_generic_ext_snapshot_img_create,
 };
 
 static void bdrv_nbd_init(void)
diff --git a/block/parallels.c b/block/parallels.c
index 3773750..fab8cff 100644
--- a/block/parallels.c
+++ b/block/parallels.c
@@ -160,6 +160,8 @@  static BlockDriver bdrv_parallels = {
     .bdrv_open		= parallels_open,
     .bdrv_read          = parallels_co_read,
     .bdrv_close		= parallels_close,
+
+    .bdrv_ext_snapshot_img_create = bdrv_generic_ext_snapshot_img_create,
 };
 
 static void bdrv_parallels_init(void)
diff --git a/block/qcow.c b/block/qcow.c
index 4276610..423bf35 100644
--- a/block/qcow.c
+++ b/block/qcow.c
@@ -890,6 +890,8 @@  static BlockDriver bdrv_qcow = {
     .bdrv_get_info          = qcow_get_info,
 
     .create_options = qcow_create_options,
+
+    .bdrv_ext_snapshot_img_create = bdrv_generic_ext_snapshot_img_create,
 };
 
 static void bdrv_qcow_init(void)
diff --git a/block/qcow2.c b/block/qcow2.c
index f6abff6..0174ae5 100644
--- a/block/qcow2.c
+++ b/block/qcow2.c
@@ -1717,6 +1717,8 @@  static BlockDriver bdrv_qcow2 = {
 
     .create_options = qcow2_create_options,
     .bdrv_check = qcow2_check,
+
+    .bdrv_ext_snapshot_img_create = bdrv_generic_ext_snapshot_img_create,
 };
 
 static void bdrv_qcow2_init(void)
diff --git a/block/qed.c b/block/qed.c
index cf85d8f..9857179 100644
--- a/block/qed.c
+++ b/block/qed.c
@@ -1585,6 +1585,8 @@  static BlockDriver bdrv_qed = {
     .bdrv_change_backing_file = bdrv_qed_change_backing_file,
     .bdrv_invalidate_cache    = bdrv_qed_invalidate_cache,
     .bdrv_check               = bdrv_qed_check,
+
+    .bdrv_ext_snapshot_img_create = bdrv_generic_ext_snapshot_img_create,
 };
 
 static void bdrv_qed_init(void)
diff --git a/block/raw-posix.c b/block/raw-posix.c
index 679fcc5..1d08a0e 100644
--- a/block/raw-posix.c
+++ b/block/raw-posix.c
@@ -1169,6 +1169,8 @@  static BlockDriver bdrv_file = {
                         = raw_get_allocated_file_size,
 
     .create_options = raw_create_options,
+
+    .bdrv_ext_snapshot_img_create = bdrv_generic_ext_snapshot_img_create,
 };
 
 /***********************************************/
@@ -1467,6 +1469,8 @@  static BlockDriver bdrv_host_device = {
     .bdrv_ioctl         = hdev_ioctl,
     .bdrv_aio_ioctl     = hdev_aio_ioctl,
 #endif
+
+    .bdrv_ext_snapshot_img_create = bdrv_generic_ext_snapshot_img_create,
 };
 
 #ifdef __linux__
@@ -1590,6 +1594,8 @@  static BlockDriver bdrv_host_floppy = {
     .bdrv_is_inserted   = floppy_is_inserted,
     .bdrv_media_changed = floppy_media_changed,
     .bdrv_eject         = floppy_eject,
+
+    .bdrv_ext_snapshot_img_create = bdrv_generic_ext_snapshot_img_create,
 };
 
 static int cdrom_open(BlockDriverState *bs, const char *filename, int flags)
@@ -1696,6 +1702,8 @@  static BlockDriver bdrv_host_cdrom = {
     /* generic scsi device */
     .bdrv_ioctl         = hdev_ioctl,
     .bdrv_aio_ioctl     = hdev_aio_ioctl,
+
+    .bdrv_ext_snapshot_img_create = bdrv_generic_ext_snapshot_img_create,
 };
 #endif /* __linux__ */
 
@@ -1814,6 +1822,8 @@  static BlockDriver bdrv_host_cdrom = {
     .bdrv_is_inserted   = cdrom_is_inserted,
     .bdrv_eject         = cdrom_eject,
     .bdrv_lock_medium   = cdrom_lock_medium,
+
+    .bdrv_ext_snapshot_img_create = bdrv_generic_ext_snapshot_img_create,
 };
 #endif /* __FreeBSD__ */
 
diff --git a/block/raw-win32.c b/block/raw-win32.c
index b89ac19..e7fa968 100644
--- a/block/raw-win32.c
+++ b/block/raw-win32.c
@@ -432,6 +432,8 @@  static BlockDriver bdrv_file = {
                         = raw_get_allocated_file_size,
 
     .create_options = raw_create_options,
+
+    .bdrv_ext_snapshot_img_create = bdrv_generic_ext_snapshot_img_create,
 };
 
 /***********************************************/
@@ -552,6 +554,10 @@  static BlockDriver bdrv_host_device = {
     .bdrv_getlength	= raw_getlength,
     .bdrv_get_allocated_file_size
                         = raw_get_allocated_file_size,
+
+    .bdrv_ext_snapshot_img_create = bdrv_generic_ext_snapshot_img_create,
+
+    .bdrv_ext_snapshot_img_create = bdrv_generic_ext_snapshot_img_create,
 };
 
 static void bdrv_file_init(void)
diff --git a/block/raw.c b/block/raw.c
index 75812db..2d1b62c 100644
--- a/block/raw.c
+++ b/block/raw.c
@@ -145,6 +145,8 @@  static BlockDriver bdrv_raw = {
     .bdrv_create        = raw_create,
     .create_options     = raw_create_options,
     .bdrv_has_zero_init = raw_has_zero_init,
+
+    .bdrv_ext_snapshot_img_create = bdrv_generic_ext_snapshot_img_create,
 };
 
 static void bdrv_raw_init(void)
diff --git a/block/rbd.c b/block/rbd.c
index 8cd10a7..eb3a0d4 100644
--- a/block/rbd.c
+++ b/block/rbd.c
@@ -958,6 +958,8 @@  static BlockDriver bdrv_rbd = {
     .bdrv_snapshot_delete   = qemu_rbd_snap_remove,
     .bdrv_snapshot_list     = qemu_rbd_snap_list,
     .bdrv_snapshot_goto     = qemu_rbd_snap_rollback,
+
+    .bdrv_ext_snapshot_img_create = bdrv_generic_ext_snapshot_img_create,
 };
 
 static void bdrv_rbd_init(void)
diff --git a/block/sheepdog.c b/block/sheepdog.c
index 3e49bb8..4f483b2 100644
--- a/block/sheepdog.c
+++ b/block/sheepdog.c
@@ -2085,6 +2085,8 @@  BlockDriver bdrv_sheepdog = {
     .bdrv_load_vmstate  = sd_load_vmstate,
 
     .create_options = sd_create_options,
+
+    .bdrv_ext_snapshot_img_create = bdrv_generic_ext_snapshot_img_create,
 };
 
 static void bdrv_sheepdog_init(void)
diff --git a/block/vdi.c b/block/vdi.c
index 021abaa..dbfaa3e 100644
--- a/block/vdi.c
+++ b/block/vdi.c
@@ -778,6 +778,8 @@  static BlockDriver bdrv_vdi = {
 
     .create_options = vdi_create_options,
     .bdrv_check = vdi_check,
+
+    .bdrv_ext_snapshot_img_create = bdrv_generic_ext_snapshot_img_create,
 };
 
 static void bdrv_vdi_init(void)
diff --git a/block/vmdk.c b/block/vmdk.c
index 19298c2..2b0acc0 100644
--- a/block/vmdk.c
+++ b/block/vmdk.c
@@ -1695,6 +1695,8 @@  static BlockDriver bdrv_vmdk = {
     .bdrv_get_allocated_file_size  = vmdk_get_allocated_file_size,
 
     .create_options = vmdk_create_options,
+
+    .bdrv_ext_snapshot_img_create = bdrv_generic_ext_snapshot_img_create,
 };
 
 static void bdrv_vmdk_init(void)
diff --git a/block/vpc.c b/block/vpc.c
index 7948609..a39fec1 100644
--- a/block/vpc.c
+++ b/block/vpc.c
@@ -810,6 +810,8 @@  static BlockDriver bdrv_vpc = {
     .bdrv_write             = vpc_co_write,
 
     .create_options = vpc_create_options,
+
+    .bdrv_ext_snapshot_img_create = bdrv_generic_ext_snapshot_img_create,
 };
 
 static void bdrv_vpc_init(void)
diff --git a/block/vvfat.c b/block/vvfat.c
index 06e6654..4e5f4fc 100644
--- a/block/vvfat.c
+++ b/block/vvfat.c
@@ -2874,6 +2874,8 @@  static BlockDriver bdrv_vvfat = {
     .bdrv_close		= vvfat_close,
     .bdrv_co_is_allocated = vvfat_co_is_allocated,
     .protocol_name	= "fat",
+
+    .bdrv_ext_snapshot_img_create = bdrv_generic_ext_snapshot_img_create,
 };
 
 static void bdrv_vvfat_init(void)
diff --git a/blockdev.c b/blockdev.c
index 9126587..0ce45c5 100644
--- a/blockdev.c
+++ b/blockdev.c
@@ -787,10 +787,10 @@  void qmp_transaction(BlockdevActionList *dev_list, Error **errp)
 
         /* create new image w/backing file */
         if (mode != NEW_IMAGE_MODE_EXISTING) {
-            bdrv_img_create(new_image_file, format,
-                            states->old_bs->filename,
-                            states->old_bs->drv->format_name,
-                            NULL, -1, flags, &local_err);
+            bdrv_ext_snapshot_img_create(states->old_bs, new_image_file, format,
+                                         states->old_bs->filename,
+                                         states->old_bs->drv->format_name,
+                                         NULL, -1, flags, &local_err);
             if (error_is_set(&local_err)) {
                 error_propagate(errp, local_err);
                 goto delete_and_fail;
diff --git a/include/block/block.h b/include/block/block.h
index ffd1936..4d83856 100644
--- a/include/block/block.h
+++ b/include/block/block.h
@@ -346,6 +346,21 @@  int bdrv_load_vmstate(BlockDriverState *bs, uint8_t *buf,
 void bdrv_img_create(const char *filename, const char *fmt,
                      const char *base_filename, const char *base_fmt,
                      char *options, uint64_t img_size, int flags, Error **errp);
+void bdrv_generic_ext_snapshot_img_create(BlockDriverState *bs,
+                                          const char *filename,
+                                          const char *fmt,
+                                          const char *base_filename,
+                                          const char *base_fmt,
+                                          char *options,
+                                          uint64_t img_size,
+                                          int flags,
+                                          Error **errp);
+void bdrv_ext_snapshot_img_create(BlockDriverState *old_bs,
+                                  const char *filename, const char *fmt,
+                                  const char *base_filename,
+                                  const char *base_fmt,
+                                  char *options, uint64_t img_size,
+                                  int flags, Error **errp);
 
 void bdrv_set_buffer_alignment(BlockDriverState *bs, int align);
 void *qemu_blockalign(BlockDriverState *bs, size_t size);
diff --git a/include/block/block_int.h b/include/block/block_int.h
index f83ffb8..2b476af 100644
--- a/include/block/block_int.h
+++ b/include/block/block_int.h
@@ -202,6 +202,14 @@  struct BlockDriver {
      */
     int (*bdrv_has_zero_init)(BlockDriverState *bs);
 
+    /* for generic block drivers this field must point to bdrv_img_create */
+    void (*bdrv_ext_snapshot_img_create)(BlockDriverState *bs,
+                                         const char *filename, const char *fmt,
+                                         const char *base_filename,
+                                         const char *base_fmt,
+                                         char *options, uint64_t img_size,
+                                         int flags, Error **errp);
+
     QLIST_ENTRY(BlockDriver) list;
 };