blob: 9af11f392f97c72c34e21d56b68463f3cdc69bc1 [file] [log] [blame]
/* SPDX-License-Identifier: GPL-2.0 */
/*
* Author: Vitaly Wool <vitaly.wool@konsulko.com>
* Copyright (C) 2025, Konsulko AB.
*/
#ifndef __ZBLOCK_H__
#define __ZBLOCK_H__
#include <linux/mm.h>
#include <linux/rbtree.h>
#include <linux/types.h>
#define SLOT_FREE 0
#define BIT_SLOT_OCCUPIED 0
#define BIT_SLOT_MAPPED 1
#if PAGE_SIZE == 0x1000
/* max 128 slots per block, max table size 32 */
#define SLOT_BITS 7
#elif PAGE_SIZE == 0x4000
/* max 256 slots per block, max table size 64 */
#define SLOT_BITS 8
#else
#warning This PAGE_SIZE is not quite supported yet
#define SLOT_BITS 8
#endif
#define MAX_SLOTS (1 << SLOT_BITS)
#define SLOT_MASK ((0x1UL << SLOT_BITS) - 1)
#define ZBLOCK_HEADER_SIZE round_up(sizeof(struct zblock_block), sizeof(long))
#define BLOCK_DATA_SIZE(order) ((PAGE_SIZE << order) - ZBLOCK_HEADER_SIZE)
#define SLOT_SIZE(nslots, order) (round_down((BLOCK_DATA_SIZE(order) / nslots), sizeof(long)))
/**
* struct zblock_block - block metadata
* Block consists of several (1/2/4/8) pages and contains fixed
* integer number of slots for allocating compressed pages.
*
* free_slots: number of free slots in the block
* slot_info: contains data about free/occupied slots
*/
struct zblock_block {
struct list_head link;
DECLARE_BITMAP(slot_info, 1 << SLOT_BITS);
u32 free_slots;
};
/**
* struct block_desc - general metadata for block lists
* Each block list stores only blocks of corresponding type which means
* that all blocks in it have the same number and size of slots.
* All slots are aligned to size of long.
*
* slot_size: size of slot for this list
* slots_per_block: number of slots per block for this list
* order: order for __get_free_pages
*/
struct block_desc {
unsigned int slot_size;
unsigned short slots_per_block;
unsigned short order;
};
struct block_desc_node {
struct rb_node node;
unsigned int this_slot_size;
unsigned int next_slot_size;
unsigned int block_idx;
};
static const struct block_desc block_desc[] = {
#if PAGE_SIZE == 0x1000
{ SLOT_SIZE(63, 0), 63, 0 },
{ SLOT_SIZE(32, 0), 32, 0 },
{ SLOT_SIZE(21, 0), 21, 0 },
{ SLOT_SIZE(15, 0), 15, 0 },
{ SLOT_SIZE(12, 0), 12, 0 },
{ SLOT_SIZE(10, 0), 10, 0 },
{ SLOT_SIZE(9, 0), 9, 0 },
{ SLOT_SIZE(8, 0), 8, 0 },
{ SLOT_SIZE(29, 2), 29, 2 },
{ SLOT_SIZE(13, 1), 13, 1 },
{ SLOT_SIZE(6, 0), 6, 0 },
{ SLOT_SIZE(11, 1), 11, 1 },
{ SLOT_SIZE(5, 0), 5, 0 },
{ SLOT_SIZE(9, 1), 9, 1 },
{ SLOT_SIZE(8, 1), 8, 1 },
{ SLOT_SIZE(29, 3), 29, 3 },
{ SLOT_SIZE(13, 2), 13, 2 },
{ SLOT_SIZE(12, 2), 12, 2 },
{ SLOT_SIZE(11, 2), 11, 2 },
{ SLOT_SIZE(10, 2), 10, 2 },
{ SLOT_SIZE(9, 2), 9, 2 },
{ SLOT_SIZE(17, 3), 17, 3 },
{ SLOT_SIZE(8, 2), 8, 2 },
{ SLOT_SIZE(15, 3), 15, 3 },
{ SLOT_SIZE(14, 3), 14, 3 },
{ SLOT_SIZE(13, 3), 13, 3 },
{ SLOT_SIZE(6, 2), 6, 2 },
{ SLOT_SIZE(11, 3), 11, 3 },
{ SLOT_SIZE(10, 3), 10, 3 },
{ SLOT_SIZE(9, 3), 9, 3 },
{ SLOT_SIZE(4, 2), 4, 2 },
#else
{ SLOT_SIZE(255, 0), 255, 0 },
{ SLOT_SIZE(185, 0), 185, 0 },
{ SLOT_SIZE(145, 0), 145, 0 },
{ SLOT_SIZE(113, 0), 113, 0 },
{ SLOT_SIZE(92, 0), 92, 0 },
{ SLOT_SIZE(75, 0), 75, 0 },
{ SLOT_SIZE(60, 0), 60, 0 },
{ SLOT_SIZE(51, 0), 51, 0 },
{ SLOT_SIZE(43, 0), 43, 0 },
{ SLOT_SIZE(37, 0), 37, 0 },
{ SLOT_SIZE(32, 0), 32, 0 },
{ SLOT_SIZE(27, 0), 27, 0 },
{ SLOT_SIZE(23, 0), 23, 0 },
{ SLOT_SIZE(19, 0), 19, 0 },
{ SLOT_SIZE(17, 0), 17, 0 },
{ SLOT_SIZE(15, 0), 15, 0 },
{ SLOT_SIZE(13, 0), 13, 0 },
{ SLOT_SIZE(11, 0), 11, 0 },
{ SLOT_SIZE(10, 0), 10, 0 },
{ SLOT_SIZE(9, 0), 9, 0 },
{ SLOT_SIZE(8, 0), 8, 0 },
{ SLOT_SIZE(15, 1), 15, 1 },
{ SLOT_SIZE(14, 1), 14, 1 },
{ SLOT_SIZE(13, 1), 13, 1 },
{ SLOT_SIZE(12, 1), 12, 1 },
{ SLOT_SIZE(11, 1), 11, 1 },
{ SLOT_SIZE(10, 1), 10, 1 },
{ SLOT_SIZE(9, 1), 9, 1 },
{ SLOT_SIZE(8, 1), 8, 1 },
{ SLOT_SIZE(15, 2), 15, 2 },
{ SLOT_SIZE(14, 2), 14, 2 },
{ SLOT_SIZE(13, 2), 13, 2 },
{ SLOT_SIZE(12, 2), 12, 2 },
{ SLOT_SIZE(11, 2), 11, 2 },
{ SLOT_SIZE(10, 2), 10, 2 },
{ SLOT_SIZE(9, 2), 9, 2 },
{ SLOT_SIZE(8, 2), 8, 2 },
{ SLOT_SIZE(7, 2), 7, 2 },
{ SLOT_SIZE(6, 2), 6, 2 },
{ SLOT_SIZE(5, 2), 5, 2 },
#endif /* PAGE_SIZE */
};
/**
* struct block_list - stores metadata of particular list
* lock: protects the list of blocks
* active_list: linked list of active (non-full) blocks
* full_list: linked list of full blocks
* block_count: total number of blocks in the list
*/
struct block_list {
spinlock_t lock;
struct list_head active_list;
struct list_head full_list;
unsigned long block_count;
};
/**
* struct zblock_pool - stores metadata for each zblock pool
* @block_lists: array of block lists
* @zpool: zpool driver
*
* This structure is allocated at pool creation time and maintains metadata
* for a particular zblock pool.
*/
struct zblock_pool {
struct block_list block_lists[ARRAY_SIZE(block_desc)];
struct zpool *zpool;
};
#endif