1 /* 2 * Copyright (C) 2008 Oracle. All rights reserved. 3 * 4 * This program is free software; you can redistribute it and/or 5 * modify it under the terms of the GNU General Public 6 * License v2 as published by the Free Software Foundation. 7 * 8 * This program is distributed in the hope that it will be useful, 9 * but WITHOUT ANY WARRANTY; without even the implied warranty of 10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 11 * General Public License for more details. 12 * 13 * You should have received a copy of the GNU General Public 14 * License along with this program; if not, write to the 15 * Free Software Foundation, Inc., 59 Temple Place - Suite 330, 16 * Boston, MA 021110-1307, USA. 17 * 18 * Based on jffs2 zlib code: 19 * Copyright © 2001-2007 Red Hat, Inc. 20 * Created by David Woodhouse <dwmw2@infradead.org> 21 */ 22 23 #include <linux/kernel.h> 24 #include <linux/slab.h> 25 #include <linux/zlib.h> 26 #include <linux/zutil.h> 27 #include <linux/vmalloc.h> 28 #include <linux/init.h> 29 #include <linux/err.h> 30 #include <linux/sched.h> 31 #include <linux/pagemap.h> 32 #include <linux/bio.h> 33 #include "compression.h" 34 35 struct workspace { 36 z_stream inf_strm; 37 z_stream def_strm; 38 char *buf; 39 struct list_head list; 40 }; 41 42 static void zlib_free_workspace(struct list_head *ws) 43 { 44 struct workspace *workspace = list_entry(ws, struct workspace, list); 45 46 vfree(workspace->def_strm.workspace); 47 vfree(workspace->inf_strm.workspace); 48 kfree(workspace->buf); 49 kfree(workspace); 50 } 51 52 static struct list_head *zlib_alloc_workspace(void) 53 { 54 struct workspace *workspace; 55 56 workspace = kzalloc(sizeof(*workspace), GFP_NOFS); 57 if (!workspace) 58 return ERR_PTR(-ENOMEM); 59 60 workspace->def_strm.workspace = vmalloc(zlib_deflate_workspacesize()); 61 workspace->inf_strm.workspace = vmalloc(zlib_inflate_workspacesize()); 62 workspace->buf = kmalloc(PAGE_CACHE_SIZE, GFP_NOFS); 63 if (!workspace->def_strm.workspace || 64 !workspace->inf_strm.workspace || !workspace->buf) 65 goto fail; 66 67 INIT_LIST_HEAD(&workspace->list); 68 69 return &workspace->list; 70 fail: 71 zlib_free_workspace(&workspace->list); 72 return ERR_PTR(-ENOMEM); 73 } 74 75 static int zlib_compress_pages(struct list_head *ws, 76 struct address_space *mapping, 77 u64 start, unsigned long len, 78 struct page **pages, 79 unsigned long nr_dest_pages, 80 unsigned long *out_pages, 81 unsigned long *total_in, 82 unsigned long *total_out, 83 unsigned long max_out) 84 { 85 struct workspace *workspace = list_entry(ws, struct workspace, list); 86 int ret; 87 char *data_in; 88 char *cpage_out; 89 int nr_pages = 0; 90 struct page *in_page = NULL; 91 struct page *out_page = NULL; 92 unsigned long bytes_left; 93 94 *out_pages = 0; 95 *total_out = 0; 96 *total_in = 0; 97 98 if (Z_OK != zlib_deflateInit(&workspace->def_strm, 3)) { 99 printk(KERN_WARNING "deflateInit failed\n"); 100 ret = -1; 101 goto out; 102 } 103 104 workspace->def_strm.total_in = 0; 105 workspace->def_strm.total_out = 0; 106 107 in_page = find_get_page(mapping, start >> PAGE_CACHE_SHIFT); 108 data_in = kmap(in_page); 109 110 out_page = alloc_page(GFP_NOFS | __GFP_HIGHMEM); 111 if (out_page == NULL) { 112 ret = -1; 113 goto out; 114 } 115 cpage_out = kmap(out_page); 116 pages[0] = out_page; 117 nr_pages = 1; 118 119 workspace->def_strm.next_in = data_in; 120 workspace->def_strm.next_out = cpage_out; 121 workspace->def_strm.avail_out = PAGE_CACHE_SIZE; 122 workspace->def_strm.avail_in = min(len, PAGE_CACHE_SIZE); 123 124 while (workspace->def_strm.total_in < len) { 125 ret = zlib_deflate(&workspace->def_strm, Z_SYNC_FLUSH); 126 if (ret != Z_OK) { 127 printk(KERN_DEBUG "btrfs deflate in loop returned %d\n", 128 ret); 129 zlib_deflateEnd(&workspace->def_strm); 130 ret = -1; 131 goto out; 132 } 133 134 /* we're making it bigger, give up */ 135 if (workspace->def_strm.total_in > 8192 && 136 workspace->def_strm.total_in < 137 workspace->def_strm.total_out) { 138 ret = -1; 139 goto out; 140 } 141 /* we need another page for writing out. Test this 142 * before the total_in so we will pull in a new page for 143 * the stream end if required 144 */ 145 if (workspace->def_strm.avail_out == 0) { 146 kunmap(out_page); 147 if (nr_pages == nr_dest_pages) { 148 out_page = NULL; 149 ret = -1; 150 goto out; 151 } 152 out_page = alloc_page(GFP_NOFS | __GFP_HIGHMEM); 153 if (out_page == NULL) { 154 ret = -1; 155 goto out; 156 } 157 cpage_out = kmap(out_page); 158 pages[nr_pages] = out_page; 159 nr_pages++; 160 workspace->def_strm.avail_out = PAGE_CACHE_SIZE; 161 workspace->def_strm.next_out = cpage_out; 162 } 163 /* we're all done */ 164 if (workspace->def_strm.total_in >= len) 165 break; 166 167 /* we've read in a full page, get a new one */ 168 if (workspace->def_strm.avail_in == 0) { 169 if (workspace->def_strm.total_out > max_out) 170 break; 171 172 bytes_left = len - workspace->def_strm.total_in; 173 kunmap(in_page); 174 page_cache_release(in_page); 175 176 start += PAGE_CACHE_SIZE; 177 in_page = find_get_page(mapping, 178 start >> PAGE_CACHE_SHIFT); 179 data_in = kmap(in_page); 180 workspace->def_strm.avail_in = min(bytes_left, 181 PAGE_CACHE_SIZE); 182 workspace->def_strm.next_in = data_in; 183 } 184 } 185 workspace->def_strm.avail_in = 0; 186 ret = zlib_deflate(&workspace->def_strm, Z_FINISH); 187 zlib_deflateEnd(&workspace->def_strm); 188 189 if (ret != Z_STREAM_END) { 190 ret = -1; 191 goto out; 192 } 193 194 if (workspace->def_strm.total_out >= workspace->def_strm.total_in) { 195 ret = -1; 196 goto out; 197 } 198 199 ret = 0; 200 *total_out = workspace->def_strm.total_out; 201 *total_in = workspace->def_strm.total_in; 202 out: 203 *out_pages = nr_pages; 204 if (out_page) 205 kunmap(out_page); 206 207 if (in_page) { 208 kunmap(in_page); 209 page_cache_release(in_page); 210 } 211 return ret; 212 } 213 214 static int zlib_decompress_biovec(struct list_head *ws, struct page **pages_in, 215 u64 disk_start, 216 struct bio_vec *bvec, 217 int vcnt, 218 size_t srclen) 219 { 220 struct workspace *workspace = list_entry(ws, struct workspace, list); 221 int ret = 0, ret2; 222 int wbits = MAX_WBITS; 223 char *data_in; 224 size_t total_out = 0; 225 unsigned long page_in_index = 0; 226 unsigned long page_out_index = 0; 227 unsigned long total_pages_in = (srclen + PAGE_CACHE_SIZE - 1) / 228 PAGE_CACHE_SIZE; 229 unsigned long buf_start; 230 unsigned long pg_offset; 231 232 data_in = kmap(pages_in[page_in_index]); 233 workspace->inf_strm.next_in = data_in; 234 workspace->inf_strm.avail_in = min_t(size_t, srclen, PAGE_CACHE_SIZE); 235 workspace->inf_strm.total_in = 0; 236 237 workspace->inf_strm.total_out = 0; 238 workspace->inf_strm.next_out = workspace->buf; 239 workspace->inf_strm.avail_out = PAGE_CACHE_SIZE; 240 pg_offset = 0; 241 242 /* If it's deflate, and it's got no preset dictionary, then 243 we can tell zlib to skip the adler32 check. */ 244 if (srclen > 2 && !(data_in[1] & PRESET_DICT) && 245 ((data_in[0] & 0x0f) == Z_DEFLATED) && 246 !(((data_in[0]<<8) + data_in[1]) % 31)) { 247 248 wbits = -((data_in[0] >> 4) + 8); 249 workspace->inf_strm.next_in += 2; 250 workspace->inf_strm.avail_in -= 2; 251 } 252 253 if (Z_OK != zlib_inflateInit2(&workspace->inf_strm, wbits)) { 254 printk(KERN_WARNING "inflateInit failed\n"); 255 return -1; 256 } 257 while (workspace->inf_strm.total_in < srclen) { 258 ret = zlib_inflate(&workspace->inf_strm, Z_NO_FLUSH); 259 if (ret != Z_OK && ret != Z_STREAM_END) 260 break; 261 262 buf_start = total_out; 263 total_out = workspace->inf_strm.total_out; 264 265 /* we didn't make progress in this inflate call, we're done */ 266 if (buf_start == total_out) 267 break; 268 269 ret2 = btrfs_decompress_buf2page(workspace->buf, buf_start, 270 total_out, disk_start, 271 bvec, vcnt, 272 &page_out_index, &pg_offset); 273 if (ret2 == 0) { 274 ret = 0; 275 goto done; 276 } 277 278 workspace->inf_strm.next_out = workspace->buf; 279 workspace->inf_strm.avail_out = PAGE_CACHE_SIZE; 280 281 if (workspace->inf_strm.avail_in == 0) { 282 unsigned long tmp; 283 kunmap(pages_in[page_in_index]); 284 page_in_index++; 285 if (page_in_index >= total_pages_in) { 286 data_in = NULL; 287 break; 288 } 289 data_in = kmap(pages_in[page_in_index]); 290 workspace->inf_strm.next_in = data_in; 291 tmp = srclen - workspace->inf_strm.total_in; 292 workspace->inf_strm.avail_in = min(tmp, 293 PAGE_CACHE_SIZE); 294 } 295 } 296 if (ret != Z_STREAM_END) 297 ret = -1; 298 else 299 ret = 0; 300 done: 301 zlib_inflateEnd(&workspace->inf_strm); 302 if (data_in) 303 kunmap(pages_in[page_in_index]); 304 return ret; 305 } 306 307 static int zlib_decompress(struct list_head *ws, unsigned char *data_in, 308 struct page *dest_page, 309 unsigned long start_byte, 310 size_t srclen, size_t destlen) 311 { 312 struct workspace *workspace = list_entry(ws, struct workspace, list); 313 int ret = 0; 314 int wbits = MAX_WBITS; 315 unsigned long bytes_left = destlen; 316 unsigned long total_out = 0; 317 char *kaddr; 318 319 workspace->inf_strm.next_in = data_in; 320 workspace->inf_strm.avail_in = srclen; 321 workspace->inf_strm.total_in = 0; 322 323 workspace->inf_strm.next_out = workspace->buf; 324 workspace->inf_strm.avail_out = PAGE_CACHE_SIZE; 325 workspace->inf_strm.total_out = 0; 326 /* If it's deflate, and it's got no preset dictionary, then 327 we can tell zlib to skip the adler32 check. */ 328 if (srclen > 2 && !(data_in[1] & PRESET_DICT) && 329 ((data_in[0] & 0x0f) == Z_DEFLATED) && 330 !(((data_in[0]<<8) + data_in[1]) % 31)) { 331 332 wbits = -((data_in[0] >> 4) + 8); 333 workspace->inf_strm.next_in += 2; 334 workspace->inf_strm.avail_in -= 2; 335 } 336 337 if (Z_OK != zlib_inflateInit2(&workspace->inf_strm, wbits)) { 338 printk(KERN_WARNING "inflateInit failed\n"); 339 return -1; 340 } 341 342 while (bytes_left > 0) { 343 unsigned long buf_start; 344 unsigned long buf_offset; 345 unsigned long bytes; 346 unsigned long pg_offset = 0; 347 348 ret = zlib_inflate(&workspace->inf_strm, Z_NO_FLUSH); 349 if (ret != Z_OK && ret != Z_STREAM_END) 350 break; 351 352 buf_start = total_out; 353 total_out = workspace->inf_strm.total_out; 354 355 if (total_out == buf_start) { 356 ret = -1; 357 break; 358 } 359 360 if (total_out <= start_byte) 361 goto next; 362 363 if (total_out > start_byte && buf_start < start_byte) 364 buf_offset = start_byte - buf_start; 365 else 366 buf_offset = 0; 367 368 bytes = min(PAGE_CACHE_SIZE - pg_offset, 369 PAGE_CACHE_SIZE - buf_offset); 370 bytes = min(bytes, bytes_left); 371 372 kaddr = kmap_atomic(dest_page, KM_USER0); 373 memcpy(kaddr + pg_offset, workspace->buf + buf_offset, bytes); 374 kunmap_atomic(kaddr, KM_USER0); 375 376 pg_offset += bytes; 377 bytes_left -= bytes; 378 next: 379 workspace->inf_strm.next_out = workspace->buf; 380 workspace->inf_strm.avail_out = PAGE_CACHE_SIZE; 381 } 382 383 if (ret != Z_STREAM_END && bytes_left != 0) 384 ret = -1; 385 else 386 ret = 0; 387 388 zlib_inflateEnd(&workspace->inf_strm); 389 return ret; 390 } 391 392 struct btrfs_compress_op btrfs_zlib_compress = { 393 .alloc_workspace = zlib_alloc_workspace, 394 .free_workspace = zlib_free_workspace, 395 .compress_pages = zlib_compress_pages, 396 .decompress_biovec = zlib_decompress_biovec, 397 .decompress = zlib_decompress, 398 }; 399