Skip to content

Commit

Permalink
vfio/mbochs: Fix missing error unwind of mbochs_used_mbytes
Browse files Browse the repository at this point in the history
[ Upstream commit de5494a ]

Convert mbochs to use an atomic scheme for this like mtty was changed
into. The atomic fixes various race conditions with probing. Add the
missing error unwind. Also add the missing kfree of mdev_state->pages.

Fixes: 681c161 ("vfio/mbochs: Convert to use vfio_register_group_dev()")
Reported-by: Cornelia Huck <cohuck@redhat.com>
Co-developed-by: Alex Williamson <alex.williamson@redhat.com>
Reviewed-by: Christoph Hellwig <hch@lst.de>
Signed-off-by: Jason Gunthorpe <jgg@nvidia.com>
Reviewed-by: Cornelia Huck <cohuck@redhat.com>
Link: https://lore.kernel.org/r/2-v4-9ea22c5e6afb+1adf-vfio_reflck_jgg@nvidia.com
Signed-off-by: Alex Williamson <alex.williamson@redhat.com>
Signed-off-by: Sasha Levin <sashal@kernel.org>
  • Loading branch information
jgunthorpe authored and gregkh committed Sep 18, 2021
1 parent 1a18fcb commit 983add4
Showing 1 changed file with 15 additions and 9 deletions.
24 changes: 15 additions & 9 deletions samples/vfio-mdev/mbochs.c
Expand Up @@ -129,7 +129,7 @@ static dev_t mbochs_devt;
static struct class *mbochs_class;
static struct cdev mbochs_cdev;
static struct device mbochs_dev;
static int mbochs_used_mbytes;
static atomic_t mbochs_avail_mbytes;
static const struct vfio_device_ops mbochs_dev_ops;

struct vfio_region_info_ext {
Expand Down Expand Up @@ -507,18 +507,22 @@ static int mbochs_reset(struct mdev_state *mdev_state)

static int mbochs_probe(struct mdev_device *mdev)
{
int avail_mbytes = atomic_read(&mbochs_avail_mbytes);
const struct mbochs_type *type =
&mbochs_types[mdev_get_type_group_id(mdev)];
struct device *dev = mdev_dev(mdev);
struct mdev_state *mdev_state;
int ret = -ENOMEM;

if (type->mbytes + mbochs_used_mbytes > max_mbytes)
return -ENOMEM;
do {
if (avail_mbytes < type->mbytes)
return -ENOSPC;
} while (!atomic_try_cmpxchg(&mbochs_avail_mbytes, &avail_mbytes,
avail_mbytes - type->mbytes));

mdev_state = kzalloc(sizeof(struct mdev_state), GFP_KERNEL);
if (mdev_state == NULL)
return -ENOMEM;
goto err_avail;
vfio_init_group_dev(&mdev_state->vdev, &mdev->dev, &mbochs_dev_ops);

mdev_state->vconfig = kzalloc(MBOCHS_CONFIG_SPACE_SIZE, GFP_KERNEL);
Expand Down Expand Up @@ -549,26 +553,26 @@ static int mbochs_probe(struct mdev_device *mdev)
mbochs_create_config_space(mdev_state);
mbochs_reset(mdev_state);

mbochs_used_mbytes += type->mbytes;

ret = vfio_register_group_dev(&mdev_state->vdev);
if (ret)
goto err_mem;
dev_set_drvdata(&mdev->dev, mdev_state);
return 0;

err_mem:
kfree(mdev_state->pages);
kfree(mdev_state->vconfig);
kfree(mdev_state);
err_avail:
atomic_add(type->mbytes, &mbochs_avail_mbytes);
return ret;
}

static void mbochs_remove(struct mdev_device *mdev)
{
struct mdev_state *mdev_state = dev_get_drvdata(&mdev->dev);

mbochs_used_mbytes -= mdev_state->type->mbytes;
vfio_unregister_group_dev(&mdev_state->vdev);
atomic_add(mdev_state->type->mbytes, &mbochs_avail_mbytes);
kfree(mdev_state->pages);
kfree(mdev_state->vconfig);
kfree(mdev_state);
Expand Down Expand Up @@ -1355,7 +1359,7 @@ static ssize_t available_instances_show(struct mdev_type *mtype,
{
const struct mbochs_type *type =
&mbochs_types[mtype_get_type_group_id(mtype)];
int count = (max_mbytes - mbochs_used_mbytes) / type->mbytes;
int count = atomic_read(&mbochs_avail_mbytes) / type->mbytes;

return sprintf(buf, "%d\n", count);
}
Expand Down Expand Up @@ -1437,6 +1441,8 @@ static int __init mbochs_dev_init(void)
{
int ret = 0;

atomic_set(&mbochs_avail_mbytes, max_mbytes);

ret = alloc_chrdev_region(&mbochs_devt, 0, MINORMASK + 1, MBOCHS_NAME);
if (ret < 0) {
pr_err("Error: failed to register mbochs_dev, err: %d\n", ret);
Expand Down

0 comments on commit 983add4

Please sign in to comment.