fs/btrfs/zlib.c

Source file repositories/reference/linux-study-clean/fs/btrfs/zlib.c

File Facts

System
Linux kernel
Corpus path
fs/btrfs/zlib.c
Extension
.c
Size
14401 bytes
Lines
515
Domain
Core OS
Bucket
VFS And Filesystem Core
Inferred role
Core OS: implementation source
Status
source implementation candidate

Why This File Exists

Core operating-system implementation surface: boot, tasks, memory, VFS, syscall-facing interfaces, synchronization, credentials, and isolation.

Dependency Surface

Detected Declarations

Annotated Snippet

struct workspace {
	z_stream strm;
	char *buf;
	unsigned int buf_size;
	struct list_head list;
	int level;
};

struct list_head *zlib_get_workspace(struct btrfs_fs_info *fs_info, unsigned int level)
{
	struct list_head *ws = btrfs_get_workspace(fs_info, BTRFS_COMPRESS_ZLIB, level);
	struct workspace *workspace = list_entry(ws, struct workspace, list);

	workspace->level = level;

	return ws;
}

void zlib_free_workspace(struct list_head *ws)
{
	struct workspace *workspace = list_entry(ws, struct workspace, list);

	kvfree(workspace->strm.workspace);
	kfree(workspace->buf);
	kfree(workspace);
}

/*
 * For s390 hardware acceleration, the buffer size should be at least
 * ZLIB_DFLTCC_BUF_SIZE to achieve the best performance.
 *
 * But if bs > ps we can have large enough folios that meet the s390 hardware
 * handling.
 */
static bool need_special_buffer(struct btrfs_fs_info *fs_info)
{
	if (!zlib_deflate_dfltcc_enabled())
		return false;
	if (btrfs_min_folio_size(fs_info) >= ZLIB_DFLTCC_BUF_SIZE)
		return false;
	return true;
}

struct list_head *zlib_alloc_workspace(struct btrfs_fs_info *fs_info, unsigned int level)
{
	struct workspace *workspace;
	int workspacesize;

	workspace = kzalloc_obj(*workspace);
	if (!workspace)
		return ERR_PTR(-ENOMEM);

	workspacesize = max(zlib_deflate_workspacesize(MAX_WBITS, MAX_MEM_LEVEL),
			zlib_inflate_workspacesize());
	workspace->strm.workspace = kvzalloc(workspacesize, GFP_KERNEL | __GFP_NOWARN);
	workspace->level = level;
	workspace->buf = NULL;
	if (need_special_buffer(fs_info)) {
		workspace->buf = kmalloc(ZLIB_DFLTCC_BUF_SIZE,
					 __GFP_NOMEMALLOC | __GFP_NORETRY |
					 __GFP_NOWARN | GFP_NOIO);
		workspace->buf_size = ZLIB_DFLTCC_BUF_SIZE;
	}
	if (!workspace->buf) {
		workspace->buf = kmalloc(fs_info->sectorsize, GFP_KERNEL);
		workspace->buf_size = fs_info->sectorsize;
	}
	if (!workspace->strm.workspace || !workspace->buf)
		goto fail;

	INIT_LIST_HEAD(&workspace->list);

	return &workspace->list;
fail:
	zlib_free_workspace(&workspace->list);
	return ERR_PTR(-ENOMEM);
}

/*
 * Helper for S390x with hardware zlib compression support.
 *
 * That hardware acceleration requires a buffer size larger than a single page
 * to get ideal performance, thus we need to do the memory copy rather than
 * use the page cache directly as input buffer.
 */
static int copy_data_into_buffer(struct address_space *mapping,
				 struct workspace *workspace, u64 filepos,
				 unsigned long length)
{
	u64 cur = filepos;

Annotation

Implementation Notes