Signed-off-by: Hyman Huang <yong.hu...@smartx.com> --- block/generic-luks.c | 104 ++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 102 insertions(+), 2 deletions(-)
diff --git a/block/generic-luks.c b/block/generic-luks.c index ebc0365d40..32cbedc86f 100644 --- a/block/generic-luks.c +++ b/block/generic-luks.c @@ -23,8 +23,14 @@ #include "qemu/osdep.h" #include "block/block_int.h" +#include "block/block-io.h" #include "block/crypto.h" +#include "block/qdict.h" #include "crypto/block.h" +#include "qapi/error.h" +#include "qemu/error-report.h" +#include "qemu/module.h" +#include "qemu/option.h" #include "generic-luks.h" @@ -50,10 +56,89 @@ static QemuOptsList gluks_create_opts_luks = { }, }; +static int gluks_read_func(QCryptoBlock *block, + size_t offset, + uint8_t *buf, + size_t buflen, + void *opaque, + Error **errp) +{ + + BlockDriverState *bs = opaque; + BDRVGLUKSState *s = bs->opaque; + ssize_t ret; + + GLOBAL_STATE_CODE(); + GRAPH_RDLOCK_GUARD_MAINLOOP(); + + ret = bdrv_pread(s->header, offset, buflen, buf, 0); + if (ret < 0) { + error_setg_errno(errp, -ret, "Could not read generic luks header"); + return ret; + } + return 0; +} + static int gluks_open(BlockDriverState *bs, QDict *options, int flags, Error **errp) { - return 0; + BDRVGLUKSState *s = bs->opaque; + QemuOpts *opts = NULL; + QCryptoBlockOpenOptions *open_opts = NULL; + QDict *cryptoopts = NULL; + unsigned int cflags = 0; + int ret; + + GLOBAL_STATE_CODE(); + + if (!bdrv_open_child(NULL, options, "file", bs, &child_of_bds, + (BDRV_CHILD_DATA | BDRV_CHILD_PRIMARY), false, errp)) { + return -EINVAL; + } + s->header = bdrv_open_child(NULL, options, "header", bs, + &child_of_bds, BDRV_CHILD_METADATA, false, + errp); + if (!s->header) { + return -EINVAL; + } + + GRAPH_RDLOCK_GUARD_MAINLOOP(); + + opts = qemu_opts_create(&block_crypto_runtime_opts_luks, + NULL, 0, &error_abort); + if (!qemu_opts_absorb_qdict(opts, options, errp)) { + ret = -EINVAL; + goto cleanup; + } + + cryptoopts = qemu_opts_to_qdict(opts, NULL); + qdict_put_str(cryptoopts, "format", + QCryptoBlockFormat_str(Q_CRYPTO_BLOCK_FORMAT_GLUKS)); + + open_opts = block_crypto_open_opts_init(cryptoopts, errp); + if (!open_opts) { + goto cleanup; + } + + s->crypto.block = qcrypto_block_open(open_opts, NULL, + gluks_read_func, + bs, + cflags, + 1, + errp); + if (!s->crypto.block) { + ret = -EIO; + goto cleanup; + } + + s->header_size = qcrypto_block_get_payload_offset(s->crypto.block); + qcrypto_block_set_payload_offset(s->crypto.block, 0); + + ret = 0; + cleanup: + qobject_unref(cryptoopts); + qapi_free_QCryptoBlockOpenOptions(open_opts); + return ret; } static int coroutine_fn GRAPH_UNLOCKED @@ -70,13 +155,24 @@ gluks_child_perms(BlockDriverState *bs, BdrvChild *c, uint64_t perm, uint64_t shared, uint64_t *nperm, uint64_t *nshared) { + if (role & BDRV_CHILD_METADATA) { + /* assign read permission only */ + perm |= BLK_PERM_CONSISTENT_READ; + /* share all permissions */ + shared |= BLK_PERM_ALL; + *nperm = perm; + *nshared = shared; + return; + } + + bdrv_default_perms(bs, c, role, reopen_queue, perm, shared, nperm, nshared); } static int64_t coroutine_fn GRAPH_RDLOCK gluks_co_getlength(BlockDriverState *bs) { - return 0; + return bdrv_co_getlength(bs->file->bs); } static BlockDriver bdrv_generic_luks = { @@ -87,8 +183,12 @@ static BlockDriver bdrv_generic_luks = { .bdrv_child_perm = gluks_child_perms, .bdrv_co_getlength = gluks_co_getlength, + .bdrv_close = block_crypto_close, + .bdrv_co_preadv = block_crypto_co_preadv, + .bdrv_co_pwritev = block_crypto_co_pwritev, .create_opts = &gluks_create_opts_luks, .amend_opts = &block_crypto_amend_opts_luks, + .is_format = false, }; static void block_generic_luks_init(void) -- 2.39.1