kernel/liveupdate/kho_block.c

Source file repositories/reference/linux-study-clean/kernel/liveupdate/kho_block.c

File Facts

System
Linux kernel
Corpus path
kernel/liveupdate/kho_block.c
Extension
.c
Size
10786 bytes
Lines
417
Domain
Core OS
Bucket
Scheduler, Processes, Timers, Sync, And Syscalls
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

if (count++ >= KHO_MAX_BLOCKS) {
			pr_err("Block set is corrupted\n");
			return true;
		}

		if (!fast->next)
			break;

		fast = phys_to_virt(fast->next);
		if (!fast->next)
			break;

		fast = phys_to_virt(fast->next);
		slow = phys_to_virt(slow->next);

		if (slow == fast) {
			pr_err("Block set is corrupted\n");
			return true;
		}
	}

	return false;
}

/**
 * kho_block_set_restore - Restore a block set from a physical address.
 * @bs:      The block set to restore.
 * @head_pa: Physical address of the first block header.
 *
 * Restores a serialized block set from a given physical address. The caller is
 * responsible for ensuring that the block set @bs has been allocated and
 * initialized prior to calling this function.
 *
 * Return: 0 on success, or a negative errno on failure.
 */
int kho_block_set_restore(struct kho_block_set *bs, u64 head_pa)
{
	struct kho_block_header_ser *ser;
	u64 next_pa = head_pa;
	int err;

	/* Restored block sets use size from the previous kernel */
	bs->incoming = true;
	if (!head_pa)
		return 0;

	bs->head_pa = head_pa;
	if (kho_block_set_is_cyclic(bs)) {
		bs->head_pa = 0;
		return -EINVAL;
	}

	while (next_pa) {
		ser = phys_to_virt(next_pa);
		if (!ser->count || ser->count > bs->count_per_block) {
			pr_warn("Block contains invalid entry count: %llu\n",
				ser->count);
			err = -EINVAL;
			goto err_destroy;
		}
		err = kho_block_add(bs, ser);
		if (err)
			goto err_destroy;
		next_pa = ser->next;
	}

	return 0;

err_destroy:
	kho_block_set_destroy(bs);

	/* Free the remaining un-restored blocks in the physical chain */
	while (next_pa) {
		struct kho_block_header_ser *next_ser = phys_to_virt(next_pa);

		next_pa = next_ser->next;
		kho_block_free_ser(bs, next_ser);
	}
	return err;
}

/**
 * kho_block_set_destroy - Destroy all blocks in a block set.
 * @bs:          The block set.
 */
void kho_block_set_destroy(struct kho_block_set *bs)
{
	struct kho_block *block, *tmp;

	list_for_each_entry_safe(block, tmp, &bs->blocks, list) {

Annotation

Implementation Notes