On Sun, Sep 04, 2005 at 10:41:02PM +0300, Ronen Shitrit ([EMAIL PROTECTED]) 
wrote:
> Hi
>  
> What do you think about the second remark??
> "
> > ->I think that we might have a problem  if a write operation will be
> > processed in parallel to a read operation, the read might wait for the
> 
> > write to complete, and the dm_async_pending might also get wrong 
> > values???           
> "
> I think that the pending counter , should be updated only in read
> operations (cb and convert ).

Hmm, how does read operation differ from write in respect to dm-crypt?
It either decrypts (read) or encrypts (write) cloned BIOs, and all operations
are strongly serialized.
dm_async_pending is a number of crypt operations to be performed by the
stack on given data, most of the time it is number of segments (bvec) in BIO,
so dm_async_pending is always set to number of operatons, so it should
be decremented when one operation is finished, no matter if it is read
(decrypt) or write (encrypt).

> Regards
> 
> Ronen Shitrit 
> Marvell Semiconductor Israel Ltd
> 
> -----Original Message-----
> From: [EMAIL PROTECTED]
> [mailto:[EMAIL PROTECTED] On Behalf Of Ronen Shitrit
> Sent: Sunday, September 04, 2005 10:10 PM
> To: [EMAIL PROTECTED]
> Subject: FW: [ACRYPTO] dm-crypt ported to acrypto.
> 
>  Evgeniy Polyakov wrote:
> 
> > Hi
> >  
> > Nice job, (horoshaya rabota)
> > Just two issue:
> > ->I saw this patch is using a global variable which counts the number
> > pending requests: dm_async_pending.
> > I think that this variable should be allocated per dm_crypt session, 
> > i.e for each crypt_config, since there can be more then 2 consumers 
> > reading through the dm_crypt.
> > ->I think that we might have a problem  if a write operation will be
> > processed in parallel to a read operation, the read might wait for the
> 
> > write to complete, and the dm_async_pending might also get wrong 
> > values???
> 
> Updated patch attached.
> Only compile tested though - will run test tomorrow.
> 
> > Regards
> > 
> > Ronen Shitrit
> > Marvell Semiconductor Israel Ltd
> 
> diff --git a/drivers/md/dm-crypt.c b/drivers/md/dm-crypt.c
> --- a/drivers/md/dm-crypt.c
> +++ b/drivers/md/dm-crypt.c
> @@ -85,6 +85,11 @@ struct crypt_config {
>       struct crypto_tfm *tfm;
>       unsigned int key_size;
>       u8 key[0];
> +
> +#if defined CONFIG_ACRYPTO || defined CONFIG_ACRYPTO_MODULE
> +     wait_queue_head_t dm_async_queue;
> +     int dm_async_pending;
> +#endif
>  };
>  
>  #define MIN_IOS        256
> @@ -230,6 +235,186 @@ static struct crypt_iv_operations crypt_
>       .generator = crypt_iv_essiv_gen
>  };
>  
> +#if defined CONFIG_ACRYPTO || defined CONFIG_ACRYPTO_MODULE
> +
> +#include <linux/acrypto.h>
> +#include <linux/crypto_def.h>
> +
> +struct dm_async_private
> +{
> +     void                    *sg;
> +     struct crypt_config     *cc;
> +};
> +
> +static inline u16 crypto_tfm_get_type(struct crypto_tfm *tfm) {
> +     u16 type;
> +     char *name;
> +
> +     name = (char *)crypto_tfm_alg_name(tfm);
> +
> +     if (!strncmp(name, "aes", 3)) {
> +             switch (crypto_tfm_alg_blocksize(tfm) << 3) {
> +                     case 128:
> +                             type = CRYPTO_TYPE_AES_128;
> +                             break;
> +                     case 192:
> +                             type = CRYPTO_TYPE_AES_192;
> +                             break;
> +                     case 256:
> +                             type = CRYPTO_TYPE_AES_256;
> +                             break;
> +                     default:
> +                             type = 0xffff;
> +                             break;
> +             }
> +     } else if (!strncmp(name, "des3_ede", 3))
> +             type = CRYPTO_TYPE_3DES;
> +     else
> +             type = 0xffff;
> +
> +     return type;
> +}
> +
> +static inline u16 crypto_tfm_get_mode(struct crypto_tfm *tfm) {
> +     u16 mode = tfm->crt_cipher.cit_mode & CRYPTO_TFM_MODE_MASK;
> +
> +     switch (mode) {
> +             case CRYPTO_TFM_MODE_ECB:
> +                     mode = CRYPTO_MODE_ECB;
> +                     break;
> +             case CRYPTO_TFM_MODE_CBC:
> +                     mode = CRYPTO_MODE_CBC;
> +                     break;
> +             case CRYPTO_TFM_MODE_CFB:
> +                     mode = CRYPTO_MODE_CFB;
> +                     break;
> +             case CRYPTO_TFM_MODE_CTR:
> +                     mode = CRYPTO_MODE_CTR;
> +                     break;
> +             default:
> +                     mode = 0xffff;
> +                     break;
> +     }
> +
> +     return mode;
> +}
> +
> +static void dm_callback(struct crypto_session_initializer *ci, struct 
> +crypto_data *data) {
> +     struct dm_async_private *priv = data->priv;
> +     
> +     priv->cc->dm_async_pending--;
> +     wake_up(&priv->cc->dm_async_queue);
> +     
> +     kfree(priv->sg);
> +}
> +
> +static inline int acrypto_process(struct crypt_config *cc, struct
> scatterlist *out, 
> +             struct scatterlist *in, unsigned int len, u8 *iv, int
> iv_size, int 
> +write) {
> +     struct crypto_session *s;
> +     struct crypto_session_initializer ci;
> +     struct crypto_data data;
> +     struct scatterlist *sg;
> +     int sg_size, err = 0;
> +     u8 *local_key;
> +     struct dm_async_private *priv;
> +
> +     memset(&ci, 0, sizeof(ci));
> +     memset(&data, 0, sizeof(data));
> +
> +     ci.operation = (write)?CRYPTO_OP_ENCRYPT:CRYPTO_OP_DECRYPT;
> +     ci.priority = 0;
> +     ci.callback = &dm_callback;
> +     ci.type = crypto_tfm_get_type(cc->tfm);
> +     ci.mode = crypto_tfm_get_mode(cc->tfm);
> +     
> +     if (ci.type == 0xffff || ci.mode == 0xffff) {
> +             err = -EINVAL;
> +             goto err_out_exit;
> +     }
> +
> +     data.sg_src_num = data.sg_dst_num = data.sg_key_num = 1;
> +     data.sg_iv_num = (iv)?1:0;
> +
> +     sg_size = sizeof(*sg) * (data.sg_src_num + 
> +                     data.sg_dst_num + data.sg_iv_num + 
> +                     data.sg_key_num + iv_size + cc->key_size + 
> +                     sizeof(struct dm_async_private));
> +     priv = (struct dm_async_private *)kmalloc(sg_size, GFP_KERNEL);
> +     if (!priv) {
> +             err = -ENOMEM;
> +             goto err_out_exit;
> +     }
> +     
> +     memset(priv, 0, sg_size);
> +#if 0
> +     printk("%s: key_size=%u, iv=%p, iv_size=%d, write=%d,
> priv=%p.\n",
> +                     __func__, cc->key_size, iv, iv_size, write, sg);
> #endif
> +     data.priv = priv;
> +     priv->cc = cc;
> +     priv->sg = priv;
> +
> +     sg = (struct scatterlist *)(priv + 1);
> +
> +     data.sg_src = &sg[0];
> +     data.sg_dst = &sg[1];
> +     
> +     data.sg_src[0].page = in->page;
> +     data.sg_src[0].offset = in->offset;
> +     data.sg_src[0].length = in->length;
> +     
> +     data.sg_dst[0].page = out->page;
> +     data.sg_dst[0].offset = out->offset;
> +     data.sg_dst[0].length = out->length;
> +     
> +     data.sg_key = &sg[2];
> +     local_key = (u8 *)&sg[3];
> +
> +     memcpy(local_key, cc->key, cc->key_size);
> +     
> +     data.sg_key[0].page = virt_to_page(local_key);
> +     data.sg_key[0].offset = offset_in_page(local_key);
> +     data.sg_key[0].length = cc->key_size;
> +
> +     if (iv) {
> +             u8 *local_iv;
> +             
> +             data.sg_iv = (struct scatterlist *)(local_key +
> cc->key_size);
> +             local_iv = (u8 *)(local_key + cc->key_size +
> sizeof(*sg));
> +             
> +             data.sg_iv[0].page = virt_to_page(local_iv);
> +             data.sg_iv[0].offset = offset_in_page(local_iv);
> +             data.sg_iv[0].length = iv_size;
> +
> +             memcpy(local_iv, iv, iv_size);
> +     }
> +
> +     s = crypto_session_alloc(&ci, &data);
> +     if (!s) {
> +             err = -ENOMEM;
> +             goto err_out_free;
> +     }
> +
> +     return 0;
> +
> +err_out_free:
> +     kfree(sg);
> +err_out_exit:
> +     cc->dm_async_pending--;
> +
> +     return err;
> +}
> +#else
> +static inline int acrypto_process(struct crypt_config *cc, struct
> scatterlist *out, 
> +             struct scatterlist *in, unsigned int len, u8 *iv, int
> iv_size, int write)
> +{
> +     return 0;
> +}
> +#endif
>  
>  static inline int
>  crypt_convert_scatterlist(struct crypt_config *cc, struct scatterlist
> *out, @@ -244,11 +429,19 @@ crypt_convert_scatterlist(struct crypt_c
>               if (r < 0)
>                       return r;
>  
> +             r = acrypto_process(cc, out, in, length, iv,
> cc->iv_size, write);
> +             if (r == 0)
> +                     return r;
> +
>               if (write)
>                       r = crypto_cipher_encrypt_iv(cc->tfm, out, in,
> length, iv);
>               else
>                       r = crypto_cipher_decrypt_iv(cc->tfm, out, in,
> length, iv);
>       } else {
> +             r = acrypto_process(cc, out, in, length, NULL, 0,
> write);
> +             if (r == 0)
> +                     return r;
> +             
>               if (write)
>                       r = crypto_cipher_encrypt(cc->tfm, out, in,
> length);
>               else
> @@ -281,6 +474,42 @@ static int crypt_convert(struct crypt_co  {
>       int r = 0;
>  
> +#if defined CONFIG_ACRYPTO || defined CONFIG_ACRYPTO_MODULE
> +     {
> +             unsigned int idx_in, idx_out, offset_in, offset_out;
> +             int num = 0;
> +
> +             idx_in = ctx->idx_in;
> +             idx_out = ctx->idx_out;
> +             offset_in = ctx->offset_in;
> +             offset_out = ctx->offset_out;
> +
> +             while(idx_in < ctx->bio_in->bi_vcnt &&
> +                   idx_out < ctx->bio_out->bi_vcnt) {
> +                     
> +                     struct bio_vec *bv_in =
> bio_iovec_idx(ctx->bio_in, idx_in);
> +                     struct bio_vec *bv_out =
> bio_iovec_idx(ctx->bio_out, idx_out);
> +             
> +                     offset_in += 1 << SECTOR_SHIFT;
> +                     offset_out += 1 << SECTOR_SHIFT;
> +                     
> +                     if (offset_in >= bv_in->bv_len) {
> +                             offset_in = 0;
> +                             idx_in++;
> +                     }
> +             
> +                     if (offset_out >= bv_out->bv_len) {
> +                             offset_out = 0;
> +                             idx_out++;
> +                     }
> +
> +                     num++;
> +             }
> +
> +             cc->dm_async_pending = num;
> +     }
> +#endif
> +
>       while(ctx->idx_in < ctx->bio_in->bi_vcnt &&
>             ctx->idx_out < ctx->bio_out->bi_vcnt) {
>               struct bio_vec *bv_in = bio_iovec_idx(ctx->bio_in,
> ctx->idx_in); @@ -470,6 +699,17 @@ static void kcryptd_do_work(void
> *data)
>                          io->bio->bi_sector - io->target->begin, 0);
>       r = crypt_convert(cc, &ctx);
>  
> +#if defined CONFIG_ACRYPTO || defined CONFIG_ACRYPTO_MODULE
> +     {
> +             long timeout = 1000;
> +             long tm;
> +             
> +             tm = wait_event_timeout(cc->dm_async_queue,
> cc->dm_async_pending == 0, msecs_to_jiffies(timeout));
> +             if (!tm)
> +                     printk("%s: bug: work was not finished in %ld
> msecs, %d users remains.\n", 
> +                                     __func__, timeout,
> cc->dm_async_pending);
> +     }
> +#endif
>       dec_pending(io, r);
>  }
>  
> @@ -680,6 +920,11 @@ static int crypt_ctr(struct dm_target *t
>       } else
>               cc->iv_mode = NULL;
>  
> +#if defined CONFIG_ACRYPTO || defined CONFIG_ACRYPTO_MODULE
> +     init_waitqueue_head(&cc->dm_async_queue);
> +     cc->dm_async_pending = 0;
> +#endif
> +
>       ti->private = cc;
>       return 0;
> 
> 
> 
> -- 
>       Evgeniy Polyakov
> _______________________________________________
> 
> Subscription: http://lists.logix.cz/mailman/listinfo/cryptoapi
> List archive: http://lists.logix.cz/pipermail/cryptoapi

-- 
        Evgeniy Polyakov
-
To unsubscribe from this list: send the line "unsubscribe linux-crypto" in
the body of a message to [EMAIL PROTECTED]
More majordomo info at  http://vger.kernel.org/majordomo-info.html

Reply via email to