ReactOS  0.4.15-dev-5496-g599ba9c
compress.c
Go to the documentation of this file.
1 /* Copyright (c) Mark Harmstone 2016-17
2  * Copyright (c) Reimar Doeffinger 2006
3  * Copyright (c) Markus Oberhumer 1996
4  *
5  * This file is part of WinBtrfs.
6  *
7  * WinBtrfs is free software: you can redistribute it and/or modify
8  * it under the terms of the GNU Lesser General Public Licence as published by
9  * the Free Software Foundation, either version 3 of the Licence, or
10  * (at your option) any later version.
11  *
12  * WinBtrfs is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15  * GNU Lesser General Public Licence for more details.
16  *
17  * You should have received a copy of the GNU Lesser General Public Licence
18  * along with WinBtrfs. If not, see <http://www.gnu.org/licenses/>. */
19 
20 // Portions of the LZO decompression code here were cribbed from code in
21 // libavcodec, also under the LGPL. Thank you, Reimar Doeffinger.
22 
23 // The LZO compression code comes from v0.22 of lzo, written way back in
24 // 1996, and available here:
25 // https://www.ibiblio.org/pub/historic-linux/ftp-archives/sunsite.unc.edu/Sep-29-1996/libs/lzo-0.22.tar.gz
26 // Modern versions of lzo are licensed under the GPL, but the very oldest
27 // versions are under the LGPL and hence okay to use here.
28 
29 #include "btrfs_drv.h"
30 
31 #define Z_SOLO
32 #define ZLIB_INTERNAL
33 
34 #ifndef __REACTOS__
35 #include "zlib/zlib.h"
36 #include "zlib/inftrees.h"
37 #include "zlib/inflate.h"
38 #else
39 #include <zlib.h>
40 #endif // __REACTOS__
41 
42 #define ZSTD_STATIC_LINKING_ONLY
43 
44 #include "zstd/zstd.h"
45 
46 #define LZO_PAGE_SIZE 4096
47 
48 typedef struct {
55  bool error;
56  void* wrkmem;
57 } lzo_stream;
58 
59 #define LZO1X_MEM_COMPRESS ((uint32_t) (16384L * sizeof(uint8_t*)))
60 
61 #define M1_MAX_OFFSET 0x0400
62 #define M2_MAX_OFFSET 0x0800
63 #define M3_MAX_OFFSET 0x4000
64 #define M4_MAX_OFFSET 0xbfff
65 
66 #define MX_MAX_OFFSET (M1_MAX_OFFSET + M2_MAX_OFFSET)
67 
68 #define M1_MARKER 0
69 #define M2_MARKER 64
70 #define M3_MARKER 32
71 #define M4_MARKER 16
72 
73 #define _DV2(p, shift1, shift2) (((( (uint32_t)(p[2]) << shift1) ^ p[1]) << shift2) ^ p[0])
74 #define DVAL_NEXT(dv, p) dv ^= p[-1]; dv = (((dv) >> 5) ^ ((uint32_t)(p[2]) << (2*5)))
75 #define _DV(p, shift) _DV2(p, shift, shift)
76 #define DVAL_FIRST(dv, p) dv = _DV((p), 5)
77 #define _DINDEX(dv, p) ((40799u * (dv)) >> 5)
78 #define DINDEX(dv, p) (((_DINDEX(dv, p)) & 0x3fff) << 0)
79 #define UPDATE_D(dict, cycle, dv, p) dict[DINDEX(dv, p)] = (p)
80 #define UPDATE_I(dict, cycle, index, p) dict[index] = (p)
81 
82 #define LZO_CHECK_MPOS_NON_DET(m_pos, m_off, in, ip, max_offset) \
83  ((void*) m_pos < (void*) in || \
84  (m_off = (uint8_t*) ip - (uint8_t*) m_pos) <= 0 || \
85  m_off > max_offset)
86 
87 #define LZO_BYTE(x) ((unsigned char) (x))
88 
89 #define ZSTD_ALLOC_TAG 0x6474737a // "zstd"
90 
91 // needs to be the same as Linux (fs/btrfs/zstd.c)
92 #define ZSTD_BTRFS_MAX_WINDOWLOG 17
93 
94 static void* zstd_malloc(void* opaque, size_t size);
95 static void zstd_free(void* opaque, void* address);
96 
97 #ifndef __REACTOS__
98 ZSTD_customMem zstd_mem = { .customAlloc = zstd_malloc, .customFree = zstd_free, .opaque = NULL };
99 #else
100 ZSTD_customMem zstd_mem = { zstd_malloc, zstd_free, NULL };
101 #endif
102 
104  uint8_t c;
105 
106  if (stream->inpos >= stream->inlen) {
107  stream->error = true;
108  return 0;
109  }
110 
111  c = stream->in[stream->inpos];
112  stream->inpos++;
113 
114  return c;
115 }
116 
117 static int lzo_len(lzo_stream* stream, int byte, int mask) {
118  int len = byte & mask;
119 
120  if (len == 0) {
121  while (!(byte = lzo_nextbyte(stream))) {
122  if (stream->error) return 0;
123 
124  len += 255;
125  }
126 
127  len += mask + byte;
128  }
129 
130  return len;
131 }
132 
133 static void lzo_copy(lzo_stream* stream, int len) {
134  if (stream->inpos + len > stream->inlen) {
135  stream->error = true;
136  return;
137  }
138 
139  if (stream->outpos + len > stream->outlen) {
140  stream->error = true;
141  return;
142  }
143 
144  do {
145  stream->out[stream->outpos] = stream->in[stream->inpos];
146  stream->inpos++;
147  stream->outpos++;
148  len--;
149  } while (len > 0);
150 }
151 
152 static void lzo_copyback(lzo_stream* stream, uint32_t back, int len) {
153  if (stream->outpos < back) {
154  stream->error = true;
155  return;
156  }
157 
158  if (stream->outpos + len > stream->outlen) {
159  stream->error = true;
160  return;
161  }
162 
163  do {
164  stream->out[stream->outpos] = stream->out[stream->outpos - back];
165  stream->outpos++;
166  len--;
167  } while (len > 0);
168 }
169 
171  uint8_t byte;
172  uint32_t len, back;
173  bool backcopy = false;
174 
175  stream->error = false;
176 
177  byte = lzo_nextbyte(stream);
178  if (stream->error) return STATUS_INTERNAL_ERROR;
179 
180  if (byte > 17) {
181  lzo_copy(stream, min((uint8_t)(byte - 17), (uint32_t)(stream->outlen - stream->outpos)));
182  if (stream->error) return STATUS_INTERNAL_ERROR;
183 
184  if (stream->outlen == stream->outpos)
185  return STATUS_SUCCESS;
186 
187  byte = lzo_nextbyte(stream);
188  if (stream->error) return STATUS_INTERNAL_ERROR;
189 
190  if (byte < 16) return STATUS_INTERNAL_ERROR;
191  }
192 
193  while (1) {
194  if (byte >> 4) {
195  backcopy = true;
196  if (byte >> 6) {
197  len = (byte >> 5) - 1;
198  back = (lzo_nextbyte(stream) << 3) + ((byte >> 2) & 7) + 1;
199  if (stream->error) return STATUS_INTERNAL_ERROR;
200  } else if (byte >> 5) {
201  len = lzo_len(stream, byte, 31);
202  if (stream->error) return STATUS_INTERNAL_ERROR;
203 
204  byte = lzo_nextbyte(stream);
205  if (stream->error) return STATUS_INTERNAL_ERROR;
206 
207  back = (lzo_nextbyte(stream) << 6) + (byte >> 2) + 1;
208  if (stream->error) return STATUS_INTERNAL_ERROR;
209  } else {
210  len = lzo_len(stream, byte, 7);
211  if (stream->error) return STATUS_INTERNAL_ERROR;
212 
213  back = (1 << 14) + ((byte & 8) << 11);
214 
215  byte = lzo_nextbyte(stream);
216  if (stream->error) return STATUS_INTERNAL_ERROR;
217 
218  back += (lzo_nextbyte(stream) << 6) + (byte >> 2);
219  if (stream->error) return STATUS_INTERNAL_ERROR;
220 
221  if (back == (1 << 14)) {
222  if (len != 1)
223  return STATUS_INTERNAL_ERROR;
224  break;
225  }
226  }
227  } else if (backcopy) {
228  len = 0;
229  back = (lzo_nextbyte(stream) << 2) + (byte >> 2) + 1;
230  if (stream->error) return STATUS_INTERNAL_ERROR;
231  } else {
232  len = lzo_len(stream, byte, 15);
233  if (stream->error) return STATUS_INTERNAL_ERROR;
234 
235  lzo_copy(stream, min(len + 3, stream->outlen - stream->outpos));
236  if (stream->error) return STATUS_INTERNAL_ERROR;
237 
238  if (stream->outlen == stream->outpos)
239  return STATUS_SUCCESS;
240 
241  byte = lzo_nextbyte(stream);
242  if (stream->error) return STATUS_INTERNAL_ERROR;
243 
244  if (byte >> 4)
245  continue;
246 
247  len = 1;
248  back = (1 << 11) + (lzo_nextbyte(stream) << 2) + (byte >> 2) + 1;
249  if (stream->error) return STATUS_INTERNAL_ERROR;
250 
251  break;
252  }
253 
254  lzo_copyback(stream, back, min(len + 2, stream->outlen - stream->outpos));
255  if (stream->error) return STATUS_INTERNAL_ERROR;
256 
257  if (stream->outlen == stream->outpos)
258  return STATUS_SUCCESS;
259 
260  len = byte & 3;
261 
262  if (len) {
263  lzo_copy(stream, min(len, stream->outlen - stream->outpos));
264  if (stream->error) return STATUS_INTERNAL_ERROR;
265 
266  if (stream->outlen == stream->outpos)
267  return STATUS_SUCCESS;
268  } else
269  backcopy = !backcopy;
270 
271  byte = lzo_nextbyte(stream);
272  if (stream->error) return STATUS_INTERNAL_ERROR;
273  }
274 
275  return STATUS_SUCCESS;
276 }
277 
278 NTSTATUS lzo_decompress(uint8_t* inbuf, uint32_t inlen, uint8_t* outbuf, uint32_t outlen, uint32_t inpageoff) {
280  uint32_t partlen, inoff, outoff;
282 
283  inoff = 0;
284  outoff = 0;
285 
286  do {
287  partlen = *(uint32_t*)&inbuf[inoff];
288 
289  if (partlen + inoff > inlen) {
290  ERR("overflow: %x + %x > %x\n", partlen, inoff, inlen);
291  return STATUS_INTERNAL_ERROR;
292  }
293 
294  inoff += sizeof(uint32_t);
295 
296  stream.in = &inbuf[inoff];
297  stream.inlen = partlen;
298  stream.inpos = 0;
299  stream.out = &outbuf[outoff];
300  stream.outlen = min(outlen, LZO_PAGE_SIZE);
301  stream.outpos = 0;
302 
304  if (!NT_SUCCESS(Status)) {
305  ERR("do_lzo_decompress returned %08lx\n", Status);
306  return Status;
307  }
308 
309  if (stream.outpos < stream.outlen)
310  RtlZeroMemory(&stream.out[stream.outpos], stream.outlen - stream.outpos);
311 
312  inoff += partlen;
313  outoff += stream.outlen;
314 
315  if (LZO_PAGE_SIZE - ((inpageoff + inoff) % LZO_PAGE_SIZE) < sizeof(uint32_t))
316  inoff = ((((inpageoff + inoff) / LZO_PAGE_SIZE) + 1) * LZO_PAGE_SIZE) - inpageoff;
317 
318  outlen -= stream.outlen;
319  } while (inoff < inlen && outlen > 0);
320 
321  return STATUS_SUCCESS;
322 }
323 
324 static void* zlib_alloc(void* opaque, unsigned int items, unsigned int size) {
325  UNUSED(opaque);
326 
328 }
329 
330 static void zlib_free(void* opaque, void* ptr) {
331  UNUSED(opaque);
332 
333  ExFreePool(ptr);
334 }
335 
336 NTSTATUS zlib_compress(uint8_t* inbuf, uint32_t inlen, uint8_t* outbuf, uint32_t outlen, unsigned int level, unsigned int* space_left) {
337  z_stream c_stream;
338  int ret;
339 
340  c_stream.zalloc = zlib_alloc;
341  c_stream.zfree = zlib_free;
342  c_stream.opaque = (voidpf)0;
343 
344  ret = deflateInit(&c_stream, level);
345 
346  if (ret != Z_OK) {
347  ERR("deflateInit returned %i\n", ret);
348  return STATUS_INTERNAL_ERROR;
349  }
350 
351  c_stream.next_in = inbuf;
352  c_stream.avail_in = inlen;
353 
354  c_stream.next_out = outbuf;
355  c_stream.avail_out = outlen;
356 
357  do {
358  ret = deflate(&c_stream, Z_FINISH);
359 
360  if (ret != Z_OK && ret != Z_STREAM_END) {
361  ERR("deflate returned %i\n", ret);
362  deflateEnd(&c_stream);
363  return STATUS_INTERNAL_ERROR;
364  }
365 
366  if (c_stream.avail_in == 0 || c_stream.avail_out == 0)
367  break;
368  } while (ret != Z_STREAM_END);
369 
370  deflateEnd(&c_stream);
371 
372  *space_left = c_stream.avail_in > 0 ? 0 : c_stream.avail_out;
373 
374  return STATUS_SUCCESS;
375 }
376 
378  z_stream c_stream;
379  int ret;
380 
381  c_stream.zalloc = zlib_alloc;
382  c_stream.zfree = zlib_free;
383  c_stream.opaque = (voidpf)0;
384 
385  ret = inflateInit(&c_stream);
386 
387  if (ret != Z_OK) {
388  ERR("inflateInit returned %i\n", ret);
389  return STATUS_INTERNAL_ERROR;
390  }
391 
392  c_stream.next_in = inbuf;
393  c_stream.avail_in = inlen;
394 
395  c_stream.next_out = outbuf;
396  c_stream.avail_out = outlen;
397 
398  do {
399  ret = inflate(&c_stream, Z_NO_FLUSH);
400 
401  if (ret != Z_OK && ret != Z_STREAM_END) {
402  ERR("inflate returned %i\n", ret);
403  inflateEnd(&c_stream);
404  return STATUS_INTERNAL_ERROR;
405  }
406 
407  if (c_stream.avail_out == 0)
408  break;
409  } while (ret != Z_STREAM_END);
410 
411  ret = inflateEnd(&c_stream);
412 
413  if (ret != Z_OK) {
414  ERR("inflateEnd returned %i\n", ret);
415  return STATUS_INTERNAL_ERROR;
416  }
417 
418  // FIXME - if we're short, should we zero the end of outbuf so we don't leak information into userspace?
419 
420  return STATUS_SUCCESS;
421 }
422 
423 static NTSTATUS lzo_do_compress(const uint8_t* in, uint32_t in_len, uint8_t* out, uint32_t* out_len, void* wrkmem) {
424  const uint8_t* ip;
425  uint32_t dv;
426  uint8_t* op;
427  const uint8_t* in_end = in + in_len;
428  const uint8_t* ip_end = in + in_len - 9 - 4;
429  const uint8_t* ii;
430  const uint8_t** dict = (const uint8_t**)wrkmem;
431 
432  op = out;
433  ip = in;
434  ii = ip;
435 
436  DVAL_FIRST(dv, ip); UPDATE_D(dict, cycle, dv, ip); ip++;
437  DVAL_NEXT(dv, ip); UPDATE_D(dict, cycle, dv, ip); ip++;
438  DVAL_NEXT(dv, ip); UPDATE_D(dict, cycle, dv, ip); ip++;
439  DVAL_NEXT(dv, ip); UPDATE_D(dict, cycle, dv, ip); ip++;
440 
441  while (1) {
442  const uint8_t* m_pos;
443  uint32_t m_len;
444  ptrdiff_t m_off;
445  uint32_t lit, dindex;
446 
447  dindex = DINDEX(dv, ip);
448  m_pos = dict[dindex];
449  UPDATE_I(dict, cycle, dindex, ip);
450 
451  if (!LZO_CHECK_MPOS_NON_DET(m_pos, m_off, in, ip, M4_MAX_OFFSET) && m_pos[0] == ip[0] && m_pos[1] == ip[1] && m_pos[2] == ip[2]) {
452  lit = (uint32_t)(ip - ii);
453  m_pos += 3;
454  if (m_off <= M2_MAX_OFFSET)
455  goto match;
456 
457  if (lit == 3) { /* better compression, but slower */
458  if (op - 2 <= out)
459  return STATUS_INTERNAL_ERROR;
460 
461  op[-2] |= LZO_BYTE(3);
462  *op++ = *ii++; *op++ = *ii++; *op++ = *ii++;
463  goto code_match;
464  }
465 
466  if (*m_pos == ip[3])
467  goto match;
468  }
469 
470  /* a literal */
471  ++ip;
472  if (ip >= ip_end)
473  break;
474  DVAL_NEXT(dv, ip);
475  continue;
476 
477  /* a match */
478 match:
479  /* store current literal run */
480  if (lit > 0) {
481  uint32_t t = lit;
482 
483  if (t <= 3) {
484  if (op - 2 <= out)
485  return STATUS_INTERNAL_ERROR;
486 
487  op[-2] |= LZO_BYTE(t);
488  } else if (t <= 18)
489  *op++ = LZO_BYTE(t - 3);
490  else {
491  uint32_t tt = t - 18;
492 
493  *op++ = 0;
494  while (tt > 255) {
495  tt -= 255;
496  *op++ = 0;
497  }
498 
499  if (tt <= 0)
500  return STATUS_INTERNAL_ERROR;
501 
502  *op++ = LZO_BYTE(tt);
503  }
504 
505  do {
506  *op++ = *ii++;
507  } while (--t > 0);
508  }
509 
510 
511  /* code the match */
512 code_match:
513  if (ii != ip)
514  return STATUS_INTERNAL_ERROR;
515 
516  ip += 3;
517  if (*m_pos++ != *ip++ || *m_pos++ != *ip++ || *m_pos++ != *ip++ ||
518  *m_pos++ != *ip++ || *m_pos++ != *ip++ || *m_pos++ != *ip++) {
519  --ip;
520  m_len = (uint32_t)(ip - ii);
521 
522  if (m_len < 3 || m_len > 8)
523  return STATUS_INTERNAL_ERROR;
524 
525  if (m_off <= M2_MAX_OFFSET) {
526  m_off -= 1;
527  *op++ = LZO_BYTE(((m_len - 1) << 5) | ((m_off & 7) << 2));
528  *op++ = LZO_BYTE(m_off >> 3);
529  } else if (m_off <= M3_MAX_OFFSET) {
530  m_off -= 1;
531  *op++ = LZO_BYTE(M3_MARKER | (m_len - 2));
532  goto m3_m4_offset;
533  } else {
534  m_off -= 0x4000;
535 
536  if (m_off <= 0 || m_off > 0x7fff)
537  return STATUS_INTERNAL_ERROR;
538 
539  *op++ = LZO_BYTE(M4_MARKER | ((m_off & 0x4000) >> 11) | (m_len - 2));
540  goto m3_m4_offset;
541  }
542  } else {
543  const uint8_t* end;
544  end = in_end;
545  while (ip < end && *m_pos == *ip)
546  m_pos++, ip++;
547  m_len = (uint32_t)(ip - ii);
548 
549  if (m_len < 3)
550  return STATUS_INTERNAL_ERROR;
551 
552  if (m_off <= M3_MAX_OFFSET) {
553  m_off -= 1;
554  if (m_len <= 33)
555  *op++ = LZO_BYTE(M3_MARKER | (m_len - 2));
556  else {
557  m_len -= 33;
558  *op++ = M3_MARKER | 0;
559  goto m3_m4_len;
560  }
561  } else {
562  m_off -= 0x4000;
563 
564  if (m_off <= 0 || m_off > 0x7fff)
565  return STATUS_INTERNAL_ERROR;
566 
567  if (m_len <= 9)
568  *op++ = LZO_BYTE(M4_MARKER | ((m_off & 0x4000) >> 11) | (m_len - 2));
569  else {
570  m_len -= 9;
571  *op++ = LZO_BYTE(M4_MARKER | ((m_off & 0x4000) >> 11));
572 m3_m4_len:
573  while (m_len > 255) {
574  m_len -= 255;
575  *op++ = 0;
576  }
577 
578  if (m_len <= 0)
579  return STATUS_INTERNAL_ERROR;
580 
581  *op++ = LZO_BYTE(m_len);
582  }
583  }
584 
585 m3_m4_offset:
586  *op++ = LZO_BYTE((m_off & 63) << 2);
587  *op++ = LZO_BYTE(m_off >> 6);
588  }
589 
590  ii = ip;
591  if (ip >= ip_end)
592  break;
593  DVAL_FIRST(dv, ip);
594  }
595 
596  /* store final literal run */
597  if (in_end - ii > 0) {
598  uint32_t t = (uint32_t)(in_end - ii);
599 
600  if (op == out && t <= 238)
601  *op++ = LZO_BYTE(17 + t);
602  else if (t <= 3)
603  op[-2] |= LZO_BYTE(t);
604  else if (t <= 18)
605  *op++ = LZO_BYTE(t - 3);
606  else {
607  uint32_t tt = t - 18;
608 
609  *op++ = 0;
610  while (tt > 255) {
611  tt -= 255;
612  *op++ = 0;
613  }
614 
615  if (tt <= 0)
616  return STATUS_INTERNAL_ERROR;
617 
618  *op++ = LZO_BYTE(tt);
619  }
620 
621  do {
622  *op++ = *ii++;
623  } while (--t > 0);
624  }
625 
626  *out_len = (uint32_t)(op - out);
627 
628  return STATUS_SUCCESS;
629 }
630 
632  uint8_t *op = stream->out;
634 
635  if (stream->inlen <= 0)
636  stream->outlen = 0;
637  else if (stream->inlen <= 9 + 4) {
638  *op++ = LZO_BYTE(17 + stream->inlen);
639 
640  stream->inpos = 0;
641  do {
642  *op++ = stream->in[stream->inpos];
643  stream->inpos++;
644  } while (stream->inlen < stream->inpos);
645  stream->outlen = (uint32_t)(op - stream->out);
646  } else
647  Status = lzo_do_compress(stream->in, stream->inlen, stream->out, &stream->outlen, stream->wrkmem);
648 
649  if (Status == STATUS_SUCCESS) {
650  op = stream->out + stream->outlen;
651  *op++ = M4_MARKER | 1;
652  *op++ = 0;
653  *op++ = 0;
654  stream->outlen += 3;
655  }
656 
657  return Status;
658 }
659 
660 static __inline uint32_t lzo_max_outlen(uint32_t inlen) {
661  return inlen + (inlen / 16) + 64 + 3; // formula comes from LZO.FAQ
662 }
663 
664 static void* zstd_malloc(void* opaque, size_t size) {
665  UNUSED(opaque);
666 
668 }
669 
670 static void zstd_free(void* opaque, void* address) {
671  UNUSED(opaque);
672 
674 }
675 
679  size_t init_res, read;
681  ZSTD_outBuffer output;
682 
684 
685  if (!stream) {
686  ERR("ZSTD_createDStream failed.\n");
687  return STATUS_INTERNAL_ERROR;
688  }
689 
690  init_res = ZSTD_initDStream(stream);
691 
692  if (ZSTD_isError(init_res)) {
693  ERR("ZSTD_initDStream failed: %s\n", ZSTD_getErrorName(init_res));
695  goto end;
696  }
697 
698  input.src = inbuf;
699  input.size = inlen;
700  input.pos = 0;
701 
702  output.dst = outbuf;
703  output.size = outlen;
704  output.pos = 0;
705 
706  do {
707  read = ZSTD_decompressStream(stream, &output, &input);
708 
709  if (ZSTD_isError(read)) {
710  ERR("ZSTD_decompressStream failed: %s\n", ZSTD_getErrorName(read));
712  goto end;
713  }
714 
715  if (output.pos == output.size)
716  break;
717  } while (read != 0);
718 
720 
721 end:
723 
724  return Status;
725 }
726 
727 NTSTATUS lzo_compress(uint8_t* inbuf, uint32_t inlen, uint8_t* outbuf, uint32_t outlen, unsigned int* space_left) {
729  unsigned int num_pages;
730  unsigned int comp_data_len;
731  uint8_t* comp_data;
734 
735  num_pages = (unsigned int)sector_align(inlen, LZO_PAGE_SIZE) / LZO_PAGE_SIZE;
736 
737  // Four-byte overall header
738  // Another four-byte header page
739  // Each page has a maximum size of lzo_max_outlen(LZO_PAGE_SIZE)
740  // Plus another four bytes for possible padding
741  comp_data_len = sizeof(uint32_t) + ((lzo_max_outlen(LZO_PAGE_SIZE) + (2 * sizeof(uint32_t))) * num_pages);
742 
743  // FIXME - can we write this so comp_data isn't necessary?
744 
745  comp_data = ExAllocatePoolWithTag(PagedPool, comp_data_len, ALLOC_TAG);
746  if (!comp_data) {
747  ERR("out of memory\n");
749  }
750 
752  if (!stream.wrkmem) {
753  ERR("out of memory\n");
754  ExFreePool(comp_data);
756  }
757 
758  out_size = (uint32_t*)comp_data;
759  *out_size = sizeof(uint32_t);
760 
761  stream.in = inbuf;
762  stream.out = comp_data + (2 * sizeof(uint32_t));
763 
764  for (unsigned int i = 0; i < num_pages; i++) {
765  uint32_t* pagelen = (uint32_t*)(stream.out - sizeof(uint32_t));
766 
767  stream.inlen = (uint32_t)min(LZO_PAGE_SIZE, outlen - (i * LZO_PAGE_SIZE));
768 
770  if (!NT_SUCCESS(Status)) {
771  ERR("lzo1x_1_compress returned %08lx\n", Status);
772  ExFreePool(comp_data);
773  return Status;
774  }
775 
776  *pagelen = stream.outlen;
777  *out_size += stream.outlen + sizeof(uint32_t);
778 
779  stream.in += LZO_PAGE_SIZE;
780  stream.out += stream.outlen + sizeof(uint32_t);
781 
782  // new page needs to start at a 32-bit boundary
783  if (LZO_PAGE_SIZE - (*out_size % LZO_PAGE_SIZE) < sizeof(uint32_t)) {
787  }
788  }
789 
790  ExFreePool(stream.wrkmem);
791 
792  if (*out_size >= outlen)
793  *space_left = 0;
794  else {
795  *space_left = outlen - *out_size;
796 
797  RtlCopyMemory(outbuf, comp_data, *out_size);
798  }
799 
800  ExFreePool(comp_data);
801 
802  return STATUS_SUCCESS;
803 }
804 
805 NTSTATUS zstd_compress(uint8_t* inbuf, uint32_t inlen, uint8_t* outbuf, uint32_t outlen, uint32_t level, unsigned int* space_left) {
807  size_t init_res, written;
809  ZSTD_outBuffer output;
810  ZSTD_parameters params;
811 
813 
814  if (!stream) {
815  ERR("ZSTD_createCStream failed.\n");
816  return STATUS_INTERNAL_ERROR;
817  }
818 
819  params = ZSTD_getParams(level, inlen, 0);
820 
821  if (params.cParams.windowLog > ZSTD_BTRFS_MAX_WINDOWLOG)
822  params.cParams.windowLog = ZSTD_BTRFS_MAX_WINDOWLOG;
823 
824  init_res = ZSTD_initCStream_advanced(stream, NULL, 0, params, inlen);
825 
826  if (ZSTD_isError(init_res)) {
827  ERR("ZSTD_initCStream_advanced failed: %s\n", ZSTD_getErrorName(init_res));
829  return STATUS_INTERNAL_ERROR;
830  }
831 
832  input.src = inbuf;
833  input.size = inlen;
834  input.pos = 0;
835 
836  output.dst = outbuf;
837  output.size = outlen;
838  output.pos = 0;
839 
840  while (input.pos < input.size && output.pos < output.size) {
841  written = ZSTD_compressStream(stream, &output, &input);
842 
843  if (ZSTD_isError(written)) {
844  ERR("ZSTD_compressStream failed: %s\n", ZSTD_getErrorName(written));
846  return STATUS_INTERNAL_ERROR;
847  }
848  }
849 
850  written = ZSTD_endStream(stream, &output);
851  if (ZSTD_isError(written)) {
852  ERR("ZSTD_endStream failed: %s\n", ZSTD_getErrorName(written));
854  return STATUS_INTERNAL_ERROR;
855  }
856 
858 
859  if (input.pos < input.size) // output would be larger than input
860  *space_left = 0;
861  else
862  *space_left = output.size - output.pos;
863 
864  return STATUS_SUCCESS;
865 }
866 
867 typedef struct {
870  unsigned int inlen;
871  unsigned int outlen;
873 } comp_part;
874 
877  uint64_t i;
878  unsigned int num_parts = (unsigned int)sector_align(end_data - start_data, COMPRESSED_EXTENT_SIZE) / COMPRESSED_EXTENT_SIZE;
879  uint8_t type;
880  comp_part* parts;
881  unsigned int buflen = 0;
882  uint8_t* buf;
883  chunk* c = NULL;
884  LIST_ENTRY* le;
885  uint64_t address, extaddr;
886  void* csum = NULL;
887 
888  if (fcb->Vcb->options.compress_type != 0 && fcb->prop_compression == PropCompression_None)
889  type = fcb->Vcb->options.compress_type;
890  else {
891  if (!(fcb->Vcb->superblock.incompat_flags & BTRFS_INCOMPAT_FLAGS_COMPRESS_ZSTD) && fcb->prop_compression == PropCompression_ZSTD)
895  else if (!(fcb->Vcb->superblock.incompat_flags & BTRFS_INCOMPAT_FLAGS_COMPRESS_LZO) && fcb->prop_compression == PropCompression_LZO)
897  else if (fcb->Vcb->superblock.incompat_flags & BTRFS_INCOMPAT_FLAGS_COMPRESS_LZO && fcb->prop_compression != PropCompression_Zlib)
899  else
901  }
902 
904  if (!NT_SUCCESS(Status)) {
905  ERR("excise_extents returned %08lx\n", Status);
906  return Status;
907  }
908 
909  parts = ExAllocatePoolWithTag(PagedPool, sizeof(comp_part) * num_parts, ALLOC_TAG);
910  if (!parts) {
911  ERR("out of memory\n");
913  }
914 
915  for (i = 0; i < num_parts; i++) {
916  if (i == num_parts - 1)
917  parts[i].inlen = ((unsigned int)(end_data - start_data) - ((num_parts - 1) * COMPRESSED_EXTENT_SIZE));
918  else
919  parts[i].inlen = COMPRESSED_EXTENT_SIZE;
920 
922  parts[i].buf, parts[i].inlen, &parts[i].cj);
923  if (!NT_SUCCESS(Status)) {
924  ERR("add_calc_job_comp returned %08lx\n", Status);
925 
926  for (unsigned int j = 0; j < i; j++) {
928  ExFreePool(parts[j].cj);
929  }
930 
931  ExFreePool(parts);
932  return Status;
933  }
934  }
935 
937 
938  for (int i = num_parts - 1; i >= 0; i--) {
939  calc_thread_main(fcb->Vcb, parts[i].cj);
940 
942 
943  if (!NT_SUCCESS(parts[i].cj->Status))
944  Status = parts[i].cj->Status;
945  }
946 
947  if (!NT_SUCCESS(Status)) {
948  ERR("calc job returned %08lx\n", Status);
949 
950  for (unsigned int i = 0; i < num_parts; i++) {
951  ExFreePool(parts[i].cj);
952  }
953 
954  ExFreePool(parts);
955  return Status;
956  }
957 
958  for (unsigned int i = 0; i < num_parts; i++) {
959  if (parts[i].cj->space_left >= fcb->Vcb->superblock.sector_size) {
960  parts[i].compression_type = type;
961  parts[i].outlen = parts[i].inlen - parts[i].cj->space_left;
962 
964  fcb->Vcb->superblock.incompat_flags |= BTRFS_INCOMPAT_FLAGS_COMPRESS_LZO;
965  else if (type == BTRFS_COMPRESSION_ZSTD)
966  fcb->Vcb->superblock.incompat_flags |= BTRFS_INCOMPAT_FLAGS_COMPRESS_ZSTD;
967 
968  if ((parts[i].outlen & (fcb->Vcb->superblock.sector_size - 1)) != 0) {
969  unsigned int newlen = (unsigned int)sector_align(parts[i].outlen, fcb->Vcb->superblock.sector_size);
970 
971  RtlZeroMemory(parts[i].buf + parts[i].outlen, newlen - parts[i].outlen);
972 
973  parts[i].outlen = newlen;
974  }
975  } else {
976  parts[i].compression_type = BTRFS_COMPRESSION_NONE;
977  parts[i].outlen = (unsigned int)sector_align(parts[i].inlen, fcb->Vcb->superblock.sector_size);
978  }
979 
980  buflen += parts[i].outlen;
981  ExFreePool(parts[i].cj);
982  }
983 
984  // check if first 128 KB of file is incompressible
985 
986  if (start_data == 0 && parts[0].compression_type == BTRFS_COMPRESSION_NONE && !fcb->Vcb->options.compress_force) {
987  TRACE("adding nocompress flag to subvol %I64x, inode %I64x\n", fcb->subvol->id, fcb->inode);
988 
990  fcb->inode_item_changed = true;
992  }
993 
994  // join together into continuous buffer
995 
997  if (!buf) {
998  ERR("out of memory\n");
999  ExFreePool(parts);
1001  }
1002 
1003  {
1004  uint8_t* buf2 = buf;
1005 
1006  for (i = 0; i < num_parts; i++) {
1007  if (parts[i].compression_type == BTRFS_COMPRESSION_NONE)
1008  RtlCopyMemory(buf2, (uint8_t*)data + (i * COMPRESSED_EXTENT_SIZE), parts[i].outlen);
1009  else
1010  RtlCopyMemory(buf2, parts[i].buf, parts[i].outlen);
1011 
1012  buf2 += parts[i].outlen;
1013  }
1014  }
1015 
1016  // find an address
1017 
1018  ExAcquireResourceSharedLite(&fcb->Vcb->chunk_lock, true);
1019 
1020  le = fcb->Vcb->chunks.Flink;
1021  while (le != &fcb->Vcb->chunks) {
1023 
1024  if (!c2->readonly && !c2->reloc) {
1025  acquire_chunk_lock(c2, fcb->Vcb);
1026 
1027  if (c2->chunk_item->type == fcb->Vcb->data_flags && (c2->chunk_item->size - c2->used) >= buflen) {
1028  if (find_data_address_in_chunk(fcb->Vcb, c2, buflen, &address)) {
1029  c = c2;
1030  c->used += buflen;
1032  release_chunk_lock(c2, fcb->Vcb);
1033  break;
1034  }
1035  }
1036 
1037  release_chunk_lock(c2, fcb->Vcb);
1038  }
1039 
1040  le = le->Flink;
1041  }
1042 
1043  ExReleaseResourceLite(&fcb->Vcb->chunk_lock);
1044 
1045  if (!c) {
1046  chunk* c2;
1047 
1048  ExAcquireResourceExclusiveLite(&fcb->Vcb->chunk_lock, true);
1049 
1050  Status = alloc_chunk(fcb->Vcb, fcb->Vcb->data_flags, &c2, false);
1051 
1052  ExReleaseResourceLite(&fcb->Vcb->chunk_lock);
1053 
1054  if (!NT_SUCCESS(Status)) {
1055  ERR("alloc_chunk returned %08lx\n", Status);
1056  ExFreePool(buf);
1057  ExFreePool(parts);
1058  return Status;
1059  }
1060 
1061  acquire_chunk_lock(c2, fcb->Vcb);
1062 
1063  if (find_data_address_in_chunk(fcb->Vcb, c2, buflen, &address)) {
1064  c = c2;
1065  c->used += buflen;
1067  }
1068 
1069  release_chunk_lock(c2, fcb->Vcb);
1070  }
1071 
1072  if (!c) {
1073  WARN("couldn't find any data chunks with %x bytes free\n", buflen);
1074  ExFreePool(buf);
1075  ExFreePool(parts);
1076  return STATUS_DISK_FULL;
1077  }
1078 
1079  // write to disk
1080 
1081  TRACE("writing %x bytes to %I64x\n", buflen, address);
1082 
1083  Status = write_data_complete(fcb->Vcb, address, buf, buflen, Irp, NULL, false, 0,
1085  if (!NT_SUCCESS(Status)) {
1086  ERR("write_data_complete returned %08lx\n", Status);
1087  ExFreePool(buf);
1088  ExFreePool(parts);
1089  return Status;
1090  }
1091 
1092  // FIXME - do rest of the function while we're waiting for I/O to finish?
1093 
1094  // calculate csums if necessary
1095 
1097  unsigned int sl = buflen >> fcb->Vcb->sector_shift;
1098 
1099  csum = ExAllocatePoolWithTag(PagedPool, sl * fcb->Vcb->csum_size, ALLOC_TAG);
1100  if (!csum) {
1101  ERR("out of memory\n");
1102  ExFreePool(buf);
1103  ExFreePool(parts);
1105  }
1106 
1107  do_calc_job(fcb->Vcb, buf, sl, csum);
1108  }
1109 
1110  ExFreePool(buf);
1111 
1112  // add extents to fcb
1113 
1114  extaddr = address;
1115 
1116  for (i = 0; i < num_parts; i++) {
1117  EXTENT_DATA* ed;
1118  EXTENT_DATA2* ed2;
1119  void* csum2;
1120 
1122  if (!ed) {
1123  ERR("out of memory\n");
1124  ExFreePool(parts);
1125 
1126  if (csum)
1127  ExFreePool(csum);
1128 
1130  }
1131 
1132  ed->generation = fcb->Vcb->superblock.generation;
1133  ed->decoded_size = parts[i].inlen;
1134  ed->compression = parts[i].compression_type;
1137  ed->type = EXTENT_TYPE_REGULAR;
1138 
1139  ed2 = (EXTENT_DATA2*)ed->data;
1140  ed2->address = extaddr;
1141  ed2->size = parts[i].outlen;
1142  ed2->offset = 0;
1143  ed2->num_bytes = parts[i].inlen;
1144 
1145  if (csum) {
1146  csum2 = ExAllocatePoolWithTag(PagedPool, (parts[i].outlen * fcb->Vcb->csum_size) >> fcb->Vcb->sector_shift, ALLOC_TAG);
1147  if (!csum2) {
1148  ERR("out of memory\n");
1149  ExFreePool(ed);
1150  ExFreePool(parts);
1151  ExFreePool(csum);
1153  }
1154 
1155  RtlCopyMemory(csum2, (uint8_t*)csum + (((extaddr - address) * fcb->Vcb->csum_size) >> fcb->Vcb->sector_shift),
1156  (parts[i].outlen * fcb->Vcb->csum_size) >> fcb->Vcb->sector_shift);
1157  } else
1158  csum2 = NULL;
1159 
1161  true, csum2, rollback);
1162  if (!NT_SUCCESS(Status)) {
1163  ERR("add_extent_to_fcb returned %08lx\n", Status);
1164  ExFreePool(ed);
1165  ExFreePool(parts);
1166 
1167  if (csum)
1168  ExFreePool(csum);
1169 
1170  return Status;
1171  }
1172 
1173  ExFreePool(ed);
1174 
1175  fcb->inode_item.st_blocks += parts[i].inlen;
1176 
1177  extaddr += parts[i].outlen;
1178  }
1179 
1180  if (csum)
1181  ExFreePool(csum);
1182 
1183  // update extent refcounts
1184 
1185  ExAcquireResourceExclusiveLite(&c->changed_extents_lock, true);
1186 
1187  extaddr = address;
1188 
1189  for (i = 0; i < num_parts; i++) {
1190  add_changed_extent_ref(c, extaddr, parts[i].outlen, fcb->subvol->id, fcb->inode,
1192 
1193  extaddr += parts[i].outlen;
1194  }
1195 
1196  ExReleaseResourceLite(&c->changed_extents_lock);
1197 
1198  fcb->extents_changed = true;
1199  fcb->inode_item_changed = true;
1201 
1202  ExFreePool(parts);
1203 
1204  return STATUS_SUCCESS;
1205 }
uint64_t generation
Definition: btrfs.h:358
ZSTDLIB_API const char * ZSTD_getErrorName(size_t code)
Definition: zstd_common.c:41
size_t size
Definition: zstd.h:574
GLint level
Definition: gl.h:1546
#define deflateInit(strm, level)
Definition: zlib.h:1810
uint8_t type
Definition: btrfs.h:363
static HANDLE PIO_APC_ROUTINE PVOID PIO_STATUS_BLOCK ULONG PVOID ULONG PVOID ULONG out_size
Definition: file.c:100
_In_ ULONG cj
Definition: winddi.h:3540
#define STATUS_INSUFFICIENT_RESOURCES
Definition: udferr_usr.h:158
NTSTATUS zlib_decompress(uint8_t *inbuf, uint32_t inlen, uint8_t *outbuf, uint32_t outlen)
Definition: compress.c:377
#define M4_MAX_OFFSET
Definition: compress.c:64
static NTSTATUS lzo1x_1_compress(lzo_stream *stream)
Definition: compress.c:631
uint32_t inpos
Definition: compress.c:51
void FAR * voidpf
Definition: zlib.h:42
#define BTRFS_COMPRESSION_NONE
Definition: btrfs.h:65
NTSTATUS write_compressed(fcb *fcb, uint64_t start_data, uint64_t end_data, void *data, PIRP Irp, LIST_ENTRY *rollback)
Definition: compress.c:875
static void lzo_copy(lzo_stream *stream, int len)
Definition: compress.c:133
static void zlib_free(void *opaque, void *ptr)
Definition: compress.c:330
#define M3_MARKER
Definition: compress.c:70
NTSTATUS lzo_decompress(uint8_t *inbuf, uint32_t inlen, uint8_t *outbuf, uint32_t outlen, uint32_t inpageoff)
Definition: compress.c:278
static const D3D_BLOB_PART parts[]
Definition: blob.c:76
#define Z_OK
Definition: zlib.h:114
uint64_t decoded_size
Definition: btrfs.h:359
#define LZO_CHECK_MPOS_NON_DET(m_pos, m_off, in, ip, max_offset)
Definition: compress.c:82
#define FSRTL_FLAG2_IS_PAGING_FILE
Definition: fsrtltypes.h:57
#define WARN(fmt,...)
Definition: debug.h:112
LONG NTSTATUS
Definition: precomp.h:26
uInt avail_in
Definition: zlib.h:60
enum prop_compression_type prop_compression
Definition: btrfs_drv.h:307
static int inbuf
Definition: adnsresfilter.c:73
ZSTDLIB_API size_t ZSTD_compressStream(ZSTD_CStream *zcs, ZSTD_outBuffer *output, ZSTD_inBuffer *input)
GLdouble GLdouble t
Definition: gl.h:2047
static void * zlib_alloc(void *opaque, unsigned int items, unsigned int size)
Definition: compress.c:324
uint64_t used
Definition: btrfs_drv.h:565
#define M2_MAX_OFFSET
Definition: compress.c:62
void add_changed_extent_ref(chunk *c, uint64_t address, uint64_t size, uint64_t root, uint64_t objid, uint64_t offset, uint32_t count, bool no_csum)
Definition: extent-tree.c:2076
NTSTATUS zstd_decompress(uint8_t *inbuf, uint32_t inlen, uint8_t *outbuf, uint32_t outlen)
Definition: compress.c:676
uint32_t outlen
Definition: compress.c:53
#define BTRFS_COMPRESSION_LZO
Definition: btrfs.h:67
#define BTRFS_COMPRESSION_ZSTD
Definition: btrfs.h:68
ZSTD_customMem zstd_mem
Definition: compress.c:98
bool readonly
Definition: btrfs_drv.h:580
uint32_t flags
Definition: btrfs.h:297
if(dx==0 &&dy==0)
Definition: linetemp.h:174
NTSTATUS lzo_compress(uint8_t *inbuf, uint32_t inlen, uint8_t *outbuf, uint32_t outlen, unsigned int *space_left)
Definition: compress.c:727
NTSTATUS NTAPI KeWaitForSingleObject(IN PVOID Object, IN KWAIT_REASON WaitReason, IN KPROCESSOR_MODE WaitMode, IN BOOLEAN Alertable, IN PLARGE_INTEGER Timeout OPTIONAL)
Definition: wait.c:416
#define LZO_BYTE(x)
Definition: compress.c:87
uint8_t encryption
Definition: btrfs.h:361
#define BTRFS_COMPRESSION_ZLIB
Definition: btrfs.h:66
#define COMPRESSED_EXTENT_SIZE
Definition: btrfs_drv.h:112
_In_ fcb _In_ chunk _In_ uint64_t start_data
Definition: btrfs_drv.h:1364
BOOLEAN NTAPI ExAcquireResourceExclusiveLite(IN PERESOURCE Resource, IN BOOLEAN Wait)
Definition: resource.c:770
#define STATUS_INTERNAL_ERROR
Definition: ntstatus.h:465
#define BTRFS_INCOMPAT_FLAGS_COMPRESS_LZO
Definition: btrfs.h:118
#define ALLOC_TAG
Definition: btrfs_drv.h:87
GLenum GLuint GLenum GLsizei const GLchar * buf
Definition: glext.h:7751
uint64_t size
Definition: btrfs.h:340
#define ZSTD_isError
Definition: zstd_internal.h:46
voidpf opaque
Definition: zlib.h:72
void do_calc_job(device_extension *Vcb, uint8_t *data, uint32_t sectors, void *csum)
Definition: calcthread.c:141
free_func zfree
Definition: zlib.h:71
GLenum GLint GLuint mask
Definition: glext.h:6028
#define Z_STREAM_END
Definition: zlib.h:115
GLenum const GLfloat * params
Definition: glext.h:5645
_In_ PIRP Irp
Definition: csq.h:116
uint64_t address
Definition: btrfs.h:368
static void lzo_copyback(lzo_stream *stream, uint32_t back, int len)
Definition: compress.c:152
ZSTDLIB_API size_t ZSTD_freeDStream(ZSTD_DStream *zds)
ZSTDLIB_API size_t ZSTD_decompressStream(ZSTD_DStream *zds, ZSTD_outBuffer *output, ZSTD_inBuffer *input)
calc_job * cj
Definition: compress.c:872
bool extents_changed
Definition: btrfs_drv.h:323
size_t ZSTD_initCStream_advanced(ZSTD_CStream *zcs, const void *dict, size_t dictSize, ZSTD_parameters params, unsigned long long pss)
int ip[4]
Definition: rtl.c:1176
static PVOID ptr
Definition: dispmode.c:27
uint8_t * in
Definition: compress.c:49
ZSTD_DStream * ZSTD_createDStream_advanced(ZSTD_customMem customMem)
#define BTRFS_ENCODING_NONE
Definition: btrfs.h:72
NTSTATUS zstd_compress(uint8_t *inbuf, uint32_t inlen, uint8_t *outbuf, uint32_t outlen, uint32_t level, unsigned int *space_left)
Definition: compress.c:805
#define offsetof(TYPE, MEMBER)
uint32_t inlen
Definition: compress.c:50
static uint8_t lzo_nextbyte(lzo_stream *stream)
Definition: compress.c:103
#define ZSTD_ALLOC_TAG
Definition: compress.c:89
void mark_fcb_dirty(_In_ fcb *fcb)
Definition: btrfs.c:1695
#define release_chunk_lock(c, Vcb)
Definition: btrfs_drv.h:1140
int deflateEnd(z_streamp strm) DECLSPEC_HIDDEN
Definition: deflate.c:1119
uint64_t size
Definition: btrfs.h:369
bool reloc
Definition: btrfs_drv.h:581
#define UNUSED(x)
Definition: btrfs_drv.h:82
struct match match
Definition: match.c:33
z_const Bytef * next_in
Definition: zlib.h:59
NTSTATUS alloc_chunk(device_extension *Vcb, uint64_t flags, chunk **pc, bool full_size) __attribute__((nonnull(1
PFLT_MESSAGE_WAITER_QUEUE CONTAINING_RECORD(Csq, DEVICE_EXTENSION, IrpQueue)) -> WaiterQ.mLock) _IRQL_raises_(DISPATCH_LEVEL) VOID NTAPI FltpAcquireMessageWaiterLock(_In_ PIO_CSQ Csq, _Out_ PKIRQL Irql)
Definition: Messaging.c:560
GLsizei GLenum const GLvoid GLsizei GLenum GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLint GLint GLint GLshort GLshort GLshort GLubyte GLubyte GLubyte GLuint GLuint GLuint GLushort GLushort GLushort GLbyte GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLfloat GLint GLint GLint GLint GLshort GLshort GLshort GLshort GLubyte GLubyte GLubyte GLubyte GLuint GLuint GLuint GLuint GLushort GLushort GLushort GLushort GLboolean const GLdouble const GLfloat const GLint const GLshort const GLbyte const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLdouble const GLfloat const GLfloat const GLint const GLint const GLshort const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort GLenum GLenum GLenum GLfloat GLenum GLint GLenum GLenum GLenum GLfloat GLenum GLenum GLint GLenum GLfloat GLenum GLint GLint GLushort GLenum GLenum GLfloat GLenum GLenum GLint GLfloat const GLubyte GLenum GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLint GLint GLsizei GLsizei GLint GLenum GLenum const GLvoid GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLenum const GLdouble GLenum GLenum const GLfloat GLenum GLenum const GLint GLsizei GLuint GLfloat GLuint GLbitfield GLfloat GLint GLuint GLboolean GLenum GLfloat GLenum GLbitfield GLenum GLfloat GLfloat GLint GLint const GLfloat GLenum GLfloat GLfloat GLint GLint GLfloat GLfloat GLint GLint const GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat const GLdouble const GLfloat const GLdouble const GLfloat GLint GLint GLint j
Definition: glfuncs.h:250
void calc_thread_main(device_extension *Vcb, calc_job *cj)
Definition: calcthread.c:22
FSRTL_ADVANCED_FCB_HEADER Header
Definition: btrfs_drv.h:283
Status
Definition: gdiplustypes.h:24
struct _LIST_ENTRY * Flink
Definition: typedefs.h:121
uint16_t encoding
Definition: btrfs.h:362
#define BTRFS_ENCRYPTION_NONE
Definition: btrfs.h:70
#define TRACE(s)
Definition: solgame.cpp:4
GLsizeiptr size
Definition: glext.h:5919
#define DVAL_FIRST(dv, p)
Definition: compress.c:76
Definition: dhcpd.h:61
#define NT_SUCCESS(StatCode)
Definition: apphelp.c:32
uint64_t inode
Definition: btrfs_drv.h:289
#define BTRFS_INODE_NODATASUM
Definition: propsheet.h:76
ZSTDLIB_API size_t ZSTD_freeCStream(ZSTD_CStream *zcs)
static NTSTATUS do_lzo_decompress(lzo_stream *stream)
Definition: compress.c:170
const GLubyte * c
Definition: glext.h:8905
alloc_func zalloc
Definition: zlib.h:70
static FILE * out
Definition: regtests2xml.c:44
GLuint address
Definition: glext.h:9393
UINT op
Definition: effect.c:236
bool error
Definition: compress.c:55
int deflate(z_streamp strm, int flush) DECLSPEC_HIDDEN
Definition: deflate.c:804
VOID FASTCALL ExReleaseResourceLite(IN PERESOURCE Resource)
Definition: resource.c:1817
static int lzo_len(lzo_stream *stream, int byte, int mask)
Definition: compress.c:117
GLint GLenum GLsizei GLsizei GLsizei GLint GLsizei const GLvoid * data
Definition: gl.h:1950
#define LZO1X_MEM_COMPRESS
Definition: compress.c:59
GLuint GLuint end
Definition: gl.h:1545
#define ZSTD_BTRFS_MAX_WINDOWLOG
Definition: compress.c:92
#define ExAllocatePoolWithTag(hernya, size, tag)
Definition: env_spec_w32.h:350
int ret
NTSTATUS bool void NTSTATUS add_extent_to_fcb(_In_ fcb *fcb, _In_ uint64_t offset, _In_reads_bytes_(edsize) EXTENT_DATA *ed, _In_ uint16_t edsize, _In_ bool unique, _In_opt_ _When_(return >=0, __drv_aliasesMem) void *csum, _In_ LIST_ENTRY *rollback) __attribute__((nonnull(1
int inflateEnd(z_streamp strm)
Definition: inflate.c:1910
Definition: parse.h:22
GLuint GLuint stream
Definition: glext.h:7522
static __inline uint32_t lzo_max_outlen(uint32_t inlen)
Definition: compress.c:660
unsigned int inlen
Definition: compress.c:870
GLenum GLsizei len
Definition: glext.h:6722
uint32_t outpos
Definition: compress.c:54
Definition: typedefs.h:119
INODE_ITEM inode_item
Definition: btrfs_drv.h:292
BYTE uint8_t
Definition: msvideo1.c:66
uint64_t num_bytes
Definition: btrfs.h:371
uint64_t st_blocks
Definition: btrfs.h:290
NTSTATUS NTSTATUS NTSTATUS write_data_complete(device_extension *Vcb, uint64_t address, void *data, uint32_t length, PIRP Irp, chunk *c, bool file_write, uint64_t irp_offset, ULONG priority) __attribute__((nonnull(1
#define EXTENT_TYPE_REGULAR
Definition: btrfs.h:75
#define ALLOC_TAG_ZLIB
Definition: btrfs_drv.h:88
size_t pos
Definition: zstd.h:575
#define ERR(fmt,...)
Definition: debug.h:110
uint8_t data[1]
Definition: btrfs.h:364
#define Z_FINISH
Definition: zlib.h:109
NTSTATUS NTSTATUS NTSTATUS NTSTATUS NTSTATUS excise_extents(device_extension *Vcb, fcb *fcb, uint64_t start_data, uint64_t end_data, PIRP Irp, LIST_ENTRY *rollback) __attribute__((nonnull(1
static void zstd_free(void *opaque, void *address)
Definition: compress.c:670
#define DVAL_NEXT(dv, p)
Definition: compress.c:74
#define UPDATE_I(dict, cycle, index, p)
Definition: compress.c:80
UINT64 uint64_t
Definition: types.h:77
GLenum GLenum GLenum input
Definition: glext.h:9031
void space_list_subtract(chunk *c, uint64_t address, uint64_t length, LIST_ENTRY *rollback)
Definition: free-space.c:2234
#define M3_MAX_OFFSET
Definition: compress.c:63
GLsizei GLenum const GLvoid GLsizei GLenum GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLint GLint GLint GLshort GLshort GLshort GLubyte GLubyte GLubyte GLuint GLuint GLuint GLushort GLushort GLushort GLbyte GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLfloat GLint GLint GLint GLint GLshort GLshort GLshort GLshort GLubyte GLubyte GLubyte GLubyte GLuint GLuint GLuint GLuint GLushort GLushort GLushort GLushort GLboolean const GLdouble const GLfloat const GLint const GLshort const GLbyte const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLdouble const GLfloat const GLfloat const GLint const GLint const GLshort const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort GLenum GLenum GLenum GLfloat GLenum GLint GLenum GLenum GLenum GLfloat GLenum GLenum GLint GLenum GLfloat GLenum GLint GLint GLushort GLenum GLenum GLfloat GLenum GLenum GLint GLfloat const GLubyte GLenum GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLint GLint GLsizei GLsizei GLint GLenum GLenum const GLvoid GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLenum const GLdouble GLenum GLenum const GLfloat GLenum GLenum const GLint GLsizei GLuint GLfloat GLuint GLbitfield GLfloat GLint GLuint GLboolean GLenum GLfloat GLenum GLbitfield GLenum GLfloat GLfloat GLint GLint const GLfloat GLenum GLfloat GLfloat GLint GLint GLfloat GLfloat GLint GLint const GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat const GLdouble const GLfloat const GLdouble const GLfloat GLint i
Definition: glfuncs.h:248
GLuint in
Definition: glext.h:9616
uint8_t * out
Definition: compress.c:52
#define acquire_chunk_lock(c, Vcb)
Definition: btrfs_drv.h:1139
#define byte(x, n)
Definition: tomcrypt.h:118
#define DINDEX(dv, p)
Definition: compress.c:78
static NTSTATUS lzo_do_compress(const uint8_t *in, uint32_t in_len, uint8_t *out, uint32_t *out_len, void *wrkmem)
Definition: compress.c:423
void * dst
Definition: zstd.h:573
NTSTATUS zlib_compress(uint8_t *inbuf, uint32_t inlen, uint8_t *outbuf, uint32_t outlen, unsigned int level, unsigned int *space_left)
Definition: compress.c:336
void * wrkmem
Definition: compress.c:56
struct _root * subvol
Definition: btrfs_drv.h:288
#define min(a, b)
Definition: monoChain.cc:55
Definition: list.h:27
#define NULL
Definition: types.h:112
__kernel_ptrdiff_t ptrdiff_t
Definition: linux.h:247
_In_ fcb _In_ chunk _In_ uint64_t _In_ uint64_t _In_ bool _In_opt_ void _In_opt_ PIRP _In_ LIST_ENTRY * rollback
Definition: btrfs_drv.h:1364
uInt avail_out
Definition: zlib.h:64
UINT32 uint32_t
Definition: types.h:75
BOOLEAN NTAPI ExAcquireResourceSharedLite(IN PERESOURCE Resource, IN BOOLEAN Wait)
Definition: resource.c:885
CHUNK_ITEM * chunk_item
Definition: btrfs_drv.h:562
Definition: ffs.h:52
#define STATUS_DISK_FULL
Definition: udferr_usr.h:155
#define Z_NO_FLUSH
Definition: zlib.h:105
#define c
Definition: ke_i.h:80
unsigned int outlen
Definition: compress.c:871
#define RtlZeroMemory(Destination, Length)
Definition: typedefs.h:262
ZSTD_CStream * ZSTD_createCStream_advanced(ZSTD_customMem customMem)
ZSTD_parameters ZSTD_getParams(int compressionLevel, unsigned long long srcSizeHint, size_t dictSize)
#define RtlCopyMemory(Destination, Source, Length)
Definition: typedefs.h:263
uint64_t offset
Definition: btrfs.h:370
int inflate(z_streamp strm, int flush)
Definition: inflate.c:1257
#define STATUS_SUCCESS
Definition: shellext.h:65
GLuint GLuint GLsizei GLenum type
Definition: gl.h:1545
#define LZO_PAGE_SIZE
Definition: compress.c:46
#define inflateInit(strm)
Definition: zlib.h:1812
uint8_t compression_type
Definition: compress.c:869
Bytef * next_out
Definition: zlib.h:63
uint64_t type
Definition: btrfs.h:343
#define uint32_t
Definition: nsiface.idl:61
static TCHAR * items[]
Definition: page1.c:45
bool inode_item_changed
Definition: btrfs_drv.h:306
static uint64_t __inline sector_align(uint64_t n, uint64_t a)
#define BTRFS_INODE_NOCOMPRESS
Definition: propsheet.h:79
#define BTRFS_INCOMPAT_FLAGS_COMPRESS_ZSTD
Definition: btrfs.h:119
NTSTATUS add_calc_job_comp(device_extension *Vcb, uint8_t compression, void *in, unsigned int inlen, void *out, unsigned int outlen, calc_job **pcj)
Definition: calcthread.c:237
struct _device_extension * Vcb
Definition: btrfs_drv.h:287
NTSTATUS bool find_data_address_in_chunk(device_extension *Vcb, chunk *c, uint64_t length, uint64_t *address) __attribute__((nonnull(1
#define ExFreePool(addr)
Definition: env_spec_w32.h:352
#define M4_MARKER
Definition: compress.c:71
static void * zstd_malloc(void *opaque, size_t size)
Definition: compress.c:664
_CRTIMP int __cdecl read(_In_ int _FileHandle, _Out_writes_bytes_(_MaxCharCount) void *_DstBuf, _In_ unsigned int _MaxCharCount)
uint8_t compression
Definition: btrfs.h:360
ZSTDLIB_API size_t ZSTD_endStream(ZSTD_CStream *zcs, ZSTD_outBuffer *output)
ZSTDLIB_API size_t ZSTD_initDStream(ZSTD_DStream *zds)
#define UPDATE_D(dict, cycle, dv, p)
Definition: compress.c:79
unsigned int(__cdecl typeof(jpeg_read_scanlines))(struct jpeg_decompress_struct *
Definition: typeof.h:31