| /* SPDX-License-Identifier: GPL-2.0 */ | |
| /* | |
| * Copyright (c) 2026, Google LLC. | |
| * Pasha Tatashin <[email protected]> | |
| */ | |
| #ifndef _LINUX_KHO_BLOCK_H | |
| #define _LINUX_KHO_BLOCK_H | |
| #include <linux/list.h> | |
| #include <linux/types.h> | |
| #include <linux/kho/abi/block.h> | |
| /** | |
| * struct kho_block - Internal representation of a serialization block. | |
| * @list: List head for linking blocks in memory. | |
| * @ser: Pointer to the serialized header in preserved memory. | |
| */ | |
| struct kho_block { | |
| struct list_head list; | |
| struct kho_block_header_ser *ser; | |
| }; | |
| /** | |
| * struct kho_block_set - A set of blocks containing serialized entries of the same type. | |
| * @blocks: The list of serialization blocks (struct kho_block). | |
| * @nblocks: The number of allocated serialization blocks. | |
| * @head_pa: Physical address of the first block header. | |
| * @entry_size: The size of each entry in the blocks. | |
| * @count_per_block: The maximum number of entries each block can hold. | |
| * @incoming: True if this block set was restored from the previous kernel. | |
| * | |
| * Note: Synchronization and locking are the responsibility of the caller. | |
| * The block set structure itself is not internally synchronized. | |
| */ | |
| struct kho_block_set { | |
| struct list_head blocks; | |
| long nblocks; | |
| u64 head_pa; | |
| size_t entry_size; | |
| u64 count_per_block; | |
| bool incoming; | |
| }; | |
| /** | |
| * struct kho_block_set_it - Iterator for serializing entries into blocks. | |
| * @bs: The block set being iterated. | |
| * @block: The current block. | |
| * @i: The current entry index within @block. | |
| */ | |
| struct kho_block_set_it { | |
| struct kho_block_set *bs; | |
| struct kho_block *block; | |
| u64 i; | |
| }; | |
| /** | |
| * KHO_BLOCK_SET_INIT - Initialize a static kho_block_set. | |
| * @_name: Name of the kho_block_set variable. | |
| * @_entry_size: The size of each entry in the block set. | |
| */ | |
| #define KHO_BLOCK_SET_INIT(_name, _entry_size) { \ | |
| .blocks = LIST_HEAD_INIT((_name).blocks), \ | |
| .entry_size = _entry_size, \ | |
| .count_per_block = (KHO_BLOCK_SIZE - \ | |
| sizeof(struct kho_block_header_ser)) / \ | |
| (_entry_size), \ | |
| } | |
| void kho_block_set_init(struct kho_block_set *bs, size_t entry_size); | |
| int kho_block_set_grow(struct kho_block_set *bs, u64 count); | |
| void kho_block_set_shrink(struct kho_block_set *bs, u64 count); | |
| int kho_block_set_restore(struct kho_block_set *bs, u64 head_pa); | |
| void kho_block_set_destroy(struct kho_block_set *bs); | |
| void kho_block_set_clear(struct kho_block_set *bs); | |
| /** | |
| * kho_block_set_head_pa - Get the physical address of the first block header. | |
| * @bs: The block set. | |
| * | |
| * Return: The physical address of the first block header, or 0 if empty. | |
| */ | |
| static inline u64 kho_block_set_head_pa(struct kho_block_set *bs) | |
| { | |
| return bs->head_pa; | |
| } | |
| /** | |
| * kho_block_set_is_empty - Check if the block set has no allocated blocks. | |
| * @bs: The block set. | |
| * | |
| * Return: True if there are no blocks in the set, false otherwise. | |
| */ | |
| static inline bool kho_block_set_is_empty(struct kho_block_set *bs) | |
| { | |
| return list_empty(&bs->blocks); | |
| } | |
| void kho_block_set_it_init(struct kho_block_set_it *it, struct kho_block_set *bs); | |
| void *kho_block_set_it_reserve_entry(struct kho_block_set_it *it); | |
| void *kho_block_set_it_read_entry(struct kho_block_set_it *it); | |
| void *kho_block_set_it_prev(struct kho_block_set_it *it); | |
| #endif /* _LINUX_KHO_BLOCK_H */ |