Message ID | 1453804705-7205-7-git-send-email-famz@redhat.com (mailing list archive) |
---|---|
State | New, archived |
Headers | show |
On 01/26/2016 05:38 AM, Fam Zheng wrote: > By implementing bdrv_dirty_bitmap_set_persistent, a driver can support > the persistent dirty bitmap feature. > > Once a dirty bitmap is made persistent, the driver is responsible for saving > the dirty bitmap when appropriate, for example before close; if a persistent > bitmap is removed or made non-persistent, .bdrv_dirty_bitmap_set_persistent > will be called, the driver should then remove the dirty bitmap from the disk. > > This operation is not recursed in block layer, a filter such as blkdebug needs > to implement the callback and explicitly pass down to bs->file, etc. > > Signed-off-by: Fam Zheng <famz@redhat.com> > --- > block/dirty-bitmap.c | 38 ++++++++++++++++++++++++++++++++++++++ > include/block/block_int.h | 8 ++++++++ > include/block/dirty-bitmap.h | 4 ++++ > 3 files changed, 50 insertions(+) > > diff --git a/block/dirty-bitmap.c b/block/dirty-bitmap.c > index 1aa7f76..882a0db 100644 > --- a/block/dirty-bitmap.c > +++ b/block/dirty-bitmap.c > @@ -43,6 +43,7 @@ struct BdrvDirtyBitmap { > int64_t size; /* Size of the bitmap (Number of sectors) */ > bool disabled; /* Bitmap is read-only */ > int active_iterators; /* How many iterators are active */ > + bool persistent; /* Whether this bitmap is persistent. */ > QLIST_ENTRY(BdrvDirtyBitmap) list; > }; > > @@ -71,6 +72,37 @@ void bdrv_dirty_bitmap_make_anon(BdrvDirtyBitmap *bitmap) > bitmap->name = NULL; > } > > +int bdrv_dirty_bitmap_set_persistent(BlockDriverState *bs, > + BdrvDirtyBitmap *bitmap, > + bool persistent, bool flag_only, > + Error **errp) > +{ > + int ret = 0; > + > + if (!bitmap->name) { > + error_setg(errp, "Cannot change the persistent status of an anonymous" > + "bitmap"); > + return -EINVAL; > + } > + > + if (persistent == bitmap->persistent) { > + return 0; > + } > + > + if (!flag_only) { > + if (!bs->drv || !bs->drv->bdrv_dirty_bitmap_set_persistent) { > + error_setg(errp, "Not supported in this format."); > + return -ENOTSUP; > + } > + ret = bs->drv->bdrv_dirty_bitmap_set_persistent(bs, bitmap, persistent, > + errp); > + } > + if (!ret) { > + bitmap->persistent = persistent; > + } > + return ret; > +} > + > BdrvDirtyBitmap *bdrv_create_dirty_bitmap(BlockDriverState *bs, > uint32_t granularity, > const char *name, > @@ -194,6 +226,12 @@ int bdrv_dirty_bitmap_create_successor(BlockDriverState *bs, > uint64_t granularity; > BdrvDirtyBitmap *child; > > + if (bitmap->persistent) { > + error_setg(errp, "Cannot create a successor for a bitmap that is " > + "persistent"); > + return -1; > + } > + Oh? so we can't make backups with persistent bitmaps? (I'll keep reading forward in the series...) > if (bdrv_dirty_bitmap_frozen(bitmap)) { > error_setg(errp, "Cannot create a successor for a bitmap that is " > "currently frozen"); > diff --git a/include/block/block_int.h b/include/block/block_int.h > index 5fa58e8..fbc34af 100644 > --- a/include/block/block_int.h > +++ b/include/block/block_int.h > @@ -305,6 +305,14 @@ struct BlockDriver { > */ > void (*bdrv_drain)(BlockDriverState *bs); > > + /** > + * Make the dirty bitmap persistent if persistent=true or transient > + * otherwise. > + */ > + int (*bdrv_dirty_bitmap_set_persistent)(BlockDriverState *bs, > + BdrvDirtyBitmap *bitmap, > + bool persistent, Error **errp); > + > QLIST_ENTRY(BlockDriver) list; > }; > > diff --git a/include/block/dirty-bitmap.h b/include/block/dirty-bitmap.h > index d14d923..5885720 100644 > --- a/include/block/dirty-bitmap.h > +++ b/include/block/dirty-bitmap.h > @@ -24,6 +24,10 @@ BdrvDirtyBitmap *bdrv_reclaim_dirty_bitmap(BlockDriverState *bs, > BdrvDirtyBitmap *bdrv_find_dirty_bitmap(BlockDriverState *bs, > const char *name); > void bdrv_dirty_bitmap_make_anon(BdrvDirtyBitmap *bitmap); > +int bdrv_dirty_bitmap_set_persistent(BlockDriverState *bs, > + BdrvDirtyBitmap *bitmap, > + bool persistent, bool flag_only, > + Error **errp); > void bdrv_release_dirty_bitmap(BlockDriverState *bs, BdrvDirtyBitmap *bitmap); > void bdrv_disable_dirty_bitmap(BdrvDirtyBitmap *bitmap); > void bdrv_enable_dirty_bitmap(BdrvDirtyBitmap *bitmap); >
On 01/26/2016 05:38 AM, Fam Zheng wrote: > By implementing bdrv_dirty_bitmap_set_persistent, a driver can support > the persistent dirty bitmap feature. > > Once a dirty bitmap is made persistent, the driver is responsible for saving > the dirty bitmap when appropriate, for example before close; if a persistent > bitmap is removed or made non-persistent, .bdrv_dirty_bitmap_set_persistent > will be called, the driver should then remove the dirty bitmap from the disk. > > This operation is not recursed in block layer, a filter such as blkdebug needs > to implement the callback and explicitly pass down to bs->file, etc. > > Signed-off-by: Fam Zheng <famz@redhat.com> > --- > block/dirty-bitmap.c | 38 ++++++++++++++++++++++++++++++++++++++ > include/block/block_int.h | 8 ++++++++ > include/block/dirty-bitmap.h | 4 ++++ > 3 files changed, 50 insertions(+) > > diff --git a/block/dirty-bitmap.c b/block/dirty-bitmap.c > index 1aa7f76..882a0db 100644 > --- a/block/dirty-bitmap.c > +++ b/block/dirty-bitmap.c > @@ -43,6 +43,7 @@ struct BdrvDirtyBitmap { > int64_t size; /* Size of the bitmap (Number of sectors) */ > bool disabled; /* Bitmap is read-only */ > int active_iterators; /* How many iterators are active */ > + bool persistent; /* Whether this bitmap is persistent. */ > QLIST_ENTRY(BdrvDirtyBitmap) list; > }; > > @@ -71,6 +72,37 @@ void bdrv_dirty_bitmap_make_anon(BdrvDirtyBitmap *bitmap) > bitmap->name = NULL; > } > What's the intended usage of flag_only? (/keeps reading/...) > +int bdrv_dirty_bitmap_set_persistent(BlockDriverState *bs, > + BdrvDirtyBitmap *bitmap, > + bool persistent, bool flag_only, > + Error **errp) > +{ > + int ret = 0; > + > + if (!bitmap->name) { > + error_setg(errp, "Cannot change the persistent status of an anonymous" > + "bitmap"); > + return -EINVAL; > + } > + > + if (persistent == bitmap->persistent) { > + return 0; > + } > + > + if (!flag_only) { > + if (!bs->drv || !bs->drv->bdrv_dirty_bitmap_set_persistent) { > + error_setg(errp, "Not supported in this format."); > + return -ENOTSUP; > + } > + ret = bs->drv->bdrv_dirty_bitmap_set_persistent(bs, bitmap, persistent, > + errp); > + } > + if (!ret) { > + bitmap->persistent = persistent; > + } > + return ret; > +} > + > BdrvDirtyBitmap *bdrv_create_dirty_bitmap(BlockDriverState *bs, > uint32_t granularity, > const char *name, > @@ -194,6 +226,12 @@ int bdrv_dirty_bitmap_create_successor(BlockDriverState *bs, > uint64_t granularity; > BdrvDirtyBitmap *child; > > + if (bitmap->persistent) { > + error_setg(errp, "Cannot create a successor for a bitmap that is " > + "persistent"); > + return -1; > + } > + > if (bdrv_dirty_bitmap_frozen(bitmap)) { > error_setg(errp, "Cannot create a successor for a bitmap that is " > "currently frozen"); > diff --git a/include/block/block_int.h b/include/block/block_int.h > index 5fa58e8..fbc34af 100644 > --- a/include/block/block_int.h > +++ b/include/block/block_int.h > @@ -305,6 +305,14 @@ struct BlockDriver { > */ > void (*bdrv_drain)(BlockDriverState *bs); > > + /** > + * Make the dirty bitmap persistent if persistent=true or transient > + * otherwise. > + */ > + int (*bdrv_dirty_bitmap_set_persistent)(BlockDriverState *bs, > + BdrvDirtyBitmap *bitmap, > + bool persistent, Error **errp); > + > QLIST_ENTRY(BlockDriver) list; > }; > > diff --git a/include/block/dirty-bitmap.h b/include/block/dirty-bitmap.h > index d14d923..5885720 100644 > --- a/include/block/dirty-bitmap.h > +++ b/include/block/dirty-bitmap.h > @@ -24,6 +24,10 @@ BdrvDirtyBitmap *bdrv_reclaim_dirty_bitmap(BlockDriverState *bs, > BdrvDirtyBitmap *bdrv_find_dirty_bitmap(BlockDriverState *bs, > const char *name); > void bdrv_dirty_bitmap_make_anon(BdrvDirtyBitmap *bitmap); > +int bdrv_dirty_bitmap_set_persistent(BlockDriverState *bs, > + BdrvDirtyBitmap *bitmap, > + bool persistent, bool flag_only, > + Error **errp); > void bdrv_release_dirty_bitmap(BlockDriverState *bs, BdrvDirtyBitmap *bitmap); > void bdrv_disable_dirty_bitmap(BdrvDirtyBitmap *bitmap); > void bdrv_enable_dirty_bitmap(BdrvDirtyBitmap *bitmap); >
diff --git a/block/dirty-bitmap.c b/block/dirty-bitmap.c index 1aa7f76..882a0db 100644 --- a/block/dirty-bitmap.c +++ b/block/dirty-bitmap.c @@ -43,6 +43,7 @@ struct BdrvDirtyBitmap { int64_t size; /* Size of the bitmap (Number of sectors) */ bool disabled; /* Bitmap is read-only */ int active_iterators; /* How many iterators are active */ + bool persistent; /* Whether this bitmap is persistent. */ QLIST_ENTRY(BdrvDirtyBitmap) list; }; @@ -71,6 +72,37 @@ void bdrv_dirty_bitmap_make_anon(BdrvDirtyBitmap *bitmap) bitmap->name = NULL; } +int bdrv_dirty_bitmap_set_persistent(BlockDriverState *bs, + BdrvDirtyBitmap *bitmap, + bool persistent, bool flag_only, + Error **errp) +{ + int ret = 0; + + if (!bitmap->name) { + error_setg(errp, "Cannot change the persistent status of an anonymous" + "bitmap"); + return -EINVAL; + } + + if (persistent == bitmap->persistent) { + return 0; + } + + if (!flag_only) { + if (!bs->drv || !bs->drv->bdrv_dirty_bitmap_set_persistent) { + error_setg(errp, "Not supported in this format."); + return -ENOTSUP; + } + ret = bs->drv->bdrv_dirty_bitmap_set_persistent(bs, bitmap, persistent, + errp); + } + if (!ret) { + bitmap->persistent = persistent; + } + return ret; +} + BdrvDirtyBitmap *bdrv_create_dirty_bitmap(BlockDriverState *bs, uint32_t granularity, const char *name, @@ -194,6 +226,12 @@ int bdrv_dirty_bitmap_create_successor(BlockDriverState *bs, uint64_t granularity; BdrvDirtyBitmap *child; + if (bitmap->persistent) { + error_setg(errp, "Cannot create a successor for a bitmap that is " + "persistent"); + return -1; + } + if (bdrv_dirty_bitmap_frozen(bitmap)) { error_setg(errp, "Cannot create a successor for a bitmap that is " "currently frozen"); diff --git a/include/block/block_int.h b/include/block/block_int.h index 5fa58e8..fbc34af 100644 --- a/include/block/block_int.h +++ b/include/block/block_int.h @@ -305,6 +305,14 @@ struct BlockDriver { */ void (*bdrv_drain)(BlockDriverState *bs); + /** + * Make the dirty bitmap persistent if persistent=true or transient + * otherwise. + */ + int (*bdrv_dirty_bitmap_set_persistent)(BlockDriverState *bs, + BdrvDirtyBitmap *bitmap, + bool persistent, Error **errp); + QLIST_ENTRY(BlockDriver) list; }; diff --git a/include/block/dirty-bitmap.h b/include/block/dirty-bitmap.h index d14d923..5885720 100644 --- a/include/block/dirty-bitmap.h +++ b/include/block/dirty-bitmap.h @@ -24,6 +24,10 @@ BdrvDirtyBitmap *bdrv_reclaim_dirty_bitmap(BlockDriverState *bs, BdrvDirtyBitmap *bdrv_find_dirty_bitmap(BlockDriverState *bs, const char *name); void bdrv_dirty_bitmap_make_anon(BdrvDirtyBitmap *bitmap); +int bdrv_dirty_bitmap_set_persistent(BlockDriverState *bs, + BdrvDirtyBitmap *bitmap, + bool persistent, bool flag_only, + Error **errp); void bdrv_release_dirty_bitmap(BlockDriverState *bs, BdrvDirtyBitmap *bitmap); void bdrv_disable_dirty_bitmap(BdrvDirtyBitmap *bitmap); void bdrv_enable_dirty_bitmap(BdrvDirtyBitmap *bitmap);
By implementing bdrv_dirty_bitmap_set_persistent, a driver can support the persistent dirty bitmap feature. Once a dirty bitmap is made persistent, the driver is responsible for saving the dirty bitmap when appropriate, for example before close; if a persistent bitmap is removed or made non-persistent, .bdrv_dirty_bitmap_set_persistent will be called, the driver should then remove the dirty bitmap from the disk. This operation is not recursed in block layer, a filter such as blkdebug needs to implement the callback and explicitly pass down to bs->file, etc. Signed-off-by: Fam Zheng <famz@redhat.com> --- block/dirty-bitmap.c | 38 ++++++++++++++++++++++++++++++++++++++ include/block/block_int.h | 8 ++++++++ include/block/dirty-bitmap.h | 4 ++++ 3 files changed, 50 insertions(+)