RE: [RFC 07/20] iommu/iommufd: Add iommufd_[un]bind_device()

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



> From: Jason Gunthorpe <jgg@xxxxxxxxxx>
> Sent: Wednesday, September 22, 2021 1:15 AM
> 
> On Sun, Sep 19, 2021 at 02:38:35PM +0800, Liu Yi L wrote:
> 
> > +/*
> > + * A iommufd_device object represents the binding relationship
> > + * between iommufd and device. It is created per a successful
> > + * binding request from device driver. The bound device must be
> > + * a physical device so far. Subdevice will be supported later
> > + * (with additional PASID information). An user-assigned cookie
> > + * is also recorded to mark the device in the /dev/iommu uAPI.
> > + */
> > +struct iommufd_device {
> > +	unsigned int id;
> > +	struct iommufd_ctx *ictx;
> > +	struct device *dev; /* always be the physical device */
> > +	u64 dev_cookie;
> >  };
> >
> >  static int iommufd_fops_open(struct inode *inode, struct file *filep)
> > @@ -32,15 +52,58 @@ static int iommufd_fops_open(struct inode *inode,
> struct file *filep)
> >  		return -ENOMEM;
> >
> >  	refcount_set(&ictx->refs, 1);
> > +	mutex_init(&ictx->lock);
> > +	xa_init_flags(&ictx->device_xa, XA_FLAGS_ALLOC);
> >  	filep->private_data = ictx;
> >
> >  	return ret;
> >  }
> >
> > +static void iommufd_ctx_get(struct iommufd_ctx *ictx)
> > +{
> > +	refcount_inc(&ictx->refs);
> > +}
> 
> See my earlier remarks about how to structure the lifetime logic, this
> ref isn't necessary.
> 
> > +static const struct file_operations iommufd_fops;
> > +
> > +/**
> > + * iommufd_ctx_fdget - Acquires a reference to the internal iommufd
> context.
> > + * @fd: [in] iommufd file descriptor.
> > + *
> > + * Returns a pointer to the iommufd context, otherwise NULL;
> > + *
> > + */
> > +static struct iommufd_ctx *iommufd_ctx_fdget(int fd)
> > +{
> > +	struct fd f = fdget(fd);
> > +	struct file *file = f.file;
> > +	struct iommufd_ctx *ictx;
> > +
> > +	if (!file)
> > +		return NULL;
> > +
> > +	if (file->f_op != &iommufd_fops)
> > +		return NULL;
> 
> Leaks the fdget
> 
> > +
> > +	ictx = file->private_data;
> > +	if (ictx)
> > +		iommufd_ctx_get(ictx);
> 
> Use success oriented flow
> 
> > +	fdput(f);
> > +	return ictx;
> > +}
> 
> > + */
> > +struct iommufd_device *iommufd_bind_device(int fd, struct device *dev,
> > +					   u64 dev_cookie)
> > +{
> > +	struct iommufd_ctx *ictx;
> > +	struct iommufd_device *idev;
> > +	unsigned long index;
> > +	unsigned int id;
> > +	int ret;
> > +
> > +	ictx = iommufd_ctx_fdget(fd);
> > +	if (!ictx)
> > +		return ERR_PTR(-EINVAL);
> > +
> > +	mutex_lock(&ictx->lock);
> > +
> > +	/* check duplicate registration */
> > +	xa_for_each(&ictx->device_xa, index, idev) {
> > +		if (idev->dev == dev || idev->dev_cookie == dev_cookie) {
> > +			idev = ERR_PTR(-EBUSY);
> > +			goto out_unlock;
> > +		}
> 
> I can't think of a reason why this expensive check is needed.
> 
> > +	}
> > +
> > +	idev = kzalloc(sizeof(*idev), GFP_KERNEL);
> > +	if (!idev) {
> > +		ret = -ENOMEM;
> > +		goto out_unlock;
> > +	}
> > +
> > +	/* Establish the security context */
> > +	ret = iommu_device_init_user_dma(dev, (unsigned long)ictx);
> > +	if (ret)
> > +		goto out_free;
> > +
> > +	ret = xa_alloc(&ictx->device_xa, &id, idev,
> > +		       XA_LIMIT(IOMMUFD_DEVID_MIN,
> IOMMUFD_DEVID_MAX),
> > +		       GFP_KERNEL);
> 
> idev should be fully initialized before being placed in the xarray, so
> this should be the last thing done.

all good suggestions above. thanks for catching them.

> Why not just use the standard xa_limit_32b instead of special single
> use constants?

yeah. should use xa_limit_32b.

Regards,
Yi Liu

> Jason




[Index of Archives]     [KVM ARM]     [KVM ia64]     [KVM ppc]     [Virtualization Tools]     [Spice Development]     [Libvirt]     [Libvirt Users]     [Linux USB Devel]     [Linux Audio Users]     [Yosemite Questions]     [Linux Kernel]     [Linux SCSI]     [XFree86]

  Powered by Linux