From: Chenbo Xia <chenbox@nvidia.com>
To: Konrad Sztyber <konrad.sztyber@intel.com>
Cc: "dev@dpdk.org" <dev@dpdk.org>,
Chaoyong He <chaoyong.he@corigine.com>,
Stephen Hemminger <stephen@networkplumber.org>,
David Marchand <david.marchand@redhat.com>,
"stable@dpdk.org" <stable@dpdk.org>,
Nipun Gupta <nipun.gupta@amd.com>,
Anatoly Burakov <anatoly.burakov@intel.com>,
Long Wu <long.wu@corigine.com>, Zerun Fu <zerun.fu@corigine.com>
Subject: Re: [PATCH v3] bus/pci: don't open uio device in secondary process
Date: Mon, 22 Sep 2025 08:22:59 +0000 [thread overview]
Message-ID: <B7194C63-9B63-4E74-876F-C0B83CD113FA@nvidia.com> (raw)
In-Reply-To: <20241011111533.20746-1-konrad.sztyber@intel.com>
Hi Konrad,
> On Oct 11, 2024, at 19:15, Konrad Sztyber <konrad.sztyber@intel.com> wrote:
>
> External email: Use caution opening links or attachments
>
>
> The uio_pci_generic driver clears the bus master bit when the device
> file is closed. So, when the secondary process terminates after probing
> a device, that device becomes unusable in the primary process.
>
> To avoid that, the device file is now opened only in the primary process
> and the secondary gets it over UNIX domain socket via SCM_RIGHTS.
>
> Fixes: 847d78fb9530 ("bus/pci: fix FD in secondary process")
> Cc: stable@dpdk.org
>
> Signed-off-by: Konrad Sztyber <konrad.sztyber@intel.com>
> ---
> v3:
> Use the rte_mp_* infrastructure to pass the uio fd from the primary
> process to the secondary.
> v2:
> Fixed coding style issues.
> ---
> drivers/bus/pci/linux/pci_uio.c | 140 ++++++++++++++++++++++++++++----
> 1 file changed, 126 insertions(+), 14 deletions(-)
>
> diff --git a/drivers/bus/pci/linux/pci_uio.c b/drivers/bus/pci/linux/pci_uio.c
> index 4c1d3327a9..220390d921 100644
> --- a/drivers/bus/pci/linux/pci_uio.c
> +++ b/drivers/bus/pci/linux/pci_uio.c
> @@ -21,14 +21,22 @@
> #include <rte_bus_pci.h>
> #include <rte_common.h>
> #include <rte_malloc.h>
> +#include <rte_eal.h>
> +#include <rte_errno.h>
>
> #include "eal_filesystem.h"
> #include "pci_init.h"
> #include "private.h"
>
> void *pci_map_addr = NULL;
> +static int pci_uio_dev_count;
>
> #define OFF_MAX ((uint64_t)(off_t)-1)
> +#define SEND_FD_MP_KEY "pci_uio_send_fd"
> +
> +struct pci_uio_send_fd_param {
> + struct rte_pci_addr addr;
> +};
>
> int
> pci_uio_read_config(const struct rte_intr_handle *intr_handle,
> @@ -211,6 +219,93 @@ pci_uio_free_resource(struct rte_pci_device *dev,
> rte_intr_fd_set(dev->intr_handle, -1);
> rte_intr_type_set(dev->intr_handle, RTE_INTR_HANDLE_UNKNOWN);
> }
> +
> + if (rte_eal_process_type() == RTE_PROC_PRIMARY) {
> + assert(pci_uio_dev_count > 0);
> + pci_uio_dev_count--;
> + if (pci_uio_dev_count == 0)
> + rte_mp_action_unregister(SEND_FD_MP_KEY);
> + }
> +}
> +
> +static int
> +pci_uio_send_fd(const struct rte_mp_msg *request, const void *peer)
> +{
> + struct rte_pci_device *dev;
> + const struct pci_uio_send_fd_param *param =
> + (const struct pci_uio_send_fd_param *)request->param;
> + struct rte_mp_msg reply = {};
> + int fd;
> +
> + strlcpy(reply.name, request->name, sizeof(reply.name));
> + TAILQ_FOREACH(dev, &rte_pci_bus.device_list, next) {
> + if (!rte_pci_addr_cmp(&dev->addr, ¶m->addr))
> + break;
> + }
> +
> + if (dev == NULL) {
> + PCI_LOG(ERR, "Could not find PCI device (" PCI_PRI_FMT ")",
> + param->addr.domain, param->addr.bus,
> + param->addr.devid, param->addr.function);
> + goto reply;
> + }
> +
> + fd = rte_intr_fd_get(dev->intr_handle);
> + if (fd < 0) {
> + PCI_LOG(ERR, "Could not get fd (" PCI_PRI_FMT ")",
> + param->addr.domain, param->addr.bus,
> + param->addr.devid, param->addr.function);
> + goto reply;
> + }
Should we just return error instead of calling rte_mp_reply when dev == NULL or fd < 0?
Thanks,
Chenbo
> +
> + reply.num_fds = 1;
> + reply.fds[0] = fd;
> +reply:
> + if (rte_mp_reply(&reply, peer) != 0) {
> + PCI_LOG(ERR, "Failed to send reply: %d (" PCI_PRI_FMT ")",
> + rte_errno, param->addr.domain, param->addr.bus,
> + param->addr.devid, param->addr.function);
> + return -1;
> + }
> +
> + return 0;
> +}
> +
> +static int
> +pci_uio_request_fd(struct rte_pci_device *dev)
> +{
> + struct rte_mp_msg request = {}, *reply;
> + struct timespec timeout = {.tv_sec = 1, .tv_nsec = 0};
> + struct pci_uio_send_fd_param *param =
> + (struct pci_uio_send_fd_param *)request.param;
> + struct rte_mp_reply replies;
> + int rc;
> +
> + strlcpy(request.name, SEND_FD_MP_KEY, sizeof(request.name));
> + memcpy(¶m->addr, &dev->addr, sizeof(param->addr));
> + request.len_param = sizeof(*param);
> +
> + rc = rte_mp_request_sync(&request, &replies, &timeout);
> + if (rc != 0 || replies.nb_received != 1) {
> + PCI_LOG(ERR, "Failed to request fd from primary: %d (" PCI_PRI_FMT ")",
> + rte_errno, dev->addr.domain, dev->addr.bus,
> + dev->addr.devid, dev->addr.function);
> + return -1;
> + }
> +
> + reply = replies.msgs;
> + if (reply->num_fds != 1) {
> + PCI_LOG(ERR, "Received unexpected number of fds: %d (" PCI_PRI_FMT ")",
> + reply->num_fds, dev->addr.domain, dev->addr.bus,
> + dev->addr.devid, dev->addr.function);
> + free(reply);
> + return -1;
> + }
> +
> + rte_intr_fd_set(dev->intr_handle, reply->fds[0]);
> + free(reply);
> +
> + return 0;
> }
>
> int
> @@ -220,7 +315,7 @@ pci_uio_alloc_resource(struct rte_pci_device *dev,
> char dirname[PATH_MAX];
> char cfgname[PATH_MAX];
> char devname[PATH_MAX]; /* contains the /dev/uioX */
> - int uio_num, fd, uio_cfg_fd;
> + int rc, uio_num, fd, uio_cfg_fd;
> struct rte_pci_addr *loc;
>
> loc = &dev->addr;
> @@ -232,18 +327,6 @@ pci_uio_alloc_resource(struct rte_pci_device *dev,
> loc->domain, loc->bus, loc->devid, loc->function);
> return 1;
> }
> - snprintf(devname, sizeof(devname), "/dev/uio%u", uio_num);
> -
> - /* save fd */
> - fd = open(devname, O_RDWR);
> - if (fd < 0) {
> - PCI_LOG(ERR, "Cannot open %s: %s", devname, strerror(errno));
> - goto error;
> - }
> -
> - if (rte_intr_fd_set(dev->intr_handle, fd))
> - goto error;
> -
> snprintf(cfgname, sizeof(cfgname),
> "/sys/class/uio/uio%u/device/config", uio_num);
>
> @@ -270,8 +353,27 @@ pci_uio_alloc_resource(struct rte_pci_device *dev,
> }
> }
>
> - if (rte_eal_process_type() != RTE_PROC_PRIMARY)
> + if (rte_eal_process_type() != RTE_PROC_PRIMARY) {
> + if (pci_uio_request_fd(dev) != 0)
> + goto error;
> return 0;
> + }
> +
> + /*
> + * The uio_pci_generic driver clears the bus master enable bit when the
> + * device file is closed, so open it only in the primary process. The
> + * secondary will get it via SCM_RIGHTS.
> + */
> + snprintf(devname, sizeof(devname), "/dev/uio%u", uio_num);
> + /* save fd */
> + fd = open(devname, O_RDWR);
> + if (fd < 0) {
> + PCI_LOG(ERR, "Cannot open %s: %s", devname, strerror(errno));
> + goto error;
> + }
> +
> + if (rte_intr_fd_set(dev->intr_handle, fd))
> + goto error;
>
> /* allocate the mapping details for secondary processes*/
> *uio_res = rte_zmalloc("UIO_RES", sizeof(**uio_res), 0);
> @@ -280,6 +382,16 @@ pci_uio_alloc_resource(struct rte_pci_device *dev,
> goto error;
> }
>
> + if (pci_uio_dev_count == 0) {
> + rc = rte_mp_action_register(SEND_FD_MP_KEY, pci_uio_send_fd);
> + if (rc != 0 && rte_errno != ENOTSUP) {
> + PCI_LOG(ERR, "Failed to register multi-process callback: %d",
> + rte_errno);
> + goto error;
> + }
> + }
> +
> + pci_uio_dev_count++;
> strlcpy((*uio_res)->path, devname, sizeof((*uio_res)->path));
> memcpy(&(*uio_res)->pci_addr, &dev->addr, sizeof((*uio_res)->pci_addr));
>
> --
> 2.46.2
>
next prev parent reply other threads:[~2025-09-22 8:23 UTC|newest]
Thread overview: 19+ messages / expand[flat|nested] mbox.gz Atom feed top
2024-08-28 10:40 [PATCH] bus/pci: don't open uio device in secondary process Konrad Sztyber
2024-08-29 5:53 ` Chaoyong He
2024-08-29 8:06 ` Chenbo Xia
2024-08-29 8:57 ` [PATCH v2] " Konrad Sztyber
2024-08-30 3:48 ` Chenbo Xia
2024-10-11 11:15 ` [PATCH v3] " Konrad Sztyber
2024-10-24 9:05 ` David Marchand
2024-11-19 10:39 ` Konrad Sztyber
2025-09-19 10:15 ` David Marchand
2026-01-13 12:14 ` Konrad Sztyber
2025-09-22 8:22 ` Chenbo Xia [this message]
2026-01-13 12:17 ` Konrad Sztyber
2026-01-13 12:35 ` [PATCH v4] " Konrad Sztyber
2026-01-13 14:31 ` Stephen Hemminger
2024-10-07 17:49 ` [PATCH] " Stephen Hemminger
2024-10-09 10:11 ` Konrad Sztyber
2024-10-09 15:12 ` Stephen Hemminger
2024-10-11 6:38 ` Konrad Sztyber
2024-10-11 6:46 ` David Marchand
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=B7194C63-9B63-4E74-876F-C0B83CD113FA@nvidia.com \
--to=chenbox@nvidia.com \
--cc=anatoly.burakov@intel.com \
--cc=chaoyong.he@corigine.com \
--cc=david.marchand@redhat.com \
--cc=dev@dpdk.org \
--cc=konrad.sztyber@intel.com \
--cc=long.wu@corigine.com \
--cc=nipun.gupta@amd.com \
--cc=stable@dpdk.org \
--cc=stephen@networkplumber.org \
--cc=zerun.fu@corigine.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: link
Be 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.