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!