* [PATCH v3 1/4] vhost/vsock: split out vhost_vsock_drop_backends helper
From: Andrey Drobyshev @ 2026-06-25 15:54 UTC (permalink / raw)
To: linux-kernel
Cc: kvm, virtualization, netdev, sgarzare, mst, stefanha,
dongli.zhang, maciej.szmigiero, bchaney, mark.kanda, ptikhomirov,
den, andrey.drobyshev
In-Reply-To: <20260625155416.480669-1-andrey.drobyshev@virtuozzo.com>
From: Pavel Tikhomirov <ptikhomirov@virtuozzo.com>
Split the actual backend dropping part from vhost_vsock_stop. We're
going to need it for the VHOST_RESET_OWNER implementation in the
following patch, when vsock->dev.mutex is already taken and owner is
checked.
Signed-off-by: Pavel Tikhomirov <ptikhomirov@virtuozzo.com>
Signed-off-by: Andrey Drobyshev <andrey.drobyshev@virtuozzo.com>
Reviewed-by: Pavel Tikhomirov <ptikhomirov@virtuozzo.com>
Reviewed-by: Stefano Garzarella <sgarzare@redhat.com>
---
drivers/vhost/vsock.c | 26 +++++++++++++++++---------
1 file changed, 17 insertions(+), 9 deletions(-)
diff --git a/drivers/vhost/vsock.c b/drivers/vhost/vsock.c
index 9aaab6bb8061..b12221ce6faf 100644
--- a/drivers/vhost/vsock.c
+++ b/drivers/vhost/vsock.c
@@ -664,9 +664,24 @@ static int vhost_vsock_start(struct vhost_vsock *vsock)
return ret;
}
-static int vhost_vsock_stop(struct vhost_vsock *vsock, bool check_owner)
+static void vhost_vsock_drop_backends(struct vhost_vsock *vsock)
{
+ struct vhost_virtqueue *vq;
size_t i;
+
+ lockdep_assert_held(&vsock->dev.mutex);
+
+ for (i = 0; i < ARRAY_SIZE(vsock->vqs); i++) {
+ vq = &vsock->vqs[i];
+
+ mutex_lock(&vq->mutex);
+ vhost_vq_set_backend(vq, NULL);
+ mutex_unlock(&vq->mutex);
+ }
+}
+
+static int vhost_vsock_stop(struct vhost_vsock *vsock, bool check_owner)
+{
int ret = 0;
mutex_lock(&vsock->dev.mutex);
@@ -677,14 +692,7 @@ static int vhost_vsock_stop(struct vhost_vsock *vsock, bool check_owner)
goto err;
}
- for (i = 0; i < ARRAY_SIZE(vsock->vqs); i++) {
- struct vhost_virtqueue *vq = &vsock->vqs[i];
-
- mutex_lock(&vq->mutex);
- vhost_vq_set_backend(vq, NULL);
- mutex_unlock(&vq->mutex);
- }
-
+ vhost_vsock_drop_backends(vsock);
err:
mutex_unlock(&vsock->dev.mutex);
return ret;
--
2.47.1
^ permalink raw reply related
* [PATCH v3 0/4] vhost/vsock: add support for VHOST_RESET_OWNER and CPR migration
From: Andrey Drobyshev @ 2026-06-25 15:54 UTC (permalink / raw)
To: linux-kernel
Cc: kvm, virtualization, netdev, sgarzare, mst, stefanha,
dongli.zhang, maciej.szmigiero, bchaney, mark.kanda, ptikhomirov,
den, andrey.drobyshev
v2 -> v3:
* Patch 4: skip the kick of TX VQ worker once backend is gone - add
to cancel_pkt() the same guard as in send_pkt().
(Reported by Sashiko AI)
v2: https://lore.kernel.org/virtualization/20260622175808.508084-1-andrey.drobyshev@virtuozzo.com
Andrey Drobyshev (2):
vhost/vsock: suppress EHOSTUNREACH fast-fail during CPR pause
vhost/vsock: re-scan TX virtqueue on device start
Pavel Tikhomirov (2):
vhost/vsock: split out vhost_vsock_drop_backends helper
vhost/vsock: add VHOST_RESET_OWNER ioctl
drivers/vhost/vsock.c | 106 +++++++++++++++++++++++++++++++++---------
1 file changed, 85 insertions(+), 21 deletions(-)
--
2.47.1
^ permalink raw reply
* Re: [PATCH v2 0/4] vhost/vsock: add support for VHOST_RESET_OWNER and CPR migration
From: Pavel Tikhomirov @ 2026-06-25 15:32 UTC (permalink / raw)
To: Andrey Drobyshev, linux-kernel
Cc: kvm, virtualization, netdev, sgarzare, mst, stefanha,
dongli.zhang, maciej.szmigiero, bchaney, mark.kanda, den
In-Reply-To: <20260622175808.508084-1-andrey.drobyshev@virtuozzo.com>
Reviewed-by: Pavel Tikhomirov <ptikhomirov@virtuozzo.com>
On 6/22/26 19:58, Andrey Drobyshev wrote:
> v1 -> v2:
>
> * Patch 2 (suppress EHOSTUNREACH): replace 'cpr_paused' + backend check
> with a single 'started' latch;
> * Patch 3 (re-scan TX virtqueue): reword commit message;
> * Patch 4 (VHOST_RESET_OWNER):
> - fix a vhost_worker use-after-free / stuck VHOST_WORK_QUEUED stall
> against the lockless send path;
> - drop the no-op vsock_for_each_connected_socket() iteration;
> * Shuffle the patches, keep RESET_OWNER implementation last to preserve
> bisectability;
> * Reword the cover letter.
>
> v1: https://lore.kernel.org/virtualization/20260612165718.433546-1-andrey.drobyshev@virtuozzo.com
>
> Host<-->guest connections via AF_VSOCK sockets aren't supposed to
> outlive VM migration, since VM is moving to another host. However
> there's a special case, which is QEMU live-update, or CPR
> (checkpoint-restore) migration. In this case, VM remains on the same
> host, and we'd like such connections to persist.
>
> For this to work, we need to be able to transfer device ownership from
> source QEMU to dest QEMU. Namely, source needs to reset ownership by
> issuing VHOST_RESET_OWNER ioctl, and then target has to claim it by
> calling VHOST_SET_OWNER.
>
> Since VHOST_RESET_OWNER isn't yet implemented for vhost-vsock, let's add
> such implementation. Patch 1 is a preliminary helper. Patches 2 and 3
> fix the pre-existing issues which do manifest during CPR / RESET_OWNER.
> Patch 4 is the ioctl's implementation itself - we keep it last to
> preserve bisectability.
>
> There's a complementary series for QEMU [0] adding support of vhost-vsock
> devices during CPR migration.
>
> I've tested this (patched QEMU + patched kernel) approximately as follows:
>
> * Run listener in the guest:
> socat -u VSOCK-LISTEN:9999 - >/tmp/recv.bin
>
> * Run data transfer from host to guest:
> socat -u FILE:/root/bigfile.bin VSOCK-CONNECT:CID:9999
>
> * Perform CPR migration during transfer (either cpr-exec or cpr-transfer)
> * Check that file hash sum matches
>
> [0] https://lore.kernel.org/qemu-devel/20260619105514.128812-1-andrey.drobyshev@virtuozzo.com
>
> Andrey Drobyshev (2):
> vhost/vsock: suppress EHOSTUNREACH fast-fail during CPR pause
> vhost/vsock: re-scan TX virtqueue on device start
>
> Pavel Tikhomirov (2):
> vhost/vsock: split out vhost_vsock_drop_backends helper
> vhost/vsock: add VHOST_RESET_OWNER ioctl
>
> drivers/vhost/vsock.c | 96 ++++++++++++++++++++++++++++++++++---------
> 1 file changed, 76 insertions(+), 20 deletions(-)
>
--
Best regards, Pavel Tikhomirov
Senior Software Developer, Virtuozzo.
^ permalink raw reply
* Re: [PATCH 1/2] tools/virtio: Add missing compat definitions for vhost_net_test
From: Eugenio Perez Martin @ 2026-06-25 14:05 UTC (permalink / raw)
To: Yichong Chen
Cc: mst, jasowang, xuanzhuo, rppt, ljs, akpm, virtualization,
linux-kernel
In-Reply-To: <84157955DFE4842D+20260618095642.510565-2-chenyichong@uniontech.com>
On Thu, Jun 18, 2026 at 11:59 AM Yichong Chen <chenyichong@uniontech.com> wrote:
>
> vhost_net_test builds virtio_ring.c in userspace.
>
> Recent virtio headers pull in new helper headers.
>
> They also use new allocation helpers and a DMA attribute.
>
> Add the missing compat definitions.
>
I'm all in with this patch but it still misses some headers, could you
check again with latest master?
$ make vhost_net_test
cc -g -O2 -Werror -Wno-maybe-uninitialized -Wall -I. -I../include/ -I
../../usr/include/ -Wno-pointer-sign -fno-strict-overflow
-fno-strict-aliasing -fno-common -MMD -U_FORTIFY_SOURCE -include
../../include/linux/kconfig.h -mfunction-return=thunk
-fcf-protection=none -mindirect-branch-register -pthread -c -o
virtio_ring.o ../../drivers/virtio/virtio_ring.c
In file included from ./linux/compiler.h:7,
from ./linux/kernel.h:12,
from ./linux/scatterlist.h:4,
from ./../../include/linux/virtio.h:7,
from ./linux/virtio.h:1,
from ../../drivers/virtio/virtio_ring.c:6:
./linux/../../../include/linux/compiler_types.h:638:10: fatal error:
asm/percpu_types.h: No such file or directory
638 | #include <asm/percpu_types.h>
| ^~~~~~~~~~~~~~~~~~~~
compilation terminated.
make: *** [<builtin>: virtio_ring.o] Error 1
> Signed-off-by: Yichong Chen <chenyichong@uniontech.com>
> ---
> tools/virtio/linux/completion.h | 9 +++++
> tools/virtio/linux/device.h | 1 +
> tools/virtio/linux/dma-mapping.h | 1 +
> tools/virtio/linux/mod_devicetable.h | 14 +++++++
> tools/virtio/linux/slab.h | 4 ++
> tools/virtio/linux/virtio_features.h | 56 ++++++++++++++++++++++++++++
> 6 files changed, 85 insertions(+)
> create mode 100644 tools/virtio/linux/completion.h
> create mode 100644 tools/virtio/linux/mod_devicetable.h
> create mode 100644 tools/virtio/linux/virtio_features.h
>
> diff --git a/tools/virtio/linux/completion.h b/tools/virtio/linux/completion.h
> new file mode 100644
> index 000000000000..5e54b679721b
> --- /dev/null
> +++ b/tools/virtio/linux/completion.h
> @@ -0,0 +1,9 @@
> +/* SPDX-License-Identifier: GPL-2.0 */
> +#ifndef _LINUX_COMPLETION_H
> +#define _LINUX_COMPLETION_H
> +
> +struct completion {
> + unsigned int done;
> +};
> +
> +#endif /* _LINUX_COMPLETION_H */
> diff --git a/tools/virtio/linux/device.h b/tools/virtio/linux/device.h
> index 075c2140d975..abf100cb0023 100644
> --- a/tools/virtio/linux/device.h
> +++ b/tools/virtio/linux/device.h
> @@ -1,4 +1,5 @@
> #ifndef LINUX_DEVICE_H
> +#define LINUX_DEVICE_H
>
> struct device {
> void *parent;
> diff --git a/tools/virtio/linux/dma-mapping.h b/tools/virtio/linux/dma-mapping.h
> index fddfa2fbb276..65e2974b3908 100644
> --- a/tools/virtio/linux/dma-mapping.h
> +++ b/tools/virtio/linux/dma-mapping.h
> @@ -59,5 +59,6 @@ enum dma_data_direction {
> * instead.
> */
> #define DMA_MAPPING_ERROR (~(dma_addr_t)0)
> +#define DMA_ATTR_DEBUGGING_IGNORE_CACHELINES 0
>
> #endif
> diff --git a/tools/virtio/linux/mod_devicetable.h b/tools/virtio/linux/mod_devicetable.h
> new file mode 100644
> index 000000000000..3ba594b8229d
> --- /dev/null
> +++ b/tools/virtio/linux/mod_devicetable.h
> @@ -0,0 +1,14 @@
> +/* SPDX-License-Identifier: GPL-2.0 */
> +#ifndef _LINUX_MOD_DEVICETABLE_H
> +#define _LINUX_MOD_DEVICETABLE_H
> +
> +#include <linux/types.h>
> +
> +struct virtio_device_id {
> + __u32 device;
> + __u32 vendor;
> +};
> +
> +#define VIRTIO_DEV_ANY_ID 0xffffffff
> +
> +#endif /* _LINUX_MOD_DEVICETABLE_H */
> diff --git a/tools/virtio/linux/slab.h b/tools/virtio/linux/slab.h
> index 319dcaa07755..13d94c6f663c 100644
> --- a/tools/virtio/linux/slab.h
> +++ b/tools/virtio/linux/slab.h
> @@ -4,4 +4,8 @@
> #define GFP_ATOMIC 0
> #define __GFP_NOWARN 0
> #define __GFP_ZERO 0
> +#define kmalloc_obj(VAR_OR_TYPE, ...) \
> + kmalloc(sizeof(VAR_OR_TYPE), GFP_KERNEL)
> +#define kmalloc_objs(VAR_OR_TYPE, COUNT, ...) \
> + kmalloc_array((COUNT), sizeof(VAR_OR_TYPE), GFP_KERNEL)
> #endif
> diff --git a/tools/virtio/linux/virtio_features.h b/tools/virtio/linux/virtio_features.h
> new file mode 100644
> index 000000000000..18c56610e209
> --- /dev/null
> +++ b/tools/virtio/linux/virtio_features.h
> @@ -0,0 +1,56 @@
> +/* SPDX-License-Identifier: GPL-2.0 */
> +#ifndef _LINUX_VIRTIO_FEATURES_H
> +#define _LINUX_VIRTIO_FEATURES_H
> +
> +#include <linux/bug.h>
> +#include <linux/string.h>
> +#include <linux/types.h>
> +
> +#define VIRTIO_FEATURES_U64S 2
> +#define VIRTIO_FEATURES_BITS (VIRTIO_FEATURES_U64S * 64)
> +
> +#define VIRTIO_BIT(b) (1ULL << ((b) & 0x3f))
> +#define VIRTIO_U64(b) ((b) >> 6)
> +
> +#define VIRTIO_DECLARE_FEATURES(name) \
> + union { \
> + u64 name; \
> + u64 name##_array[VIRTIO_FEATURES_U64S]; \
> + }
> +
> +static inline bool virtio_features_chk_bit(unsigned int bit)
> +{
> + return bit < VIRTIO_FEATURES_BITS;
> +}
> +
> +static inline bool virtio_features_test_bit(const u64 *features,
> + unsigned int bit)
> +{
> + return virtio_features_chk_bit(bit) &&
> + !!(features[VIRTIO_U64(bit)] & VIRTIO_BIT(bit));
> +}
> +
> +static inline void virtio_features_set_bit(u64 *features, unsigned int bit)
> +{
> + if (virtio_features_chk_bit(bit))
> + features[VIRTIO_U64(bit)] |= VIRTIO_BIT(bit);
> +}
> +
> +static inline void virtio_features_clear_bit(u64 *features, unsigned int bit)
> +{
> + if (virtio_features_chk_bit(bit))
> + features[VIRTIO_U64(bit)] &= ~VIRTIO_BIT(bit);
> +}
> +
> +static inline void virtio_features_zero(u64 *features)
> +{
> + memset(features, 0, sizeof(features[0]) * VIRTIO_FEATURES_U64S);
> +}
> +
> +static inline void virtio_features_from_u64(u64 *features, u64 from)
> +{
> + virtio_features_zero(features);
> + features[0] = from;
> +}
> +
> +#endif /* _LINUX_VIRTIO_FEATURES_H */
> --
> 2.51.0
>
^ permalink raw reply
* Re: [PATCH] vhost/net: fix clear_user start address in VHOST_GET_FEATURES_ARRAY
From: Eugenio Perez Martin @ 2026-06-25 13:56 UTC (permalink / raw)
To: rom.wang
Cc: Michael S . Tsirkin, Jason Wang, Paolo Abeni, kvm, virtualization,
netdev, linux-kernel, Yufeng Wang
In-Reply-To: <CAJaqyWcFm0A5ucL5TLP8+T8JNOiZyaL-_mb747_fKhH9Qm83ig@mail.gmail.com>
On Thu, Jun 25, 2026 at 3:48 PM Eugenio Perez Martin
<eperezma@redhat.com> wrote:
>
> On Tue, May 26, 2026 at 10:04 AM rom.wang <r4o5m6e8o@163.com> wrote:
> >
> > From: Yufeng Wang <wangyufeng@kylinos.cn>
> >
> > The clear_user() call in VHOST_GET_FEATURES_ARRAY incorrectly starts
> > at argp, which is the beginning of the features array, overwriting the
> > data just written by copy_to_user(). It should start after the copied
> > elements at argp + copied * sizeof(u64) to only zero the trailing
> > unused space.
> >
> > Fixes: 333c515d1896 ("vhost-net: allow configuring extended features")
> > Signed-off-by: Yufeng Wang <wangyufeng@kylinos.cn>
> > ---
> > drivers/vhost/net.c | 3 ++-
> > 1 file changed, 2 insertions(+), 1 deletion(-)
> >
> > diff --git a/drivers/vhost/net.c b/drivers/vhost/net.c
> > index db341c922673..70c578acf840 100644
> > --- a/drivers/vhost/net.c
> > +++ b/drivers/vhost/net.c
> > @@ -1777,7 +1777,8 @@ static long vhost_net_ioctl(struct file *f, unsigned int ioctl,
> > return -EFAULT;
> >
> > /* Zero the trailing space provided by user-space, if any */
> > - if (clear_user(argp, size_mul(count - copied, sizeof(u64))))
> > + if (clear_user(argp + copied * sizeof(u64),
> > + size_mul(count - copied, sizeof(u64))))
>
> The fix looks good to me, but why not use size_mul() macro for copied
> * sizeof(u64) multiplication?
>
Also, could you add a new switch to tools/virtio/vhost_net_test.c to
use the VHOST_GET_FEATURES_ARRAY and VHOST_SET_FEATURES_ARRAY instead
of VHOST_GET_FEATURES and VHOST_SET_FEATURES?
> > return -EFAULT;
> > return 0;
> > case VHOST_SET_FEATURES_ARRAY:
> > --
> > 2.34.1
> >
> >
^ permalink raw reply
* Re: [PATCH] tools/virtio: Remove unsupported --batch option from vhost_net_test
From: Eugenio Perez Martin @ 2026-06-25 13:55 UTC (permalink / raw)
To: Yichong Chen; +Cc: mst, jasowang, xuanzhuo, virtualization, linux-kernel
In-Reply-To: <E091F15D8FBE8F16+20260618100254.513806-1-chenyichong@uniontech.com>
On Thu, Jun 18, 2026 at 12:03 PM Yichong Chen <chenyichong@uniontech.com> wrote:
>
> vhost_net_test has --batch in longopts, but not in help.
>
> The parser never handles 'b', so --batch hits assert(0).
>
> Remove the unsupported option.
>
> Signed-off-by: Yichong Chen <chenyichong@uniontech.com>
Acked-by: Eugenio Pérez <eperezma@redhat.com>
Thanks!
> ---
> tools/virtio/vhost_net_test.c | 5 -----
> 1 file changed, 5 deletions(-)
>
> diff --git a/tools/virtio/vhost_net_test.c b/tools/virtio/vhost_net_test.c
> index 389d99a6d7c7..566e15420bb6 100644
> --- a/tools/virtio/vhost_net_test.c
> +++ b/tools/virtio/vhost_net_test.c
> @@ -450,11 +450,6 @@ static const struct option longopts[] = {
> .val = 'n',
> .has_arg = required_argument,
> },
> - {
> - .name = "batch",
> - .val = 'b',
> - .has_arg = required_argument,
> - },
> {
> }
> };
> --
> 2.51.0
>
^ permalink raw reply
* Re: [PATCH] vhost/net: fix clear_user start address in VHOST_GET_FEATURES_ARRAY
From: Eugenio Perez Martin @ 2026-06-25 13:48 UTC (permalink / raw)
To: rom.wang
Cc: Michael S . Tsirkin, Jason Wang, Paolo Abeni, kvm, virtualization,
netdev, linux-kernel, Yufeng Wang
In-Reply-To: <20260526080336.61296-1-r4o5m6e8o@163.com>
On Tue, May 26, 2026 at 10:04 AM rom.wang <r4o5m6e8o@163.com> wrote:
>
> From: Yufeng Wang <wangyufeng@kylinos.cn>
>
> The clear_user() call in VHOST_GET_FEATURES_ARRAY incorrectly starts
> at argp, which is the beginning of the features array, overwriting the
> data just written by copy_to_user(). It should start after the copied
> elements at argp + copied * sizeof(u64) to only zero the trailing
> unused space.
>
> Fixes: 333c515d1896 ("vhost-net: allow configuring extended features")
> Signed-off-by: Yufeng Wang <wangyufeng@kylinos.cn>
> ---
> drivers/vhost/net.c | 3 ++-
> 1 file changed, 2 insertions(+), 1 deletion(-)
>
> diff --git a/drivers/vhost/net.c b/drivers/vhost/net.c
> index db341c922673..70c578acf840 100644
> --- a/drivers/vhost/net.c
> +++ b/drivers/vhost/net.c
> @@ -1777,7 +1777,8 @@ static long vhost_net_ioctl(struct file *f, unsigned int ioctl,
> return -EFAULT;
>
> /* Zero the trailing space provided by user-space, if any */
> - if (clear_user(argp, size_mul(count - copied, sizeof(u64))))
> + if (clear_user(argp + copied * sizeof(u64),
> + size_mul(count - copied, sizeof(u64))))
The fix looks good to me, but why not use size_mul() macro for copied
* sizeof(u64) multiplication?
> return -EFAULT;
> return 0;
> case VHOST_SET_FEATURES_ARRAY:
> --
> 2.34.1
>
>
^ permalink raw reply
* Re: [PATCH v3 1/7] list: Add mutable iterator variants
From: Jani Nikula @ 2026-06-25 11:00 UTC (permalink / raw)
To: Kaitao Cheng, David Laight, Christian König,
David Hildenbrand (Arm), Alexei Starovoitov
Cc: Andrew Morton, David Hildenbrand, Jens Axboe, Tejun Heo,
Alexander Viro, Christian Brauner, Daniel Borkmann,
Andrii Nakryiko, Johannes Weiner, Peter Zijlstra, Ingo Molnar,
Arnaldo Carvalho de Melo, Namhyung Kim, Thomas Gleixner,
Juri Lelli, Vincent Guittot, Paul Moore, Andy Shevchenko,
Paul E. McKenney, Shakeel Butt, David Howells, Simona Vetter,
Randy Dunlap, Luca Ceresoli, Philipp Stanner, linux-block,
linux-kernel, cgroups, linux-ntfs-dev, linux-fsdevel, io-uring,
audit, bpf, netdev, dri-devel, linux-perf-users,
linux-trace-kernel, kexec, live-patching, linux-modules,
linux-crypto, linux-pm, rcu, sched-ext, linux-mm, virtualization,
damon, llvm, Kaitao Cheng, Muchun Song
In-Reply-To: <0ed6b5c3-e955-46e2-9fc6-075a0dfd1c4f@linux.dev>
On Thu, 25 Jun 2026, Kaitao Cheng <kaitao.cheng@linux.dev> wrote:
> 在 2026/6/24 22:23, David Laight 写道:
>> On Wed, 24 Jun 2026 15:23:47 +0200
>> Christian König <christian.koenig@amd.com> wrote:
>>> On 6/24/26 15:14, Kaitao Cheng wrote:
>>>> 在 2026/6/22 16:42, David Laight 写道:
>>>>> On Mon, 22 Jun 2026 12:05:31 +0800
>>>>> Kaitao Cheng <kaitao.cheng@linux.dev> wrote:
>>>>>
>>>>>> From: Kaitao Cheng <chengkaitao@kylinos.cn>
>>>>>>
>>>>>> The list_for_each*_safe() helpers are used when the loop body may
>>>>>> remove the current entry. Their API exposes the temporary cursor at
>>>>>> every call site, even though most users only need it for the iterator
>>>>>> implementation and never reference it in the loop body.
>>>>>>
>>>>>> Add *_mutable() variants for list and hlist iteration. The new helpers
>>>>>> support both forms: callers may keep passing an explicit temporary cursor
>>>>>> when they need to inspect or reset it, or omit it and let the helper use
>>>>>> a unique internal cursor.
>>>>>
>>>>> I'm not really sure 'mutable' means anything either.
>>>>> It is possible to make it valid for the loop body (or even other threads)
>>>>> to delete arbitrary list items - but that needs significant extra overheads.
>>>>>
>>>>> It might be worth doing something that doesn't need the extra variable,
>>>>> but there is little point doing all the churn just to rename things.
>>>>>
>>>>>>
>>>>>> This makes call sites that only mutate the list through the current entry
>>>>>> less noisy, while keeping the existing *_safe() helpers available for
>>>>>> compatibility.
>>>>>>
>>>>>> Signed-off-by: Kaitao Cheng <chengkaitao@kylinos.cn>
>>>>>> ---
>>>>>> include/linux/list.h | 269 +++++++++++++++++++++++++++++++++++++------
>>>>>> 1 file changed, 231 insertions(+), 38 deletions(-)
>>>>>>
>>>>>> diff --git a/include/linux/list.h b/include/linux/list.h
>>>>>> index 09d979976b3b..1081def7cea9 100644
>>>>>> --- a/include/linux/list.h
>>>>>> +++ b/include/linux/list.h
>>>>>> @@ -7,6 +7,7 @@
>>>>>> #include <linux/stddef.h>
>>>>>> #include <linux/poison.h>
>>>>>> #include <linux/const.h>
>>>>>> +#include <linux/args.h>
>>>>>>
>>>>>> #include <asm/barrier.h>
>>>>>>
>>>>>> @@ -763,28 +764,72 @@ static inline void list_splice_tail_init(struct list_head *list,
>>>>>> #define list_for_each_prev(pos, head) \
>>>>>> for (pos = (head)->prev; !list_is_head(pos, (head)); pos = pos->prev)
>>>>>>
>>>>>> -/**
>>>>>> - * list_for_each_safe - iterate over a list safe against removal of list entry
>>>>>> - * @pos: the &struct list_head to use as a loop cursor.
>>>>>> - * @n: another &struct list_head to use as temporary storage
>>>>>> - * @head: the head for your list.
>>>>>> +/*
>>>>>> + * list_for_each_safe is an old interface, use list_for_each_mutable instead.
>>>>>> */
>>>>>> #define list_for_each_safe(pos, n, head) \
>>>>>> for (pos = (head)->next, n = pos->next; \
>>>>>> !list_is_head(pos, (head)); \
>>>>>> pos = n, n = pos->next)
>>>>>>
>>>>>> +#define __list_for_each_mutable_internal(pos, tmp, head) \
>>>>>> + for (typeof(pos) tmp = (pos = (head)->next)->next; \
>>>>>
>>>>> Use auto
>>>>>
>>>>>> + !list_is_head(pos, (head)); \
>>>>>> + pos = tmp, tmp = pos->next)
>>>>>> +
>>>>>> +#define __list_for_each_mutable1(pos, head) \
>>>>>> + __list_for_each_mutable_internal(pos, __UNIQUE_ID(next), head)
>>>>>> +
>>>>>> +#define __list_for_each_mutable2(pos, next, head) \
>>>>>> + list_for_each_safe(pos, next, head)
>>>>>> +
>>>>>> /**
>>>>>> - * list_for_each_prev_safe - iterate over a list backwards safe against removal of list entry
>>>>>> + * list_for_each_mutable - iterate over a list safe against entry removal
>>>>>> * @pos: the &struct list_head to use as a loop cursor.
>>>>>> - * @n: another &struct list_head to use as temporary storage
>>>>>> - * @head: the head for your list.
>>>>>> + * @...: either (head) or (next, head)
>>>>>> + *
>>>>>> + * next: another &struct list_head to use as optional temporary storage.
>>>>>> + * The temporary cursor is internal unless explicitly supplied by
>>>>>> + * the caller.
>>>>>> + * head: the head for your list.
>>>>>> + */
>>>>>> +#define list_for_each_mutable(pos, ...) \
>>>>>> + CONCATENATE(__list_for_each_mutable, COUNT_ARGS(__VA_ARGS__)) \
>>>>>> + (pos, __VA_ARGS__)
>>>>>
>>>>> The variable argument count logic really just slows down compilation.
>>>>> Maybe there aren't enough copies of this code to make that significant.
>>>>> But just because you can do it doesn't mean it is a gooD idea.
>>>>> I'm also not sure it really adds anything to the readability.
>>>>>
>>>>> And, it you are going to make the middle argument optional there is
>>>>> no need to change the macro name.
>>>>
>>>> Christian König and Jani Nikula also disagree with the variadic-argument
>>>> implementation approach. If we abandon that method, it means we will
>>>> inevitably need to add some new macros. If mutable is not a good name,
>>>> suggestions for better alternatives would be welcome; coming up with a
>>>> suitable name is indeed rather tricky.
>>>
>>> I don't think you need to add a new macro for the specific use case that people want to modify the next element of the iteration.
>>>
>>> If I remember your numbers correctly that is a really corner case and keeping using the existing *_safe() macros for that sounds perfectly fine to me.
>>
>> IIRC currently you have a choice of either:
>> define Item that can't be deleted
>> list_for_each() The current item.
>> list_for_each_safe() The next item.
>> There is also likely to be code that updates the variables to allow
>> for other scenarios.
>>
>> Note that if increase a reference count and release a lock then list_for_each()
>> is likely safer than list_for_each_safe() :-)
>>
>> list.h has 9 variants of the 'safe' loop.
>> The bloat of another 9 is getting excessive.
>>
>> It has to be said that this is one of my least favourite type of list...
>
> Hi Christian König, David Laight, Jani Nikula, David Hildenbrand,
> Andy Shevchenko, Alexei Starovoitov
>
> For ease of discussion, I need to summarize the currently possible
> approaches and briefly describe their respective pros and cons,
> using the list_for_each_entry* interfaces as examples.
>
> 1. Add list_for_each_entry_mutable, while keeping list_for_each_entry
> and list_for_each_entry_safe unchanged. list_for_each_entry_mutable
> would be used specifically for safe deletion scenarios that do not
> need to expose the temporary cursor externally. The code can refer to
> the v1 version.
>
> Pros: Does not depend on immediate per-subsystem adaptation and can be
> merged directly.
> Cons: Requires adding a whole set of mutable interfaces, which makes the
> code somewhat redundant.
Seems fine, and the original _safe naming is ambiguous anyway.
> 2. Directly optimize away the temporary cursor in list_for_each_entry_safe
> and define it inside the loop instead, changing the interface from four
> arguments to three.
>
> Pros: Does not add redundant interfaces.
> Cons: (1) Users need to manually update special cases that use the
> traversal variable of list_for_each_entry_safe, the new
> list_for_each_entry_safe would no longer apply there and would
> need to be open-coded.
> (2) Because the macro arguments changes, all list_for_each_entry_safe
> callers would need to be modified and merged together, making it
> difficult to merge such a large amount of code at once.
This won't fly because there are literally thousands of
list_for_each_entry_safe() users.
> 3. Use a variadic macro approach to optimize list_for_each_entry_safe,
> so that it supports both three and four arguments.
>
> Pros: (1) Does not add redundant interfaces.
> (2) Does not depend on immediate per-subsystem adaptation and can
> be merged directly.
> Cons: (1) Increases compile time.
> (2) Makes the interface harder for users to use.
Basically I'm against any variadic macro tricks where the optional
argument is not the last argument. That's just way too surprising, and
goes against common practice in just about all other languages.
> 4. Optimize list_for_each_entry by defining the temporary cursor internally,
> making it compatible with the functionality of list_for_each_entry_safe.
> The code can refer to the v2 version.
>
> Pros: (1) Does not add redundant interfaces.
> (2) The number of externally visible arguments of list_for_each_entry
> remains unchanged, still three.
> Cons: (1) list_for_each_entry and list_for_each_entry_safe would be merged
> into one, and list_for_each_entry_safe would gradually be deprecated.
> (2) Users need to manually update special cases that use the traversal
> variable of list_for_each_entry, the new list_for_each_entry would no
> longer apply there and would need to be open-coded. There are 15 such
> cases in total.
This sounds good to me, though I take it there's some code size increase
and/or performance penalty?
Maybe the 15 cases are questionable anyway?
> 5. Use a variadic macro approach to optimize list_for_each_entry, so that
> it supports both three and four arguments.
>
> Pros: (1) Does not add redundant interfaces.
> (2) Does not depend on immediate per-subsystem adaptation and can be
> merged directly.
> Cons: (1) Increases compile time.
> (2) list_for_each_entry and list_for_each_entry_safe would be merged
> into one, and list_for_each_entry_safe would gradually be deprecated.
Please don't do the macro tricks.
> 6. Make no changes, keep the current logic unchanged, and close the current
> email discussion.
I like hiding the temporary stuff when possible.
BR,
Jani.
--
Jani Nikula, Intel
^ permalink raw reply
* Re: [PATCH net v3 1/2] iov_iter: export iov_iter_restore
From: Christian Brauner @ 2026-06-25 10:43 UTC (permalink / raw)
To: Octavian Purdila
Cc: netdev, Alexander Viro, Andrew Morton, Arseniy Krasnov,
David S. Miller, Eric Dumazet, Eugenio Pérez, Jakub Kicinski,
Jason Wang, kvm, linux-block, linux-fsdevel, linux-kernel,
Michael S. Tsirkin, Paolo Abeni, Simon Horman, Stefan Hajnoczi,
Stefano Garzarella, virtualization, Xuan Zhuo, Jens Axboe
In-Reply-To: <20260622222757.2130402-2-tavip@google.com>
> Export iov_iter_restore so that it can be used by modules.
>
> This is needed by the virtio vsock transport (which can be built as a
> module) to restore the msg_iter state when transmission fails.
>
> Acked-by: Stefano Garzarella <sgarzare@redhat.com>
> Signed-off-by: Octavian Purdila <tavip@google.com>
>
> diff --git a/lib/iov_iter.c b/lib/iov_iter.c
> index 273919b16161..f5df63961fb2 100644
> --- a/lib/iov_iter.c
> +++ b/lib/iov_iter.c
> @@ -1491,6 +1491,7 @@ void iov_iter_restore(struct iov_iter *i, struct iov_iter_state *state)
> i->__iov -= state->nr_segs - i->nr_segs;
> i->nr_segs = state->nr_segs;
> }
> +EXPORT_SYMBOL_GPL(iov_iter_restore);
At least only export it for the module that really needs it. For
example, see:
EXPORT_SYMBOL_FOR_MODULES(__kernel_write, "autofs4");
--
Christian Brauner <brauner@kernel.org>
^ permalink raw reply
* Re: [PATCH] vdpa_sim: fix cleanup after worker creation failure
From: Eugenio Perez Martin @ 2026-06-25 8:54 UTC (permalink / raw)
To: Xiong Weimin; +Cc: virtualization, jasowang, mst, xuanzhuo
In-Reply-To: <20260625083017.497842-1-15927021679@163.com>
On Thu, Jun 25, 2026 at 10:37 AM Xiong Weimin <15927021679@163.com> wrote:
>
> From: Xiong Weimin <xiongweimin@kylinos.cn>
>
> vdpasim_create() leaves vdpasim->worker as an ERR_PTR when
> kthread_run_worker() fails. The error path then drops the device
> reference, which releases the partially initialized simulator.
>
> vdpasim_free() unconditionally passes the worker pointer to
> kthread_destroy_worker(), so the ERR_PTR is dereferenced and can
> trigger a general protection fault.
>
> Store the worker error, clear the pointer, and make the release path
> only clean up resources that were successfully initialized before
> the failure.
>
> Tested on openEuler VM with kernel 6.16.8: module build, reload,
> and vdpa dev add via vdpasim_net.
>
> Signed-off-by: Xiong Weimin <xiongweimin@kylinos.cn>
> ---
> drivers/vdpa/vdpa_sim/vdpa_sim.c | 24 ++++++++++++++++--------
> 1 file changed, 16 insertions(+), 8 deletions(-)
>
> diff --git a/drivers/vdpa/vdpa_sim/vdpa_sim.c b/drivers/vdpa/vdpa_sim/vdpa_sim.c
> index 1111111..2222222 100644
> --- a/drivers/vdpa/vdpa_sim/vdpa_sim.c
> +++ b/drivers/vdpa/vdpa_sim/vdpa_sim.c
> @@ -231,8 +231,11 @@ struct vdpasim *vdpasim_create(struct vdpasim_dev_attr *dev_attr,
> kthread_init_work(&vdpasim->work, vdpasim_work_fn);
> vdpasim->worker = kthread_run_worker(0, "vDPA sim worker: %s",
> dev_attr->name);
> - if (IS_ERR(vdpasim->worker))
> + if (IS_ERR(vdpasim->worker)) {
> + ret = PTR_ERR(vdpasim->worker);
> + vdpasim->worker = NULL;
> goto err_iommu;
> + }
>
> mutex_init(&vdpasim->mutex);
> spin_lock_init(&vdpasim->iommu_lock);
> @@ -750,18 +753,24 @@ static void vdpasim_free(struct vdpa_device *vdpa)
> struct vdpasim *vdpasim = vdpa_to_sim(vdpa);
> int i;
>
> - kthread_cancel_work_sync(&vdpasim->work);
> - kthread_destroy_worker(vdpasim->worker);
> + if (vdpasim->worker) {
> + kthread_cancel_work_sync(&vdpasim->work);
> + kthread_destroy_worker(vdpasim->worker);
> + }
>
> - for (i = 0; i < vdpasim->dev_attr.nvqs; i++) {
> - vringh_kiov_cleanup(&vdpasim->vqs[i].out_iov);
> - vringh_kiov_cleanup(&vdpasim->vqs[i].in_iov);
> + if (vdpasim->vqs) {
> + for (i = 0; i < vdpasim->dev_attr.nvqs; i++) {
> + vringh_kiov_cleanup(&vdpasim->vqs[i].out_iov);
> + vringh_kiov_cleanup(&vdpasim->vqs[i].in_iov);
> + }
> }
>
> vdpasim->dev_attr.free(vdpasim);
>
> - for (i = 0; i < vdpasim->dev_attr.nas; i++)
> - vhost_iotlb_reset(&vdpasim->iommu[i]);
> + if (vdpasim->iommu && vdpasim->iommu_pt) {
> + for (i = 0; i < vdpasim->dev_attr.nas; i++)
> + vhost_iotlb_reset(&vdpasim->iommu[i]);
> + }
> kfree(vdpasim->iommu);
> kfree(vdpasim->iommu_pt);
> kfree(vdpasim->vqs);
Isn't this the exact same fix as v1 of
https://lore.kernel.org/lkml/20260620100959.2070316-1-slf@hdu.edu.cn/
?
^ permalink raw reply
* [PATCH] vdpa_sim: fix cleanup after worker creation failure
From: Xiong Weimin @ 2026-06-25 8:30 UTC (permalink / raw)
To: virtualization; +Cc: jasowang, mst, xuanzhuo, eperezma
From: Xiong Weimin <xiongweimin@kylinos.cn>
vdpasim_create() leaves vdpasim->worker as an ERR_PTR when
kthread_run_worker() fails. The error path then drops the device
reference, which releases the partially initialized simulator.
vdpasim_free() unconditionally passes the worker pointer to
kthread_destroy_worker(), so the ERR_PTR is dereferenced and can
trigger a general protection fault.
Store the worker error, clear the pointer, and make the release path
only clean up resources that were successfully initialized before
the failure.
Tested on openEuler VM with kernel 6.16.8: module build, reload,
and vdpa dev add via vdpasim_net.
Signed-off-by: Xiong Weimin <xiongweimin@kylinos.cn>
---
drivers/vdpa/vdpa_sim/vdpa_sim.c | 24 ++++++++++++++++--------
1 file changed, 16 insertions(+), 8 deletions(-)
diff --git a/drivers/vdpa/vdpa_sim/vdpa_sim.c b/drivers/vdpa/vdpa_sim/vdpa_sim.c
index 1111111..2222222 100644
--- a/drivers/vdpa/vdpa_sim/vdpa_sim.c
+++ b/drivers/vdpa/vdpa_sim/vdpa_sim.c
@@ -231,8 +231,11 @@ struct vdpasim *vdpasim_create(struct vdpasim_dev_attr *dev_attr,
kthread_init_work(&vdpasim->work, vdpasim_work_fn);
vdpasim->worker = kthread_run_worker(0, "vDPA sim worker: %s",
dev_attr->name);
- if (IS_ERR(vdpasim->worker))
+ if (IS_ERR(vdpasim->worker)) {
+ ret = PTR_ERR(vdpasim->worker);
+ vdpasim->worker = NULL;
goto err_iommu;
+ }
mutex_init(&vdpasim->mutex);
spin_lock_init(&vdpasim->iommu_lock);
@@ -750,18 +753,24 @@ static void vdpasim_free(struct vdpa_device *vdpa)
struct vdpasim *vdpasim = vdpa_to_sim(vdpa);
int i;
- kthread_cancel_work_sync(&vdpasim->work);
- kthread_destroy_worker(vdpasim->worker);
+ if (vdpasim->worker) {
+ kthread_cancel_work_sync(&vdpasim->work);
+ kthread_destroy_worker(vdpasim->worker);
+ }
- for (i = 0; i < vdpasim->dev_attr.nvqs; i++) {
- vringh_kiov_cleanup(&vdpasim->vqs[i].out_iov);
- vringh_kiov_cleanup(&vdpasim->vqs[i].in_iov);
+ if (vdpasim->vqs) {
+ for (i = 0; i < vdpasim->dev_attr.nvqs; i++) {
+ vringh_kiov_cleanup(&vdpasim->vqs[i].out_iov);
+ vringh_kiov_cleanup(&vdpasim->vqs[i].in_iov);
+ }
}
vdpasim->dev_attr.free(vdpasim);
- for (i = 0; i < vdpasim->dev_attr.nas; i++)
- vhost_iotlb_reset(&vdpasim->iommu[i]);
+ if (vdpasim->iommu && vdpasim->iommu_pt) {
+ for (i = 0; i < vdpasim->dev_attr.nas; i++)
+ vhost_iotlb_reset(&vdpasim->iommu[i]);
+ }
kfree(vdpasim->iommu);
kfree(vdpasim->iommu_pt);
kfree(vdpasim->vqs);
--
2.39.0
^ permalink raw reply related
* RE: [RFCv2 PATCH 2/6] efi/unaccepted: Set unaccepted bits for all hotplug memory
From: Duan, Zhenzhong @ 2026-06-25 6:38 UTC (permalink / raw)
To: Kiryl Shutsemau
Cc: marcandre.lureau@redhat.com, david@kernel.org, Edgecombe, Rick P,
prsampat@amd.com, pbonzini@redhat.com, mst@redhat.com,
peterx@redhat.com, Qiang, Chenyi, Reshetova, Elena,
michael.roth@amd.com, ackerleytng@google.com,
linux-kernel@vger.kernel.org, linux-coco@lists.linux.dev,
virtualization@lists.linux.dev, x86@kernel.org, Xu, Yilun,
Li, Xiaoyao, Peng, Chao P
In-Reply-To: <ajvNXyYwb7FXAJhP@thinkstation>
>-----Original Message-----
>From: Kiryl Shutsemau <kas@kernel.org>
>Subject: Re: [RFCv2 PATCH 2/6] efi/unaccepted: Set unaccepted bits for all hotplug
>memory
>
>On Tue, Jun 23, 2026 at 06:17:33AM -0400, Zhenzhong Duan wrote:
>> In coco guests, hotpluggable memory ranges are initially unaccepted.
>> While a previous change expanded the unaccepted memory bitmap boundaries
>> to include these hotplug spaces, the actual bits inside the bitmap are
>> not yet marked as unaccepted.
>>
>> Walks SRAT a second time after the bitmap is allocated and sets the bits
>> corresponding to hotpluggable ranges.
>>
>> This ensures the bitmap state accurately reflects all static and hotplug
>> memory ranges before booting kernel.
>>
>> Signed-off-by: Zhenzhong Duan <zhenzhong.duan@intel.com>
>> ---
>> .../firmware/efi/libstub/unaccepted_memory.c | 18 ++++++++++++++++++
>> 1 file changed, 18 insertions(+)
>>
>> diff --git a/drivers/firmware/efi/libstub/unaccepted_memory.c
>b/drivers/firmware/efi/libstub/unaccepted_memory.c
>> index bfbb78bd7b8a..01bed8e751ca 100644
>> --- a/drivers/firmware/efi/libstub/unaccepted_memory.c
>> +++ b/drivers/firmware/efi/libstub/unaccepted_memory.c
>> @@ -92,6 +92,23 @@ static void update_mem_boundaries(struct
>acpi_srat_mem_affinity *mem, struct sra
>> *(ctx->mem_end) = range_end;
>> }
>>
>> +static void mark_hotplug_memory_unaccepted(struct acpi_srat_mem_affinity
>*mem,
>> + struct srat_parse_ctx *ctx)
>> +{
>> + u64 unit_size = unaccepted_table->unit_size;
>> + u64 start, end;
>> +
>> + start = round_up(mem->base_address, unit_size);
>> + end = round_down(mem->base_address + mem->length, unit_size);
>
>We can get here with start > end if srat range is less then unit_size.
Will add a check to ignore small range less than unit_size:
+ if (start >= end)
+ return;
+
Thanks
Zhenzhong
^ permalink raw reply
* RE: [RFCv2 PATCH 5/6] mm/memory_hotplug: Support ACPI hotplug/unplug for coco guest
From: Duan, Zhenzhong @ 2026-06-25 5:56 UTC (permalink / raw)
To: Kiryl Shutsemau
Cc: marcandre.lureau@redhat.com, david@kernel.org, Edgecombe, Rick P,
prsampat@amd.com, pbonzini@redhat.com, mst@redhat.com,
peterx@redhat.com, Qiang, Chenyi, Reshetova, Elena,
michael.roth@amd.com, ackerleytng@google.com,
linux-kernel@vger.kernel.org, linux-coco@lists.linux.dev,
virtualization@lists.linux.dev, x86@kernel.org, Xu, Yilun,
Li, Xiaoyao, Peng, Chao P
In-Reply-To: <ajvOP9NwqNstgNvl@thinkstation>
>-----Original Message-----
>From: Kiryl Shutsemau <kas@kernel.org>
>Subject: Re: [RFCv2 PATCH 5/6] mm/memory_hotplug: Support ACPI
>hotplug/unplug for coco guest
>
>On Tue, Jun 23, 2026 at 06:17:36AM -0400, Zhenzhong Duan wrote:
>> + spin_lock_irqsave(&unaccepted_memory_lock, flags);
>> + for (; range_start < bitmap_size; range_start = range_end) {
>> + unsigned long phys_start, phys_end;
>> + unsigned long unaccepted_one, plugged_zero;
>> +
>> + range_start = find_next_andnot_bit(plugged_bitmap,
>unaccepted->bitmap,
>> + bitmap_size, range_start);
>> +
>> + if (range_start >= bitmap_size)
>> + break;
>> +
>> + unaccepted_one = find_next_bit(unaccepted->bitmap,
>bitmap_size, range_start);
>> + plugged_zero = find_next_zero_bit(plugged_bitmap, bitmap_size,
>range_start);
>> + range_end = min(unaccepted_one, plugged_zero);
>> +
>> + phys_start = range_start * unit_size + unaccepted->phys_base;
>> + phys_end = range_end * unit_size + unaccepted->phys_base;
>> +
>> + arch_unaccept_memory(phys_start, phys_end);
>> + bitmap_set(unaccepted->bitmap, range_start, range_end -
>range_start);
>> + }
>> + spin_unlock_irqrestore(&unaccepted_memory_lock, flags);
>
>Accept TDCALL under the spin lock will kill scalability.
OK, I can drop the lock during arch_unaccept_memory() and avoid race
by checking the accepting_list just like in accept_memory().
I initially wrapped this in the spinlock because TDG.MEM.PAGE.RELEASE
is a quick local TDX module call to transition pages back to PENDING state,
without the heavy VMM trapping/faulting overhead associated with
memory acceptance paths.
Thanks
Zhenzhong
^ permalink raw reply
* Re: [PATCH v3 1/7] list: Add mutable iterator variants
From: Kaitao Cheng @ 2026-06-25 3:01 UTC (permalink / raw)
To: David Laight, Christian König, Jani Nikula,
David Hildenbrand (Arm), Alexei Starovoitov
Cc: Andrew Morton, David Hildenbrand, Jens Axboe, Tejun Heo,
Alexander Viro, Christian Brauner, Daniel Borkmann,
Andrii Nakryiko, Johannes Weiner, Peter Zijlstra, Ingo Molnar,
Arnaldo Carvalho de Melo, Namhyung Kim, Thomas Gleixner,
Juri Lelli, Vincent Guittot, Paul Moore, Andy Shevchenko,
Paul E. McKenney, Shakeel Butt, David Howells, Simona Vetter,
Randy Dunlap, Luca Ceresoli, Philipp Stanner, linux-block,
linux-kernel, cgroups, linux-ntfs-dev, linux-fsdevel, io-uring,
audit, bpf, netdev, dri-devel, linux-perf-users,
linux-trace-kernel, kexec, live-patching, linux-modules,
linux-crypto, linux-pm, rcu, sched-ext, linux-mm, virtualization,
damon, llvm, Kaitao Cheng, Muchun Song
In-Reply-To: <20260624152324.3def88ce@pumpkin>
在 2026/6/24 22:23, David Laight 写道:
> On Wed, 24 Jun 2026 15:23:47 +0200
> Christian König <christian.koenig@amd.com> wrote:
>> On 6/24/26 15:14, Kaitao Cheng wrote:
>>> 在 2026/6/22 16:42, David Laight 写道:
>>>> On Mon, 22 Jun 2026 12:05:31 +0800
>>>> Kaitao Cheng <kaitao.cheng@linux.dev> wrote:
>>>>
>>>>> From: Kaitao Cheng <chengkaitao@kylinos.cn>
>>>>>
>>>>> The list_for_each*_safe() helpers are used when the loop body may
>>>>> remove the current entry. Their API exposes the temporary cursor at
>>>>> every call site, even though most users only need it for the iterator
>>>>> implementation and never reference it in the loop body.
>>>>>
>>>>> Add *_mutable() variants for list and hlist iteration. The new helpers
>>>>> support both forms: callers may keep passing an explicit temporary cursor
>>>>> when they need to inspect or reset it, or omit it and let the helper use
>>>>> a unique internal cursor.
>>>>
>>>> I'm not really sure 'mutable' means anything either.
>>>> It is possible to make it valid for the loop body (or even other threads)
>>>> to delete arbitrary list items - but that needs significant extra overheads.
>>>>
>>>> It might be worth doing something that doesn't need the extra variable,
>>>> but there is little point doing all the churn just to rename things.
>>>>
>>>>>
>>>>> This makes call sites that only mutate the list through the current entry
>>>>> less noisy, while keeping the existing *_safe() helpers available for
>>>>> compatibility.
>>>>>
>>>>> Signed-off-by: Kaitao Cheng <chengkaitao@kylinos.cn>
>>>>> ---
>>>>> include/linux/list.h | 269 +++++++++++++++++++++++++++++++++++++------
>>>>> 1 file changed, 231 insertions(+), 38 deletions(-)
>>>>>
>>>>> diff --git a/include/linux/list.h b/include/linux/list.h
>>>>> index 09d979976b3b..1081def7cea9 100644
>>>>> --- a/include/linux/list.h
>>>>> +++ b/include/linux/list.h
>>>>> @@ -7,6 +7,7 @@
>>>>> #include <linux/stddef.h>
>>>>> #include <linux/poison.h>
>>>>> #include <linux/const.h>
>>>>> +#include <linux/args.h>
>>>>>
>>>>> #include <asm/barrier.h>
>>>>>
>>>>> @@ -763,28 +764,72 @@ static inline void list_splice_tail_init(struct list_head *list,
>>>>> #define list_for_each_prev(pos, head) \
>>>>> for (pos = (head)->prev; !list_is_head(pos, (head)); pos = pos->prev)
>>>>>
>>>>> -/**
>>>>> - * list_for_each_safe - iterate over a list safe against removal of list entry
>>>>> - * @pos: the &struct list_head to use as a loop cursor.
>>>>> - * @n: another &struct list_head to use as temporary storage
>>>>> - * @head: the head for your list.
>>>>> +/*
>>>>> + * list_for_each_safe is an old interface, use list_for_each_mutable instead.
>>>>> */
>>>>> #define list_for_each_safe(pos, n, head) \
>>>>> for (pos = (head)->next, n = pos->next; \
>>>>> !list_is_head(pos, (head)); \
>>>>> pos = n, n = pos->next)
>>>>>
>>>>> +#define __list_for_each_mutable_internal(pos, tmp, head) \
>>>>> + for (typeof(pos) tmp = (pos = (head)->next)->next; \
>>>>
>>>> Use auto
>>>>
>>>>> + !list_is_head(pos, (head)); \
>>>>> + pos = tmp, tmp = pos->next)
>>>>> +
>>>>> +#define __list_for_each_mutable1(pos, head) \
>>>>> + __list_for_each_mutable_internal(pos, __UNIQUE_ID(next), head)
>>>>> +
>>>>> +#define __list_for_each_mutable2(pos, next, head) \
>>>>> + list_for_each_safe(pos, next, head)
>>>>> +
>>>>> /**
>>>>> - * list_for_each_prev_safe - iterate over a list backwards safe against removal of list entry
>>>>> + * list_for_each_mutable - iterate over a list safe against entry removal
>>>>> * @pos: the &struct list_head to use as a loop cursor.
>>>>> - * @n: another &struct list_head to use as temporary storage
>>>>> - * @head: the head for your list.
>>>>> + * @...: either (head) or (next, head)
>>>>> + *
>>>>> + * next: another &struct list_head to use as optional temporary storage.
>>>>> + * The temporary cursor is internal unless explicitly supplied by
>>>>> + * the caller.
>>>>> + * head: the head for your list.
>>>>> + */
>>>>> +#define list_for_each_mutable(pos, ...) \
>>>>> + CONCATENATE(__list_for_each_mutable, COUNT_ARGS(__VA_ARGS__)) \
>>>>> + (pos, __VA_ARGS__)
>>>>
>>>> The variable argument count logic really just slows down compilation.
>>>> Maybe there aren't enough copies of this code to make that significant.
>>>> But just because you can do it doesn't mean it is a gooD idea.
>>>> I'm also not sure it really adds anything to the readability.
>>>>
>>>> And, it you are going to make the middle argument optional there is
>>>> no need to change the macro name.
>>>
>>> Christian König and Jani Nikula also disagree with the variadic-argument
>>> implementation approach. If we abandon that method, it means we will
>>> inevitably need to add some new macros. If mutable is not a good name,
>>> suggestions for better alternatives would be welcome; coming up with a
>>> suitable name is indeed rather tricky.
>>
>> I don't think you need to add a new macro for the specific use case that people want to modify the next element of the iteration.
>>
>> If I remember your numbers correctly that is a really corner case and keeping using the existing *_safe() macros for that sounds perfectly fine to me.
>
> IIRC currently you have a choice of either:
> define Item that can't be deleted
> list_for_each() The current item.
> list_for_each_safe() The next item.
> There is also likely to be code that updates the variables to allow
> for other scenarios.
>
> Note that if increase a reference count and release a lock then list_for_each()
> is likely safer than list_for_each_safe() :-)
>
> list.h has 9 variants of the 'safe' loop.
> The bloat of another 9 is getting excessive.
>
> It has to be said that this is one of my least favourite type of list...
Hi Christian König, David Laight, Jani Nikula, David Hildenbrand,
Andy Shevchenko, Alexei Starovoitov
For ease of discussion, I need to summarize the currently possible
approaches and briefly describe their respective pros and cons,
using the list_for_each_entry* interfaces as examples.
1. Add list_for_each_entry_mutable, while keeping list_for_each_entry
and list_for_each_entry_safe unchanged. list_for_each_entry_mutable
would be used specifically for safe deletion scenarios that do not
need to expose the temporary cursor externally. The code can refer to
the v1 version.
Pros: Does not depend on immediate per-subsystem adaptation and can be
merged directly.
Cons: Requires adding a whole set of mutable interfaces, which makes the
code somewhat redundant.
2. Directly optimize away the temporary cursor in list_for_each_entry_safe
and define it inside the loop instead, changing the interface from four
arguments to three.
Pros: Does not add redundant interfaces.
Cons: (1) Users need to manually update special cases that use the
traversal variable of list_for_each_entry_safe, the new
list_for_each_entry_safe would no longer apply there and would
need to be open-coded.
(2) Because the macro arguments changes, all list_for_each_entry_safe
callers would need to be modified and merged together, making it
difficult to merge such a large amount of code at once.
3. Use a variadic macro approach to optimize list_for_each_entry_safe,
so that it supports both three and four arguments.
Pros: (1) Does not add redundant interfaces.
(2) Does not depend on immediate per-subsystem adaptation and can
be merged directly.
Cons: (1) Increases compile time.
(2) Makes the interface harder for users to use.
4. Optimize list_for_each_entry by defining the temporary cursor internally,
making it compatible with the functionality of list_for_each_entry_safe.
The code can refer to the v2 version.
Pros: (1) Does not add redundant interfaces.
(2) The number of externally visible arguments of list_for_each_entry
remains unchanged, still three.
Cons: (1) list_for_each_entry and list_for_each_entry_safe would be merged
into one, and list_for_each_entry_safe would gradually be deprecated.
(2) Users need to manually update special cases that use the traversal
variable of list_for_each_entry, the new list_for_each_entry would no
longer apply there and would need to be open-coded. There are 15 such
cases in total.
5. Use a variadic macro approach to optimize list_for_each_entry, so that
it supports both three and four arguments.
Pros: (1) Does not add redundant interfaces.
(2) Does not depend on immediate per-subsystem adaptation and can be
merged directly.
Cons: (1) Increases compile time.
(2) list_for_each_entry and list_for_each_entry_safe would be merged
into one, and list_for_each_entry_safe would gradually be deprecated.
6. Make no changes, keep the current logic unchanged, and close the current
email discussion.
Which of the six solutions above do people prefer?
--
Thanks
Kaitao Cheng
^ permalink raw reply
* [PATCH] drm/virtio: fail init on display-info timeout
From: Pengpeng Hou @ 2026-06-25 3:02 UTC (permalink / raw)
To: David Airlie, Gerd Hoffmann, Dmitry Osipenko
Cc: Gurchetan Singh, Chia-I Wu, Maarten Lankhorst, Maxime Ripard,
Thomas Zimmermann, Simona Vetter, dri-devel, virtualization,
linux-kernel, pengpeng
virtio_gpu_init() sends GET_DISPLAY_INFO when scanouts are present and
waits for display_info_pending to clear. If the response never arrives,
the wait result is ignored and probe still succeeds.
Return -ETIMEDOUT on display-info timeout. Because this happens after
virtio_device_ready(), reset the device and tear down modesetting before
using the existing vbuf and virtqueue cleanup path.
Signed-off-by: Pengpeng Hou <pengpeng@iscas.ac.cn>
---
drivers/gpu/drm/virtio/virtgpu_kms.c | 12 ++++++++++--
1 file changed, 10 insertions(+), 2 deletions(-)
diff --git a/drivers/gpu/drm/virtio/virtgpu_kms.c b/drivers/gpu/drm/virtio/virtgpu_kms.c
index cfde9f573df6..31209bea97ae 100644
--- a/drivers/gpu/drm/virtio/virtgpu_kms.c
+++ b/drivers/gpu/drm/virtio/virtgpu_kms.c
@@ -262,11 +262,19 @@ int virtio_gpu_init(struct virtio_device *vdev, struct drm_device *dev)
virtio_gpu_cmd_get_edids(vgdev);
virtio_gpu_cmd_get_display_info(vgdev);
virtio_gpu_notify(vgdev);
- wait_event_timeout(vgdev->resp_wq, !vgdev->display_info_pending,
- 5 * HZ);
+ if (!wait_event_timeout(vgdev->resp_wq,
+ !vgdev->display_info_pending,
+ 5 * HZ)) {
+ DRM_ERROR("timed out waiting for display info\n");
+ ret = -ETIMEDOUT;
+ goto err_ready;
+ }
}
return 0;
+err_ready:
+ virtio_reset_device(vgdev->vdev);
+ virtio_gpu_modeset_fini(vgdev);
err_scanouts:
virtio_gpu_free_vbufs(vgdev);
err_vbufs:
--
2.50.1 (Apple Git-155)
^ permalink raw reply related
* [PATCH v4] virtio_net: disable cb when NAPI is busy-polled
From: Longjun Tang @ 2026-06-25 1:37 UTC (permalink / raw)
To: mst, xuanzhuo
Cc: jasowang, edumazet, virtualization, netdev, tanglongjun,
lange_tang
From: Longjun Tang <tanglongjun@kylinos.cn>
When busy-poll is active, napi_schedule_prep() returns false in
virtqueue_napi_schedule(), so virtqueue_disable_cb() is skipped.
The device may keep firing irqs until reaches virtqueue_napi_complete().
Under load (received == budget), it will lead to a large number
of spurious interrupts.
Fix it by disabling the callback at the virtnet_poll() entry.
This keeps the callback off while we poll and it is re-enabled by
virtqueue_napi_complete() when going idle.
Fixes: ceef438d613f ("virtio_net: remove custom busy_poll")
Acked-by: Michael S. Tsirkin <mst@redhat.com>
Signed-off-by: Longjun Tang <tanglongjun@kylinos.cn>
---
V1 -> V2: Remain agnostic to busy polling
V2 -> V3: Add fixes tag
V3 -> V4: Update commit message and remove some comments
---
drivers/net/virtio_net.c | 2 ++
1 file changed, 2 insertions(+)
diff --git a/drivers/net/virtio_net.c b/drivers/net/virtio_net.c
index f4adcfee7a80..569e4db187d1 100644
--- a/drivers/net/virtio_net.c
+++ b/drivers/net/virtio_net.c
@@ -3008,6 +3008,8 @@ static int virtnet_poll(struct napi_struct *napi, int budget)
unsigned int xdp_xmit = 0;
bool napi_complete;
+ virtqueue_disable_cb(rq->vq);
+
virtnet_poll_cleantx(rq, budget);
received = virtnet_receive(rq, budget, &xdp_xmit);
--
2.43.0
^ permalink raw reply related
* Re:Re: [PATCH v3] virtio_net: disable cb when NAPI is busy-polled
From: Lange Tang @ 2026-06-25 1:28 UTC (permalink / raw)
To: mst@redhat.com
Cc: xuanzhuo@linux.alibaba.com, jasowang@redhat.com,
edumazet@google.com, virtualization@lists.linux.dev,
netdev@vger.kernel.org, Tang Longjun
In-Reply-To: <20260624030656-mutt-send-email-mst@kernel.org>
At 2026-06-24 15:08:24, "Michael S. Tsirkin" <mst@redhat.com> wrote:
>On Wed, Jun 24, 2026 at 03:02:06PM +0800, Longjun Tang wrote:
>> From: Longjun Tang <tanglongjun@kylinos.cn>
>>
>> When busy-poll is active, napi_schedule_prep() returns false in
>> virtqueue_napi_schedule(), so virtqueue_disable_cb() is skipped.
>> The device may keep firing irqs until reaches virtqueue_napi_complete().
>> Under load (received == budget), it will lead to a large number
>> of spurious interrupts.
>>
>> Fix it by disabling the callback at the virtnet_poll() entry. This keeps
>> the callback off while we poll and re-enable
>
>and it is re-enabled
>
>> by virtqueue_napi_complete()
>> when going idle.
>>
>> Fixes: ceef438d613f ("virtio_net: remove custom busy_poll")
>> Acked-by: Michael S. Tsirkin <mst@redhat.com>
>> Signed-off-by: Longjun Tang <tanglongjun@kylinos.cn>
>>
>> ---
>> V1 -> V2: Remain agnostic to busy polling
>> V2 -> V3: Add fixes tag
>> ---
>> drivers/net/virtio_net.c | 5 +++++
>> 1 file changed, 5 insertions(+)
>>
>> diff --git a/drivers/net/virtio_net.c b/drivers/net/virtio_net.c
>> index f4adcfee7a80..0a11f2b32500 100644
>> --- a/drivers/net/virtio_net.c
>> +++ b/drivers/net/virtio_net.c
>> @@ -3008,6 +3008,11 @@ static int virtnet_poll(struct napi_struct *napi, int budget)
>> unsigned int xdp_xmit = 0;
>> bool napi_complete;
>>
>> + /* Keep callbacks suppressed for the duration of this poll,
>> + * busy-poll need.
>
>I don't know what "busy-poll need" means. Just drop this part?
>In fact, the whole comment can go, we know virtqueue_disable_cb
>disables callbacks.
Thanks for your reply. I got it, see you next version.
>
>> + */
>> + virtqueue_disable_cb(rq->vq);
>> +
>> virtnet_poll_cleantx(rq, budget);
>>
>> received = virtnet_receive(rq, budget, &xdp_xmit);
>> --
>> 2.43.0
^ permalink raw reply
* Re: [PATCH v4] vhost/vdpa: reject overflowing PA map page counts on 32-bit
From: Michael S. Tsirkin @ 2026-06-24 22:10 UTC (permalink / raw)
To: Yousef Alhouseen
Cc: Jason Wang, Eugenio Pérez, kvm, virtualization, netdev,
linux-kernel
In-Reply-To: <CAMuQ4bX-iDvcUOPPY+NLz95tkRJYwWqvzAr=U48uNaub_HZLGw@mail.gmail.com>
On Wed, Jun 24, 2026 at 03:02:02PM -0700, Yousef Alhouseen wrote:
> vhost_vdpa_pa_map() adds the IOVA page offset to the user-controlled map
> size before computing the number of pages to pin. On 32-bit systems,
> where unsigned long is narrower than u64, that addition can overflow and
> the code can pin and map fewer pages than the requested IOTLB range.
>
> Reject sizes that overflow the unsigned long page-count calculation.
>
> Fixes: 22af48cf91aa ("vdpa: factor out vhost_vdpa_pa_map() and
> vhost_vdpa_pa_unmap()")
still 2 lines?
> Acked-by: Michael S. Tsirkin <mst@redhat.com>
> Signed-off-by: Yousef Alhouseen <alhouseenyousef@gmail.com>
> ---
> Changes in v4:
> - Keep the Fixes tag on one line.
> - Add Michael's Acked-by tag.
>
> Changes in v3:
> - Add the Fixes tag.
>
> Changes in v2:
> - Clarify that the overflow is on 32-bit systems.
> - Drop the unrelated memlock check change.
>
> drivers/vhost/vdpa.c | 9 ++++++++-
> 1 file changed, 8 insertions(+), 1 deletion(-)
>
> diff --git a/drivers/vhost/vdpa.c b/drivers/vhost/vdpa.c
> index ac55275fa..38b28ed3d 100644
> --- a/drivers/vhost/vdpa.c
> +++ b/drivers/vhost/vdpa.c
> @@ -1102,6 +1102,7 @@ static int vhost_vdpa_pa_map(struct vhost_vdpa *v,
> unsigned int gup_flags = FOLL_LONGTERM;
> unsigned long npages, cur_base, map_pfn, last_pfn = 0;
> unsigned long lock_limit, sz2pin, nchunks, i;
> + unsigned long page_offset;
> u64 start = iova;
> long pinned;
> int ret = 0;
> @@ -1114,7 +1115,13 @@ static int vhost_vdpa_pa_map(struct vhost_vdpa *v,
> if (perm & VHOST_ACCESS_WO)
> gup_flags |= FOLL_WRITE;
>
> - npages = PFN_UP(size + (iova & ~PAGE_MASK));
> + page_offset = iova & ~PAGE_MASK;
> + if (size > ULONG_MAX - page_offset) {
> + ret = -EINVAL;
> + goto free;
> + }
> +
> + npages = PFN_UP(size + page_offset);
> if (!npages) {
> ret = -EINVAL;
> goto free;
> --
> 2.54.0
^ permalink raw reply
* [PATCH v4] vhost/vdpa: reject overflowing PA map page counts on 32-bit
From: Yousef Alhouseen @ 2026-06-24 22:02 UTC (permalink / raw)
To: Michael S. Tsirkin, Jason Wang, Eugenio Pérez
Cc: kvm, virtualization, netdev, linux-kernel, Yousef Alhouseen
vhost_vdpa_pa_map() adds the IOVA page offset to the user-controlled map
size before computing the number of pages to pin. On 32-bit systems,
where unsigned long is narrower than u64, that addition can overflow and
the code can pin and map fewer pages than the requested IOTLB range.
Reject sizes that overflow the unsigned long page-count calculation.
Fixes: 22af48cf91aa ("vdpa: factor out vhost_vdpa_pa_map() and
vhost_vdpa_pa_unmap()")
Acked-by: Michael S. Tsirkin <mst@redhat.com>
Signed-off-by: Yousef Alhouseen <alhouseenyousef@gmail.com>
---
Changes in v4:
- Keep the Fixes tag on one line.
- Add Michael's Acked-by tag.
Changes in v3:
- Add the Fixes tag.
Changes in v2:
- Clarify that the overflow is on 32-bit systems.
- Drop the unrelated memlock check change.
drivers/vhost/vdpa.c | 9 ++++++++-
1 file changed, 8 insertions(+), 1 deletion(-)
diff --git a/drivers/vhost/vdpa.c b/drivers/vhost/vdpa.c
index ac55275fa..38b28ed3d 100644
--- a/drivers/vhost/vdpa.c
+++ b/drivers/vhost/vdpa.c
@@ -1102,6 +1102,7 @@ static int vhost_vdpa_pa_map(struct vhost_vdpa *v,
unsigned int gup_flags = FOLL_LONGTERM;
unsigned long npages, cur_base, map_pfn, last_pfn = 0;
unsigned long lock_limit, sz2pin, nchunks, i;
+ unsigned long page_offset;
u64 start = iova;
long pinned;
int ret = 0;
@@ -1114,7 +1115,13 @@ static int vhost_vdpa_pa_map(struct vhost_vdpa *v,
if (perm & VHOST_ACCESS_WO)
gup_flags |= FOLL_WRITE;
- npages = PFN_UP(size + (iova & ~PAGE_MASK));
+ page_offset = iova & ~PAGE_MASK;
+ if (size > ULONG_MAX - page_offset) {
+ ret = -EINVAL;
+ goto free;
+ }
+
+ npages = PFN_UP(size + page_offset);
if (!npages) {
ret = -EINVAL;
goto free;
--
2.54.0
^ permalink raw reply related
* Re: [PATCH v3] vhost/vdpa: reject overflowing PA map page counts on 32-bit
From: Michael S. Tsirkin @ 2026-06-24 21:59 UTC (permalink / raw)
To: Yousef Alhouseen
Cc: Jason Wang, Eugenio Pérez, kvm, virtualization, netdev,
linux-kernel
In-Reply-To: <CAMuQ4bV8OeSTOVnAPRh6ygKdogFjqEiDNj1Vbh623KBBkZgxiw@mail.gmail.com>
On Wed, Jun 24, 2026 at 02:56:20PM -0700, Yousef Alhouseen wrote:
> vhost_vdpa_pa_map() adds the IOVA page offset to the user-controlled map
> size before computing the number of pages to pin. On 32-bit systems,
> where unsigned long is narrower than u64, that addition can overflow and
> the code can pin and map fewer pages than the requested IOTLB range.
>
> Reject sizes that overflow the unsigned long page-count calculation.
>
> Fixes: 22af48cf91aa ("vdpa: factor out vhost_vdpa_pa_map() and
> vhost_vdpa_pa_unmap()")
weirdly wrapped. will likely break some tools.
> Signed-off-by: Yousef Alhouseen <alhouseenyousef@gmail.com>
Acked-by: Michael S. Tsirkin <mst@redhat.com>
> ---
> Changes in v3:
> - Add the Fixes tag.
>
> Changes in v2:
> - Clarify that the overflow is on 32-bit systems.
> - Drop the unrelated memlock check change.
>
> drivers/vhost/vdpa.c | 9 ++++++++-
> 1 file changed, 8 insertions(+), 1 deletion(-)
>
> diff --git a/drivers/vhost/vdpa.c b/drivers/vhost/vdpa.c
> index ac55275fa..38b28ed3d 100644
> --- a/drivers/vhost/vdpa.c
> +++ b/drivers/vhost/vdpa.c
> @@ -1102,6 +1102,7 @@ static int vhost_vdpa_pa_map(struct vhost_vdpa *v,
> unsigned int gup_flags = FOLL_LONGTERM;
> unsigned long npages, cur_base, map_pfn, last_pfn = 0;
> unsigned long lock_limit, sz2pin, nchunks, i;
> + unsigned long page_offset;
> u64 start = iova;
> long pinned;
> int ret = 0;
> @@ -1114,7 +1115,13 @@ static int vhost_vdpa_pa_map(struct vhost_vdpa *v,
> if (perm & VHOST_ACCESS_WO)
> gup_flags |= FOLL_WRITE;
>
> - npages = PFN_UP(size + (iova & ~PAGE_MASK));
> + page_offset = iova & ~PAGE_MASK;
> + if (size > ULONG_MAX - page_offset) {
> + ret = -EINVAL;
> + goto free;
> + }
> +
> + npages = PFN_UP(size + page_offset);
> if (!npages) {
> ret = -EINVAL;
> goto free;
> --
> 2.54.0
^ permalink raw reply
* [PATCH v3] vhost/vdpa: reject overflowing PA map page counts on 32-bit
From: Yousef Alhouseen @ 2026-06-24 21:56 UTC (permalink / raw)
To: Michael S. Tsirkin, Jason Wang, Eugenio Pérez
Cc: kvm, virtualization, netdev, linux-kernel, Yousef Alhouseen
vhost_vdpa_pa_map() adds the IOVA page offset to the user-controlled map
size before computing the number of pages to pin. On 32-bit systems,
where unsigned long is narrower than u64, that addition can overflow and
the code can pin and map fewer pages than the requested IOTLB range.
Reject sizes that overflow the unsigned long page-count calculation.
Fixes: 22af48cf91aa ("vdpa: factor out vhost_vdpa_pa_map() and
vhost_vdpa_pa_unmap()")
Signed-off-by: Yousef Alhouseen <alhouseenyousef@gmail.com>
---
Changes in v3:
- Add the Fixes tag.
Changes in v2:
- Clarify that the overflow is on 32-bit systems.
- Drop the unrelated memlock check change.
drivers/vhost/vdpa.c | 9 ++++++++-
1 file changed, 8 insertions(+), 1 deletion(-)
diff --git a/drivers/vhost/vdpa.c b/drivers/vhost/vdpa.c
index ac55275fa..38b28ed3d 100644
--- a/drivers/vhost/vdpa.c
+++ b/drivers/vhost/vdpa.c
@@ -1102,6 +1102,7 @@ static int vhost_vdpa_pa_map(struct vhost_vdpa *v,
unsigned int gup_flags = FOLL_LONGTERM;
unsigned long npages, cur_base, map_pfn, last_pfn = 0;
unsigned long lock_limit, sz2pin, nchunks, i;
+ unsigned long page_offset;
u64 start = iova;
long pinned;
int ret = 0;
@@ -1114,7 +1115,13 @@ static int vhost_vdpa_pa_map(struct vhost_vdpa *v,
if (perm & VHOST_ACCESS_WO)
gup_flags |= FOLL_WRITE;
- npages = PFN_UP(size + (iova & ~PAGE_MASK));
+ page_offset = iova & ~PAGE_MASK;
+ if (size > ULONG_MAX - page_offset) {
+ ret = -EINVAL;
+ goto free;
+ }
+
+ npages = PFN_UP(size + page_offset);
if (!npages) {
ret = -EINVAL;
goto free;
--
2.54.0
^ permalink raw reply related
* Re: [PATCH v2] vhost/vdpa: reject overflowing PA map page counts on 32-bit
From: Michael S. Tsirkin @ 2026-06-24 21:54 UTC (permalink / raw)
To: Yousef Alhouseen
Cc: Jason Wang, Eugenio Pérez, kvm, virtualization, netdev,
linux-kernel
In-Reply-To: <CAMuQ4bURwyoJtKUskzXpbUtrxXT1vBZZxpKpnnJY6qWsLtTBMA@mail.gmail.com>
On Wed, Jun 24, 2026 at 02:51:53PM -0700, Yousef Alhouseen wrote:
> vhost_vdpa_pa_map() adds the IOVA page offset to the user-controlled map
> size before computing the number of pages to pin. On 32-bit systems,
> where unsigned long is narrower than u64, that addition can overflow and
> the code can pin and map fewer pages than the requested IOTLB range.
>
> Reject sizes that overflow the unsigned long page-count calculation.
>
And a Fixes: tag, please.
> Signed-off-by: Yousef Alhouseen <alhouseenyousef@gmail.com>
> ---
> Changes in v2:
> - Clarify that the overflow is on 32-bit systems.
> - Drop the unrelated memlock check change.
>
> drivers/vhost/vdpa.c | 9 ++++++++-
> 1 file changed, 8 insertions(+), 1 deletion(-)
>
> diff --git a/drivers/vhost/vdpa.c b/drivers/vhost/vdpa.c
> index ac55275fa..38b28ed3d 100644
> --- a/drivers/vhost/vdpa.c
> +++ b/drivers/vhost/vdpa.c
> @@ -1102,6 +1102,7 @@ static int vhost_vdpa_pa_map(struct vhost_vdpa *v,
> unsigned int gup_flags = FOLL_LONGTERM;
> unsigned long npages, cur_base, map_pfn, last_pfn = 0;
> unsigned long lock_limit, sz2pin, nchunks, i;
> + unsigned long page_offset;
> u64 start = iova;
> long pinned;
> int ret = 0;
> @@ -1114,7 +1115,13 @@ static int vhost_vdpa_pa_map(struct vhost_vdpa *v,
> if (perm & VHOST_ACCESS_WO)
> gup_flags |= FOLL_WRITE;
>
> - npages = PFN_UP(size + (iova & ~PAGE_MASK));
> + page_offset = iova & ~PAGE_MASK;
> + if (size > ULONG_MAX - page_offset) {
> + ret = -EINVAL;
> + goto free;
> + }
> +
> + npages = PFN_UP(size + page_offset);
> if (!npages) {
> ret = -EINVAL;
> goto free;
> --
> 2.54.0
^ permalink raw reply
* [PATCH v2] vhost/vdpa: reject overflowing PA map page counts on 32-bit
From: Yousef Alhouseen @ 2026-06-24 21:51 UTC (permalink / raw)
To: Michael S. Tsirkin, Jason Wang, Eugenio Pérez
Cc: kvm, virtualization, netdev, linux-kernel, Yousef Alhouseen
vhost_vdpa_pa_map() adds the IOVA page offset to the user-controlled map
size before computing the number of pages to pin. On 32-bit systems,
where unsigned long is narrower than u64, that addition can overflow and
the code can pin and map fewer pages than the requested IOTLB range.
Reject sizes that overflow the unsigned long page-count calculation.
Signed-off-by: Yousef Alhouseen <alhouseenyousef@gmail.com>
---
Changes in v2:
- Clarify that the overflow is on 32-bit systems.
- Drop the unrelated memlock check change.
drivers/vhost/vdpa.c | 9 ++++++++-
1 file changed, 8 insertions(+), 1 deletion(-)
diff --git a/drivers/vhost/vdpa.c b/drivers/vhost/vdpa.c
index ac55275fa..38b28ed3d 100644
--- a/drivers/vhost/vdpa.c
+++ b/drivers/vhost/vdpa.c
@@ -1102,6 +1102,7 @@ static int vhost_vdpa_pa_map(struct vhost_vdpa *v,
unsigned int gup_flags = FOLL_LONGTERM;
unsigned long npages, cur_base, map_pfn, last_pfn = 0;
unsigned long lock_limit, sz2pin, nchunks, i;
+ unsigned long page_offset;
u64 start = iova;
long pinned;
int ret = 0;
@@ -1114,7 +1115,13 @@ static int vhost_vdpa_pa_map(struct vhost_vdpa *v,
if (perm & VHOST_ACCESS_WO)
gup_flags |= FOLL_WRITE;
- npages = PFN_UP(size + (iova & ~PAGE_MASK));
+ page_offset = iova & ~PAGE_MASK;
+ if (size > ULONG_MAX - page_offset) {
+ ret = -EINVAL;
+ goto free;
+ }
+
+ npages = PFN_UP(size + page_offset);
if (!npages) {
ret = -EINVAL;
goto free;
--
2.54.0
^ permalink raw reply related
* Re: [PATCH] vhost/vdpa: reject overflowing PA map page counts
From: Yousef Alhouseen @ 2026-06-24 21:47 UTC (permalink / raw)
To: Michael S. Tsirkin
Cc: Jason Wang, Eugenio Pérez, kvm, virtualization, netdev,
linux-kernel
In-Reply-To: <20260624153850-mutt-send-email-mst@kernel.org>
On Wed, Jun 24, 2026 at 01:53:38PM -0400, Michael S. Tsirkin wrote:
> You should add "on 32 bit systems" - I do not see how it can
> overflow on 64 bit.
Right, the overflow I was trying to cover is the unsigned long
page-count calculation on 32-bit systems, where size can be wider than
unsigned long and the page offset is added before PFN_UP(). I should
have made that scope explicit in the changelog.
> I don't see how this can happen at all - pinned_vm is in units of pages.
Agreed, that part is not needed for this fix. I'll drop the memlock
check change and send a v2 with the changelog clarified to say this is
for 32-bit systems.
Thanks,
Yousef
On Wed, 24 Jun 2026 15:53:38 -0400, "Michael S. Tsirkin" <mst@redhat.com> wrote:
> On Wed, Jun 24, 2026 at 09:06:53PM +0200, Yousef Alhouseen wrote:
> > vhost_vdpa_pa_map() adds the IOVA page offset to the user-controlled map
> > size before computing the number of pages to pin. If that addition wraps,
> > the code can pin and map fewer pages than the requested IOTLB range.
> >
> > Reject sizes that overflow the page-count calculation.
>
> You should add "on 32 bit systems" - I do not see how it can
> overflow on 64 bit.
>
> > Also make the
> > memlock check subtraction-based so a large page count cannot wrap the
> > pinned page total.
>
> I don't see how this can happen at all - pinned_vm is in units of pages.
>
> > Signed-off-by: Yousef Alhouseen <alhouseenyousef@gmail.com>
> > ---
> > drivers/vhost/vdpa.c | 12 ++++++++++--
> > 1 file changed, 10 insertions(+), 2 deletions(-)
> >
> > diff --git a/drivers/vhost/vdpa.c b/drivers/vhost/vdpa.c
> > index ac55275fa..090cb8693 100644
> > --- a/drivers/vhost/vdpa.c
> > +++ b/drivers/vhost/vdpa.c
> > @@ -1102,6 +1102,8 @@ static int vhost_vdpa_pa_map(struct vhost_vdpa *v,
> > unsigned int gup_flags = FOLL_LONGTERM;
> > unsigned long npages, cur_base, map_pfn, last_pfn = 0;
> > unsigned long lock_limit, sz2pin, nchunks, i;
> > + unsigned long page_offset;
> > + u64 pinned_vm;
> > u64 start = iova;
> > long pinned;
> > int ret = 0;
> > @@ -1114,7 +1116,12 @@ static int vhost_vdpa_pa_map(struct vhost_vdpa *v,
> > if (perm & VHOST_ACCESS_WO)
> > gup_flags |= FOLL_WRITE;
> >
> > - npages = PFN_UP(size + (iova & ~PAGE_MASK));
> > + page_offset = iova & ~PAGE_MASK;
> > + if (size > ULONG_MAX - page_offset) {
> > + ret = -EINVAL;
> > + goto free;
> > + }
> > + npages = PFN_UP(size + page_offset);
> > if (!npages) {
> > ret = -EINVAL;
> > goto free;
> > @@ -1123,7 +1130,8 @@ static int vhost_vdpa_pa_map(struct vhost_vdpa *v,
> > mmap_read_lock(dev->mm);
> >
> > lock_limit = PFN_DOWN(rlimit(RLIMIT_MEMLOCK));
> > - if (npages + atomic64_read(&dev->mm->pinned_vm) > lock_limit) {
> > + pinned_vm = atomic64_read(&dev->mm->pinned_vm);
> > + if (npages > lock_limit || pinned_vm > lock_limit - npages) {
> > ret = -ENOMEM;
> > goto unlock;
> > }
> > --
> > 2.54.0
^ permalink raw reply
* [syzbot] Monthly virt report (Jun 2026)
From: syzbot @ 2026-06-24 20:32 UTC (permalink / raw)
To: linux-kernel, syzkaller-bugs, virtualization
Hello virt maintainers/developers,
This is a 31-day syzbot report for the virt subsystem.
All related reports/information can be found at:
https://syzkaller.appspot.com/upstream/s/virt
During the period, 0 new issues were detected and 0 were fixed.
In total, 5 issues are still open and 61 have already been fixed.
There are also 2 low-priority issues.
Some of the still happening issues:
Ref Crashes Repro Title
<1> 24 No WARNING: refcount bug in call_timer_fn (4)
https://syzkaller.appspot.com/bug?extid=07dcf509f4c013e25dc5
<2> 3 Yes memory leak in __vsock_create (2)
https://syzkaller.appspot.com/bug?extid=1b2c9c4a0f8708082678
<3> 3913 Yes INFO: rcu detected stall in do_idle
https://syzkaller.appspot.com/bug?extid=385468161961cee80c31
---
This report is generated by a bot. It may contain errors.
See https://goo.gl/tpsmEJ for more information about syzbot.
syzbot engineers can be reached at syzkaller@googlegroups.com.
To disable reminders for individual bugs, reply with the following command:
#syz set <Ref> no-reminders
To change bug's subsystems, reply with:
#syz set <Ref> subsystems: new-subsystem
You may send multiple commands in a single email message.
^ 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