Hi

On Wed, 27 May 2026, Leonid Ravich wrote:

> +/*
> + * Multi-data-unit variant of crypt_convert_block_skcipher.  Submits all
> + * remaining sectors of the current bio in one skcipher request whose
> + * data_unit_size is cc->sector_size.  The cipher walks the IV between
> + * data units (see crypto_skcipher_set_data_unit_size()).
> + *
> + * Returns the same set of values as crypt_convert_block_skcipher:
> + *   0 on synchronous success (full chunk processed),
> + *   -EINPROGRESS / -EBUSY on asynchronous dispatch,
> + *   -EAGAIN if the per-bio scatterlist allocation cannot be made.  The
> + *           caller MUST disable multi-data-unit batching for the rest
> + *           of this bio and re-enter the per-sector path, which uses
> + *           only mempool reserves and is therefore safe even on the
> + *           swap-out-to-dm-crypt path under total memory exhaustion.
> + *   negative errno otherwise.
> + *
> + * On success the bio iterators have been advanced by the chunk size.
> + *
> + * Walks the bio with __bio_for_each_bvec so that multi-page folios
> + * produce one scatterlist entry rather than N (one per PAGE_SIZE).
> + */
> +static int crypt_convert_block_skcipher_multi(struct crypt_config *cc,
> +                                           struct convert_context *ctx,
> +                                           struct skcipher_request *req,
> +                                           unsigned int *out_processed)
> +{
> +     const unsigned int sector_size = cc->sector_size;
> +     const gfp_t gfp = GFP_NOIO | __GFP_NORETRY | __GFP_NOWARN;
> +     unsigned int total_in = ctx->iter_in.bi_size;
> +     unsigned int total_out = ctx->iter_out.bi_size;
> +     unsigned int total = min(total_in, total_out);
> +     unsigned int n_sectors;
> +     unsigned int n_sg_in = 0, n_sg_out = 0;
> +     struct dm_crypt_request *dmreq = dmreq_of_req(cc, req);
> +     struct scatterlist *sg_in = NULL, *sg_out = NULL;
> +     struct bvec_iter iter_in, iter_out;
> +     struct bio_vec bv;
> +     u8 *iv, *org_iv;
> +     int r;
> +
> +     if (unlikely(total < sector_size))
> +             return -EIO;
> +     n_sectors = total / sector_size;
> +     total = n_sectors * sector_size;

Division is slow. There should be this:
        n_sectors = total >> cc->sector_shift;


> +     if (unlikely(total < sector_size))
> +             return -EIO;

The condition total < sector_size is true if total is small but it goes 
through if total is bigger but unaligned. I think that it should be:

        if (unlikely(total & (sector_size - 1)))
                return -EIO;

(then, we can drop the line "total = n_sectors * sector_size")

ctx->iter_in.bi_size is supposed to be the same as ctx->iter_out.bi_size, 
so do we really need total = min(total_in, total_out)? Should it instead 
warn if they differ? (where the warning would indicate a bug in the code)

Mikulas


Reply via email to