fs/btrfs/zstd.c

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

File Facts

System
Linux kernel
Corpus path
fs/btrfs/zstd.c
Extension
.c
Size
21221 bytes
Lines
737
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 {
	void *mem;
	size_t size;
	char *buf;
	int level;
	int req_level;
	unsigned long last_used; /* jiffies */
	struct list_head list;
	struct list_head lru_list;
	zstd_in_buffer in_buf;
	zstd_out_buffer out_buf;
	zstd_parameters params;
};

/*
 * Zstd Workspace Management
 *
 * Zstd workspaces have different memory requirements depending on the level.
 * The zstd workspaces are managed by having individual lists for each level
 * and a global lru.  Forward progress is maintained by protecting a max level
 * workspace.
 *
 * Getting a workspace is done by using the bitmap to identify the levels that
 * have available workspaces and scans up.  This lets us recycle higher level
 * workspaces because of the monotonic memory guarantee.  A workspace's
 * last_used is only updated if it is being used by the corresponding memory
 * level.  Putting a workspace involves adding it back to the appropriate places
 * and adding it back to the lru if necessary.
 *
 * A timer is used to reclaim workspaces if they have not been used for
 * ZSTD_BTRFS_RECLAIM_JIFFIES.  This helps keep only active workspaces around.
 * The upper bound is provided by the workqueue limit which is 2 (percpu limit).
 */

struct zstd_workspace_manager {
	spinlock_t lock;
	struct list_head lru_list;
	struct list_head idle_ws[ZSTD_BTRFS_MAX_LEVEL];
	unsigned long active_map;
	wait_queue_head_t wait;
	struct timer_list timer;
};

static size_t zstd_ws_mem_sizes[ZSTD_BTRFS_MAX_LEVEL];

static inline struct workspace *list_to_workspace(struct list_head *list)
{
	return container_of(list, struct workspace, list);
}

static inline int clip_level(int level)
{
	return max(0, level - 1);
}

/*
 * Timer callback to free unused workspaces.
 *
 * @t: timer
 *
 * This scans the lru_list and attempts to reclaim any workspace that hasn't
 * been used for ZSTD_BTRFS_RECLAIM_JIFFIES.
 *
 * The context is softirq and does not need the _bh locking primitives.
 */
static void zstd_reclaim_timer_fn(struct timer_list *timer)
{
	struct zstd_workspace_manager *zwsm =
		container_of(timer, struct zstd_workspace_manager, timer);
	unsigned long reclaim_threshold = jiffies - ZSTD_BTRFS_RECLAIM_JIFFIES;
	struct list_head *pos, *next;

	spin_lock(&zwsm->lock);

	if (list_empty(&zwsm->lru_list)) {
		spin_unlock(&zwsm->lock);
		return;
	}

	list_for_each_prev_safe(pos, next, &zwsm->lru_list) {
		struct workspace *victim = container_of(pos, struct workspace,
							lru_list);
		int level;

		if (time_after(victim->last_used, reclaim_threshold))
			break;

		/* workspace is in use */
		if (victim->req_level)
			continue;

Annotation

Implementation Notes