From mboxrd@z Thu Jan 1 00:00:00 1970 Received: from us-smtp-delivery-124.mimecast.com (us-smtp-delivery-124.mimecast.com [170.10.129.124]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 594E41F2B8D for ; Tue, 7 Jul 2026 21:00:28 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=170.10.129.124 ARC-Seal:i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1783458029; cv=none; b=uCxk67wPzlk/5IKeTTynN2wRksaVPG7p0PdOl5BHkavhpt//YeI/PEoee3ZA3Ibavjj219LYoSy0g8EvolOMGV4aSTSUNvixurCJQ+BOtsH0Uxgvf8cAdxN5brUozZKPmMW5My6/NHAelour/F3sl9ru3J2JRkC5PPiqJL11hYM= ARC-Message-Signature:i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1783458029; c=relaxed/simple; bh=0mBsGbgBTeVM/eW4enC7aj4kXxmBKZJh8tBWxys9SbU=; h=Date:From:To:Cc:Subject:Message-ID:MIME-Version:Content-Type: Content-Disposition; b=lN6lZZlc33KaW/RkIDuoZ63VqbqxcnRumMViOxEJSgLB3ePimfQbVcuGavumRIZVaTDseWWrg1Aq6L2ZtWre+OhwU2h5Zl0jY8FlBnFZk9NR7Ubc9nE8jQI21XWYUOGE1JcNpNWfKP9d3M3PICfoa35Jr5dB+b7SDIoNqrffX4I= ARC-Authentication-Results:i=1; smtp.subspace.kernel.org; dmarc=pass (p=quarantine dis=none) header.from=redhat.com; spf=pass smtp.mailfrom=redhat.com; dkim=pass (1024-bit key) header.d=redhat.com header.i=@redhat.com header.b=CgKeG76Y; dkim=pass (2048-bit key) header.d=redhat.com header.i=@redhat.com header.b=tPkzmrrl; arc=none smtp.client-ip=170.10.129.124 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=quarantine dis=none) header.from=redhat.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=redhat.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (1024-bit key) header.d=redhat.com header.i=@redhat.com header.b="CgKeG76Y"; dkim=pass (2048-bit key) header.d=redhat.com header.i=@redhat.com header.b="tPkzmrrl" DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1783458027; 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; bh=kKewETw3VUxgZoi1+l0iiO2wkszqPLLirEDaQBs0im8=; b=CgKeG76YhRNJTc2i89TrGif0dzs70UZXBoNw99xFeLXPcpEWTfbFGwHaruoy2l2lFRdcmc aFbyXrSKsnVMcluROaI1WAmLM8iz7iA0WN+d5ZPTvtT2gatc1qWB6Inyyl/Evm6PC1lpji 3N39Mh6sLknRILYSLqs7XlHveB2nyvQ= Received: from mail-wm1-f70.google.com (mail-wm1-f70.google.com [209.85.128.70]) by relay.mimecast.com with ESMTP with STARTTLS (version=TLSv1.3, cipher=TLS_AES_256_GCM_SHA384) id us-mta-417-BvDWgAn6PX-jC5HFYiws5Q-1; Tue, 07 Jul 2026 17:00:26 -0400 X-MC-Unique: BvDWgAn6PX-jC5HFYiws5Q-1 X-Mimecast-MFC-AGG-ID: BvDWgAn6PX-jC5HFYiws5Q_1783458024 Received: by mail-wm1-f70.google.com with SMTP id 5b1f17b1804b1-493bfc3b84aso21549545e9.0 for ; Tue, 07 Jul 2026 14:00:25 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=google; t=1783458024; x=1784062824; darn=vger.kernel.org; h=content-disposition:mime-version:message-id:subject:cc:to:from:date :from:to:cc:subject:date:message-id:reply-to; bh=kKewETw3VUxgZoi1+l0iiO2wkszqPLLirEDaQBs0im8=; b=tPkzmrrlmy7f5NaJKWP+7ot1ntxHIoQo2LdvZR3fiTjMVF5IwFxwl7RXeLHckmyzk3 MOQ+UrOnf4wME5s+FUgl70feFOHg/CW5qrReO4qAMvvzpIUvwkZ3b87waYIs3Q3odke0 I2vXI7yf22KJzmYn+dmfL2NYl5FgOKfmgaEopkNtBmpBXBgCEvEDo1pf4PXVCKgLMdSW uz7RD45w2f280YdPMwr0ZbqX01WKZmnoHdcxBOhaSWbbj+zbAHciwDv0gKgn8v82ZbZu AnBXM9Qkx2/wtYHPQoTvilFDZXjevmGg1bKTq+TVTlvyV23ujpP9Qvn7aCfvEqG82pPZ /ScA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20251104; t=1783458024; x=1784062824; h=content-disposition:mime-version:message-id:subject:cc:to:from:date :x-gm-gg:x-gm-message-state:from:to:cc:subject:date:message-id :reply-to; bh=kKewETw3VUxgZoi1+l0iiO2wkszqPLLirEDaQBs0im8=; b=li14ezTOPuKkUbtV8UVG65o+UcxQeK56ovzrFG6y4I6LWzvWtHlK071kIDj7f99iwH lMtnLCg/3d1YEMWCn4sEYjIZ0+XyTFd2W5JNLNsC4jTKTOJKOOODjQ4kb8OGzILTlfJg zZPFuGgdPl3IKRG63kldTeHxM10ep+J7ebWJolct8+L5vW5xllWVeEGfe1+uP5yfPGGD mOLYO/4/BnwnAsdBrv3d1WXEB+OzkrVDY6KYiJJ6MhdI6gqHaPuygysp37C8Fn1O7WRb XzET63EyhoqrRxjixxD4cWzXWNXlSvTp9COMXxB6EAboc2Yw8C107YWAm3geXPYqhGYv 2S2g== X-Gm-Message-State: AOJu0YyyVw2HxUfrOYZhIZl3G+KI37Kfw4Z381UwUiqozcMEF/e6D7ru NT9QRvnM4EQalICYr+QZ7jpbi+B8W4zU/GA4+qyOYRoopy0e1TLEZtSQd+6HZcqMgl/fy69Kthf JyoP/Mb+IIy+gL/lttG3MKUPgdakOhHYnW87wPAWIEuJkTug/lP1ZOnTtwft8CMvwS3ry7oaYAB vNpUObBQoQ4fSNcS67JJr5eI1Tn/Mla4EOnbts0JjO4dU= X-Gm-Gg: AfdE7cmXCfRO+8cDXJGy/kZK5mSvHY3RFr5sgJr34QbreV4lhj53qzvTnVgNZT/wj12 EFNpqhIWlMyrOaEKcCAh51PuKiQMVNy1q41SwxG7GjKEpigtTk8FGSWbE+m/WrUv+MQ5t5Oq37M fE3j3s2ukuzhtW62u4V+mwpN+sp+GrYqVq0lYTy3sDfE/truDHj30JpmMI/mKh+FSfrJUfjq8gz zfK8id41Zc3myAMHlef148Sbd87vxObUNaK7wSvboV0dUnAjtf1zw5YFgUZzansBhh0Hd+ylxP4 fcSdLzSwaO793hiuy+cxbfrIbtcj9k0IkuE8lGdzjWP1+1Inl06jkhyqBbP2F54KQNu7npGNC8k l5b0lRBGd8OPCdDyMhcqid3hGXJ9lDc8o X-Received: by 2002:a05:600c:15d2:b0:493:b56b:c45c with SMTP id 5b1f17b1804b1-493df06cfdamr51675885e9.30.1783458023794; Tue, 07 Jul 2026 14:00:23 -0700 (PDT) X-Received: by 2002:a05:600c:15d2:b0:493:b56b:c45c with SMTP id 5b1f17b1804b1-493df06cfdamr51675435e9.30.1783458023000; Tue, 07 Jul 2026 14:00:23 -0700 (PDT) Received: from redhat.com (IGLD-80-230-68-31.inter.net.il. [80.230.68.31]) by smtp.gmail.com with ESMTPSA id ffacd0b85a97d-47a9e4d7801sm37233013f8f.16.2026.07.07.14.00.21 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Tue, 07 Jul 2026 14:00:22 -0700 (PDT) Date: Tue, 7 Jul 2026 17:00:20 -0400 From: "Michael S. Tsirkin" To: linux-kernel@vger.kernel.org Cc: David Hildenbrand , Jason Wang , Xuan Zhuo , Eugenio =?utf-8?B?UMOpcmV6?= , Adam Litke , Rusty Russell , virtualization@lists.linux.dev Subject: [PATCH v4] virtio_balloon: prime stats vq after virtio_device_ready() Message-ID: <135278ef075f563ca5b0f3a40e2afcfeb7454f99.1783457622.git.mst@redhat.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Type: text/plain; charset=us-ascii Content-Disposition: inline X-Mailer: git-send-email 2.51.2.2891.g4157995a80.dirty X-Mutt-Fcc: =sent The virtio spec requires the driver not to kick the device before DRIVER_OK is set. init_vqs() primes the stats virtqueue with a buffer and kicks the device before virtio_device_ready() is called in virtballoon_probe(), violating this requirement. Further, if the device responds to the early kick by processing the buffer before DRIVER_OK, stats_request() fires and queues update_balloon_stats_work. Should probe then fail and free vb, the work runs against freed memory. To fix, move buffer setup to after DRIVER_OK. Be careful to disable update_balloon_stats_work while this is going on, to make sure it does not race with the setup. Testing: tested that stats still work after the change. Fixes: 9564e138b1f6 ("virtio: Add memory statistics reporting to the balloon driver (V4)") Reported-by: Sashiko:gemini-3.1-pro-preview Cc: David Hildenbrand Assisted-by: Claude:claude-sonnet-4-6 Signed-off-by: Michael S. Tsirkin --- v4: extract stats_update_and_send() helper; call get_buf() before updating stats buffer in stats_handle_request(). also ignore add bug failures (never trigger anyway) (reported by sashiko) v3: add disable_work comment and BUG_ON -> WARN_ON_ONCE (David Hildenbrand) v2: check that work enable/disable is balanced; explain how add_outbuf never fails in probe/restore drivers/virtio/virtio_balloon.c | 67 +++++++++++++++++++-------------- 1 file changed, 39 insertions(+), 28 deletions(-) diff --git a/drivers/virtio/virtio_balloon.c b/drivers/virtio/virtio_balloon.c index 088b3a0e6ce6..4c4b9bea4356 100644 --- a/drivers/virtio/virtio_balloon.c +++ b/drivers/virtio/virtio_balloon.c @@ -417,6 +417,17 @@ static unsigned int update_balloon_stats(struct virtio_balloon *vb) return idx; } +static void stats_update_and_send(struct virtio_balloon *vb) +{ + struct scatterlist sg; + unsigned int num_stats; + + num_stats = update_balloon_stats(vb); + sg_init_one(&sg, vb->stats, sizeof(vb->stats[0]) * num_stats); + virtqueue_add_outbuf(vb->stats_vq, &sg, 1, vb, GFP_KERNEL); + virtqueue_kick(vb->stats_vq); +} + /* * While most virtqueues communicate guest-initiated requests to the hypervisor, * the stats queue operates in reverse. The driver initializes the virtqueue @@ -440,18 +451,11 @@ static void stats_request(struct virtqueue *vq) static void stats_handle_request(struct virtio_balloon *vb) { - struct virtqueue *vq; - struct scatterlist sg; - unsigned int len, num_stats; + unsigned int len; - num_stats = update_balloon_stats(vb); - - vq = vb->stats_vq; - if (!virtqueue_get_buf(vq, &len)) + if (!virtqueue_get_buf(vb->stats_vq, &len)) return; - sg_init_one(&sg, vb->stats, sizeof(vb->stats[0]) * num_stats); - virtqueue_add_outbuf(vq, &sg, 1, vb, GFP_KERNEL); - virtqueue_kick(vq); + stats_update_and_send(vb); } static inline s64 towards_target(struct virtio_balloon *vb) @@ -611,25 +615,9 @@ static int init_vqs(struct virtio_balloon *vb) vb->inflate_vq = vqs[VIRTIO_BALLOON_VQ_INFLATE]; vb->deflate_vq = vqs[VIRTIO_BALLOON_VQ_DEFLATE]; if (virtio_has_feature(vb->vdev, VIRTIO_BALLOON_F_STATS_VQ)) { - struct scatterlist sg; - unsigned int num_stats; vb->stats_vq = vqs[VIRTIO_BALLOON_VQ_STATS]; - - /* - * Prime this virtqueue with one buffer so the hypervisor can - * use it to signal us later (it can't be broken yet!). - */ - num_stats = update_balloon_stats(vb); - - sg_init_one(&sg, vb->stats, sizeof(vb->stats[0]) * num_stats); - err = virtqueue_add_outbuf(vb->stats_vq, &sg, 1, vb, - GFP_KERNEL); - if (err) { - dev_warn(&vb->vdev->dev, "%s: add stat_vq failed\n", - __func__); - return err; - } - virtqueue_kick(vb->stats_vq); + /* Prevent update_balloon_stats_work from accessing the stats vq. */ + disable_work(&vb->update_balloon_stats_work); } if (virtio_has_feature(vb->vdev, VIRTIO_BALLOON_F_FREE_PAGE_HINT)) @@ -916,6 +904,25 @@ static int virtio_balloon_register_shrinker(struct virtio_balloon *vb) return 0; } +static void setup_vqs(struct virtio_balloon *vb) +{ + bool ret; + + if (!virtio_has_feature(vb->vdev, VIRTIO_BALLOON_F_STATS_VQ)) + return; + + /* + * Prime this virtqueue with one buffer so the hypervisor can + * use it to signal us later (it can't be broken yet!). + */ + stats_update_and_send(vb); + + ret = enable_and_queue_work(system_freezable_wq, + &vb->update_balloon_stats_work); + /* Make sure we balanced enable/disable, or we won't report stats. */ + WARN_ON_ONCE(!ret); +} + static int virtballoon_probe(struct virtio_device *vdev) { struct virtio_balloon *vb; @@ -1059,6 +1066,8 @@ static int virtballoon_probe(struct virtio_device *vdev) virtio_device_ready(vdev); + setup_vqs(vb); + if (towards_target(vb)) virtballoon_changed(vdev); return 0; @@ -1148,6 +1157,8 @@ static int virtballoon_restore(struct virtio_device *vdev) virtio_device_ready(vdev); + setup_vqs(vb); + if (towards_target(vb)) virtballoon_changed(vdev); update_balloon_size(vb); -- MST