Changeset 17678


Ignore:
Timestamp:
2009-09-22T20:00:28+02:00 (8 years ago)
Author:
nbd
Message:

unlzma: fix a race condition and add some optimizations to improve performance
also make peek_old_byte errors non-fatal

Location:
trunk/target/linux/generic-2.6
Files:
2 edited

Legend:

Unmodified
Added
Removed
  • trunk/target/linux/generic-2.6/patches-2.6.30/052-pcomp_lzma_support.patch

    r17475 r17678  
    11--- /dev/null 
    22+++ b/crypto/unlzma.c 
    3 @@ -0,0 +1,748 @@ 
     3@@ -0,0 +1,772 @@ 
    44+/* 
    55+ * LZMA uncompresion module for pcomp 
     
    5151+       struct task_struct *thread; 
    5252+       wait_queue_head_t next_req; 
     53+       wait_queue_head_t req_done; 
    5354+       struct mutex mutex; 
     55+       bool waiting; 
    5456+       bool active; 
    5557+       bool cancel; 
     
    107109+{ 
    108110+       do { 
     111+               ctx->waiting = true; 
    109112+               mutex_unlock(&ctx->mutex); 
     113+               wake_up(&ctx->req_done); 
    110114+               if (wait_event_interruptible(ctx->next_req, 
    111115+                       unlzma_should_stop(ctx) || (*avail > 0))) 
     
    214218+       u32 pos; 
    215219+ 
    216 +       BUG_ON(!ctx->n_buffers); 
     220+       if (!ctx->n_buffers) { 
     221+               printk(KERN_ERR "unlzma/%s: no buffer\n", __func__); 
     222+               goto error; 
     223+       } 
     224+ 
    217225+       pos = ctx->pos - offs; 
    218 +       if (pos >= ctx->dict_size) { 
    219 +               pos = (~pos % ctx->dict_size); 
    220 +       } 
     226+       if (unlikely(pos >= ctx->dict_size)) 
     227+               pos = ~pos & (ctx->dict_size - 1); 
    221228+ 
    222229+       while (bh->offset > pos) { 
    223230+               bh--; 
    224231+               i--; 
    225 +               BUG_ON(!i); 
     232+               if (!i) { 
     233+                       printk(KERN_ERR "unlzma/%s: position %d out of range\n", __func__, pos); 
     234+                       goto error; 
     235+               } 
    226236+       } 
    227237+ 
    228238+       pos -= bh->offset; 
    229 +       BUG_ON(pos >= bh->size); 
     239+       if (pos >= bh->size) { 
     240+               printk(KERN_ERR "unlzma/%s: position %d out of range\n", __func__, pos); 
     241+               goto error; 
     242+       } 
    230243+ 
    231244+       return bh->ptr[pos]; 
     245+ 
     246+error: 
     247+       ctx->cancel = true; 
     248+       return 0; 
    232249+} 
    233250+ 
     
    636653+               return -ENOMEM; 
    637654+ 
     655+       ctx->waiting = false; 
    638656+       mutex_init(&ctx->mutex); 
    639657+       init_waitqueue_head(&ctx->next_req); 
     658+       init_waitqueue_head(&ctx->req_done); 
    640659+       ctx->thread = kthread_run(unlzma_thread, ctx, "unlzma/%d", instance++); 
    641660+       if (IS_ERR(ctx->thread)) { 
     
    650669+unlzma_decompress_init(struct crypto_pcomp *tfm) 
    651670+{ 
    652 +       struct unlzma_ctx *ctx = crypto_tfm_ctx(crypto_pcomp_tfm(tfm)); 
    653 + 
    654 +       ctx->pos = 0; 
    655671+       return 0; 
    656672+} 
     
    659675+unlzma_wait_complete(struct unlzma_ctx *ctx, bool finish) 
    660676+{ 
     677+       DEFINE_WAIT(__wait); 
     678+ 
    661679+       do { 
     680+               wake_up(&ctx->next_req); 
     681+               prepare_to_wait(&ctx->req_done, &__wait, TASK_INTERRUPTIBLE); 
    662682+               mutex_unlock(&ctx->mutex); 
    663 +               wake_up(&ctx->next_req); 
    664683+               schedule(); 
    665684+               mutex_lock(&ctx->mutex); 
    666 +       } while (ctx->active && (ctx->avail_in > 0) && (ctx->avail_out > 0)); 
     685+       } while (!ctx->waiting && ctx->active); 
     686+       finish_wait(&ctx->req_done, &__wait); 
    667687+} 
    668688+ 
     
    678698+ 
    679699+       pos = ctx->pos; 
     700+       ctx->waiting = false; 
    680701+       ctx->next_in = req->next_in; 
    681702+       ctx->avail_in = req->avail_in; 
     
    695716+out: 
    696717+       mutex_unlock(&ctx->mutex); 
     718+       if (ctx->cancel) 
     719+               return -EINVAL; 
     720+ 
    697721+       return pos; 
    698722+} 
  • trunk/target/linux/generic-2.6/patches-2.6.31/052-pcomp_lzma_support.patch

    r17351 r17678  
    11--- /dev/null 
    22+++ b/crypto/unlzma.c 
    3 @@ -0,0 +1,723 @@ 
     3@@ -0,0 +1,772 @@ 
    44+/* 
    55+ * LZMA uncompresion module for pcomp 
     
    3737+ 
    3838+#include <crypto/internal/compress.h> 
     39+#include <net/netlink.h> 
    3940+#include "unlzma.h" 
    4041+ 
     
    4243+ 
    4344+struct unlzma_buffer { 
    44 +       struct unlzma_buffer *last; 
    4545+       int offset; 
    4646+       int size; 
     
    5151+       struct task_struct *thread; 
    5252+       wait_queue_head_t next_req; 
     53+       wait_queue_head_t req_done; 
    5354+       struct mutex mutex; 
     55+       bool waiting; 
    5456+       bool active; 
    5557+       bool cancel; 
     
    6971+       u8 previous_byte; 
    7072+       ssize_t pos; 
    71 +       struct unlzma_buffer *head; 
    7273+       int buf_full; 
     74+       int n_buffers; 
     75+       int buffers_max; 
     76+       struct unlzma_buffer *buffers; 
    7377+ 
    7478+       /* cstate */ 
     
    9397+       struct unlzma_buffer *bh; 
    9498+ 
    95 +       bh = kzalloc(sizeof(struct unlzma_buffer), GFP_KERNEL); 
     99+       BUG_ON(ctx->n_buffers >= ctx->buffers_max); 
     100+       bh = &ctx->buffers[ctx->n_buffers++]; 
    96101+       bh->ptr = ctx->next_out; 
    97102+       bh->offset = ctx->pos; 
    98 +       bh->last = ctx->head; 
    99103+       bh->size = ctx->avail_out; 
    100 +       ctx->head = bh; 
    101104+       ctx->buf_full = 0; 
    102105+} 
     
    106109+{ 
    107110+       do { 
     111+               ctx->waiting = true; 
    108112+               mutex_unlock(&ctx->mutex); 
     113+               wake_up(&ctx->req_done); 
    109114+               if (wait_event_interruptible(ctx->next_req, 
    110115+                       unlzma_should_stop(ctx) || (*avail > 0))) 
     
    209214+peek_old_byte(struct unlzma_ctx *ctx, u32 offs) 
    210215+{ 
    211 +       struct unlzma_buffer *bh = ctx->head; 
     216+       struct unlzma_buffer *bh = &ctx->buffers[ctx->n_buffers - 1]; 
     217+       int i = ctx->n_buffers; 
    212218+       u32 pos; 
    213219+ 
     220+       if (!ctx->n_buffers) { 
     221+               printk(KERN_ERR "unlzma/%s: no buffer\n", __func__); 
     222+               goto error; 
     223+       } 
     224+ 
    214225+       pos = ctx->pos - offs; 
    215 +       if (pos >= ctx->dict_size) { 
    216 +               pos = (~pos % ctx->dict_size); 
    217 +       } 
     226+       if (unlikely(pos >= ctx->dict_size)) 
     227+               pos = ~pos & (ctx->dict_size - 1); 
    218228+ 
    219229+       while (bh->offset > pos) { 
    220 +               bh = bh->last; 
    221 +               BUG_ON(!bh); 
     230+               bh--; 
     231+               i--; 
     232+               if (!i) { 
     233+                       printk(KERN_ERR "unlzma/%s: position %d out of range\n", __func__, pos); 
     234+                       goto error; 
     235+               } 
    222236+       } 
    223237+ 
    224238+       pos -= bh->offset; 
    225 +       BUG_ON(pos >= bh->size); 
     239+       if (pos >= bh->size) { 
     240+               printk(KERN_ERR "unlzma/%s: position %d out of range\n", __func__, pos); 
     241+               goto error; 
     242+       } 
    226243+ 
    227244+       return bh->ptr[pos]; 
     245+ 
     246+error: 
     247+       ctx->cancel = true; 
     248+       return 0; 
    228249+} 
    229250+ 
     
    461482+       } 
    462483+ 
     484+       ctx->n_buffers = 0; 
    463485+       ctx->pos = 0; 
    464486+       get_buffer(ctx); 
     
    555577+               ctx->cancel = false; 
    556578+               ctx->active = false; 
    557 +               while (ctx->head) { 
    558 +                       struct unlzma_buffer *bh = ctx->head; 
    559 +                       ctx->head = bh->last; 
    560 +                       kfree(bh); 
    561 +               } 
    562579+       } while (!kthread_should_stop()); 
    563580+       mutex_unlock(&ctx->mutex); 
     
    599616+               kthread_stop(ctx->thread); 
    600617+               ctx->thread = NULL; 
     618+               if (ctx->buffers) 
     619+                       kfree(ctx->buffers); 
     620+               ctx->buffers_max = 0; 
     621+               ctx->buffers = NULL; 
    601622+       } 
    602623+} 
     
    606627+{ 
    607628+       struct unlzma_ctx *ctx = crypto_tfm_ctx(crypto_pcomp_tfm(tfm)); 
     629+       struct nlattr *tb[UNLZMA_DECOMP_MAX + 1]; 
    608630+       int ret = 0; 
    609631+ 
    610632+       if (ctx->thread) 
    611 +               return 0; 
    612 + 
     633+               return -EINVAL; 
     634+ 
     635+       if (!p) 
     636+               return -EINVAL; 
     637+ 
     638+       ret = nla_parse(tb, UNLZMA_DECOMP_MAX, p, len, NULL); 
     639+       if (!tb[UNLZMA_DECOMP_OUT_BUFFERS]) 
     640+               return -EINVAL; 
     641+ 
     642+       if (ctx->buffers_max && (ctx->buffers_max < 
     643+           nla_get_u32(tb[UNLZMA_DECOMP_OUT_BUFFERS]))) { 
     644+               kfree(ctx->buffers); 
     645+               ctx->buffers_max = 0; 
     646+               ctx->buffers = NULL; 
     647+       } 
     648+       if (!ctx->buffers) { 
     649+               ctx->buffers_max = nla_get_u32(tb[UNLZMA_DECOMP_OUT_BUFFERS]); 
     650+               ctx->buffers = kzalloc(sizeof(struct unlzma_buffer) * ctx->buffers_max, GFP_KERNEL); 
     651+       } 
     652+       if (!ctx->buffers) 
     653+               return -ENOMEM; 
     654+ 
     655+       ctx->waiting = false; 
    613656+       mutex_init(&ctx->mutex); 
    614657+       init_waitqueue_head(&ctx->next_req); 
     658+       init_waitqueue_head(&ctx->req_done); 
    615659+       ctx->thread = kthread_run(unlzma_thread, ctx, "unlzma/%d", instance++); 
    616660+       if (IS_ERR(ctx->thread)) { 
     
    625669+unlzma_decompress_init(struct crypto_pcomp *tfm) 
    626670+{ 
    627 +       struct unlzma_ctx *ctx = crypto_tfm_ctx(crypto_pcomp_tfm(tfm)); 
    628 + 
    629 +       ctx->pos = 0; 
    630671+       return 0; 
    631672+} 
     
    634675+unlzma_wait_complete(struct unlzma_ctx *ctx, bool finish) 
    635676+{ 
     677+       DEFINE_WAIT(__wait); 
     678+ 
    636679+       do { 
     680+               wake_up(&ctx->next_req); 
     681+               prepare_to_wait(&ctx->req_done, &__wait, TASK_INTERRUPTIBLE); 
    637682+               mutex_unlock(&ctx->mutex); 
    638 +               wake_up(&ctx->next_req); 
    639683+               schedule(); 
    640684+               mutex_lock(&ctx->mutex); 
    641 +       } while (ctx->active && (ctx->avail_in > 0) && (ctx->avail_out > 0)); 
     685+       } while (!ctx->waiting && ctx->active); 
     686+       finish_wait(&ctx->req_done, &__wait); 
    642687+} 
    643688+ 
     
    653698+ 
    654699+       pos = ctx->pos; 
     700+       ctx->waiting = false; 
    655701+       ctx->next_in = req->next_in; 
    656702+       ctx->avail_in = req->avail_in; 
     
    670716+out: 
    671717+       mutex_unlock(&ctx->mutex); 
     718+       if (ctx->cancel) 
     719+               return -EINVAL; 
     720+ 
    672721+       return pos; 
    673722+} 
     
    833882+ 
    834883+#endif 
     884--- a/include/crypto/compress.h 
     885+++ b/include/crypto/compress.h 
     886@@ -49,6 +49,12 @@ enum zlib_decomp_params { 
     887  
     888 #define ZLIB_DECOMP_MAX        (__ZLIB_DECOMP_MAX - 1) 
     889  
     890+enum unlzma_decomp_params { 
     891+       UNLZMA_DECOMP_OUT_BUFFERS = 1, /* naximum number of output buffers */ 
     892+       __UNLZMA_DECOMP_MAX, 
     893+}; 
     894+#define UNLZMA_DECOMP_MAX      (__UNLZMA_DECOMP_MAX - 1) 
     895+ 
     896  
     897 struct crypto_pcomp { 
     898        struct crypto_tfm base; 
Note: See TracChangeset for help on using the changeset viewer.