From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-0.2 required=3.0 tests=BAYES_00,DKIM_INVALID, DKIM_SIGNED,HEADER_FROM_DIFFERENT_DOMAINS,HTML_MESSAGE,HTML_MIME_NO_HTML_TAG, INCLUDES_CR_TRAILER,INCLUDES_PATCH,MAILING_LIST_MULTI,MIME_HTML_ONLY, SPF_HELO_NONE,SPF_PASS,URIBL_BLOCKED autolearn=no autolearn_force=no version=3.4.0 Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id EB642C433ED for ; Wed, 5 May 2021 15:47:54 +0000 (UTC) Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mail.kernel.org (Postfix) with ESMTPS id 3B81D610FC for ; Wed, 5 May 2021 15:47:54 +0000 (UTC) DMARC-Filter: OpenDMARC Filter v1.3.2 mail.kernel.org 3B81D610FC Authentication-Results: mail.kernel.org; dmarc=fail (p=none dis=none) header.from=il.ibm.com Authentication-Results: mail.kernel.org; spf=pass smtp.mailfrom=qemu-devel-bounces+qemu-devel=archiver.kernel.org@nongnu.org Received: from localhost ([::1]:46756 helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1leJke-00035t-Q6 for qemu-devel@archiver.kernel.org; Wed, 05 May 2021 11:47:52 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]:39330) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1leJVg-0002yY-DF for qemu-devel@nongnu.org; Wed, 05 May 2021 11:32:24 -0400 Received: from mx0b-001b2d01.pphosted.com ([148.163.158.5]:53450) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1leJVZ-0005oZ-52 for qemu-devel@nongnu.org; Wed, 05 May 2021 11:32:24 -0400 Received: from pps.filterd (m0098421.ppops.net [127.0.0.1]) by mx0a-001b2d01.pphosted.com (8.16.0.43/8.16.0.43) with SMTP id 145F3G3f139909 for ; Wed, 5 May 2021 11:32:13 -0400 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=ibm.com; h=in-reply-to : from : to : cc : date : references : content-type : message-id : content-transfer-encoding : mime-version : subject; s=pp1; bh=eqFESLcHh1iCZ+Lgp3SJpFIktm6PsCTl2ekp7UHcgRI=; b=RBa3ESHIZoR/d2/2KKAD9X7G5yXT4q1Yog5iVfkYfOL913cQzp8xdjlyJWY+GMyv+vpk GLV6jXaBDIDCtX0Q91HOnmSj8eqsSDREIje6PNMhVg3ZZOlruOQ4RMr8Wr0dOwBVV5K4 TMiZM9e0nS8/tNNuPmrGbVf3YG7KJva0VfUTLtvod3S/w8QUdzepHn2w1Cl7tPUZK2NT CR3kShox8WHzbR0tC9+6QLdjr0vsnV3umjrLhADYJ+BeugEK+fAgQ0TEX0HnF0Hp4vJF OabhJC6212lMcQI525+4x9qdNK/OkvJEBpAQpsG/Ba1a+ktfajpL4Q2CEDYOPgmH9a3o zQ== Received: from smtp.notes.na.collabserv.com (smtp.notes.na.collabserv.com [192.155.248.90]) by mx0a-001b2d01.pphosted.com with ESMTP id 38bwcu1g3c-1 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NOT) for ; Wed, 05 May 2021 11:32:12 -0400 Received: from localhost by smtp.notes.na.collabserv.com with smtp.notes.na.collabserv.com ESMTP for from ; Wed, 5 May 2021 15:32:12 -0000 Received: from us1a3-smtp02.a3.dal06.isc4sb.com (10.106.154.159) by smtp.notes.na.collabserv.com (10.106.227.141) with smtp.notes.na.collabserv.com ESMTP; Wed, 5 May 2021 15:32:09 -0000 Received: from us1a3-mail134.a3.dal06.isc4sb.com ([10.146.45.171]) by us1a3-smtp02.a3.dal06.isc4sb.com with ESMTP id 2021050515320914-449491 ; Wed, 5 May 2021 15:32:09 +0000 In-Reply-To: From: "Or Ozeri" To: "=?ISO-8859-1?Q?Daniel_P=2E_Berrang=E9?=" Date: Wed, 5 May 2021 15:32:09 +0000 Sensitivity: Importance: Normal X-Priority: 3 (Normal) References: , <20210502073617.2978836-1-oro@il.ibm.com> X-Mailer: IBM iNotes ($HaikuForm 1054.1) | IBM Domino Build SCN1812108_20180501T0841_FP130 January 13, 2021 at 14:04 X-LLNOutbound: False X-Disclaimed: 38219 X-TNEFEvaluated: 1 Content-Type: text/html; charset=UTF-8 x-cbid: 21050515-3649-0000-0000-0000058350D2 X-IBM-SpamModules-Scores: BY=0.293256; FL=0; FP=0; FZ=0; HX=0; KW=0; PH=0; SC=0; ST=0; TS=0; UL=0; ISC=; MB=0.198149 X-IBM-SpamModules-Versions: BY=3.00015144; HX=3.00000242; KW=3.00000007; PH=3.00000004; SC=3.00000296; SDB=6.01543696; UDB=6.00825223; IPR=6.01310096; MB=3.00036875; MTD=3.00000008; XFM=3.00000015; UTC=2021-05-05 15:32:10 X-IBM-AV-DETECTION: SAVI=unsuspicious REMOTE=unsuspicious XFE=unused X-IBM-AV-VERSION: SAVI=2021-03-22 13:42:56 - 6.00012377 x-cbparentid: 21050515-3650-0000-0000-0000D0415192 Message-Id: X-Proofpoint-ORIG-GUID: gUi6jKTqOGxH-yxi2vjUc3cMd3OMjk5p X-Proofpoint-GUID: gUi6jKTqOGxH-yxi2vjUc3cMd3OMjk5p Content-Transfer-Encoding: quoted-printable X-Proofpoint-UnRewURL: 18 URL's were un-rewritten MIME-Version: 1.0 Subject: RE: [PATCH] block/rbd: Add support for rbd image encryption X-Proofpoint-Virus-Version: vendor=fsecure engine=2.50.10434:6.0.391, 18.0.761 definitions=2021-05-05_09:2021-05-05, 2021-05-05 signatures=0 X-Proofpoint-Spam-Reason: orgsafe Received-SPF: pass client-ip=148.163.158.5; envelope-from=ORO@il.ibm.com; helo=mx0b-001b2d01.pphosted.com X-Spam_score_int: -21 X-Spam_score: -2.2 X-Spam_bar: -- X-Spam_report: (-2.2 / 5.0 requ) BAYES_00=-1.9, DKIM_SIGNED=0.1, DKIM_VALID=-0.1, DKIM_VALID_EF=-0.1, HTML_MESSAGE=0.001, HTML_MIME_NO_HTML_TAG=0.377, MIME_HTML_ONLY=0.1, RCVD_IN_DNSWL_LOW=-0.7, RCVD_IN_MSPIKE_H2=-0.001, SPF_HELO_NONE=0.001, SPF_PASS=-0.001 autolearn=ham autolearn_force=no X-Spam_action: no action X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.23 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: kwolf@redhat.com, Danny Harnik , qemu-devel@nongnu.org, qemu-block@nongnu.org, to.my.trociny@gmail.com Errors-To: qemu-devel-bounces+qemu-devel=archiver.kernel.org@nongnu.org Sender: "Qemu-devel" Thanks Daniel!
I prepared a modified patch addressing all of your suggesti= ons (including resizing after formatting to increase the image size).
=
The only thing I'm not sure about is your last point regarding reporti= ng image is encrypted.

When I followed the flo= w of "qemu-img info" on an "rbd:pool/image" I saw that this information is = extracted from the root BlockDriverState.
In our case, the root B= lockDriverState comes from:

BlockDriver bdrv_raw =3D {
    .format_name          =3D "raw",

...

The RBD driver is a child of this ro= ot raw driver.

Given this situation, it is not clear to me= how can I set:
bs->drv->format_name=3D"luks2", bs->encrypte= d=3Dtrue
On the root BlockDriverState.

Any advic= e?

---= --"Daniel P. Berrang=C3=A9" <berrange@redhat.com> wrote: -----
To: Or Ozeri <oro@il.ibm.com>
From: "D= aniel P. Berrang=C3=A9" <berrange@redhat.com>
Date: 05/04/2021 05:47PM
Cc: = qemu-devel@nongn= u.org, kwolf@redh= at.com, to= .my.trociny@gmail.com, qemu-block@nongnu.org, dannyh@il.ibm.com
Subject: [EXTERNAL] Re: [PATCH]= block/rbd: Add support for rbd image encryption

On Sun, May 02, 2021 at 10:36:17A= M +0300, Or Ozeri wrote:
> Starting from ceph Pacific, RBD has built-= in support for image-level encryption.
> Currently supported formats = are LUKS version 1 and 2.
>
> There are 2 new relevant librbd = APIs for controlling encryption, both expect an
> open image context:=
>
> rbd_encryption_format: formats an image (i.e. writes the = LUKS header)
> rbd_encryption_load: loads encryptor/decryptor to the = image IO stack

>
> This commit extends the qemu rbd driver= API to support the above.
>
> Signed-off-by: Or Ozeri <oro@il.ibm.com>
= > ---
>  block/rbd.c          | 230 = ++++++++++++++++++++++++++++++++++++++++++-
>  qapi/block-core.j= son |  61 ++++++++++++
>  2 files changed, 287 insertions(+= ), 4 deletions(-)
>
> diff --git a/block/rbd.c b/block/rbd.c> index f098a89c7b..1239e97889 100644
> --- a/block/rbd.c
>= ; +++ b/block/rbd.c
> @@ -108,6 +108,13 @@ typedef struct BDRVRBDStat= e {
>      uint64_t image_size;
>  } BDRVRB= DState;
>  
> +#ifdef LIBRBD_SUPPORTS_ENCRYPTION
> += typedef int (*RbdEncryptionFunc)(rbd_image_t image,
> +    =                     &nbs= p;       rbd_encryption_format_t format,
> +   &n= bsp;                     =         rbd_encryption_options_t opts,
> +  =                     &nbs= p;         size_t opts_size);
> +#endif
> +=
>  static int qemu_rbd_connect(rados_t *cluster, rados_ioctx_t = *io_ctx,
>                 &n= bsp;            BlockdevOptionsRbd *opts, boo= l cache,
>                 &n= bsp;            const char *keypairs, const c= har *secretid,
> @@ -341,6 +348,115 @@ static void qemu_rbd_memset(RA= DOSCB *rcb, int64_t offs)
>      }
>  }
= >  
> +#ifdef LIBRBD_SUPPORTS_ENCRYPTION
> +static int = qemu_rbd_convert_luks_options(
> +        RbdEncr= yptionOptionsLUKSBase *luks_opts,
> +        rbd_= encryption_algorithm_t *alg,
> +        char** pa= ssphrase,
> +        Error **errp)
> +{
= > +    int r =3D 0;
> +
> +    if (!luks= _opts->has_passphrase_secret) {
> +        r = =3D -EINVAL;
> +        error_setg_errno(errp, -r= , "missing encrypt.passphrase-secret");
> +       &nbs= p;return r;
> +    }
> +
> +    *pass= phrase =3D qcrypto_secret_lookup_as_utf8(luks_opts->passphrase_secret,> +                   &nb= sp;                     &= nbsp;      errp);
> +    if (!*passphrase) {=
> +        return -EIO;
> +    }=
> +
> +    if (luks_opts->has_cipher_alg) {
&g= t; +        switch (luks_opts->cipher_alg) {
>= +            case RBD_ENCRYPTION_ALGORITHM_A= ES_128: {
> +                = *alg =3D RBD_ENCRYPTION_ALGORITHM_AES128;
> +       &n= bsp;        break;
> +        = ;    }
> +            case RB= D_ENCRYPTION_ALGORITHM_AES_256: {
> +         &nb= sp;      *alg =3D RBD_ENCRYPTION_ALGORITHM_AES256;
> +=                break;
> + &n= bsp;          }
> +       &nb= sp;    default: {
> +           &n= bsp;    r =3D -ENOTSUP;
> +         &nb= sp;      error_setg_errno(errp, -r, "unknown encryption algo= rithm: %u",
> +               &nbs= p;                 luks_opts->ci= pher_alg);
> +                = ;return r;
> +            }
> + &= nbsp;      }
> +    } else {
> +  = ;      /* default alg */
> +       &nbs= p;*alg =3D RBD_ENCRYPTION_ALGORITHM_AES256;
> +    }
>= ; +
> +    return 0;
> +}
> +
> +static i= nt qemu_rbd_apply_encryption_function(rbd_image_t image,
> +   &= nbsp;                    =                     &nbs= p;RbdEncryptionSpec* spec,
> +           &nb= sp;                     &= nbsp;            RbdEncryptionFunc func,
&= gt; +                    =                     &nbs= p;    Error **errp)
> +{
> +    int r =3D 0= ;
> +    g_autofree char *passphrase =3D NULL;
> + &n= bsp;  g_autofree rbd_encryption_options_t opts =3D NULL;
> + &nb= sp;  rbd_encryption_format_t format;
> +    size_t opt= s_size;
> +
> +    switch (spec->format) {
>= +        case RBD_IMAGE_ENCRYPTION_FORMAT_LUKS1: {
= > +            rbd_encryption_luks1_format= _options_t *luks1_opts =3D
> +           &nb= sp;        g_new0(rbd_encryption_luks1_format_options_t= , 1);
> +            format =3D RBD_ENC= RYPTION_FORMAT_LUKS1;
> +            op= ts =3D luks1_opts;
> +            opts_= size =3D sizeof(rbd_encryption_luks1_format_options_t);
> +   &n= bsp;        r =3D qemu_rbd_convert_luks_options(
>= ; +                    qa= pi_RbdEncryptionOptionsLUKS1_base(&spec->u.luks1),
> +   =                  &luks1_op= ts->alg, &passphrase, errp);
> +         &= nbsp;  if (passphrase) {
> +           =      luks1_opts->passphrase =3D passphrase;
> + &nb= sp;              luks1_opts->passphra= se_size =3D strlen(passphrase);
> +          = ;  }
> +            break;
>= +        }
> +        case R= BD_IMAGE_ENCRYPTION_FORMAT_LUKS2: {
> +         &= nbsp;  rbd_encryption_luks2_format_options_t *luks2_opts =3D
> +=                    g_new= 0(rbd_encryption_luks2_format_options_t, 1);
> +      =      format =3D RBD_ENCRYPTION_FORMAT_LUKS2;
> + &nbs= p;          opts =3D luks2_opts;
> +   =          opts_size =3D sizeof(rbd_encryption_luks2= _format_options_t);
> +            r = =3D qemu_rbd_convert_luks_options(
> +         &n= bsp;          qapi_RbdEncryptionOptionsLUKS2_base(= &spec->u.luks2),
> +            =        &luks2_opts->alg, &passphrase, errp)= ;
> +            if (passphrase) {
&= gt; +                luks2_opts->= ;passphrase =3D passphrase;
> +           &n= bsp;    luks2_opts->passphrase_size =3D strlen(passphrase);> +            }
> +     =        break;
> +        }> +        default: {
> +      = ;      r =3D -ENOTSUP;
> +        =    error_setg_errno(
> +          = ;          errp, -r, "unknown image encryption for= mat: %u",
> +                =    spec->format);
> +        }
&= gt; +    }
> +
> +    if (r < 0) {
&g= t; +        return r;
> +    }
> = +
> +    r =3D func(image, format, opts, opts_size);
>= ; +    if (r < 0) {
> +        error= _setg_errno(errp, -r, "error applying encryption function");
> + &nbs= p;  }
> +
> +    return r;
> +}
> +#= endif
> +
>  /* FIXME Deprecate and remove keypairs or mak= e it available in QMP. */
>  static int qemu_rbd_do_create(Block= devCreateOptions *options,
>            = ;                    cons= t char *keypairs, const char *password_secret,
> @@ -358,6 +474,13 @@= static int qemu_rbd_do_create(BlockdevCreateOptions *options,
> &nbs= p;        return -EINVAL;
>      }=
>  
> +#ifndef LIBRBD_SUPPORTS_ENCRYPTION
> +  = ;  if (opts->location->has_encrypt) {
> +     &n= bsp;  error_setg(errp, "RBD library does not support image encryption"= );
> +        return -ENOTSUP;
> +   &= nbsp;}
> +#endif
> +
>      if (opts->h= as_cluster_size) {
>          int64_t objsiz= e =3D opts->cluster_size;
>          if (= (objsize - 1) & objsize) {    /* not a power of 2? */
>= @@ -383,6 +506,30 @@ static int qemu_rbd_do_create(BlockdevCreateOptions *= options,
>          goto out;
>  =    }
>  
> +#ifdef LIBRBD_SUPPORTS_ENCRYPTION> +    if (opts->location->has_encrypt) {
> + &n= bsp;      rbd_image_t image;
> +
> +   &nbs= p;    ret =3D rbd_open(io_ctx, opts->location->image, &= image, NULL);
> +        if (ret < 0) {
>= ; +            error_setg_errno(errp, -ret, "= error reading header from %s",
> +          =                   opts->lo= cation->image);
> +            goto = out;
> +        }
> +
> +   &nbs= p;    ret =3D qemu_rbd_apply_encryption_function(image,
> +=                     &nbs= p;                     &n= bsp;     opts->location->encrypt,
> +     &= nbsp;                    =                     &nbs= p; &rbd_encryption_format,
> +          =                     &nbs= p;                 errp);
> +=        rbd_close(image);
> +      = ;  if (ret < 0) {
> +           &nbs= p;/* encryption format fail, try removing the image */
> +   &nb= sp;        rbd_remove(io_ctx, opts->location->ima= ge);
> +            goto out;
> +=        }
> +    }
> +#endif
<= br>What happens to the size of the image when creating with luks ? LUKS
= will typically have at least 1 MB of overhead for the headers. When
QEMU= gets told to create an image with a size "512MB" that refers to
the gue= st exposed size. So with LUKS QEMU might allocate 513 MB instead
on the = host POV, to ensure the guest POV is still 512 MB.  Does RBD
do thi= s correctly and if not, can QEMU adjust to take this into account ?

=

> +
>      ret =3D 0;
>  out:>      rados_ioctx_destroy(io_ctx);
> @@ -395,6 +5= 42,42 @@ static int qemu_rbd_co_create(BlockdevCreateOptions *options, Erro= r **errp)
>      return qemu_rbd_do_create(options, NU= LL, NULL, errp);
>  }
>  
> +static int qemu_rb= d_extract_encryption_spec(QemuOpts *opts,
> +       &n= bsp;                     =                RbdEncryptionSpec **= spec,
> +                 &nb= sp;                     &= nbsp;    Error **errp)
> +{
> +    QDict *o= pts_qdict;
> +    QDict *encrypt_qdict;
> +   &n= bsp;Visitor *v;
> +    int ret =3D 0;
> +
> + &= nbsp;  opts_qdict =3D qemu_opts_to_qdict(opts, NULL);
> +  =  qdict_extract_subqdict(opts_qdict, &encrypt_qdict, "encrypt.");<= br>> +    qobject_unref(opts_qdict);
> +    if= (!qdict_size(encrypt_qdict)) {
> +        *spec = =3D NULL;
> +        goto exit;
> +   =  }
> +
> +    /* Convert options into a QAPI obj= ect */
> +    v =3D qobject_input_visitor_new_flat_confused= (encrypt_qdict, errp);
> +    if (!v) {
> +   &n= bsp;    ret =3D -EINVAL;
> +        got= o exit;
> +    }
> +
> +    visit_typ= e_RbdEncryptionSpec(v, NULL, spec, errp);
> +    visit_free= (v);
> +    if (!*spec) {
> +       &n= bsp;ret =3D -EINVAL;
> +        goto exit;
>= ; +    }
> +
> +exit:
> +    qobject_= unref(encrypt_qdict);
> +    return ret;
> +}
>= +
>  static int coroutine_fn qemu_rbd_co_create_opts(BlockDrive= r *drv,
>                 &nb= sp;                     &= nbsp;          const char *filename,
>  = ;                     &nb= sp;                     &= nbsp;    QemuOpts *opts,
> @@ -403,6 +586,7 @@ static int c= oroutine_fn qemu_rbd_co_create_opts(BlockDriver *drv,
>    =  BlockdevCreateOptions *create_options;
>      B= lockdevCreateOptionsRbd *rbd_opts;
>      BlockdevOpti= onsRbd *loc;
> +    RbdEncryptionSpec *encryption_spec =3D = NULL;
>      Error *local_err =3D NULL;
>  =    const char *keypairs, *password_secret;
>    =  QDict *options =3D NULL;
> @@ -431,6 +615,11 @@ static int cor= outine_fn qemu_rbd_co_create_opts(BlockDriver *drv,
>     &= nbsp;    goto exit;
>      }
>  <= br>> +    ret =3D qemu_rbd_extract_encryption_spec(opts, &= encryption_spec, errp);
> +    if (ret < 0) {
> + =        goto exit;
> +    }
> +>      /*
>       * Caution: while = qdict_get_try_str() is fine, getting non-string
>      = ; * types would require more care.  When @options come from -blockdev<= br>> @@ -446,6 +635,8 @@ static int coroutine_fn qemu_rbd_co_create_opts= (BlockDriver *drv,
>      loc->q_namespace =3D g_st= rdup(qdict_get_try_str(options, "namespace"));
>      = loc->has_q_namespace =3D !!loc->q_namespace;
>     &n= bsp;loc->image       =3D g_strdup(qdict_get_try_str(optio= ns, "image"));
> +    loc->encrypt     =3D enc= ryption_spec;
> +    loc->has_encrypt =3D !!encryption_s= pec;
>      keypairs         =3D q= dict_get_try_str(options, "=3Dkeyvalue-pairs");
>  
> &nbs= p;    ret =3D qemu_rbd_do_create(create_options, keypairs, passwo= rd_secret, errp);
> @@ -756,12 +947,26 @@ static int qemu_rbd_open(Bl= ockDriverState *bs, QDict *options, int flags,
>      =    goto failed_open;
>      }
>  = ;
> +    if (opts->has_encrypt) {
> +#ifdef LIBRBD= _SUPPORTS_ENCRYPTION
> +        r =3D qemu_rbd_ap= ply_encryption_function(s->image, opts->encrypt,
> +   &nb= sp;                     &= nbsp;                    = &rbd_encryption_load, errp);
> +        if (= r < 0) {
> +            goto failed_= post_open;
> +        }
> +#else
> + =        r =3D -ENOTSUP;
> +       &= nbsp;error_setg_errno(errp, -r,
> +          = ;               "RBD library does not su= pport image encryption");
> +        goto failed_= post_open;
> +#endif
> +    }
> +
>  = ;    r =3D rbd_get_size(s->image, &s->image_size);
&= gt;      if (r < 0) {
>        =  error_setg_errno(errp, -r, "error getting image size from %s",
&g= t;                     &n= bsp;     s->image_name);
> -        = rbd_close(s->image);
> -        goto failed_op= en;
> +        goto failed_post_open;
> &nb= sp;    }
>  
>      /* If we are = using an rbd snapshot, we must be r/o, otherwise
> @@ -769,8 +974,7 @= @ static int qemu_rbd_open(BlockDriverState *bs, QDict *options, int flags,=
>      if (s->snap !=3D NULL) {
>   &nb= sp;      r =3D bdrv_apply_auto_read_only(bs, "rbd snapshots = are read-only", errp);
>          if (r <= 0) {
> -            rbd_close(s->im= age);
> -            goto failed_open;<= br>> +            goto failed_post_open;>          }
>      }>  
> @@ -780,6 +984,8 @@ static int qemu_rbd_open(BlockDriv= erState *bs, QDict *options, int flags,
>      r =3D 0= ;
>      goto out;
>  
> +failed_post= _open:
> +    rbd_close(s->image);
>  failed_= open:
>      rados_ioctx_destroy(s->io_ctx);
>= ;      g_free(s->snap);
> @@ -1243,6 +1449,22 @@ st= atic QemuOptsList qemu_rbd_create_opts =3D {
>       &= nbsp;      .type =3D QEMU_OPT_STRING,
>     =          .help =3D "ID of secret providing the pas= sword",
>          },
> +    = ;    {
> +            .name = =3D "encrypt.format",
> +            .t= ype =3D QEMU_OPT_STRING,
> +            = ;.help =3D "Encrypt the image, format choices: 'luks1', 'luks2'",
> +=        },
> +        {
&g= t; +            .name =3D "encrypt.cipher-alg= ",
> +            .type =3D QEMU_OPT_ST= RING,
> +            .help =3D "Name of= encryption cipher algorithm"
> +           =          " (allowed values: aes-128, aes-256)",> +        },
> +        = {
> +            .name =3D "encrypt.pas= sphrase-secret",
> +            .type = =3D QEMU_OPT_STRING,
> +            .he= lp =3D "ID of secret providing LUKS passphrase",
> +     &n= bsp;  },
>          { /* end of list */= }
>      }
>  };
> diff --git a/qapi= /block-core.json b/qapi/block-core.json
> index 6d227924d0..a1f3230e2= 9 100644
> --- a/qapi/block-core.json
> +++ b/qapi/block-core.j= son
> @@ -3609,6 +3609,64 @@
>  { 'enum': 'RbdAuthMode',>    'data': [ 'cephx', 'none' ] }
>  
> +#= #
> +# @RbdImageEncryptionFormat:
> +#
> +# Since: 6.1> +##
> +{ 'enum': 'RbdImageEncryptionFormat',
> +  'd= ata': [ 'luks1', 'luks2' ] }

We already have LUKS support in QEMU th= at we use with raw files
and with qcow2, and here we call LUKSv1 simply = "luks".

IOW, I think we should just have "luks" and "luks2"

= > +
> +##
> +# @RbdEncryptionAlgorithm:
> +#
> += # Since: 6.1
> +##
> +{ 'enum': 'RbdEncryptionAlgorithm',
&g= t; +  'data': [ 'aes-128', 'aes-256' ] }

We already have a QCry= ptoCipherAlgorithm we should be using

> +
> +##
> +# = @RbdEncryptionOptionsLUKSBase:
> +#
> +# @cipher-alg: The encry= ption algorithm
> +# @passphrase-secret: ID of a QCryptoSecret object= providing a passphrase
> +#            = ;         for unlocking the encryption
> +#
&g= t; +# Since: 6.1
> +##
> +{ 'struct': 'RbdEncryptionOptionsLUKS= Base',
> +  'data': { '*cipher-alg': 'RbdEncryptionAlgorithm',> +            '*passphrase-secret': 'st= r' }}

For other block devices we've called it "key-secret", so pleas= e
lets keep the same terminology

IIUC, cipher-alg is only relevan= t when creating a new
disk image.

IOW, we ought to have separate = option structs for the code
paths for opening and creating images, since= the format
only wants a secret.

> +
> +##
> +# @R= bdEncryptionOptionsLUKS1:
> +#
> +# Since: 6.1
> +##
&= gt; +{ 'struct': 'RbdEncryptionOptionsLUKS1',
> +  'base': 'RbdE= ncryptionOptionsLUKSBase',
> +  'data': {}}
> +
> +#= #
> +# @RbdEncryptionOptionsLUKS2:
> +#
> +# Since: 6.1> +##
> +{ 'struct': 'RbdEncryptionOptionsLUKS2',
> + &nbs= p;'base': 'RbdEncryptionOptionsLUKSBase',
> +  'data': {}}
&g= t; +
> +##
> +# @RbdEncryptionSpec:
> +#
> +# Since= : 6.1
> +##
> +{ 'union': 'RbdEncryptionSpec',
> +  = 'base': { 'format': 'RbdImageEncryptionFormat' },
> +  'discrimi= nator': 'format',
> +  'data': { 'luks1': 'RbdEncryptionOptionsL= UKS1',
> +            'luks2': 'RbdEncr= yptionOptionsLUKS2'} }



> +
>  ##
>  = ;# @BlockdevOptionsRbd:
>  #
> @@ -3624,6 +3682,8 @@
&g= t;  #
>  # @snapshot: Ceph snapshot name.
>  #> +# @encrypt: Image encryption specification. (Since 6.1)
> +#<= br>>  # @user: Ceph id name.
>  #
>  # @auth-= client-required: Acceptable authentication modes.
> @@ -3646,6 +3706,= 7 @@
>              'image': 'str'= ,
>              '*conf': 'str',>              '*snapshot': 'str',<= br>> +            '*encrypt': 'RbdEncrypti= onSpec',
>              '*user': '= str',
>              '*auth-client= -required': ['RbdAuthMode'],
>           &nb= sp;  '*key-secret': 'str',


Is there any way to report that = LUKS is enabled for a given image ?

For an application to specify th= e "key-secret" for encryption, we
need to know that the image is encrypt= ed.  For the existing raw
and qcow2 file luks support we have this = reported with "qemu-img info"


Regards,
Daniel
--
|: https://berrange.com     =   -o-    https://www.flickr.com/photos/dberrange  :|
|: https://libvirt.org       &nb= sp;  -o-            https://fstop138.berrange.com  :|
|:= https://entangle-photo.org = ;    -o-    https://www.instagram.com/dberrange  :|