* [PATCH] [Target_Core_Mod/PSCSI]: Added support for ->create_virtdevice_from_fd()
@ 2008-10-21 20:26 Nicholas A. Bellinger
2008-10-21 23:19 ` Nicholas A. Bellinger
0 siblings, 1 reply; 2+ messages in thread
From: Nicholas A. Bellinger @ 2008-10-21 20:26 UTC (permalink / raw)
To: Linux-iSCSI.org Target Dev, LKML, Linux-fsdevel, linux-scsi
Cc: Joel Becker, Greg KH, Andrew Morton, Christoph Hellwig,
Ming Zhang, FUJITA Tomonori, H. Peter Anvin, Mike Christie
>From bd4227278bbb6ec911a15b380f2479782cbe94ce Mon Sep 17 00:00:00 2001
From: Nicholas Bellinger <nab@linux-iscsi.org>
Date: Mon, 20 Oct 2008 23:35:44 -0700
Subject: [PATCH] [Target_Core_Mod/PSCSI]: Added support for ->create_virtdevice_from_fd()
Added se_subsystem_api_t->create_virtdevice_from_fd() for locating (and
for TYPE_DISK, claiming) struct scsi_device from a passed open file descriptor
for Linux/SCSI storage objects.
This patch relies upon commit 362d4ef391699b0282dfbef3da633a561d9cbde7 for
the target_core_mod configfs infrastructure.
Here are the FIXMEs specific to configfs/fd and Linux/SCSI:
*) Determine long term status of struct gendisk->driverfs_dev for
locating struct scsi_device from struct inode for Linux/SCSI.
*) Add support for struct scsi_device's backed by character device.
*) SCSI CDROM can only be attached through the fd method when medium
is in the drive.
Signed-off-by: Nicholas A. Bellinger <nab@linux-iscsi.org>
---
drivers/lio-core/target_core_pscsi.c | 385 ++++++++++++++++++++--------------
drivers/lio-core/target_core_pscsi.h | 2 +
2 files changed, 234 insertions(+), 153 deletions(-)
diff --git a/drivers/lio-core/target_core_pscsi.c b/drivers/lio-core/target_core_pscsi.c
index f8fd2d5..be5c648 100644
--- a/drivers/lio-core/target_core_pscsi.c
+++ b/drivers/lio-core/target_core_pscsi.c
@@ -37,6 +37,7 @@
#include <linux/spinlock.h>
#include <linux/smp_lock.h>
#include <linux/genhd.h>
+#include <linux/file.h>
#include <scsi/scsi.h>
#include <scsi/scsi_device.h>
@@ -243,23 +244,8 @@ extern int pscsi_attach_hba (iscsi_portal_group_t *tpg, se_hba_t *hba, se_hbainf
PYXPRINT("CORE_HBA[%d] - Attached Parallel SCSI HBA to Generic Target Core"
" with TCQ Depth: %d MaxSectors: %hu\n", hba->hba_id,
atomic_read(&hba->max_queue_depth), max_sectors);
-#if 0
- /*
- * For Parallel SCSI we assume the devices are already attached to the
- * HBA, so go ahead and scan the bus for devices to export as iSCSI LUNs.
- */
- if ((pscsi_dev_count = pscsi_scan_devices(hba, hi)) < 0) {
- PYXPRINT("No devices present, ignoring request to add"
- " Parallel SCSI HBA %d.\n", sh->host_no);
- goto fail;
- }
-#endif
+
return(0);
-#if 0
-fail:
- scsi_host_put(sh);
- return(-1);
-#endif
}
/* pscsi_detach_hba(): (Part of se_subsystem_api_t template)
@@ -280,92 +266,6 @@ extern int pscsi_detach_hba (se_hba_t *hba)
return(0);
}
-/* pscsi_scan_devices(): (Part of se_subsystem_api_t template)
- *
- * FIXME: For <= v2.4, check what locking the midlayer does for accessing Scsi_Host->host_queue (if any?)
- */
-#if 0
-extern int pscsi_scan_devices (se_hba_t *iscsi_hba, se_hbainfo_t *hi)
-{
- int pscsi_dev_count = 0;
- int dev_flags = 0;
- se_device_t *dev;
- struct scsi_device *sd;
- struct Scsi_Host *sh = (struct Scsi_Host *) iscsi_hba->hba_ptr;
-
- spin_lock_irq(sh->host_lock);
- list_for_each_entry(sd, &sh->__devices, siblings) {
- if (sd->type == TYPE_DISK) {
- if (scsi_device_get(sd))
- continue;
-
- spin_unlock_irq(sh->host_lock);
-
- if (pscsi_check_sd(sd) < 0) {
- spin_lock_irq(sh->host_lock);
- scsi_device_put(sd);
- continue;
- }
-
- /*
- * In some cases (namely the iSCSI Initiator Case) we want to
- * grab exclusive access to the underlying Linux block device
- * immediately at this point. We use parameter that is passed
- * with addhbatotarget to determine when to claim for this case.
- */
- if (hi->os_claim_devices)
- if (!(pscsi_claim_sd(sd))) {
- dev_flags |= DF_CLAIMED_BLOCKDEV;
- dev_flags |= DF_PERSISTENT_CLAIMED_BLOCKDEV;
- }
-
- dev = pscsi_add_device_to_list(iscsi_hba, sd, dev_flags);
-
- if (dev_flags & DF_CLAIMED_BLOCKDEV) {
- dev_flags &= ~DF_CLAIMED_BLOCKDEV;
- dev_flags &= ~DF_PERSISTENT_CLAIMED_BLOCKDEV;
- }
-
- spin_lock_irq(sh->host_lock);
-
- if (!dev) {
- scsi_device_put(sd);
- continue;
- }
-
- pscsi_dev_count++;
- continue;
- }
-
- /*
- * We may need to do peripheral-type specific checking of access counts.
- */
-//#warning FIXME v2.8: Check usage of scsi_device_get() for non TYPE_DISK
- if (sd->type == TYPE_ROM || sd->type == TYPE_TAPE || sd->type == TYPE_MEDIUM_CHANGER) {
- spin_unlock_irq(sh->host_lock);
- dev = pscsi_add_device_to_list(iscsi_hba, sd, dev_flags);
- spin_lock_irq(sh->host_lock);
-
- if (!dev)
- continue;
-
- pscsi_dev_count++;
- continue;
- }
-
- }
- spin_unlock_irq(sh->host_lock);
-
- if (!pscsi_dev_count)
- return(-1);
-
- PYXPRINT("iSCSI_PSCSI[%d] - Detected %d Parallel SCSI Devices\n",
- sh->host_no, pscsi_dev_count);
-
- return(pscsi_dev_count);
-}
-#endif
-
/* pscsi_add_device_to_list():
*
* FIXME: We are going to want to increment struct scsi_device->access_count
@@ -504,13 +404,105 @@ extern void *pscsi_allocate_virtdevice (se_hba_t *hba, const char *name)
return((void *)pdv);
}
+/*
+ * Called with struct Scsi_Host->host_lock called.
+ */
+extern se_device_t *pscsi_create_type_disk (struct scsi_device *sd, pscsi_dev_virt_t *pdv, se_hba_t *hba)
+{
+ se_device_t *dev;
+ struct Scsi_Host *sh = sd->host;
+ u32 dev_flags = 0;
+
+ if (sd->type != TYPE_DISK)
+ return(NULL);
+
+ if (scsi_device_get(sd)) {
+ printk(KERN_ERR "scsi_device_get() failed for %d:%d:%d:%d\n",
+ sh->host_no, sd->channel, sd->id, sd->lun);
+ spin_unlock_irq(sh->host_lock);
+ return(NULL);
+ }
+ spin_unlock_irq(sh->host_lock);
+
+ if (pscsi_check_sd(sd) < 0) {
+ scsi_device_put(sd);
+ printk(KERN_ERR "pscsi_check_sd() failed for %d:%d:%d:%d\n",
+ sh->host_no, sd->channel, sd->id, sd->lun);
+ return(NULL);
+ }
+ if (!(pscsi_claim_sd(sd))) {
+ dev_flags |= DF_CLAIMED_BLOCKDEV;
+ dev_flags |= DF_PERSISTENT_CLAIMED_BLOCKDEV;
+ }
+ if (!(dev = pscsi_add_device_to_list(hba, pdv, sd, dev_flags))) {
+ scsi_device_put(sd);
+ return(NULL);
+ }
+ PYXPRINT("CORE_PSCSI[%d] - Added TYPE_DISK for %d:%d:%d\n",
+ sh->host_no, sd->channel, sd->id, sd->lun);
+
+ return(dev);
+}
+
+/*
+ * Called with struct Scsi_Host->host_lock called.
+ */
+extern se_device_t *pscsi_create_type_rom (struct scsi_device *sd, pscsi_dev_virt_t *pdv, se_hba_t *hba)
+{
+ se_device_t *dev;
+ struct Scsi_Host *sh = sd->host;
+ u32 dev_flags = 0;
+
+ if (sd->type != TYPE_ROM)
+ return(NULL);
+
+ if (scsi_device_get(sd)) {
+ printk(KERN_ERR "scsi_device_get() failed for %d:%d:%d:%d\n",
+ sh->host_no, sd->channel, sd->id, sd->lun);
+ spin_unlock_irq(sh->host_lock);
+ return(NULL);
+ }
+ spin_unlock_irq(sh->host_lock);
+
+ if (!(dev = pscsi_add_device_to_list(hba, pdv, sd, dev_flags))) {
+ scsi_device_put(sd);
+ return(NULL);
+ }
+ PYXPRINT("CORE_PSCSI[%d] - Added Type: %s for %d:%d:%d\n",
+ sh->host_no, scsi_device_type(sd->type), sd->channel,
+ sd->id, sd->lun);
+
+ return(dev);
+}
+
+/*
+ *Called with struct Scsi_Host->host_lock called.
+ */
+extern se_device_t *pscsi_create_type_other (struct scsi_device *sd, pscsi_dev_virt_t *pdv, se_hba_t *hba)
+{
+ se_device_t *dev;
+ struct Scsi_Host *sh = sd->host;
+ u32 dev_flags = 0;
+
+ if ((sd->type == TYPE_DISK) || (sd->type == TYPE_ROM))
+ return(NULL);
+ spin_unlock_irq(sh->host_lock);
+
+ if (!(dev = pscsi_add_device_to_list(hba, pdv, sd, dev_flags)))
+ return(NULL);
+
+ PYXPRINT("CORE_PSCSI[%d] - Added Type: %s for %d:%d:%d\n",
+ sh->host_no, scsi_device_type(sd->type), sd->channel,
+ sd->id, sd->lun);
+
+ return(dev);
+}
+
extern se_device_t *pscsi_create_virtdevice (se_hba_t *hba, void *p)
{
pscsi_dev_virt_t *pdv = (pscsi_dev_virt_t *)p;
- se_device_t *dev;
struct scsi_device *sd;
struct Scsi_Host *sh = (struct Scsi_Host *) hba->hba_ptr;
- u32 dev_flags = 0;
if (!(pdv)) {
printk(KERN_ERR "Unable to locate pscsi_dev_virt_t parameter\n");
@@ -523,54 +515,17 @@ extern se_device_t *pscsi_create_virtdevice (se_hba_t *hba, void *p)
!(pdv->pdv_target_id == sd->id) ||
!(pdv->pdv_lun_id == sd->lun))
continue;
-
- if (sd->type == TYPE_DISK) {
- if (scsi_device_get(sd)) {
- spin_unlock_irq(sh->host_lock);
- printk(KERN_ERR "scsi_device_get() failed for %d:%d:%d:%d\n",
- sh->host_no, sd->channel, sd->id, sd->lun);
- return(NULL);
- }
- spin_unlock_irq(sh->host_lock);
-
- if (pscsi_check_sd(sd) < 0) {
- scsi_device_put(sd);
- printk(KERN_ERR "pscsi_check_sd() failed for %d:%d:%d:%d\n",
- sh->host_no, sd->channel, sd->id, sd->lun);
- return(NULL);
- }
-#warning FIXME: Is this already being done inside target_core_mod..?
- if (!(pscsi_claim_sd(sd))) {
- dev_flags |= DF_CLAIMED_BLOCKDEV;
- dev_flags |= DF_PERSISTENT_CLAIMED_BLOCKDEV;
- }
-
- if (!(dev = pscsi_add_device_to_list(hba, pdv, sd, dev_flags))) {
- scsi_device_put(sd);
- return(NULL);
- }
- PYXPRINT("CORE_PSCSI[%d] - Added TYPE_DISK for %d:%d:%d\n",
- sh->host_no, sd->channel, sd->id, sd->lun);
-
- return(dev);
- }
-#warning FIXME: Can all NON TYPE_DISK be handled this way..?
- if ((sd->type == TYPE_ROM) ||
- (sd->type == TYPE_TAPE) ||
- (sd->type == TYPE_MEDIUM_CHANGER)) {
- spin_unlock_irq(sh->host_lock);
-
- if (!(dev = pscsi_add_device_to_list(hba, pdv, sd, dev_flags)))
- return(NULL);
-
- PYXPRINT("CORE_PSCSI[%d] - Added TYPE_DISK for %d:%d:%d\n",
- sh->host_no, sd->channel, sd->id, sd->lun);
-
- return(dev);
+ /*
+ * Functions will release struct scsi_host->host_lock
+ */
+ switch (sd->type) {
+ case TYPE_DISK:
+ return(pscsi_create_type_disk(sd, pdv, hba));
+ case TYPE_ROM:
+ return(pscsi_create_type_rom(sd, pdv, hba));
+ default:
+ return(pscsi_create_type_other(sd, pdv, hba));
}
-
- printk(KERN_ERR "Unable to process SCSI device type: %d\n", sd->type);
- return(NULL);
}
spin_unlock_irq(sh->host_lock);
@@ -672,8 +627,10 @@ extern void pscsi_free_device (void *p)
pscsi_dev_virt_t *pdv = (pscsi_dev_virt_t *) p;
struct scsi_device *sd = (struct scsi_device *) pdv->pdv_sd;
- if (sd && (sd->type == TYPE_DISK)) {
- scsi_device_put(sd);
+ if (sd) {
+ if ((sd->type == TYPE_DISK) || (sd->type == TYPE_ROM))
+ scsi_device_put(sd);
+
pdv->pdv_sd = NULL;
}
@@ -1011,6 +968,128 @@ extern ssize_t pscsi_show_configfs_dev_params (se_hba_t *hba, se_subsystem_dev_t
return((ssize_t)bl);
}
+extern se_device_t *pscsi_create_virtdevice_from_fd (
+ se_subsystem_dev_t *se_dev,
+ const char *page)
+{
+ pscsi_dev_virt_t *pdv = (pscsi_dev_virt_t *) se_dev->se_dev_su_ptr;
+ se_device_t *dev = NULL;
+ se_hba_t *hba = se_dev->se_dev_hba;
+ struct block_device *bd = NULL;
+ struct file *filp;
+ struct gendisk *gd = NULL;
+ struct inode *inode;
+ struct scsi_device *sd = NULL;
+ struct Scsi_Host *sh = (struct Scsi_Host *)hba->hba_ptr;
+ char *p = (char *)page;
+ int fd;
+
+ fd = simple_strtol(p, &p, 0);
+ if ((fd < 3 || fd > 7)) {
+ printk(KERN_ERR "PSCSI: Illegal value of file descriptor: %d\n", fd);
+ return(ERR_PTR(-EINVAL));
+ }
+ if (!(filp = fget(fd))) {
+ printk(KERN_ERR "PSCSI: Unable to fget() fd: %d\n", fd);
+ return(ERR_PTR(-EBADF));
+ }
+ if (!(inode = igrab(filp->f_mapping->host))) {
+ printk(KERN_ERR "PSCSI: Unable to locate struct inode for struct"
+ " block_device fd\n");
+ fput(filp);
+ return(ERR_PTR(-EINVAL));
+ }
+ /*
+ * Look for struct scsi_device with a backing struct block_device.
+ *
+ * This means struct scsi_device->type == TYPE_DISK && TYPE_ROM.
+ */
+ if (S_ISBLK(inode->i_mode)) {
+ if (!(bd = I_BDEV(filp->f_mapping->host))) {
+ printk(KERN_ERR "PSCSI: Unable to locate struct"
+ " block_device from I_BDEV()\n");
+ iput(inode);
+ fput(filp);
+ return(ERR_PTR(-EINVAL));
+ }
+ if (!(gd = bd->bd_disk)) {
+ printk(KERN_ERR "PSCSI: Unable to locate struct gendisk"
+ " from struct block_device\n");
+ iput(inode);
+ fput(filp);
+ return(ERR_PTR(-EINVAL));
+ }
+ /*
+ * This struct gendisk->driver_fs() is marked as "// remove'
+ * in include/linux/genhd.h..
+ *
+ * Currently in drivers/scsi/s[d,r].c:s[d,r]_probe(), this
+ * pointer gets set by struct scsi_device->sdev_gendev.
+ *
+ * Is there a better way to locate struct scsi_device from
+ * struct inode..?
+ */
+ if (!(gd->driverfs_dev)) {
+ printk(KERN_ERR "PSCSI: struct gendisk->driverfs_dev"
+ " is NULL!\n");
+ iput(inode);
+ fput(filp);
+ return(ERR_PTR(-EINVAL));
+ }
+ if (!(sd = to_scsi_device(gd->driverfs_dev))) {
+ printk(KERN_ERR "PSCSI: Unable to locate struct scsi_device"
+ " from struct gendisk->driverfs_dev\n");
+ iput(inode);
+ fput(filp);
+ return(ERR_PTR(-EINVAL));
+ }
+ if (sd->host != sh) {
+ printk(KERN_ERR "PSCSI: Trying to attach scsi_device"
+ " Host ID: %d, but se_hba_t has SCSI Host ID: %d\n",
+ sd->host->host_no, sh->host_no);
+ iput(inode);
+ fput(filp);
+ return(ERR_PTR(-EINVAL));
+ }
+ /*
+ * pscsi_create_type_[disk,rom]() will release host_lock..
+ */
+ spin_lock_irq(sh->host_lock);
+ switch (sd->type) {
+ case TYPE_DISK:
+ dev = pscsi_create_type_disk(sd, pdv, se_dev->se_dev_hba);
+ break;
+ case TYPE_ROM:
+ dev = pscsi_create_type_rom(sd, pdv, se_dev->se_dev_hba);
+ break;
+ default:
+ printk(KERN_ERR "PSCSI: Unable to handle type S_ISBLK() =="
+ " TRUE Type: %s\n", scsi_device_type(sd->type));
+ spin_unlock_irq(sh->host_lock);
+ iput(inode);
+ fput(filp);
+ return(ERR_PTR(-ENOSYS));
+ }
+ } else if (S_ISCHR(inode->i_mode)) {
+#warning FIXME: Figure how to get struct scsi_device from character device's struct inode
+ printk(KERN_ERR "SCSI Character Device unsupported via"
+ " configfs/fd method. Use configfs/control instead\n");
+ iput(inode);
+ fput(filp);
+ return(ERR_PTR(-ENOSYS));
+ } else {
+ printk(KERN_ERR "PSCSI: File destriptor is not SCSI block or character"
+ " device, ignoring\n");
+ iput(inode);
+ fput(filp);
+ return(ERR_PTR(-ENODEV));
+ }
+
+ iput(inode);
+ fput(filp);
+ return(dev);
+}
+
extern int pscsi_check_dev_params (se_hba_t *hba, struct iscsi_target *t, se_dev_transport_info_t *dti)
{
if (!(t->hba_params_set & PARAM_HBA_SCSI_CHANNEL_ID)) {
diff --git a/drivers/lio-core/target_core_pscsi.h b/drivers/lio-core/target_core_pscsi.h
index 74d444b..f2883d8 100644
--- a/drivers/lio-core/target_core_pscsi.h
+++ b/drivers/lio-core/target_core_pscsi.h
@@ -75,6 +75,7 @@ extern int pscsi_check_hba_params (se_hbainfo_t *, struct iscsi_target *, int);
extern ssize_t pscsi_set_configfs_dev_params (se_hba_t *, se_subsystem_dev_t *, const char *, ssize_t);
extern ssize_t pscsi_check_configfs_dev_params (se_hba_t *, se_subsystem_dev_t *);
extern ssize_t pscsi_show_configfs_dev_params (se_hba_t *, se_subsystem_dev_t *, char *);
+extern se_device_t *pscsi_create_virtdevice_from_fd (se_subsystem_dev_t *, const char *);
extern int pscsi_check_dev_params (se_hba_t *, struct iscsi_target *, se_dev_transport_info_t *);
extern void pscsi_get_plugin_info (void *, char *, int *);
extern void pscsi_get_hba_info (se_hba_t *, char *, int *);
@@ -166,6 +167,7 @@ se_subsystem_spc_t pscsi_template_spc = ISCSI_PSCSI_SPC;
check_configfs_dev_params: pscsi_check_configfs_dev_params, \
set_configfs_dev_params: pscsi_set_configfs_dev_params, \
show_configfs_dev_params: pscsi_show_configfs_dev_params, \
+ create_virtdevice_from_fd: pscsi_create_virtdevice_from_fd, \
check_dev_params: pscsi_check_dev_params, \
get_plugin_info: pscsi_get_plugin_info, \
get_hba_info: pscsi_get_hba_info, \
--
1.5.4.1
^ permalink raw reply related [flat|nested] 2+ messages in thread
* Re: [PATCH] [Target_Core_Mod/PSCSI]: Added support for ->create_virtdevice_from_fd()
2008-10-21 20:26 [PATCH] [Target_Core_Mod/PSCSI]: Added support for ->create_virtdevice_from_fd() Nicholas A. Bellinger
@ 2008-10-21 23:19 ` Nicholas A. Bellinger
0 siblings, 0 replies; 2+ messages in thread
From: Nicholas A. Bellinger @ 2008-10-21 23:19 UTC (permalink / raw)
To: linux-iscsi-target-dev; +Cc: LKML, Linux-fsdevel, linux-scsi
One follow up "cleanup" commit for support FD export via Linux/PSCSI..
>From a9ca407d4babc04b6fb67635ec4da34b2a1e1d6e Mon Sep 17 00:00:00 2001
From: Nicholas Bellinger <nab@linux-iscsi.org>
Date: Tue, 21 Oct 2008 16:06:19 -0700
Subject: [PATCH] [Target_Core_Mod/PSCSI]: Remove debugging tests from struct scsi_device->type
Remove incorrect and unnecessary debugging for struct scsi_device->type checks
in pscsi_create_type_[disk,rom,other]()
Signed-off-by: Nicholas A. Bellinger <nab@linux-iscsi.org>
---
drivers/lio-core/target_core_pscsi.c | 9 ---------
1 files changed, 0 insertions(+), 9 deletions(-)
diff --git a/drivers/lio-core/target_core_pscsi.c b/drivers/lio-core/target_core_pscsi.c
index be5c648..045bda8 100644
--- a/drivers/lio-core/target_core_pscsi.c
+++ b/drivers/lio-core/target_core_pscsi.c
@@ -413,9 +413,6 @@ extern se_device_t *pscsi_create_type_disk (struct scsi_device *sd, pscsi_dev_vi
struct Scsi_Host *sh = sd->host;
u32 dev_flags = 0;
- if (sd->type != TYPE_DISK)
- return(NULL);
-
if (scsi_device_get(sd)) {
printk(KERN_ERR "scsi_device_get() failed for %d:%d:%d:%d\n",
sh->host_no, sd->channel, sd->id, sd->lun);
@@ -453,9 +450,6 @@ extern se_device_t *pscsi_create_type_rom (struct scsi_device *sd, pscsi_dev_vir
struct Scsi_Host *sh = sd->host;
u32 dev_flags = 0;
- if (sd->type != TYPE_ROM)
- return(NULL);
-
if (scsi_device_get(sd)) {
printk(KERN_ERR "scsi_device_get() failed for %d:%d:%d:%d\n",
sh->host_no, sd->channel, sd->id, sd->lun);
@@ -484,10 +478,7 @@ extern se_device_t *pscsi_create_type_other (struct scsi_device *sd, pscsi_dev_v
struct Scsi_Host *sh = sd->host;
u32 dev_flags = 0;
- if ((sd->type == TYPE_DISK) || (sd->type == TYPE_ROM))
- return(NULL);
spin_unlock_irq(sh->host_lock);
-
if (!(dev = pscsi_add_device_to_list(hba, pdv, sd, dev_flags)))
return(NULL);
--
1.5.4.1
On Tue, 2008-10-21 at 13:26 -0700, Nicholas A. Bellinger wrote:
> >From bd4227278bbb6ec911a15b380f2479782cbe94ce Mon Sep 17 00:00:00 2001
> From: Nicholas Bellinger <nab@linux-iscsi.org>
> Date: Mon, 20 Oct 2008 23:35:44 -0700
> Subject: [PATCH] [Target_Core_Mod/PSCSI]: Added support for ->create_virtdevice_from_fd()
>
> Added se_subsystem_api_t->create_virtdevice_from_fd() for locating (and
> for TYPE_DISK, claiming) struct scsi_device from a passed open file descriptor
> for Linux/SCSI storage objects.
>
> This patch relies upon commit 362d4ef391699b0282dfbef3da633a561d9cbde7 for
> the target_core_mod configfs infrastructure.
>
> Here are the FIXMEs specific to configfs/fd and Linux/SCSI:
>
> *) Determine long term status of struct gendisk->driverfs_dev for
> locating struct scsi_device from struct inode for Linux/SCSI.
> *) Add support for struct scsi_device's backed by character device.
> *) SCSI CDROM can only be attached through the fd method when medium
> is in the drive.
>
> Signed-off-by: Nicholas A. Bellinger <nab@linux-iscsi.org>
> ---
> drivers/lio-core/target_core_pscsi.c | 385 ++++++++++++++++++++--------------
> drivers/lio-core/target_core_pscsi.h | 2 +
> 2 files changed, 234 insertions(+), 153 deletions(-)
>
> diff --git a/drivers/lio-core/target_core_pscsi.c b/drivers/lio-core/target_core_pscsi.c
> index f8fd2d5..be5c648 100644
> --- a/drivers/lio-core/target_core_pscsi.c
> +++ b/drivers/lio-core/target_core_pscsi.c
> @@ -37,6 +37,7 @@
> #include <linux/spinlock.h>
> #include <linux/smp_lock.h>
> #include <linux/genhd.h>
> +#include <linux/file.h>
>
> #include <scsi/scsi.h>
> #include <scsi/scsi_device.h>
> @@ -243,23 +244,8 @@ extern int pscsi_attach_hba (iscsi_portal_group_t *tpg, se_hba_t *hba, se_hbainf
> PYXPRINT("CORE_HBA[%d] - Attached Parallel SCSI HBA to Generic Target Core"
> " with TCQ Depth: %d MaxSectors: %hu\n", hba->hba_id,
> atomic_read(&hba->max_queue_depth), max_sectors);
> -#if 0
> - /*
> - * For Parallel SCSI we assume the devices are already attached to the
> - * HBA, so go ahead and scan the bus for devices to export as iSCSI LUNs.
> - */
> - if ((pscsi_dev_count = pscsi_scan_devices(hba, hi)) < 0) {
> - PYXPRINT("No devices present, ignoring request to add"
> - " Parallel SCSI HBA %d.\n", sh->host_no);
> - goto fail;
> - }
> -#endif
> +
> return(0);
> -#if 0
> -fail:
> - scsi_host_put(sh);
> - return(-1);
> -#endif
> }
>
> /* pscsi_detach_hba(): (Part of se_subsystem_api_t template)
> @@ -280,92 +266,6 @@ extern int pscsi_detach_hba (se_hba_t *hba)
> return(0);
> }
>
> -/* pscsi_scan_devices(): (Part of se_subsystem_api_t template)
> - *
> - * FIXME: For <= v2.4, check what locking the midlayer does for accessing Scsi_Host->host_queue (if any?)
> - */
> -#if 0
> -extern int pscsi_scan_devices (se_hba_t *iscsi_hba, se_hbainfo_t *hi)
> -{
> - int pscsi_dev_count = 0;
> - int dev_flags = 0;
> - se_device_t *dev;
> - struct scsi_device *sd;
> - struct Scsi_Host *sh = (struct Scsi_Host *) iscsi_hba->hba_ptr;
> -
> - spin_lock_irq(sh->host_lock);
> - list_for_each_entry(sd, &sh->__devices, siblings) {
> - if (sd->type == TYPE_DISK) {
> - if (scsi_device_get(sd))
> - continue;
> -
> - spin_unlock_irq(sh->host_lock);
> -
> - if (pscsi_check_sd(sd) < 0) {
> - spin_lock_irq(sh->host_lock);
> - scsi_device_put(sd);
> - continue;
> - }
> -
> - /*
> - * In some cases (namely the iSCSI Initiator Case) we want to
> - * grab exclusive access to the underlying Linux block device
> - * immediately at this point. We use parameter that is passed
> - * with addhbatotarget to determine when to claim for this case.
> - */
> - if (hi->os_claim_devices)
> - if (!(pscsi_claim_sd(sd))) {
> - dev_flags |= DF_CLAIMED_BLOCKDEV;
> - dev_flags |= DF_PERSISTENT_CLAIMED_BLOCKDEV;
> - }
> -
> - dev = pscsi_add_device_to_list(iscsi_hba, sd, dev_flags);
> -
> - if (dev_flags & DF_CLAIMED_BLOCKDEV) {
> - dev_flags &= ~DF_CLAIMED_BLOCKDEV;
> - dev_flags &= ~DF_PERSISTENT_CLAIMED_BLOCKDEV;
> - }
> -
> - spin_lock_irq(sh->host_lock);
> -
> - if (!dev) {
> - scsi_device_put(sd);
> - continue;
> - }
> -
> - pscsi_dev_count++;
> - continue;
> - }
> -
> - /*
> - * We may need to do peripheral-type specific checking of access counts.
> - */
> -//#warning FIXME v2.8: Check usage of scsi_device_get() for non TYPE_DISK
> - if (sd->type == TYPE_ROM || sd->type == TYPE_TAPE || sd->type == TYPE_MEDIUM_CHANGER) {
> - spin_unlock_irq(sh->host_lock);
> - dev = pscsi_add_device_to_list(iscsi_hba, sd, dev_flags);
> - spin_lock_irq(sh->host_lock);
> -
> - if (!dev)
> - continue;
> -
> - pscsi_dev_count++;
> - continue;
> - }
> -
> - }
> - spin_unlock_irq(sh->host_lock);
> -
> - if (!pscsi_dev_count)
> - return(-1);
> -
> - PYXPRINT("iSCSI_PSCSI[%d] - Detected %d Parallel SCSI Devices\n",
> - sh->host_no, pscsi_dev_count);
> -
> - return(pscsi_dev_count);
> -}
> -#endif
> -
> /* pscsi_add_device_to_list():
> *
> * FIXME: We are going to want to increment struct scsi_device->access_count
> @@ -504,13 +404,105 @@ extern void *pscsi_allocate_virtdevice (se_hba_t *hba, const char *name)
> return((void *)pdv);
> }
>
> +/*
> + * Called with struct Scsi_Host->host_lock called.
> + */
> +extern se_device_t *pscsi_create_type_disk (struct scsi_device *sd, pscsi_dev_virt_t *pdv, se_hba_t *hba)
> +{
> + se_device_t *dev;
> + struct Scsi_Host *sh = sd->host;
> + u32 dev_flags = 0;
> +
> + if (sd->type != TYPE_DISK)
> + return(NULL);
> +
> + if (scsi_device_get(sd)) {
> + printk(KERN_ERR "scsi_device_get() failed for %d:%d:%d:%d\n",
> + sh->host_no, sd->channel, sd->id, sd->lun);
> + spin_unlock_irq(sh->host_lock);
> + return(NULL);
> + }
> + spin_unlock_irq(sh->host_lock);
> +
> + if (pscsi_check_sd(sd) < 0) {
> + scsi_device_put(sd);
> + printk(KERN_ERR "pscsi_check_sd() failed for %d:%d:%d:%d\n",
> + sh->host_no, sd->channel, sd->id, sd->lun);
> + return(NULL);
> + }
> + if (!(pscsi_claim_sd(sd))) {
> + dev_flags |= DF_CLAIMED_BLOCKDEV;
> + dev_flags |= DF_PERSISTENT_CLAIMED_BLOCKDEV;
> + }
> + if (!(dev = pscsi_add_device_to_list(hba, pdv, sd, dev_flags))) {
> + scsi_device_put(sd);
> + return(NULL);
> + }
> + PYXPRINT("CORE_PSCSI[%d] - Added TYPE_DISK for %d:%d:%d\n",
> + sh->host_no, sd->channel, sd->id, sd->lun);
> +
> + return(dev);
> +}
> +
> +/*
> + * Called with struct Scsi_Host->host_lock called.
> + */
> +extern se_device_t *pscsi_create_type_rom (struct scsi_device *sd, pscsi_dev_virt_t *pdv, se_hba_t *hba)
> +{
> + se_device_t *dev;
> + struct Scsi_Host *sh = sd->host;
> + u32 dev_flags = 0;
> +
> + if (sd->type != TYPE_ROM)
> + return(NULL);
> +
> + if (scsi_device_get(sd)) {
> + printk(KERN_ERR "scsi_device_get() failed for %d:%d:%d:%d\n",
> + sh->host_no, sd->channel, sd->id, sd->lun);
> + spin_unlock_irq(sh->host_lock);
> + return(NULL);
> + }
> + spin_unlock_irq(sh->host_lock);
> +
> + if (!(dev = pscsi_add_device_to_list(hba, pdv, sd, dev_flags))) {
> + scsi_device_put(sd);
> + return(NULL);
> + }
> + PYXPRINT("CORE_PSCSI[%d] - Added Type: %s for %d:%d:%d\n",
> + sh->host_no, scsi_device_type(sd->type), sd->channel,
> + sd->id, sd->lun);
> +
> + return(dev);
> +}
> +
> +/*
> + *Called with struct Scsi_Host->host_lock called.
> + */
> +extern se_device_t *pscsi_create_type_other (struct scsi_device *sd, pscsi_dev_virt_t *pdv, se_hba_t *hba)
> +{
> + se_device_t *dev;
> + struct Scsi_Host *sh = sd->host;
> + u32 dev_flags = 0;
> +
> + if ((sd->type == TYPE_DISK) || (sd->type == TYPE_ROM))
> + return(NULL);
> + spin_unlock_irq(sh->host_lock);
> +
> + if (!(dev = pscsi_add_device_to_list(hba, pdv, sd, dev_flags)))
> + return(NULL);
> +
> + PYXPRINT("CORE_PSCSI[%d] - Added Type: %s for %d:%d:%d\n",
> + sh->host_no, scsi_device_type(sd->type), sd->channel,
> + sd->id, sd->lun);
> +
> + return(dev);
> +}
> +
> extern se_device_t *pscsi_create_virtdevice (se_hba_t *hba, void *p)
> {
> pscsi_dev_virt_t *pdv = (pscsi_dev_virt_t *)p;
> - se_device_t *dev;
> struct scsi_device *sd;
> struct Scsi_Host *sh = (struct Scsi_Host *) hba->hba_ptr;
> - u32 dev_flags = 0;
>
> if (!(pdv)) {
> printk(KERN_ERR "Unable to locate pscsi_dev_virt_t parameter\n");
> @@ -523,54 +515,17 @@ extern se_device_t *pscsi_create_virtdevice (se_hba_t *hba, void *p)
> !(pdv->pdv_target_id == sd->id) ||
> !(pdv->pdv_lun_id == sd->lun))
> continue;
> -
> - if (sd->type == TYPE_DISK) {
> - if (scsi_device_get(sd)) {
> - spin_unlock_irq(sh->host_lock);
> - printk(KERN_ERR "scsi_device_get() failed for %d:%d:%d:%d\n",
> - sh->host_no, sd->channel, sd->id, sd->lun);
> - return(NULL);
> - }
> - spin_unlock_irq(sh->host_lock);
> -
> - if (pscsi_check_sd(sd) < 0) {
> - scsi_device_put(sd);
> - printk(KERN_ERR "pscsi_check_sd() failed for %d:%d:%d:%d\n",
> - sh->host_no, sd->channel, sd->id, sd->lun);
> - return(NULL);
> - }
> -#warning FIXME: Is this already being done inside target_core_mod..?
> - if (!(pscsi_claim_sd(sd))) {
> - dev_flags |= DF_CLAIMED_BLOCKDEV;
> - dev_flags |= DF_PERSISTENT_CLAIMED_BLOCKDEV;
> - }
> -
> - if (!(dev = pscsi_add_device_to_list(hba, pdv, sd, dev_flags))) {
> - scsi_device_put(sd);
> - return(NULL);
> - }
> - PYXPRINT("CORE_PSCSI[%d] - Added TYPE_DISK for %d:%d:%d\n",
> - sh->host_no, sd->channel, sd->id, sd->lun);
> -
> - return(dev);
> - }
> -#warning FIXME: Can all NON TYPE_DISK be handled this way..?
> - if ((sd->type == TYPE_ROM) ||
> - (sd->type == TYPE_TAPE) ||
> - (sd->type == TYPE_MEDIUM_CHANGER)) {
> - spin_unlock_irq(sh->host_lock);
> -
> - if (!(dev = pscsi_add_device_to_list(hba, pdv, sd, dev_flags)))
> - return(NULL);
> -
> - PYXPRINT("CORE_PSCSI[%d] - Added TYPE_DISK for %d:%d:%d\n",
> - sh->host_no, sd->channel, sd->id, sd->lun);
> -
> - return(dev);
> + /*
> + * Functions will release struct scsi_host->host_lock
> + */
> + switch (sd->type) {
> + case TYPE_DISK:
> + return(pscsi_create_type_disk(sd, pdv, hba));
> + case TYPE_ROM:
> + return(pscsi_create_type_rom(sd, pdv, hba));
> + default:
> + return(pscsi_create_type_other(sd, pdv, hba));
> }
> -
> - printk(KERN_ERR "Unable to process SCSI device type: %d\n", sd->type);
> - return(NULL);
> }
> spin_unlock_irq(sh->host_lock);
>
> @@ -672,8 +627,10 @@ extern void pscsi_free_device (void *p)
> pscsi_dev_virt_t *pdv = (pscsi_dev_virt_t *) p;
> struct scsi_device *sd = (struct scsi_device *) pdv->pdv_sd;
>
> - if (sd && (sd->type == TYPE_DISK)) {
> - scsi_device_put(sd);
> + if (sd) {
> + if ((sd->type == TYPE_DISK) || (sd->type == TYPE_ROM))
> + scsi_device_put(sd);
> +
> pdv->pdv_sd = NULL;
> }
>
> @@ -1011,6 +968,128 @@ extern ssize_t pscsi_show_configfs_dev_params (se_hba_t *hba, se_subsystem_dev_t
> return((ssize_t)bl);
> }
>
> +extern se_device_t *pscsi_create_virtdevice_from_fd (
> + se_subsystem_dev_t *se_dev,
> + const char *page)
> +{
> + pscsi_dev_virt_t *pdv = (pscsi_dev_virt_t *) se_dev->se_dev_su_ptr;
> + se_device_t *dev = NULL;
> + se_hba_t *hba = se_dev->se_dev_hba;
> + struct block_device *bd = NULL;
> + struct file *filp;
> + struct gendisk *gd = NULL;
> + struct inode *inode;
> + struct scsi_device *sd = NULL;
> + struct Scsi_Host *sh = (struct Scsi_Host *)hba->hba_ptr;
> + char *p = (char *)page;
> + int fd;
> +
> + fd = simple_strtol(p, &p, 0);
> + if ((fd < 3 || fd > 7)) {
> + printk(KERN_ERR "PSCSI: Illegal value of file descriptor: %d\n", fd);
> + return(ERR_PTR(-EINVAL));
> + }
> + if (!(filp = fget(fd))) {
> + printk(KERN_ERR "PSCSI: Unable to fget() fd: %d\n", fd);
> + return(ERR_PTR(-EBADF));
> + }
> + if (!(inode = igrab(filp->f_mapping->host))) {
> + printk(KERN_ERR "PSCSI: Unable to locate struct inode for struct"
> + " block_device fd\n");
> + fput(filp);
> + return(ERR_PTR(-EINVAL));
> + }
> + /*
> + * Look for struct scsi_device with a backing struct block_device.
> + *
> + * This means struct scsi_device->type == TYPE_DISK && TYPE_ROM.
> + */
> + if (S_ISBLK(inode->i_mode)) {
> + if (!(bd = I_BDEV(filp->f_mapping->host))) {
> + printk(KERN_ERR "PSCSI: Unable to locate struct"
> + " block_device from I_BDEV()\n");
> + iput(inode);
> + fput(filp);
> + return(ERR_PTR(-EINVAL));
> + }
> + if (!(gd = bd->bd_disk)) {
> + printk(KERN_ERR "PSCSI: Unable to locate struct gendisk"
> + " from struct block_device\n");
> + iput(inode);
> + fput(filp);
> + return(ERR_PTR(-EINVAL));
> + }
> + /*
> + * This struct gendisk->driver_fs() is marked as "// remove'
> + * in include/linux/genhd.h..
> + *
> + * Currently in drivers/scsi/s[d,r].c:s[d,r]_probe(), this
> + * pointer gets set by struct scsi_device->sdev_gendev.
> + *
> + * Is there a better way to locate struct scsi_device from
> + * struct inode..?
> + */
> + if (!(gd->driverfs_dev)) {
> + printk(KERN_ERR "PSCSI: struct gendisk->driverfs_dev"
> + " is NULL!\n");
> + iput(inode);
> + fput(filp);
> + return(ERR_PTR(-EINVAL));
> + }
> + if (!(sd = to_scsi_device(gd->driverfs_dev))) {
> + printk(KERN_ERR "PSCSI: Unable to locate struct scsi_device"
> + " from struct gendisk->driverfs_dev\n");
> + iput(inode);
> + fput(filp);
> + return(ERR_PTR(-EINVAL));
> + }
> + if (sd->host != sh) {
> + printk(KERN_ERR "PSCSI: Trying to attach scsi_device"
> + " Host ID: %d, but se_hba_t has SCSI Host ID: %d\n",
> + sd->host->host_no, sh->host_no);
> + iput(inode);
> + fput(filp);
> + return(ERR_PTR(-EINVAL));
> + }
> + /*
> + * pscsi_create_type_[disk,rom]() will release host_lock..
> + */
> + spin_lock_irq(sh->host_lock);
> + switch (sd->type) {
> + case TYPE_DISK:
> + dev = pscsi_create_type_disk(sd, pdv, se_dev->se_dev_hba);
> + break;
> + case TYPE_ROM:
> + dev = pscsi_create_type_rom(sd, pdv, se_dev->se_dev_hba);
> + break;
> + default:
> + printk(KERN_ERR "PSCSI: Unable to handle type S_ISBLK() =="
> + " TRUE Type: %s\n", scsi_device_type(sd->type));
> + spin_unlock_irq(sh->host_lock);
> + iput(inode);
> + fput(filp);
> + return(ERR_PTR(-ENOSYS));
> + }
> + } else if (S_ISCHR(inode->i_mode)) {
> +#warning FIXME: Figure how to get struct scsi_device from character device's struct inode
> + printk(KERN_ERR "SCSI Character Device unsupported via"
> + " configfs/fd method. Use configfs/control instead\n");
> + iput(inode);
> + fput(filp);
> + return(ERR_PTR(-ENOSYS));
> + } else {
> + printk(KERN_ERR "PSCSI: File destriptor is not SCSI block or character"
> + " device, ignoring\n");
> + iput(inode);
> + fput(filp);
> + return(ERR_PTR(-ENODEV));
> + }
> +
> + iput(inode);
> + fput(filp);
> + return(dev);
> +}
> +
> extern int pscsi_check_dev_params (se_hba_t *hba, struct iscsi_target *t, se_dev_transport_info_t *dti)
> {
> if (!(t->hba_params_set & PARAM_HBA_SCSI_CHANNEL_ID)) {
> diff --git a/drivers/lio-core/target_core_pscsi.h b/drivers/lio-core/target_core_pscsi.h
> index 74d444b..f2883d8 100644
> --- a/drivers/lio-core/target_core_pscsi.h
> +++ b/drivers/lio-core/target_core_pscsi.h
> @@ -75,6 +75,7 @@ extern int pscsi_check_hba_params (se_hbainfo_t *, struct iscsi_target *, int);
> extern ssize_t pscsi_set_configfs_dev_params (se_hba_t *, se_subsystem_dev_t *, const char *, ssize_t);
> extern ssize_t pscsi_check_configfs_dev_params (se_hba_t *, se_subsystem_dev_t *);
> extern ssize_t pscsi_show_configfs_dev_params (se_hba_t *, se_subsystem_dev_t *, char *);
> +extern se_device_t *pscsi_create_virtdevice_from_fd (se_subsystem_dev_t *, const char *);
> extern int pscsi_check_dev_params (se_hba_t *, struct iscsi_target *, se_dev_transport_info_t *);
> extern void pscsi_get_plugin_info (void *, char *, int *);
> extern void pscsi_get_hba_info (se_hba_t *, char *, int *);
> @@ -166,6 +167,7 @@ se_subsystem_spc_t pscsi_template_spc = ISCSI_PSCSI_SPC;
> check_configfs_dev_params: pscsi_check_configfs_dev_params, \
> set_configfs_dev_params: pscsi_set_configfs_dev_params, \
> show_configfs_dev_params: pscsi_show_configfs_dev_params, \
> + create_virtdevice_from_fd: pscsi_create_virtdevice_from_fd, \
> check_dev_params: pscsi_check_dev_params, \
> get_plugin_info: pscsi_get_plugin_info, \
> get_hba_info: pscsi_get_hba_info, \
^ permalink raw reply related [flat|nested] 2+ messages in thread
end of thread, other threads:[~2008-10-21 23:19 UTC | newest]
Thread overview: 2+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2008-10-21 20:26 [PATCH] [Target_Core_Mod/PSCSI]: Added support for ->create_virtdevice_from_fd() Nicholas A. Bellinger
2008-10-21 23:19 ` Nicholas A. Bellinger
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).