ReactOS  0.4.15-dev-309-g7c8d563
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;
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 
707 
708  if (ZSTD_isError(read)) {
709  ERR("ZSTD_decompressStream failed: %s\n", ZSTD_getErrorName(read));
711  goto end;
712  }
713 
715 
716 end:
718 
719  return Status;
720 }
721 
722 NTSTATUS lzo_compress(uint8_t* inbuf, uint32_t inlen, uint8_t* outbuf, uint32_t outlen, unsigned int* space_left) {
724  unsigned int num_pages;
725  unsigned int comp_data_len;
726  uint8_t* comp_data;
729 #ifdef __REACTOS__
730  unsigned int i;
731 #endif // __REACTOS__
732 
733  num_pages = (unsigned int)sector_align(inlen, LZO_PAGE_SIZE) / LZO_PAGE_SIZE;
734 
735  // Four-byte overall header
736  // Another four-byte header page
737  // Each page has a maximum size of lzo_max_outlen(LZO_PAGE_SIZE)
738  // Plus another four bytes for possible padding
739  comp_data_len = sizeof(uint32_t) + ((lzo_max_outlen(LZO_PAGE_SIZE) + (2 * sizeof(uint32_t))) * num_pages);
740 
741  // FIXME - can we write this so comp_data isn't necessary?
742 
743  comp_data = ExAllocatePoolWithTag(PagedPool, comp_data_len, ALLOC_TAG);
744  if (!comp_data) {
745  ERR("out of memory\n");
747  }
748 
750  if (!stream.wrkmem) {
751  ERR("out of memory\n");
752  ExFreePool(comp_data);
754  }
755 
756  out_size = (uint32_t*)comp_data;
757  *out_size = sizeof(uint32_t);
758 
759  stream.in = inbuf;
760  stream.out = comp_data + (2 * sizeof(uint32_t));
761 
762 #ifndef __REACTOS__
763  for (unsigned int i = 0; i < num_pages; i++) {
764 #else
765  for (i = 0; i < num_pages; i++) {
766 #endif // __REACTOS__
767  uint32_t* pagelen = (uint32_t*)(stream.out - sizeof(uint32_t));
768 
769  stream.inlen = (uint32_t)min(LZO_PAGE_SIZE, outlen - (i * LZO_PAGE_SIZE));
770 
772  if (!NT_SUCCESS(Status)) {
773  ERR("lzo1x_1_compress returned %08lx\n", Status);
774  ExFreePool(comp_data);
775  return Status;
776  }
777 
778  *pagelen = stream.outlen;
779  *out_size += stream.outlen + sizeof(uint32_t);
780 
781  stream.in += LZO_PAGE_SIZE;
782  stream.out += stream.outlen + sizeof(uint32_t);
783 
784  // new page needs to start at a 32-bit boundary
785  if (LZO_PAGE_SIZE - (*out_size % LZO_PAGE_SIZE) < sizeof(uint32_t)) {
789  }
790  }
791 
792  ExFreePool(stream.wrkmem);
793 
794  if (*out_size >= outlen)
795  *space_left = 0;
796  else {
797  *space_left = outlen - *out_size;
798 
799  RtlCopyMemory(outbuf, comp_data, *out_size);
800  }
801 
802  ExFreePool(comp_data);
803 
804  return STATUS_SUCCESS;
805 }
806 
807 NTSTATUS zstd_compress(uint8_t* inbuf, uint32_t inlen, uint8_t* outbuf, uint32_t outlen, uint32_t level, unsigned int* space_left) {
809  size_t init_res, written;
812  ZSTD_parameters params;
813 
815 
816  if (!stream) {
817  ERR("ZSTD_createCStream failed.\n");
818  return STATUS_INTERNAL_ERROR;
819  }
820 
821  params = ZSTD_getParams(level, inlen, 0);
822 
823  if (params.cParams.windowLog > ZSTD_BTRFS_MAX_WINDOWLOG)
824  params.cParams.windowLog = ZSTD_BTRFS_MAX_WINDOWLOG;
825 
826  init_res = ZSTD_initCStream_advanced(stream, NULL, 0, params, inlen);
827 
828  if (ZSTD_isError(init_res)) {
829  ERR("ZSTD_initCStream_advanced failed: %s\n", ZSTD_getErrorName(init_res));
831  return STATUS_INTERNAL_ERROR;
832  }
833 
834  input.src = inbuf;
835  input.size = inlen;
836  input.pos = 0;
837 
838  output.dst = outbuf;
839  output.size = outlen;
840  output.pos = 0;
841 
842  while (input.pos < input.size && output.pos < output.size) {
843  written = ZSTD_compressStream(stream, &output, &input);
844 
845  if (ZSTD_isError(written)) {
846  ERR("ZSTD_compressStream failed: %s\n", ZSTD_getErrorName(written));
848  return STATUS_INTERNAL_ERROR;
849  }
850  }
851 
852  written = ZSTD_endStream(stream, &output);
853  if (ZSTD_isError(written)) {
854  ERR("ZSTD_endStream failed: %s\n", ZSTD_getErrorName(written));
856  return STATUS_INTERNAL_ERROR;
857  }
858 
860 
861  if (input.pos < input.size) // output would be larger than input
862  *space_left = 0;
863  else
864  *space_left = output.size - output.pos;
865 
866  return STATUS_SUCCESS;
867 }
868 
869 typedef struct {
872  unsigned int inlen;
873  unsigned int outlen;
875 } comp_part;
876 
879  uint64_t i;
880  unsigned int num_parts = (unsigned int)sector_align(end_data - start_data, COMPRESSED_EXTENT_SIZE) / COMPRESSED_EXTENT_SIZE;
881  uint8_t type;
882  comp_part* parts;
883  unsigned int buflen = 0;
884  uint8_t* buf;
885  chunk* c = NULL;
886  LIST_ENTRY* le;
887  uint64_t address, extaddr;
888  void* csum = NULL;
889 #ifdef __REACTOS__
890  int32_t i2;
891  uint32_t i3, j;
892 #endif // __REACTOS__
893 
894  if (fcb->Vcb->options.compress_type != 0 && fcb->prop_compression == PropCompression_None)
895  type = fcb->Vcb->options.compress_type;
896  else {
897  if (!(fcb->Vcb->superblock.incompat_flags & BTRFS_INCOMPAT_FLAGS_COMPRESS_ZSTD) && fcb->prop_compression == PropCompression_ZSTD)
901  else if (!(fcb->Vcb->superblock.incompat_flags & BTRFS_INCOMPAT_FLAGS_COMPRESS_LZO) && fcb->prop_compression == PropCompression_LZO)
903  else if (fcb->Vcb->superblock.incompat_flags & BTRFS_INCOMPAT_FLAGS_COMPRESS_LZO && fcb->prop_compression != PropCompression_Zlib)
905  else
907  }
908 
910  if (!NT_SUCCESS(Status)) {
911  ERR("excise_extents returned %08lx\n", Status);
912  return Status;
913  }
914 
915  parts = ExAllocatePoolWithTag(PagedPool, sizeof(comp_part) * num_parts, ALLOC_TAG);
916  if (!parts) {
917  ERR("out of memory\n");
919  }
920 
921  for (i = 0; i < num_parts; i++) {
922  if (i == num_parts - 1)
923  parts[i].inlen = ((unsigned int)(end_data - start_data) - ((num_parts - 1) * COMPRESSED_EXTENT_SIZE));
924  else
925  parts[i].inlen = COMPRESSED_EXTENT_SIZE;
926 
928  parts[i].buf, parts[i].inlen, &parts[i].cj);
929  if (!NT_SUCCESS(Status)) {
930  ERR("add_calc_job_comp returned %08lx\n", Status);
931 
932 #ifndef __REACTOS__
933  for (unsigned int j = 0; j < i; j++) {
934 #else
935  for (j = 0; j < i; j++) {
936 #endif // __REACTOS__
938  ExFreePool(parts[j].cj);
939  }
940 
941  ExFreePool(parts);
942  return Status;
943  }
944  }
945 
947 
948 #ifndef __REACTOS__
949  for (int i = num_parts - 1; i >= 0; i--) {
950  calc_thread_main(fcb->Vcb, parts[i].cj);
951 
953 
954  if (!NT_SUCCESS(parts[i].cj->Status))
955  Status = parts[i].cj->Status;
956  }
957 #else
958  for (i2 = num_parts - 1; i2 >= 0; i2--) {
959  calc_thread_main(fcb->Vcb, parts[i].cj);
960 
961  KeWaitForSingleObject(&parts[i2].cj->event, Executive, KernelMode, false, NULL);
962 
963  if (!NT_SUCCESS(parts[i2].cj->Status))
964  Status = parts[i2].cj->Status;
965  }
966 #endif // __REACTOS__
967 
968  if (!NT_SUCCESS(Status)) {
969  ERR("calc job returned %08lx\n", Status);
970 
971 #ifndef __REACTOS__
972  for (unsigned int i = 0; i < num_parts; i++) {
973  ExFreePool(parts[i].cj);
974  }
975 #else
976  for (i3 = 0; i3 < num_parts; i3++) {
977  ExFreePool(parts[i3].cj);
978  }
979 #endif // __REACTOS__
980 
981  ExFreePool(parts);
982  return Status;
983  }
984 
985 #ifndef __REACTOS__
986  for (unsigned int i = 0; i < num_parts; i++) {
987  if (parts[i].cj->space_left >= fcb->Vcb->superblock.sector_size) {
988  parts[i].compression_type = type;
989  parts[i].outlen = parts[i].inlen - parts[i].cj->space_left;
990 
992  fcb->Vcb->superblock.incompat_flags |= BTRFS_INCOMPAT_FLAGS_COMPRESS_LZO;
993  else if (type == BTRFS_COMPRESSION_ZSTD)
994  fcb->Vcb->superblock.incompat_flags |= BTRFS_INCOMPAT_FLAGS_COMPRESS_ZSTD;
995 
996  if ((parts[i].outlen % fcb->Vcb->superblock.sector_size) != 0) {
997  unsigned int newlen = (unsigned int)sector_align(parts[i].outlen, fcb->Vcb->superblock.sector_size);
998 
999  RtlZeroMemory(parts[i].buf + parts[i].outlen, newlen - parts[i].outlen);
1000 
1001  parts[i].outlen = newlen;
1002  }
1003  } else {
1004  parts[i].compression_type = BTRFS_COMPRESSION_NONE;
1005  parts[i].outlen = (unsigned int)sector_align(parts[i].inlen, fcb->Vcb->superblock.sector_size);
1006  }
1007 
1008  buflen += parts[i].outlen;
1009  ExFreePool(parts[i].cj);
1010  }
1011 #else
1012  for (i3 = 0; i3 < num_parts; i3++) {
1013  if (parts[i3].cj->space_left >= fcb->Vcb->superblock.sector_size) {
1014  parts[i3].compression_type = type;
1015  parts[i3].outlen = parts[i3].inlen - parts[i3].cj->space_left;
1016 
1017  if (type == BTRFS_COMPRESSION_LZO)
1018  fcb->Vcb->superblock.incompat_flags |= BTRFS_INCOMPAT_FLAGS_COMPRESS_LZO;
1019  else if (type == BTRFS_COMPRESSION_ZSTD)
1020  fcb->Vcb->superblock.incompat_flags |= BTRFS_INCOMPAT_FLAGS_COMPRESS_ZSTD;
1021 
1022  if ((parts[i3].outlen % fcb->Vcb->superblock.sector_size) != 0) {
1023  unsigned int newlen = (unsigned int)sector_align(parts[i3].outlen, fcb->Vcb->superblock.sector_size);
1024 
1025  RtlZeroMemory(parts[i3].buf + parts[i3].outlen, newlen - parts[i3].outlen);
1026 
1027  parts[i3].outlen = newlen;
1028  }
1029  } else {
1030  parts[i3].compression_type = BTRFS_COMPRESSION_NONE;
1031  parts[i3].outlen = (unsigned int)sector_align(parts[i3].inlen, fcb->Vcb->superblock.sector_size);
1032  }
1033 
1034  buflen += parts[i3].outlen;
1035  ExFreePool(parts[i3].cj);
1036  }
1037 #endif // __REACTOS__
1038 
1039  // check if first 128 KB of file is incompressible
1040 
1041  if (start_data == 0 && parts[0].compression_type == BTRFS_COMPRESSION_NONE && !fcb->Vcb->options.compress_force) {
1042  TRACE("adding nocompress flag to subvol %I64x, inode %I64x\n", fcb->subvol->id, fcb->inode);
1043 
1045  fcb->inode_item_changed = true;
1047  }
1048 
1049  // join together into continuous buffer
1050 
1052  if (!buf) {
1053  ERR("out of memory\n");
1054  ExFreePool(parts);
1056  }
1057 
1058  {
1059  uint8_t* buf2 = buf;
1060 
1061  for (i = 0; i < num_parts; i++) {
1062  if (parts[i].compression_type == BTRFS_COMPRESSION_NONE)
1063  RtlCopyMemory(buf2, (uint8_t*)data + (i * COMPRESSED_EXTENT_SIZE), parts[i].outlen);
1064  else
1065  RtlCopyMemory(buf2, parts[i].buf, parts[i].outlen);
1066 
1067  buf2 += parts[i].outlen;
1068  }
1069  }
1070 
1071  // find an address
1072 
1073  ExAcquireResourceSharedLite(&fcb->Vcb->chunk_lock, true);
1074 
1075  le = fcb->Vcb->chunks.Flink;
1076  while (le != &fcb->Vcb->chunks) {
1078 
1079  if (!c2->readonly && !c2->reloc) {
1080  acquire_chunk_lock(c2, fcb->Vcb);
1081 
1082  if (c2->chunk_item->type == fcb->Vcb->data_flags && (c2->chunk_item->size - c2->used) >= buflen) {
1083  if (find_data_address_in_chunk(fcb->Vcb, c2, buflen, &address)) {
1084  c = c2;
1085  c->used += buflen;
1086  space_list_subtract(c, false, address, buflen, rollback);
1087  release_chunk_lock(c2, fcb->Vcb);
1088  break;
1089  }
1090  }
1091 
1092  release_chunk_lock(c2, fcb->Vcb);
1093  }
1094 
1095  le = le->Flink;
1096  }
1097 
1098  ExReleaseResourceLite(&fcb->Vcb->chunk_lock);
1099 
1100  if (!c) {
1101  chunk* c2;
1102 
1103  ExAcquireResourceExclusiveLite(&fcb->Vcb->chunk_lock, true);
1104 
1105  Status = alloc_chunk(fcb->Vcb, fcb->Vcb->data_flags, &c2, false);
1106 
1107  ExReleaseResourceLite(&fcb->Vcb->chunk_lock);
1108 
1109  if (!NT_SUCCESS(Status)) {
1110  ERR("alloc_chunk returned %08lx\n", Status);
1111  ExFreePool(buf);
1112  ExFreePool(parts);
1113  return Status;
1114  }
1115 
1116  acquire_chunk_lock(c2, fcb->Vcb);
1117 
1118  if (find_data_address_in_chunk(fcb->Vcb, c2, buflen, &address)) {
1119  c = c2;
1120  c->used += buflen;
1121  space_list_subtract(c, false, address, buflen, rollback);
1122  }
1123 
1124  release_chunk_lock(c2, fcb->Vcb);
1125  }
1126 
1127  if (!c) {
1128  WARN("couldn't find any data chunks with %x bytes free\n", buflen);
1129  ExFreePool(buf);
1130  ExFreePool(parts);
1131  return STATUS_DISK_FULL;
1132  }
1133 
1134  // write to disk
1135 
1136  TRACE("writing %x bytes to %I64x\n", buflen, address);
1137 
1138  Status = write_data_complete(fcb->Vcb, address, buf, buflen, Irp, NULL, false, 0,
1140  if (!NT_SUCCESS(Status)) {
1141  ERR("write_data_complete returned %08lx\n", Status);
1142  ExFreePool(buf);
1143  ExFreePool(parts);
1144  return Status;
1145  }
1146 
1147  // FIXME - do rest of the function while we're waiting for I/O to finish?
1148 
1149  // calculate csums if necessary
1150 
1152  unsigned int sl = buflen / fcb->Vcb->superblock.sector_size;
1153 
1154  csum = ExAllocatePoolWithTag(PagedPool, sl * fcb->Vcb->csum_size, ALLOC_TAG);
1155  if (!csum) {
1156  ERR("out of memory\n");
1157  ExFreePool(buf);
1158  ExFreePool(parts);
1160  }
1161 
1162  do_calc_job(fcb->Vcb, buf, sl, csum);
1163  }
1164 
1165  ExFreePool(buf);
1166 
1167  // add extents to fcb
1168 
1169  extaddr = address;
1170 
1171  for (i = 0; i < num_parts; i++) {
1172  EXTENT_DATA* ed;
1173  EXTENT_DATA2* ed2;
1174  void* csum2;
1175 
1177  if (!ed) {
1178  ERR("out of memory\n");
1179  ExFreePool(parts);
1180 
1181  if (csum)
1182  ExFreePool(csum);
1183 
1185  }
1186 
1187  ed->generation = fcb->Vcb->superblock.generation;
1188  ed->decoded_size = parts[i].inlen;
1189  ed->compression = parts[i].compression_type;
1193 
1194  ed2 = (EXTENT_DATA2*)ed->data;
1195  ed2->address = extaddr;
1196  ed2->size = parts[i].outlen;
1197  ed2->offset = 0;
1198  ed2->num_bytes = parts[i].inlen;
1199 
1200  if (csum) {
1201  csum2 = ExAllocatePoolWithTag(PagedPool, parts[i].outlen * fcb->Vcb->csum_size / fcb->Vcb->superblock.sector_size, ALLOC_TAG);
1202  if (!csum2) {
1203  ERR("out of memory\n");
1204  ExFreePool(ed);
1205  ExFreePool(parts);
1206  ExFreePool(csum);
1208  }
1209 
1210  RtlCopyMemory(csum2, (uint8_t*)csum + ((extaddr - address) * fcb->Vcb->csum_size / fcb->Vcb->superblock.sector_size),
1211  parts[i].outlen * fcb->Vcb->csum_size / fcb->Vcb->superblock.sector_size);
1212  } else
1213  csum2 = NULL;
1214 
1216  true, csum2, rollback);
1217  if (!NT_SUCCESS(Status)) {
1218  ERR("add_extent_to_fcb returned %08lx\n", Status);
1219  ExFreePool(ed);
1220  ExFreePool(parts);
1221 
1222  if (csum)
1223  ExFreePool(csum);
1224 
1225  return Status;
1226  }
1227 
1228  ExFreePool(ed);
1229 
1230  fcb->inode_item.st_blocks += parts[i].inlen;
1231 
1232  extaddr += parts[i].outlen;
1233  }
1234 
1235  if (csum)
1236  ExFreePool(csum);
1237 
1238  // update extent refcounts
1239 
1240  ExAcquireResourceExclusiveLite(&c->changed_extents_lock, true);
1241 
1242  extaddr = address;
1243 
1244  for (i = 0; i < num_parts; i++) {
1245  add_changed_extent_ref(c, extaddr, parts[i].outlen, fcb->subvol->id, fcb->inode,
1247 
1248  extaddr += parts[i].outlen;
1249  }
1250 
1251  ExReleaseResourceLite(&c->changed_extents_lock);
1252 
1253  fcb->extents_changed = true;
1254  fcb->inode_item_changed = true;
1256 
1257  ExFreePool(parts);
1258 
1259  return STATUS_SUCCESS;
1260 }
uint64_t generation
Definition: btrfs.h:346
ZSTDLIB_API const char * ZSTD_getErrorName(size_t code)
Definition: zstd_common.c:39
GLint level
Definition: gl.h:1546
uint8_t type
Definition: btrfs.h:351
static HANDLE PIO_APC_ROUTINE PVOID PIO_STATUS_BLOCK ULONG PVOID ULONG PVOID ULONG out_size
Definition: file.c:100
NTSYSAPI VOID NTAPI RtlCopyMemory(VOID UNALIGNED *Destination, CONST VOID UNALIGNED *Source, ULONG Length)
static UCHAR ULONG UCHAR ULONG UCHAR * output
Definition: bcrypt.c:29
_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
#define BTRFS_COMPRESSION_NONE
Definition: btrfs.h:61
void space_list_subtract(chunk *c, bool deleting, uint64_t address, uint64_t length, LIST_ENTRY *rollback)
Definition: free-space.c:2047
NTSTATUS write_compressed(fcb *fcb, uint64_t start_data, uint64_t end_data, void *data, PIRP Irp, LIST_ENTRY *rollback)
Definition: compress.c:877
static void lzo_copy(lzo_stream *stream, int len)
Definition: compress.c:133
EXTENT_DATA2 * ed2
Definition: write.c:2805
static void zlib_free(void *opaque, void *ptr)
Definition: compress.c:330
#define M3_MARKER
Definition: compress.c:70
GLenum GLuint GLenum GLsizei const GLchar * buf
Definition: glext.h:7751
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)
Definition: write.c:2182
_In_ PIRP Irp
Definition: csq.h:116
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
uint64_t decoded_size
Definition: btrfs.h:347
#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
int ZEXPORT inflateEnd(z_streamp strm)
Definition: inflate.c:1277
uInt avail_in
Definition: zlib.h:88
enum prop_compression_type prop_compression
Definition: btrfs_drv.h:318
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
release_chunk_lock(c, Vcb)
static void * zlib_alloc(void *opaque, unsigned int items, unsigned int size)
Definition: compress.c:324
GLuint GLuint GLsizei GLenum type
Definition: gl.h:1545
uint64_t used
Definition: btrfs_drv.h:574
#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
GLuint GLuint end
Definition: gl.h:1545
#define BTRFS_COMPRESSION_LZO
Definition: btrfs.h:63
#define BTRFS_COMPRESSION_ZSTD
Definition: btrfs.h:64
ZSTD_customMem zstd_mem
Definition: compress.c:98
bool readonly
Definition: btrfs_drv.h:589
NTSTATUS lzo_compress(uint8_t *inbuf, uint32_t inlen, uint8_t *outbuf, uint32_t outlen, unsigned int *space_left)
Definition: compress.c:722
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:349
int ZEXPORT deflateEnd(z_streamp strm)
Definition: deflate.c:1079
#define deflateInit(strm, level)
Definition: zlib.h:1793
#define BTRFS_COMPRESSION_ZLIB
Definition: btrfs.h:62
#define COMPRESSED_EXTENT_SIZE
Definition: btrfs_drv.h:116
#define Z_STREAM_END
Definition: zlib.h:178
_In_ fcb _In_ chunk _In_ uint64_t start_data
Definition: btrfs_drv.h:1357
BOOLEAN NTAPI ExAcquireResourceExclusiveLite(IN PERESOURCE Resource, IN BOOLEAN Wait)
Definition: resource.c:770
#define STATUS_INTERNAL_ERROR
Definition: ntstatus.h:451
#define BTRFS_INCOMPAT_FLAGS_COMPRESS_LZO
Definition: btrfs.h:111
#define ALLOC_TAG
Definition: btrfs_drv.h:91
uint64_t size
Definition: btrfs.h:328
voidpf opaque
Definition: zlib.h:100
void do_calc_job(device_extension *Vcb, uint8_t *data, uint32_t sectors, void *csum)
Definition: calcthread.c:141
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
free_func zfree
Definition: zlib.h:99
GLenum GLint GLuint mask
Definition: glext.h:6028
GLenum const GLfloat * params
Definition: glext.h:5645
uint64_t address
Definition: btrfs.h:356
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:874
#define Z_OK
Definition: zlib.h:177
bool extents_changed
Definition: btrfs_drv.h:334
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:68
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:807
smooth NULL
Definition: ftsmooth.c:416
#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:1625
uint64_t size
Definition: btrfs.h:357
bool reloc
Definition: btrfs_drv.h:590
#define UNUSED(x)
Definition: btrfs_drv.h:86
struct match match
Definition: match.c:33
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:294
struct _LIST_ENTRY * Flink
Definition: typedefs.h:120
uint16_t encoding
Definition: btrfs.h:350
#define BTRFS_ENCRYPTION_NONE
Definition: btrfs.h:66
#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
if(!(yy_init))
Definition: macro.lex.yy.c:714
#define NT_SUCCESS(StatCode)
Definition: apphelp.c:32
uint64_t inode
Definition: btrfs_drv.h:300
#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:98
size_t ZSTD_initCStream_advanced(ZSTD_CStream *zcs, const void *dict, size_t dictSize, ZSTD_parameters params, unsigned long long pledgedSrcSize)
static FILE * out
Definition: regtests2xml.c:44
GLuint address
Definition: glext.h:9393
UINT op
Definition: effect.c:224
bool error
Definition: compress.c:55
VOID FASTCALL ExReleaseResourceLite(IN PERESOURCE Resource)
Definition: resource.c:1817
#define Z_NO_FLUSH
Definition: zlib.h:168
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
int ZEXPORT inflate(z_streamp strm, int flush)
Definition: inflate.c:622
#define LZO1X_MEM_COMPRESS
Definition: compress.c:59
#define ZSTD_BTRFS_MAX_WINDOWLOG
Definition: compress.c:92
#define ExAllocatePoolWithTag(hernya, size, tag)
Definition: env_spec_w32.h:350
int ret
NTSTATUS excise_extents(device_extension *Vcb, fcb *fcb, uint64_t start_data, uint64_t end_data, PIRP Irp, LIST_ENTRY *rollback)
Definition: write.c:2384
#define inflateInit(strm)
Definition: zlib.h:1795
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:872
int ZEXPORT deflate(z_streamp strm, int flush)
Definition: deflate.c:766
GLenum GLsizei len
Definition: glext.h:6722
uint32_t outpos
Definition: compress.c:54
Definition: typedefs.h:118
INODE_ITEM inode_item
Definition: btrfs_drv.h:303
BYTE uint8_t
Definition: msvideo1.c:66
uint64_t num_bytes
Definition: btrfs.h:359
uint64_t st_blocks
Definition: btrfs.h:283
uint64_t flags
Definition: btrfs.h:290
INT32 int32_t
Definition: types.h:71
#define EXTENT_TYPE_REGULAR
Definition: btrfs.h:71
#define ALLOC_TAG_ZLIB
Definition: btrfs_drv.h:92
Status
Definition: gdiplustypes.h:24
#define ERR(fmt,...)
Definition: debug.h:110
uint8_t data[1]
Definition: btrfs.h:352
Byte FAR * voidpf
Definition: zconf.h:413
#define Z_FINISH
Definition: zlib.h:172
#define ZSTD_isError
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
#define M3_MAX_OFFSET
Definition: compress.c:63
GLuint in
Definition: glext.h:9616
uint8_t * out
Definition: compress.c:52
#define acquire_chunk_lock(c, Vcb)
Definition: btrfs_drv.h:1137
#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
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:299
#define min(a, b)
Definition: monoChain.cc:55
Definition: list.h:27
__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:1357
uInt avail_out
Definition: zlib.h:92
z_const Bytef * next_in
Definition: zlib.h:87
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:571
Definition: fs.h:216
bool find_data_address_in_chunk(device_extension *Vcb, chunk *c, uint64_t length, uint64_t *address)
#define STATUS_DISK_FULL
Definition: udferr_usr.h:155
#define c
Definition: ke_i.h:80
unsigned int outlen
Definition: compress.c:873
#define RtlZeroMemory(Destination, Length)
Definition: typedefs.h:261
ZSTD_CStream * ZSTD_createCStream_advanced(ZSTD_customMem customMem)
ZSTD_parameters ZSTD_getParams(int compressionLevel, unsigned long long srcSizeHint, size_t dictSize)
uint64_t offset
Definition: btrfs.h:358
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)
Definition: write.c:2736
#define LZO_PAGE_SIZE
Definition: compress.c:46
uint8_t compression_type
Definition: compress.c:871
Bytef * next_out
Definition: zlib.h:91
NTSTATUS alloc_chunk(device_extension *Vcb, uint64_t flags, chunk **pc, bool full_size)
Definition: write.c:361
uint64_t type
Definition: btrfs.h:331
#define uint32_t
Definition: nsiface.idl:61
static TCHAR * items[]
Definition: page1.c:45
return STATUS_SUCCESS
Definition: btrfs.c:3014
EXTENT_DATA * ed
Definition: write.c:2804
bool inode_item_changed
Definition: btrfs_drv.h:317
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:112
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:298
#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:348
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