// SPDX-License-Identifier: GPL-2.0
/*
* f2fs compress support
*
* Copyright (c) 2019 Chao Yu <chao@kernel.org>
*/
#include <linux/fs.h>
#include <linux/f2fs_fs.h>
#include <linux/writeback.h>
#include <linux/backing-dev.h>
#include <linux/lzo.h>
#include <linux/lz4.h>
#include "f2fs.h"
#include "node.h"
#include <trace/events/f2fs.h>
struct f2fs_compress_ops {
int (*init_compress_ctx)(struct compress_ctx *cc);
void (*destroy_compress_ctx)(struct compress_ctx *cc);
int (*compress_pages)(struct compress_ctx *cc);
int (*decompress_pages)(struct decompress_io_ctx *dic);
};
static unsigned int offset_in_cluster(struct compress_ctx *cc, pgoff_t index)
{
return index & (cc->cluster_size - 1);
}
static pgoff_t cluster_idx(struct compress_ctx *cc, pgoff_t index)
{
return index >> cc->log_cluster_size;
}
static pgoff_t start_idx_of_cluster(struct compress_ctx *cc)
{
return cc->cluster_idx << cc->log_cluster_size;
}
bool f2fs_is_compressed_page(struct page *page)
{
if (!PagePrivate(page))
return false;
if (!page_private(page))
return false;
if (IS_ATOMIC_WRITTEN_PAGE(page) || IS_DUMMY_WRITTEN_PAGE(page))
return false;
f2fs_bug_on(F2FS_M_SB(page->mapping),
*((u32 *)page_private(page)) != F2FS_COMPRESSED_PAGE_MAGIC);
return true;
}
static void f2fs_set_compressed_page(struct page *page,
struct inode *inode, pgoff_t index, void *data, refcount_t *r)
{
SetPagePrivate(page);
set_page_private(page, (unsigned long)data);
/* i_crypto_info and iv index */
page->index = index;
page->mapping = inode->i_mapping;
if (r)
refcount_inc(r);
}
static void f2fs_put_compressed_page(struct page *page)
{
set_page_private(page, (unsigned long)NULL);
ClearPagePrivate(page);
page->mapping = NULL;
unlock_page(page);
put_page(page);
}
static void f2fs_drop_rpages(struct compress_ctx *cc, int len, bool unlock)
{
int i;
for (i = 0; i < len; i++) {
if (!cc->rpages[i])
continue;
if (unlock)
unlock_page(cc->rpages[i]);
else
put_page(cc->rpages[i]);
}
}
static void f2fs_put_rpages(struct compress_ctx *cc)
{
f2fs_drop_rpages(cc, cc->cluster_size, false);
}
static void f2fs_unlock_rpages(struct compress_ctx *cc, int len)
{
f2fs_drop_rpages(cc, len, true);
}
static void f2fs_put_rpages_mapping(struct compress_ctx *cc,
struct address_space *mapping,
pgoff_t start, int len)