From patchwork Mon Oct 23 09:55:18 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: David Marchand X-Patchwork-Id: 133170 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 6ABBE431E0; Mon, 23 Oct 2023 11:55:30 +0200 (CEST) Received: from mails.dpdk.org (localhost [127.0.0.1]) by mails.dpdk.org (Postfix) with ESMTP id 57DA240275; Mon, 23 Oct 2023 11:55:30 +0200 (CEST) Received: from us-smtp-delivery-124.mimecast.com (us-smtp-delivery-124.mimecast.com [170.10.133.124]) by mails.dpdk.org (Postfix) with ESMTP id D356640270 for ; Mon, 23 Oct 2023 11:55:28 +0200 (CEST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1698054928; 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; bh=N1Oi9GbuvPNxphCBlDtbgu+LW18f7I/m7eDUn6NpEmo=; b=eYNb1iKwbRnt6/l8NXq37pIV9y4QimZdoRqrJ3g1xYVfjlPJQ8wSGfoTSrNvpMpv2Lw1iR wIL7wkhOQciUpR5iZ50O7sH2KQosxwwMfAdrx3IrIl6ya/rZvVQVtkIhjvenGAs6zizv0/ wsYgI+EswKmjpc5/V9ZgxaithcCfHsI= Received: from mimecast-mx02.redhat.com (mimecast-mx02.redhat.com [66.187.233.88]) by relay.mimecast.com with ESMTP with STARTTLS (version=TLSv1.2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id us-mta-140-SWJduy0sMiCVik1Czu6yow-1; Mon, 23 Oct 2023 05:55:26 -0400 X-MC-Unique: SWJduy0sMiCVik1Czu6yow-1 Received: from smtp.corp.redhat.com (int-mx10.intmail.prod.int.rdu2.redhat.com [10.11.54.10]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mimecast-mx02.redhat.com (Postfix) with ESMTPS id BF9511020208; Mon, 23 Oct 2023 09:55:25 +0000 (UTC) Received: from dmarchan.redhat.com (unknown [10.45.225.98]) by smtp.corp.redhat.com (Postfix) with ESMTP id 05171492BFB; Mon, 23 Oct 2023 09:55:24 +0000 (UTC) From: David Marchand To: dev@dpdk.org Cc: Maxime Coquelin , Chenbo Xia Subject: [PATCH 1/3] vhost: robustify virtqueue access lock asserts Date: Mon, 23 Oct 2023 11:55:18 +0200 Message-ID: <20231023095520.2864868-1-david.marchand@redhat.com> MIME-Version: 1.0 X-Scanned-By: MIMEDefang 3.4.1 on 10.11.54.10 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 A simple comment in vhost_user_msg_handler() is not that robust. Add a lock_all_qps property to message handlers so that their implementation can add a build check and assert a vq is locked. Signed-off-by: David Marchand Acked-by: Eelco Chaudron Reviewed-by: Maxime Coquelin --- lib/vhost/vhost_user.c | 110 +++++++++++++++++++---------------------- 1 file changed, 51 insertions(+), 59 deletions(-) diff --git a/lib/vhost/vhost_user.c b/lib/vhost/vhost_user.c index 901a80bbaa..5bbdbd54d8 100644 --- a/lib/vhost/vhost_user.c +++ b/lib/vhost/vhost_user.c @@ -56,14 +56,24 @@ #define INFLIGHT_ALIGNMENT 64 #define INFLIGHT_VERSION 0x1 -typedef struct vhost_message_handler { +typedef const struct vhost_message_handler { const char *description; int (*callback)(struct virtio_net **pdev, struct vhu_msg_context *ctx, int main_fd); bool accepts_fd; + bool lock_all_qps; } vhost_message_handler_t; static vhost_message_handler_t vhost_message_handlers[]; +/* vhost_user_msg_handler() locks all qps based on a handler's lock_all_qps. + * Later, a handler may need to ensure the vq has been locked (for example, + * when calling lock annotated helpers). + */ +#define VHOST_USER_ASSERT_LOCK(dev, vq, id) do { \ + RTE_BUILD_BUG_ON(!vhost_message_handlers[id].lock_all_qps); \ + vq_assert_lock(dev, vq); \ +} while (0) + static int send_vhost_reply(struct virtio_net *dev, int sockfd, struct vhu_msg_context *ctx); static int read_vhost_message(struct virtio_net *dev, int sockfd, struct vhu_msg_context *ctx); @@ -400,7 +410,7 @@ vhost_user_set_features(struct virtio_net **pdev, cleanup_vq(vq, 1); cleanup_vq_inflight(dev, vq); /* vhost_user_lock_all_queue_pairs locked all qps */ - vq_assert_lock(dev, vq); + VHOST_USER_ASSERT_LOCK(dev, vq, VHOST_USER_SET_FEATURES); rte_rwlock_write_unlock(&vq->access_lock); free_vq(dev, vq); } @@ -2224,7 +2234,7 @@ vhost_user_set_vring_enable(struct virtio_net **pdev, vq = dev->virtqueue[index]; if (!(dev->flags & VIRTIO_DEV_VDPA_CONFIGURED)) { /* vhost_user_lock_all_queue_pairs locked all qps */ - vq_assert_lock(dev, vq); + VHOST_USER_ASSERT_LOCK(dev, vq, VHOST_USER_SET_VRING_ENABLE); if (enable && vq->async && vq->async->pkts_inflight_n) { VHOST_LOG_CONFIG(dev->ifname, ERR, "failed to enable vring. Inflight packets must be completed first\n"); @@ -2829,41 +2839,43 @@ vhost_user_set_status(struct virtio_net **pdev, } #define VHOST_MESSAGE_HANDLERS \ -VHOST_MESSAGE_HANDLER(VHOST_USER_NONE, NULL, false) \ -VHOST_MESSAGE_HANDLER(VHOST_USER_GET_FEATURES, vhost_user_get_features, false) \ -VHOST_MESSAGE_HANDLER(VHOST_USER_SET_FEATURES, vhost_user_set_features, false) \ -VHOST_MESSAGE_HANDLER(VHOST_USER_SET_OWNER, vhost_user_set_owner, false) \ -VHOST_MESSAGE_HANDLER(VHOST_USER_RESET_OWNER, vhost_user_reset_owner, false) \ -VHOST_MESSAGE_HANDLER(VHOST_USER_SET_MEM_TABLE, vhost_user_set_mem_table, true) \ -VHOST_MESSAGE_HANDLER(VHOST_USER_SET_LOG_BASE, vhost_user_set_log_base, true) \ -VHOST_MESSAGE_HANDLER(VHOST_USER_SET_LOG_FD, vhost_user_set_log_fd, true) \ -VHOST_MESSAGE_HANDLER(VHOST_USER_SET_VRING_NUM, vhost_user_set_vring_num, false) \ -VHOST_MESSAGE_HANDLER(VHOST_USER_SET_VRING_ADDR, vhost_user_set_vring_addr, false) \ -VHOST_MESSAGE_HANDLER(VHOST_USER_SET_VRING_BASE, vhost_user_set_vring_base, false) \ -VHOST_MESSAGE_HANDLER(VHOST_USER_GET_VRING_BASE, vhost_user_get_vring_base, false) \ -VHOST_MESSAGE_HANDLER(VHOST_USER_SET_VRING_KICK, vhost_user_set_vring_kick, true) \ -VHOST_MESSAGE_HANDLER(VHOST_USER_SET_VRING_CALL, vhost_user_set_vring_call, true) \ -VHOST_MESSAGE_HANDLER(VHOST_USER_SET_VRING_ERR, vhost_user_set_vring_err, true) \ -VHOST_MESSAGE_HANDLER(VHOST_USER_GET_PROTOCOL_FEATURES, vhost_user_get_protocol_features, false) \ -VHOST_MESSAGE_HANDLER(VHOST_USER_SET_PROTOCOL_FEATURES, vhost_user_set_protocol_features, false) \ -VHOST_MESSAGE_HANDLER(VHOST_USER_GET_QUEUE_NUM, vhost_user_get_queue_num, false) \ -VHOST_MESSAGE_HANDLER(VHOST_USER_SET_VRING_ENABLE, vhost_user_set_vring_enable, false) \ -VHOST_MESSAGE_HANDLER(VHOST_USER_SEND_RARP, vhost_user_send_rarp, false) \ -VHOST_MESSAGE_HANDLER(VHOST_USER_NET_SET_MTU, vhost_user_net_set_mtu, false) \ -VHOST_MESSAGE_HANDLER(VHOST_USER_SET_BACKEND_REQ_FD, vhost_user_set_req_fd, true) \ -VHOST_MESSAGE_HANDLER(VHOST_USER_IOTLB_MSG, vhost_user_iotlb_msg, false) \ -VHOST_MESSAGE_HANDLER(VHOST_USER_GET_CONFIG, vhost_user_get_config, false) \ -VHOST_MESSAGE_HANDLER(VHOST_USER_SET_CONFIG, vhost_user_set_config, false) \ -VHOST_MESSAGE_HANDLER(VHOST_USER_POSTCOPY_ADVISE, vhost_user_set_postcopy_advise, false) \ -VHOST_MESSAGE_HANDLER(VHOST_USER_POSTCOPY_LISTEN, vhost_user_set_postcopy_listen, false) \ -VHOST_MESSAGE_HANDLER(VHOST_USER_POSTCOPY_END, vhost_user_postcopy_end, false) \ -VHOST_MESSAGE_HANDLER(VHOST_USER_GET_INFLIGHT_FD, vhost_user_get_inflight_fd, false) \ -VHOST_MESSAGE_HANDLER(VHOST_USER_SET_INFLIGHT_FD, vhost_user_set_inflight_fd, true) \ -VHOST_MESSAGE_HANDLER(VHOST_USER_SET_STATUS, vhost_user_set_status, false) \ -VHOST_MESSAGE_HANDLER(VHOST_USER_GET_STATUS, vhost_user_get_status, false) - -#define VHOST_MESSAGE_HANDLER(id, handler, accepts_fd) \ - [id] = { #id, handler, accepts_fd }, +VHOST_MESSAGE_HANDLER(VHOST_USER_NONE, NULL, false, false) \ +VHOST_MESSAGE_HANDLER(VHOST_USER_GET_FEATURES, vhost_user_get_features, false, false) \ +VHOST_MESSAGE_HANDLER(VHOST_USER_SET_FEATURES, vhost_user_set_features, false, true) \ +VHOST_MESSAGE_HANDLER(VHOST_USER_SET_OWNER, vhost_user_set_owner, false, true) \ +VHOST_MESSAGE_HANDLER(VHOST_USER_RESET_OWNER, vhost_user_reset_owner, false, false) \ +VHOST_MESSAGE_HANDLER(VHOST_USER_SET_MEM_TABLE, vhost_user_set_mem_table, true, true) \ +VHOST_MESSAGE_HANDLER(VHOST_USER_SET_LOG_BASE, vhost_user_set_log_base, true, true) \ +VHOST_MESSAGE_HANDLER(VHOST_USER_SET_LOG_FD, vhost_user_set_log_fd, true, true) \ +VHOST_MESSAGE_HANDLER(VHOST_USER_SET_VRING_NUM, vhost_user_set_vring_num, false, true) \ +VHOST_MESSAGE_HANDLER(VHOST_USER_SET_VRING_ADDR, vhost_user_set_vring_addr, false, true) \ +VHOST_MESSAGE_HANDLER(VHOST_USER_SET_VRING_BASE, vhost_user_set_vring_base, false, true) \ +VHOST_MESSAGE_HANDLER(VHOST_USER_GET_VRING_BASE, vhost_user_get_vring_base, false, false) \ +VHOST_MESSAGE_HANDLER(VHOST_USER_SET_VRING_KICK, vhost_user_set_vring_kick, true, true) \ +VHOST_MESSAGE_HANDLER(VHOST_USER_SET_VRING_CALL, vhost_user_set_vring_call, true, true) \ +VHOST_MESSAGE_HANDLER(VHOST_USER_SET_VRING_ERR, vhost_user_set_vring_err, true, true) \ +VHOST_MESSAGE_HANDLER(VHOST_USER_GET_PROTOCOL_FEATURES, vhost_user_get_protocol_features, \ + false, false) \ +VHOST_MESSAGE_HANDLER(VHOST_USER_SET_PROTOCOL_FEATURES, vhost_user_set_protocol_features, \ + false, true) \ +VHOST_MESSAGE_HANDLER(VHOST_USER_GET_QUEUE_NUM, vhost_user_get_queue_num, false, false) \ +VHOST_MESSAGE_HANDLER(VHOST_USER_SET_VRING_ENABLE, vhost_user_set_vring_enable, false, true) \ +VHOST_MESSAGE_HANDLER(VHOST_USER_SEND_RARP, vhost_user_send_rarp, false, true) \ +VHOST_MESSAGE_HANDLER(VHOST_USER_NET_SET_MTU, vhost_user_net_set_mtu, false, true) \ +VHOST_MESSAGE_HANDLER(VHOST_USER_SET_BACKEND_REQ_FD, vhost_user_set_req_fd, true, true) \ +VHOST_MESSAGE_HANDLER(VHOST_USER_IOTLB_MSG, vhost_user_iotlb_msg, false, false) \ +VHOST_MESSAGE_HANDLER(VHOST_USER_GET_CONFIG, vhost_user_get_config, false, false) \ +VHOST_MESSAGE_HANDLER(VHOST_USER_SET_CONFIG, vhost_user_set_config, false, false) \ +VHOST_MESSAGE_HANDLER(VHOST_USER_POSTCOPY_ADVISE, vhost_user_set_postcopy_advise, false, false) \ +VHOST_MESSAGE_HANDLER(VHOST_USER_POSTCOPY_LISTEN, vhost_user_set_postcopy_listen, false, false) \ +VHOST_MESSAGE_HANDLER(VHOST_USER_POSTCOPY_END, vhost_user_postcopy_end, false, false) \ +VHOST_MESSAGE_HANDLER(VHOST_USER_GET_INFLIGHT_FD, vhost_user_get_inflight_fd, false, false) \ +VHOST_MESSAGE_HANDLER(VHOST_USER_SET_INFLIGHT_FD, vhost_user_set_inflight_fd, true, false) \ +VHOST_MESSAGE_HANDLER(VHOST_USER_SET_STATUS, vhost_user_set_status, false, false) \ +VHOST_MESSAGE_HANDLER(VHOST_USER_GET_STATUS, vhost_user_get_status, false, false) + +#define VHOST_MESSAGE_HANDLER(id, handler, accepts_fd, lock_all_qps) \ + [id] = { #id, handler, accepts_fd, lock_all_qps }, static vhost_message_handler_t vhost_message_handlers[] = { VHOST_MESSAGE_HANDLERS }; @@ -3131,31 +3143,11 @@ vhost_user_msg_handler(int vid, int fd) * inactive, so it is safe. Otherwise taking the access_lock * would cause a dead lock. */ - switch (request) { - case VHOST_USER_SET_FEATURES: - case VHOST_USER_SET_PROTOCOL_FEATURES: - case VHOST_USER_SET_OWNER: - case VHOST_USER_SET_MEM_TABLE: - case VHOST_USER_SET_LOG_BASE: - case VHOST_USER_SET_LOG_FD: - case VHOST_USER_SET_VRING_NUM: - case VHOST_USER_SET_VRING_ADDR: - case VHOST_USER_SET_VRING_BASE: - case VHOST_USER_SET_VRING_KICK: - case VHOST_USER_SET_VRING_CALL: - case VHOST_USER_SET_VRING_ERR: - case VHOST_USER_SET_VRING_ENABLE: - case VHOST_USER_SEND_RARP: - case VHOST_USER_NET_SET_MTU: - case VHOST_USER_SET_BACKEND_REQ_FD: + if (msg_handler->lock_all_qps) { if (!(dev->flags & VIRTIO_DEV_VDPA_CONFIGURED)) { vhost_user_lock_all_queue_pairs(dev); unlock_required = 1; } - break; - default: - break; - } handled = false;