[PATCHv2 1/4] block: bio-integrity: directly map user buffers
Pankaj Raghav
p.raghav at samsung.com
Mon Oct 30 07:40:47 PDT 2023
> +static int bio_integrity_copy_user(struct bio *bio, struct bio_vec *bvec,
> + int nr_vecs, unsigned int len,
> + unsigned int direction, u32 seed)
> +{
> + struct bio_integrity_payload *bip;
> + struct bio_vec *copy_vec = NULL;
> + struct iov_iter iter;
> + void *buf;
> + int ret;
> +
> + /* if bvec is on the stack, we need to allocate a copy for the completion */
> + if (nr_vecs <= UIO_FASTIOV) {
> + copy_vec = kcalloc(sizeof(*bvec), nr_vecs, GFP_KERNEL);
> + if (!copy_vec)
> + return -ENOMEM;
> + memcpy(copy_vec, bvec, nr_vecs * sizeof(*bvec));
> + }
> +
> + buf = kmalloc(len, GFP_KERNEL);
> + if (!buf)
> + goto free_copy;
ret is not set to -ENOMEM here.
> +
> + if (direction == ITER_SOURCE) {
> + iov_iter_bvec(&iter, direction, bvec, nr_vecs, len);
> + if (!copy_from_iter_full(buf, len, &iter)) {
> + ret = -EFAULT;
> + goto free_buf;
> + }
> + } else {
> + memset(buf, 0, len);
> + }
> +
> + /*
> + * We just need one vec for this bip, but we need to preserve the
> + * number of vecs in the user bvec for the completion handling, so use
> + * nr_vecs.
> + */
> + bip = bio_integrity_alloc(bio, GFP_KERNEL, nr_vecs);
> + if (IS_ERR(bip)) {
> + ret = PTR_ERR(bip);
> + goto free_buf;
> + }
> +
> + ret = bio_integrity_add_page(bio, virt_to_page(buf), len,
> + offset_in_page(buf));
> + if (ret != len) {
> + ret = -ENOMEM;
> + goto free_bip;
> + }
> +
> + bip->bip_flags |= BIP_INTEGRITY_USER;
> + bip->copy_vec = copy_vec ?: bvec;
> + return 0;
> +free_bip:
> + bio_integrity_free(bio);
> +free_buf:
> + kfree(buf);
> +free_copy:
> + kfree(copy_vec);
> + return ret;
> +}
> +
More information about the Linux-nvme
mailing list