On Mon, 16 Mar 2026, Keith Busch wrote:
> From: Keith Busch <[email protected]>
>
> In the unlikely case where the base bio uses a highly fragmented vector,
> the four inline scatterlist elements may not be enough, so allocate a
> temporary scatterlist when needed.
>
> Signed-off-by: Keith Busch <[email protected]>
> ---
> +static int crypt_build_sgl(struct crypt_config *cc, struct scatterlist **psg,
> struct bvec_iter *iter, struct bio *bio,
> int max_segs)
> {
> unsigned int bytes = cc->sector_size;
> + struct scatterlist *sg = *psg;
> struct bvec_iter tmp = *iter;
> int segs, i = 0;
>
> bio_advance_iter(bio, &tmp, bytes);
> segs = tmp.bi_idx - iter->bi_idx + !!tmp.bi_bvec_done;
> - if (segs > max_segs)
> - return -EIO;
> + if (segs > max_segs) {
> + sg = kmalloc_array(segs, sizeof(struct scatterlist), GFP_NOIO);
> + if (!sg)
> + return -ENOMEM;
> + }
>
> sg_init_table(sg, segs);
> do {
GFP_NOIO allocations may be unavailable when you are swapping to the
dm-crypt device and the machine runs out of memory temporarily. There
should be:
sg = kmalloc_array(segs, sizeof(struct scatterlist), GFP_NOWAIT |
__GFP_NOMEMALLOC);
and if it fails, allocate "sg" from a mempool with GFP_NOIO (mempool_alloc
with GFP_NOIO can't fail, it waits until someone frees some entries into
the mempool).
As there are two consecutive calls to crypt_build_sgl, there should be two
mempools, one for the first call and the second for the second call. The
mempools should be sized for the worst possible fragmentation.
Mikulas