Coverage Report

Created: 2026-10-17 06:38

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/barebox/fs/squashfs/zstd_wrapper.c
Line
Count
Source
1
/*
2
 * Squashfs - a compressed read only filesystem for Linux
3
 *
4
 * Copyright (c) 2016-present, Facebook, Inc.
5
 * All rights reserved.
6
 *
7
 * This program is free software; you can redistribute it and/or
8
 * modify it under the terms of the GNU General Public License
9
 * as published by the Free Software Foundation; either version 2,
10
 * or (at your option) any later version.
11
 *
12
 * This program 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 General Public License for more details.
16
 *
17
 * zstd_wrapper.c
18
 */
19
20
#include <linux/zstd.h>
21
22
#include "squashfs_fs.h"
23
#include "squashfs_fs_sb.h"
24
#include "squashfs.h"
25
#include "decompressor.h"
26
#include "page_actor.h"
27
28
struct workspace {
29
  void *mem;
30
  size_t mem_size;
31
  size_t window_size;
32
};
33
34
static void *zstd_init(struct squashfs_sb_info *msblk, void *buff)
35
0
{
36
0
  struct workspace *wksp = kmalloc(sizeof(*wksp), GFP_KERNEL);
37
38
0
  if (wksp == NULL)
39
0
    goto failed;
40
0
  wksp->window_size = max_t(size_t,
41
0
      msblk->block_size, SQUASHFS_METADATA_SIZE);
42
0
  wksp->mem_size = ZSTD_DStreamWorkspaceBound(wksp->window_size);
43
0
  wksp->mem = vmalloc(wksp->mem_size);
44
0
  if (wksp->mem == NULL)
45
0
    goto failed;
46
47
0
  return wksp;
48
49
0
failed:
50
0
  ERROR("Failed to allocate zstd workspace\n");
51
0
  kfree(wksp);
52
0
  return ERR_PTR(-ENOMEM);
53
0
}
54
55
56
static void zstd_free(void *strm)
57
0
{
58
0
  struct workspace *wksp = strm;
59
60
0
  if (wksp)
61
0
    vfree(wksp->mem);
62
0
  kfree(wksp);
63
0
}
64
65
66
static int zstd_uncompress(struct squashfs_sb_info *msblk, void *strm,
67
  char **bh, int b, int offset, int length,
68
  struct squashfs_page_actor *output)
69
0
{
70
0
  struct workspace *wksp = strm;
71
0
  ZSTD_DStream *stream;
72
0
  size_t total_out = 0;
73
0
  size_t zstd_err;
74
0
  int k = 0;
75
0
  ZSTD_inBuffer in_buf = { NULL, 0, 0 };
76
0
  ZSTD_outBuffer out_buf = { NULL, 0, 0 };
77
78
0
  stream = ZSTD_initDStream(wksp->window_size, wksp->mem, wksp->mem_size);
79
80
0
  if (!stream) {
81
0
    ERROR("Failed to initialize zstd decompressor\n");
82
0
    goto out;
83
0
  }
84
85
0
  out_buf.size = PAGE_SIZE;
86
0
  out_buf.dst = squashfs_first_page(output);
87
88
0
  do {
89
0
    if (in_buf.pos == in_buf.size && k < b) {
90
0
      int avail = min(length, msblk->devblksize - offset);
91
92
0
      length -= avail;
93
0
      in_buf.src = bh[k] + offset;
94
0
      in_buf.size = avail;
95
0
      in_buf.pos = 0;
96
0
      offset = 0;
97
0
    }
98
99
0
    if (out_buf.pos == out_buf.size) {
100
0
      out_buf.dst = squashfs_next_page(output);
101
0
      if (out_buf.dst == NULL) {
102
        /* Shouldn't run out of pages
103
         * before stream is done.
104
         */
105
0
        squashfs_finish_page(output);
106
0
        goto out;
107
0
      }
108
0
      out_buf.pos = 0;
109
0
      out_buf.size = PAGE_SIZE;
110
0
    }
111
112
0
    total_out -= out_buf.pos;
113
0
    zstd_err = ZSTD_decompressStream(stream, &out_buf, &in_buf);
114
0
    total_out += out_buf.pos; /* add the additional data produced */
115
116
0
    if (in_buf.pos == in_buf.size && k < b)
117
0
      kfree(bh[k++]);
118
0
  } while (zstd_err != 0 && !ZSTD_isError(zstd_err));
119
120
0
  squashfs_finish_page(output);
121
122
0
  if (ZSTD_isError(zstd_err)) {
123
0
    ERROR("zstd decompression error: %d\n",
124
0
        (int)ZSTD_getErrorCode(zstd_err));
125
0
    goto out;
126
0
  }
127
128
0
  if (k < b)
129
0
    goto out;
130
131
0
  return (int)total_out;
132
133
0
out:
134
0
  for (; k < b; k++)
135
0
    kfree(bh[k]);
136
137
0
  return -EIO;
138
0
}
139
140
const struct squashfs_decompressor squashfs_zstd_comp_ops = {
141
  .init = zstd_init,
142
  .free = zstd_free,
143
  .decompress = zstd_uncompress,
144
  .id = ZSTD_COMPRESSION,
145
  .name = "zstd",
146
  .supported = 1
147
};