include/crypto/scatterwalk.h

Source file repositories/reference/linux-study-clean/include/crypto/scatterwalk.h

File Facts

System
Linux kernel
Corpus path
include/crypto/scatterwalk.h
Extension
.h
Size
8030 bytes
Lines
257
Domain
Repository Root And Misc
Bucket
include
Inferred role
Repository Root And Misc: implementation source
Status
source implementation candidate

Why This File Exists

Top-level or miscellaneous repository surface. Use this as map coverage unless a later manual pass promotes the file into a deeper subsystem dossier.

Dependency Surface

Detected Declarations

Annotated Snippet

#ifndef _CRYPTO_SCATTERWALK_H
#define _CRYPTO_SCATTERWALK_H

#include <crypto/algapi.h>

#include <linux/highmem.h>
#include <linux/mm.h>
#include <linux/scatterlist.h>

static inline void scatterwalk_crypto_chain(struct scatterlist *head,
					    struct scatterlist *sg, int num)
{
	if (sg)
		sg_chain(head, num, sg);
	else
		sg_mark_end(head);
}

static inline void scatterwalk_start(struct scatter_walk *walk,
				     struct scatterlist *sg)
{
	walk->sg = sg;
	walk->offset = sg->offset;
}

/*
 * This is equivalent to scatterwalk_start(walk, sg) followed by
 * scatterwalk_skip(walk, pos).
 */
static inline void scatterwalk_start_at_pos(struct scatter_walk *walk,
					    struct scatterlist *sg,
					    unsigned int pos)
{
	while (pos > sg->length) {
		pos -= sg->length;
		sg = sg_next(sg);
	}
	walk->sg = sg;
	walk->offset = sg->offset + pos;
}

static inline unsigned int scatterwalk_clamp(struct scatter_walk *walk,
					     unsigned int nbytes)
{
	unsigned int len_this_sg;
	unsigned int limit;

	if (walk->offset >= walk->sg->offset + walk->sg->length)
		scatterwalk_start(walk, sg_next(walk->sg));
	len_this_sg = walk->sg->offset + walk->sg->length - walk->offset;

	/*
	 * HIGHMEM case: the page may have to be mapped into memory.  To avoid
	 * the complexity of having to map multiple pages at once per sg entry,
	 * clamp the returned length to not cross a page boundary.
	 *
	 * !HIGHMEM case: no mapping is needed; all pages of the sg entry are
	 * already mapped contiguously in the kernel's direct map.  For improved
	 * performance, allow the walker to return data segments that cross a
	 * page boundary.  Do still cap the length to PAGE_SIZE, since some
	 * users rely on that to avoid disabling preemption for too long when
	 * using SIMD.  It's also needed for when skcipher_walk uses a bounce
	 * page due to the data not being aligned to the algorithm's alignmask.
	 */
	if (IS_ENABLED(CONFIG_HIGHMEM))
		limit = PAGE_SIZE - offset_in_page(walk->offset);
	else
		limit = PAGE_SIZE;

	return min3(nbytes, len_this_sg, limit);
}

/*
 * Create a scatterlist that represents the remaining data in a walk.  Uses
 * chaining to reference the original scatterlist, so this uses at most two
 * entries in @sg_out regardless of the number of entries in the original list.
 * Assumes that sg_init_table() was already done.
 */
static inline void scatterwalk_get_sglist(struct scatter_walk *walk,
					  struct scatterlist sg_out[2])
{
	if (walk->offset >= walk->sg->offset + walk->sg->length)
		scatterwalk_start(walk, sg_next(walk->sg));
	sg_set_page(sg_out, sg_page(walk->sg),
		    walk->sg->offset + walk->sg->length - walk->offset,
		    walk->offset);
	scatterwalk_crypto_chain(sg_out, sg_next(walk->sg), 2);
}

static inline void scatterwalk_map(struct scatter_walk *walk)

Annotation

Implementation Notes