[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
Re: [Qemu-devel] [PATCH] block: Add bdrv_forbid_ext_snapshots.
From: |
Jeff Cody |
Subject: |
Re: [Qemu-devel] [PATCH] block: Add bdrv_forbid_ext_snapshots. |
Date: |
Wed, 25 Sep 2013 22:01:07 -0400 |
User-agent: |
Mutt/1.5.21 (2010-09-15) |
On Wed, Sep 25, 2013 at 04:23:22PM +0200, Benoît Canet wrote:
> Drivers having a bs->file where set to recurse the call to their child.
> Protocol and drivers designed to be on the bottom of the stack where set to
> allow
> snapshots.
> Future protocols like quorum where creating snapshots does not make sense
> without block filters will be set to forbid snapshots.
>
> Signed-off-by: Benoit Canet <address@hidden>
> ---
> block.c | 27 +++++++++++++++++++++++++++
> 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 | 4 ++++
> block/raw_bsd.c | 4 +++-
> block/rbd.c | 2 ++
> block/sheepdog.c | 6 ++++++
> block/ssh.c | 2 ++
> block/vdi.c | 2 ++
> block/vhdx.c | 2 ++
> block/vmdk.c | 2 ++
> block/vpc.c | 2 ++
> block/vvfat.c | 2 ++
> blockdev.c | 5 +++++
> include/block/block.h | 10 ++++++++++
> include/block/block_int.h | 7 +++++++
> 29 files changed, 132 insertions(+), 1 deletion(-)
>
> diff --git a/block.c b/block.c
> index 4a98250..ff296df 100644
> --- a/block.c
> +++ b/block.c
> @@ -4651,3 +4651,30 @@ int bdrv_amend_options(BlockDriverState *bs,
> QEMUOptionParameter *options)
> }
> return bs->drv->bdrv_amend_options(bs, options);
> }
> +
> +bool bdrv_is_ext_snapshot_forbidden(BlockDriverState *bs)
> +{
I think either:
A) Name this function bdrv_forbid_ext_snapshots(), or
B) Name the BlockDriver function ptr to .bdrv_is_ext_snapshot_forbidden
The idea being that this function and the BlockDriver function ptr
should have the same name (e.g. bdrv_has_zero_init, and
bs->drv->bdrv_has_zero_init, etc..)
> + /* allow snapshot by default */
> + if (!bs->drv->bdrv_forbid_ext_snapshots) {
> + return false;
Rather than return false here, we could do:
if (!bs->drv->bdrv_forbid_ext_snapshots) {
if (bs->file) {
return bdrv_is_ext_snapshot_forbidden(bs->file);
} else {
return false;
}
}
That would then get rid of the need for
bdrv_recurse_forbid_ext_snapshots(), if I understand correctly the
goal. And then the only Block Drivers that need to populate
.bdrv_is_ext_snapshot_forbidden() are the ones that explicitly forbid
it themselves. I.e., the only image driver now that would need to
populate this is blkverify (and later on quorum).
> + }
> + return bs->drv->bdrv_forbid_ext_snapshots(bs);
> +}
> +
> +bool bdrv_recurse_forbid_ext_snapshots(BlockDriverState *bs)
> +{
> + if (!bs->file->drv) {
> + return false;
> + }
> + return bs->file->drv->bdrv_forbid_ext_snapshots(bs->file);
> +}
(As I said above, I don't think this function is needed...)
> +
> +bool bdrv_forbid_ext_snapshots(BlockDriverState *bs)
> +{
> + return true;
> +}
> +
... and if you chose A above, then maybe just name this function
something more like 'bdrv_ext_snapshots_forbidden()', etc.
> +bool bdrv_allow_ext_snapshots(BlockDriverState *bs)
> +{
> + return false;
> +}
I understand why this returns false (it is actually 'false' meaning
don't forbid external snapshots, as it is mapped to
.bdrv_forbid_ext_snapshots()). But it is a bit discordant to have
'bdrv_allow_ext_snapshots()' return false to mean snapshots are
allowed.
And again, as I said above, I don't think this is needed; if
.bdrv_forbid_ext_snapshots is NULL, then the driver is not forbidding
snapshots.
Thanks,
Jeff
> diff --git a/block/blkdebug.c b/block/blkdebug.c
> index be948b2..5acee0f 100644
> --- a/block/blkdebug.c
> +++ b/block/blkdebug.c
> @@ -641,6 +641,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_forbid_ext_snapshots = bdrv_recurse_forbid_ext_snapshots,
> };
>
> static void bdrv_blkdebug_init(void)
> diff --git a/block/blkverify.c b/block/blkverify.c
> index 2077d8a..7890adb 100644
> --- a/block/blkverify.c
> +++ b/block/blkverify.c
> @@ -313,6 +313,8 @@ static BlockDriver bdrv_blkverify = {
> .bdrv_aio_readv = blkverify_aio_readv,
> .bdrv_aio_writev = blkverify_aio_writev,
> .bdrv_aio_flush = blkverify_aio_flush,
> +
> + .bdrv_forbid_ext_snapshots = bdrv_forbid_ext_snapshots,
> };
>
> static void bdrv_blkverify_init(void)
> diff --git a/block/bochs.c b/block/bochs.c
> index 51d9a90..55c13c5 100644
> --- a/block/bochs.c
> +++ b/block/bochs.c
> @@ -242,6 +242,8 @@ static BlockDriver bdrv_bochs = {
> .bdrv_open = bochs_open,
> .bdrv_read = bochs_co_read,
> .bdrv_close = bochs_close,
> +
> + .bdrv_forbid_ext_snapshots = bdrv_recurse_forbid_ext_snapshots,
> };
>
> static void bdrv_bochs_init(void)
> diff --git a/block/cloop.c b/block/cloop.c
> index b907023..bb28758 100644
> --- a/block/cloop.c
> +++ b/block/cloop.c
> @@ -195,6 +195,8 @@ static BlockDriver bdrv_cloop = {
> .bdrv_open = cloop_open,
> .bdrv_read = cloop_co_read,
> .bdrv_close = cloop_close,
> +
> + .bdrv_forbid_ext_snapshots = bdrv_recurse_forbid_ext_snapshots,
> };
>
> static void bdrv_cloop_init(void)
> diff --git a/block/cow.c b/block/cow.c
> index 909c3e7..ceb786a 100644
> --- a/block/cow.c
> +++ b/block/cow.c
> @@ -393,6 +393,8 @@ static BlockDriver bdrv_cow = {
> .bdrv_co_get_block_status = cow_co_get_block_status,
>
> .create_options = cow_create_options,
> +
> + .bdrv_forbid_ext_snapshots = bdrv_recurse_forbid_ext_snapshots,
> };
>
> static void bdrv_cow_init(void)
> diff --git a/block/curl.c b/block/curl.c
> index 5a46f97..ac3c94a 100644
> --- a/block/curl.c
> +++ b/block/curl.c
> @@ -617,6 +617,8 @@ static BlockDriver bdrv_http = {
> .bdrv_getlength = curl_getlength,
>
> .bdrv_aio_readv = curl_aio_readv,
> +
> + .bdrv_forbid_ext_snapshots = bdrv_allow_ext_snapshots,
> };
>
> static BlockDriver bdrv_https = {
> @@ -630,6 +632,8 @@ static BlockDriver bdrv_https = {
> .bdrv_getlength = curl_getlength,
>
> .bdrv_aio_readv = curl_aio_readv,
> +
> + .bdrv_forbid_ext_snapshots = bdrv_allow_ext_snapshots,
> };
>
> static BlockDriver bdrv_ftp = {
> @@ -643,6 +647,8 @@ static BlockDriver bdrv_ftp = {
> .bdrv_getlength = curl_getlength,
>
> .bdrv_aio_readv = curl_aio_readv,
> +
> + .bdrv_forbid_ext_snapshots = bdrv_allow_ext_snapshots,
> };
>
> static BlockDriver bdrv_ftps = {
> @@ -656,6 +662,8 @@ static BlockDriver bdrv_ftps = {
> .bdrv_getlength = curl_getlength,
>
> .bdrv_aio_readv = curl_aio_readv,
> +
> + .bdrv_forbid_ext_snapshots = bdrv_allow_ext_snapshots,
> };
>
> static BlockDriver bdrv_tftp = {
> @@ -669,6 +677,8 @@ static BlockDriver bdrv_tftp = {
> .bdrv_getlength = curl_getlength,
>
> .bdrv_aio_readv = curl_aio_readv,
> +
> + .bdrv_forbid_ext_snapshots = bdrv_allow_ext_snapshots,
> };
>
> static void curl_block_init(void)
> diff --git a/block/dmg.c b/block/dmg.c
> index d5e9b1f..96e7103 100644
> --- a/block/dmg.c
> +++ b/block/dmg.c
> @@ -382,6 +382,8 @@ static BlockDriver bdrv_dmg = {
> .bdrv_open = dmg_open,
> .bdrv_read = dmg_co_read,
> .bdrv_close = dmg_close,
> +
> + .bdrv_forbid_ext_snapshots = bdrv_recurse_forbid_ext_snapshots,
> };
>
> static void bdrv_dmg_init(void)
> diff --git a/block/gluster.c b/block/gluster.c
> index 877686a..dfb7997 100644
> --- a/block/gluster.c
> +++ b/block/gluster.c
> @@ -626,6 +626,8 @@ static BlockDriver bdrv_gluster = {
> .bdrv_aio_discard = qemu_gluster_aio_discard,
> #endif
> .create_options = qemu_gluster_create_options,
> +
> + .bdrv_forbid_ext_snapshots = bdrv_allow_ext_snapshots,
> };
>
> static BlockDriver bdrv_gluster_tcp = {
> @@ -647,6 +649,8 @@ static BlockDriver bdrv_gluster_tcp = {
> .bdrv_aio_discard = qemu_gluster_aio_discard,
> #endif
> .create_options = qemu_gluster_create_options,
> +
> + .bdrv_forbid_ext_snapshots = bdrv_allow_ext_snapshots,
> };
>
> static BlockDriver bdrv_gluster_unix = {
> @@ -668,6 +672,8 @@ static BlockDriver bdrv_gluster_unix = {
> .bdrv_aio_discard = qemu_gluster_aio_discard,
> #endif
> .create_options = qemu_gluster_create_options,
> +
> + .bdrv_forbid_ext_snapshots = bdrv_allow_ext_snapshots,
> };
>
> static BlockDriver bdrv_gluster_rdma = {
> @@ -689,6 +695,8 @@ static BlockDriver bdrv_gluster_rdma = {
> .bdrv_aio_discard = qemu_gluster_aio_discard,
> #endif
> .create_options = qemu_gluster_create_options,
> +
> + .bdrv_forbid_ext_snapshots = bdrv_allow_ext_snapshots,
> };
>
> static void bdrv_gluster_init(void)
> diff --git a/block/iscsi.c b/block/iscsi.c
> index 6152ef1..4cc7ce0 100644
> --- a/block/iscsi.c
> +++ b/block/iscsi.c
> @@ -1544,6 +1544,8 @@ static BlockDriver bdrv_iscsi = {
> .bdrv_ioctl = iscsi_ioctl,
> .bdrv_aio_ioctl = iscsi_aio_ioctl,
> #endif
> +
> + .bdrv_forbid_ext_snapshots = bdrv_allow_ext_snapshots,
> };
>
> static QemuOptsList qemu_iscsi_opts = {
> diff --git a/block/nbd.c b/block/nbd.c
> index c8deeee..7eac042 100644
> --- a/block/nbd.c
> +++ b/block/nbd.c
> @@ -651,6 +651,8 @@ static BlockDriver bdrv_nbd = {
> .bdrv_co_flush_to_os = nbd_co_flush,
> .bdrv_co_discard = nbd_co_discard,
> .bdrv_getlength = nbd_getlength,
> +
> + .bdrv_forbid_ext_snapshots = bdrv_allow_ext_snapshots,
> };
>
> static BlockDriver bdrv_nbd_tcp = {
> @@ -665,6 +667,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_forbid_ext_snapshots = bdrv_allow_ext_snapshots,
> };
>
> static BlockDriver bdrv_nbd_unix = {
> @@ -679,6 +683,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_forbid_ext_snapshots = bdrv_allow_ext_snapshots,
> };
>
> static void bdrv_nbd_init(void)
> diff --git a/block/parallels.c b/block/parallels.c
> index 2121e43..01ee036 100644
> --- a/block/parallels.c
> +++ b/block/parallels.c
> @@ -168,6 +168,8 @@ static BlockDriver bdrv_parallels = {
> .bdrv_open = parallels_open,
> .bdrv_read = parallels_co_read,
> .bdrv_close = parallels_close,
> +
> + .bdrv_forbid_ext_snapshots = bdrv_recurse_forbid_ext_snapshots,
> };
>
> static void bdrv_parallels_init(void)
> diff --git a/block/qcow.c b/block/qcow.c
> index c470e05..47f3b44 100644
> --- a/block/qcow.c
> +++ b/block/qcow.c
> @@ -918,6 +918,8 @@ static BlockDriver bdrv_qcow = {
> .bdrv_get_info = qcow_get_info,
>
> .create_options = qcow_create_options,
> +
> + .bdrv_forbid_ext_snapshots = bdrv_recurse_forbid_ext_snapshots,
> };
>
> static void bdrv_qcow_init(void)
> diff --git a/block/qcow2.c b/block/qcow2.c
> index 318d95d..c560133b 100644
> --- a/block/qcow2.c
> +++ b/block/qcow2.c
> @@ -2141,6 +2141,8 @@ static BlockDriver bdrv_qcow2 = {
> .create_options = qcow2_create_options,
> .bdrv_check = qcow2_check,
> .bdrv_amend_options = qcow2_amend_options,
> +
> + .bdrv_forbid_ext_snapshots = bdrv_recurse_forbid_ext_snapshots,
> };
>
> static void bdrv_qcow2_init(void)
> diff --git a/block/qed.c b/block/qed.c
> index 6c0cba0..e7aaa98 100644
> --- a/block/qed.c
> +++ b/block/qed.c
> @@ -1615,6 +1615,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_forbid_ext_snapshots = bdrv_recurse_forbid_ext_snapshots,
> };
>
> static void bdrv_qed_init(void)
> diff --git a/block/raw-posix.c b/block/raw-posix.c
> index f7f102d..ab2a64b 100644
> --- a/block/raw-posix.c
> +++ b/block/raw-posix.c
> @@ -1222,6 +1222,8 @@ static BlockDriver bdrv_file = {
> = raw_get_allocated_file_size,
>
> .create_options = raw_create_options,
> +
> + .bdrv_forbid_ext_snapshots = bdrv_allow_ext_snapshots,
> };
>
> /***********************************************/
> @@ -1568,6 +1570,8 @@ static BlockDriver bdrv_host_device = {
> .bdrv_ioctl = hdev_ioctl,
> .bdrv_aio_ioctl = hdev_aio_ioctl,
> #endif
> +
> + .bdrv_forbid_ext_snapshots = bdrv_allow_ext_snapshots,
> };
>
> #ifdef __linux__
> @@ -1692,6 +1696,8 @@ static BlockDriver bdrv_host_floppy = {
> .bdrv_is_inserted = floppy_is_inserted,
> .bdrv_media_changed = floppy_media_changed,
> .bdrv_eject = floppy_eject,
> +
> + .bdrv_forbid_ext_snapshots = bdrv_allow_ext_snapshots,
> };
>
> static int cdrom_open(BlockDriverState *bs, QDict *options, int flags,
> @@ -1799,6 +1805,8 @@ static BlockDriver bdrv_host_cdrom = {
> /* generic scsi device */
> .bdrv_ioctl = hdev_ioctl,
> .bdrv_aio_ioctl = hdev_aio_ioctl,
> +
> + .bdrv_forbid_ext_snapshots = bdrv_allow_ext_snapshots,
> };
> #endif /* __linux__ */
>
> @@ -1917,6 +1925,8 @@ static BlockDriver bdrv_host_cdrom = {
> .bdrv_is_inserted = cdrom_is_inserted,
> .bdrv_eject = cdrom_eject,
> .bdrv_lock_medium = cdrom_lock_medium,
> +
> + .bdrv_forbid_ext_snapshots = bdrv_allow_ext_snapshots,
> };
> #endif /* __FreeBSD__ */
>
> diff --git a/block/raw-win32.c b/block/raw-win32.c
> index 6ef320f..3479881 100644
> --- a/block/raw-win32.c
> +++ b/block/raw-win32.c
> @@ -475,6 +475,8 @@ static BlockDriver bdrv_file = {
> = raw_get_allocated_file_size,
>
> .create_options = raw_create_options,
> +
> + .bdrv_forbid_ext_snapshots = bdrv_allow_ext_snapshots,
> };
>
> /***********************************************/
> @@ -614,6 +616,8 @@ static BlockDriver bdrv_host_device = {
> .bdrv_getlength = raw_getlength,
> .bdrv_get_allocated_file_size
> = raw_get_allocated_file_size,
> +
> + .bdrv_forbid_ext_snapshots = bdrv_allow_ext_snapshots,
> };
>
> static void bdrv_file_init(void)
> diff --git a/block/raw_bsd.c b/block/raw_bsd.c
> index d4ace60..2d1af9a 100644
> --- a/block/raw_bsd.c
> +++ b/block/raw_bsd.c
> @@ -185,7 +185,9 @@ static BlockDriver bdrv_raw = {
> .bdrv_ioctl = &raw_ioctl,
> .bdrv_aio_ioctl = &raw_aio_ioctl,
> .create_options = &raw_create_options[0],
> - .bdrv_has_zero_init = &raw_has_zero_init
> + .bdrv_has_zero_init = &raw_has_zero_init,
> +
> + .bdrv_forbid_ext_snapshots = bdrv_allow_ext_snapshots,
> };
>
> static void bdrv_raw_init(void)
> diff --git a/block/rbd.c b/block/rbd.c
> index ee1dec5..203d786 100644
> --- a/block/rbd.c
> +++ b/block/rbd.c
> @@ -1030,6 +1030,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_forbid_ext_snapshots = bdrv_allow_ext_snapshots,
> };
>
> static void bdrv_rbd_init(void)
> diff --git a/block/sheepdog.c b/block/sheepdog.c
> index 5f81c93..2ba2e20 100644
> --- a/block/sheepdog.c
> +++ b/block/sheepdog.c
> @@ -2361,6 +2361,8 @@ static BlockDriver bdrv_sheepdog = {
> .bdrv_load_vmstate = sd_load_vmstate,
>
> .create_options = sd_create_options,
> +
> + .bdrv_forbid_ext_snapshots = bdrv_allow_ext_snapshots,
> };
>
> static BlockDriver bdrv_sheepdog_tcp = {
> @@ -2390,6 +2392,8 @@ static BlockDriver bdrv_sheepdog_tcp = {
> .bdrv_load_vmstate = sd_load_vmstate,
>
> .create_options = sd_create_options,
> +
> + .bdrv_forbid_ext_snapshots = bdrv_allow_ext_snapshots,
> };
>
> static BlockDriver bdrv_sheepdog_unix = {
> @@ -2419,6 +2423,8 @@ static BlockDriver bdrv_sheepdog_unix = {
> .bdrv_load_vmstate = sd_load_vmstate,
>
> .create_options = sd_create_options,
> +
> + .bdrv_forbid_ext_snapshots = bdrv_allow_ext_snapshots,
> };
>
> static void bdrv_sheepdog_init(void)
> diff --git a/block/ssh.c b/block/ssh.c
> index aa63c9d..a3c1fe5 100644
> --- a/block/ssh.c
> +++ b/block/ssh.c
> @@ -1052,6 +1052,8 @@ static BlockDriver bdrv_ssh = {
> .bdrv_getlength = ssh_getlength,
> .bdrv_co_flush_to_disk = ssh_co_flush,
> .create_options = ssh_create_options,
> +
> + .bdrv_forbid_ext_snapshots = bdrv_allow_ext_snapshots,
> };
>
> static void bdrv_ssh_init(void)
> diff --git a/block/vdi.c b/block/vdi.c
> index dcbc27c..78a74da 100644
> --- a/block/vdi.c
> +++ b/block/vdi.c
> @@ -805,6 +805,8 @@ static BlockDriver bdrv_vdi = {
>
> .create_options = vdi_create_options,
> .bdrv_check = vdi_check,
> +
> + .bdrv_forbid_ext_snapshots = bdrv_recurse_forbid_ext_snapshots,
> };
>
> static void bdrv_vdi_init(void)
> diff --git a/block/vhdx.c b/block/vhdx.c
> index b8aa49c..ddf3744 100644
> --- a/block/vhdx.c
> +++ b/block/vhdx.c
> @@ -963,6 +963,8 @@ static BlockDriver bdrv_vhdx = {
> .bdrv_reopen_prepare = vhdx_reopen_prepare,
> .bdrv_co_readv = vhdx_co_readv,
> .bdrv_co_writev = vhdx_co_writev,
> +
> + .bdrv_forbid_ext_snapshots = bdrv_recurse_forbid_ext_snapshots,
> };
>
> static void bdrv_vhdx_init(void)
> diff --git a/block/vmdk.c b/block/vmdk.c
> index 5d56e31..78719f0 100644
> --- a/block/vmdk.c
> +++ b/block/vmdk.c
> @@ -1868,6 +1868,8 @@ static BlockDriver bdrv_vmdk = {
> .bdrv_has_zero_init = vmdk_has_zero_init,
>
> .create_options = vmdk_create_options,
> +
> + .bdrv_forbid_ext_snapshots = bdrv_recurse_forbid_ext_snapshots,
> };
>
> static void bdrv_vmdk_init(void)
> diff --git a/block/vpc.c b/block/vpc.c
> index db61274..f7fef97 100644
> --- a/block/vpc.c
> +++ b/block/vpc.c
> @@ -843,6 +843,8 @@ static BlockDriver bdrv_vpc = {
>
> .create_options = vpc_create_options,
> .bdrv_has_zero_init = vpc_has_zero_init,
> +
> + .bdrv_forbid_ext_snapshots = bdrv_recurse_forbid_ext_snapshots,
> };
>
> static void bdrv_vpc_init(void)
> diff --git a/block/vvfat.c b/block/vvfat.c
> index 3ddaa0b..eef207c 100644
> --- a/block/vvfat.c
> +++ b/block/vvfat.c
> @@ -2993,6 +2993,8 @@ static BlockDriver bdrv_vvfat = {
> .bdrv_read = vvfat_co_read,
> .bdrv_write = vvfat_co_write,
> .bdrv_co_get_block_status = vvfat_co_get_block_status,
> +
> + .bdrv_forbid_ext_snapshots = bdrv_allow_ext_snapshots,
> };
>
> static void bdrv_vvfat_init(void)
> diff --git a/blockdev.c b/blockdev.c
> index 8aa66a9..12528cf 100644
> --- a/blockdev.c
> +++ b/blockdev.c
> @@ -1133,6 +1133,11 @@ static void
> external_snapshot_prepare(BlkTransactionState *common,
>
> flags = state->old_bs->open_flags;
>
> + if (bdrv_is_ext_snapshot_forbidden(state->old_bs)) {
> + error_set(errp, QERR_FEATURE_DISABLED, "snapshot");
> + return;
> + }
> +
> /* create new image w/backing file */
> if (mode != NEW_IMAGE_MODE_EXISTING) {
> bdrv_img_create(new_image_file, format,
> diff --git a/include/block/block.h b/include/block/block.h
> index f808550..98f1cbb 100644
> --- a/include/block/block.h
> +++ b/include/block/block.h
> @@ -130,6 +130,16 @@ void bdrv_info(Monitor *mon, QObject **ret_data);
> void bdrv_stats_print(Monitor *mon, const QObject *data);
> void bdrv_info_stats(Monitor *mon, QObject **ret_data);
>
> +/* used to know if an external snapshot could be taken */
> +bool bdrv_is_ext_snapshot_forbidden(BlockDriverState *bs);
> +/* generics .bdrv_forbid_snapshots implementations */
> +/* Used by drivers having a bs->file */
> +bool bdrv_recurse_forbid_ext_snapshots(BlockDriverState *bs);
> +/* Used by drivers where snapshots does not makes sense without block
> filters */
> +bool bdrv_forbid_ext_snapshots(BlockDriverState *bs);
> +/* Used by regular protocols and bottom of the stack drivers */
> +bool bdrv_allow_ext_snapshots(BlockDriverState *bs);
> +
> /* disk I/O throttling */
> void bdrv_io_limits_enable(BlockDriverState *bs);
> void bdrv_io_limits_disable(BlockDriverState *bs);
> diff --git a/include/block/block_int.h b/include/block/block_int.h
> index 211087a..c41336b 100644
> --- a/include/block/block_int.h
> +++ b/include/block/block_int.h
> @@ -217,6 +217,13 @@ struct BlockDriver {
> */
> int (*bdrv_has_zero_init)(BlockDriverState *bs);
>
> + /* This function return true in BlockDriver for which the extern snapshot
> + * operation does not make sense.
> + * Else it's recursively called from the top to the down of the
> + * BlockDriverState chain.
> + */
> + bool (*bdrv_forbid_ext_snapshots)(BlockDriverState *bs);
> +
> QLIST_ENTRY(BlockDriver) list;
> };
>
> --
> 1.8.1.2
>
>