Re: [PATCH v3 05/15] iommufd: File descriptor, context, kconfig and makefiles

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

 



On Thu, Nov 03, 2022 at 07:22:11AM +0000, Tian, Kevin wrote:
> > From: Jason Gunthorpe <jgg@xxxxxxxxxx>
> > Sent: Wednesday, October 26, 2022 2:12 AM
> > 
> > --- a/MAINTAINERS
> > +++ b/MAINTAINERS
> > @@ -10714,6 +10714,16 @@ F:	drivers/iommu/dma-iommu.h
> >  F:	drivers/iommu/iova.c
> >  F:	include/linux/iova.h
> > 
> > +IOMMU FD
> 
> remove the space, i.e. IOMMUFD

OK

> > +config IOMMUFD
> > +	tristate "IOMMU Userspace API"
> > +	select INTERVAL_TREE
> > +	select INTERVAL_TREE_SPAN_ITER
> > +	select IOMMU_API
> > +	default n
> > +	help
> > +	  Provides /dev/iommu the user API to control the IOMMU subsystem
> > as
> > +	  it relates to managing IO page tables that point at user space
> > memory.
> > +
> > +	  This would commonly be used in combination with VFIO.
> 
> remove this line

Sure
 
> > +/**
> > + * iommufd_put_object_keep_user() - Release part of the refcount on obj
> 
> what does 'part of the refcount' mean?
> 
> > + * @obj - Object to release
> > + *
> > + * Objects have two protections to ensure that userspace has a consistent
> > + * experience with destruction. Normally objects are locked so that destroy
> > will
> > + * block while there are concurrent users, and wait for the object to be
> > + * unlocked.
> > + *
> > + * However, destroy can also be blocked by holding users reference counts
> > on the
> > + * objects, in that case destroy will immediately return EBUSY and will not
> > wait
> > + * for reference counts to go to zero.
> > + *
> > + * This function switches from blocking userspace to returning EBUSY.
> 
> Not sure where "switch from... to..." comes from. Also this function alone
> doesn't deal anything with EBUSY. Probably it is clearer that this interface
> is used for long-term refcounting which the destroy path should favor to
> not block as it did for transient refcounting in concurrent ioctl paths.

How about this:

/**
 * iommufd_ref_to_users() - Switch from destroy_rwsem to users refcount
 *        protection
 * @obj - Object to release
 *
 * Objects have two refcount protections (destroy_rwsem and the refcount_t
 * users). Holding either of these will prevent the object from being destroyed.
 *
 * Depending on the use case, one protection or the other is appropriate.  In
 * most cases references are being protected by the destroy_rwsem. This allows
 * orderly destruction of the object becuase iommufd_object_destroy_user() will
 * wait for it to become unlocked. However, as a rwsem, it cannot be held across
 * a system call return. So cases that have longer term needs must switch
 * to the weaker users refcount_t.
 *
 * With users protection iommufd_object_destroy_user() will return -EBUSY to
 * userspace and refuse to destroy the object.
 */

With a function rename.

> > + * It should be used in places where the users will be held beyond a single
> > + * system call.
> 
> 'users' or 'external drivers'? Do we ever allow userspace to hold the lock
> of a kernel object for undefined time?

"users" is the name of the variable and the refcount

We don't allow userspace to hold a lock, but we do allow it to hold a
refcount. And the refcount is defined so that it must be unheld
internally in the kernel when the fd is released. Eg this is part of
what the access_ops unmap callback is doing.

 
> > +++ b/drivers/iommu/iommufd/main.c
> > @@ -0,0 +1,345 @@
> > +// SPDX-License-Identifier: GPL-2.0-only
> > +/* Copyright (C) 2021 Intel Corporation
> > + * Copyright (c) 2021-2022, NVIDIA CORPORATION & AFFILIATES
> > + *
> > + * iommufd provides control over the IOMMU HW objects created by
> > IOMMU kernel
> > + * drivers. IOMMU HW objects revolve around IO page tables that map
> > incoming DMA
> > + * addresses (IOVA) to CPU addresses.
> 
> "to bus addresses".

CPU address is correct, these are all phys_addr_t's. The IOVA is the
"bus address" in kernel terminology.

> > + *
> > + * The API is divided into a general portion that is intended to work with any
> > + * kernel IOMMU driver, and a device specific portion that  is intended to be
> > + * used with a userspace HW driver paired with the specific kernel driver.
> > This
> > + * mechanism allows all the unique functionalities in individual IOMMUs to
> > be
> > + * exposed to userspace control.
> 
> there is no device specific portion in this series.

Lets drop the paragraph

> > +/*
> > + * Allow concurrent access to the object. This should only be done once the
> > + * system call that created the object is guaranteed to succeed.
> 
> an object is not always created by a system call, e.g. iommufd_access

Yes, but that is actually a special case, "iommufd_access" is a "leaf"
object that doesn't have any way for userspace to block it. Something
like that can always be destroyed, indeed we require it as part of the
drive facing API. So this guidance isn't aimed at that.

How about:


/*
 * Allow concurrent access to the object.
 *
 * Once another thread can see the object pointer it can prevent object
 * destruction. Expect for special kernel-only objects there is no in-kernel way
 * to reliably destroy a single object. Thus all APIs that are creating objects
 * must use iommufd_object_abort() to handle their errors and only call
 * iommufd_object_finalize() once object creation cannot fail.
 */

> > +static int iommufd_destroy(struct iommufd_ucmd *ucmd)
> > +{
> > +	struct iommu_destroy *cmd = ucmd->cmd;
> > +	struct iommufd_object *obj;
> > +
> > +	obj = iommufd_get_object(ucmd->ictx, cmd->id,
> > IOMMUFD_OBJ_ANY);
> > +	if (IS_ERR(obj))
> > +		return PTR_ERR(obj);
> > +	iommufd_put_object_keep_user(obj);
> > +	if (!iommufd_object_destroy_user(ucmd->ictx, obj))
> > +		return -EBUSY;
> 
> Add a comment that it implies a refcnt hold by external driver in a
> long time so return error instead of blocking...

Lets do "See iommufd_ref_to_users" 

> > +	nr = _IOC_NR(cmd);
> > +	if (nr < IOMMUFD_CMD_BASE ||
> > +	    (nr - IOMMUFD_CMD_BASE) >= ARRAY_SIZE(iommufd_ioctl_ops))
> > +		return -ENOIOCTLCMD;
> 
> According to the description in iommufd.h:
> 
> 	*  - ENOTTY: The IOCTL number itself is not supported at all

Yes, it is weird, but in ioctl handlers you return ENOTTY by returning
ENOIOCTLCMD which is then converted to ENOTTY in vfs_ioctl()
 
> > +	op = &iommufd_ioctl_ops[nr - IOMMUFD_CMD_BASE];
> > +	if (op->ioctl_num != cmd)
> > +		return -ENOIOCTLCMD;
> > +	if (ucmd.user_size < op->min_size)
> > +		return -EOPNOTSUPP;
> 
> -EINVAL?

Yes

> > +/**
> > + * DOC: General ioctl format
> > + *
> > + * The ioctl mechanims follows a general format to allow for extensibility.
> 
> mechanism

It was changed to "interface" in another comment

Thanks,
Jason 



[Index of Archives]     [Linux Wireless]     [Linux Kernel]     [ATH6KL]     [Linux Bluetooth]     [Linux Netdev]     [Kernel Newbies]     [Share Photos]     [IDE]     [Security]     [Git]     [Netfilter]     [Bugtraq]     [Yosemite News]     [MIPS Linux]     [ARM Linux]     [Linux Security]     [Linux RAID]     [Linux ATA RAID]     [Samba]     [Device Mapper]

  Powered by Linux