Re: [PATCH 01/15] scsi: allocate host device

chenxiang (M)
2021-11-26T02:49:13Z

Hi Hannes,

在 2021/11/25 23:10, Hannes Reinecke 写道:
> Add a flag 'alloc_host_dev' to the SCSI host template and allocate
> a virtual scsi device if the flag is set.
> This device has the SCSI id <max_id + 1>:0, so won't clash with any
> devices the HBA might allocate. It's also excluded from scanning and
> will not show up in sysfs.
> Intention is to use this device to send internal commands to the HBA.
>
> Signed-off-by: Hannes Reinecke <hare@suse.de>
> ---
> drivers/scsi/hosts.c | 8 +++++
> drivers/scsi/scsi_scan.c | 67 +++++++++++++++++++++++++++++++++++++-
> drivers/scsi/scsi_sysfs.c | 3 +-
> include/scsi/scsi_device.h | 2 +-
> include/scsi/scsi_host.h | 21 ++++++++++++
> 5 files changed, 98 insertions(+), 3 deletions(-)
>
> diff --git a/drivers/scsi/hosts.c b/drivers/scsi/hosts.c
> index f69b77cbf538..a539fa2fb221 100644
> --- a/drivers/scsi/hosts.c
> +++ b/drivers/scsi/hosts.c
> @@ -290,6 +290,14 @@ int scsi_add_host_with_dma(struct Scsi_Host *shost, struct device *dev,
> if (error)
> goto out_del_dev;
>
> + if (sht->alloc_host_sdev) {
> + shost->shost_sdev = scsi_get_host_dev(shost);
> + if (!shost->shost_sdev) {
> + error = -ENOMEM;
> + goto out_del_dev;
> + }
> + }
> +
> scsi_proc_host_add(shost);
> scsi_autopm_put_host(shost);
> return error;
> diff --git a/drivers/scsi/scsi_scan.c b/drivers/scsi/scsi_scan.c
> index 328c0e79dfe7..e2910aa02a65 100644
> --- a/drivers/scsi/scsi_scan.c
> +++ b/drivers/scsi/scsi_scan.c
> @@ -1139,6 +1139,12 @@ static int scsi_probe_and_add_lun(struct scsi_target *starget,
> if (!sdev)
> goto out;
>
> + if (scsi_device_is_host_dev(sdev)) {
> + if (bflagsp)
> + *bflagsp = BLIST_NOLUN;
> + return SCSI_SCAN_LUN_PRESENT;
> + }
> +
> result = kmalloc(result_len, GFP_KERNEL);
> if (!result)
> goto out_free_sdev;
> @@ -1755,6 +1761,9 @@ static void scsi_sysfs_add_devices(struct Scsi_Host *shost)
> /* If device is already visible, skip adding it to sysfs */
> if (sdev->is_visible)
> continue;
> + /* Host devices should never be visible in sysfs */
> + if (scsi_device_is_host_dev(sdev))
> + continue;
> if (!scsi_host_scan_allowed(shost) ||
> scsi_sysfs_add_sdev(sdev) != 0)
> __scsi_remove_device(sdev);
> @@ -1919,12 +1928,16 @@ EXPORT_SYMBOL(scsi_scan_host);
>
> void scsi_forget_host(struct Scsi_Host *shost)
> {
> - struct scsi_device *sdev;
> + struct scsi_device *sdev, *host_sdev = NULL;
> unsigned long flags;
>
> restart:
> spin_lock_irqsave(shost->host_lock, flags);
> list_for_each_entry(sdev, &shost->__devices, siblings) {
> + if (scsi_device_is_host_dev(sdev)) {
> + host_sdev = sdev;
> + continue;
> + }
> if (sdev->sdev_state == SDEV_DEL)
> continue;
> spin_unlock_irqrestore(shost->host_lock, flags);
> @@ -1932,5 +1945,57 @@ void scsi_forget_host(struct Scsi_Host *shost)
> goto restart;
> }
> spin_unlock_irqrestore(shost->host_lock, flags);
> + /* Remove host device last, might be needed to send commands */
> + if (host_sdev)
> + __scsi_remove_device(host_sdev);
> }
>
> +/**
> + * scsi_get_host_dev - Create a virtual scsi_device to the host adapter
> + * @shost: Host that needs a scsi_device
> + *
> + * Lock status: None assumed.
> + *
> + * Returns: The scsi_device or NULL
> + *
> + * Notes:
> + * Attach a single scsi_device to the Scsi_Host. The primary aim
> + * for this device is to serve as a container from which valid
> + * scsi commands can be allocated from. Each scsi command will carry
> + * an unused/free command tag, which then can be used by the LLDD to
> + * send internal or passthrough commands without having to find a
> + * valid command tag internally.
> + */
> +struct scsi_device *scsi_get_host_dev(struct Scsi_Host *shost)
> +{
> + struct scsi_device *sdev = NULL;
> + struct scsi_target *starget;
> +
> + mutex_lock(&shost->scan_mutex);
> + if (!scsi_host_scan_allowed(shost))
> + goto out;
> + starget = scsi_alloc_target(&shost->shost_gendev, 0,
> + shost->max_id);
> + if (!starget)
> + goto out;
> +
> + sdev = scsi_alloc_sdev(starget, 0, NULL);
> + if (sdev)
> + sdev->borken = 0;
> + else
> + scsi_target_reap(starget);

Currently many scsi drivers fill some interfaces such as
target_alloc()/slave_alloc() for real disks.
When allocating scsi target and scsi device for host dev, it will also
call those interfaces, and not sure whether it breaks those drivers.
From function sas_target_alloc() (common interface in libsas layer), it
seems break it as there is no sas_rphy for host dev.