From patchwork Tue Jun 11 13:39:55 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Maxime Coquelin X-Patchwork-Id: 140929 X-Patchwork-Delegate: maxime.coquelin@redhat.com Return-Path: X-Original-To: patchwork@inbox.dpdk.org Delivered-To: patchwork@inbox.dpdk.org Received: from mails.dpdk.org (mails.dpdk.org [217.70.189.124]) by inbox.dpdk.org (Postfix) with ESMTP id 609BF424CD; Tue, 11 Jun 2024 15:40:32 +0200 (CEST) Received: from mails.dpdk.org (localhost [127.0.0.1]) by mails.dpdk.org (Postfix) with ESMTP id 3D5EB40A81; Tue, 11 Jun 2024 15:40:17 +0200 (CEST) Received: from us-smtp-delivery-124.mimecast.com (us-smtp-delivery-124.mimecast.com [170.10.129.124]) by mails.dpdk.org (Postfix) with ESMTP id 3B01140A73 for ; Tue, 11 Jun 2024 15:40:15 +0200 (CEST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1718113214; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version:content-type:content-type: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=UW86mXMLPp7WGfGNsbapc89QSBDe2AumDvzg+FaN75Y=; b=LUytZUDMtdeXyWNnVle59Ppt49A6GPwfbDbWVEjOVB6POFHnzOumGAftSrCYM6sBWqygrJ 0zrF5uKnStxjMHKzHqfqd+ifCI1WMRd+h2vlPG2kJ1u1dJHIVhYsyYdb6asxjkorTi7fIo wyDtDLOczYnhi/O/v5MYrta6zLQ054s= Received: from mx-prod-mc-05.mail-002.prod.us-west-2.aws.redhat.com (ec2-54-186-198-63.us-west-2.compute.amazonaws.com [54.186.198.63]) by relay.mimecast.com with ESMTP with STARTTLS (version=TLSv1.3, cipher=TLS_AES_256_GCM_SHA384) id us-mta-611-OyUUsWpUNpCqhd32hmFEQg-1; Tue, 11 Jun 2024 09:40:11 -0400 X-MC-Unique: OyUUsWpUNpCqhd32hmFEQg-1 Received: from mx-prod-int-02.mail-002.prod.us-west-2.aws.redhat.com (mx-prod-int-02.mail-002.prod.us-west-2.aws.redhat.com [10.30.177.15]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (2048 bits) server-digest SHA256) (No client certificate requested) by mx-prod-mc-05.mail-002.prod.us-west-2.aws.redhat.com (Postfix) with ESMTPS id 838421955DA3; Tue, 11 Jun 2024 13:40:10 +0000 (UTC) Received: from max-p1.redhat.com (unknown [10.39.208.15]) by mx-prod-int-02.mail-002.prod.us-west-2.aws.redhat.com (Postfix) with ESMTP id 987B51956087; Tue, 11 Jun 2024 13:40:08 +0000 (UTC) From: Maxime Coquelin To: dev@dpdk.org, david.marchand@redhat.com, chenbox@nvidia.com Cc: Maxime Coquelin Subject: [PATCH v4 3/5] vhost: hide synchronization within FD manager Date: Tue, 11 Jun 2024 15:39:55 +0200 Message-ID: <20240611133957.72032-4-maxime.coquelin@redhat.com> In-Reply-To: <20240611133957.72032-1-maxime.coquelin@redhat.com> References: <20240611133957.72032-1-maxime.coquelin@redhat.com> MIME-Version: 1.0 X-Scanned-By: MIMEDefang 3.0 on 10.30.177.15 X-Mimecast-Spam-Score: 0 X-Mimecast-Originator: redhat.com X-BeenThere: dev@dpdk.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: DPDK patches and discussions List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: dev-bounces@dpdk.org This patch forces synchronization for all FDs additions or deletions in the FD set. With that, it is no more necessary for the user to know about the FD set pipe, so hide its initialization in the FD manager. Signed-off-by: Maxime Coquelin --- lib/vhost/fd_man.c | 180 ++++++++++++++++++++++++--------------------- lib/vhost/fd_man.h | 8 +- lib/vhost/socket.c | 12 +-- lib/vhost/vduse.c | 18 +---- 4 files changed, 101 insertions(+), 117 deletions(-) diff --git a/lib/vhost/fd_man.c b/lib/vhost/fd_man.c index a07fba5b6d..75843b52ef 100644 --- a/lib/vhost/fd_man.c +++ b/lib/vhost/fd_man.c @@ -2,7 +2,9 @@ * Copyright(c) 2010-2014 Intel Corporation */ +#include #include +#include #include #include @@ -17,6 +19,87 @@ RTE_LOG_REGISTER_SUFFIX(vhost_fdset_logtype, fdset, INFO); #define FDPOLLERR (POLLERR | POLLHUP | POLLNVAL) +static void +fdset_pipe_read_cb(int readfd, void *dat, + int *remove __rte_unused) +{ + char charbuf[16]; + struct fdset *fdset = dat; + int r = read(readfd, charbuf, sizeof(charbuf)); + /* + * Just an optimization, we don't care if read() failed + * so ignore explicitly its return value to make the + * compiler happy + */ + RTE_SET_USED(r); + + pthread_mutex_lock(&fdset->sync_mutex); + fdset->sync = true; + pthread_cond_broadcast(&fdset->sync_cond); + pthread_mutex_unlock(&fdset->sync_mutex); +} + +static void +fdset_pipe_uninit(struct fdset *fdset) +{ + fdset_del(fdset, fdset->u.readfd); + close(fdset->u.readfd); + fdset->u.readfd = -1; + close(fdset->u.writefd); + fdset->u.writefd = -1; +} + +static int +fdset_pipe_init(struct fdset *fdset) +{ + int ret; + + pthread_mutex_init(&fdset->sync_mutex, NULL); + pthread_cond_init(&fdset->sync_cond, NULL); + + if (pipe(fdset->u.pipefd) < 0) { + VHOST_FDMAN_LOG(ERR, + "failed to create pipe for vhost fdset"); + return -1; + } + + ret = fdset_add(fdset, fdset->u.readfd, + fdset_pipe_read_cb, NULL, fdset); + if (ret < 0) { + VHOST_FDMAN_LOG(ERR, + "failed to add pipe readfd %d into vhost server fdset", + fdset->u.readfd); + + fdset_pipe_uninit(fdset); + return -1; + } + + return 0; +} + +static void +fdset_sync(struct fdset *fdset) +{ + int ret; + + pthread_mutex_lock(&fdset->sync_mutex); + + fdset->sync = false; + ret = write(fdset->u.writefd, "1", 1); + if (ret < 0) { + VHOST_FDMAN_LOG(ERR, + "Failed to write to notification pipe: %s", + strerror(errno)); + goto out_unlock; + } + + while (!fdset->sync) + pthread_cond_wait(&fdset->sync_cond, &fdset->sync_mutex); + +out_unlock: + pthread_mutex_unlock(&fdset->sync_mutex); +} + static int get_last_valid_idx(struct fdset *pfdset, int last_valid_idx) { @@ -96,6 +179,12 @@ fdset_add_fd(struct fdset *pfdset, int idx, int fd, pfd->revents = 0; } +void +fdset_uninit(struct fdset *pfdset) +{ + fdset_pipe_uninit(pfdset); +} + int fdset_init(struct fdset *pfdset) { @@ -103,8 +192,6 @@ fdset_init(struct fdset *pfdset) pthread_mutex_init(&pfdset->fd_mutex, NULL); pthread_mutex_init(&pfdset->fd_polling_mutex, NULL); - pthread_mutex_init(&pfdset->sync_mutex, NULL); - pthread_cond_init(&pfdset->sync_cond, NULL); for (i = 0; i < MAX_FDS; i++) { pfdset->fd[i].fd = -1; @@ -112,7 +199,7 @@ fdset_init(struct fdset *pfdset) } pfdset->num = 0; - return 0; + return fdset_pipe_init(pfdset); } /** @@ -142,6 +229,8 @@ fdset_add(struct fdset *pfdset, int fd, fd_cb rcb, fd_cb wcb, void *dat) fdset_add_fd(pfdset, i, fd, rcb, wcb, dat); pthread_mutex_unlock(&pfdset->fd_mutex); + fdset_sync(pfdset); + return 0; } @@ -173,6 +262,8 @@ fdset_del(struct fdset *pfdset, int fd) pthread_mutex_unlock(&pfdset->fd_mutex); } while (i != -1); + fdset_sync(pfdset); + return dat; } @@ -206,6 +297,9 @@ fdset_try_del(struct fdset *pfdset, int fd) } pthread_mutex_unlock(&pfdset->fd_mutex); + + fdset_sync(pfdset); + return 0; } @@ -311,83 +405,3 @@ fdset_event_dispatch(void *arg) return 0; } - -static void -fdset_pipe_read_cb(int readfd, void *dat, - int *remove __rte_unused) -{ - char charbuf[16]; - struct fdset *fdset = dat; - int r = read(readfd, charbuf, sizeof(charbuf)); - /* - * Just an optimization, we don't care if read() failed - * so ignore explicitly its return value to make the - * compiler happy - */ - RTE_SET_USED(r); - - pthread_mutex_lock(&fdset->sync_mutex); - fdset->sync = true; - pthread_cond_broadcast(&fdset->sync_cond); - pthread_mutex_unlock(&fdset->sync_mutex); -} - -void -fdset_pipe_uninit(struct fdset *fdset) -{ - fdset_del(fdset, fdset->u.readfd); - close(fdset->u.readfd); - close(fdset->u.writefd); -} - -int -fdset_pipe_init(struct fdset *fdset) -{ - int ret; - - if (pipe(fdset->u.pipefd) < 0) { - VHOST_FDMAN_LOG(ERR, - "failed to create pipe for vhost fdset"); - return -1; - } - - ret = fdset_add(fdset, fdset->u.readfd, - fdset_pipe_read_cb, NULL, fdset); - - if (ret < 0) { - VHOST_FDMAN_LOG(ERR, - "failed to add pipe readfd %d into vhost server fdset", - fdset->u.readfd); - - fdset_pipe_uninit(fdset); - return -1; - } - - return 0; -} - -void -fdset_pipe_notify(struct fdset *fdset) -{ - int r = write(fdset->u.writefd, "1", 1); - /* - * Just an optimization, we don't care if write() failed - * so ignore explicitly its return value to make the - * compiler happy - */ - RTE_SET_USED(r); -} - -void -fdset_pipe_notify_sync(struct fdset *fdset) -{ - pthread_mutex_lock(&fdset->sync_mutex); - - fdset->sync = false; - fdset_pipe_notify(fdset); - - while (!fdset->sync) - pthread_cond_wait(&fdset->sync_cond, &fdset->sync_mutex); - - pthread_mutex_unlock(&fdset->sync_mutex); -} diff --git a/lib/vhost/fd_man.h b/lib/vhost/fd_man.h index 0f4cddfe56..c18e3a435c 100644 --- a/lib/vhost/fd_man.h +++ b/lib/vhost/fd_man.h @@ -42,6 +42,7 @@ struct fdset { bool sync; }; +void fdset_uninit(struct fdset *pfdset); int fdset_init(struct fdset *pfdset); @@ -53,11 +54,4 @@ int fdset_try_del(struct fdset *pfdset, int fd); uint32_t fdset_event_dispatch(void *arg); -int fdset_pipe_init(struct fdset *fdset); - -void fdset_pipe_uninit(struct fdset *fdset); - -void fdset_pipe_notify(struct fdset *fdset); -void fdset_pipe_notify_sync(struct fdset *fdset); - #endif diff --git a/lib/vhost/socket.c b/lib/vhost/socket.c index 896c8e6471..0251111017 100644 --- a/lib/vhost/socket.c +++ b/lib/vhost/socket.c @@ -279,7 +279,6 @@ vhost_user_add_connection(int fd, struct vhost_user_socket *vsocket) TAILQ_INSERT_TAIL(&vsocket->conn_list, conn, next); pthread_mutex_unlock(&vsocket->conn_mutex); - fdset_pipe_notify(&vhost_user.fdset); return; err_cleanup: @@ -1190,20 +1189,11 @@ rte_vhost_driver_start(const char *path) return -1; } - /** - * create a pipe which will be waited by poll and notified to - * rebuild the wait list of poll. - */ - if (fdset_pipe_init(&vhost_user.fdset) < 0) { - VHOST_CONFIG_LOG(path, ERR, "failed to create pipe for vhost fdset"); - return -1; - } - int ret = rte_thread_create_internal_control(&fdset_tid, "vhost-evt", fdset_event_dispatch, &vhost_user.fdset); if (ret != 0) { VHOST_CONFIG_LOG(path, ERR, "failed to create fdset handling thread"); - fdset_pipe_uninit(&vhost_user.fdset); + fdset_uninit(&vhost_user.fdset); return -1; } } diff --git a/lib/vhost/vduse.c b/lib/vhost/vduse.c index 530c148399..d87fc500d4 100644 --- a/lib/vhost/vduse.c +++ b/lib/vhost/vduse.c @@ -225,7 +225,6 @@ vduse_vring_setup(struct virtio_net *dev, unsigned int index) close(vq->kickfd); vq->kickfd = VIRTIO_UNINITIALIZED_EVENTFD; } - fdset_pipe_notify(&vduse.fdset); vhost_enable_guest_notification(dev, vq, 1); VHOST_CONFIG_LOG(dev->ifname, INFO, "Ctrl queue event handler installed"); } @@ -238,10 +237,8 @@ vduse_vring_cleanup(struct virtio_net *dev, unsigned int index) struct vduse_vq_eventfd vq_efd; int ret; - if (vq == dev->cvq && vq->kickfd >= 0) { + if (vq == dev->cvq && vq->kickfd >= 0) fdset_del(&vduse.fdset, vq->kickfd); - fdset_pipe_notify(&vduse.fdset); - } vq_efd.index = index; vq_efd.fd = VDUSE_EVENTFD_DEASSIGN; @@ -432,20 +429,11 @@ vduse_device_create(const char *path, bool compliant_ol_flags) return -1; } - /** - * create a pipe which will be waited by poll and notified to - * rebuild the wait list of poll. - */ - if (fdset_pipe_init(&vduse.fdset) < 0) { - VHOST_CONFIG_LOG(path, ERR, "failed to create pipe for vduse fdset"); - return -1; - } - ret = rte_thread_create_internal_control(&fdset_tid, "vduse-evt", fdset_event_dispatch, &vduse.fdset); if (ret != 0) { VHOST_CONFIG_LOG(path, ERR, "failed to create vduse fdset handling thread"); - fdset_pipe_uninit(&vduse.fdset); + fdset_uninit(&vduse.fdset); return -1; } @@ -573,7 +561,6 @@ vduse_device_create(const char *path, bool compliant_ol_flags) dev->vduse_dev_fd); goto out_dev_destroy; } - fdset_pipe_notify(&vduse.fdset); free(dev_config); @@ -616,7 +603,6 @@ vduse_device_destroy(const char *path) vduse_device_stop(dev); fdset_del(&vduse.fdset, dev->vduse_dev_fd); - fdset_pipe_notify_sync(&vduse.fdset); if (dev->vduse_dev_fd >= 0) { close(dev->vduse_dev_fd);