static int ipcomp_compress(struct xfrm_state *x, struct sk_buff *skb) { int err, plen, dlen, ihlen; struct iphdr *iph = skb->nh.iph; struct ipcomp_data *ipcd = x->data; u8 *start, *scratch = ipcd->scratch; ihlen = iph->ihl * 4; plen = skb->len - ihlen; dlen = IPCOMP_SCRATCH_SIZE; start = skb->data + ihlen; err = crypto_comp_compress(ipcd->tfm, start, plen, scratch, &dlen); if (err) goto out; if ((dlen + sizeof(struct ip_comp_hdr)) >= plen) { err = -EMSGSIZE; goto out; } memcpy(start, scratch, dlen); pskb_trim(skb, ihlen + dlen); out: return err; }
static int ipcomp_compress(struct xfrm_state *x, struct sk_buff *skb) { struct ipcomp_data *ipcd = x->data; const int plen = skb->len; int dlen = IPCOMP_SCRATCH_SIZE; u8 *start = skb->data; const int cpu = get_cpu(); u8 *scratch = *per_cpu_ptr(ipcomp_scratches, cpu); struct crypto_comp *tfm = *per_cpu_ptr(ipcd->tfms, cpu); int err; local_bh_disable(); err = crypto_comp_compress(tfm, start, plen, scratch, &dlen); local_bh_enable(); if (err) goto out; if ((dlen + sizeof(struct ip_comp_hdr)) >= plen) { err = -EMSGSIZE; goto out; } memcpy(start + sizeof(struct ip_comp_hdr), scratch, dlen); put_cpu(); pskb_trim(skb, dlen + sizeof(struct ip_comp_hdr)); return 0; out: put_cpu(); return err; }
int scfs_compress_crypto(const void *in_buf, size_t in_len, void *out_buf, size_t *out_len, int compr_type) { int err = 0; struct scfs_compressor *compr = scfs_compressors[compr_type]; unsigned int tmp_len; if (compr_type == SCFS_COMP_NONE) goto no_compr; if (compr->comp_mutex) mutex_lock(compr->comp_mutex); tmp_len = (unsigned int)*out_len; err = crypto_comp_compress(compr->cc, in_buf, in_len, out_buf, &tmp_len); *out_len = (size_t)tmp_len; if (compr->comp_mutex) mutex_unlock(compr->comp_mutex); if (unlikely(err)) { SCFS_PRINT_ERROR("cannot compress %d bytes, compressor %s, " "error %d, leave data uncompressed", in_len, compr->name, err); err = 0; goto no_compr; } return err; no_compr: memcpy(out_buf, in_buf, in_len); *out_len = in_len; // *compr_type = SCFS_COMP_NONE; return err; }
static int ipcomp6_output(struct sk_buff **pskb) { int err; struct dst_entry *dst = (*pskb)->dst; struct xfrm_state *x = dst->xfrm; struct ipv6hdr *top_iph; int hdr_len; struct ipv6_comp_hdr *ipch; struct ipcomp_data *ipcd = x->data; int plen, dlen; u8 *start, *scratch = ipcd->scratch; hdr_len = (*pskb)->h.raw - (*pskb)->data; /* check whether datagram len is larger than threshold */ if (((*pskb)->len - hdr_len) < ipcd->threshold) { goto out_ok; } if ((skb_is_nonlinear(*pskb) || skb_cloned(*pskb)) && skb_linearize(*pskb, GFP_ATOMIC) != 0) { err = -ENOMEM; goto error; } /* compression */ plen = (*pskb)->len - hdr_len; dlen = IPCOMP_SCRATCH_SIZE; start = (*pskb)->h.raw; err = crypto_comp_compress(ipcd->tfm, start, plen, scratch, &dlen); if (err) { goto error; } if ((dlen + sizeof(struct ipv6_comp_hdr)) >= plen) { goto out_ok; } memcpy(start + sizeof(struct ip_comp_hdr), scratch, dlen); pskb_trim(*pskb, hdr_len + dlen + sizeof(struct ip_comp_hdr)); /* insert ipcomp header and replace datagram */ top_iph = (struct ipv6hdr *)(*pskb)->data; top_iph->payload_len = htons((*pskb)->len - sizeof(struct ipv6hdr)); ipch = (struct ipv6_comp_hdr *)start; ipch->nexthdr = *(*pskb)->nh.raw; ipch->flags = 0; ipch->cpi = htons((u16 )ntohl(x->id.spi)); *(*pskb)->nh.raw = IPPROTO_COMP; out_ok: err = 0; error: return err; }
static int pstore_compress(const void *in, void *out, unsigned int inlen, unsigned int outlen) { int ret; ret = crypto_comp_compress(tfm, in, inlen, out, &outlen); if (ret) { pr_err("crypto_comp_compress failed, ret = %d!\n", ret); return ret; } return outlen; }
/** * ubifs_compress - compress data. * @in_buf: data to compress * @in_len: length of the data to compress * @out_buf: output buffer where compressed data should be stored * @out_len: output buffer length is returned here * @compr_type: type of compression to use on enter, actually used compression * type on exit * * This function compresses input buffer @in_buf of length @in_len and stores * the result in the output buffer @out_buf and the resulting length in * @out_len. If the input buffer does not compress, it is just copied to the * @out_buf. The same happens if @compr_type is %UBIFS_COMPR_NONE or if * compression error occurred. * * Note, if the input buffer was not compressed, it is copied to the output * buffer and %UBIFS_COMPR_NONE is returned in @compr_type. */ void ubifs_compress(const void *in_buf, int in_len, void *out_buf, int *out_len, int *compr_type) { int err; struct ubifs_compressor *compr = ubifs_compressors[*compr_type]; if (*compr_type == UBIFS_COMPR_NONE) goto no_compr; /* If the input data is small, do not even try to compress it */ if (in_len < UBIFS_MIN_COMPR_LEN) goto no_compr; if (compr->comp_mutex) mutex_lock(compr->comp_mutex); err = crypto_comp_compress(compr->cc, in_buf, in_len, out_buf, (unsigned int *)out_len); if (compr->comp_mutex) mutex_unlock(compr->comp_mutex); if (unlikely(err)) { ubifs_warn("cannot compress %d bytes, compressor %s, " "error %d, leave data uncompressed", in_len, compr->name, err); goto no_compr; } /* * If the data compressed only slightly, it is better to leave it * uncompressed to improve read speed. */ if (in_len - *out_len < UBIFS_MIN_COMPRESS_DIFF) goto no_compr; if (*compr_type == UBIFS_COMPR_LZO999) *compr_type = UBIFS_COMPR_LZO; return; no_compr: memcpy(out_buf, in_buf, in_len); *out_len = in_len; *compr_type = UBIFS_COMPR_NONE; }
static int zswap_comp_op(enum comp_op op, const u8 *src, unsigned int slen, u8 *dst, unsigned int *dlen) { struct crypto_comp *tfm; int ret; tfm = *per_cpu_ptr(zswap_comp_pcpu_tfms, get_cpu()); switch (op) { case ZSWAP_COMPOP_COMPRESS: ret = crypto_comp_compress(tfm, src, slen, dst, dlen); break; case ZSWAP_COMPOP_DECOMPRESS: ret = crypto_comp_decompress(tfm, src, slen, dst, dlen); break; default: ret = -EINVAL; } put_cpu(); return ret; }
static inline int zcache_comp_op(enum comp_op op, const u8 *src, unsigned int slen, u8 *dst, unsigned int *dlen) { struct crypto_comp *tfm; int ret; BUG_ON(!zcache_comp_pcpu_tfms); tfm = *per_cpu_ptr(zcache_comp_pcpu_tfms, get_cpu()); BUG_ON(!tfm); switch (op) { case ZCACHE_COMPOP_COMPRESS: ret = crypto_comp_compress(tfm, src, slen, dst, dlen); break; case ZCACHE_COMPOP_DECOMPRESS: ret = crypto_comp_decompress(tfm, src, slen, dst, dlen); break; } put_cpu(); return ret; }
int zcomp_compress(struct zcomp_strm *zstrm, const void *src, unsigned int *dst_len) { /* * Our dst memory (zstrm->buffer) is always `2 * PAGE_SIZE' sized * because sometimes we can endup having a bigger compressed data * due to various reasons: for example compression algorithms tend * to add some padding to the compressed buffer. Speaking of padding, * comp algorithm `842' pads the compressed length to multiple of 8 * and returns -ENOSP when the dst memory is not big enough, which * is not something that ZRAM wants to see. We can handle the * `compressed_size > PAGE_SIZE' case easily in ZRAM, but when we * receive -ERRNO from the compressing backend we can't help it * anymore. To make `842' happy we need to tell the exact size of * the dst buffer, zram_drv will take care of the fact that * compressed buffer is too big. */ *dst_len = PAGE_SIZE * 2; return crypto_comp_compress(zstrm->tfm, src, PAGE_SIZE, zstrm->buffer, dst_len); }
void ubifs_compress(const void *in_buf, int in_len, void *out_buf, int *out_len, int *compr_type) { int err; struct ubifs_compressor *compr = ubifs_compressors[*compr_type]; if (*compr_type == UBIFS_COMPR_NONE) goto no_compr; if (in_len < UBIFS_MIN_COMPR_LEN) goto no_compr; if (compr->comp_mutex) mutex_lock(compr->comp_mutex); err = crypto_comp_compress(compr->cc, in_buf, in_len, out_buf, (unsigned int *)out_len); if (compr->comp_mutex) mutex_unlock(compr->comp_mutex); if (unlikely(err)) { ubifs_warn("cannot compress %d bytes, compressor %s, " "error %d, leave data uncompressed", in_len, compr->name, err); goto no_compr; } if (in_len - *out_len < UBIFS_MIN_COMPRESS_DIFF) goto no_compr; return; no_compr: memcpy(out_buf, in_buf, in_len); *out_len = in_len; *compr_type = UBIFS_COMPR_NONE; }
static int ipcomp6_output(struct sk_buff **pskb) { int err; struct dst_entry *dst = (*pskb)->dst; struct xfrm_state *x = dst->xfrm; struct ipv6hdr *tmp_iph = NULL, *iph, *top_iph; int hdr_len = 0; struct ipv6_comp_hdr *ipch; struct ipcomp_data *ipcd = x->data; u8 *prevhdr; u8 nexthdr = 0; int plen, dlen; u8 *start, *scratch = ipcd->scratch; if ((*pskb)->ip_summed == CHECKSUM_HW) { err = skb_checksum_help(pskb, 0); if (err) goto error_nolock; } spin_lock_bh(&x->lock); err = xfrm_check_output(x, *pskb, AF_INET6); if (err) goto error; if (x->props.mode) { hdr_len = sizeof(struct ipv6hdr); nexthdr = IPPROTO_IPV6; iph = (*pskb)->nh.ipv6h; top_iph = (struct ipv6hdr *)skb_push(*pskb, sizeof(struct ipv6hdr)); top_iph->version = 6; top_iph->priority = iph->priority; top_iph->flow_lbl[0] = iph->flow_lbl[0]; top_iph->flow_lbl[1] = iph->flow_lbl[1]; top_iph->flow_lbl[2] = iph->flow_lbl[2]; top_iph->nexthdr = IPPROTO_IPV6; /* initial */ top_iph->payload_len = htons((*pskb)->len - sizeof(struct ipv6hdr)); top_iph->hop_limit = iph->hop_limit; memcpy(&top_iph->saddr, (struct in6_addr *)&x->props.saddr, sizeof(struct in6_addr)); memcpy(&top_iph->daddr, (struct in6_addr *)&x->id.daddr, sizeof(struct in6_addr)); (*pskb)->nh.raw = (*pskb)->data; /* == top_iph */ (*pskb)->h.raw = (*pskb)->nh.raw + hdr_len; } else { hdr_len = ip6_find_1stfragopt(*pskb, &prevhdr); nexthdr = *prevhdr; } /* check whether datagram len is larger than threshold */ if (((*pskb)->len - hdr_len) < ipcd->threshold) { goto out_ok; } if ((skb_is_nonlinear(*pskb) || skb_cloned(*pskb)) && skb_linearize(*pskb, GFP_ATOMIC) != 0) { err = -ENOMEM; goto error; } /* compression */ plen = (*pskb)->len - hdr_len; dlen = IPCOMP_SCRATCH_SIZE; start = (*pskb)->data + hdr_len; err = crypto_comp_compress(ipcd->tfm, start, plen, scratch, &dlen); if (err) { goto error; } if ((dlen + sizeof(struct ipv6_comp_hdr)) >= plen) { goto out_ok; } memcpy(start, scratch, dlen); pskb_trim(*pskb, hdr_len+dlen); /* insert ipcomp header and replace datagram */ tmp_iph = kmalloc(hdr_len, GFP_ATOMIC); if (!tmp_iph) { err = -ENOMEM; goto error; } memcpy(tmp_iph, (*pskb)->nh.raw, hdr_len); top_iph = (struct ipv6hdr*)skb_push(*pskb, sizeof(struct ipv6_comp_hdr)); memcpy(top_iph, tmp_iph, hdr_len); kfree(tmp_iph); if (x->props.mode && (x->props.flags & XFRM_STATE_NOECN)) IP6_ECN_clear(top_iph); top_iph->payload_len = htons((*pskb)->len - sizeof(struct ipv6hdr)); (*pskb)->nh.raw = (*pskb)->data; /* top_iph */ ip6_find_1stfragopt(*pskb, &prevhdr); *prevhdr = IPPROTO_COMP; ipch = (struct ipv6_comp_hdr *)((unsigned char *)top_iph + hdr_len); ipch->nexthdr = nexthdr; ipch->flags = 0; ipch->cpi = htons((u16 )ntohl(x->id.spi)); (*pskb)->h.raw = (unsigned char*)ipch; out_ok: x->curlft.bytes += (*pskb)->len; x->curlft.packets++; spin_unlock_bh(&x->lock); if (((*pskb)->dst = dst_pop(dst)) == NULL) { err = -EHOSTUNREACH; goto error_nolock; } err = NET_XMIT_BYPASS; out_exit: return err; error: spin_unlock_bh(&x->lock); error_nolock: kfree_skb(*pskb); goto out_exit; }