patches for DPDK stable branches
 help / color / mirror / Atom feed
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, &param->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(&param->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
> 


      parent reply	other threads:[~2025-09-22  8:23 UTC|newest]

Thread overview: 7+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
     [not found] <20240828104002.226704-1-konrad.sztyber@intel.com>
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
2025-09-22  8:22     ` Chenbo Xia [this message]

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 a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).