@@ -995,6 +995,15 @@ static int bdrv_open_common(BlockDriverState *bs, BdrvChild *file,
goto free_and_fail;
}
+ if (!(open_flags & BDRV_O_NO_LOCK)) {
+ BdrvLockfCmd cmd = open_flags & BDRV_O_RDWR ? BDRV_LOCKF_RWLOCK :
+ BDRV_LOCKF_ROLOCK;
+ ret = bdrv_lockf(bs, cmd, errp);
+ if (ret != 0 && ret != -ENOTSUP) {
+ goto free_and_fail;
+ }
+ }
+
ret = refresh_total_sectors(bs, bs->total_sectors);
if (ret < 0) {
error_setg_errno(errp, -ret, "Could not refresh total sector count");
@@ -2141,6 +2150,10 @@ static void bdrv_close(BlockDriverState *bs)
blk_dev_change_media_cb(bs->blk, false);
}
+ if (bs->drv && !(bs->open_flags & BDRV_O_NO_LOCK)) {
+ bdrv_lockf(bs, BDRV_LOCKF_UNLOCK, &error_abort);
+ }
+
if (bs->drv) {
BdrvChild *child, *next;
@@ -3981,3 +3994,15 @@ void bdrv_refresh_filename(BlockDriverState *bs)
QDECREF(json);
}
}
+
+int bdrv_lockf(BlockDriverState *bs, BdrvLockfCmd cmd, Error **errp)
+{
+ if (!bs->drv) {
+ error_setg(errp, "No medium to lock");
+ return -ENOMEDIUM;
+ } else if (!bs->drv->bdrv_lockf) {
+ return -ENOTSUP;
+ } else {
+ return bs->drv->bdrv_lockf(bs, cmd, errp);
+ }
+}
@@ -542,4 +542,12 @@ void bdrv_drained_begin(BlockDriverState *bs);
*/
void bdrv_drained_end(BlockDriverState *bs);
+typedef enum {
+ BDRV_LOCKF_RWLOCK,
+ BDRV_LOCKF_ROLOCK,
+ BDRV_LOCKF_UNLOCK,
+} BdrvLockfCmd;
+
+int bdrv_lockf(BlockDriverState *bs, BdrvLockfCmd cmd, Error **errp);
+
#endif
@@ -317,6 +317,11 @@ struct BlockDriver {
*/
void (*bdrv_drain)(BlockDriverState *bs);
+ /**
+ * Lock/unlock the image.
+ */
+ int (*bdrv_lockf)(BlockDriverState *bs, BdrvLockfCmd cmd, Error **errp);
+
QLIST_ENTRY(BlockDriver) list;
};
Block drivers can implement this new operation .bdrv_lockf to actually lock the image in the protocol specific way. Signed-off-by: Fam Zheng <famz@redhat.com> --- block.c | 25 +++++++++++++++++++++++++ include/block/block.h | 8 ++++++++ include/block/block_int.h | 5 +++++ 3 files changed, 38 insertions(+)