* Re: [PATCH] mm/balloon: expose per-node balloon pages in node meminfo
From: David Hildenbrand (Arm) @ 2026-05-08 8:23 UTC (permalink / raw)
To: Hao Ge, Andrew Morton; +Cc: linux-mm, virtualization, linux-kernel
In-Reply-To: <20260508015316.25722-1-hao.ge@linux.dev>
On 5/8/26 03:53, Hao Ge wrote:
> Commit 835de37603ef ("meminfo: add a per node counter for balloon
> drivers") added NR_BALLOON_PAGES and exposed it in /proc/meminfo.
> However, the per-node view at /sys/devices/system/node/nodeX/meminfo
> was not updated, even though the counter is already tracked per-node.
>
> Add it to node_read_meminfo() so users can see balloon usage per
> NUMA node without having to parse the raw vmstat file.
Using ballooning with vNUMA is rather rare. But sure, why not.
>
> Signed-off-by: Hao Ge <hao.ge@linux.dev>
> ---
> drivers/base/node.c | 4 +++-
> 1 file changed, 3 insertions(+), 1 deletion(-)
>
> diff --git a/drivers/base/node.c b/drivers/base/node.c
> index d7647d077b66..53f4e51d6d82 100644
> --- a/drivers/base/node.c
> +++ b/drivers/base/node.c
> @@ -513,6 +513,7 @@ static ssize_t node_read_meminfo(struct device *dev,
> "Node %d Slab: %8lu kB\n"
> "Node %d SReclaimable: %8lu kB\n"
> "Node %d SUnreclaim: %8lu kB\n"
> + "Node %d Balloon: %8lu kB\n"
> #ifdef CONFIG_TRANSPARENT_HUGEPAGE
> "Node %d AnonHugePages: %8lu kB\n"
> "Node %d ShmemHugePages: %8lu kB\n"
> @@ -543,7 +544,8 @@ static ssize_t node_read_meminfo(struct device *dev,
> node_page_state(pgdat, NR_KERNEL_MISC_RECLAIMABLE)),
> nid, K(sreclaimable + sunreclaimable),
> nid, K(sreclaimable),
> - nid, K(sunreclaimable)
> + nid, K(sunreclaimable),
> + nid, K(node_page_state(pgdat, NR_BALLOON_PAGES))
> #ifdef CONFIG_TRANSPARENT_HUGEPAGE
> ,
> nid, K(node_page_state(pgdat, NR_ANON_THPS)),
Shouldn't it be placed under "Unaccepted:", just like for /proc/meminfo?
--
Cheers,
David
^ permalink raw reply
* Re: drm/bochs: Drop manual put on probe error path
From: Markus Elfring @ 2026-05-08 7:43 UTC (permalink / raw)
To: Thomas Zimmermann, Myeonghun Pak, dri-devel, virtualization,
David Airlie, Gerd Hoffmann, Maarten Lankhorst, Maxime Ripard,
Simona Vetter
Cc: LKML
In-Reply-To: <da9ecab6-063f-4c29-a685-7b776234905a@suse.de>
…
> > Return the probe error directly and let devres own the final put.
…
> Fixes: 04826f588682 ("drm/bochs: Allocate DRM device in struct
> bochs_device")
…
See also once more:
https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/tree/Documentation/process/submitting-patches.rst?h=v7.1-rc2#n145
Regards,
Markus
^ permalink raw reply
* Re: [mst-vhost:balloon 4/30] Warning: mm/mempolicy.c:2527 expecting prototype for vma_alloc_folio(). Prototype was for alloc_frozen_pages() instead
From: Michael S. Tsirkin @ 2026-05-08 6:16 UTC (permalink / raw)
To: kernel test robot; +Cc: oe-kbuild-all, kvm, virtualization, netdev
In-Reply-To: <202605080331.y1eIdVUC-lkp@intel.com>
On Fri, May 08, 2026 at 03:56:56AM +0800, kernel test robot wrote:
> tree: https://git.kernel.org/pub/scm/linux/kernel/git/mst/vhost.git balloon
> head: 9f56ee36fbf6a6d336dc6a9eaeb4f8a67cb42a31
> commit: 95744e0e9c4df79c6bc8ec96306b29c7a8e8984e [4/30] mm: move vma_alloc_folio to page_alloc.c
> config: powerpc-allmodconfig (https://download.01.org/0day-ci/archive/20260508/202605080331.y1eIdVUC-lkp@intel.com/config)
> compiler: powerpc64-linux-gcc (GCC) 15.2.0
> reproduce (this is a W=1 build): (https://download.01.org/0day-ci/archive/20260508/202605080331.y1eIdVUC-lkp@intel.com/reproduce)
>
> If you fix the issue in a separate patch/commit (i.e. not just a new version of
> the same patch/commit), kindly add following tags
> | Reported-by: kernel test robot <lkp@intel.com>
> | Closes: https://lore.kernel.org/oe-kbuild-all/202605080331.y1eIdVUC-lkp@intel.com/
>
> All warnings (new ones prefixed by >>):
>
> >> Warning: mm/mempolicy.c:2527 expecting prototype for vma_alloc_folio(). Prototype was for alloc_frozen_pages() instead
>
> --
> 0-DAY CI Kernel Test Service
> https://github.com/intel/lkp-tests/wiki
kerneldoc messed up by a rebase. will fix up.
^ permalink raw reply
* Re: [mst-vhost:balloon 6/30] Warning: mm/mempolicy.c:2444 function parameter 'user_addr' not described in '__alloc_pages_mpol'
From: Michael S. Tsirkin @ 2026-05-08 6:09 UTC (permalink / raw)
To: kernel test robot; +Cc: oe-kbuild-all, kvm, virtualization, netdev
In-Reply-To: <202605080515.6jRN5wN7-lkp@intel.com>
On Fri, May 08, 2026 at 05:26:30AM +0800, kernel test robot wrote:
> tree: https://git.kernel.org/pub/scm/linux/kernel/git/mst/vhost.git balloon
> head: 9f56ee36fbf6a6d336dc6a9eaeb4f8a67cb42a31
> commit: c4289f5a4e563611a468b4b5379025a4aa4a7c12 [6/30] mm: thread user_addr through page allocator for cache-friendly zeroing
> config: powerpc-allmodconfig (https://download.01.org/0day-ci/archive/20260508/202605080515.6jRN5wN7-lkp@intel.com/config)
> compiler: powerpc64-linux-gcc (GCC) 15.2.0
> reproduce (this is a W=1 build): (https://download.01.org/0day-ci/archive/20260508/202605080515.6jRN5wN7-lkp@intel.com/reproduce)
>
> If you fix the issue in a separate patch/commit (i.e. not just a new version of
> the same patch/commit), kindly add following tags
> | Reported-by: kernel test robot <lkp@intel.com>
> | Closes: https://lore.kernel.org/oe-kbuild-all/202605080515.6jRN5wN7-lkp@intel.com/
>
> All warnings (new ones prefixed by >>):
>
> >> Warning: mm/mempolicy.c:2444 function parameter 'user_addr' not described in '__alloc_pages_mpol'
> >> Warning: mm/mempolicy.c:2444 expecting prototype for alloc_pages_mpol(). Prototype was for __alloc_pages_mpol() instead
> Warning: mm/mempolicy.c:2547 expecting prototype for vma_alloc_folio(). Prototype was for alloc_frozen_pages() instead
>
> --
> 0-DAY CI Kernel Test Service
> https://github.com/intel/lkp-tests/wiki
kerneldoc messed up with a rebase. will fix in v6.
^ permalink raw reply
* [PATCH] vdpa/mlx5: Use kvzalloc_flex() for MTT command memory
From: Rosen Penev @ 2026-05-08 5:18 UTC (permalink / raw)
To: virtualization
Cc: Dragos Tatulea, Michael S. Tsirkin, Jason Wang, Xuan Zhuo,
Eugenio Pérez, open list
The create mkey command memory embeds the MTT array as a flexible array
member. Use kvzalloc_flex() to allocate it directly instead of open-coding
the struct_size() calculation with kvcalloc().
The MTT allocation still needs to be aligned to MLX5_VDPA_MTT_ALIGN bytes.
Since each MTT entry is __be64, align the entry count directly and avoid
carrying a separate byte length variable.
Assisted-by: Codex:GPT-5.5
Signed-off-by: Rosen Penev <rosenp@gmail.com>
---
drivers/vdpa/mlx5/core/mr.c | 7 +++----
1 file changed, 3 insertions(+), 4 deletions(-)
diff --git a/drivers/vdpa/mlx5/core/mr.c b/drivers/vdpa/mlx5/core/mr.c
index 42c2705077a6..6d02ccf9eb91 100644
--- a/drivers/vdpa/mlx5/core/mr.c
+++ b/drivers/vdpa/mlx5/core/mr.c
@@ -221,11 +221,10 @@ static int create_direct_keys(struct mlx5_vdpa_dev *mvdev, struct mlx5_vdpa_mr *
list_for_each_entry(dmr, &mr->head, list) {
struct mlx5_create_mkey_mem *cmd_mem;
- int mttlen, mttcount;
+ int mttcount;
- mttlen = roundup(MLX5_ST_SZ_BYTES(mtt) * dmr->nsg, MLX5_VDPA_MTT_ALIGN);
- mttcount = mttlen / sizeof(cmd_mem->mtt[0]);
- cmd_mem = kvcalloc(1, struct_size(cmd_mem, mtt, mttcount), GFP_KERNEL);
+ mttcount = ALIGN(dmr->nsg, MLX5_VDPA_MTT_ALIGN / sizeof(cmd_mem->mtt[0]));
+ cmd_mem = kvzalloc_flex(*cmd_mem, mtt, mttcount);
if (!cmd_mem) {
err = -ENOMEM;
goto done;
--
2.54.0
^ permalink raw reply related
* [PATCH] mm/balloon: expose per-node balloon pages in node meminfo
From: Hao Ge @ 2026-05-08 1:53 UTC (permalink / raw)
To: Andrew Morton, David Hildenbrand
Cc: linux-mm, virtualization, linux-kernel, Hao Ge
Commit 835de37603ef ("meminfo: add a per node counter for balloon
drivers") added NR_BALLOON_PAGES and exposed it in /proc/meminfo.
However, the per-node view at /sys/devices/system/node/nodeX/meminfo
was not updated, even though the counter is already tracked per-node.
Add it to node_read_meminfo() so users can see balloon usage per
NUMA node without having to parse the raw vmstat file.
Signed-off-by: Hao Ge <hao.ge@linux.dev>
---
drivers/base/node.c | 4 +++-
1 file changed, 3 insertions(+), 1 deletion(-)
diff --git a/drivers/base/node.c b/drivers/base/node.c
index d7647d077b66..53f4e51d6d82 100644
--- a/drivers/base/node.c
+++ b/drivers/base/node.c
@@ -513,6 +513,7 @@ static ssize_t node_read_meminfo(struct device *dev,
"Node %d Slab: %8lu kB\n"
"Node %d SReclaimable: %8lu kB\n"
"Node %d SUnreclaim: %8lu kB\n"
+ "Node %d Balloon: %8lu kB\n"
#ifdef CONFIG_TRANSPARENT_HUGEPAGE
"Node %d AnonHugePages: %8lu kB\n"
"Node %d ShmemHugePages: %8lu kB\n"
@@ -543,7 +544,8 @@ static ssize_t node_read_meminfo(struct device *dev,
node_page_state(pgdat, NR_KERNEL_MISC_RECLAIMABLE)),
nid, K(sreclaimable + sunreclaimable),
nid, K(sreclaimable),
- nid, K(sunreclaimable)
+ nid, K(sunreclaimable),
+ nid, K(node_page_state(pgdat, NR_BALLOON_PAGES))
#ifdef CONFIG_TRANSPARENT_HUGEPAGE
,
nid, K(node_page_state(pgdat, NR_ANON_THPS)),
--
2.25.1
^ permalink raw reply related
* Re: [PATCH net] vsock/virtio: fix potential unbounded skb queue
From: Michael S. Tsirkin @ 2026-05-07 22:48 UTC (permalink / raw)
To: Stefano Garzarella
Cc: Eric Dumazet, Arseniy Krasnov, Bobby Eshleman, Stefan Hajnoczi,
David S . Miller, Jakub Kicinski, Paolo Abeni, Simon Horman,
netdev, eric.dumazet, Arseniy Krasnov, Jason Wang, Xuan Zhuo,
Eugenio Pérez, kvm, virtualization
In-Reply-To: <afyMCyBvZpzWrLtO@sgarzare-redhat>
On Thu, May 07, 2026 at 02:59:13PM +0200, Stefano Garzarella wrote:
> On Thu, May 07, 2026 at 07:45:10AM -0400, Michael S. Tsirkin wrote:
> > On Thu, May 07, 2026 at 11:09:47AM +0200, Stefano Garzarella wrote:
> > > On Wed, May 06, 2026 at 11:37:45AM -0400, Michael S. Tsirkin wrote:
> > > > On Tue, May 05, 2026 at 06:11:13PM +0200, Stefano Garzarella wrote:
> > > > > On Tue, May 05, 2026 at 07:14:36AM -0700, Eric Dumazet wrote:
> > > > > > On Tue, May 5, 2026 at 6:52 AM Stefano Garzarella <sgarzare@redhat.com> wrote:
> > > > > > >
> > > > > > > On Thu, Apr 30, 2026 at 12:26:52PM +0000, Eric Dumazet wrote:
> > > > > > > >virtio_transport_inc_rx_pkt() checks vvs->rx_bytes + len > vvs->buf_alloc.
> > > > > > > >
> > > > > > > >virtio_transport_recv_enqueue() skips coalescing for packets
> > > > > > > >with VIRTIO_VSOCK_SEQ_EOM.
> > > > > > > >
> > > > > > > >If fed with packets with len == 0 and VIRTIO_VSOCK_SEQ_EOM,
> > > > > > > >a very large number of packets can be queued
> > > > > > > >because vvs->rx_bytes stays at 0.
> > > > > > > >
> > > > > > > >Fix this by estimating the skb metadata size:
> > > > > > > >
> > > > > > > > (Number of skbs in the queue) * SKB_TRUESIZE(0)
> > > > > > > >
> > > > > > > >Fixes: 077706165717 ("virtio/vsock: don't use skbuff state to account credit")
> > > > > > > >Signed-off-by: Eric Dumazet <edumazet@google.com>
> > > > > > > >Cc: Arseniy Krasnov <AVKrasnov@sberdevices.ru>
> > > > > > > >Cc: Stefan Hajnoczi <stefanha@redhat.com>
> > > > > > > >Cc: Stefano Garzarella <sgarzare@redhat.com>
> > > > > > > >Cc: "Michael S. Tsirkin" <mst@redhat.com>
> > > > > > > >Cc: Jason Wang <jasowang@redhat.com>
> > > > > > > >Cc: Xuan Zhuo <xuanzhuo@linux.alibaba.com>
> > > > > > > >Cc: "Eugenio Pérez" <eperezma@redhat.com>
> > > > > > > >Cc: kvm@vger.kernel.org
> > > > > > > >Cc: virtualization@lists.linux.dev
> > > > > > > >---
> > > > > > > > net/vmw_vsock/virtio_transport_common.c | 4 +++-
> > > > > > > > 1 file changed, 3 insertions(+), 1 deletion(-)
> > > > > > > >
> > > > > > > >diff --git a/net/vmw_vsock/virtio_transport_common.c b/net/vmw_vsock/virtio_transport_common.c
> > > > > > > >index 416d533f493d7b07e9c77c43f741d28cfcd0953e..9b8014516f4fb1130ae184635fbba4dfee58bd64 100644
> > > > > > > >--- a/net/vmw_vsock/virtio_transport_common.c
> > > > > > > >+++ b/net/vmw_vsock/virtio_transport_common.c
> > > > > > > >@@ -447,7 +447,9 @@ static int virtio_transport_send_pkt_info(struct vsock_sock *vsk,
> > > > > > > > static bool virtio_transport_inc_rx_pkt(struct virtio_vsock_sock *vvs,
> > > > > > > > u32 len)
> > > > > > > > {
> > > > > > > >- if (vvs->buf_used + len > vvs->buf_alloc)
> > > > > > > >+ u64 skb_overhead = (skb_queue_len(&vvs->rx_queue) + 1) * SKB_TRUESIZE(0);
> > > > > > > >+
> > > > > > > >+ if (skb_overhead + vvs->buf_used + len > vvs->buf_alloc)
> > > > > > > > return false;
> > > > > > >
> > > > > > > I'm not sure about this fix, I mean that maybe this is incomplete.
> > > > > > > In virtio-vsock, there is a credit mechanism between the two peers:
> > > > > > > https://docs.oasis-open.org/virtio/virtio/v1.3/csd01/virtio-v1.3-csd01.html#x1-4850003
> > > > > > >
> > > > > > > This takes only the payload into account, so it’s true that this problem
> > > > > > > exists; however, perhaps we should also inform the other peer of a lower
> > > > > > > credit balance, otherwise the other peer will believe it has much more
> > > > > > > credit than it actually does, send a large payload, and then the packet
> > > > > > > will be discarded and the data lost (there are no retransmissions,
> > > > > > > etc.).
> > > > > >
> > > > > > I dunno, perhaps revert 077706165717 ("virtio/vsock: don't use skbuff
> > > > > > state to account credit")
> > > > > > and find a better fix then?
> > > > >
> > > > > IIRC the same issue was there before the commit fixed by that one (commit
> > > > > 71dc9ec9ac7d ("virtio/vsock: replace virtio_vsock_pkt with sk_buff")), so
> > > > > not sure about reverting it TBH.
> > > > >
> > > > > CCing Arseniy and Bobby.
> > > > >
> > > > > >
> > > > > > There is always a discrepancy between skb->len and skb->truesize.
> > > > > > You will not be able to announce a 1MB window, and accept one milliion
> > > > > > skb of 1-byte each.
> > > > > >
> > > > > > This kind of contract is broken.
> > > > > >
> > > > >
> > > > > Yep, I agree, but before we start discarding data (and losing it), IMHO we
> > > > > should at least inform the other peer that we're out of space.
> > > > >
> > > > > @Stefan, @Michael, do you think we can do something in the spec to avoid
> > > > > this issue and in some way take into account also the metadata in the
> > > > > credit. I mean to avoid the 1-byte packets flooding.
> > > > >
> > > > > Thanks,
> > > > > Stefano
> > > >
> > > > Why do we need the metadata? Just don't keep it around if you begin
> > > > running low on memory.
> > >
> > > I don't think removing the skuffs will be easy; we added them for ebpf,
> > > zero-copy, and seqpacket as well.
> >
> > You do not need to remove them completely.
> >
> > > For now, we're already doing something:
> > > merging the skuffs if they don't have EOM set.
> >
> >
> > Right that's good. You could go further and merge with EOM too
> > if you stick the info about message boundaries somewhere else.
>
> This adds a lot of complexity IMO, but we can try.
>
> Do you have something in mind?
BER is clearly overkill but here's a POC that claude made for me,
just to give u an idea. It's clearly has a ton of issues,
for example I dislike how GFP_ATOMIC is handled.
Yet it seems to work fine in light testing.
-->
vsock/virtio: use DWARF ULEB128 to record EOM boundaries, enable cross-EOM skb coalescing
virtio_transport_recv_enqueue() currently refuses to coalesce an
incoming skb with the previous one when the previous skb carries
VIRTIO_VSOCK_SEQ_EOM. This forces one skb per seqpacket message.
For workloads with many small or zero-byte messages the per-skb
overhead (~960 bytes) dominates, causing unbounded memory growth.
Decouple message boundary tracking from the skb structure: store
boundary offsets in a compact side buffer using DWARF ULEB128
encoding with the EOR flag folded into the low bit, then allow
the data of multiple complete messages to be coalesced into a single
skb.
Cross-EOM coalescing fires only when:
- both the tail skb and the incoming packet carry EOM (complete msgs)
- the incoming packet fits in the tail skb's tailroom
- no BPF psock is attached (read_skb expects one msg per skb)
On allocation failure the code falls back to separate skbs (existing
behaviour). Credit accounting is unchanged; the boundary buffer is
capped at PAGE_SIZE.
Signed-off-by: Michael S. Tsirkin <mst@redhat.com>
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
diff --git a/include/linux/virtio_vsock.h b/include/linux/virtio_vsock.h
index f91704731057..e36b9ab28372 100644
--- a/include/linux/virtio_vsock.h
+++ b/include/linux/virtio_vsock.h
@@ -12,6 +12,7 @@
struct virtio_vsock_skb_cb {
bool reply;
bool tap_delivered;
+ bool has_boundary_entries;
u32 offset;
};
@@ -167,6 +168,12 @@ struct virtio_vsock_sock {
u32 buf_used;
struct sk_buff_head rx_queue;
u32 msg_count;
+
+ /* ULEB128-encoded seqpacket message boundary buffer */
+ u8 *boundary_buf;
+ u32 boundary_len;
+ u32 boundary_alloc;
+ u32 boundary_off;
};
struct virtio_vsock_pkt_info {
diff --git a/net/vmw_vsock/virtio_transport_common.c b/net/vmw_vsock/virtio_transport_common.c
index 416d533f493d..81654f70f72c 100644
--- a/net/vmw_vsock/virtio_transport_common.c
+++ b/net/vmw_vsock/virtio_transport_common.c
@@ -11,6 +11,7 @@
#include <linux/sched/signal.h>
#include <linux/ctype.h>
#include <linux/list.h>
+#include <linux/skmsg.h>
#include <linux/virtio_vsock.h>
#include <uapi/linux/vsockmon.h>
@@ -26,6 +27,91 @@
/* Threshold for detecting small packets to copy */
#define GOOD_COPY_LEN 128
+#define VSOCK_BOUNDARY_BUF_INIT 64
+#define VSOCK_BOUNDARY_BUF_MAX PAGE_SIZE
+
+/* ULEB128 boundary encoding: value = (msg_len << 1) | eor.
+ * Each byte carries 7 data bits; bit 7 is set on all but the last byte.
+ * Max 5 bytes for a u32 msg_len (33 bits with eor shift).
+ */
+static int vsock_uleb_encode_boundary(u8 *buf, u32 msg_len, bool eor)
+{
+ u64 val = ((u64)msg_len << 1) | eor;
+ int n = 0;
+
+ do {
+ buf[n] = val & 0x7f;
+ val >>= 7;
+ if (val)
+ buf[n] |= 0x80;
+ n++;
+ } while (val);
+
+ return n;
+}
+
+static int vsock_uleb_decode_boundary(const u8 *buf, u32 avail,
+ u32 *msg_len, bool *eor)
+{
+ u64 val = 0;
+ int shift = 0;
+ int n = 0;
+
+ do {
+ if (n >= avail || shift >= 35)
+ return -EINVAL;
+ val |= (u64)(buf[n] & 0x7f) << shift;
+ shift += 7;
+ } while (buf[n++] & 0x80);
+
+ *eor = val & 1;
+ *msg_len = val >> 1;
+ return n;
+}
+
+static void vsock_boundary_buf_compact(struct virtio_vsock_sock *vvs)
+{
+ if (vvs->boundary_off == 0)
+ return;
+
+ vvs->boundary_len -= vvs->boundary_off;
+ memmove(vvs->boundary_buf, vvs->boundary_buf + vvs->boundary_off,
+ vvs->boundary_len);
+ vvs->boundary_off = 0;
+}
+
+static int vsock_boundary_buf_ensure(struct virtio_vsock_sock *vvs, u32 needed)
+{
+ u32 new_alloc;
+ u8 *new_buf;
+
+ if (vvs->boundary_alloc >= needed)
+ return 0;
+
+ /* Reclaim consumed space before growing */
+ if (vvs->boundary_off) {
+ needed -= vvs->boundary_off;
+ vsock_boundary_buf_compact(vvs);
+ if (vvs->boundary_alloc >= needed)
+ return 0;
+ }
+
+ new_alloc = max(needed, vvs->boundary_alloc ? vvs->boundary_alloc * 2
+ : VSOCK_BOUNDARY_BUF_INIT);
+ if (new_alloc > VSOCK_BOUNDARY_BUF_MAX)
+ new_alloc = VSOCK_BOUNDARY_BUF_MAX;
+ if (new_alloc < needed)
+ return -ENOMEM;
+
+ new_buf = krealloc(vvs->boundary_buf, new_alloc, GFP_ATOMIC);
+ if (!new_buf)
+ return -ENOMEM;
+
+ vvs->boundary_buf = new_buf;
+ vvs->boundary_alloc = new_alloc;
+ return 0;
+}
+
static void virtio_transport_cancel_close_work(struct vsock_sock *vsk,
bool cancel_timeout);
static s64 virtio_transport_has_space(struct virtio_vsock_sock *vvs);
@@ -682,41 +768,74 @@ virtio_transport_seqpacket_do_peek(struct vsock_sock *vsk,
total = 0;
len = msg_data_left(msg);
- skb_queue_walk(&vvs->rx_queue, skb) {
- struct virtio_vsock_hdr *hdr;
+ skb = skb_peek(&vvs->rx_queue);
+ if (skb && VIRTIO_VSOCK_SKB_CB(skb)->has_boundary_entries) {
+ u32 msg_len, offset;
+ size_t bytes;
+ bool eor;
+ int ret;
- if (total < len) {
- size_t bytes;
+ ret = vsock_uleb_decode_boundary(
+ vvs->boundary_buf + vvs->boundary_off,
+ vvs->boundary_len - vvs->boundary_off,
+ &msg_len, &eor);
+ if (ret < 0)
+ goto unlock;
+
+ offset = VIRTIO_VSOCK_SKB_CB(skb)->offset;
+ bytes = min(len, (size_t)msg_len);
+
+ if (bytes) {
int err;
- bytes = len - total;
- if (bytes > skb->len)
- bytes = skb->len;
-
spin_unlock_bh(&vvs->rx_lock);
-
- /* sk_lock is held by caller so no one else can dequeue.
- * Unlock rx_lock since skb_copy_datagram_iter() may sleep.
- */
- err = skb_copy_datagram_iter(skb, VIRTIO_VSOCK_SKB_CB(skb)->offset,
+ err = skb_copy_datagram_iter(skb, offset,
&msg->msg_iter, bytes);
if (err)
return err;
-
spin_lock_bh(&vvs->rx_lock);
}
- total += skb->len;
- hdr = virtio_vsock_hdr(skb);
+ total = msg_len;
+ if (eor)
+ msg->msg_flags |= MSG_EOR;
+ } else {
+ skb_queue_walk(&vvs->rx_queue, skb) {
+ struct virtio_vsock_hdr *hdr;
- if (le32_to_cpu(hdr->flags) & VIRTIO_VSOCK_SEQ_EOM) {
- if (le32_to_cpu(hdr->flags) & VIRTIO_VSOCK_SEQ_EOR)
- msg->msg_flags |= MSG_EOR;
+ if (total < len) {
+ size_t bytes;
+ int err;
- break;
+ bytes = len - total;
+ if (bytes > skb->len)
+ bytes = skb->len;
+
+ spin_unlock_bh(&vvs->rx_lock);
+
+ err = skb_copy_datagram_iter(
+ skb,
+ VIRTIO_VSOCK_SKB_CB(skb)->offset,
+ &msg->msg_iter, bytes);
+ if (err)
+ return err;
+
+ spin_lock_bh(&vvs->rx_lock);
+ }
+
+ total += skb->len;
+ hdr = virtio_vsock_hdr(skb);
+
+ if (le32_to_cpu(hdr->flags) & VIRTIO_VSOCK_SEQ_EOM) {
+ if (le32_to_cpu(hdr->flags) &
+ VIRTIO_VSOCK_SEQ_EOR)
+ msg->msg_flags |= MSG_EOR;
+ break;
+ }
}
}
+unlock:
spin_unlock_bh(&vvs->rx_lock);
return total;
@@ -740,57 +859,105 @@ static int virtio_transport_seqpacket_do_dequeue(struct vsock_sock *vsk,
}
while (!msg_ready) {
- struct virtio_vsock_hdr *hdr;
- size_t pkt_len;
-
- skb = __skb_dequeue(&vvs->rx_queue);
+ skb = skb_peek(&vvs->rx_queue);
if (!skb)
break;
- hdr = virtio_vsock_hdr(skb);
- pkt_len = (size_t)le32_to_cpu(hdr->len);
- if (dequeued_len >= 0) {
+ if (VIRTIO_VSOCK_SKB_CB(skb)->has_boundary_entries) {
size_t bytes_to_copy;
+ u32 msg_len, offset;
+ bool eor;
+ int ret;
- bytes_to_copy = min(user_buf_len, pkt_len);
+ ret = vsock_uleb_decode_boundary(
+ vvs->boundary_buf + vvs->boundary_off,
+ vvs->boundary_len - vvs->boundary_off,
+ &msg_len, &eor);
+ if (ret < 0)
+ break;
+ vvs->boundary_off += ret;
- if (bytes_to_copy) {
+ offset = VIRTIO_VSOCK_SKB_CB(skb)->offset;
+ bytes_to_copy = min(user_buf_len, (size_t)msg_len);
+
+ if (bytes_to_copy && dequeued_len >= 0) {
int err;
- /* sk_lock is held by caller so no one else can dequeue.
- * Unlock rx_lock since skb_copy_datagram_iter() may sleep.
- */
spin_unlock_bh(&vvs->rx_lock);
-
- err = skb_copy_datagram_iter(skb, 0,
+ err = skb_copy_datagram_iter(skb, offset,
&msg->msg_iter,
bytes_to_copy);
- if (err) {
- /* Copy of message failed. Rest of
- * fragments will be freed without copy.
- */
- dequeued_len = err;
- } else {
- user_buf_len -= bytes_to_copy;
- }
-
spin_lock_bh(&vvs->rx_lock);
+ if (err)
+ dequeued_len = err;
+ else
+ user_buf_len -= bytes_to_copy;
}
if (dequeued_len >= 0)
- dequeued_len += pkt_len;
- }
+ dequeued_len += msg_len;
- if (le32_to_cpu(hdr->flags) & VIRTIO_VSOCK_SEQ_EOM) {
+ VIRTIO_VSOCK_SKB_CB(skb)->offset += msg_len;
msg_ready = true;
vvs->msg_count--;
- if (le32_to_cpu(hdr->flags) & VIRTIO_VSOCK_SEQ_EOR)
+ if (eor)
msg->msg_flags |= MSG_EOR;
- }
- virtio_transport_dec_rx_pkt(vvs, pkt_len, pkt_len);
- kfree_skb(skb);
+ virtio_transport_dec_rx_pkt(vvs, msg_len, msg_len);
+
+ if (VIRTIO_VSOCK_SKB_CB(skb)->offset >= skb->len) {
+ __skb_unlink(skb, &vvs->rx_queue);
+ kfree_skb(skb);
+ }
+
+ if (vvs->boundary_off >= vvs->boundary_len / 2)
+ vsock_boundary_buf_compact(vvs);
+ } else {
+ struct virtio_vsock_hdr *hdr;
+ size_t pkt_len;
+
+ skb = __skb_dequeue(&vvs->rx_queue);
+ if (!skb)
+ break;
+ hdr = virtio_vsock_hdr(skb);
+ pkt_len = (size_t)le32_to_cpu(hdr->len);
+
+ if (dequeued_len >= 0) {
+ size_t bytes_to_copy;
+
+ bytes_to_copy = min(user_buf_len, pkt_len);
+
+ if (bytes_to_copy) {
+ int err;
+
+ spin_unlock_bh(&vvs->rx_lock);
+ err = skb_copy_datagram_iter(
+ skb, 0, &msg->msg_iter,
+ bytes_to_copy);
+ if (err)
+ dequeued_len = err;
+ else
+ user_buf_len -= bytes_to_copy;
+ spin_lock_bh(&vvs->rx_lock);
+ }
+
+ if (dequeued_len >= 0)
+ dequeued_len += pkt_len;
+ }
+
+ if (le32_to_cpu(hdr->flags) & VIRTIO_VSOCK_SEQ_EOM) {
+ msg_ready = true;
+ vvs->msg_count--;
+
+ if (le32_to_cpu(hdr->flags) &
+ VIRTIO_VSOCK_SEQ_EOR)
+ msg->msg_flags |= MSG_EOR;
+ }
+
+ virtio_transport_dec_rx_pkt(vvs, pkt_len, pkt_len);
+ kfree_skb(skb);
+ }
}
spin_unlock_bh(&vvs->rx_lock);
@@ -1132,6 +1299,7 @@ void virtio_transport_destruct(struct vsock_sock *vsk)
virtio_transport_cancel_close_work(vsk, true);
+ kfree(vvs->boundary_buf);
kfree(vvs);
vsk->trans = NULL;
}
@@ -1224,6 +1392,11 @@ static void virtio_transport_remove_sock(struct vsock_sock *vsk)
* removing it.
*/
__skb_queue_purge(&vvs->rx_queue);
+ kfree(vvs->boundary_buf);
+ vvs->boundary_buf = NULL;
+ vvs->boundary_len = 0;
+ vvs->boundary_alloc = 0;
+ vvs->boundary_off = 0;
vsock_remove_sock(vsk);
}
@@ -1395,23 +1568,62 @@ virtio_transport_recv_enqueue(struct vsock_sock *vsk,
!skb_is_nonlinear(skb)) {
struct virtio_vsock_hdr *last_hdr;
struct sk_buff *last_skb;
+ bool last_has_eom;
+ bool has_eom;
last_skb = skb_peek_tail(&vvs->rx_queue);
last_hdr = virtio_vsock_hdr(last_skb);
+ last_has_eom = le32_to_cpu(last_hdr->flags) & VIRTIO_VSOCK_SEQ_EOM;
+ has_eom = le32_to_cpu(hdr->flags) & VIRTIO_VSOCK_SEQ_EOM;
- /* If there is space in the last packet queued, we copy the
- * new packet in its buffer. We avoid this if the last packet
- * queued has VIRTIO_VSOCK_SEQ_EOM set, because this is
- * delimiter of SEQPACKET message, so 'pkt' is the first packet
- * of a new message.
- */
- if (skb->len < skb_tailroom(last_skb) &&
- !(le32_to_cpu(last_hdr->flags) & VIRTIO_VSOCK_SEQ_EOM)) {
- memcpy(skb_put(last_skb, skb->len), skb->data, skb->len);
- free_pkt = true;
- last_hdr->flags |= hdr->flags;
- le32_add_cpu(&last_hdr->len, len);
- goto out;
+ if (skb->len < skb_tailroom(last_skb)) {
+ if (!last_has_eom) {
+ /* Same-message coalescing (existing path) */
+ memcpy(skb_put(last_skb, skb->len),
+ skb->data, skb->len);
+ free_pkt = true;
+ last_hdr->flags |= hdr->flags;
+ le32_add_cpu(&last_hdr->len, len);
+ goto out;
+ }
+
+ /* Cross-EOM: coalesce complete messages into one skb,
+ * recording message boundaries in a compact BER buffer.
+ * Only when incoming packet also has EOM (complete msg).
+ */
+ if (has_eom && !sk_psock(sk_vsock(vsk))) {
+ bool prev_eor, cur_eor;
+ u8 tmp[12];
+ int n = 0;
+
+ cur_eor = le32_to_cpu(hdr->flags) &
+ VIRTIO_VSOCK_SEQ_EOR;
+
+ if (!VIRTIO_VSOCK_SKB_CB(last_skb)->has_boundary_entries) {
+ u32 prev_len = le32_to_cpu(last_hdr->len);
+
+ prev_eor = le32_to_cpu(last_hdr->flags) &
+ VIRTIO_VSOCK_SEQ_EOR;
+ n += vsock_uleb_encode_boundary(
+ tmp + n, prev_len, prev_eor);
+ }
+ n += vsock_uleb_encode_boundary(
+ tmp + n, len, cur_eor);
+
+ if (!vsock_boundary_buf_ensure(
+ vvs, vvs->boundary_len + n)) {
+ memcpy(vvs->boundary_buf +
+ vvs->boundary_len, tmp, n);
+ vvs->boundary_len += n;
+ VIRTIO_VSOCK_SKB_CB(last_skb)->has_boundary_entries = true;
+ memcpy(skb_put(last_skb, skb->len),
+ skb->data, skb->len);
+ free_pkt = true;
+ last_hdr->flags |= hdr->flags;
+ le32_add_cpu(&last_hdr->len, len);
+ goto out;
+ }
+ }
}
}
^ permalink raw reply related
* [PATCH v5 28/28] virtio_balloon: implement VIRTIO_BALLOON_F_DEVICE_INIT_REPORTED
From: Michael S. Tsirkin @ 2026-05-07 22:23 UTC (permalink / raw)
To: linux-kernel
Cc: David Hildenbrand, Jason Wang, Xuan Zhuo, Eugenio Pérez,
virtualization
In-Reply-To: <cover.1778192416.git.mst@redhat.com>
Add VIRTIO_BALLOON_F_DEVICE_INIT_REPORTED (bit 6): when negotiated,
the device guarantees it initializes reported pages (zeros, or
poison_val if PAGE_POISON). The device signals success via the
used length of each reporting_vq element.
Gate host_zeroes_pages on both the feature bit and the actual
page content: when PAGE_POISON is negotiated with poison_val != 0,
the device fills with poison bytes, not zeros.
Clear the feature in validate() if REPORTING is not present or if running in a
confidential computing environment (untrusted host).
Renumber DEVICE_INIT_ON_INFLATE from bit 6 to bit 7 to make room.
See the virtio spec change:
https://github.com/oasis-tcs/virtio-spec/issues/244
Signed-off-by: Michael S. Tsirkin <mst@redhat.com>
Assisted-by: Claude:claude-opus-4-6
Assisted-by: cursor-agent:GPT-5.4-xhigh
virtio_balloon: skip zeroing for host-zeroed reported pages
Check per-page used length returned by the device to determine
which reported pages were zeroed. If used_len matches the page
size, the device successfully initialized the page (e.g. via
MADV_DONTNEED), and we set the corresponding zeroed_bitmap bit.
This requires no feature negotiation: existing devices return
used_len=0 (the conservative "not zeroed" case), while updated
devices return the page size on successful discard.
host_zeroes_pages is set unconditionally so the page_reporting
drain path checks the bitmap and marks matching pages as PG_zeroed
in the buddy allocator.
Signed-off-by: Michael S. Tsirkin <mst@redhat.com>
Assisted-by: Claude:claude-opus-4-6
---
drivers/virtio/virtio_balloon.c | 30 ++++++++++++++++++++++++++---
include/uapi/linux/virtio_balloon.h | 3 ++-
2 files changed, 29 insertions(+), 4 deletions(-)
diff --git a/drivers/virtio/virtio_balloon.c b/drivers/virtio/virtio_balloon.c
index 1eb9a6376038..f1ad842eb3d6 100644
--- a/drivers/virtio/virtio_balloon.c
+++ b/drivers/virtio/virtio_balloon.c
@@ -218,6 +218,8 @@ static int virtballoon_free_page_report(struct page_reporting_dev_info *pr_dev_i
struct virtqueue *vq = vb->reporting_vq;
unsigned int i, err;
+ bitmap_zero(pr_dev_info->zeroed_bitmap, nents);
+
/* We should always be able to add these buffers to an empty queue. */
for (i = 0; i < nents; i++) {
struct scatterlist one;
@@ -237,10 +239,14 @@ static int virtballoon_free_page_report(struct page_reporting_dev_info *pr_dev_i
/* When host has read buffer, this completes via balloon_ack */
for (i = 0; i < nents; i++) {
- unsigned int unused;
+ struct scatterlist *entry;
+ unsigned int used_len;
wait_event(vb->acked,
- virtqueue_get_buf(vq, &unused));
+ (entry = virtqueue_get_buf(vq, &used_len)));
+ if (used_len == entry->length)
+ set_bit(entry - sg,
+ pr_dev_info->zeroed_bitmap);
}
}
@@ -1118,8 +1124,16 @@ static int virtballoon_probe(struct virtio_device *vdev)
#endif
vb->pr_dev_info.capacity = capacity;
+ /*
+ * With PAGE_POISON, device fills with poison_val not
+ * zeros; only treat as zeroed when poison_val is 0.
+ */
vb->pr_dev_info.host_zeroes_pages =
- !cc_platform_has(CC_ATTR_GUEST_MEM_ENCRYPT);
+ virtio_has_feature(vdev,
+ VIRTIO_BALLOON_F_DEVICE_INIT_REPORTED) &&
+ (!virtio_has_feature(vdev,
+ VIRTIO_BALLOON_F_PAGE_POISON) ||
+ want_init_on_free());
err = page_reporting_register(&vb->pr_dev_info);
if (err)
goto out_unregister_oom;
@@ -1245,9 +1259,18 @@ static int virtballoon_validate(struct virtio_device *vdev)
else if (!virtio_has_feature(vdev, VIRTIO_BALLOON_F_PAGE_POISON))
__virtio_clear_bit(vdev, VIRTIO_BALLOON_F_REPORTING);
+ if (!virtio_has_feature(vdev, VIRTIO_BALLOON_F_REPORTING))
+ __virtio_clear_bit(vdev, VIRTIO_BALLOON_F_DEVICE_INIT_REPORTED);
+
+ /* Device fills with poison_val, not zeros; disable zeroed hint */
if (virtio_has_feature(vdev, VIRTIO_BALLOON_F_PAGE_POISON) &&
!want_init_on_free())
__virtio_clear_bit(vdev, VIRTIO_BALLOON_F_DEVICE_INIT_ON_INFLATE);
+
+ if (cc_platform_has(CC_ATTR_GUEST_MEM_ENCRYPT)) {
+ __virtio_clear_bit(vdev, VIRTIO_BALLOON_F_DEVICE_INIT_REPORTED);
+ __virtio_clear_bit(vdev, VIRTIO_BALLOON_F_DEVICE_INIT_ON_INFLATE);
+ }
__virtio_clear_bit(vdev, VIRTIO_F_ACCESS_PLATFORM);
return 0;
}
@@ -1259,6 +1282,7 @@ static unsigned int features[] = {
VIRTIO_BALLOON_F_FREE_PAGE_HINT,
VIRTIO_BALLOON_F_PAGE_POISON,
VIRTIO_BALLOON_F_REPORTING,
+ VIRTIO_BALLOON_F_DEVICE_INIT_REPORTED,
VIRTIO_BALLOON_F_DEVICE_INIT_ON_INFLATE,
};
diff --git a/include/uapi/linux/virtio_balloon.h b/include/uapi/linux/virtio_balloon.h
index d129736cc3a8..cbaf18e0b17c 100644
--- a/include/uapi/linux/virtio_balloon.h
+++ b/include/uapi/linux/virtio_balloon.h
@@ -37,7 +37,8 @@
#define VIRTIO_BALLOON_F_FREE_PAGE_HINT 3 /* VQ to report free pages */
#define VIRTIO_BALLOON_F_PAGE_POISON 4 /* Guest is using page poisoning */
#define VIRTIO_BALLOON_F_REPORTING 5 /* Page reporting virtqueue */
-#define VIRTIO_BALLOON_F_DEVICE_INIT_ON_INFLATE 6 /* Device initializes pages on inflate */
+#define VIRTIO_BALLOON_F_DEVICE_INIT_REPORTED 6 /* Device initializes reported pages */
+#define VIRTIO_BALLOON_F_DEVICE_INIT_ON_INFLATE 7 /* Device initializes pages on inflate */
/* Size of a PFN in the balloon interface. */
#define VIRTIO_BALLOON_PFN_SHIFT 12
--
MST
^ permalink raw reply related
* [PATCH v5 27/28] virtio_balloon: disable reporting zeroed optimization for confidential guests
From: Michael S. Tsirkin @ 2026-05-07 22:23 UTC (permalink / raw)
To: linux-kernel
Cc: David Hildenbrand, Jason Wang, Xuan Zhuo, Eugenio Pérez,
virtualization
In-Reply-To: <cover.1778192416.git.mst@redhat.com>
In confidential computing environments (TDX, SEV-SNP), the host
is untrusted and may lie about zeroing reported pages. Disable
host_zeroes_pages so the guest does not skip re-zeroing based on
the used_len hint from an untrusted device.
Signed-off-by: Michael S. Tsirkin <mst@redhat.com>
Assisted-by: Claude:claude-opus-4-6
---
drivers/virtio/virtio_balloon.c | 3 +++
1 file changed, 3 insertions(+)
diff --git a/drivers/virtio/virtio_balloon.c b/drivers/virtio/virtio_balloon.c
index 708b0c344ae9..1eb9a6376038 100644
--- a/drivers/virtio/virtio_balloon.c
+++ b/drivers/virtio/virtio_balloon.c
@@ -18,6 +18,7 @@
#include <linux/wait.h>
#include <linux/mm.h>
#include <linux/page_reporting.h>
+#include <linux/cc_platform.h>
/*
* Balloon device works in 4K page units. So each page is pointed to by
@@ -1117,6 +1118,8 @@ static int virtballoon_probe(struct virtio_device *vdev)
#endif
vb->pr_dev_info.capacity = capacity;
+ vb->pr_dev_info.host_zeroes_pages =
+ !cc_platform_has(CC_ATTR_GUEST_MEM_ENCRYPT);
err = page_reporting_register(&vb->pr_dev_info);
if (err)
goto out_unregister_oom;
--
MST
^ permalink raw reply related
* [PATCH v5 26/28] mm: balloon: use put_page_zeroed for zeroed balloon pages
From: Michael S. Tsirkin @ 2026-05-07 22:23 UTC (permalink / raw)
To: linux-kernel; +Cc: Andrew Morton, David Hildenbrand, linux-mm, virtualization
In-Reply-To: <cover.1778192416.git.mst@redhat.com>
When a balloon page marked PageZeroed is freed during migration,
use put_page_zeroed() to propagate the zeroed hint to the buddy
allocator. Previously the hint was silently lost via plain put_page().
Signed-off-by: Michael S. Tsirkin <mst@redhat.com>
Assisted-by: Claude:claude-opus-4-6
---
mm/balloon.c | 7 ++++++-
1 file changed, 6 insertions(+), 1 deletion(-)
diff --git a/mm/balloon.c b/mm/balloon.c
index 96a8f1e20bc6..1bf7eb2642a9 100644
--- a/mm/balloon.c
+++ b/mm/balloon.c
@@ -324,7 +324,12 @@ static int balloon_page_migrate(struct page *newpage, struct page *page,
balloon_page_finalize(page);
spin_unlock_irqrestore(&balloon_pages_lock, flags);
- put_page(page);
+ if (PageZeroed(page)) {
+ __ClearPageZeroed(page);
+ put_page_zeroed(page);
+ } else {
+ put_page(page);
+ }
return 0;
}
--
MST
^ permalink raw reply related
* [PATCH v5 25/28] virtio_balloon: implement VIRTIO_BALLOON_F_DEVICE_INIT_ON_INFLATE
From: Michael S. Tsirkin @ 2026-05-07 22:23 UTC (permalink / raw)
To: linux-kernel
Cc: David Hildenbrand, Jason Wang, Xuan Zhuo, Eugenio Pérez,
virtualization
In-Reply-To: <cover.1778192416.git.mst@redhat.com>
When the device offers DEVICE_INIT_ON_INFLATE (bit 7), the device
initializes inflated pages and returns a per-page bitmap indicating
which pages were successfully initialized.
The driver appends a device-writable bitmap buffer to each inflate
descriptor chain via virtqueue_add_sgs. After the host acknowledges,
the driver checks bitmap bits (bounded by used_len) and marks pages
with SetPageZeroed.
tell_host() returns used_len from virtqueue_get_buf(). Bitmap reads
are bounded: fill_balloon() and virtballoon_migratepage() only trust
bits within the used_len range.
On deflate, release_pages_balloon checks PageZeroed per page and
uses put_page_zeroed for pages the host initialized, propagating
the zeroed hint to the buddy allocator.
If inflate_vq has fewer than 2 descriptors, the feature is
cleared at probe time. If PAGE_POISON is negotiated with non-zero
poison_val, the feature is cleared in validate().
See the virtio spec change:
https://lore.kernel.org/all/9c69b992c3dd83dfef3db92cd86b2fd8a0730d48.1777731396.git.mst@redhat.com
Signed-off-by: Michael S. Tsirkin <mst@redhat.com>
Assisted-by: Claude:claude-opus-4-6
Assisted-by: cursor-agent:GPT-5.4-xhigh
---
drivers/virtio/virtio_balloon.c | 97 +++++++++++++++++++++++++----
include/uapi/linux/virtio_balloon.h | 1 +
2 files changed, 87 insertions(+), 11 deletions(-)
diff --git a/drivers/virtio/virtio_balloon.c b/drivers/virtio/virtio_balloon.c
index e99ffbbdd2bd..708b0c344ae9 100644
--- a/drivers/virtio/virtio_balloon.c
+++ b/drivers/virtio/virtio_balloon.c
@@ -120,6 +120,9 @@ struct virtio_balloon {
struct virtqueue *reporting_vq;
struct page_reporting_dev_info pr_dev_info;
+ /* Bitmap returned by host for DEVICE_INIT_ON_INFLATE */
+ DECLARE_BITMAP(inflate_bitmap, VIRTIO_BALLOON_ARRAY_PFNS_MAX);
+
/* State for keeping the wakeup_source active while adjusting the balloon */
spinlock_t wakeup_lock;
bool processing_wakeup_event;
@@ -180,20 +183,30 @@ static void balloon_ack(struct virtqueue *vq)
wake_up(&vb->acked);
}
-static void tell_host(struct virtio_balloon *vb, struct virtqueue *vq)
+static unsigned int tell_host(struct virtio_balloon *vb, struct virtqueue *vq)
{
- struct scatterlist sg;
+ struct scatterlist sg_out, sg_in;
+ struct scatterlist *sgs[] = { &sg_out, &sg_in };
unsigned int len;
- sg_init_one(&sg, vb->pfns, sizeof(vb->pfns[0]) * vb->num_pfns);
+ sg_init_one(&sg_out, vb->pfns, sizeof(vb->pfns[0]) * vb->num_pfns);
- /* We should always be able to add one buffer to an empty queue. */
- virtqueue_add_outbuf(vq, &sg, 1, vb, GFP_KERNEL);
+ if (vq == vb->inflate_vq &&
+ virtio_has_feature(vb->vdev,
+ VIRTIO_BALLOON_F_DEVICE_INIT_ON_INFLATE)) {
+ unsigned int bitmap_bytes;
+
+ bitmap_bytes = DIV_ROUND_UP(vb->num_pfns, 8);
+ bitmap_zero(vb->inflate_bitmap, vb->num_pfns);
+ sg_init_one(&sg_in, vb->inflate_bitmap, bitmap_bytes);
+ virtqueue_add_sgs(vq, sgs, 1, 1, vb, GFP_KERNEL);
+ } else {
+ virtqueue_add_outbuf(vq, &sg_out, 1, vb, GFP_KERNEL);
+ }
virtqueue_kick(vq);
- /* When host has read buffer, this completes via balloon_ack */
wait_event(vb->acked, virtqueue_get_buf(vq, &len));
-
+ return len;
}
static int virtballoon_free_page_report(struct page_reporting_dev_info *pr_dev_info,
@@ -290,8 +303,37 @@ static unsigned int fill_balloon(struct virtio_balloon *vb, size_t num)
num_allocated_pages = vb->num_pfns;
/* Did we get any? */
- if (vb->num_pfns != 0)
- tell_host(vb, vb->inflate_vq);
+ if (vb->num_pfns != 0) {
+ unsigned int used_len = tell_host(vb, vb->inflate_vq);
+
+ if (virtio_has_feature(vb->vdev,
+ VIRTIO_BALLOON_F_DEVICE_INIT_ON_INFLATE)) {
+ unsigned int i;
+ unsigned int valid_bits = used_len * 8;
+
+ for (i = 0; i < vb->num_pfns;
+ i += VIRTIO_BALLOON_PAGES_PER_PAGE) {
+ unsigned int pfn, j;
+ bool zeroed = true;
+
+ if (i + VIRTIO_BALLOON_PAGES_PER_PAGE > valid_bits)
+ break;
+ for (j = 0; j < VIRTIO_BALLOON_PAGES_PER_PAGE; j++) {
+ if (!test_bit(i + j, vb->inflate_bitmap)) {
+ zeroed = false;
+ break;
+ }
+ }
+ if (zeroed) {
+ pfn = virtio32_to_cpu(vb->vdev,
+ vb->pfns[i]);
+ __SetPageZeroed(pfn_to_page(pfn >>
+ (PAGE_SHIFT -
+ VIRTIO_BALLOON_PFN_SHIFT)));
+ }
+ }
+ }
+ }
mutex_unlock(&vb->balloon_lock);
return num_allocated_pages;
@@ -304,7 +346,12 @@ static void release_pages_balloon(struct virtio_balloon *vb,
list_for_each_entry_safe(page, next, pages, lru) {
list_del(&page->lru);
- put_page(page); /* balloon reference */
+ if (PageZeroed(page)) {
+ __ClearPageZeroed(page);
+ put_page_zeroed(page);
+ } else {
+ put_page(page);
+ }
}
}
@@ -851,7 +898,25 @@ static int virtballoon_migratepage(struct balloon_dev_info *vb_dev_info,
/* balloon's page migration 1st step -- inflate "newpage" */
vb->num_pfns = VIRTIO_BALLOON_PAGES_PER_PAGE;
set_page_pfns(vb, vb->pfns, newpage);
- tell_host(vb, vb->inflate_vq);
+ {
+ unsigned int used_len = tell_host(vb, vb->inflate_vq);
+
+ if (virtio_has_feature(vb->vdev,
+ VIRTIO_BALLOON_F_DEVICE_INIT_ON_INFLATE) &&
+ used_len >= DIV_ROUND_UP(VIRTIO_BALLOON_PAGES_PER_PAGE, 8)) {
+ unsigned int j;
+ bool zeroed = true;
+
+ for (j = 0; j < VIRTIO_BALLOON_PAGES_PER_PAGE; j++) {
+ if (!test_bit(j, vb->inflate_bitmap)) {
+ zeroed = false;
+ break;
+ }
+ }
+ if (zeroed)
+ __SetPageZeroed(newpage);
+ }
+ }
/* balloon's page migration 2nd step -- deflate "page" */
vb->num_pfns = VIRTIO_BALLOON_PAGES_PER_PAGE;
@@ -956,6 +1021,12 @@ static int virtballoon_probe(struct virtio_device *vdev)
if (err)
goto out_free_vb;
+ if (virtio_has_feature(vdev, VIRTIO_BALLOON_F_DEVICE_INIT_ON_INFLATE) &&
+ virtqueue_get_vring_size(vb->inflate_vq) < 2) {
+ err = -ENOSPC;
+ goto out_del_vqs;
+ }
+
if (!virtio_has_feature(vb->vdev, VIRTIO_BALLOON_F_DEFLATE_ON_OOM))
vb->vb_dev_info.adjust_managed_page_count = true;
#ifdef CONFIG_BALLOON_MIGRATION
@@ -1171,6 +1242,9 @@ static int virtballoon_validate(struct virtio_device *vdev)
else if (!virtio_has_feature(vdev, VIRTIO_BALLOON_F_PAGE_POISON))
__virtio_clear_bit(vdev, VIRTIO_BALLOON_F_REPORTING);
+ if (virtio_has_feature(vdev, VIRTIO_BALLOON_F_PAGE_POISON) &&
+ !want_init_on_free())
+ __virtio_clear_bit(vdev, VIRTIO_BALLOON_F_DEVICE_INIT_ON_INFLATE);
__virtio_clear_bit(vdev, VIRTIO_F_ACCESS_PLATFORM);
return 0;
}
@@ -1182,6 +1256,7 @@ static unsigned int features[] = {
VIRTIO_BALLOON_F_FREE_PAGE_HINT,
VIRTIO_BALLOON_F_PAGE_POISON,
VIRTIO_BALLOON_F_REPORTING,
+ VIRTIO_BALLOON_F_DEVICE_INIT_ON_INFLATE,
};
static struct virtio_driver virtio_balloon_driver = {
diff --git a/include/uapi/linux/virtio_balloon.h b/include/uapi/linux/virtio_balloon.h
index ee35a372805d..d129736cc3a8 100644
--- a/include/uapi/linux/virtio_balloon.h
+++ b/include/uapi/linux/virtio_balloon.h
@@ -37,6 +37,7 @@
#define VIRTIO_BALLOON_F_FREE_PAGE_HINT 3 /* VQ to report free pages */
#define VIRTIO_BALLOON_F_PAGE_POISON 4 /* Guest is using page poisoning */
#define VIRTIO_BALLOON_F_REPORTING 5 /* Page reporting virtqueue */
+#define VIRTIO_BALLOON_F_DEVICE_INIT_ON_INFLATE 6 /* Device initializes pages on inflate */
/* Size of a PFN in the balloon interface. */
#define VIRTIO_BALLOON_PFN_SHIFT 12
--
MST
^ permalink raw reply related
* [PATCH v5 20/28] virtio_balloon: submit reported pages as individual buffers
From: Michael S. Tsirkin @ 2026-05-07 22:23 UTC (permalink / raw)
To: linux-kernel
Cc: David Hildenbrand, Jason Wang, Xuan Zhuo, Eugenio Pérez,
virtualization
In-Reply-To: <cover.1778192416.git.mst@redhat.com>
Submit each reported page as a separate virtqueue buffer instead
of one buffer with an sg list of all pages. This avoids indirect
descriptor allocation (kmalloc in the reporting path) and gives
per-page used length feedback from the device.
On error, the already-queued pages are kicked and drained
before the error is returned. The caller (page_reporting_drain)
then marks the batch as unreported, which is conservative
but correct.
Signed-off-by: Michael S. Tsirkin <mst@redhat.com>
Assisted-by: Claude:claude-opus-4-6
---
drivers/virtio/virtio_balloon.c | 36 +++++++++++++++++++++------------
1 file changed, 23 insertions(+), 13 deletions(-)
diff --git a/drivers/virtio/virtio_balloon.c b/drivers/virtio/virtio_balloon.c
index 7ed024315539..e99ffbbdd2bd 100644
--- a/drivers/virtio/virtio_balloon.c
+++ b/drivers/virtio/virtio_balloon.c
@@ -202,25 +202,35 @@ static int virtballoon_free_page_report(struct page_reporting_dev_info *pr_dev_i
struct virtio_balloon *vb =
container_of(pr_dev_info, struct virtio_balloon, pr_dev_info);
struct virtqueue *vq = vb->reporting_vq;
- unsigned int unused, err;
+ unsigned int i, err;
/* We should always be able to add these buffers to an empty queue. */
- err = virtqueue_add_inbuf(vq, sg, nents, vb, GFP_NOWAIT);
+ for (i = 0; i < nents; i++) {
+ struct scatterlist one;
- /*
- * In the extremely unlikely case that something has occurred and we
- * are able to trigger an error we will simply display a warning
- * and exit without actually processing the pages.
- */
- if (WARN_ON_ONCE(err))
- return err;
+ sg_init_table(&one, 1);
+ sg_set_page(&one, sg_page(&sg[i]), sg[i].length,
+ sg[i].offset);
+ err = virtqueue_add_inbuf(vq, &one, 1, &sg[i], GFP_NOWAIT);
+ if (WARN_ON_ONCE(err)) {
+ nents = i;
+ break;
+ }
+ }
- virtqueue_kick(vq);
+ if (nents) {
+ virtqueue_kick(vq);
- /* When host has read buffer, this completes via balloon_ack */
- wait_event(vb->acked, virtqueue_get_buf(vq, &unused));
+ /* When host has read buffer, this completes via balloon_ack */
+ for (i = 0; i < nents; i++) {
+ unsigned int unused;
- return 0;
+ wait_event(vb->acked,
+ virtqueue_get_buf(vq, &unused));
+ }
+ }
+
+ return err;
}
static void set_page_pfns(struct virtio_balloon *vb,
--
MST
^ permalink raw reply related
* [PATCH v5 14/28] mm: page_reporting: allow driver to set batch capacity
From: Michael S. Tsirkin @ 2026-05-07 22:23 UTC (permalink / raw)
To: linux-kernel
Cc: David Hildenbrand, Jason Wang, Xuan Zhuo, Eugenio Pérez,
Andrew Morton, Lorenzo Stoakes, Liam R. Howlett, Vlastimil Babka,
Mike Rapoport, Suren Baghdasaryan, Michal Hocko, Brendan Jackman,
Johannes Weiner, Zi Yan, virtualization, linux-mm
In-Reply-To: <cover.1778192416.git.mst@redhat.com>
Add a capacity field to page_reporting_dev_info so drivers can
control the maximum number of pages per report batch. This is
useful when the driver needs to reserve virtqueue descriptors for
metadata (e.g., a bitmap buffer) alongside the page buffers.
The value is capped at PAGE_REPORTING_CAPACITY and rounded down
to a power of 2. If unset (0), defaults to PAGE_REPORTING_CAPACITY.
The virtio_balloon driver sets capacity to the reporting virtqueue
size, letting page_reporting adapt to whatever the device provides.
Signed-off-by: Michael S. Tsirkin <mst@redhat.com>
Assisted-by: Claude:claude-opus-4-6
---
drivers/virtio/virtio_balloon.c | 5 +----
include/linux/page_reporting.h | 3 +++
mm/page_reporting.c | 26 +++++++++++++++-----------
3 files changed, 19 insertions(+), 15 deletions(-)
diff --git a/drivers/virtio/virtio_balloon.c b/drivers/virtio/virtio_balloon.c
index d1fbc8fe8470..7ed024315539 100644
--- a/drivers/virtio/virtio_balloon.c
+++ b/drivers/virtio/virtio_balloon.c
@@ -1017,10 +1017,6 @@ static int virtballoon_probe(struct virtio_device *vdev)
unsigned int capacity;
capacity = virtqueue_get_vring_size(vb->reporting_vq);
- if (capacity < PAGE_REPORTING_CAPACITY) {
- err = -ENOSPC;
- goto out_unregister_oom;
- }
/*
* The default page reporting order is @pageblock_order, which
@@ -1039,6 +1035,7 @@ static int virtballoon_probe(struct virtio_device *vdev)
vb->pr_dev_info.order = 5;
#endif
+ vb->pr_dev_info.capacity = capacity;
err = page_reporting_register(&vb->pr_dev_info);
if (err)
goto out_unregister_oom;
diff --git a/include/linux/page_reporting.h b/include/linux/page_reporting.h
index fe648dfa3a7c..306468b6c7d8 100644
--- a/include/linux/page_reporting.h
+++ b/include/linux/page_reporting.h
@@ -21,6 +21,9 @@ struct page_reporting_dev_info {
/* Minimal order of page reporting */
unsigned int order;
+
+ /* Max pages per report batch (default PAGE_REPORTING_CAPACITY) */
+ unsigned int capacity;
};
/* Tear-down and bring-up for page reporting devices */
diff --git a/mm/page_reporting.c b/mm/page_reporting.c
index f0042d5743af..247cda44e9de 100644
--- a/mm/page_reporting.c
+++ b/mm/page_reporting.c
@@ -174,10 +174,10 @@ page_reporting_cycle(struct page_reporting_dev_info *prdev, struct zone *zone,
* list processed. This should result in us reporting all pages on
* an idle system in about 30 seconds.
*
- * The division here should be cheap since PAGE_REPORTING_CAPACITY
- * should always be a power of 2.
+ * The division here should be cheap since capacity should
+ * always be a power of 2.
*/
- budget = DIV_ROUND_UP(area->nr_free, PAGE_REPORTING_CAPACITY * 16);
+ budget = DIV_ROUND_UP(area->nr_free, prdev->capacity * 16);
/* loop through free list adding unreported pages to sg list */
list_for_each_entry_safe(page, next, list, lru) {
@@ -222,10 +222,10 @@ page_reporting_cycle(struct page_reporting_dev_info *prdev, struct zone *zone,
spin_unlock_irq(&zone->lock);
/* begin processing pages in local list */
- err = prdev->report(prdev, sgl, PAGE_REPORTING_CAPACITY);
+ err = prdev->report(prdev, sgl, prdev->capacity);
/* reset offset since the full list was reported */
- *offset = PAGE_REPORTING_CAPACITY;
+ *offset = prdev->capacity;
/* update budget to reflect call to report function */
budget--;
@@ -234,7 +234,7 @@ page_reporting_cycle(struct page_reporting_dev_info *prdev, struct zone *zone,
spin_lock_irq(&zone->lock);
/* flush reported pages from the sg list */
- page_reporting_drain(prdev, sgl, PAGE_REPORTING_CAPACITY, !err);
+ page_reporting_drain(prdev, sgl, prdev->capacity, !err);
/*
* Reset next to first entry, the old next isn't valid
@@ -260,13 +260,13 @@ static int
page_reporting_process_zone(struct page_reporting_dev_info *prdev,
struct scatterlist *sgl, struct zone *zone)
{
- unsigned int order, mt, leftover, offset = PAGE_REPORTING_CAPACITY;
+ unsigned int order, mt, leftover, offset = prdev->capacity;
unsigned long watermark;
int err = 0;
/* Generate minimum watermark to be able to guarantee progress */
watermark = low_wmark_pages(zone) +
- (PAGE_REPORTING_CAPACITY << page_reporting_order);
+ (prdev->capacity << page_reporting_order);
/*
* Cancel request if insufficient free memory or if we failed
@@ -290,7 +290,7 @@ page_reporting_process_zone(struct page_reporting_dev_info *prdev,
}
/* report the leftover pages before going idle */
- leftover = PAGE_REPORTING_CAPACITY - offset;
+ leftover = prdev->capacity - offset;
if (leftover) {
sgl = &sgl[offset];
err = prdev->report(prdev, sgl, leftover);
@@ -322,11 +322,11 @@ static void page_reporting_process(struct work_struct *work)
atomic_set(&prdev->state, state);
/* allocate scatterlist to store pages being reported on */
- sgl = kmalloc_objs(*sgl, PAGE_REPORTING_CAPACITY);
+ sgl = kmalloc_objs(*sgl, prdev->capacity);
if (!sgl)
goto err_out;
- sg_init_table(sgl, PAGE_REPORTING_CAPACITY);
+ sg_init_table(sgl, prdev->capacity);
for_each_zone(zone) {
err = page_reporting_process_zone(prdev, sgl, zone);
@@ -376,6 +376,10 @@ int page_reporting_register(struct page_reporting_dev_info *prdev)
page_reporting_order = pageblock_order;
}
+ if (!prdev->capacity || prdev->capacity > PAGE_REPORTING_CAPACITY)
+ prdev->capacity = PAGE_REPORTING_CAPACITY;
+ prdev->capacity = rounddown_pow_of_two(prdev->capacity);
+
/* initialize state and work structures */
atomic_set(&prdev->state, PAGE_REPORTING_IDLE);
INIT_DELAYED_WORK(&prdev->work, &page_reporting_process);
--
MST
^ permalink raw reply related
* Re: [PATCH v4 3/3] vfio/pci: Replace vfio_pci_core_setup_barmap() with vfio_pci_core_get_iomap()
From: Alex Williamson @ 2026-05-07 22:21 UTC (permalink / raw)
To: Matt Evans
Cc: Kevin Tian, Jason Gunthorpe, Ankit Agrawal, Alistair Popple,
Leon Romanovsky, Kees Cook, Shameer Kolothum, Yishai Hadas,
Alexey Kardashevskiy, Eric Auger, Peter Xu, Vivek Kasireddy,
Zhi Wang, kvm, linux-kernel, virtualization, alex
In-Reply-To: <20260505173835.2324179-4-mattev@meta.com>
On Tue, 5 May 2026 10:38:31 -0700
Matt Evans <mattev@meta.com> wrote:
> Since "vfio/pci: Set up barmap in vfio_pci_core_enable()", the
> resource request and iomap for the BARs was performed early, and
> vfio_pci_core_setup_barmap() just checks those actions succeeded.
>
> Move this logic to a new helper that checks success and returns the
> iomap address, replacing the various bare vdev->barmap[] lookups.
> This maintains the error behaviour of the previous on-demand
> vfio_pci_core_setup_barmap() scheme.
>
> Signed-off-by: Matt Evans <mattev@meta.com>
> ---
> drivers/vfio/pci/nvgrace-gpu/main.c | 11 ++++-------
> drivers/vfio/pci/vfio_pci_core.c | 11 +++++------
> drivers/vfio/pci/vfio_pci_dmabuf.c | 2 +-
> drivers/vfio/pci/vfio_pci_rdwr.c | 30 ++++++++---------------------
> drivers/vfio/pci/virtio/legacy_io.c | 13 ++++++-------
> include/linux/vfio_pci_core.h | 20 ++++++++++++++++++-
> 6 files changed, 43 insertions(+), 44 deletions(-)
>
> diff --git a/drivers/vfio/pci/nvgrace-gpu/main.c b/drivers/vfio/pci/nvgrace-gpu/main.c
> index fa056b69f899..e153002258ce 100644
> --- a/drivers/vfio/pci/nvgrace-gpu/main.c
> +++ b/drivers/vfio/pci/nvgrace-gpu/main.c
> @@ -184,13 +184,10 @@ static int nvgrace_gpu_open_device(struct vfio_device *core_vdev)
>
> /*
> * GPU readiness is checked by reading the BAR0 registers.
> - *
> - * ioremap BAR0 to ensure that the BAR0 mapping is present before
> - * register reads on first fault before establishing any GPU
> - * memory mapping.
> + * The BAR map was just set up by vfio_pci_core_enable(), so
> + * check that was successful and bail early if not:
> */
> - ret = vfio_pci_core_setup_barmap(vdev, 0);
> - if (ret)
> + if (IS_ERR(vfio_pci_core_get_iomap(vdev, 0)))
> goto error_exit;
Sashiko notes we're not setting ret here. The bots are also paranoid
about the unreachable condition that the get_iomap below could return an
ERR_PTR. Maybe head off both by adding an __iomem pointer to the
nvgrace_gpu_pci_core_device struct and a temporary one here. Store the
iomap in the temporary variable, use it to test for IS_ERR() and
PTR_ERR(), then set the pointer in the structure after the last error
condition here. Add one line in the close_device to set it NULL. Then
just use nvdev->bar0_io below.
>
> if (nvdev->resmem.memlength) {
> @@ -275,7 +272,7 @@ nvgrace_gpu_check_device_ready(struct nvgrace_gpu_pci_core_device *nvdev)
> if (!__vfio_pci_memory_enabled(vdev))
> return -EIO;
>
> - ret = nvgrace_gpu_wait_device_ready(vdev->barmap[0]);
> + ret = nvgrace_gpu_wait_device_ready(vfio_pci_core_get_iomap(vdev, 0));
> if (ret)
> return ret;
>
> diff --git a/drivers/vfio/pci/vfio_pci_core.c b/drivers/vfio/pci/vfio_pci_core.c
> index 62931dc381d8..5c8bd13f10d0 100644
> --- a/drivers/vfio/pci/vfio_pci_core.c
> +++ b/drivers/vfio/pci/vfio_pci_core.c
> @@ -1761,7 +1761,7 @@ int vfio_pci_core_mmap(struct vfio_device *core_vdev, struct vm_area_struct *vma
> struct pci_dev *pdev = vdev->pdev;
> unsigned int index;
> u64 phys_len, req_len, pgoff, req_start;
> - int ret;
> + void __iomem *bar_io;
>
> index = vma->vm_pgoff >> (VFIO_PCI_OFFSET_SHIFT - PAGE_SHIFT);
>
> @@ -1795,12 +1795,11 @@ int vfio_pci_core_mmap(struct vfio_device *core_vdev, struct vm_area_struct *vma
> return -EINVAL;
>
> /*
> - * Even though we don't make use of the barmap for the mmap,
> - * we need to request the region and the barmap tracks that.
> + * Ensure the BAR resource region is reserved for use.
> */
> - ret = vfio_pci_core_setup_barmap(vdev, index);
> - if (ret)
> - return ret;
> + bar_io = vfio_pci_core_get_iomap(vdev, index);
> + if (IS_ERR(bar_io))
> + return PTR_ERR(bar_io);
>
> vma->vm_private_data = vdev;
> vma->vm_page_prot = pgprot_noncached(vma->vm_page_prot);
> diff --git a/drivers/vfio/pci/vfio_pci_dmabuf.c b/drivers/vfio/pci/vfio_pci_dmabuf.c
> index 69a5c2d511e6..46cd44b22c9c 100644
> --- a/drivers/vfio/pci/vfio_pci_dmabuf.c
> +++ b/drivers/vfio/pci/vfio_pci_dmabuf.c
> @@ -248,7 +248,7 @@ int vfio_pci_core_feature_dma_buf(struct vfio_pci_core_device *vdev, u32 flags,
> * else. Check that PCI resources have been claimed for it.
> */
> if (get_dma_buf.region_index >= VFIO_PCI_ROM_REGION_INDEX ||
> - vfio_pci_core_setup_barmap(vdev, get_dma_buf.region_index))
> + IS_ERR(vfio_pci_core_get_iomap(vdev, get_dma_buf.region_index)))
> return -ENODEV;
>
> dma_ranges = memdup_array_user(&arg->dma_ranges, get_dma_buf.nr_ranges,
> diff --git a/drivers/vfio/pci/vfio_pci_rdwr.c b/drivers/vfio/pci/vfio_pci_rdwr.c
> index 3bfbb879a005..7f14dd46de17 100644
> --- a/drivers/vfio/pci/vfio_pci_rdwr.c
> +++ b/drivers/vfio/pci/vfio_pci_rdwr.c
> @@ -198,19 +198,6 @@ ssize_t vfio_pci_core_do_io_rw(struct vfio_pci_core_device *vdev, bool test_mem,
> }
> EXPORT_SYMBOL_GPL(vfio_pci_core_do_io_rw);
>
> -/*
> - * The barmap is set up in vfio_pci_core_enable(). Callers use this
> - * function to check that the BAR resources are requested or that the
> - * pci_iomap() was done.
> - */
> -int vfio_pci_core_setup_barmap(struct vfio_pci_core_device *vdev, int bar)
> -{
> - if (IS_ERR(vdev->barmap[bar]))
> - return PTR_ERR(vdev->barmap[bar]);
> - return 0;
> -}
> -EXPORT_SYMBOL_GPL(vfio_pci_core_setup_barmap);
> -
> ssize_t vfio_pci_bar_rw(struct vfio_pci_core_device *vdev, char __user *buf,
> size_t count, loff_t *ppos, bool iswrite)
> {
> @@ -262,13 +249,11 @@ ssize_t vfio_pci_bar_rw(struct vfio_pci_core_device *vdev, char __user *buf,
> */
> max_width = VFIO_PCI_IO_WIDTH_4;
> } else {
> - int ret = vfio_pci_core_setup_barmap(vdev, bar);
> - if (ret) {
> - done = ret;
> + io = vfio_pci_core_get_iomap(vdev, bar);
> + if (IS_ERR(io)) {
> + done = PTR_ERR(io);
> goto out;
> }
> -
> - io = vdev->barmap[bar];
> }
>
> if (bar == vdev->msix_bar) {
> @@ -423,6 +408,7 @@ int vfio_pci_ioeventfd(struct vfio_pci_core_device *vdev, loff_t offset,
> loff_t pos = offset & VFIO_PCI_OFFSET_MASK;
> int ret, bar = VFIO_PCI_OFFSET_TO_INDEX(offset);
> struct vfio_pci_ioeventfd *ioeventfd;
> + void __iomem *io;
>
> /* Only support ioeventfds into BARs */
> if (bar > VFIO_PCI_BAR5_REGION_INDEX)
> @@ -440,9 +426,9 @@ int vfio_pci_ioeventfd(struct vfio_pci_core_device *vdev, loff_t offset,
> if (count == 8)
> return -EINVAL;
>
> - ret = vfio_pci_core_setup_barmap(vdev, bar);
> - if (ret)
> - return ret;
> + io = vfio_pci_core_get_iomap(vdev, bar);
> + if (IS_ERR(io))
> + return PTR_ERR(io);
Sashiko seems to note a real existing error here that should also be
pulled out to a separate fix. Given the right offset, this could
generate a negative BAR value. The test at the end of the previous
chunk should should be expanded to `if (bar < 0 || bar > ...BAR5...)`.
Do you want to pick that up in this series? I think it's the only case
that lets that slip through. Thanks,
Alex
^ permalink raw reply
* Re: [PATCH v4 1/3] vfio/pci: Set up BAR resources and maps in vfio_pci_core_enable()
From: Alex Williamson @ 2026-05-07 22:21 UTC (permalink / raw)
To: Matt Evans
Cc: Kevin Tian, Jason Gunthorpe, Ankit Agrawal, Alistair Popple,
Leon Romanovsky, Kees Cook, Shameer Kolothum, Yishai Hadas,
Alexey Kardashevskiy, Eric Auger, Peter Xu, Vivek Kasireddy,
Zhi Wang, kvm, linux-kernel, virtualization, alex
In-Reply-To: <20260505173835.2324179-2-mattev@meta.com>
On Tue, 5 May 2026 10:38:29 -0700
Matt Evans <mattev@meta.com> wrote:
> Previously BAR resource requests and the corresponding pci_iomap()
> were performed on-demand and without synchronisation, which was racy.
> Rather than add synchronisation, it's simplest to address this by
> doing both activities from vfio_pci_core_enable().
>
> The resource allocation and/or pci_iomap() can still fail; their
> status is tracked and existing calls to vfio_pci_core_setup_barmap()
> will fail in a similar way to before. This keeps the point of failure
> as observed by userspace the same, i.e. failures to request/map unused
> BARs are benign.
>
> Fixes: 89e1f7d4c66d ("vfio: Add PCI device driver")
> Signed-off-by: Matt Evans <mattev@meta.com>
> ---
> drivers/vfio/pci/vfio_pci_core.c | 36 +++++++++++++++++++++++++++++++-
> drivers/vfio/pci/vfio_pci_rdwr.c | 26 +++++++----------------
> 2 files changed, 42 insertions(+), 20 deletions(-)
>
> diff --git a/drivers/vfio/pci/vfio_pci_core.c b/drivers/vfio/pci/vfio_pci_core.c
> index 3f8d093aacf8..62931dc381d8 100644
> --- a/drivers/vfio/pci/vfio_pci_core.c
> +++ b/drivers/vfio/pci/vfio_pci_core.c
> @@ -482,6 +482,39 @@ static int vfio_pci_core_runtime_resume(struct device *dev)
> }
> #endif /* CONFIG_PM */
>
> +/*
> + * Eager-request BAR resources, and iomap them. Soft failures are
> + * allowed, and consumers must check the barmap before use in order to
> + * give compatible user-visible behaviour with the previous on-demand
> + * allocation method.
> + */
> +static void vfio_pci_core_map_bars(struct vfio_pci_core_device *vdev)
> +{
> + struct pci_dev *pdev = vdev->pdev;
> + int i;
> +
> + for (i = 0; i < PCI_STD_NUM_BARS; i++) {
> + int bar = i + PCI_STD_RESOURCES;
> +
> + vdev->barmap[bar] = ERR_PTR(-ENODEV);
> +
> + if (!pci_resource_len(pdev, i))
> + continue;
> +
> + if (pci_request_selected_regions(pdev, 1 << bar, "vfio")) {
> + pci_dbg(vdev->pdev, "Failed to reserve region %d\n", bar);
> + vdev->barmap[bar] = ERR_PTR(-EBUSY);
> + continue;
> + }
> +
> + vdev->barmap[bar] = pci_iomap(pdev, bar, 0);
> + if (!vdev->barmap[bar]) {
Sashiko notes[1] correctly that we need to release the requested region
here.
[1]https://sashiko.dev/#/patchset/20260505173835.2324179-1-mattev@meta.com
> + pci_dbg(vdev->pdev, "Failed to iomap region %d\n", bar);
> + vdev->barmap[bar] = ERR_PTR(-ENOMEM);
> + }
> + }
> +}
> +
> /*
> * The pci-driver core runtime PM routines always save the device state
> * before going into suspended state. If the device is going into low power
> @@ -568,6 +601,7 @@ int vfio_pci_core_enable(struct vfio_pci_core_device *vdev)
> if (!vfio_vga_disabled() && vfio_pci_is_vga(pdev))
> vdev->has_vga = true;
>
> + vfio_pci_core_map_bars(vdev);
>
> return 0;
>
> @@ -648,7 +682,7 @@ void vfio_pci_core_disable(struct vfio_pci_core_device *vdev)
>
> for (i = 0; i < PCI_STD_NUM_BARS; i++) {
> bar = i + PCI_STD_RESOURCES;
> - if (!vdev->barmap[bar])
> + if (IS_ERR_OR_NULL(vdev->barmap[bar]))
> continue;
> pci_iounmap(pdev, vdev->barmap[bar]);
> pci_release_selected_regions(pdev, 1 << bar);
> diff --git a/drivers/vfio/pci/vfio_pci_rdwr.c b/drivers/vfio/pci/vfio_pci_rdwr.c
> index 4251ee03e146..3bfbb879a005 100644
> --- a/drivers/vfio/pci/vfio_pci_rdwr.c
> +++ b/drivers/vfio/pci/vfio_pci_rdwr.c
> @@ -198,27 +198,15 @@ ssize_t vfio_pci_core_do_io_rw(struct vfio_pci_core_device *vdev, bool test_mem,
> }
> EXPORT_SYMBOL_GPL(vfio_pci_core_do_io_rw);
>
> +/*
> + * The barmap is set up in vfio_pci_core_enable(). Callers use this
> + * function to check that the BAR resources are requested or that the
> + * pci_iomap() was done.
> + */
> int vfio_pci_core_setup_barmap(struct vfio_pci_core_device *vdev, int bar)
> {
> - struct pci_dev *pdev = vdev->pdev;
> - int ret;
> - void __iomem *io;
> -
> - if (vdev->barmap[bar])
> - return 0;
> -
> - ret = pci_request_selected_regions(pdev, 1 << bar, "vfio");
> - if (ret)
> - return ret;
> -
> - io = pci_iomap(pdev, bar, 0);
> - if (!io) {
> - pci_release_selected_regions(pdev, 1 << bar);
> - return -ENOMEM;
> - }
> -
> - vdev->barmap[bar] = io;
> -
> + if (IS_ERR(vdev->barmap[bar]))
> + return PTR_ERR(vdev->barmap[bar]);
> return 0;
> }
> EXPORT_SYMBOL_GPL(vfio_pci_core_setup_barmap);
^ permalink raw reply
* [mst-vhost:balloon 6/30] Warning: mm/mempolicy.c:2444 function parameter 'user_addr' not described in '__alloc_pages_mpol'
From: kernel test robot @ 2026-05-07 21:26 UTC (permalink / raw)
To: Michael S. Tsirkin; +Cc: oe-kbuild-all, kvm, virtualization, netdev
tree: https://git.kernel.org/pub/scm/linux/kernel/git/mst/vhost.git balloon
head: 9f56ee36fbf6a6d336dc6a9eaeb4f8a67cb42a31
commit: c4289f5a4e563611a468b4b5379025a4aa4a7c12 [6/30] mm: thread user_addr through page allocator for cache-friendly zeroing
config: powerpc-allmodconfig (https://download.01.org/0day-ci/archive/20260508/202605080515.6jRN5wN7-lkp@intel.com/config)
compiler: powerpc64-linux-gcc (GCC) 15.2.0
reproduce (this is a W=1 build): (https://download.01.org/0day-ci/archive/20260508/202605080515.6jRN5wN7-lkp@intel.com/reproduce)
If you fix the issue in a separate patch/commit (i.e. not just a new version of
the same patch/commit), kindly add following tags
| Reported-by: kernel test robot <lkp@intel.com>
| Closes: https://lore.kernel.org/oe-kbuild-all/202605080515.6jRN5wN7-lkp@intel.com/
All warnings (new ones prefixed by >>):
>> Warning: mm/mempolicy.c:2444 function parameter 'user_addr' not described in '__alloc_pages_mpol'
>> Warning: mm/mempolicy.c:2444 expecting prototype for alloc_pages_mpol(). Prototype was for __alloc_pages_mpol() instead
Warning: mm/mempolicy.c:2547 expecting prototype for vma_alloc_folio(). Prototype was for alloc_frozen_pages() instead
--
0-DAY CI Kernel Test Service
https://github.com/intel/lkp-tests/wiki
^ permalink raw reply
* Re: [PATCH] vsock/virtio: fix vsockmon info leak in non-linear tap copy
From: Bobby Eshleman @ 2026-05-07 20:12 UTC (permalink / raw)
To: Stefano Garzarella
Cc: Paolo Abeni, Arseniy Krasnov, Bobby Eshleman, stefanha, netdev,
linux-kernel, mst, jasowang, xuanzhuo, eperezma, davem, edumazet,
kuba, horms, Yiqi Sun, kvm, virtualization
In-Reply-To: <afnXIGtswspSEk8x@sgarzare-redhat>
On Tue, May 05, 2026 at 02:44:16PM +0200, Stefano Garzarella wrote:
> CCing Arseniy and Bobby.
>
> On Tue, May 05, 2026 at 12:26:21PM +0200, Paolo Abeni wrote:
> > On 4/30/26 9:11 AM, Yiqi Sun wrote:
> > > vsockmon mirrors packets through virtio_transport_build_skb(), which
> > > builds a new skb and copies the payload into it. For non-linear skbs,
> > > this goes through virtio_transport_copy_nonlinear_skb().
> > >
> > > Helper manually initializes a iov_iter, but leaves iov_iter.count unset.
> > > As a result, skb_copy_datagram_iter() sees zero writable bytes
> > > in the destination iterator and copies no payload data.
> > >
> > > This becomes an info leak because virtio_transport_build_skb() has
> > > already reserved payload_len bytes in the new skb with skb_put(). The
> > > skb is then returned to the tap path with that payload area still
> > > uninitialized, so userspace reading from a vsockmon device can observe
> > > heap contents and potentially kernel address.
> > >
> > > Fix it by initializing iov_iter.count to the number of bytes to copy.
> > >
> > > Fixes: 4b0bf10eb077 ("vsock/virtio: non-linear skb handling for tap")
> > > Signed-off-by: Yiqi Sun <sunyiqixm@gmail.com>
> > > ---
> > > net/vmw_vsock/virtio_transport_common.c | 2 +-
> > > 1 file changed, 1 insertion(+), 1 deletion(-)
> > >
> > > diff --git a/net/vmw_vsock/virtio_transport_common.c b/net/vmw_vsock/virtio_transport_common.c
> > > index 416d533f493d..6b26ee57ccab 100644
> > > --- a/net/vmw_vsock/virtio_transport_common.c
> > > +++ b/net/vmw_vsock/virtio_transport_common.c
> > > @@ -152,7 +152,7 @@ static void virtio_transport_copy_nonlinear_skb(const struct sk_buff *skb,
> > > iov_iter.nr_segs = 1;
> > >
> > > to_copy = min_t(size_t, len, skb->len);
> > > -
> > > + iov_iter.count = to_copy;
> > > skb_copy_datagram_iter(skb, VIRTIO_VSOCK_SKB_CB(skb)->offset,
> > > &iov_iter, to_copy);
> >
> > @Stefano, @Stefan, the patch LGTM, but sashiko pointed out to a
> > pre-existing issue you should probably want to address:
> >
> > > to_copy = min_t(size_t, len, skb->len);
> > Does this length calculation account for the offset when a packet is
> > split across multiple transmissions?
> > If a packet is requeued, VIRTIO_VSOCK_SKB_CB(skb)->offset is increased,
> > but to_copy still evaluates to the full length of the skb.
>
> Yep, I just checked and vhost-vsock is the only place where we call
> virtio_transport_deliver_tap_pkt() wiht an offset != 0, but I agree that we
> should also fix it.
>
> Looking better in net/vmw_vsock/virtio_transport_common.c I think this is a
> regression, indeed we have this comment in virtio_transport_build_skb():
>
> /* A packet could be split to fit the RX buffer, so we can retrieve
> * the payload length from the header and the buffer pointer taking
> * care of the offset in the original packet.
> */
> pkt_hdr = virtio_vsock_hdr(pkt);
>
> Before commit 71dc9ec9ac7d ("virtio/vsock: replace virtio_vsock_pkt with
> sk_buff") we read the payload lenght from the header that is always set to
> the right value before delivering the packet to the tap.
>
> From that commit, we don't to consider the offset anymore since we started
> to use `len` from the skb, so IMO we should go back to what we did before
> it, I mean:
>
> payload_len = le32_to_cpu(pkt->hdr.len);
>
> @Bobby do you remember why we did that change? Or if you see any issue going
> back to what we did initially?
I think this was just one that made it through the cracks. I vaguely
recall a few other instances where I assumed skb->len could stand-in for
hdr.len, but it didn't hold.
Using hdr.len like the original looks correct to me.
Best,
Bobby
^ permalink raw reply
* Re: [PATCH] vsock/virtio: fix vsockmon info leak in non-linear tap, copy
From: Arseniy Krasnov @ 2026-05-07 20:03 UTC (permalink / raw)
To: Paolo Abeni, Stefano Garzarella, Bobby Eshleman
Cc: netdev, linux-kernel, Michael S. Tsirkin, Jason Wang, Xuan Zhuo,
Yiqi Sun, kvm, virtualization
In-Reply-To: <afnXIGtswspSEk8x@sgarzare-redhat>
>CCing Arseniy and Bobby.
Thanks!
>
>On Tue, May 05, 2026 at 12:26:21PM +0200, Paolo Abeni wrote:
>>On 4/30/26 9:11 AM, Yiqi Sun wrote:
>>> vsockmon mirrors packets through virtio_transport_build_skb(), which
>>> builds a new skb and copies the payload into it. For non-linear skbs,
>>> this goes through virtio_transport_copy_nonlinear_skb().
>>>
>>> Helper manually initializes a iov_iter, but leaves iov_iter.count unset.
>>> As a result, skb_copy_datagram_iter() sees zero writable bytes
>>> in the destination iterator and copies no payload data.
>>>
>>> This becomes an info leak because virtio_transport_build_skb() has
>>> already reserved payload_len bytes in the new skb with skb_put(). The
>>> skb is then returned to the tap path with that payload area still
>>> uninitialized, so userspace reading from a vsockmon device can observe
>>> heap contents and potentially kernel address.
>>>
>>> Fix it by initializing iov_iter.count to the number of bytes to copy.
>>>
>>> Fixes: 4b0bf10eb077 ("vsock/virtio: non-linear skb handling for tap")
>>> Signed-off-by: Yiqi Sun <sunyiqixm@gmail.com>
>>> ---
>>> net/vmw_vsock/virtio_transport_common.c | 2 +-
>>> 1 file changed, 1 insertion(+), 1 deletion(-)
>>>
>>> diff --git a/net/vmw_vsock/virtio_transport_common.c b/net/vmw_vsock/virtio_transport_common.c
>>> index 416d533f493d..6b26ee57ccab 100644
>>> --- a/net/vmw_vsock/virtio_transport_common.c
>>> +++ b/net/vmw_vsock/virtio_transport_common.c
>>> @@ -152,7 +152,7 @@ static void virtio_transport_copy_nonlinear_skb(const struct sk_buff *skb,
>>> iov_iter.nr_segs = 1;
>>>
>>> to_copy = min_t(size_t, len, skb->len);
>>> -
>>> + iov_iter.count = to_copy;
>>> skb_copy_datagram_iter(skb, VIRTIO_VSOCK_SKB_CB(skb)->offset,
>>> &iov_iter, to_copy);
>>
>>@Stefano, @Stefan, the patch LGTM, but sashiko pointed out to a
>>pre-existing issue you should probably want to address:
>>
>>> to_copy = min_t(size_t, len, skb->len);
>>Does this length calculation account for the offset when a packet is
>>split across multiple transmissions?
>>If a packet is requeued, VIRTIO_VSOCK_SKB_CB(skb)->offset is increased,
>>but to_copy still evaluates to the full length of the skb.
>
>Yep, I just checked and vhost-vsock is the only place where we call
>virtio_transport_deliver_tap_pkt() wiht an offset != 0, but I agree that
>we should also fix it.
Yes, looks like the only place where offset could be non zero is 'vhost_transport_do_send_pkt()'.
And we set valid length in header every attempt to send it:
/* Set the correct length in the header */
hdr->len = cpu_to_le32(payload_len);
In all other places we call 'virtio_transport_deliver_tap_pkt()' with offset == 0. And thus
skb->len == hdr->len.
So for me looks ok. E.g. len in header is actual data.
>
>Looking better in net/vmw_vsock/virtio_transport_common.c I think this
>is a regression, indeed we have this comment in
>virtio_transport_build_skb():
>
> /* A packet could be split to fit the RX buffer, so we can retrieve
> * the payload length from the header and the buffer pointer taking
> * care of the offset in the original packet.
> */
> pkt_hdr = virtio_vsock_hdr(pkt);
>
>Before commit 71dc9ec9ac7d ("virtio/vsock: replace virtio_vsock_pkt with
>sk_buff") we read the payload lenght from the header that is always set
>to the right value before delivering the packet to the tap.
>
> From that commit, we don't to consider the offset anymore since we
>started to use `len` from the skb, so IMO we should go back to what we
>did before it, I mean:
>
> payload_len = le32_to_cpu(pkt->hdr.len);
>
>@Bobby do you remember why we did that change? Or if you see any issue
>going back to what we did initially?
>
>
>Also IMO we should avoid to set all the iov_iter fields by hand and
>start to use iov_iter_kvec(). Plus, we can just use
>skb_copy_datagram_iter() in any case, like we already do in vhost-vsock,
>since it already handles linear vs non linear.
>
>At the end I mean something like this:
>
>@@ -171,7 +150,7 @@ static struct sk_buff *virtio_transport_build_skb(void *opaque)
> * care of the offset in the original packet.
> */
> pkt_hdr = virtio_vsock_hdr(pkt);
>- payload_len = pkt->len;
>+ payload_len = le32_to_cpu(pkt_hdr->len);
>
> skb = alloc_skb(sizeof(*hdr) + sizeof(*pkt_hdr) + payload_len,
> GFP_ATOMIC);
>@@ -214,13 +193,17 @@ static struct sk_buff *virtio_transport_build_skb(void *opaque)
> skb_put_data(skb, pkt_hdr, sizeof(*pkt_hdr));
>
> if (payload_len) {
>- if (skb_is_nonlinear(pkt)) {
>- void *data = skb_put(skb, payload_len);
>+ struct iov_iter iov_iter;
>+ struct kvec kvec;
>+ void *data = skb_put(skb, payload_len);
>
>- virtio_transport_copy_nonlinear_skb(pkt, data, payload_len);
>- } else {
>- skb_put_data(skb, pkt->data, payload_len);
>- }
>+ kvec.iov_base = data;
>+ kvec.iov_len = payload_len;
>+ iov_iter_kvec(&iov_iter, READ, &kvec, 1, payload_len);
>+
>+ skb_copy_datagram_iter(pkt,
>+ VIRTIO_VSOCK_SKB_CB(pkt)->offset,
>+ &iov_iter, payload_len);
> }
>
> return skb;
>
>And removing virtio_transport_copy_nonlinear_skb().
Yes, this looks shorter and better.
>
>If you agree, I can send a proper series with these changes that should
>fix the issue reported by Yiqi Sun introduced by commit 4b0bf10eb077
>("vsock/virtio: non-linear skb handling for tap") and the issue
>introduced by commit 71dc9ec9ac7d ("virtio/vsock: replace
>virtio_vsock_pkt with sk_buff").
>
>Thanks,
>Stefano
Thanks
^ permalink raw reply
* [mst-vhost:balloon 4/30] Warning: mm/mempolicy.c:2527 expecting prototype for vma_alloc_folio(). Prototype was for alloc_frozen_pages() instead
From: kernel test robot @ 2026-05-07 19:56 UTC (permalink / raw)
To: Michael S. Tsirkin; +Cc: oe-kbuild-all, kvm, virtualization, netdev
tree: https://git.kernel.org/pub/scm/linux/kernel/git/mst/vhost.git balloon
head: 9f56ee36fbf6a6d336dc6a9eaeb4f8a67cb42a31
commit: 95744e0e9c4df79c6bc8ec96306b29c7a8e8984e [4/30] mm: move vma_alloc_folio to page_alloc.c
config: powerpc-allmodconfig (https://download.01.org/0day-ci/archive/20260508/202605080331.y1eIdVUC-lkp@intel.com/config)
compiler: powerpc64-linux-gcc (GCC) 15.2.0
reproduce (this is a W=1 build): (https://download.01.org/0day-ci/archive/20260508/202605080331.y1eIdVUC-lkp@intel.com/reproduce)
If you fix the issue in a separate patch/commit (i.e. not just a new version of
the same patch/commit), kindly add following tags
| Reported-by: kernel test robot <lkp@intel.com>
| Closes: https://lore.kernel.org/oe-kbuild-all/202605080331.y1eIdVUC-lkp@intel.com/
All warnings (new ones prefixed by >>):
>> Warning: mm/mempolicy.c:2527 expecting prototype for vma_alloc_folio(). Prototype was for alloc_frozen_pages() instead
--
0-DAY CI Kernel Test Service
https://github.com/intel/lkp-tests/wiki
^ permalink raw reply
* [PATCH] virtio-mmio: move guest page size setting into vm_reset()
From: Sungho Bae @ 2026-05-07 18:38 UTC (permalink / raw)
To: mst, jasowang
Cc: xuanzhuo, eperezma, stephan.gerhold, virtualization, linux-kernel,
Sungho Bae
From: Sungho Bae <baver.bae@lge.com>
The virtio-mmio legacy spec (Section 4.2.4) requires the driver to
write the guest page size "during initialization, before any queues
are used". Reset is step 1 of the initialization sequence
(Section 3.1), so setting GuestPageSize immediately after the status
register reset in vm_reset() is more proper.
Currently the GuestPageSize write lives in two separate call sites:
- virtio_mmio_probe(), before register_virtio_device()
- virtio_mmio_restore(), before virtio_device_restore()
Both of these write the value *before* the reset that happens inside
register_virtio_device()/virtio_device_restore(), so a device
implementation that clears GuestPageSize on reset would lose the
value. QEMU's virtio_mmio_reset() for example zeroes guest_page_shift
on a full device reset.
The current code happens to work because the Linux driver triggers
only a "soft reset" (STATUS register write of 0), and QEMU's
soft-reset path does not clear guest_page_shift. But relying on
this is fragile and not guaranteed by the spec.
Move the GuestPageSize write into vm_reset(), right after the status
reset. This ensures the value is set:
- at the correct point in the initialization sequence per spec,
- after every reset (probe, restore, or any future path), and
- exactly once, removing the duplication.
Fixes: e0c2ce821795 ("virtio_mmio: Restore guest page size on resume")
Signed-off-by: Sungho Bae <baver.bae@lge.com>
---
drivers/virtio/virtio_mmio.c | 15 ++++++++++-----
1 file changed, 10 insertions(+), 5 deletions(-)
diff --git a/drivers/virtio/virtio_mmio.c b/drivers/virtio/virtio_mmio.c
index 595c2274fbb5..daa65b269a36 100644
--- a/drivers/virtio/virtio_mmio.c
+++ b/drivers/virtio/virtio_mmio.c
@@ -254,6 +254,16 @@ static void vm_reset(struct virtio_device *vdev)
/* 0 status means a reset. */
writel(0, vm_dev->base + VIRTIO_MMIO_STATUS);
+
+ /*
+ * The virtio-mmio legacy spec requires the driver to write the
+ * guest page size during initialization, before any queues are
+ * used. Since reset is step 1 of initialization (Section 3.1),
+ * set it here so it is always in place for subsequent queue setup
+ * in every code path (probe, restore, etc.).
+ */
+ if (vm_dev->version == 1)
+ writel(PAGE_SIZE, vm_dev->base + VIRTIO_MMIO_GUEST_PAGE_SIZE);
}
@@ -547,9 +557,6 @@ static int virtio_mmio_restore(struct device *dev)
{
struct virtio_mmio_device *vm_dev = dev_get_drvdata(dev);
- if (vm_dev->version == 1)
- writel(PAGE_SIZE, vm_dev->base + VIRTIO_MMIO_GUEST_PAGE_SIZE);
-
return virtio_device_restore(&vm_dev->vdev);
}
@@ -619,8 +626,6 @@ static int virtio_mmio_probe(struct platform_device *pdev)
vm_dev->vdev.id.vendor = readl(vm_dev->base + VIRTIO_MMIO_VENDOR_ID);
if (vm_dev->version == 1) {
- writel(PAGE_SIZE, vm_dev->base + VIRTIO_MMIO_GUEST_PAGE_SIZE);
-
rc = dma_set_mask(&pdev->dev, DMA_BIT_MASK(64));
/*
* In the legacy case, ensure our coherently-allocated virtio
--
2.43.0
^ permalink raw reply related
* Re: [PATCH net] vsock/virtio: fix potential unbounded skb queue
From: Jakub Kicinski @ 2026-05-07 17:18 UTC (permalink / raw)
To: Eric Dumazet
Cc: Stefano Garzarella, Michael S. Tsirkin, Arseniy Krasnov,
Bobby Eshleman, Stefan Hajnoczi, David S . Miller, Paolo Abeni,
Simon Horman, netdev, eric.dumazet, Arseniy Krasnov, Jason Wang,
Xuan Zhuo, Eugenio Pérez, kvm, virtualization
In-Reply-To: <CANn89iJ+qOFPSUACvda7djOVKGM8t+FfwdA5Ymjxe+g_tJtmnA@mail.gmail.com>
On Thu, 7 May 2026 09:32:24 -0700 Eric Dumazet wrote:
> On Thu, May 7, 2026 at 9:05 AM Stefano Garzarella <sgarzare@redhat.com> wrote:
> > On Thu, May 07, 2026 at 07:33:40AM -0700, Jakub Kicinski wrote:
> > >We can revert if you think that the risk of regression is high..
> > >Please LMK soon, we can do it before patch reaches Linus.
> >
> > Some tests in tools/testing/vsock/vsock_test.c are failing with this
> > patch applied.
> >
> > Test 18 are failing sometime in this way (I guess because we are
> > dropping packets):
> >
> > 18 - SOCK_STREAM MSG_ZEROCOPY...hash mismatch
> >
> > Test 22 is failing 100% in this way:
> >
> > 22 - SOCK_STREAM virtio credit update + SO_RCVLOWAT...send failed:
> > Resource temporarily unavailable
> >
> >
> > With my followup patch adding also advertisement to the other peer
> > (still draft locally, waiting for Michael proposal) I saw 22 failing,
> > because tests expects that can use the entire buf_alloc, but now we are
> > reducing it. So IMO we should do like in `__sock_set_rcvbuf()` and
> > double the buffer size, or at least digest an overhead equal to the
> > buffer size set by the user via SO_VM_SOCKETS_BUFFER_SIZE (yeah,
> > AF_VSOCK has it owns sockopt since the beginning :-().
> >
> > With that approach tests are passing, but I'd like to stress a bit more
> > that patch. I'll send it tomorrow as fixup of this patch, or if you
> > prefer to revert, I'll send as standalone.
>
> A plain revert is a big issue, now users now how to crash hypervisors.
>
> This vulnerability allows a compromised guest (controlling
> virtio_vsock_hdr fields)
> to continuously flood the host's vsock receive queue without
> triggering any memory
> accounting limits or reader wakeups, resulting in unbounded host
> kernel memory consumption (Host DoS via OOM).
>
> A vulnerability where a KVM guest can crash or deadlock its host is
> classified as a KVM DoS.
>
> Am I missing something?
Alright, let's leave it.
^ permalink raw reply
* Re: [PATCH net] vsock/virtio: fix potential unbounded skb queue
From: Eric Dumazet @ 2026-05-07 16:32 UTC (permalink / raw)
To: Stefano Garzarella
Cc: Jakub Kicinski, Michael S. Tsirkin, Arseniy Krasnov,
Bobby Eshleman, Stefan Hajnoczi, David S . Miller, Paolo Abeni,
Simon Horman, netdev, eric.dumazet, Arseniy Krasnov, Jason Wang,
Xuan Zhuo, Eugenio Pérez, kvm, virtualization
In-Reply-To: <afyy9CeniTBF3o2I@sgarzare-redhat>
On Thu, May 7, 2026 at 9:05 AM Stefano Garzarella <sgarzare@redhat.com> wrote:
>
> On Thu, May 07, 2026 at 07:33:40AM -0700, Jakub Kicinski wrote:
> >On Thu, 7 May 2026 14:59:13 +0200 Stefano Garzarella wrote:
> >> >well if you want to support pathological cases such as 1 byte messages
> >> >that would mean like 100x reduction no?
> >>
> >> Yep, but since this patch is already merged, IMHO that is better than
> >> losing data in those pathological cases.
> >
> >We can revert if you think that the risk of regression is high..
> >Please LMK soon, we can do it before patch reaches Linus.
> >
>
> Some tests in tools/testing/vsock/vsock_test.c are failing with this
> patch applied.
>
> Test 18 are failing sometime in this way (I guess because we are
> dropping packets):
>
> 18 - SOCK_STREAM MSG_ZEROCOPY...hash mismatch
>
> Test 22 is failing 100% in this way:
>
> 22 - SOCK_STREAM virtio credit update + SO_RCVLOWAT...send failed:
> Resource temporarily unavailable
>
>
> With my followup patch adding also advertisement to the other peer
> (still draft locally, waiting for Michael proposal) I saw 22 failing,
> because tests expects that can use the entire buf_alloc, but now we are
> reducing it. So IMO we should do like in `__sock_set_rcvbuf()` and
> double the buffer size, or at least digest an overhead equal to the
> buffer size set by the user via SO_VM_SOCKETS_BUFFER_SIZE (yeah,
> AF_VSOCK has it owns sockopt since the beginning :-().
>
> With that approach tests are passing, but I'd like to stress a bit more
> that patch. I'll send it tomorrow as fixup of this patch, or if you
> prefer to revert, I'll send as standalone.
>
A plain revert is a big issue, now users now how to crash hypervisors.
This vulnerability allows a compromised guest (controlling
virtio_vsock_hdr fields)
to continuously flood the host's vsock receive queue without
triggering any memory
accounting limits or reader wakeups, resulting in unbounded host
kernel memory consumption (Host DoS via OOM).
A vulnerability where a KVM guest can crash or deadlock its host is
classified as a KVM DoS.
Am I missing something?
^ permalink raw reply
* Re: [PATCH net] vsock/virtio: fix potential unbounded skb queue
From: Stefano Garzarella @ 2026-05-07 16:05 UTC (permalink / raw)
To: Jakub Kicinski
Cc: Michael S. Tsirkin, Eric Dumazet, Arseniy Krasnov, Bobby Eshleman,
Stefan Hajnoczi, David S . Miller, Paolo Abeni, Simon Horman,
netdev, eric.dumazet, Arseniy Krasnov, Jason Wang, Xuan Zhuo,
Eugenio Pérez, kvm, virtualization
In-Reply-To: <20260507073340.0604667d@kernel.org>
On Thu, May 07, 2026 at 07:33:40AM -0700, Jakub Kicinski wrote:
>On Thu, 7 May 2026 14:59:13 +0200 Stefano Garzarella wrote:
>> >well if you want to support pathological cases such as 1 byte messages
>> >that would mean like 100x reduction no?
>>
>> Yep, but since this patch is already merged, IMHO that is better than
>> losing data in those pathological cases.
>
>We can revert if you think that the risk of regression is high..
>Please LMK soon, we can do it before patch reaches Linus.
>
Some tests in tools/testing/vsock/vsock_test.c are failing with this
patch applied.
Test 18 are failing sometime in this way (I guess because we are
dropping packets):
18 - SOCK_STREAM MSG_ZEROCOPY...hash mismatch
Test 22 is failing 100% in this way:
22 - SOCK_STREAM virtio credit update + SO_RCVLOWAT...send failed:
Resource temporarily unavailable
With my followup patch adding also advertisement to the other peer
(still draft locally, waiting for Michael proposal) I saw 22 failing,
because tests expects that can use the entire buf_alloc, but now we are
reducing it. So IMO we should do like in `__sock_set_rcvbuf()` and
double the buffer size, or at least digest an overhead equal to the
buffer size set by the user via SO_VM_SOCKETS_BUFFER_SIZE (yeah,
AF_VSOCK has it owns sockopt since the beginning :-().
With that approach tests are passing, but I'd like to stress a bit more
that patch. I'll send it tomorrow as fixup of this patch, or if you
prefer to revert, I'll send as standalone.
Thanks,
Stefano
^ permalink raw reply
* Re: [PATCH net-next v10 4/4] tun/tap & vhost-net: avoid ptr_ring tail-drop when a qdisc is present
From: Simon Schippers @ 2026-05-07 15:19 UTC (permalink / raw)
To: Michael S. Tsirkin
Cc: willemdebruijn.kernel, jasowang, andrew+netdev, davem, edumazet,
kuba, pabeni, eperezma, leiyang, stephen, jon, tim.gebauer,
netdev, linux-kernel, kvm, virtualization
In-Reply-To: <c9fc9e0a-0837-49b4-91b9-4adb54c1a037@tu-dortmund.de>
On 5/7/26 08:32, Simon Schippers wrote:
> On 5/7/26 00:56, Michael S. Tsirkin wrote:
>> On Wed, May 06, 2026 at 06:28:06PM -0400, Michael S. Tsirkin wrote:
>>> On Wed, May 06, 2026 at 04:10:33PM +0200, Simon Schippers wrote:
>>>> This commit prevents tail-drop when a qdisc is present and the ptr_ring
>>>> becomes full. Once an entry is successfully produced and the ptr_ring
>>>> reaches capacity, the netdev queue is stopped instead of dropping
>>>> subsequent packets. If no qdisc is present, the previous tail-drop
>>>> behavior is preserved.
>>>>
>>>> If producing an entry fails anyways due to a race, tun_net_xmit() drops
>>>> the packet. Such races are expected because LLTX is enabled and the
>>>> transmit path operates without the usual locking.
>>>>
>>>> The __tun_wake_queue() function of the consumer races with the producer
>>>> for waking/stopping the netdev queue, which could result in a stalled
>>>> queue. Therefore, an smp_mb__after_atomic() is introduced that pairs
>>>> with the smp_mb() of the consumer. It follows the principle of store
>>>> buffering described in tools/memory-model/Documentation/recipes.txt:
>>>>
>>>> - The producer in tun_net_xmit() first sets __QUEUE_STATE_DRV_XOFF,
>>>> followed by an smp_mb__after_atomic() (= smp_mb()), and then reads the
>>>> ring with __ptr_ring_produce_peek().
>>>>
>>>> - The consumer in __tun_wake_queue() first writes zero to the ring in
>>>> __ptr_ring_consume(), followed by an smp_mb(), and then reads the queue
>>>> status with netif_tx_queue_stopped().
>>>>
>>>> => Following the aforementioned principle, it is impossible for the
>>>> producer to see a full ring (and therefore not wake the queue on the
>>>> re-check) while the consumer simultaneously fails to see a stopped
>>>> queue (and therefore also does not wake it).
>>>>
>>>> Benchmarks:
>>>> The benchmarks show a slight regression in raw transmission performance
>>>> when using two sending threads. Packet loss also occurs only in the
>>>> two-thread sending case; no packet loss was observed with a single
>>>> sending thread.
>>>>
>>>> Test setup:
>>>> AMD Ryzen 5 5600X at 4.3 GHz, 3200 MHz RAM, isolated QEMU threads;
>>>> Average over 50 runs @ 100,000,000 packets. SRSO and spectre v2
>>>> mitigations disabled.
>>>>
>>>> Note for tap+vhost-net:
>>>> XDP drop program active in VM -> ~2.5x faster; slower for tap due to
>>>> more syscalls (high utilization of entry_SYSRETQ_unsafe_stack in perf)
>>>>
>>>> +--------------------------+--------------+----------------+----------+
>>>> | 1 thread | Stock | Patched with | diff |
>>>> | sending | | fq_codel qdisc | |
>>>> +------------+-------------+--------------+----------------+----------+
>>>> | TAP | Received | 1.132 Mpps | 1.133 Mpps | +0.1% |
>>>> | +-------------+--------------+----------------+----------+
>>>> | | Lost/s | 3.765 Mpps | 0 pps | |
>>>> +------------+-------------+--------------+----------------+----------+
>>>> | TAP | Received | 3.857 Mpps | 3.905 Mpps | +1.2% |
>>>> | +-------------+--------------+----------------+----------+
>>>> | +vhost-net | Lost/s | 0.802 Mpps | 0 pps | |
>>>> +------------+-------------+--------------+----------------+----------+
>>>>
>>>> +--------------------------+--------------+----------------+----------+
>>>> | 2 threads | Stock | Patched with | diff |
>>>> | sending | | fq_codel qdisc | |
>>>> +------------+-------------+--------------+----------------+----------+
>>>> | TAP | Received | 1.115 Mpps | 1.092 Mpps | -2.1% |
>>>> | +-------------+--------------+----------------+----------+
>>>> | | Lost/s | 8.490 Mpps | 359 pps | |
>>>> +------------+-------------+--------------+----------------+----------+
>>>> | TAP | Received | 3.664 Mpps | 3.549 Mpps | -3.1% |
>>>> | +-------------+--------------+----------------+----------+
>>>> | +vhost-net | Lost/s | 5.330 Mpps | 832 pps | |
>>>> +------------+-------------+--------------+----------------+----------+
>>>>
>>>> Co-developed-by: Tim Gebauer <tim.gebauer@tu-dortmund.de>
>>>> Signed-off-by: Tim Gebauer <tim.gebauer@tu-dortmund.de>
>>>> Signed-off-by: Simon Schippers <simon.schippers@tu-dortmund.de>
>>>> ---
>>>> drivers/net/tun.c | 25 +++++++++++++++++++++++--
>>>> 1 file changed, 23 insertions(+), 2 deletions(-)
>>>>
>>>> diff --git a/drivers/net/tun.c b/drivers/net/tun.c
>>>> index fc358c4c355b..d9ffbf88cfd8 100644
>>>> --- a/drivers/net/tun.c
>>>> +++ b/drivers/net/tun.c
>>>> @@ -1018,6 +1018,7 @@ static netdev_tx_t tun_net_xmit(struct sk_buff *skb, struct net_device *dev)
>>>> struct netdev_queue *queue;
>>>> struct tun_file *tfile;
>>>> int len = skb->len;
>>>> + int ret;
>>>>
>>>> rcu_read_lock();
>>>> tfile = rcu_dereference(tun->tfiles[txq]);
>>>> @@ -1072,13 +1073,33 @@ static netdev_tx_t tun_net_xmit(struct sk_buff *skb, struct net_device *dev)
>>>>
>>>> nf_reset_ct(skb);
>>>>
>>>> - if (ptr_ring_produce(&tfile->tx_ring, skb)) {
>>>> + queue = netdev_get_tx_queue(dev, txq);
>>>> +
>>>> + spin_lock(&tfile->tx_ring.producer_lock);
>>>> + ret = __ptr_ring_produce(&tfile->tx_ring, skb);
>>>> + if (!qdisc_txq_has_no_queue(queue) &&
>>>> + (__ptr_ring_produce_peek(&tfile->tx_ring) || ret)) {
>>>> + netif_tx_stop_queue(queue);
>>>> + /* Paired with smp_mb() in __tun_wake_queue() */
>>>> + smp_mb__after_atomic();
>>>> + if (!__ptr_ring_produce_peek(&tfile->tx_ring))
>>>> + netif_tx_wake_queue(queue);
>>>> + }
>>>> + spin_unlock(&tfile->tx_ring.producer_lock);
>>>> +
>>>
>>> There's a weird corner case here when tx_queue_len is 0
>>> but a qdisc has been configured - it looks like that
>>> currently it just drops all packets, with this change,
>>> the qdisc will get stuck permanently.
>>>
>>> I suspect just checking tx_ring.size should fix it.
>>> Or if you feel adventurous, change return code for __ptr_ring_produce
>>> to distinguish between "no ring" and "no space".
>>
>>
>> __ptr_ring_produce_peek really.
>>
>
> Yes, I like the approach of returning this from
> __ptr_ring_produce_peek(). Then I will do a switch on the return value
> in tun_net_xmit().
Sashiko reports the same :)
So for the v11 I will:
- Change __ptr_ring_produce_peek() to return -ENOSPC / -EINVAL? (for 0
sized ring) / 0
- Lock the ring.consumer_lock in __tun_detach() to avoid a race with
consumer (Sashiko).
>
> Additionally, I should wake up in tun_queue_resize() after calling
> ptr_ring_resize_multiple_bh(). For a new dev->tx_queue_len > 0, it
> should be fine without waking, but for 0 it is not.
>
>>
>>>
>>>> + if (ret) {
>>>> + /* This should be a rare case if a qdisc is present, but
>>>> + * can happen due to lltx.
>>>> + * Since skb_tx_timestamp(), skb_orphan(),
>>>> + * run_ebpf_filter() and pskb_trim() could have tinkered
>>>> + * with the SKB, returning NETDEV_TX_BUSY is unsafe and
>>>> + * we must drop instead.
>>>> + */
>>>> drop_reason = SKB_DROP_REASON_FULL_RING;
>>>> goto drop;
>>>> }
>>>>
>>>> /* dev->lltx requires to do our own update of trans_start */
>>>> - queue = netdev_get_tx_queue(dev, txq);
>>>> txq_trans_cond_update(queue);
>>>>
>>>> /* Notify and wake up reader process */
>>>> --
>>>> 2.43.0
>>
^ permalink raw reply
* Re: [PATCH net] vsock/virtio: fix potential unbounded skb queue
From: Michael S. Tsirkin @ 2026-05-07 14:52 UTC (permalink / raw)
To: Stefano Garzarella
Cc: Eric Dumazet, Arseniy Krasnov, Bobby Eshleman, Stefan Hajnoczi,
David S . Miller, Jakub Kicinski, Paolo Abeni, Simon Horman,
netdev, eric.dumazet, Arseniy Krasnov, Jason Wang, Xuan Zhuo,
Eugenio Pérez, kvm, virtualization
In-Reply-To: <afyMCyBvZpzWrLtO@sgarzare-redhat>
On Thu, May 07, 2026 at 02:59:13PM +0200, Stefano Garzarella wrote:
> On Thu, May 07, 2026 at 07:45:10AM -0400, Michael S. Tsirkin wrote:
> > On Thu, May 07, 2026 at 11:09:47AM +0200, Stefano Garzarella wrote:
> > > On Wed, May 06, 2026 at 11:37:45AM -0400, Michael S. Tsirkin wrote:
> > > > On Tue, May 05, 2026 at 06:11:13PM +0200, Stefano Garzarella wrote:
> > > > > On Tue, May 05, 2026 at 07:14:36AM -0700, Eric Dumazet wrote:
> > > > > > On Tue, May 5, 2026 at 6:52 AM Stefano Garzarella <sgarzare@redhat.com> wrote:
> > > > > > >
> > > > > > > On Thu, Apr 30, 2026 at 12:26:52PM +0000, Eric Dumazet wrote:
> > > > > > > >virtio_transport_inc_rx_pkt() checks vvs->rx_bytes + len > vvs->buf_alloc.
> > > > > > > >
> > > > > > > >virtio_transport_recv_enqueue() skips coalescing for packets
> > > > > > > >with VIRTIO_VSOCK_SEQ_EOM.
> > > > > > > >
> > > > > > > >If fed with packets with len == 0 and VIRTIO_VSOCK_SEQ_EOM,
> > > > > > > >a very large number of packets can be queued
> > > > > > > >because vvs->rx_bytes stays at 0.
> > > > > > > >
> > > > > > > >Fix this by estimating the skb metadata size:
> > > > > > > >
> > > > > > > > (Number of skbs in the queue) * SKB_TRUESIZE(0)
> > > > > > > >
> > > > > > > >Fixes: 077706165717 ("virtio/vsock: don't use skbuff state to account credit")
> > > > > > > >Signed-off-by: Eric Dumazet <edumazet@google.com>
> > > > > > > >Cc: Arseniy Krasnov <AVKrasnov@sberdevices.ru>
> > > > > > > >Cc: Stefan Hajnoczi <stefanha@redhat.com>
> > > > > > > >Cc: Stefano Garzarella <sgarzare@redhat.com>
> > > > > > > >Cc: "Michael S. Tsirkin" <mst@redhat.com>
> > > > > > > >Cc: Jason Wang <jasowang@redhat.com>
> > > > > > > >Cc: Xuan Zhuo <xuanzhuo@linux.alibaba.com>
> > > > > > > >Cc: "Eugenio Pérez" <eperezma@redhat.com>
> > > > > > > >Cc: kvm@vger.kernel.org
> > > > > > > >Cc: virtualization@lists.linux.dev
> > > > > > > >---
> > > > > > > > net/vmw_vsock/virtio_transport_common.c | 4 +++-
> > > > > > > > 1 file changed, 3 insertions(+), 1 deletion(-)
> > > > > > > >
> > > > > > > >diff --git a/net/vmw_vsock/virtio_transport_common.c b/net/vmw_vsock/virtio_transport_common.c
> > > > > > > >index 416d533f493d7b07e9c77c43f741d28cfcd0953e..9b8014516f4fb1130ae184635fbba4dfee58bd64 100644
> > > > > > > >--- a/net/vmw_vsock/virtio_transport_common.c
> > > > > > > >+++ b/net/vmw_vsock/virtio_transport_common.c
> > > > > > > >@@ -447,7 +447,9 @@ static int virtio_transport_send_pkt_info(struct vsock_sock *vsk,
> > > > > > > > static bool virtio_transport_inc_rx_pkt(struct virtio_vsock_sock *vvs,
> > > > > > > > u32 len)
> > > > > > > > {
> > > > > > > >- if (vvs->buf_used + len > vvs->buf_alloc)
> > > > > > > >+ u64 skb_overhead = (skb_queue_len(&vvs->rx_queue) + 1) * SKB_TRUESIZE(0);
> > > > > > > >+
> > > > > > > >+ if (skb_overhead + vvs->buf_used + len > vvs->buf_alloc)
> > > > > > > > return false;
> > > > > > >
> > > > > > > I'm not sure about this fix, I mean that maybe this is incomplete.
> > > > > > > In virtio-vsock, there is a credit mechanism between the two peers:
> > > > > > > https://docs.oasis-open.org/virtio/virtio/v1.3/csd01/virtio-v1.3-csd01.html#x1-4850003
> > > > > > >
> > > > > > > This takes only the payload into account, so it’s true that this problem
> > > > > > > exists; however, perhaps we should also inform the other peer of a lower
> > > > > > > credit balance, otherwise the other peer will believe it has much more
> > > > > > > credit than it actually does, send a large payload, and then the packet
> > > > > > > will be discarded and the data lost (there are no retransmissions,
> > > > > > > etc.).
> > > > > >
> > > > > > I dunno, perhaps revert 077706165717 ("virtio/vsock: don't use skbuff
> > > > > > state to account credit")
> > > > > > and find a better fix then?
> > > > >
> > > > > IIRC the same issue was there before the commit fixed by that one (commit
> > > > > 71dc9ec9ac7d ("virtio/vsock: replace virtio_vsock_pkt with sk_buff")), so
> > > > > not sure about reverting it TBH.
> > > > >
> > > > > CCing Arseniy and Bobby.
> > > > >
> > > > > >
> > > > > > There is always a discrepancy between skb->len and skb->truesize.
> > > > > > You will not be able to announce a 1MB window, and accept one milliion
> > > > > > skb of 1-byte each.
> > > > > >
> > > > > > This kind of contract is broken.
> > > > > >
> > > > >
> > > > > Yep, I agree, but before we start discarding data (and losing it), IMHO we
> > > > > should at least inform the other peer that we're out of space.
> > > > >
> > > > > @Stefan, @Michael, do you think we can do something in the spec to avoid
> > > > > this issue and in some way take into account also the metadata in the
> > > > > credit. I mean to avoid the 1-byte packets flooding.
> > > > >
> > > > > Thanks,
> > > > > Stefano
> > > >
> > > > Why do we need the metadata? Just don't keep it around if you begin
> > > > running low on memory.
> > >
> > > I don't think removing the skuffs will be easy; we added them for ebpf,
> > > zero-copy, and seqpacket as well.
> >
> > You do not need to remove them completely.
> >
> > > For now, we're already doing something:
> > > merging the skuffs if they don't have EOM set.
> >
> >
> > Right that's good. You could go further and merge with EOM too
> > if you stick the info about message boundaries somewhere else.
>
> This adds a lot of complexity IMO, but we can try.
>
> Do you have something in mind?
I'll send something shortly just to give you an idea.
> >
> > > As a quick fix, I'm thinking of reducing the `buf_alloc` value to account
> > > for the overhead and notifying the other peer, at least until we find a
> > > better solution.
> > >
> > > Stefano
> >
> > well if you want to support pathological cases such as 1 byte messages
> > that would mean like 100x reduction no?
> >
>
> Yep, but since this patch is already merged, IMHO that is better than losing
> data in those pathological cases.
>
> Thanks,
> Stefano
^ permalink raw reply
page: next (older) | prev (newer) | latest
- recent:[subjects (threaded)|topics (new)|topics (active)]
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox