crypto/scompress.c

Source file repositories/reference/linux-study-clean/crypto/scompress.c

File Facts

System
Linux kernel
Corpus path
crypto/scompress.c
Extension
.c
Size
9309 bytes
Lines
403
Domain
Kernel Services
Bucket
crypto
Inferred role
Kernel Services: exported/initcall integration point
Status
integration implementation candidate

Why This File Exists

Shared kernel service surface used by multiple subsystems, including helpers, cryptography, virtualization support, and async I/O infrastructure.

Dependency Surface

Detected Declarations

Annotated Snippet

struct scomp_scratch {
	spinlock_t	lock;
	union {
		void	*src __guarded_by(&lock);
		unsigned long saddr __guarded_by(&lock);
	};
};

static DEFINE_PER_CPU(struct scomp_scratch, scomp_scratch) = {
	.lock = __SPIN_LOCK_UNLOCKED(scomp_scratch.lock),
};

static const struct crypto_type crypto_scomp_type;
static DEFINE_MUTEX(scomp_lock);
static int scomp_scratch_users __guarded_by(&scomp_lock);

static cpumask_t scomp_scratch_want;
static void scomp_scratch_workfn(struct work_struct *work);
static DECLARE_WORK(scomp_scratch_work, scomp_scratch_workfn);

static int __maybe_unused crypto_scomp_report(
	struct sk_buff *skb, struct crypto_alg *alg)
{
	struct crypto_report_comp rscomp = {
		.type = "scomp",
	};

	return nla_put(skb, CRYPTOCFGA_REPORT_COMPRESS,
		       sizeof(rscomp), &rscomp);
}

static void __maybe_unused crypto_scomp_show(struct seq_file *m,
					     struct crypto_alg *alg)
{
	seq_puts(m, "type         : scomp\n");
}

static void crypto_scomp_free_scratches(void)
	__context_unsafe(/* frees @scratch */)
{
	struct scomp_scratch *scratch;
	int i;

	for_each_possible_cpu(i) {
		scratch = per_cpu_ptr(&scomp_scratch, i);

		free_page(scratch->saddr);
		scratch->src = NULL;
	}
}

static int scomp_alloc_scratch(struct scomp_scratch *scratch, int cpu)
{
	int node = cpu_to_node(cpu);
	struct page *page;

	page = alloc_pages_node(node, GFP_KERNEL, 0);
	if (!page)
		return -ENOMEM;
	spin_lock_bh(&scratch->lock);
	scratch->src = page_address(page);
	spin_unlock_bh(&scratch->lock);
	return 0;
}

static void scomp_scratch_workfn(struct work_struct *work)
{
	int cpu;

	for_each_cpu(cpu, &scomp_scratch_want) {
		struct scomp_scratch *scratch;

		scratch = per_cpu_ptr(&scomp_scratch, cpu);
		if (context_unsafe(scratch->src))
			continue;
		if (scomp_alloc_scratch(scratch, cpu))
			break;

		cpumask_clear_cpu(cpu, &scomp_scratch_want);
	}
}

static int crypto_scomp_alloc_scratches(void)
	__context_unsafe(/* allocates @scratch */)
{
	unsigned int i = cpumask_first(cpu_possible_mask);
	struct scomp_scratch *scratch;

	scratch = per_cpu_ptr(&scomp_scratch, i);
	return scomp_alloc_scratch(scratch, i);

Annotation

Implementation Notes