11
11
#include <linux/backing-dev.h>
12
12
#include <linux/lzo.h>
13
13
#include <linux/lz4.h>
14
+ #include <linux/zstd.h>
14
15
15
16
#include "f2fs.h"
16
17
#include "node.h"
@@ -291,6 +292,165 @@ static const struct f2fs_compress_ops f2fs_lz4_ops = {
291
292
};
292
293
#endif
293
294
295
+ #ifdef CONFIG_F2FS_FS_ZSTD
296
+ #define F2FS_ZSTD_DEFAULT_CLEVEL 1
297
+
298
+ static int zstd_init_compress_ctx (struct compress_ctx * cc )
299
+ {
300
+ ZSTD_parameters params ;
301
+ ZSTD_CStream * stream ;
302
+ void * workspace ;
303
+ unsigned int workspace_size ;
304
+
305
+ params = ZSTD_getParams (F2FS_ZSTD_DEFAULT_CLEVEL , cc -> rlen , 0 );
306
+ workspace_size = ZSTD_CStreamWorkspaceBound (params .cParams );
307
+
308
+ workspace = f2fs_kvmalloc (F2FS_I_SB (cc -> inode ),
309
+ workspace_size , GFP_NOFS );
310
+ if (!workspace )
311
+ return - ENOMEM ;
312
+
313
+ stream = ZSTD_initCStream (params , 0 , workspace , workspace_size );
314
+ if (!stream ) {
315
+ printk_ratelimited ("%sF2FS-fs (%s): %s ZSTD_initCStream failed\n" ,
316
+ KERN_ERR , F2FS_I_SB (cc -> inode )-> sb -> s_id ,
317
+ __func__ );
318
+ kvfree (workspace );
319
+ return - EIO ;
320
+ }
321
+
322
+ cc -> private = workspace ;
323
+ cc -> private2 = stream ;
324
+
325
+ cc -> clen = cc -> rlen - PAGE_SIZE - COMPRESS_HEADER_SIZE ;
326
+ return 0 ;
327
+ }
328
+
329
+ static void zstd_destroy_compress_ctx (struct compress_ctx * cc )
330
+ {
331
+ kvfree (cc -> private );
332
+ cc -> private = NULL ;
333
+ cc -> private2 = NULL ;
334
+ }
335
+
336
+ static int zstd_compress_pages (struct compress_ctx * cc )
337
+ {
338
+ ZSTD_CStream * stream = cc -> private2 ;
339
+ ZSTD_inBuffer inbuf ;
340
+ ZSTD_outBuffer outbuf ;
341
+ int src_size = cc -> rlen ;
342
+ int dst_size = src_size - PAGE_SIZE - COMPRESS_HEADER_SIZE ;
343
+ int ret ;
344
+
345
+ inbuf .pos = 0 ;
346
+ inbuf .src = cc -> rbuf ;
347
+ inbuf .size = src_size ;
348
+
349
+ outbuf .pos = 0 ;
350
+ outbuf .dst = cc -> cbuf -> cdata ;
351
+ outbuf .size = dst_size ;
352
+
353
+ ret = ZSTD_compressStream (stream , & outbuf , & inbuf );
354
+ if (ZSTD_isError (ret )) {
355
+ printk_ratelimited ("%sF2FS-fs (%s): %s ZSTD_compressStream failed, ret: %d\n" ,
356
+ KERN_ERR , F2FS_I_SB (cc -> inode )-> sb -> s_id ,
357
+ __func__ , ZSTD_getErrorCode (ret ));
358
+ return - EIO ;
359
+ }
360
+
361
+ ret = ZSTD_endStream (stream , & outbuf );
362
+ if (ZSTD_isError (ret )) {
363
+ printk_ratelimited ("%sF2FS-fs (%s): %s ZSTD_endStream returned %d\n" ,
364
+ KERN_ERR , F2FS_I_SB (cc -> inode )-> sb -> s_id ,
365
+ __func__ , ZSTD_getErrorCode (ret ));
366
+ return - EIO ;
367
+ }
368
+
369
+ cc -> clen = outbuf .pos ;
370
+ return 0 ;
371
+ }
372
+
373
+ static int zstd_init_decompress_ctx (struct decompress_io_ctx * dic )
374
+ {
375
+ ZSTD_DStream * stream ;
376
+ void * workspace ;
377
+ unsigned int workspace_size ;
378
+
379
+ workspace_size = ZSTD_DStreamWorkspaceBound (MAX_COMPRESS_WINDOW_SIZE );
380
+
381
+ workspace = f2fs_kvmalloc (F2FS_I_SB (dic -> inode ),
382
+ workspace_size , GFP_NOFS );
383
+ if (!workspace )
384
+ return - ENOMEM ;
385
+
386
+ stream = ZSTD_initDStream (MAX_COMPRESS_WINDOW_SIZE ,
387
+ workspace , workspace_size );
388
+ if (!stream ) {
389
+ printk_ratelimited ("%sF2FS-fs (%s): %s ZSTD_initDStream failed\n" ,
390
+ KERN_ERR , F2FS_I_SB (dic -> inode )-> sb -> s_id ,
391
+ __func__ );
392
+ kvfree (workspace );
393
+ return - EIO ;
394
+ }
395
+
396
+ dic -> private = workspace ;
397
+ dic -> private2 = stream ;
398
+
399
+ return 0 ;
400
+ }
401
+
402
+ static void zstd_destroy_decompress_ctx (struct decompress_io_ctx * dic )
403
+ {
404
+ kvfree (dic -> private );
405
+ dic -> private = NULL ;
406
+ dic -> private2 = NULL ;
407
+ }
408
+
409
+ static int zstd_decompress_pages (struct decompress_io_ctx * dic )
410
+ {
411
+ ZSTD_DStream * stream = dic -> private2 ;
412
+ ZSTD_inBuffer inbuf ;
413
+ ZSTD_outBuffer outbuf ;
414
+ int ret ;
415
+
416
+ inbuf .pos = 0 ;
417
+ inbuf .src = dic -> cbuf -> cdata ;
418
+ inbuf .size = dic -> clen ;
419
+
420
+ outbuf .pos = 0 ;
421
+ outbuf .dst = dic -> rbuf ;
422
+ outbuf .size = dic -> rlen ;
423
+
424
+ ret = ZSTD_decompressStream (stream , & outbuf , & inbuf );
425
+ if (ZSTD_isError (ret )) {
426
+ printk_ratelimited ("%sF2FS-fs (%s): %s ZSTD_compressStream failed, ret: %d\n" ,
427
+ KERN_ERR , F2FS_I_SB (dic -> inode )-> sb -> s_id ,
428
+ __func__ , ZSTD_getErrorCode (ret ));
429
+ return - EIO ;
430
+ }
431
+
432
+ if (dic -> rlen != outbuf .pos ) {
433
+ printk_ratelimited ("%sF2FS-fs (%s): %s ZSTD invalid rlen:%zu, "
434
+ "expected:%lu\n" , KERN_ERR ,
435
+ F2FS_I_SB (dic -> inode )-> sb -> s_id ,
436
+ __func__ , dic -> rlen ,
437
+ PAGE_SIZE << dic -> log_cluster_size );
438
+ return - EIO ;
439
+ }
440
+
441
+ return 0 ;
442
+ }
443
+
444
+ static const struct f2fs_compress_ops f2fs_zstd_ops = {
445
+ .init_compress_ctx = zstd_init_compress_ctx ,
446
+ .destroy_compress_ctx = zstd_destroy_compress_ctx ,
447
+ .compress_pages = zstd_compress_pages ,
448
+ .init_decompress_ctx = zstd_init_decompress_ctx ,
449
+ .destroy_decompress_ctx = zstd_destroy_decompress_ctx ,
450
+ .decompress_pages = zstd_decompress_pages ,
451
+ };
452
+ #endif
453
+
294
454
static const struct f2fs_compress_ops * f2fs_cops [COMPRESS_MAX ] = {
295
455
#ifdef CONFIG_F2FS_FS_LZO
296
456
& f2fs_lzo_ops ,
@@ -302,6 +462,11 @@ static const struct f2fs_compress_ops *f2fs_cops[COMPRESS_MAX] = {
302
462
#else
303
463
NULL ,
304
464
#endif
465
+ #ifdef CONFIG_F2FS_FS_ZSTD
466
+ & f2fs_zstd_ops ,
467
+ #else
468
+ NULL ,
469
+ #endif
305
470
};
306
471
307
472
bool f2fs_is_compress_backend_ready (struct inode * inode )
0 commit comments