Re: [Ocf-linux-users] patch for OCF
Brought to you by:
david-m
From: David M. <uc...@gm...> - 2013-04-23 11:59:22
|
hwang7 wrote the following: > Hi david > > When using cryptosoft of OCF to do the crypto and run test scripts > which includes the following commands on SMP platform(we do the test > on fsl_p4080 which is a SMP processor with 8 cores): > > $ openssl speed -evp des -engine cryptodev -elapsed -multi 10 > $ openssl speed -evp des3 -engine cryptodev -elapsed -multi 10 > $ openssl speed -evp aes128 -engine cryptodev -elapsed -multi 10 > > The system will give out call trace or hang. > > The root causes of this issue is: > The swcr_sessions is not protected properly, and the three > types of session operation "create session, use session, delete > session" are also not protected properly. > > So: > 1.add spin lock to protect swcr_sessions > 2.add state/ref fields to session, use session state to prevent from > deleting a session when it's in creating or using state, and use spin > lock to protect the session state. Thanks for sending in the patch. I did see it the first time you posted it, I just haven't had time to digest it fully, sorry for not responding earlier. Does the fsl_p4080 have any HW acceleration underneath cryptosoft or are you using purely software acceleration ? The patch looks pretty good, but it would help me a lot if you could describe what kind of re-entry/call sequence was causing the main problem. Thanks, Davidm > diff -urbN ocf-linux-20120127/ocf/cryptosoft.c ocf-linux-20120127-1/ocf/cryptosoft.c > --- ocf-linux-20120127/ocf/cryptosoft.c 2012-01-27 09:04:28.000000000 +0800 > +++ ocf-linux-20120127-1/ocf/cryptosoft.c 2013-01-30 12:41:25.554624164 +0800 > @@ -77,6 +77,11 @@ > > #define SW_TYPE_INUSE 0x10000000 > > +#define SW_SESSION_IDLE 0x0 > +#define SW_SESSION_CREATION_IN_PROGRESS 0x1 > +#define SW_SESSION_IN_USE 0x2 > +#define SW_SESSION_DELETION_IN_PROGRESS 0x3 > + > /* We change some of the above if we have an async interface */ > > #define SW_TYPE_ALG_AMASK (SW_TYPE_ALG_MASK | SW_TYPE_ASYNC) > @@ -91,6 +96,8 @@ > struct work_struct workq; > int sw_type; > int sw_alg; > + int sw_state; > + int sw_ref; > struct crypto_tfm *sw_tfm; > spinlock_t sw_tfm_lock; > union { > @@ -283,6 +290,25 @@ > MODULE_PARM_DESC(swcr_debug, "Enable debug"); > > static void swcr_process_req(struct swcr_req *req); > +static DEFINE_SPINLOCK(session_lock); > + > +static inline void _swcr_set_state(struct swcr_data *swd, int state, int lock) > +{ > + unsigned long flags; > + if( lock ) > + spin_lock_irqsave(&session_lock, flags); > + > + if (swd != NULL) > + swd->sw_state = state; > + > + if ( lock ) > + spin_unlock_irqrestore(&session_lock, flags); > +} > + > +static inline void swcr_set_state(struct swcr_data *swd, int state) > +{ > + _swcr_set_state(swd, state, 0); > +} > > /* > * somethings just need to be run with user context no matter whether > @@ -339,14 +365,17 @@ > swcr_newsession(device_t dev, u_int32_t *sid, struct cryptoini *cri) > { > struct swcr_data **swd; > - u_int32_t i; > + u_int32_t index, i; > int error; > char *algo; > int mode; > + unsigned long flags; > > + spin_lock_irqsave(&session_lock, flags); > dprintk("%s()\n", __FUNCTION__); > if (sid == NULL || cri == NULL) { > dprintk("%s,%d - EINVAL\n", __FILE__, __LINE__); > + spin_unlock_irqrestore(&session_lock, flags); > return EINVAL; > } > > @@ -372,6 +401,7 @@ > else > swcr_sesnum /= 2; > dprintk("%s,%d: ENOBUFS\n", __FILE__, __LINE__); > + spin_unlock_irqrestore(&session_lock, flags); > return ENOBUFS; > } > memset(swd, 0, swcr_sesnum * sizeof(struct swcr_data *)); > @@ -386,30 +416,39 @@ > swcr_sessions = swd; > } > > - swd = &swcr_sessions[i]; > - *sid = i; > + index = i; > + swd = &swcr_sessions[index]; > + *sid = index; > > while (cri) { > *swd = (struct swcr_data *) kmalloc(sizeof(struct swcr_data), > SLAB_ATOMIC); > if (*swd == NULL) { > - swcr_freesession(NULL, i); > + swcr_set_state(swcr_sessions[index], SW_SESSION_DELETION_IN_PROGRESS); > + spin_unlock_irqrestore(&session_lock, flags); > + swcr_freesession(NULL, index); > dprintk("%s,%d: ENOBUFS\n", __FILE__, __LINE__); > return ENOBUFS; > } > memset(*swd, 0, sizeof(struct swcr_data)); > + swcr_set_state(*swd, SW_SESSION_CREATION_IN_PROGRESS); > + spin_unlock_irqrestore(&session_lock, flags); > > if (cri->cri_alg < 0 || > cri->cri_alg>=sizeof(crypto_details)/sizeof(crypto_details[0])){ > printk("cryptosoft: Unknown algorithm 0x%x\n", cri->cri_alg); > - swcr_freesession(NULL, i); > + _swcr_set_state(swcr_sessions[index], > + SW_SESSION_DELETION_IN_PROGRESS, 1); > + swcr_freesession(NULL, index); > return EINVAL; > } > > algo = crypto_details[cri->cri_alg].alg_name; > if (!algo || !*algo) { > printk("cryptosoft: Unsupported algorithm 0x%x\n", cri->cri_alg); > - swcr_freesession(NULL, i); > + _swcr_set_state(swcr_sessions[index], > + SW_SESSION_DELETION_IN_PROGRESS, 1); > + swcr_freesession(NULL, index); > return EINVAL; > } > > @@ -450,7 +489,9 @@ > algo,mode); > err = IS_ERR((*swd)->sw_tfm) ? -(PTR_ERR((*swd)->sw_tfm)) : EINVAL; > (*swd)->sw_tfm = NULL; /* ensure NULL */ > - swcr_freesession(NULL, i); > + _swcr_set_state(swcr_sessions[index], > + SW_SESSION_DELETION_IN_PROGRESS, 1); > + swcr_freesession(NULL, index); > return err; > } > > @@ -482,7 +523,9 @@ > if (error) { > printk("cryptosoft: setkey failed %d (crt_flags=0x%x)\n", error, > (*swd)->sw_tfm->crt_flags); > - swcr_freesession(NULL, i); > + _swcr_set_state(swcr_sessions[index], > + SW_SESSION_DELETION_IN_PROGRESS, 1); > + swcr_freesession(NULL, index); > return error; > } > } else if ((*swd)->sw_type & (SW_TYPE_HMAC | SW_TYPE_HASH)) { > @@ -504,7 +547,9 @@ > if (!(*swd)->sw_tfm) { > dprintk("cryptosoft: crypto_alloc_hash failed(%s,0x%x)\n", > algo, mode); > - swcr_freesession(NULL, i); > + _swcr_set_state(swcr_sessions[index], > + SW_SESSION_DELETION_IN_PROGRESS, 1); > + swcr_freesession(NULL, index); > return EINVAL; > } > > @@ -512,7 +557,9 @@ > (*swd)->u.hmac.sw_key = (char *)kmalloc((*swd)->u.hmac.sw_klen, > SLAB_ATOMIC); > if ((*swd)->u.hmac.sw_key == NULL) { > - swcr_freesession(NULL, i); > + _swcr_set_state(swcr_sessions[index], > + SW_SESSION_DELETION_IN_PROGRESS, 1); > + swcr_freesession(NULL, index); > dprintk("%s,%d: ENOBUFS\n", __FILE__, __LINE__); > return ENOBUFS; > } > @@ -532,24 +579,33 @@ > if (!(*swd)->sw_tfm) { > dprintk("cryptosoft: crypto_alloc_comp failed(%s,0x%x)\n", > algo, mode); > - swcr_freesession(NULL, i); > + _swcr_set_state(swcr_sessions[index], > + SW_SESSION_DELETION_IN_PROGRESS, 1); > + swcr_freesession(NULL, index); > return EINVAL; > } > (*swd)->u.sw_comp_buf = kmalloc(CRYPTO_MAX_DATA_LEN, SLAB_ATOMIC); > if ((*swd)->u.sw_comp_buf == NULL) { > - swcr_freesession(NULL, i); > + _swcr_set_state(swcr_sessions[index], > + SW_SESSION_DELETION_IN_PROGRESS, 1); > + swcr_freesession(NULL, index); > dprintk("%s,%d: ENOBUFS\n", __FILE__, __LINE__); > return ENOBUFS; > } > } else { > printk("cryptosoft: Unhandled sw_type %d\n", (*swd)->sw_type); > - swcr_freesession(NULL, i); > + _swcr_set_state(swcr_sessions[index], > + SW_SESSION_DELETION_IN_PROGRESS, 1); > + swcr_freesession(NULL, index); > return EINVAL; > } > > cri = cri->cri_next; > swd = &((*swd)->sw_next); > + spin_lock_irqsave(&session_lock, flags); > } > + swcr_set_state(swcr_sessions[index], SW_SESSION_IDLE); > + spin_unlock_irqrestore(&session_lock, flags); > return 0; > } > > @@ -559,22 +615,42 @@ > static int > swcr_freesession(device_t dev, u_int64_t tid) > { > + unsigned long flags; > struct swcr_data *swd; > u_int32_t sid = CRYPTO_SESID2LID(tid); > > + spin_lock_irqsave(&session_lock, flags); > dprintk("%s()\n", __FUNCTION__); > if (sid > swcr_sesnum || swcr_sessions == NULL || > swcr_sessions[sid] == NULL) { > dprintk("%s,%d: EINVAL\n", __FILE__, __LINE__); > + spin_unlock_irqrestore(&session_lock, flags); > return(EINVAL); > } > > /* Silently accept and return */ > - if (sid == 0) > + if (sid == 0) { > + spin_unlock_irqrestore(&session_lock, flags); > return(0); > + } > > while ((swd = swcr_sessions[sid]) != NULL) { > + if (swd->sw_state == SW_SESSION_IN_USE > + || swd->sw_state == SW_SESSION_CREATION_IN_PROGRESS) { > + spin_unlock_irqrestore(&session_lock, flags); > + return EAGAIN; > + } > + /* > + * If the session is to be deleted, it should all be deleted > + * so mark it as unuseable. > + * In fact, only the first swcr_data's state is used as the > + * session state now, so just change it to mark the session > + * as being delete > + */ > + swcr_set_state(swd, SW_SESSION_DELETION_IN_PROGRESS); > swcr_sessions[sid] = swd->sw_next; > + swcr_set_state(swcr_sessions[sid], SW_SESSION_DELETION_IN_PROGRESS); > + spin_unlock_irqrestore(&session_lock, flags); > if (swd->sw_tfm) { > switch (swd->sw_type & SW_TYPE_ALG_AMASK) { > #ifdef HAVE_AHASH > @@ -615,16 +691,18 @@ > kfree(swd->u.hmac.sw_key); > } > kfree(swd); > + spin_lock_irqsave(&session_lock, flags); > } > + spin_unlock_irqrestore(&session_lock, flags); > return 0; > } > > static void swcr_process_req_complete(struct swcr_req *req) > { > + unsigned long flags; > dprintk("%s()\n", __FUNCTION__); > > if (req->sw->sw_type & SW_TYPE_INUSE) { > - unsigned long flags; > spin_lock_irqsave(&req->sw->sw_tfm_lock, flags); > req->sw->sw_type &= ~SW_TYPE_INUSE; > spin_unlock_irqrestore(&req->sw->sw_tfm_lock, flags); > @@ -665,6 +743,12 @@ > } > > done: > + spin_lock_irqsave(&session_lock, flags); > + req->sw_head->sw_ref--; > + if (req->sw_head->sw_ref <= 0) { > + swcr_set_state(req->sw_head, SW_SESSION_IDLE); > + } > + spin_unlock_irqrestore(&session_lock, flags); > dprintk("%s crypto_done %p\n", __FUNCTION__, req); > crypto_done(req->crp); > kmem_cache_free(swcr_req_cache, req); > @@ -1162,6 +1246,7 @@ > { > struct swcr_req *req = NULL; > u_int32_t lid; > + unsigned long flags; > > dprintk("%s()\n", __FUNCTION__); > /* Sanity check */ > @@ -1179,10 +1264,12 @@ > } > > lid = crp->crp_sid & 0xffffffff; > + spin_lock_irqsave(&session_lock, flags); > if (lid >= swcr_sesnum || lid == 0 || swcr_sessions == NULL || > swcr_sessions[lid] == NULL) { > crp->crp_etype = ENOENT; > dprintk("%s,%d: ENOENT\n", __FILE__, __LINE__); > + spin_unlock_irqrestore(&session_lock, flags); > goto done; > } > > @@ -1195,6 +1282,7 @@ > if (skb_shinfo(skb)->nr_frags >= SCATTERLIST_MAX) { > printk("%s,%d: %d nr_frags > SCATTERLIST_MAX", __FILE__, __LINE__, > skb_shinfo(skb)->nr_frags); > + spin_unlock_irqrestore(&session_lock, flags); > goto done; > } > } else if (crp->crp_flags & CRYPTO_F_IOV) { > @@ -1202,6 +1290,7 @@ > if (uiop->uio_iovcnt > SCATTERLIST_MAX) { > printk("%s,%d: %d uio_iovcnt > SCATTERLIST_MAX", __FILE__, __LINE__, > uiop->uio_iovcnt); > + spin_unlock_irqrestore(&session_lock, flags); > goto done; > } > } > @@ -1213,11 +1302,24 @@ > if (req == NULL) { > dprintk("%s,%d: ENOMEM\n", __FILE__, __LINE__); > crp->crp_etype = ENOMEM; > + spin_unlock_irqrestore(&session_lock, flags); > goto done; > } > memset(req, 0, sizeof(*req)); > > req->sw_head = swcr_sessions[lid]; > + if (req->sw_head->sw_state == SW_SESSION_DELETION_IN_PROGRESS) { > + crp->crp_etype = EINVAL; > + spin_unlock_irqrestore(&session_lock, flags); > + goto done; > + } else if (req->sw_head->sw_state == SW_SESSION_CREATION_IN_PROGRESS) { > + crp->crp_etype = EAGAIN; > + spin_unlock_irqrestore(&session_lock, flags); > + goto done; > + } > + swcr_set_state(req->sw_head, SW_SESSION_IN_USE); > + req->sw_head->sw_ref++; > + spin_unlock_irqrestore(&session_lock, flags); > req->crp = crp; > req->crd = crp->crp_desc; > > > ------------------------------------------------------------------------------ > Try New Relic Now & We'll Send You this Cool Shirt > New Relic is the only SaaS-based application performance monitoring service > that delivers powerful full stack analytics. Optimize and monitor your > browser, app, & servers with just a few lines of code. Try New Relic > and get this awesome Nerd Life shirt! http://p.sf.net/sfu/newrelic_d2d_apr > _______________________________________________ > Ocf-linux-users mailing list > Ocf...@li... > https://lists.sourceforge.net/lists/listinfo/ocf-linux-users -- David McCullough, da...@sp..., Ph: 0410 560 763 |