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


Reply via email to