Subject: Re: [PATCH v9 vfio 4/7] vfio/pds: Add VFIO live migration support

From: Jason Gunthorpe <[email-masked]>
Date: Thu, 4 May 2023 14:50:33 -0300

On Fri, Apr 21, 2023 at 06:06:39PM -0700, Brett Creeley wrote:

> +static int
> +pds_vfio_dma_map_lm_file(struct device *dev, enum dma_data_direction dir,
> +			 struct pds_vfio_lm_file *lm_file)
> +{
> +	struct pds_lm_sg_elem *sgl, *sge;
> +	struct scatterlist *sg;
> +	dma_addr_t sgl_addr;
> +	size_t sgl_size;
> +	int err;
> +	int i;
> +
> +	if (!lm_file)
> +		return -EINVAL;
> +
> +	/* dma map file pages */
> +	err = dma_map_sgtable(dev, &lm_file->sg_table, dir, 0);
> +	if (err)
> +		return err;
> +
> +	lm_file->num_sge = lm_file->sg_table.nents;
> +
> +	/* alloc sgl */
> +	sgl_size = lm_file->num_sge * sizeof(struct pds_lm_sg_elem);
> +	sgl = kzalloc(sgl_size, GFP_KERNEL);
> +	if (!sgl) {
> +		err = -ENOMEM;
> +		goto err_alloc_sgl;
> +	}
> +
> +	sgl_addr = dma_map_single(dev, sgl, sgl_size, DMA_TO_DEVICE);
> +	if (dma_mapping_error(dev, sgl_addr)) {
> +		err = -EIO;
> +		goto err_map_sgl;
> +	}
> +
> +	lm_file->sgl = sgl;
> +	lm_file->sgl_addr = sgl_addr;
> +
> +	/* fill sgl */
> +	sge = sgl;
> +	for_each_sgtable_dma_sg(&lm_file->sg_table, sg, i) {
> +		sge->addr = cpu_to_le64(sg_dma_address(sg));
> +		sge->len  = cpu_to_le32(sg_dma_len(sg));
> +		dev_dbg(dev, "addr = %llx, len = %u\n", sge->addr, sge->len);
> +		sge++;
> +	}

This sequence is in the wrong order, the dma_map_single() has to be
after the data is written to the memory as it synchronizes the caches
on some arches

> +
> +	return 0;
> +
> +err_map_sgl:
> +	kfree(sgl);
> +err_alloc_sgl:
> +	dma_unmap_sgtable(dev, &lm_file->sg_table, dir, 0);
> +	return err;

And why is the goto error unwind in a messed up order? Error unwinds
should always be strictly in the opposite order of the success
path. Check them all when you are fixing the "come from" notation

Jason