On 09/06/2026 13:18, Sumit Saxena wrote:
scsi_host_alloc() used kzalloc(), which always picks an arbitrary node.
Extend the function to accept a 'struct device *dev' parameter and use
kzalloc_node() with dev_to_node(dev) so the Scsi_Host struct lands on
the same NUMA node as the HBA, mirroring the treatment already applied
to struct scsi_device, struct scsi_target, and shost_data.

When dev is NULL (legacy ISA/platform drivers without a dma_dev) the
allocation falls back to NUMA_NO_NODE, preserving existing behaviour.

Update all in-tree callers:
   - PCI-based HBA drivers pass &pdev->dev (or the equivalent struct
     member such as &phba->pcidev->dev, &h->pdev->dev, &ha->pdev->dev)
     so their host struct is placed on the adapter's node.
   - Non-PCI drivers (ISA, Amiga, ARM PCMCIA, virtio, Hyper-V, PS3, …)
     pass NULL.
   - libfc's libfc_host_alloc() inline helper passes NULL; FC drivers
     that want NUMA awareness can open-code the call with their pdev.

Suggested-by: John Garry <[email protected]>
Signed-off-by: Sumit Saxena <[email protected]>

Wow ... I was not expecting such a large change, but admittedly I did not consider the implementation.

I did mention that pci-based adapters should already be effectively doing kzalloc_node() since the adapter driver is probed on the local NUMA node (and kmalloc first tries local NUMA allocations).

---

diff --git a/drivers/scsi/hosts.c b/drivers/scsi/hosts.c
index e047747d4ecf..e1f42be79729 100644
--- a/drivers/scsi/hosts.c
+++ b/drivers/scsi/hosts.c
@@ -403,12 +403,14 @@ static const struct device_type scsi_host_type = {
   * Return value:
   *    Pointer to a new Scsi_Host
   **/
-struct Scsi_Host *scsi_host_alloc(const struct scsi_host_template *sht, int 
privsize)
+struct Scsi_Host *scsi_host_alloc(const struct scsi_host_template *sht, int 
privsize,
+                                 struct device *dev)
  {
        struct Scsi_Host *shost;
        int index;
- shost = kzalloc(sizeof(struct Scsi_Host) + privsize, GFP_KERNEL);
+       shost = kzalloc_node(sizeof(struct Scsi_Host) + privsize, GFP_KERNEL,
+                            dev ? dev_to_node(dev) : NUMA_NO_NODE);
        if (!shost)
                return NULL;

-extern struct Scsi_Host *scsi_host_alloc(const struct scsi_host_template *, 
int);
+extern struct Scsi_Host *scsi_host_alloc(const struct scsi_host_template *sht,
+                                        int privsize, struct device *dev);
  extern int __must_check scsi_add_host_with_dma(struct Scsi_Host *,
                                               struct device *,
                                               struct device *);


scsi_add_host_with_dma() and scsi_add_host() do assignment of shost->dma_dev, so I think that could be moved to scsi_host_alloc().

I can imagine that we always know dev and dma_dev at Scsi_Host alloc time (and not just scsi_add_host()) time. However those would be very intrusive changes.

Let me consider this more. Maybe we can have a platform device version of shost alloc, as I can't imagine that we care about much more. Thanks!

Reply via email to