Hi

I already ported this patch to the OCF, and I'm using it over the OCF.
I also don't see any issue with small partitions??

The crypt_convert API is called from 2 different places in the code:
1. For read requests through the kcrypt_do_work working Q, called from
bi_end_io of the crypt_clone.
2. For Write requests through the crypt_clone directly.

In my recent version of the patch:
 I implemented a callback for read, which update the pending counter,
and callback for write
 Which doesn't update it.
 And in the crypt_convert I update the pending counter only if it's a
read operation.

By doing this I'm making sure that only one read request will be handled
at a time and the pending counter
Will be updated correctly for the read requests.

Now, I still see that I'm getting few writing requests inside the
Acrypto Q at the same time.
I think it is not OK  since currently the patch is not handling buffers
correctly for this case: the write task
Believe that the write was done, and it frees the buffers. (If I
understood it correctly) ???


I will send a patch, once the dm_crypt will be stable with the OCF.

Ronen Shitrit 
Marvell Semiconductor Israel Ltd

-----Original Message-----
From: Evgeniy Polyakov [mailto:[EMAIL PROTECTED] 
Sent: Sunday, September 04, 2005 11:07 PM
To: Ronen Shitrit
Cc: [EMAIL PROTECTED]; linux-crypto@vger.kernel.org
Subject: Re: [ACRYPTO] dm-crypt ported to acrypto.

On Sun, Sep 04, 2005 at 10:54:46PM +0300, Ronen Shitrit
([EMAIL PROTECTED]) wrote:
>  Hi
> 
> Did you tried to format a large partition (let say 10G) encrypted by 
> dm-crypt with AES-CBC?
> I'm trying this and I see, that write and read request are mixing 
> together.
> Why? Cause in the current patch the Read is blocked until all its 
> fragments will be encrypted, But the Write is not blocked it is queued

> and we return to the user, before the encrypt is completed.


I tried only 512mb partition, everything went fine there.
Hmm, it is very strange behaviour, reading and writing in device mapper
are the same - it is data copying between two BIOs - original and
cloned, when dm-crypt is set up, data is encrypted/decrypted btween
those BIOs, so it is not possible to just go through there.
Probably dm_async_pending setup is broken, but in my experiments it was
always normal 512 byte segments...
Coyld you please add some debug in dm_async_pending setup in
crypt_convert() and in dm_callback() so we could determine if there is
some kind of misorders there?

> Regards
> 
> Ronen Shitrit
> Marvell Semiconductor Israel Ltd
> 
> 
> -----Original Message-----
> From: Evgeniy Polyakov [mailto:[EMAIL PROTECTED]
> Sent: Sunday, September 04, 2005 10:50 PM
> To: Ronen Shitrit
> Cc: [EMAIL PROTECTED]; linux-crypto@vger.kernel.org
> Subject: Re: [ACRYPTO] dm-crypt ported to acrypto.
> 
> 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

-- 
        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