Linux virtualization list
 help / color / mirror / Atom feed
* Re: [PATCH 1/2] vfio/pci: Set up barmap in vfio_pci_core_enable()
From: Matt Evans @ 2026-04-23 14:18 UTC (permalink / raw)
  To: Alex Williamson
  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
In-Reply-To: <20260421133123.36fc0353@shazbot.org>

Hi Alex,

On 21/04/2026 20:31, Alex Williamson wrote:
> 
> On Tue, 21 Apr 2026 10:41:40 -0700
> Matt Evans <mattev@meta.com> wrote:
> 
>> The previous lazy-setup of the barmaps provided opportunities to
>> forget to do it (for example, DMABUF export).  Since all users will
>> ultimately require BAR resources to have been requested, request them
>> in vfio_pci_core_enable.
>>
>> Existing calls to vfio_pci_core_setup_barmap() are now benign, but
>> remain because some callers use it to validate a BAR index.  This
>> fixes at least the case where DMABUF export could succeed before
>> resources were requested.
>>
>> This keeps resource request and ioremap() done at the same time, but
>> in future the ioremap() could be done on-demand (not all VFIO users
>> need it).
>>
>> Fixes: 7f5764e179c6 ("vfio: use vfio_pci_core_setup_barmap to map bar in mmap")
>> Fixes: 0d77ed3589ac0 ("vfio/pci: Pull BAR mapping setup from read-write path")
>> Signed-off-by: Matt Evans <mattev@meta.com>
>> ---
>>   drivers/vfio/pci/vfio_pci_core.c | 63 +++++++++++++++++++++++++++-----
>>   drivers/vfio/pci/vfio_pci_rdwr.c | 25 +++----------
>>   2 files changed, 60 insertions(+), 28 deletions(-)
>>
>> diff --git a/drivers/vfio/pci/vfio_pci_core.c b/drivers/vfio/pci/vfio_pci_core.c
>> index 3f8d093aacf8..4a314213f3ae 100644
>> --- a/drivers/vfio/pci/vfio_pci_core.c
>> +++ b/drivers/vfio/pci/vfio_pci_core.c
>> @@ -482,6 +482,55 @@ static int vfio_pci_core_runtime_resume(struct device *dev)
>>   }
>>   #endif /* CONFIG_PM */
>>   
>> +static void __vfio_pci_core_unmap_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;
>> +
>> +		if (!vdev->barmap[i])
>> +			continue;
>> +		pci_iounmap(pdev, vdev->barmap[bar]);
>> +		pci_release_selected_regions(pdev, 1 << bar);
>> +		vdev->barmap[bar] = NULL;
>> +	}
>> +}
>> +
>> +static int __vfio_pci_core_map_bars(struct vfio_pci_core_device *vdev)
>> +{
>> +	struct pci_dev *pdev = vdev->pdev;
>> +	int ret = 0;
>> +	int i;
>> +
>> +	/* Eager-request BAR resources (and iomap) */
>> +	for (i = 0; i < PCI_STD_NUM_BARS; i++) {
>> +		int bar = i + PCI_STD_RESOURCES;
>> +		void __iomem *io;
>> +
>> +		if (pci_resource_len(pdev, i) == 0)
>> +			continue;
>> +
>> +		ret = pci_request_selected_regions(pdev, 1 << bar, "vfio");
>> +		if (ret)
>> +			goto err_free_barmap;
>> +
>> +		io = pci_iomap(pdev, bar, 0);
>> +		if (!io) {
>> +			pci_release_selected_regions(pdev, 1 << bar);
>> +			ret = -ENOMEM;
>> +			goto err_free_barmap;
>> +		}
>> +		vdev->barmap[bar] = io;
>> +	}
>> +	return 0;
>> +
>> +err_free_barmap:
>> +	__vfio_pci_core_unmap_bars(vdev);
>> +	return ret;
>> +}
>> +
>>   /*
>>    * 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 +617,9 @@ int vfio_pci_core_enable(struct vfio_pci_core_device *vdev)
>>   	if (!vfio_vga_disabled() && vfio_pci_is_vga(pdev))
>>   		vdev->has_vga = true;
>>   
>> +	ret = __vfio_pci_core_map_bars(vdev);
>> +	if (ret)
>> +		goto out_free_zdev;
> 
> Beyond simply changing to a preemptive mapping scheme, this hard
> failure makes me concerned about regressing userspace.  With the
> current lazy scheme, we only claim the BAR if the user accesses it and
> the failure only occurs in the access path.  That means we could have
> BARs that are never mapped.  With a hard failure here, with might be
> uncovering some latent issues, and if those latent issues are with BARs
> that we never cared to map previously, we're causing trouble for no
> gain.

Thanks.  Hm, so for example a valid non-zero-sized BAR but the 
pci_iomap() hitting ENOMEM.  Good point, that could be annoying if the 
BAR was otherwise unused.

> I'd suggest setup should be a void function that generates pci_warn()
> on conflict or iomap error, but doesn't block the device.  Each usage
> path (including mmap that gets removed in the next path) still needs to
> validate the mapping is present for the given BAR and fail the call
> path otherwise.

I'd hoped to be able to assume resources have been successfully 
requested, since we've at least one example of forgetting to do it 
explicitly (DMABUF export), but no worries.  I'll re-add explicit checks 
to usage paths (incl. for DMABUF export) to make failures consistent 
with current behaviour.

> There's also a subtle range check added in the virtio driver in the
> next patch, is that fixing a bug or paranoia?  Do we need a helper that
> does a range test and barmap test?  Thanks,

That'll be nicer, I agree.  Given the point above, two tiny helpers make 
sense for the two "uses":

- Was resource X requested successfully?   (For DMABUF, mmap, etc.)
- Get X's iomapped base address.  (For rdwr, virtio, nvgpu-grace.)

(The motivation for the range check was just robustness, not a specific 
bug.  It's cheap to sanity-check and Pretty Bad if the index is ever out 
of range.)

Reposting... Thanks,


Matt


^ permalink raw reply

* Re: [PATCH RFC v3 01/19] mm: thread user_addr through page allocator for cache-friendly zeroing
From: David Hildenbrand (Arm) @ 2026-04-23 14:13 UTC (permalink / raw)
  To: Gregory Price, Michael S. Tsirkin
  Cc: linux-kernel, Andrew Morton, Vlastimil Babka, Brendan Jackman,
	Michal Hocko, Suren Baghdasaryan, Jason Wang, Andrea Arcangeli,
	linux-mm, virtualization, Johannes Weiner, Zi Yan,
	Lorenzo Stoakes, Liam R. Howlett, Mike Rapoport,
	Matthew Wilcox (Oracle), Muchun Song, Oscar Salvador, Baolin Wang,
	Nico Pache, Ryan Roberts, Dev Jain, Barry Song, Lance Yang,
	Matthew Brost, Joshua Hahn, Rakie Kim, Byungchul Park, Ying Huang,
	Alistair Popple, Hugh Dickins, Christoph Lameter, David Rientjes,
	Roman Gushchin, Harry Yoo, Chris Li, Kairui Song, Kemeng Shi,
	Nhat Pham, Baoquan He, linux-fsdevel
In-Reply-To: <aeohzbmhQAoOODPm@gourry-fedora-PF4VCD3F>

On 4/23/26 15:42, Gregory Price wrote:
> On Thu, Apr 23, 2026 at 07:57:01AM -0400, Michael S. Tsirkin wrote:
>> On Thu, Apr 23, 2026 at 11:46:56AM +0200, David Hildenbrand (Arm) wrote:
>>
>> Changes we have to add: 8 changes
>> Rename 4 existing APIs adding _user: __alloc_pages,
>> __folio_alloc, folio_alloc_mpol, __alloc_frozen_pages + add
>> 4 wrapper macros/inlines in gfp.h that forward to the _user variants with
>> USER_ADDR_NONE. Roughly 6-8 lines of boilerplate per API.
>>
> 
> This is essentially what i was proposing.
> 
> The result would be more external surface to the buddy (at least 2 maybe
> more functions, plus all the _noprof stuff and a bunch of other things).

We probably wouldn't need prof stuff if all we care about is vma_alloc_folio()
that will only be calling _noprof internally.

> 
> And then all the callers have to be updated anywhere, and not make it
> any harder to mess up.  You either have
> 
>     old_interface(..., user_addr);
>     /* Churn everything using the old interface */
> 
> or
> 
>     __internal(..., user_addr) { }
> 
>     old_interface(...) {
>        __internal(..., NO_USER_ADDR);
>     }
> 
>     new_interface(..., user_addr) {
>        __internal(..., user_addr);
>     }
> 
>     /* 
>      * Update some callsites to use new_interface()
>      * mostly a bunch of _mpol() functions but some others
>      */
> 
> but someone could still just as easily do
> 
>     old_interface();
>     /* don't fall folio_zero_user() - Bug! */
> 
> So it's not like this makes things any harder to mess up.

Right.

Looking at the patch, there would already be less churn if

folio_alloc_mpol()
__alloc_frozen_pages_noprof()
__alloc_pages()
post_alloc_hook()

Would have simple wrappers.

hugetlb calls  __alloc_frozen_pages(). That's rather nasty, given that
it wants to allocate a frozen folio.

alloc_hugetlb_folio() already consumes vma+addr.
alloc_buddy_hugetlb_folio_with_mpol() already consumes vma+addr.

Maybe we could forward the vma+addr here and call a vma_alloc_froze_folio() if
we have a VMA+addr to have a clean interface.

But really, that hugetlb code is rather messy. I'd vote for leaving hugetlb
alone on a v1, and focusing on non-hugetlb first.

-- 
Cheers,

David

^ permalink raw reply

* Re: [PATCH RFC v3 01/19] mm: thread user_addr through page allocator for cache-friendly zeroing
From: Gregory Price @ 2026-04-23 13:42 UTC (permalink / raw)
  To: Michael S. Tsirkin
  Cc: David Hildenbrand (Arm), linux-kernel, Andrew Morton,
	Vlastimil Babka, Brendan Jackman, Michal Hocko,
	Suren Baghdasaryan, Jason Wang, Andrea Arcangeli, linux-mm,
	virtualization, Johannes Weiner, Zi Yan, Lorenzo Stoakes,
	Liam R. Howlett, Mike Rapoport, Matthew Wilcox (Oracle),
	Muchun Song, Oscar Salvador, Baolin Wang, Nico Pache,
	Ryan Roberts, Dev Jain, Barry Song, Lance Yang, Matthew Brost,
	Joshua Hahn, Rakie Kim, Byungchul Park, Ying Huang,
	Alistair Popple, Hugh Dickins, Christoph Lameter, David Rientjes,
	Roman Gushchin, Harry Yoo, Chris Li, Kairui Song, Kemeng Shi,
	Nhat Pham, Baoquan He, linux-fsdevel
In-Reply-To: <20260423074433-mutt-send-email-mst@kernel.org>

On Thu, Apr 23, 2026 at 07:57:01AM -0400, Michael S. Tsirkin wrote:
> On Thu, Apr 23, 2026 at 11:46:56AM +0200, David Hildenbrand (Arm) wrote:
> > On 4/23/26 06:31, Gregory Price wrote:
> 
> Changes we have to add: 8 changes
> Rename 4 existing APIs adding _user: __alloc_pages,
> __folio_alloc, folio_alloc_mpol, __alloc_frozen_pages + add
> 4 wrapper macros/inlines in gfp.h that forward to the _user variants with
> USER_ADDR_NONE. Roughly 6-8 lines of boilerplate per API.
>

This is essentially what i was proposing.

The result would be more external surface to the buddy (at least 2 maybe
more functions, plus all the _noprof stuff and a bunch of other things).

And then all the callers have to be updated anywhere, and not make it
any harder to mess up.  You either have

    old_interface(..., user_addr);
    /* Churn everything using the old interface */

or

    __internal(..., user_addr) { }

    old_interface(...) {
       __internal(..., NO_USER_ADDR);
    }

    new_interface(..., user_addr) {
       __internal(..., user_addr);
    }

    /* 
     * Update some callsites to use new_interface()
     * mostly a bunch of _mpol() functions but some others
     */

but someone could still just as easily do

    old_interface();
    /* don't fall folio_zero_user() - Bug! */

So it's not like this makes things any harder to mess up.

There is no elegant fix here if we want to do this all inside the buddy.

If the performance increase weren't so blatantly dramatic we could also
consider just not doing this at all.

There's maybe an alternative here in considering a change to the way the
buddy manages zeroed pages - but there's no guarantees we find a pattern
there either.

~Gregory

^ permalink raw reply

* [syzbot] Monthly virt report (Apr 2026)
From: syzbot @ 2026-04-23 12:44 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, 2 new issues were detected and 0 were fixed.
In total, 8 issues are still open and 60 have already been fixed.

Some of the still happening issues:

Ref Crashes Repro Title
<1> 3810    Yes   INFO: rcu detected stall in do_idle
                  https://syzkaller.appspot.com/bug?extid=385468161961cee80c31
<2> 701     Yes   INFO: rcu detected stall in addrconf_rs_timer (6)
                  https://syzkaller.appspot.com/bug?extid=fecf8bd19c1f78edb255
<3> 337     Yes   INFO: task hung in __vhost_worker_flush
                  https://syzkaller.appspot.com/bug?extid=7f3bbe59e8dd2328a990
<4> 102     No    KCSAN: data-race in virtqueue_disable_cb / virtqueue_disable_cb (5)
                  https://syzkaller.appspot.com/bug?extid=9d46c74b27b961b244a9
<5> 2       Yes   WARNING in virtio_transport_send_pkt_info (2)
                  https://syzkaller.appspot.com/bug?extid=28e5f3d207b14bae122a

---
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

* Re: [PATCH RFC v3 01/19] mm: thread user_addr through page allocator for cache-friendly zeroing
From: Michael S. Tsirkin @ 2026-04-23 11:57 UTC (permalink / raw)
  To: David Hildenbrand (Arm)
  Cc: Gregory Price, linux-kernel, Andrew Morton, Vlastimil Babka,
	Brendan Jackman, Michal Hocko, Suren Baghdasaryan, Jason Wang,
	Andrea Arcangeli, linux-mm, virtualization, Johannes Weiner,
	Zi Yan, Lorenzo Stoakes, Liam R. Howlett, Mike Rapoport,
	Matthew Wilcox (Oracle), Muchun Song, Oscar Salvador, Baolin Wang,
	Nico Pache, Ryan Roberts, Dev Jain, Barry Song, Lance Yang,
	Matthew Brost, Joshua Hahn, Rakie Kim, Byungchul Park, Ying Huang,
	Alistair Popple, Hugh Dickins, Christoph Lameter, David Rientjes,
	Roman Gushchin, Harry Yoo, Chris Li, Kairui Song, Kemeng Shi,
	Nhat Pham, Baoquan He, linux-fsdevel
In-Reply-To: <c165d6af-4a35-4a41-9086-ee307640c044@kernel.org>

On Thu, Apr 23, 2026 at 11:46:56AM +0200, David Hildenbrand (Arm) wrote:
> On 4/23/26 06:31, Gregory Price wrote:
> > On Wed, Apr 22, 2026 at 05:20:27PM -0400, Michael S. Tsirkin wrote:
> >> On Wed, Apr 22, 2026 at 03:47:07PM -0400, Gregory Price wrote:
> >>>
> >>> __alloc_user_pages(..., gfp_t gfp, user_addr)
> >>
> >> With a wrapper approach, looks like we'd need something like
> >> __GFP_SKIP_ZERO so post_alloc_hook doesn't zero sequentially, then the
> >> wrapper re-zeros with folio_zero_user().  But then the wrapper needs to
> >> know whether the page was pre-zeroed (PG_zeroed), which is cleared by
> >> post_alloc_hook before return.  So the information doesn't survive to
> >> the wrapper.
> >>
> > 
> > I was thinking more that internally you already have that information
> > you need to know to skip the zeroing - and so the wrapper can just pass
> > __GFP_ZERO and post_alloc_hook() would do the right thing regardless
> > 
> > Then on the way out, the new wrapper would take care of cacheline piece.
> > 
> > However, i explored this a bit - and while it saves some churn on the
> > interface, it adds two paths into the buddy - and that increase in
> > surface might not be worth it.
> > 
> > So I see the tradeoff here.  The churn is probably worth it.
> 
> In v2 I commented [1]
> 
> "
> For example, instead of changing all callers of post_alloc_hook() to
> pass USER_ADDR_NONE, can we make post_alloc_hook() a simple wrapper
> around a variant that consumes an address.
> 
> So isn't there a way we can just keep the changes mostly to mm/page_alloc.c?
> "
> 
> That should avoid most of the churn outside of page_alloc, no?
> 
> [1] https://lore.kernel.org/r/4bdc66f2-1469-4b91-9935-74c3d3ca0ed9@kernel.org
> 
> -- 
> Cheers,
> 
> David

Yes I'm sorry I missed that one and didn't answer it. My bad.

To answer the question, no, definitely not *most*. Here are some numbers:

What we save: 11 one-line changes adding , USER_ADDR_NONE in callers
that don't care about user_addr (compaction, filemap, khugepaged,
migrate, page_frag_cache, shmem, slub, swap_state).

Changes we have to add: 8 changes
Rename 4 existing APIs adding _user: __alloc_pages,
__folio_alloc, folio_alloc_mpol, __alloc_frozen_pages + add
4 wrapper macros/inlines in gfp.h that forward to the _user variants with
USER_ADDR_NONE. Roughly 6-8 lines of boilerplate per API.

 
What stays the same, but now has to call the new APIs:

all internal plumbing (page_alloc.c, mempolicy.c, internal.h, hugetlb.c,
the actual user-page callers in memory.c/huge_memory.c/highmem.h):
38 calls, of these 21 in page_alloc.c, 17 outside it.


The changes would be less trivial to review, too. And I would not call
the resulting very long names "elegant".

More importantly, it makes it harder to review: instead of
compiler checking we did not forget a parameter, it compiles fine,
but we get a subtle slowdown or corruption on non x86.

And I thought you agreed with this sentiment when you said
"yea something that is harder to mess up would be nice":
https://lore.kernel.org/all/20260414062524-mutt-send-email-mst@kernel.org/




From where I stand, we would adding technical debt by piling up new
wrapper APIs, for no benefit.

But then, I'm not the maintainer here. And adding extra wrappers
is easy for me. So, let me know. Thanks!


-- 
MST


^ permalink raw reply

* Re: [PATCH net] vsock/virtio: fix MSG_ZEROCOPY pinned-pages accounting
From: patchwork-bot+netdevbpf @ 2026-04-23 11:10 UTC (permalink / raw)
  To: Stefano Garzarella
  Cc: netdev, edumazet, horms, kvm, avkrasnov, davem, pabeni, kuba, mst,
	jasowang, virtualization, linux-kernel, eperezma, xuanzhuo,
	stefanha, yimingqian591
In-Reply-To: <20260420132051.217589-1-sgarzare@redhat.com>

Hello:

This patch was applied to netdev/net.git (main)
by Paolo Abeni <pabeni@redhat.com>:

On Mon, 20 Apr 2026 15:20:51 +0200 you wrote:
> From: Stefano Garzarella <sgarzare@redhat.com>
> 
> virtio_transport_init_zcopy_skb() uses iter->count as the size argument
> for msg_zerocopy_realloc(), which in turn passes it to
> mm_account_pinned_pages() for RLIMIT_MEMLOCK accounting. However, this
> function is called after virtio_transport_fill_skb() has already consumed
> the iterator via __zerocopy_sg_from_iter(), so on the last skb, iter->count
> will be 0, skipping the RLIMIT_MEMLOCK enforcement.
> 
> [...]

Here is the summary with links:
  - [net] vsock/virtio: fix MSG_ZEROCOPY pinned-pages accounting
    https://git.kernel.org/netdev/net/c/1cb36e252211

You are awesome, thank you!
-- 
Deet-doot-dot, I am a bot.
https://korg.docs.kernel.org/patchwork/pwbot.html



^ permalink raw reply

* Re: [PATCH 3/4] scsi: Support scsi_devices without a device wide limit
From: Hannes Reinecke @ 2026-04-23 10:32 UTC (permalink / raw)
  To: John Garry, Mike Christie, martin.petersen, linux-scsi,
	james.bottomley, virtualization, mst, pbonzini, stefanha,
	eperezma
In-Reply-To: <65e78d0c-23a5-4702-9946-60b83532a61b@oracle.com>

On 4/23/26 12:02, John Garry wrote:
> On 22/04/2026 14:15, Hannes Reinecke wrote:
>>> --- a/drivers/scsi/scsi_scan.c
>>> +++ b/drivers/scsi/scsi_scan.c
>>> @@ -352,18 +352,20 @@ static struct scsi_device 
>>> *scsi_alloc_sdev(struct scsi_target *starget,
>>>       if (scsi_device_is_pseudo_dev(sdev))
>>>           return sdev;
>>> -    depth = sdev->host->cmd_per_lun ?: 1;
>>> +    if (sdev->host->cmd_per_lun != SCSI_UNLIMITED_CMD_PER_LUN) {
>>> +        depth = sdev->host->cmd_per_lun ?: 1;
>> Why don't we use a simple flag in the host (or host template) to
>> indicate that cmd_per_lun should be ignored?
>> I'm not in favour of using magic values for a setting which
>> otherwise is a limit.
>> Look to dev_loss_tmo as a bad example ...
> 
> I think it's better to not have a flag and also keep cmd_per_lun, as 
> then we need to sanitize one vs the other. As mentioned in the cover 
> letter response, cmd_per_lun could be got rid off / reworked.
> 
> Personally I also dislike how the scsi budget code checks for a budget 
> map being non-NULL (which is for reserved scsi devices, which doesn't 
> need a per-sdev budget map).

Let's see if we can schedule a session at LSF; I really would like to
get this one sorted out.

Cheers,

Hannes
-- 
Dr. Hannes Reinecke                  Kernel Storage Architect
hare@suse.de                                +49 911 74053 688
SUSE Software Solutions GmbH, Frankenstr. 146, 90461 Nürnberg
HRB 36809 (AG Nürnberg), GF: I. Totev, A. McDonald, W. Knoblich

^ permalink raw reply

* Re: [PATCH 3/4] scsi: Support scsi_devices without a device wide limit
From: John Garry @ 2026-04-23 10:02 UTC (permalink / raw)
  To: Hannes Reinecke, Mike Christie, martin.petersen, linux-scsi,
	james.bottomley, virtualization, mst, pbonzini, stefanha,
	eperezma
In-Reply-To: <448302b1-3950-4e6d-ae8b-337cad09f3fe@suse.de>

On 22/04/2026 14:15, Hannes Reinecke wrote:
>> --- a/drivers/scsi/scsi_scan.c
>> +++ b/drivers/scsi/scsi_scan.c
>> @@ -352,18 +352,20 @@ static struct scsi_device 
>> *scsi_alloc_sdev(struct scsi_target *starget,
>>       if (scsi_device_is_pseudo_dev(sdev))
>>           return sdev;
>> -    depth = sdev->host->cmd_per_lun ?: 1;
>> +    if (sdev->host->cmd_per_lun != SCSI_UNLIMITED_CMD_PER_LUN) {
>> +        depth = sdev->host->cmd_per_lun ?: 1;
> Why don't we use a simple flag in the host (or host template) to
> indicate that cmd_per_lun should be ignored?
> I'm not in favour of using magic values for a setting which
> otherwise is a limit.
> Look to dev_loss_tmo as a bad example ...

I think it's better to not have a flag and also keep cmd_per_lun, as 
then we need to sanitize one vs the other. As mentioned in the cover 
letter response, cmd_per_lun could be got rid off / reworked.

Personally I also dislike how the scsi budget code checks for a budget 
map being non-NULL (which is for reserved scsi devices, which doesn't 
need a per-sdev budget map).

^ permalink raw reply

* Re: [PATCH RFC v3 01/19] mm: thread user_addr through page allocator for cache-friendly zeroing
From: David Hildenbrand (Arm) @ 2026-04-23  9:46 UTC (permalink / raw)
  To: Gregory Price, Michael S. Tsirkin
  Cc: linux-kernel, Andrew Morton, Vlastimil Babka, Brendan Jackman,
	Michal Hocko, Suren Baghdasaryan, Jason Wang, Andrea Arcangeli,
	linux-mm, virtualization, Johannes Weiner, Zi Yan,
	Lorenzo Stoakes, Liam R. Howlett, Mike Rapoport,
	Matthew Wilcox (Oracle), Muchun Song, Oscar Salvador, Baolin Wang,
	Nico Pache, Ryan Roberts, Dev Jain, Barry Song, Lance Yang,
	Matthew Brost, Joshua Hahn, Rakie Kim, Byungchul Park, Ying Huang,
	Alistair Popple, Hugh Dickins, Christoph Lameter, David Rientjes,
	Roman Gushchin, Harry Yoo, Chris Li, Kairui Song, Kemeng Shi,
	Nhat Pham, Baoquan He, linux-fsdevel
In-Reply-To: <aemglPlcwFFHNj1A@gourry-fedora-PF4VCD3F>

On 4/23/26 06:31, Gregory Price wrote:
> On Wed, Apr 22, 2026 at 05:20:27PM -0400, Michael S. Tsirkin wrote:
>> On Wed, Apr 22, 2026 at 03:47:07PM -0400, Gregory Price wrote:
>>>
>>> __alloc_user_pages(..., gfp_t gfp, user_addr)
>>
>> With a wrapper approach, looks like we'd need something like
>> __GFP_SKIP_ZERO so post_alloc_hook doesn't zero sequentially, then the
>> wrapper re-zeros with folio_zero_user().  But then the wrapper needs to
>> know whether the page was pre-zeroed (PG_zeroed), which is cleared by
>> post_alloc_hook before return.  So the information doesn't survive to
>> the wrapper.
>>
> 
> I was thinking more that internally you already have that information
> you need to know to skip the zeroing - and so the wrapper can just pass
> __GFP_ZERO and post_alloc_hook() would do the right thing regardless
> 
> Then on the way out, the new wrapper would take care of cacheline piece.
> 
> However, i explored this a bit - and while it saves some churn on the
> interface, it adds two paths into the buddy - and that increase in
> surface might not be worth it.
> 
> So I see the tradeoff here.  The churn is probably worth it.

In v2 I commented [1]

"
For example, instead of changing all callers of post_alloc_hook() to
pass USER_ADDR_NONE, can we make post_alloc_hook() a simple wrapper
around a variant that consumes an address.

So isn't there a way we can just keep the changes mostly to mm/page_alloc.c?
"

That should avoid most of the churn outside of page_alloc, no?

[1] https://lore.kernel.org/r/4bdc66f2-1469-4b91-9935-74c3d3ca0ed9@kernel.org

-- 
Cheers,

David

^ permalink raw reply

* Re: [PATCH 0/4] scsi: Support devices that don't have a cmd_per_lun limit
From: Hannes Reinecke @ 2026-04-23  9:45 UTC (permalink / raw)
  To: Mike Christie, Stefan Hajnoczi
  Cc: martin.petersen, linux-scsi, james.bottomley, virtualization, mst,
	pbonzini, eperezma
In-Reply-To: <603eee86-9914-4ac8-b937-a38922e69a45@oracle.com>

On 4/22/26 20:05, Mike Christie wrote:
> On 4/20/26 12:33 PM, Stefan Hajnoczi wrote:
>> On Fri, Apr 17, 2026 at 05:57:20PM -0500, Mike Christie wrote:
>>> The following patches were made over Linus's and Martin's 7.1 trees.
>>> They fix an issue where for virtio-scsi we export a lot of non-scsi
>>> devices but are getting throttled by the cmd_per_lun_limit too early.
>>> For example we export 1 or more NVMe or block devices and would like
>>> to just pass command to them in way where virtio-scsi's hw queue
>>> limits match the physical hardware. Or in some cases we are doing
>>> cgroup based throttling on the host side, and we don't want the guest
>>> to block IO when the host knows we have extra bandwidth.
>>>
>>> The patches add a new cmd_per_lun value so drivers can indicate
>>> when to avoid tracking queueing at the device wide level. They
>>> then rely on just the block layer hw queue limits. And the patches
>>> convert virtio-scsi. They also fix some can_queue related issues
>>> discovered while testing/reviewing.
>>
>> Hi Mike,
>> Is there a difference between setting cmd_per_lun to U32_MAX with your
>> patches versus setting cmd_per_lun to the virtqueue size without your
>> patches (this can already be done today without code changes in the
>> driver)?
> 
> The problem today is that cmd_per_lun doesn't take into account the
> multiqueue queues (virtqueues in virtio) so we have a low limit of 1024
> commands total. On a 32-128 vCPU VM we can easily hit that as there's
> lots of IO submission threads spread over lots of those CPUs. CPUs are
> then mapped to block mq queues which are mapped to virtqueues so we are
> hitting them hard.
> 
> That 1024 value comes from QEMU which limits virtqueue_size to 1024.
> We could increase that to 4096 or 32K or whatever. The problem is that
> we would then be wasting a lot of memory as we would be allocating lots
> of really large virtqueues that would go underutilized (we are submitting
> 10s of thousands of total IOs but not to just a single queue).
> 
> So a possibly good balance between not having to use a magic number
> (U32_MAX) plus having to update the spec would be to:
> 
> 1. Fix up scsi-ml and virtio-scsi so they allow cmd_per_lun to be
> greater than can_queue (virtqueue_size for virtio-scsi).
> 
> 2. Increase the scsi-ml cap cmd_per_lun cap from 4096 to S16_MAX
> (scsi-ml uses a short for cmd_per_lun).
> 
> The only drawback to this would be that for each scsi_device we track
> running IO with a sbitmap. For my cases, we don't need it, so it would
> be a waste of memory. For a S16_MAX worth of commands I think it would
> be 128K wasted so not too bad for us as we don't have lots of these
> types of high perf devices per VM.
> 
Ideally I would kill cmd_per_lun.
This really is a poor man's fairness algorithm (sole purpose is to
avoid starvation with many luns), and we really should look at if
we cannot replace it with tagsets.

Cheers,

Hannes
-- 
Dr. Hannes Reinecke                  Kernel Storage Architect
hare@suse.de                                +49 911 74053 688
SUSE Software Solutions GmbH, Frankenstr. 146, 90461 Nürnberg
HRB 36809 (AG Nürnberg), GF: I. Totev, A. McDonald, W. Knoblich

^ permalink raw reply

* Re: [PATCH v11 03/13] lib/group_cpus: Add group_mask_cpus_evenly()
From: Marco Crivellari @ 2026-04-23  8:11 UTC (permalink / raw)
  To: Aaron Tomlin
  Cc: James.Bottomley, MPT-FusionLinux.pdl, aacraid, akpm, axboe,
	bigeasy, chandrakanth.patil, chenridong, chjohnst, frederic, hare,
	hch, jinpu.wang, juri.lelli, kashyap.desai, kbusch, kch,
	linux-block, linux-kernel, linux-nvme, linux-scsi, liyihang9,
	longman, martin.petersen, maz, megaraidlinux.pdl, ming.lei, mingo,
	mpi3mr-linuxdrv.pdl, mproche, mst, neelx, nick.lange, peterz,
	ranjan.kumar, ruanjinjie, sagi, sathya.prakash, sean,
	shivasharan.srikanteshwara, sreekanth.reddy, steve,
	suganath-prabu.subramani, sumit.saxena, tglx, tom.leiming,
	vincent.guittot, virtualization, wagi, yphbchou0911
In-Reply-To: <tfkr5mlsdzbhdzv46ookoy2e7ed2wcozuxanv4wagjf6hqb4sa@7i753lpqkxvp>

On Wed, Apr 22, 2026 at 7:47 PM Aaron Tomlin <atomlin@atomlin.com> wrote:
>
> On Mon, Apr 20, 2026 at 03:11:52PM +0200, Marco Crivellari wrote:
> > Without it, I guess the kmalloc() in `group_mask_cpus_evenly()` will
> > return ZERO_SIZE_PTR:
>
> Hi Marco,
>
> Thank you for reviewing the patch.
>
> You are correct. If numgrps is 0, __do_kmalloc_node() will
> return ZERO_SIZE_PTR.
>
> > Should this check be added or it is not needed? Or maybe rely on `ZERO_OR_NULL_PTR()` ?
>
>  - File: mm/slub.c
>
>     5275 static __always_inline
>     5276 void *__do_kmalloc_node(size_t size, kmem_buckets *b, gfp_t flags, int node,
>     5277                         unsigned long caller)
>     5278 {
>     5279         struct kmem_cache *s;
>     5280         void *ret;
>      :
>     5289         if (unlikely(!size))
>     5290                 return ZERO_SIZE_PTR;
>      :
>     5298 }
>
> Regarding your suggestion: rather than relying on ZERO_OR_NULL_PTR() after
> the fact, I think it is much cleaner to just add the early exit at the very
> beginning of the function, exactly as group_cpus_evenly() does. It avoids
> the allocator path entirely.

Hi,

Cool, I think that's the right thing indeed.

Thanks!

-- 

Marco Crivellari

SUSE Labs

^ permalink raw reply

* Re: [PATCH net v2] hv_sock: Return -EIO for malformed/short packets
From: Stefano Garzarella @ 2026-04-23  7:55 UTC (permalink / raw)
  To: Dexuan Cui
  Cc: kys, haiyangz, wei.liu, longli, davem, edumazet, kuba, pabeni,
	horms, niuxuewei.nxw, linux-hyperv, virtualization, netdev,
	linux-kernel, stable
In-Reply-To: <20260423064811.1371749-1-decui@microsoft.com>

On Wed, Apr 22, 2026 at 11:48:11PM -0700, Dexuan Cui wrote:
>Commit f63152958994 fixes a regression, however it fails to report an
>error for malformed/short packets -- normally we should never see such
>packets, but let's report an error for them just in case.
>
>Fixes: f63152958994 ("hv_sock: Report EOF instead of -EIO for FIN")
>Cc: stable@vger.kernel.org
>Signed-off-by: Dexuan Cui <decui@microsoft.com>
>---
>
>Commit f63152958994 is currently only in net.git's master branch.
>
>Changes since v1:
>    Integrated comments from Stefano Garzarella:
>
>        1) access 'vsk' directly:
>           s/hvs->vsk->peer_shutdown/vsk->peer_shutdown/
>
>        2) test the error condition first and return -EIO for that.
>
>    NO other changes.

Thanks, LGTM!

Acked-by: Stefano Garzarella <sgarzare@redhat.com>


^ permalink raw reply

* RE: [EXTERNAL] Re: [PATCH net] hv_sock: Return -EIO for malformed/short packets
From: Dexuan Cui @ 2026-04-23  6:50 UTC (permalink / raw)
  To: Dexuan Cui, Stefano Garzarella
  Cc: KY Srinivasan, Haiyang Zhang, wei.liu@kernel.org, Long Li,
	davem@davemloft.net, edumazet@google.com, kuba@kernel.org,
	pabeni@redhat.com, horms@kernel.org, niuxuewei.nxw@antgroup.com,
	linux-hyperv@vger.kernel.org, virtualization@lists.linux.dev,
	netdev@vger.kernel.org, linux-kernel@vger.kernel.org,
	stable@vger.kernel.org
In-Reply-To: <SA1PR21MB6921EDE5E6530B09931ABD93BF2D2@SA1PR21MB6921.namprd21.prod.outlook.com>

> From: Dexuan Cui
> Sent: Wednesday, April 22, 2026 11:15 AM
>  ...
> Thank you Stefano! I'll post v2 later today.

Posted v2:
https://lore.kernel.org/linux-hyperv/20260423064811.1371749-1-decui@microsoft.com/T/#u

^ permalink raw reply

* [PATCH net v2] hv_sock: Return -EIO for malformed/short packets
From: Dexuan Cui @ 2026-04-23  6:48 UTC (permalink / raw)
  To: kys, haiyangz, wei.liu, decui, longli, sgarzare, davem, edumazet,
	kuba, pabeni, horms, niuxuewei.nxw, linux-hyperv, virtualization,
	netdev, linux-kernel
  Cc: stable

Commit f63152958994 fixes a regression, however it fails to report an
error for malformed/short packets -- normally we should never see such
packets, but let's report an error for them just in case.

Fixes: f63152958994 ("hv_sock: Report EOF instead of -EIO for FIN")
Cc: stable@vger.kernel.org
Signed-off-by: Dexuan Cui <decui@microsoft.com>
---

Commit f63152958994 is currently only in net.git's master branch.

Changes since v1:
    Integrated comments from Stefano Garzarella:

        1) access 'vsk' directly:
           s/hvs->vsk->peer_shutdown/vsk->peer_shutdown/

        2) test the error condition first and return -EIO for that.

    NO other changes.


 net/vmw_vsock/hyperv_transport.c | 27 ++++++++++++++++++---------
 1 file changed, 18 insertions(+), 9 deletions(-)

diff --git a/net/vmw_vsock/hyperv_transport.c b/net/vmw_vsock/hyperv_transport.c
index 76e78c83fdbc..f862988c1e86 100644
--- a/net/vmw_vsock/hyperv_transport.c
+++ b/net/vmw_vsock/hyperv_transport.c
@@ -704,17 +704,26 @@ static s64 hvs_stream_has_data(struct vsock_sock *vsk)
 		if (hvs->recv_desc) {
 			/* Here hvs->recv_data_len is 0, so hvs->recv_desc must
 			 * be NULL unless it points to the 0-byte-payload FIN
-			 * packet: see hvs_update_recv_data().
+			 * packet or a malformed/short packet: see
+			 * hvs_update_recv_data().
 			 *
-			 * Here all the payload has been dequeued, but
-			 * hvs_channel_readable_payload() still returns 1,
-			 * because the VMBus ringbuffer's read_index is not
-			 * updated for the FIN packet: hvs_stream_dequeue() ->
-			 * hv_pkt_iter_next() updates the cached priv_read_index
-			 * but has no opportunity to update the read_index in
-			 * hv_pkt_iter_close() as hvs_stream_has_data() returns
-			 * 0 for the FIN packet, so it won't get dequeued.
+			 * If hvs->recv_desc points to the FIN packet, here all
+			 * the payload has been dequeued and the peer_shutdown
+			 * flag is set, but hvs_channel_readable_payload() still
+			 * returns 1, because the VMBus ringbuffer's read_index
+			 * is not updated for the FIN packet:
+			 * hvs_stream_dequeue() -> hv_pkt_iter_next() updates
+			 * the cached priv_read_index but has no opportunity to
+			 * update the read_index in hv_pkt_iter_close() as
+			 * hvs_stream_has_data() returns 0 for the FIN packet,
+			 * so it won't get dequeued.
+			 *
+			 * In case hvs->recv_desc points to a malformed/short
+			 * packet, return -EIO.
 			 */
+			if (!(vsk->peer_shutdown & SEND_SHUTDOWN))
+				return -EIO;
+
 			return 0;
 		}
 
-- 
2.49.0


^ permalink raw reply related

* Re: [PATCH RFC v3 01/19] mm: thread user_addr through page allocator for cache-friendly zeroing
From: Gregory Price @ 2026-04-23  4:31 UTC (permalink / raw)
  To: Michael S. Tsirkin
  Cc: linux-kernel, Andrew Morton, David Hildenbrand, Vlastimil Babka,
	Brendan Jackman, Michal Hocko, Suren Baghdasaryan, Jason Wang,
	Andrea Arcangeli, linux-mm, virtualization, Johannes Weiner,
	Zi Yan, Lorenzo Stoakes, Liam R. Howlett, Mike Rapoport,
	Matthew Wilcox (Oracle), Muchun Song, Oscar Salvador, Baolin Wang,
	Nico Pache, Ryan Roberts, Dev Jain, Barry Song, Lance Yang,
	Matthew Brost, Joshua Hahn, Rakie Kim, Byungchul Park, Ying Huang,
	Alistair Popple, Hugh Dickins, Christoph Lameter, David Rientjes,
	Roman Gushchin, Harry Yoo, Chris Li, Kairui Song, Kemeng Shi,
	Nhat Pham, Baoquan He, linux-fsdevel
In-Reply-To: <20260422171315-mutt-send-email-mst@kernel.org>

On Wed, Apr 22, 2026 at 05:20:27PM -0400, Michael S. Tsirkin wrote:
> On Wed, Apr 22, 2026 at 03:47:07PM -0400, Gregory Price wrote:
> > 
> > __alloc_user_pages(..., gfp_t gfp, user_addr)
> 
> With a wrapper approach, looks like we'd need something like
> __GFP_SKIP_ZERO so post_alloc_hook doesn't zero sequentially, then the
> wrapper re-zeros with folio_zero_user().  But then the wrapper needs to
> know whether the page was pre-zeroed (PG_zeroed), which is cleared by
> post_alloc_hook before return.  So the information doesn't survive to
> the wrapper.
> 

I was thinking more that internally you already have that information
you need to know to skip the zeroing - and so the wrapper can just pass
__GFP_ZERO and post_alloc_hook() would do the right thing regardless

Then on the way out, the new wrapper would take care of cacheline piece.

However, i explored this a bit - and while it saves some churn on the
interface, it adds two paths into the buddy - and that increase in
surface might not be worth it.

So I see the tradeoff here.  The churn is probably worth it.

~Gregory

^ permalink raw reply

* Re: [PATCH RFC v3 10/19] mm: remove arch vma_alloc_zeroed_movable_folio overrides
From: Greg Ungerer @ 2026-04-22 21:29 UTC (permalink / raw)
  To: Michael S. Tsirkin, linux-kernel
  Cc: Andrew Morton, David Hildenbrand, Vlastimil Babka,
	Brendan Jackman, Michal Hocko, Suren Baghdasaryan, Jason Wang,
	Andrea Arcangeli, Gregory Price, linux-mm, virtualization,
	Richard Henderson, Matt Turner, Magnus Lindholm,
	Geert Uytterhoeven, Heiko Carstens, Vasily Gorbik,
	Alexander Gordeev, Christian Borntraeger, Sven Schnelle,
	Thomas Gleixner, Ingo Molnar, Borislav Petkov, Dave Hansen, x86,
	H. Peter Anvin, linux-alpha, linux-m68k, linux-s390
In-Reply-To: <006f9142e591ba8c340c3b354aee76aec5c285b9.1776808210.git.mst@redhat.com>

On 22/4/26 08:01, Michael S. Tsirkin wrote:
> Now that the generic vma_alloc_zeroed_movable_folio() uses
> __GFP_ZERO, the arch-specific macros on alpha, m68k, s390, and
> x86 that did the same thing are redundant.  Remove them.
> 
> arm64 is not affected: it has a real function override that
> handles MTE tag zeroing, not just __GFP_ZERO.
> 
> Suggested-by: David Hildenbrand <david@kernel.org>
> Signed-off-by: Michael S. Tsirkin <mst@redhat.com>
> ---
>   arch/alpha/include/asm/page.h   | 3 ---
>   arch/m68k/include/asm/page_no.h | 3 ---

For arch/m68k/include/asm/page_no.h:

Acked-by: Greg Ungerer <gerg@linux-m68k.org>



^ permalink raw reply

* Re: [PATCH RFC v3 01/19] mm: thread user_addr through page allocator for cache-friendly zeroing
From: Michael S. Tsirkin @ 2026-04-22 21:20 UTC (permalink / raw)
  To: Gregory Price
  Cc: linux-kernel, Andrew Morton, David Hildenbrand, Vlastimil Babka,
	Brendan Jackman, Michal Hocko, Suren Baghdasaryan, Jason Wang,
	Andrea Arcangeli, linux-mm, virtualization, Johannes Weiner,
	Zi Yan, Lorenzo Stoakes, Liam R. Howlett, Mike Rapoport,
	Matthew Wilcox (Oracle), Muchun Song, Oscar Salvador, Baolin Wang,
	Nico Pache, Ryan Roberts, Dev Jain, Barry Song, Lance Yang,
	Matthew Brost, Joshua Hahn, Rakie Kim, Byungchul Park, Ying Huang,
	Alistair Popple, Hugh Dickins, Christoph Lameter, David Rientjes,
	Roman Gushchin, Harry Yoo, Chris Li, Kairui Song, Kemeng Shi,
	Nhat Pham, Baoquan He, linux-fsdevel
In-Reply-To: <aekluxNPxF8CN8fL@gourry-fedora-PF4VCD3F>

On Wed, Apr 22, 2026 at 03:47:07PM -0400, Gregory Price wrote:
> On Tue, Apr 21, 2026 at 06:01:10PM -0400, Michael S. Tsirkin wrote:
> > Thread a user virtual address from vma_alloc_folio() down through
> > the page allocator to post_alloc_hook().  This is plumbing preparation
> > for a subsequent patch that will use user_addr to call folio_zero_user()
> > for cache-friendly zeroing of user pages.
> > 
> > The user_addr is stored in struct alloc_context and flows through:
> >   vma_alloc_folio -> folio_alloc_mpol -> __alloc_pages_mpol ->
> >   __alloc_frozen_pages -> get_page_from_freelist -> prep_new_page ->
> >   post_alloc_hook
> > 
> > Public APIs (__alloc_pages, __folio_alloc, folio_alloc_mpol) gain a
> > user_addr parameter directly.  Callers that do not need user_addr
> > pass USER_ADDR_NONE ((unsigned long)-1), since
> > address 0 is a valid user mapping.
> > 
> 
> Question: rather than churning the entirety of the existing interfaces,
> is there a possibility of adding an explicit interface for this
> interaction that amounts to:
> 
> __alloc_user_pages(..., gfp_t gfp, user_addr)
> {
>     BUG_ON(!(gfp & __GFP_ZERO));
> 
>     /* post_alloc_hook implements the already-zeroed skip */
>     page = alloc_page(..., gfp, ...); /* existing interface */
> 
>     /* Do the cacheline stuff here instead of in the core */
>     cacheline_nonsense(page, user_addr);
> 
>     return page; /* user doesn't need to do explicit zeroing */
> }
> 
> Then rather than leaking information out of the buddy, we just need to
> get the zeroed information *into* the buddy.
> 
> the users that want zeroing but need the explicit user_addr step just
> defer the zeroing to outside post_alloc_hook().
> 
> That's just my immediate gut reaction to all this churn on the existing
> interfaces.
> 
> Existing users can continue using the buddy as-is, and enlightened users
> can optimize for this specific kind of __GFP_ZERO interaction.
> 
> ~Gregory


Hmm. Maybe I misunderstand what you propose, but this seems pretty close
to what v2 did - each callsite checked whether the page was pre-zeroed
and called folio_zero_user() itself.  The feedback (both you and David)
was that threading it through the allocator is better.

With a wrapper approach, looks like we'd need something like
__GFP_SKIP_ZERO so post_alloc_hook doesn't zero sequentially, then the
wrapper re-zeros with folio_zero_user().  But then the wrapper needs to
know whether the page was pre-zeroed (PG_zeroed), which is cleared by
post_alloc_hook before return.  So the information doesn't survive to
the wrapper.

We could return the zeroed hint via an output parameter, but that's
what v2's pghint_t was, and it was disliked.

The user_addr threading through the allocator does add API churn,
but it's all mechanical (adding one parameter, callers pass
USER_ADDR_NONE), any mistaked are just build errors.

And it makes the zeroing path closer to being correct by
construction: every allocation either explicitly
says no address or has a user_addr - and then gets
cache-friendly zeroing or skip-if-prezeroed, with no possibility
of a callsite forgetting to handle it.

Fundamentally, David told me I need to move folio_zero_user into
post_alloc_hook as a prerequisite to the optimization, so I did that -
let's stick to it then, shall we?


This approach also fixes a pre-existing double-zeroing on architectures with
aliasing data caches + init_on_alloc, where current code zeros once
via kernel_init_pages() then again via clear_user_highpage() at
the callsite. I don't see how that would be possible with the wrapper.

-- 
MST


^ permalink raw reply

* Re: [PATCH RFC v3 01/19] mm: thread user_addr through page allocator for cache-friendly zeroing
From: Michael S. Tsirkin @ 2026-04-22 20:32 UTC (permalink / raw)
  To: Gregory Price
  Cc: linux-kernel, Andrew Morton, David Hildenbrand, Vlastimil Babka,
	Brendan Jackman, Michal Hocko, Suren Baghdasaryan, Jason Wang,
	Andrea Arcangeli, linux-mm, virtualization, Johannes Weiner,
	Zi Yan, Lorenzo Stoakes, Liam R. Howlett, Mike Rapoport,
	Matthew Wilcox (Oracle), Muchun Song, Oscar Salvador, Baolin Wang,
	Nico Pache, Ryan Roberts, Dev Jain, Barry Song, Lance Yang,
	Matthew Brost, Joshua Hahn, Rakie Kim, Byungchul Park, Ying Huang,
	Alistair Popple, Hugh Dickins, Christoph Lameter, David Rientjes,
	Roman Gushchin, Harry Yoo, Chris Li, Kairui Song, Kemeng Shi,
	Nhat Pham, Baoquan He, linux-fsdevel
In-Reply-To: <aekluxNPxF8CN8fL@gourry-fedora-PF4VCD3F>

On Wed, Apr 22, 2026 at 03:47:07PM -0400, Gregory Price wrote:
> On Tue, Apr 21, 2026 at 06:01:10PM -0400, Michael S. Tsirkin wrote:
> > Thread a user virtual address from vma_alloc_folio() down through
> > the page allocator to post_alloc_hook().  This is plumbing preparation
> > for a subsequent patch that will use user_addr to call folio_zero_user()
> > for cache-friendly zeroing of user pages.
> > 
> > The user_addr is stored in struct alloc_context and flows through:
> >   vma_alloc_folio -> folio_alloc_mpol -> __alloc_pages_mpol ->
> >   __alloc_frozen_pages -> get_page_from_freelist -> prep_new_page ->
> >   post_alloc_hook
> > 
> > Public APIs (__alloc_pages, __folio_alloc, folio_alloc_mpol) gain a
> > user_addr parameter directly.  Callers that do not need user_addr
> > pass USER_ADDR_NONE ((unsigned long)-1), since
> > address 0 is a valid user mapping.
> > 
> 
> Question: rather than churning the entirety of the existing interfaces,
> is there a possibility of adding an explicit interface for this
> interaction that amounts to:
> 
> __alloc_user_pages(..., gfp_t gfp, user_addr)
> {
>     BUG_ON(!(gfp & __GFP_ZERO));
> 
>     /* post_alloc_hook implements the already-zeroed skip */
>     page = alloc_page(..., gfp, ...); /* existing interface */
> 
>     /* Do the cacheline stuff here instead of in the core */
>     cacheline_nonsense(page, user_addr);
> 
>     return page; /* user doesn't need to do explicit zeroing */
> }
> 
> Then rather than leaking information out of the buddy, we just need to
> get the zeroed information *into* the buddy.
> 
> the users that want zeroing but need the explicit user_addr step just
> defer the zeroing to outside post_alloc_hook().
> 
> That's just my immediate gut reaction to all this churn on the existing
> interfaces.
> 
> Existing users can continue using the buddy as-is, and enlightened users
> can optimize for this specific kind of __GFP_ZERO interaction.
> 
> ~Gregory


I am sorry i do not understand. Users have no idea if they need
"user_addr step" - it is an arch thing.

the places that pass USER_ADDR_NONE can avoid being changed.

*However* without this change it is easy to miss someone who
has to pass the address and simply forgot to, and this
someone gets GFP_ZERO from the caller.

It took me forever to find all places as it is, at least
every change is explicit.

Because no testing on x86 will show the issue, and it is a subtle
corruption even on other arches.

I think churn is better than a risk of silent corruption...

-- 
MST


^ permalink raw reply

* Re: [PATCH RFC v3 01/19] mm: thread user_addr through page allocator for cache-friendly zeroing
From: Gregory Price @ 2026-04-22 19:47 UTC (permalink / raw)
  To: Michael S. Tsirkin
  Cc: linux-kernel, Andrew Morton, David Hildenbrand, Vlastimil Babka,
	Brendan Jackman, Michal Hocko, Suren Baghdasaryan, Jason Wang,
	Andrea Arcangeli, linux-mm, virtualization, Johannes Weiner,
	Zi Yan, Lorenzo Stoakes, Liam R. Howlett, Mike Rapoport,
	Matthew Wilcox (Oracle), Muchun Song, Oscar Salvador, Baolin Wang,
	Nico Pache, Ryan Roberts, Dev Jain, Barry Song, Lance Yang,
	Matthew Brost, Joshua Hahn, Rakie Kim, Byungchul Park, Ying Huang,
	Alistair Popple, Hugh Dickins, Christoph Lameter, David Rientjes,
	Roman Gushchin, Harry Yoo, Chris Li, Kairui Song, Kemeng Shi,
	Nhat Pham, Baoquan He, linux-fsdevel
In-Reply-To: <9dd9deabd42801f3c344326991d1431c3d8db39d.1776808210.git.mst@redhat.com>

On Tue, Apr 21, 2026 at 06:01:10PM -0400, Michael S. Tsirkin wrote:
> Thread a user virtual address from vma_alloc_folio() down through
> the page allocator to post_alloc_hook().  This is plumbing preparation
> for a subsequent patch that will use user_addr to call folio_zero_user()
> for cache-friendly zeroing of user pages.
> 
> The user_addr is stored in struct alloc_context and flows through:
>   vma_alloc_folio -> folio_alloc_mpol -> __alloc_pages_mpol ->
>   __alloc_frozen_pages -> get_page_from_freelist -> prep_new_page ->
>   post_alloc_hook
> 
> Public APIs (__alloc_pages, __folio_alloc, folio_alloc_mpol) gain a
> user_addr parameter directly.  Callers that do not need user_addr
> pass USER_ADDR_NONE ((unsigned long)-1), since
> address 0 is a valid user mapping.
> 

Question: rather than churning the entirety of the existing interfaces,
is there a possibility of adding an explicit interface for this
interaction that amounts to:

__alloc_user_pages(..., gfp_t gfp, user_addr)
{
    BUG_ON(!(gfp & __GFP_ZERO));

    /* post_alloc_hook implements the already-zeroed skip */
    page = alloc_page(..., gfp, ...); /* existing interface */

    /* Do the cacheline stuff here instead of in the core */
    cacheline_nonsense(page, user_addr);

    return page; /* user doesn't need to do explicit zeroing */
}

Then rather than leaking information out of the buddy, we just need to
get the zeroed information *into* the buddy.

the users that want zeroing but need the explicit user_addr step just
defer the zeroing to outside post_alloc_hook().

That's just my immediate gut reaction to all this churn on the existing
interfaces.

Existing users can continue using the buddy as-is, and enlightened users
can optimize for this specific kind of __GFP_ZERO interaction.

~Gregory

^ permalink raw reply

* [PATCH v12 13/13] docs: add io_queue flag to isolcpus
From: Aaron Tomlin @ 2026-04-22 18:52 UTC (permalink / raw)
  To: axboe, kbusch, hch, sagi, mst
  Cc: atomlin, aacraid, James.Bottomley, martin.petersen, liyihang9,
	kashyap.desai, sumit.saxena, shivasharan.srikanteshwara,
	chandrakanth.patil, sathya.prakash, sreekanth.reddy,
	suganath-prabu.subramani, ranjan.kumar, jinpu.wang, tglx, mingo,
	peterz, juri.lelli, vincent.guittot, akpm, maz, ruanjinjie,
	bigeasy, yphbchou0911, wagi, frederic, longman, chenridong, hare,
	kch, ming.lei, tom.leiming, steve, sean, chjohnst, neelx, mproche,
	nick.lange, marco.crivellari, linux-block, linux-kernel,
	virtualization, linux-nvme, linux-scsi, megaraidlinux.pdl,
	mpi3mr-linuxdrv.pdl, MPT-FusionLinux.pdl
In-Reply-To: <20260422185215.100929-1-atomlin@atomlin.com>

From: Daniel Wagner <wagi@kernel.org>

The io_queue flag informs multiqueue device drivers where to place
hardware queues. Document this new flag in the isolcpus
command-line argument description.

Signed-off-by: Daniel Wagner <wagi@kernel.org>
Reviewed-by: Hannes Reinecke <hare@suse.de>
[atomlin: Refined io_queue kernel parameter documentation]
Signed-off-by: Aaron Tomlin <atomlin@atomlin.com>
---
 .../admin-guide/kernel-parameters.txt         | 30 ++++++++++++++++++-
 1 file changed, 29 insertions(+), 1 deletion(-)

diff --git a/Documentation/admin-guide/kernel-parameters.txt b/Documentation/admin-guide/kernel-parameters.txt
index cf3807641d89..e2d798351964 100644
--- a/Documentation/admin-guide/kernel-parameters.txt
+++ b/Documentation/admin-guide/kernel-parameters.txt
@@ -2810,7 +2810,6 @@ Kernel parameters
 			  "number of CPUs in system - 1".
 
 			managed_irq
-
 			  Isolate from being targeted by managed interrupts
 			  which have an interrupt mask containing isolated
 			  CPUs. The affinity of managed interrupts is
@@ -2833,6 +2832,35 @@ Kernel parameters
 			  housekeeping CPUs has no influence on those
 			  queues.
 
+			io_queue
+			  Applicable to managed IRQs only. Restrict
+			  multiqueue hardware queue allocation to online
+			  housekeeping CPUs. This guarantees that all
+			  managed hardware completion interrupts are routed
+			  exclusively to housekeeping cores, shielding
+			  isolated CPUs from I/O interruptions even if they
+			  initiated the request.
+
+			  The io_queue configuration takes precedence over
+			  managed_irq. When io_queue is used, managed_irq
+			  placement constraints have no effect.
+
+			  Note: Using io_queue restricts the number of
+			  allocated hardware queues to match the number of
+			  housekeeping CPUs. This prevents MSI-X vector
+			  exhaustion and forces isolated CPUs to share
+			  submission queues.
+
+			  Note: Offlining housekeeping CPUs which serve
+			  isolated CPUs will fail. The isolated CPUs must
+			  be offlined before offlining the housekeeping
+			  CPUs.
+
+			  Note: When I/O is submitted by an application on
+			  an isolated CPU, the hardware completion
+			  interrupt is handled entirely by a housekeeping
+			  CPU.
+
 			The format of <cpu-list> is described above.
 
 	iucv=		[HW,NET]
-- 
2.51.0


^ permalink raw reply related

* [PATCH v12 12/13] genirq/affinity: Restrict managed IRQ affinity to housekeeping CPUs
From: Aaron Tomlin @ 2026-04-22 18:52 UTC (permalink / raw)
  To: axboe, kbusch, hch, sagi, mst
  Cc: atomlin, aacraid, James.Bottomley, martin.petersen, liyihang9,
	kashyap.desai, sumit.saxena, shivasharan.srikanteshwara,
	chandrakanth.patil, sathya.prakash, sreekanth.reddy,
	suganath-prabu.subramani, ranjan.kumar, jinpu.wang, tglx, mingo,
	peterz, juri.lelli, vincent.guittot, akpm, maz, ruanjinjie,
	bigeasy, yphbchou0911, wagi, frederic, longman, chenridong, hare,
	kch, ming.lei, tom.leiming, steve, sean, chjohnst, neelx, mproche,
	nick.lange, marco.crivellari, linux-block, linux-kernel,
	virtualization, linux-nvme, linux-scsi, megaraidlinux.pdl,
	mpi3mr-linuxdrv.pdl, MPT-FusionLinux.pdl
In-Reply-To: <20260422185215.100929-1-atomlin@atomlin.com>

At present, the managed interrupt spreading algorithm distributes vectors
across all available CPUs within a given node or system. On systems
employing CPU isolation (e.g., "isolcpus=io_queue"), this behaviour
defeats the primary purpose of isolation by routing hardware interrupts
(such as NVMe completion queues) directly to isolated cores.

Update irq_create_affinity_masks() to respect the housekeeping CPU mask.
Introduce irq_spread_hk_filter() to intersect the natively calculated
affinity mask with the HK_TYPE_IO_QUEUE mask, thereby keeping managed
interrupts off isolated CPUs.

To ensure strict isolation whilst guaranteeing a valid routing destination:

    1.  Fallback mechanism: Should the initial spreading logic assign a
        vector exclusively to isolated CPUs (resulting in an empty
        intersection), the filter safely falls back to the system's
        online housekeeping CPUs.

    2.  Hotplug safety: The fallback utilises data_race(cpu_online_mask)
        instead of allocating a local cpumask snapshot. This circumvents
        CONFIG_CPUMASK_OFFSTACK stack bloat hazards on high-core-count
        systems. Furthermore, it prevents deadlocks with concurrent CPU
        hotplug operations (e.g., during storage driver error recovery)
        by eliminating the need to hold the CPU hotplug read lock.

    3.  Fast-path optimisation: The filtering logic is conditionally
        executed only if housekeeping is enabled, thereby ensuring zero
        overhead for standard configurations.

Signed-off-by: Aaron Tomlin <atomlin@atomlin.com>
---
 kernel/irq/affinity.c | 26 +++++++++++++++++++++++++-
 1 file changed, 25 insertions(+), 1 deletion(-)

diff --git a/kernel/irq/affinity.c b/kernel/irq/affinity.c
index e0cf70a99339..03e914ffd720 100644
--- a/kernel/irq/affinity.c
+++ b/kernel/irq/affinity.c
@@ -8,6 +8,24 @@
 #include <linux/slab.h>
 #include <linux/cpu.h>
 #include <linux/group_cpus.h>
+#include <linux/sched/isolation.h>
+
+/**
+ * irq_spread_hk_filter - Restrict an interrupt affinity mask to housekeeping CPUs
+ * @mask:            The interrupt affinity mask to filter (in/out)
+ * @hk_mask:         The system's housekeeping CPU mask
+ *
+ * Intersects @mask with @hk_mask to keep interrupts off isolated CPUs.
+ * If this intersection is empty (meaning all targeted CPUs were isolated),
+ * it falls back to the online housekeeping CPUs to guarantee a valid
+ * routing destination.
+ */
+static void irq_spread_hk_filter(struct cpumask *mask,
+				 const struct cpumask *hk_mask)
+{
+	if (!cpumask_and(mask, mask, hk_mask))
+		cpumask_and(mask, hk_mask, data_race(cpu_online_mask));
+}
 
 static void default_calc_sets(struct irq_affinity *affd, unsigned int affvecs)
 {
@@ -27,6 +45,8 @@ irq_create_affinity_masks(unsigned int nvecs, struct irq_affinity *affd)
 {
 	unsigned int affvecs, curvec, usedvecs, i;
 	struct irq_affinity_desc *masks = NULL;
+	const struct cpumask *hk_mask = housekeeping_cpumask(HK_TYPE_IO_QUEUE);
+	bool hk_enabled = housekeeping_enabled(HK_TYPE_IO_QUEUE);
 
 	/*
 	 * Determine the number of vectors which need interrupt affinities
@@ -83,8 +103,12 @@ irq_create_affinity_masks(unsigned int nvecs, struct irq_affinity *affd)
 			return NULL;
 		}
 
-		for (int j = 0; j < nr_masks; j++)
+		for (int j = 0; j < nr_masks; j++) {
 			cpumask_copy(&masks[curvec + j].mask, &result[j]);
+			if (hk_enabled)
+				irq_spread_hk_filter(&masks[curvec + j].mask,
+						     hk_mask);
+		}
 		kfree(result);
 
 		curvec += nr_masks;
-- 
2.51.0


^ permalink raw reply related

* [PATCH v12 11/13] blk-mq: prevent offlining hk CPUs with associated online isolated CPUs
From: Aaron Tomlin @ 2026-04-22 18:52 UTC (permalink / raw)
  To: axboe, kbusch, hch, sagi, mst
  Cc: atomlin, aacraid, James.Bottomley, martin.petersen, liyihang9,
	kashyap.desai, sumit.saxena, shivasharan.srikanteshwara,
	chandrakanth.patil, sathya.prakash, sreekanth.reddy,
	suganath-prabu.subramani, ranjan.kumar, jinpu.wang, tglx, mingo,
	peterz, juri.lelli, vincent.guittot, akpm, maz, ruanjinjie,
	bigeasy, yphbchou0911, wagi, frederic, longman, chenridong, hare,
	kch, ming.lei, tom.leiming, steve, sean, chjohnst, neelx, mproche,
	nick.lange, marco.crivellari, linux-block, linux-kernel,
	virtualization, linux-nvme, linux-scsi, megaraidlinux.pdl,
	mpi3mr-linuxdrv.pdl, MPT-FusionLinux.pdl
In-Reply-To: <20260422185215.100929-1-atomlin@atomlin.com>

From: Daniel Wagner <wagi@kernel.org>

When isolcpus=io_queue is enabled and the last housekeeping CPU
for a given hctx goes offline, no CPU would be left to handle I/O.
To prevent I/O stalls, disallow offlining housekeeping CPUs that are
still serving isolated CPUs.

Signed-off-by: Daniel Wagner <wagi@kernel.org>
Reviewed-by: Hannes Reinecke <hare@suse.de>
[atomlin: Removed duplicate paragraph from commit message]
Signed-off-by: Aaron Tomlin <atomlin@atomlin.com>
---
 block/blk-mq.c | 42 ++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 42 insertions(+)

diff --git a/block/blk-mq.c b/block/blk-mq.c
index 4c5c16cce4f8..4257d5b26641 100644
--- a/block/blk-mq.c
+++ b/block/blk-mq.c
@@ -3720,6 +3720,43 @@ static bool blk_mq_hctx_has_requests(struct blk_mq_hw_ctx *hctx)
 	return data.has_rq;
 }
 
+static bool blk_mq_hctx_can_offline_hk_cpu(struct blk_mq_hw_ctx *hctx,
+					   unsigned int this_cpu)
+{
+	const struct cpumask *hk_mask = housekeeping_cpumask(HK_TYPE_IO_QUEUE);
+
+	for (int i = 0; i < hctx->nr_ctx; i++) {
+		struct blk_mq_ctx *ctx = hctx->ctxs[i];
+
+		if (ctx->cpu == this_cpu)
+			continue;
+
+		/*
+		 * Check if this context has at least one online
+		 * housekeeping CPU; in this case the hardware context is
+		 * usable.
+		 */
+		if (cpumask_test_cpu(ctx->cpu, hk_mask) &&
+		    cpu_online(ctx->cpu))
+			break;
+
+		/*
+		 * The context doesn't have any online housekeeping CPUs,
+		 * but there might be an online isolated CPU mapped to
+		 * it.
+		 */
+		if (cpu_is_offline(ctx->cpu))
+			continue;
+
+		pr_warn("%s: trying to offline hctx%d but there is still an online isolcpu CPU %d mapped to it\n",
+			hctx->queue->disk->disk_name,
+			hctx->queue_num, ctx->cpu);
+		return false;
+	}
+
+	return true;
+}
+
 static bool blk_mq_hctx_has_online_cpu(struct blk_mq_hw_ctx *hctx,
 		unsigned int this_cpu)
 {
@@ -3752,6 +3789,11 @@ static int blk_mq_hctx_notify_offline(unsigned int cpu, struct hlist_node *node)
 			struct blk_mq_hw_ctx, cpuhp_online);
 	int ret = 0;
 
+	if (housekeeping_enabled(HK_TYPE_IO_QUEUE)) {
+		if (!blk_mq_hctx_can_offline_hk_cpu(hctx, cpu))
+			return -EINVAL;
+	}
+
 	if (!hctx->nr_ctx || blk_mq_hctx_has_online_cpu(hctx, cpu))
 		return 0;
 
-- 
2.51.0


^ permalink raw reply related

* [PATCH v12 10/13] blk-mq: use hk cpus only when isolcpus=io_queue is enabled
From: Aaron Tomlin @ 2026-04-22 18:52 UTC (permalink / raw)
  To: axboe, kbusch, hch, sagi, mst
  Cc: atomlin, aacraid, James.Bottomley, martin.petersen, liyihang9,
	kashyap.desai, sumit.saxena, shivasharan.srikanteshwara,
	chandrakanth.patil, sathya.prakash, sreekanth.reddy,
	suganath-prabu.subramani, ranjan.kumar, jinpu.wang, tglx, mingo,
	peterz, juri.lelli, vincent.guittot, akpm, maz, ruanjinjie,
	bigeasy, yphbchou0911, wagi, frederic, longman, chenridong, hare,
	kch, ming.lei, tom.leiming, steve, sean, chjohnst, neelx, mproche,
	nick.lange, marco.crivellari, linux-block, linux-kernel,
	virtualization, linux-nvme, linux-scsi, megaraidlinux.pdl,
	mpi3mr-linuxdrv.pdl, MPT-FusionLinux.pdl
In-Reply-To: <20260422185215.100929-1-atomlin@atomlin.com>

From: Daniel Wagner <wagi@kernel.org>

Extend the capabilities of the generic CPU to hardware queue (hctx)
mapping code, so it maps houskeeping CPUs and isolated CPUs to the
hardware queues evenly.

A hctx is only operational when there is at least one online
housekeeping CPU assigned (aka active_hctx). Thus, check the final
mapping that there is no hctx which has only offline housekeeing CPU and
online isolated CPUs.

Example mapping result:

  16 online CPUs

  isolcpus=io_queue,2-3,6-7,12-13

Queue mapping:
        hctx0: default 0 2
        hctx1: default 1 3
        hctx2: default 4 6
        hctx3: default 5 7
        hctx4: default 8 12
        hctx5: default 9 13
        hctx6: default 10
        hctx7: default 11
        hctx8: default 14
        hctx9: default 15

IRQ mapping:
        irq 42 affinity 0 effective 0  nvme0q0
        irq 43 affinity 0 effective 0  nvme0q1
        irq 44 affinity 1 effective 1  nvme0q2
        irq 45 affinity 4 effective 4  nvme0q3
        irq 46 affinity 5 effective 5  nvme0q4
        irq 47 affinity 8 effective 8  nvme0q5
        irq 48 affinity 9 effective 9  nvme0q6
        irq 49 affinity 10 effective 10  nvme0q7
        irq 50 affinity 11 effective 11  nvme0q8
        irq 51 affinity 14 effective 14  nvme0q9
        irq 52 affinity 15 effective 15  nvme0q10

A corner case is when the number of online CPUs and present CPUs
differ and the driver asks for less queues than online CPUs, e.g.

  8 online CPUs, 16 possible CPUs

  isolcpus=io_queue,2-3,6-7,12-13
  virtio_blk.num_request_queues=2

Queue mapping:
        hctx0: default 0 1 2 3 4 5 6 7 8 12 13
        hctx1: default 9 10 11 14 15

IRQ mapping
        irq 27 affinity 0 effective 0 virtio0-config
        irq 28 affinity 0-1,4-5,8 effective 5 virtio0-req.0
        irq 29 affinity 9-11,14-15 effective 0 virtio0-req.1

Noteworthy is that for the normal/default configuration (!isoclpus) the
mapping will change for systems which have non hyperthreading CPUs. The
main assignment loop will completely rely that group_mask_cpus_evenly to
do the right thing. The old code would distribute the CPUs linearly over
the hardware context:

queue mapping for /dev/nvme0n1
        hctx0: default 0 8
        hctx1: default 1 9
        hctx2: default 2 10
        hctx3: default 3 11
        hctx4: default 4 12
        hctx5: default 5 13
        hctx6: default 6 14
        hctx7: default 7 15

The assign each hardware context the map generated by the
group_mask_cpus_evenly function:

queue mapping for /dev/nvme0n1
        hctx0: default 0 1
        hctx1: default 2 3
        hctx2: default 4 5
        hctx3: default 6 7
        hctx4: default 8 9
        hctx5: default 10 11
        hctx6: default 12 13
        hctx7: default 14 15

In case of hyperthreading CPUs, the resulting map stays the same.

Signed-off-by: Daniel Wagner <wagi@kernel.org>
[atomlin:
    - Fixed absolute vs. relative hardware queue index mix-up in
      blk_mq_map_queues and validation checks; fixed typographical
      errors
    - Reduced stack frame size of blk_mq_num_queues()]
Signed-off-by: Aaron Tomlin <atomlin@atomlin.com>
---
 block/blk-mq-cpumap.c | 168 +++++++++++++++++++++++++++++++++++++-----
 1 file changed, 150 insertions(+), 18 deletions(-)

diff --git a/block/blk-mq-cpumap.c b/block/blk-mq-cpumap.c
index 8244ecf87835..f7c5f52f3b35 100644
--- a/block/blk-mq-cpumap.c
+++ b/block/blk-mq-cpumap.c
@@ -22,7 +22,11 @@ static unsigned int blk_mq_num_queues(const struct cpumask *mask,
 {
 	unsigned int num;
 
-	num = cpumask_weight(mask);
+	if (housekeeping_enabled(HK_TYPE_IO_QUEUE))
+		num = cpumask_weight_and(mask, housekeeping_cpumask(HK_TYPE_IO_QUEUE));
+	else
+		num = cpumask_weight(mask);
+
 	return min_not_zero(num, max_queues);
 }
 
@@ -31,9 +35,13 @@ static unsigned int blk_mq_num_queues(const struct cpumask *mask,
  *
  * Returns an affinity mask that represents the queue-to-CPU mapping
  * requested by the block layer based on possible CPUs.
+ * This helper takes isolcpus settings into account.
  */
 const struct cpumask *blk_mq_possible_queue_affinity(void)
 {
+	if (housekeeping_enabled(HK_TYPE_IO_QUEUE))
+		return housekeeping_cpumask(HK_TYPE_IO_QUEUE);
+
 	return cpu_possible_mask;
 }
 EXPORT_SYMBOL_GPL(blk_mq_possible_queue_affinity);
@@ -46,6 +54,14 @@ EXPORT_SYMBOL_GPL(blk_mq_possible_queue_affinity);
  */
 const struct cpumask *blk_mq_online_queue_affinity(void)
 {
+	/*
+	 * Return the stable housekeeping mask if enabled. Callers (e.g.,
+	 * the IRQ affinity core) are responsible for safely intersecting
+	 * this with a local snapshot of the online mask.
+	 */
+	if (housekeeping_enabled(HK_TYPE_IO_QUEUE))
+		return housekeeping_cpumask(HK_TYPE_IO_QUEUE);
+
 	return cpu_online_mask;
 }
 EXPORT_SYMBOL_GPL(blk_mq_online_queue_affinity);
@@ -57,7 +73,8 @@ EXPORT_SYMBOL_GPL(blk_mq_online_queue_affinity);
  *		ignored.
  *
  * Calculates the number of queues to be used for a multiqueue
- * device based on the number of possible CPUs.
+ * device based on the number of possible CPUs. This helper
+ * takes isolcpus settings into account.
  */
 unsigned int blk_mq_num_possible_queues(unsigned int max_queues)
 {
@@ -72,7 +89,8 @@ EXPORT_SYMBOL_GPL(blk_mq_num_possible_queues);
  *		ignored.
  *
  * Calculates the number of queues to be used for a multiqueue
- * device based on the number of online CPUs.
+ * device based on the number of online CPUs. This helper
+ * takes isolcpus settings into account.
  */
 unsigned int blk_mq_num_online_queues(unsigned int max_queues)
 {
@@ -80,23 +98,104 @@ unsigned int blk_mq_num_online_queues(unsigned int max_queues)
 }
 EXPORT_SYMBOL_GPL(blk_mq_num_online_queues);
 
+static bool blk_mq_validate(struct blk_mq_queue_map *qmap,
+			    const struct cpumask *active_hctx)
+{
+	/*
+	 * Verify if the mapping is usable when housekeeping
+	 * configuration is enabled
+	 */
+
+	for (int queue = 0; queue < qmap->nr_queues; queue++) {
+		int cpu;
+
+		if (cpumask_test_cpu(queue, active_hctx)) {
+			/*
+			 * This hctx has at least one online CPU thus it
+			 * is able to serve any assigned isolated CPU.
+			 */
+			continue;
+		}
+
+		/*
+		 * There is no housekeeping online CPU for this hctx, all
+		 * good as long as all non-housekeeping CPUs are also
+		 * offline.
+		 */
+		for_each_online_cpu(cpu) {
+			if (qmap->mq_map[cpu] != qmap->queue_offset + queue)
+				continue;
+
+			pr_warn("Unable to create a usable CPU-to-queue mapping with the given constraints\n");
+			return false;
+		}
+	}
+
+	return true;
+}
+
+static void blk_mq_map_fallback(struct blk_mq_queue_map *qmap)
+{
+	unsigned int cpu;
+
+	/*
+	 * Map all CPUs to the first hctx to ensure at least one online
+	 * CPU is serving it.
+	 */
+	for_each_possible_cpu(cpu)
+		qmap->mq_map[cpu] = 0;
+}
+
 void blk_mq_map_queues(struct blk_mq_queue_map *qmap)
 {
-	const struct cpumask *masks;
+	struct cpumask *masks __free(kfree) = NULL;
+	const struct cpumask *constraint;
 	unsigned int queue, cpu, nr_masks;
+	cpumask_var_t active_hctx;
 
-	masks = group_cpus_evenly(qmap->nr_queues, &nr_masks);
-	if (!masks) {
-		for_each_possible_cpu(cpu)
-			qmap->mq_map[cpu] = qmap->queue_offset;
-		return;
-	}
+	if (!zalloc_cpumask_var(&active_hctx, GFP_KERNEL))
+		goto fallback;
+
+	if (housekeeping_enabled(HK_TYPE_IO_QUEUE))
+		constraint = housekeeping_cpumask(HK_TYPE_IO_QUEUE);
+	else
+		constraint = cpu_possible_mask;
+
+	/* Map CPUs to the hardware contexts (hctx) */
+	masks = group_mask_cpus_evenly(qmap->nr_queues, constraint, &nr_masks);
+	if (!masks)
+		goto free_fallback;
 
 	for (queue = 0; queue < qmap->nr_queues; queue++) {
-		for_each_cpu(cpu, &masks[queue % nr_masks])
+		unsigned int idx = (qmap->queue_offset + queue) % nr_masks;
+
+		for_each_cpu(cpu, &masks[idx]) {
 			qmap->mq_map[cpu] = qmap->queue_offset + queue;
+
+			if (cpu_online(cpu))
+				cpumask_set_cpu(queue, active_hctx);
+		}
 	}
-	kfree(masks);
+
+	/* Map any unassigned CPU evenly to the hardware contexts (hctx) */
+	queue = cpumask_first(active_hctx);
+	for_each_cpu_andnot(cpu, cpu_possible_mask, constraint) {
+		qmap->mq_map[cpu] = qmap->queue_offset + queue;
+		queue = cpumask_next_wrap(queue, active_hctx);
+	}
+
+	if (!blk_mq_validate(qmap, active_hctx))
+		goto free_fallback;
+
+	free_cpumask_var(active_hctx);
+
+	return;
+
+free_fallback:
+	free_cpumask_var(active_hctx);
+
+fallback:
+	blk_mq_map_fallback(qmap);
 }
 EXPORT_SYMBOL_GPL(blk_mq_map_queues);
 
@@ -133,24 +232,57 @@ void blk_mq_map_hw_queues(struct blk_mq_queue_map *qmap,
 			  struct device *dev, unsigned int offset)
 
 {
-	const struct cpumask *mask;
+	cpumask_var_t active_hctx, mask;
 	unsigned int queue, cpu;
 
 	if (!dev->bus->irq_get_affinity)
 		goto fallback;
 
+	if (!zalloc_cpumask_var(&active_hctx, GFP_KERNEL))
+		goto fallback;
+
+	if (!zalloc_cpumask_var(&mask, GFP_KERNEL)) {
+		free_cpumask_var(active_hctx);
+		goto fallback;
+	}
+
+	/* Map CPUs to the hardware contexts (hctx) */
 	for (queue = 0; queue < qmap->nr_queues; queue++) {
-		mask = dev->bus->irq_get_affinity(dev, queue + offset);
-		if (!mask)
-			goto fallback;
+		const struct cpumask *affinity_mask;
 
-		for_each_cpu(cpu, mask)
+		affinity_mask = dev->bus->irq_get_affinity(dev, offset + queue);
+		if (!affinity_mask)
+			goto free_fallback;
+
+		for_each_cpu(cpu, affinity_mask) {
 			qmap->mq_map[cpu] = qmap->queue_offset + queue;
+
+			cpumask_set_cpu(cpu, mask);
+			if (cpu_online(cpu))
+				cpumask_set_cpu(queue, active_hctx);
+		}
 	}
 
+	/* Map any unassigned CPU evenly to the hardware contexts (hctx) */
+	queue = cpumask_first(active_hctx);
+	for_each_cpu_andnot(cpu, cpu_possible_mask, mask) {
+		qmap->mq_map[cpu] = qmap->queue_offset + queue;
+		queue = cpumask_next_wrap(queue, active_hctx);
+	}
+
+	if (!blk_mq_validate(qmap, active_hctx))
+		goto free_fallback;
+
+	free_cpumask_var(active_hctx);
+	free_cpumask_var(mask);
+
 	return;
 
+free_fallback:
+	free_cpumask_var(active_hctx);
+	free_cpumask_var(mask);
+
 fallback:
-	blk_mq_map_queues(qmap);
+	blk_mq_map_fallback(qmap);
 }
 EXPORT_SYMBOL_GPL(blk_mq_map_hw_queues);
-- 
2.51.0


^ permalink raw reply related

* [PATCH v12 09/13] isolation: Introduce io_queue isolcpus type
From: Aaron Tomlin @ 2026-04-22 18:52 UTC (permalink / raw)
  To: axboe, kbusch, hch, sagi, mst
  Cc: atomlin, aacraid, James.Bottomley, martin.petersen, liyihang9,
	kashyap.desai, sumit.saxena, shivasharan.srikanteshwara,
	chandrakanth.patil, sathya.prakash, sreekanth.reddy,
	suganath-prabu.subramani, ranjan.kumar, jinpu.wang, tglx, mingo,
	peterz, juri.lelli, vincent.guittot, akpm, maz, ruanjinjie,
	bigeasy, yphbchou0911, wagi, frederic, longman, chenridong, hare,
	kch, ming.lei, tom.leiming, steve, sean, chjohnst, neelx, mproche,
	nick.lange, marco.crivellari, linux-block, linux-kernel,
	virtualization, linux-nvme, linux-scsi, megaraidlinux.pdl,
	mpi3mr-linuxdrv.pdl, MPT-FusionLinux.pdl
In-Reply-To: <20260422185215.100929-1-atomlin@atomlin.com>

From: Daniel Wagner <wagi@kernel.org>

Multiqueue drivers spread I/O queues across all CPUs for optimal
performance. However, these drivers are not aware of CPU isolation
requirements and will distribute queues without considering the isolcpus
configuration.

Introduce a new isolcpus mask that allows users to define which CPUs
should have I/O queues assigned. This is similar to managed_irq, but
intended for drivers that do not use the managed IRQ infrastructure

Signed-off-by: Daniel Wagner <wagi@kernel.org>
Reviewed-by: Martin K. Petersen <martin.petersen@oracle.com>
Reviewed-by: Hannes Reinecke <hare@suse.de>
Signed-off-by: Aaron Tomlin <atomlin@atomlin.com>
---
 include/linux/sched/isolation.h | 1 +
 kernel/sched/isolation.c        | 7 +++++++
 2 files changed, 8 insertions(+)

diff --git a/include/linux/sched/isolation.h b/include/linux/sched/isolation.h
index dc3975ff1b2e..7b266fc2a405 100644
--- a/include/linux/sched/isolation.h
+++ b/include/linux/sched/isolation.h
@@ -18,6 +18,7 @@ enum hk_type {
 	HK_TYPE_MANAGED_IRQ,
 	/* Inverse of boot-time nohz_full= or isolcpus=nohz arguments */
 	HK_TYPE_KERNEL_NOISE,
+	HK_TYPE_IO_QUEUE,
 	HK_TYPE_MAX,
 
 	/*
diff --git a/kernel/sched/isolation.c b/kernel/sched/isolation.c
index ef152d401fe2..3406e3024fd4 100644
--- a/kernel/sched/isolation.c
+++ b/kernel/sched/isolation.c
@@ -16,6 +16,7 @@ enum hk_flags {
 	HK_FLAG_DOMAIN		= BIT(HK_TYPE_DOMAIN),
 	HK_FLAG_MANAGED_IRQ	= BIT(HK_TYPE_MANAGED_IRQ),
 	HK_FLAG_KERNEL_NOISE	= BIT(HK_TYPE_KERNEL_NOISE),
+	HK_FLAG_IO_QUEUE	= BIT(HK_TYPE_IO_QUEUE),
 };
 
 DEFINE_STATIC_KEY_FALSE(housekeeping_overridden);
@@ -340,6 +341,12 @@ static int __init housekeeping_isolcpus_setup(char *str)
 			continue;
 		}
 
+		if (!strncmp(str, "io_queue,", 9)) {
+			str += 9;
+			flags |= HK_FLAG_IO_QUEUE;
+			continue;
+		}
+
 		/*
 		 * Skip unknown sub-parameter and validate that it is not
 		 * containing an invalid character.
-- 
2.51.0


^ permalink raw reply related

* [PATCH v12 08/13] virtio: blk/scsi: use block layer helpers to constrain queue affinity
From: Aaron Tomlin @ 2026-04-22 18:52 UTC (permalink / raw)
  To: axboe, kbusch, hch, sagi, mst
  Cc: atomlin, aacraid, James.Bottomley, martin.petersen, liyihang9,
	kashyap.desai, sumit.saxena, shivasharan.srikanteshwara,
	chandrakanth.patil, sathya.prakash, sreekanth.reddy,
	suganath-prabu.subramani, ranjan.kumar, jinpu.wang, tglx, mingo,
	peterz, juri.lelli, vincent.guittot, akpm, maz, ruanjinjie,
	bigeasy, yphbchou0911, wagi, frederic, longman, chenridong, hare,
	kch, ming.lei, tom.leiming, steve, sean, chjohnst, neelx, mproche,
	nick.lange, marco.crivellari, linux-block, linux-kernel,
	virtualization, linux-nvme, linux-scsi, megaraidlinux.pdl,
	mpi3mr-linuxdrv.pdl, MPT-FusionLinux.pdl
In-Reply-To: <20260422185215.100929-1-atomlin@atomlin.com>

From: Daniel Wagner <wagi@kernel.org>

Ensure that IRQ affinity setup also respects the queue-to-CPU mapping
constraints provided by the block layer. This allows the virtio drivers
to avoid assigning interrupts to CPUs that the block layer has excluded
(e.g., isolated CPUs).

Signed-off-by: Daniel Wagner <wagi@kernel.org>
Reviewed-by: Martin K. Petersen <martin.petersen@oracle.com>
Reviewed-by: Hannes Reinecke <hare@suse.de>
Signed-off-by: Aaron Tomlin <atomlin@atomlin.com>
---
 drivers/block/virtio_blk.c | 4 +++-
 drivers/scsi/virtio_scsi.c | 5 ++++-
 2 files changed, 7 insertions(+), 2 deletions(-)

diff --git a/drivers/block/virtio_blk.c b/drivers/block/virtio_blk.c
index b1c9a27fe00f..9d737510454b 100644
--- a/drivers/block/virtio_blk.c
+++ b/drivers/block/virtio_blk.c
@@ -964,7 +964,9 @@ static int init_vq(struct virtio_blk *vblk)
 	unsigned short num_vqs;
 	unsigned short num_poll_vqs;
 	struct virtio_device *vdev = vblk->vdev;
-	struct irq_affinity desc = { 0, };
+	struct irq_affinity desc = {
+		.mask = blk_mq_possible_queue_affinity(),
+	};
 
 	err = virtio_cread_feature(vdev, VIRTIO_BLK_F_MQ,
 				   struct virtio_blk_config, num_queues,
diff --git a/drivers/scsi/virtio_scsi.c b/drivers/scsi/virtio_scsi.c
index 5fdaa71f0652..d0b6a137e9b7 100644
--- a/drivers/scsi/virtio_scsi.c
+++ b/drivers/scsi/virtio_scsi.c
@@ -847,7 +847,10 @@ static int virtscsi_init(struct virtio_device *vdev,
 	u32 num_vqs, num_poll_vqs, num_req_vqs;
 	struct virtqueue_info *vqs_info;
 	struct virtqueue **vqs;
-	struct irq_affinity desc = { .pre_vectors = 2 };
+	struct irq_affinity desc = {
+		.pre_vectors = 2,
+		.mask = blk_mq_possible_queue_affinity(),
+	};
 
 	num_req_vqs = vscsi->num_queues;
 	num_vqs = num_req_vqs + VIRTIO_SCSI_VQ_BASE;
-- 
2.51.0


^ permalink raw reply related


This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox