raw-posix driver changes for bdrv_reopen_xx functions to safely reopen image files. Reopening of image files while changing hostcache dynamically is handled here.
Signed-off-by: Supriya Kannery <supri...@linux.vnet.ibm.com> Index: qemu/block/raw.c =================================================================== --- qemu.orig/block/raw.c +++ qemu/block/raw.c @@ -9,6 +9,23 @@ static int raw_open(BlockDriverState *bs return 0; } +static int raw_reopen_prepare(BlockDriverState *bs, BDRVReopenState **prs, + int flags) +{ + return bdrv_reopen_prepare(bs->file, prs, flags); +} + +static void raw_reopen_commit(BlockDriverState *bs, BDRVReopenState *rs, + int flags) +{ + bdrv_reopen_commit(bs->file, rs, flags); +} + +static void raw_reopen_abort(BlockDriverState *bs, BDRVReopenState *rs) +{ + bdrv_reopen_abort(bs->file, rs); +} + static int coroutine_fn raw_co_readv(BlockDriverState *bs, int64_t sector_num, int nb_sectors, QEMUIOVector *qiov) { @@ -107,10 +124,12 @@ static BlockDriver bdrv_raw = { /* It's really 0, but we need to make g_malloc() happy */ .instance_size = 1, - .bdrv_open = raw_open, + .bdrv_reopen_prepare + = raw_reopen_prepare, + .bdrv_reopen_commit = raw_reopen_commit, + .bdrv_reopen_abort = raw_reopen_abort, .bdrv_close = raw_close, - .bdrv_co_readv = raw_co_readv, .bdrv_co_writev = raw_co_writev, .bdrv_co_flush = raw_co_flush, Index: qemu/block/raw-posix.c =================================================================== --- qemu.orig/block/raw-posix.c +++ qemu/block/raw-posix.c @@ -136,6 +136,11 @@ typedef struct BDRVRawState { #endif } BDRVRawState; +typedef struct BDRVRawReopenState { + int reopen_fd; + BDRVReopenState reopen_state; +} BDRVRawReopenState; + static int fd_open(BlockDriverState *bs); static int64_t raw_getlength(BlockDriverState *bs); @@ -279,6 +284,70 @@ static int raw_open(BlockDriverState *bs return raw_open_common(bs, filename, flags, 0); } +static int raw_reopen_prepare(BlockDriverState *bs, BDRVReopenState **prs, + int flags) +{ + BDRVRawReopenState *raw_rs = g_malloc0(sizeof(BDRVRawReopenState)); + BDRVRawState *s = bs->opaque; + int ret = 0; + + raw_rs->reopen_state.reopen_flags = s->open_flags; + raw_rs->reopen_state.bs = bs; + raw_rs->reopen_fd = -1; + *prs = &(raw_rs->reopen_state); + + /* Flags that can be set using fcntl */ + int fcntl_flags = BDRV_O_NOCACHE; + + if ((bs->open_flags & ~fcntl_flags) == (flags & ~fcntl_flags)) { + raw_rs->reopen_fd = dup(s->fd); + if (raw_rs->reopen_fd <= 0) { + return -1; + } + if ((flags & BDRV_O_NOCACHE)) { + raw_rs->reopen_state.reopen_flags |= O_DIRECT; + } else { + raw_rs->reopen_state.reopen_flags &= ~O_DIRECT; + } + ret = fcntl_setfl(raw_rs->reopen_fd, raw_rs->reopen_state.reopen_flags); + } else { + + /* TBD: Handle O_DSYNC and other flags. For now return error */ + ret = -1; + } + return ret; +} + +static void raw_reopen_commit(BlockDriverState *bs, BDRVReopenState *rs, + int flags) +{ + BDRVRawReopenState *raw_rs; + BDRVRawState *s = bs->opaque; + + raw_rs = container_of(rs, BDRVRawReopenState, reopen_state); + + /* Set new flags, so replace old fd with new one */ + close(s->fd); + s->fd = raw_rs->reopen_fd; + s->open_flags = rs->reopen_flags; + bs->open_flags = flags; + + g_free(raw_rs); + +} + +static void raw_reopen_abort(BlockDriverState *bs, BDRVReopenState *rs) +{ + BDRVRawReopenState *raw_rs; + + raw_rs = container_of(rs, BDRVRawReopenState, reopen_state); + + if (raw_rs->reopen_fd != -1) { + close(raw_rs->reopen_fd); + } + g_free(raw_rs); +} + /* XXX: use host sector size if necessary with: #ifdef DIOCGSECTORSIZE { @@ -631,6 +700,9 @@ static BlockDriver bdrv_file = { .instance_size = sizeof(BDRVRawState), .bdrv_probe = NULL, /* no probe for protocols */ .bdrv_file_open = raw_open, + .bdrv_reopen_prepare = raw_reopen_prepare, + .bdrv_reopen_commit = raw_reopen_commit, + .bdrv_reopen_abort = raw_reopen_abort, .bdrv_close = raw_close, .bdrv_create = raw_create, .bdrv_co_discard = raw_co_discard,