From: Christoph Hellwig <hch@lst.de> To: Greg Kroah-Hartman <gregkh@linuxfoundation.org>, Jason Gunthorpe <jgg@nvidia.com>, Alex Williamson <alex.williamson@redhat.com>, Kirti Wankhede <kwankhede@nvidia.com> Cc: David Airlie <airlied@linux.ie>, Tony Krowiak <akrowiak@linux.ibm.com>, Christian Borntraeger <borntraeger@de.ibm.com>, Cornelia Huck <cohuck@redhat.com>, Jonathan Corbet <corbet@lwn.net>, Daniel Vetter <daniel@ffwll.ch>, dri-devel@lists.freedesktop.org, Vasily Gorbik <gor@linux.ibm.com>, Heiko Carstens <hca@linux.ibm.com>, intel-gfx@lists.freedesktop.org, Jani Nikula <jani.nikula@linux.intel.com>, Jason Herne <jjherne@linux.ibm.com>, Joonas Lahtinen <joonas.lahtinen@linux.intel.com>, kvm@vger.kernel.org, linux-doc@vger.kernel.org, linux-s390@vger.kernel.org, Halil Pasic <pasic@linux.ibm.com>, "Rafael J. Wysocki" <rafael@kernel.org>, Rodrigo Vivi <rodrigo.vivi@intel.com> Subject: [PATCH 04/10] driver core: Don't return EPROBE_DEFER to userspace during sysfs bind Date: Thu, 17 Jun 2021 16:22:12 +0200 [thread overview] Message-ID: <20210617142218.1877096-5-hch@lst.de> (raw) In-Reply-To: <20210617142218.1877096-1-hch@lst.de> EPROBE_DEFER is an internal kernel error code and it should not be leaked to userspace via the bind_store() sysfs. Userspace doesn't have this constant and cannot understand it. Further, it doesn't really make sense to have userspace trigger a deferred probe via bind_store(), which could eventually succeed, while simultaneously returning an error back. Resolve this by splitting driver_probe_device so that the version used by the sysfs binding that turns EPROBE_DEFER into -EAGAIN, while the one used for internally binding keeps the error code, and calls driver_deferred_probe_add where needed. This also allows to nicely split out the defer_all_probes / probe_count checks so that they actually allow for full device_{block,unblock}_probing protection while not bothering the sysfs bind case. Signed-off-by: Christoph Hellwig <hch@lst.de> Reviewed-by: Cornelia Huck <cohuck@redhat.com> Reviewed-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> --- drivers/base/dd.c | 84 +++++++++++++++++++++++++---------------------- 1 file changed, 45 insertions(+), 39 deletions(-) diff --git a/drivers/base/dd.c b/drivers/base/dd.c index 25341f52198c..1d8012459587 100644 --- a/drivers/base/dd.c +++ b/drivers/base/dd.c @@ -491,15 +491,6 @@ EXPORT_SYMBOL_GPL(device_bind_driver); static atomic_t probe_count = ATOMIC_INIT(0); static DECLARE_WAIT_QUEUE_HEAD(probe_waitqueue); -static void driver_deferred_probe_add_trigger(struct device *dev, - int local_trigger_count) -{ - driver_deferred_probe_add(dev); - /* Did a trigger occur while probing? Need to re-trigger if yes */ - if (local_trigger_count != atomic_read(&deferred_trigger_count)) - driver_deferred_probe_trigger(); -} - static ssize_t state_synced_show(struct device *dev, struct device_attribute *attr, char *buf) { @@ -547,10 +538,9 @@ static int call_driver_probe(struct device *dev, struct device_driver *drv) static int really_probe(struct device *dev, struct device_driver *drv) { - int local_trigger_count = atomic_read(&deferred_trigger_count); bool test_remove = IS_ENABLED(CONFIG_DEBUG_TEST_DRIVER_REMOVE) && !drv->suppress_bind_attrs; - int ret = -EPROBE_DEFER, probe_ret = 0; + int ret; if (defer_all_probes) { /* @@ -559,17 +549,13 @@ static int really_probe(struct device *dev, struct device_driver *drv) * wait_for_device_probe() right after that to avoid any races. */ dev_dbg(dev, "Driver %s force probe deferral\n", drv->name); - driver_deferred_probe_add(dev); - return ret; + return -EPROBE_DEFER; } ret = device_links_check_suppliers(dev); - if (ret == -EPROBE_DEFER) - driver_deferred_probe_add_trigger(dev, local_trigger_count); if (ret) return ret; - atomic_inc(&probe_count); pr_debug("bus: '%s': %s: probing driver %s with device %s\n", drv->bus->name, __func__, drv->name, dev_name(dev)); if (!list_empty(&dev->devres_head)) { @@ -604,13 +590,13 @@ static int really_probe(struct device *dev, struct device_driver *drv) goto probe_failed; } - probe_ret = call_driver_probe(dev, drv); - if (probe_ret) { + ret = call_driver_probe(dev, drv); + if (ret) { /* * Return probe errors as positive values so that the callers * can distinguish them from other errors. */ - ret = -probe_ret; + ret = -ret; goto probe_failed; } @@ -681,11 +667,7 @@ static int really_probe(struct device *dev, struct device_driver *drv) dev->pm_domain->dismiss(dev); pm_runtime_reinit(dev); dev_pm_set_driver_flags(dev, 0); - if (probe_ret == -EPROBE_DEFER) - driver_deferred_probe_add_trigger(dev, local_trigger_count); done: - atomic_dec(&probe_count); - wake_up_all(&probe_waitqueue); return ret; } @@ -739,21 +721,7 @@ void wait_for_device_probe(void) } EXPORT_SYMBOL_GPL(wait_for_device_probe); -/** - * driver_probe_device - attempt to bind device & driver together - * @drv: driver to bind a device to - * @dev: device to try to bind to the driver - * - * This function returns -ENODEV if the device is not registered, -EBUSY if it - * already has a driver, 0 if the device is bound successfully and a positive - * (inverted) error code for failures from the ->probe method. - * - * This function must be called with @dev lock held. When called for a - * USB interface, @dev->parent lock must be held as well. - * - * If the device has a parent, runtime-resume the parent before driver probing. - */ -static int driver_probe_device(struct device_driver *drv, struct device *dev) +static int __driver_probe_device(struct device_driver *drv, struct device *dev) { int ret = 0; @@ -784,6 +752,42 @@ static int driver_probe_device(struct device_driver *drv, struct device *dev) return ret; } +/** + * driver_probe_device - attempt to bind device & driver together + * @drv: driver to bind a device to + * @dev: device to try to bind to the driver + * + * This function returns -ENODEV if the device is not registered, -EBUSY if it + * already has a driver, 0 if the device is bound successfully and a positive + * (inverted) error code for failures from the ->probe method. + * + * This function must be called with @dev lock held. When called for a + * USB interface, @dev->parent lock must be held as well. + * + * If the device has a parent, runtime-resume the parent before driver probing. + */ +static int driver_probe_device(struct device_driver *drv, struct device *dev) +{ + int trigger_count = atomic_read(&deferred_trigger_count); + int ret; + + atomic_inc(&probe_count); + ret = __driver_probe_device(drv, dev); + if (ret == -EPROBE_DEFER || ret == EPROBE_DEFER) { + driver_deferred_probe_add(dev); + + /* + * Did a trigger occur while probing? Need to re-trigger if yes + */ + if (trigger_count != atomic_read(&deferred_trigger_count) && + !defer_all_probes) + driver_deferred_probe_trigger(); + } + atomic_dec(&probe_count); + wake_up_all(&probe_waitqueue); + return ret; +} + static inline bool cmdline_requested_async_probing(const char *drv_name) { return parse_option_str(async_probe_drv_names, drv_name); @@ -1051,12 +1055,14 @@ int device_driver_attach(struct device_driver *drv, struct device *dev) int ret; __device_driver_lock(dev, dev->parent); - ret = driver_probe_device(drv, dev); + ret = __driver_probe_device(drv, dev); __device_driver_unlock(dev, dev->parent); /* also return probe errors as normal negative errnos */ if (ret > 0) ret = -ret; + if (ret == -EPROBE_DEFER) + return -EAGAIN; return ret; } -- 2.30.2
WARNING: multiple messages have this Message-ID (diff)
From: Christoph Hellwig <hch@lst.de> To: Greg Kroah-Hartman <gregkh@linuxfoundation.org>, Jason Gunthorpe <jgg@nvidia.com>, Alex Williamson <alex.williamson@redhat.com>, Kirti Wankhede <kwankhede@nvidia.com> Cc: Tony Krowiak <akrowiak@linux.ibm.com>, Jason Herne <jjherne@linux.ibm.com>, kvm@vger.kernel.org, Vasily Gorbik <gor@linux.ibm.com>, Jonathan Corbet <corbet@lwn.net>, David Airlie <airlied@linux.ie>, linux-s390@vger.kernel.org, Heiko Carstens <hca@linux.ibm.com>, Cornelia Huck <cohuck@redhat.com>, linux-doc@vger.kernel.org, dri-devel@lists.freedesktop.org, Halil Pasic <pasic@linux.ibm.com>, Christian Borntraeger <borntraeger@de.ibm.com>, "Rafael J. Wysocki" <rafael@kernel.org>, intel-gfx@lists.freedesktop.org Subject: [Intel-gfx] [PATCH 04/10] driver core: Don't return EPROBE_DEFER to userspace during sysfs bind Date: Thu, 17 Jun 2021 16:22:12 +0200 [thread overview] Message-ID: <20210617142218.1877096-5-hch@lst.de> (raw) In-Reply-To: <20210617142218.1877096-1-hch@lst.de> EPROBE_DEFER is an internal kernel error code and it should not be leaked to userspace via the bind_store() sysfs. Userspace doesn't have this constant and cannot understand it. Further, it doesn't really make sense to have userspace trigger a deferred probe via bind_store(), which could eventually succeed, while simultaneously returning an error back. Resolve this by splitting driver_probe_device so that the version used by the sysfs binding that turns EPROBE_DEFER into -EAGAIN, while the one used for internally binding keeps the error code, and calls driver_deferred_probe_add where needed. This also allows to nicely split out the defer_all_probes / probe_count checks so that they actually allow for full device_{block,unblock}_probing protection while not bothering the sysfs bind case. Signed-off-by: Christoph Hellwig <hch@lst.de> Reviewed-by: Cornelia Huck <cohuck@redhat.com> Reviewed-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> --- drivers/base/dd.c | 84 +++++++++++++++++++++++++---------------------- 1 file changed, 45 insertions(+), 39 deletions(-) diff --git a/drivers/base/dd.c b/drivers/base/dd.c index 25341f52198c..1d8012459587 100644 --- a/drivers/base/dd.c +++ b/drivers/base/dd.c @@ -491,15 +491,6 @@ EXPORT_SYMBOL_GPL(device_bind_driver); static atomic_t probe_count = ATOMIC_INIT(0); static DECLARE_WAIT_QUEUE_HEAD(probe_waitqueue); -static void driver_deferred_probe_add_trigger(struct device *dev, - int local_trigger_count) -{ - driver_deferred_probe_add(dev); - /* Did a trigger occur while probing? Need to re-trigger if yes */ - if (local_trigger_count != atomic_read(&deferred_trigger_count)) - driver_deferred_probe_trigger(); -} - static ssize_t state_synced_show(struct device *dev, struct device_attribute *attr, char *buf) { @@ -547,10 +538,9 @@ static int call_driver_probe(struct device *dev, struct device_driver *drv) static int really_probe(struct device *dev, struct device_driver *drv) { - int local_trigger_count = atomic_read(&deferred_trigger_count); bool test_remove = IS_ENABLED(CONFIG_DEBUG_TEST_DRIVER_REMOVE) && !drv->suppress_bind_attrs; - int ret = -EPROBE_DEFER, probe_ret = 0; + int ret; if (defer_all_probes) { /* @@ -559,17 +549,13 @@ static int really_probe(struct device *dev, struct device_driver *drv) * wait_for_device_probe() right after that to avoid any races. */ dev_dbg(dev, "Driver %s force probe deferral\n", drv->name); - driver_deferred_probe_add(dev); - return ret; + return -EPROBE_DEFER; } ret = device_links_check_suppliers(dev); - if (ret == -EPROBE_DEFER) - driver_deferred_probe_add_trigger(dev, local_trigger_count); if (ret) return ret; - atomic_inc(&probe_count); pr_debug("bus: '%s': %s: probing driver %s with device %s\n", drv->bus->name, __func__, drv->name, dev_name(dev)); if (!list_empty(&dev->devres_head)) { @@ -604,13 +590,13 @@ static int really_probe(struct device *dev, struct device_driver *drv) goto probe_failed; } - probe_ret = call_driver_probe(dev, drv); - if (probe_ret) { + ret = call_driver_probe(dev, drv); + if (ret) { /* * Return probe errors as positive values so that the callers * can distinguish them from other errors. */ - ret = -probe_ret; + ret = -ret; goto probe_failed; } @@ -681,11 +667,7 @@ static int really_probe(struct device *dev, struct device_driver *drv) dev->pm_domain->dismiss(dev); pm_runtime_reinit(dev); dev_pm_set_driver_flags(dev, 0); - if (probe_ret == -EPROBE_DEFER) - driver_deferred_probe_add_trigger(dev, local_trigger_count); done: - atomic_dec(&probe_count); - wake_up_all(&probe_waitqueue); return ret; } @@ -739,21 +721,7 @@ void wait_for_device_probe(void) } EXPORT_SYMBOL_GPL(wait_for_device_probe); -/** - * driver_probe_device - attempt to bind device & driver together - * @drv: driver to bind a device to - * @dev: device to try to bind to the driver - * - * This function returns -ENODEV if the device is not registered, -EBUSY if it - * already has a driver, 0 if the device is bound successfully and a positive - * (inverted) error code for failures from the ->probe method. - * - * This function must be called with @dev lock held. When called for a - * USB interface, @dev->parent lock must be held as well. - * - * If the device has a parent, runtime-resume the parent before driver probing. - */ -static int driver_probe_device(struct device_driver *drv, struct device *dev) +static int __driver_probe_device(struct device_driver *drv, struct device *dev) { int ret = 0; @@ -784,6 +752,42 @@ static int driver_probe_device(struct device_driver *drv, struct device *dev) return ret; } +/** + * driver_probe_device - attempt to bind device & driver together + * @drv: driver to bind a device to + * @dev: device to try to bind to the driver + * + * This function returns -ENODEV if the device is not registered, -EBUSY if it + * already has a driver, 0 if the device is bound successfully and a positive + * (inverted) error code for failures from the ->probe method. + * + * This function must be called with @dev lock held. When called for a + * USB interface, @dev->parent lock must be held as well. + * + * If the device has a parent, runtime-resume the parent before driver probing. + */ +static int driver_probe_device(struct device_driver *drv, struct device *dev) +{ + int trigger_count = atomic_read(&deferred_trigger_count); + int ret; + + atomic_inc(&probe_count); + ret = __driver_probe_device(drv, dev); + if (ret == -EPROBE_DEFER || ret == EPROBE_DEFER) { + driver_deferred_probe_add(dev); + + /* + * Did a trigger occur while probing? Need to re-trigger if yes + */ + if (trigger_count != atomic_read(&deferred_trigger_count) && + !defer_all_probes) + driver_deferred_probe_trigger(); + } + atomic_dec(&probe_count); + wake_up_all(&probe_waitqueue); + return ret; +} + static inline bool cmdline_requested_async_probing(const char *drv_name) { return parse_option_str(async_probe_drv_names, drv_name); @@ -1051,12 +1055,14 @@ int device_driver_attach(struct device_driver *drv, struct device *dev) int ret; __device_driver_lock(dev, dev->parent); - ret = driver_probe_device(drv, dev); + ret = __driver_probe_device(drv, dev); __device_driver_unlock(dev, dev->parent); /* also return probe errors as normal negative errnos */ if (ret > 0) ret = -ret; + if (ret == -EPROBE_DEFER) + return -EAGAIN; return ret; } -- 2.30.2 _______________________________________________ Intel-gfx mailing list Intel-gfx@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/intel-gfx
next prev parent reply other threads:[~2021-06-17 14:24 UTC|newest] Thread overview: 42+ messages / expand[flat|nested] mbox.gz Atom feed top 2021-06-17 14:22 Allow mdev drivers to directly create the vfio_device (v4) Christoph Hellwig 2021-06-17 14:22 ` [Intel-gfx] " Christoph Hellwig 2021-06-17 14:22 ` [PATCH 01/10] driver core: Pull required checks into driver_probe_device() Christoph Hellwig 2021-06-17 14:22 ` [Intel-gfx] " Christoph Hellwig 2021-06-17 14:22 ` [PATCH 02/10] driver core: Better distinguish probe errors in really_probe Christoph Hellwig 2021-06-17 14:22 ` [Intel-gfx] " Christoph Hellwig 2021-06-17 14:22 ` [PATCH 03/10] driver core: Flow the return code from ->probe() through to sysfs bind Christoph Hellwig 2021-06-17 14:22 ` [Intel-gfx] " Christoph Hellwig 2021-06-17 14:22 ` Christoph Hellwig [this message] 2021-06-17 14:22 ` [Intel-gfx] [PATCH 04/10] driver core: Don't return EPROBE_DEFER to userspace during " Christoph Hellwig 2021-06-17 14:22 ` [PATCH 05/10] driver core: Export device_driver_attach() Christoph Hellwig 2021-06-17 14:22 ` [Intel-gfx] " Christoph Hellwig 2021-06-17 14:22 ` [PATCH 06/10] vfio/mdev: Remove CONFIG_VFIO_MDEV_DEVICE Christoph Hellwig 2021-06-17 14:22 ` [Intel-gfx] " Christoph Hellwig 2021-06-17 14:22 ` [PATCH 07/10] vfio/mdev: Allow the mdev_parent_ops to specify the device driver to bind Christoph Hellwig 2021-06-17 14:22 ` [Intel-gfx] " Christoph Hellwig 2021-06-17 14:22 ` [PATCH 08/10] vfio/mtty: Convert to use vfio_register_group_dev() Christoph Hellwig 2021-06-17 14:22 ` [Intel-gfx] " Christoph Hellwig 2021-06-17 14:22 ` [PATCH 09/10] vfio/mdpy: " Christoph Hellwig 2021-06-17 14:22 ` [Intel-gfx] " Christoph Hellwig 2021-06-17 14:22 ` [PATCH 10/10] vfio/mbochs: " Christoph Hellwig 2021-06-17 14:22 ` [Intel-gfx] " Christoph Hellwig 2021-06-17 14:47 ` [Intel-gfx] ✗ Fi.CI.CHECKPATCH: warning for series starting with [01/10] driver core: Pull required checks into driver_probe_device() Patchwork 2021-06-17 15:16 ` [Intel-gfx] ✓ Fi.CI.BAT: success " Patchwork 2021-06-17 17:12 ` [Intel-gfx] ✓ Fi.CI.IGT: " Patchwork 2021-06-23 0:05 ` Allow mdev drivers to directly create the vfio_device (v4) Jason Gunthorpe 2021-06-23 0:05 ` [Intel-gfx] " Jason Gunthorpe 2021-06-23 0:05 ` Jason Gunthorpe 2021-06-23 1:21 ` Alex Williamson 2021-06-23 1:21 ` [Intel-gfx] " Alex Williamson 2021-06-23 1:21 ` Alex Williamson -- strict thread matches above, loose matches on Subject: below -- 2021-06-15 13:35 Allow mdev drivers to directly create the vfio_device (v3) Christoph Hellwig 2021-06-15 13:35 ` [PATCH 04/10] driver core: Don't return EPROBE_DEFER to userspace during sysfs bind Christoph Hellwig 2021-06-15 14:03 ` Cornelia Huck 2021-06-15 14:03 ` Cornelia Huck 2021-06-15 19:36 ` Alex Williamson 2021-06-15 19:36 ` Alex Williamson 2021-06-14 15:08 Allow mdev drivers to directly create the vfio_device (v2 / alternative) Christoph Hellwig 2021-06-14 15:08 ` [PATCH 04/10] driver core: Don't return EPROBE_DEFER to userspace during sysfs bind Christoph Hellwig 2021-06-14 22:43 ` Jason Gunthorpe 2021-06-14 22:43 ` Jason Gunthorpe 2021-06-08 0:55 [PATCH 00/10] Allow mdev drivers to directly create the vfio_device Jason Gunthorpe 2021-06-08 0:55 ` [PATCH 04/10] driver core: Don't return EPROBE_DEFER to userspace during sysfs bind Jason Gunthorpe 2021-06-08 6:14 ` Christoph Hellwig 2021-06-08 7:37 ` Greg Kroah-Hartman
Reply instructions: You may reply publicly to this message via plain-text email using any one of the following methods: * Save the following mbox file, import it into your mail client, and reply-to-all from there: mbox Avoid top-posting and favor interleaved quoting: https://en.wikipedia.org/wiki/Posting_style#Interleaved_style * Reply using the --to, --cc, and --in-reply-to switches of git-send-email(1): git send-email \ --in-reply-to=20210617142218.1877096-5-hch@lst.de \ --to=hch@lst.de \ --cc=airlied@linux.ie \ --cc=akrowiak@linux.ibm.com \ --cc=alex.williamson@redhat.com \ --cc=borntraeger@de.ibm.com \ --cc=cohuck@redhat.com \ --cc=corbet@lwn.net \ --cc=daniel@ffwll.ch \ --cc=dri-devel@lists.freedesktop.org \ --cc=gor@linux.ibm.com \ --cc=gregkh@linuxfoundation.org \ --cc=hca@linux.ibm.com \ --cc=intel-gfx@lists.freedesktop.org \ --cc=jani.nikula@linux.intel.com \ --cc=jgg@nvidia.com \ --cc=jjherne@linux.ibm.com \ --cc=joonas.lahtinen@linux.intel.com \ --cc=kvm@vger.kernel.org \ --cc=kwankhede@nvidia.com \ --cc=linux-doc@vger.kernel.org \ --cc=linux-s390@vger.kernel.org \ --cc=pasic@linux.ibm.com \ --cc=rafael@kernel.org \ --cc=rodrigo.vivi@intel.com \ /path/to/YOUR_REPLY https://kernel.org/pub/software/scm/git/docs/git-send-email.html * If your mail client supports setting the In-Reply-To header via mailto: links, try the mailto: linkBe sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes, see mirroring instructions on how to clone and mirror all data and code used by this external index.