[PATCH] [Target_Core_Mod/IBLOCK]: Added support for->create_virtdevice_from_fd()

From: Nicholas A. Bellinger
Date: Tue Oct 21 2008 - 16:25:38 EST


>From 9c6293c1bfe82d04a215fab22a3a850ea879a137 Mon Sep 17 00:00:00 2001
From: Nicholas Bellinger <nab@xxxxxxxxxxxxxxx>
Date: Mon, 20 Oct 2008 23:33:01 -0700
Subject: [PATCH] [Target_Core_Mod/IBLOCK]: Added support for ->create_virtdevice_from_fd()

Added se_subsystem_api_t->create_virtdevice_from_fd() for locating
and claiming struct block_device from a passed open file descriptor for
Linux/BLOCK storage objects.

This patch also adds target_core_device.c:linux_blockdevice_claim_bd()
for use with iblock_create_virtdevice_from_fd().

This patch relies upon commit 362d4ef391699b0282dfbef3da633a561d9cbde7 for
the target_core_mod configfs infrastructure.

Signed-off-by: Nicholas A. Bellinger <nab@xxxxxxxxxxxxxxx>
---
drivers/lio-core/target_core_device.c | 19 +++++-
drivers/lio-core/target_core_device.h | 1 +
drivers/lio-core/target_core_iblock.c | 116 ++++++++++++++++++++++++++-------
drivers/lio-core/target_core_iblock.h | 2 +
4 files changed, 112 insertions(+), 26 deletions(-)

diff --git a/drivers/lio-core/target_core_device.c b/drivers/lio-core/target_core_device.c
index 8a2a4fe..bcb564e 100644
--- a/drivers/lio-core/target_core_device.c
+++ b/drivers/lio-core/target_core_device.c
@@ -64,7 +64,24 @@
#undef TARGET_CORE_DEVICE_C

extern se_global_t *se_global;
-extern __u32 iscsi_unpack_lun (unsigned char *);
+
+extern struct block_device *linux_blockdevice_claim_bd (struct block_device *bd, void *claim_ptr)
+{
+ if (blkdev_get(bd, FMODE_WRITE|FMODE_READ, O_RDWR) < 0)
+ return(NULL);
+ /*
+ * If no claim pointer was passed from claimee, use struct block_device.
+ */
+ if (!claim_ptr)
+ claim_ptr = (void *)bd;
+
+ if (bd_claim(bd, claim_ptr) < 0) {
+ blkdev_put(bd);
+ return(NULL);
+ }
+
+ return(bd);
+}

extern struct block_device *__linux_blockdevice_claim (int major, int minor, void *claim_ptr, int *ret)
{
diff --git a/drivers/lio-core/target_core_device.h b/drivers/lio-core/target_core_device.h
index 0aaaad9..7f5a4f3 100644
--- a/drivers/lio-core/target_core_device.h
+++ b/drivers/lio-core/target_core_device.h
@@ -27,6 +27,7 @@
#ifndef TARGET_CORE_DEVICE_H
#define TARGET_CORE_DEVICE_H

+extern struct block_device *linux_blockdevice_claim_bd (struct block_device *, void *);
extern struct block_device *__linux_blockdevice_claim (int, int, void *, int *);
extern struct block_device *linux_blockdevice_claim (int, int, void *);
extern int linux_blockdevice_release (int, int, struct block_device *);
diff --git a/drivers/lio-core/target_core_iblock.c b/drivers/lio-core/target_core_iblock.c
index 8303786..2c66c5b 100644
--- a/drivers/lio-core/target_core_iblock.c
+++ b/drivers/lio-core/target_core_iblock.c
@@ -37,6 +37,7 @@
#include <linux/smp_lock.h>
#include <linux/bio.h>
#include <linux/genhd.h>
+#include <linux/file.h>
#include <scsi/scsi.h>
#include <scsi/scsi_host.h>

@@ -48,6 +49,7 @@
#include <iscsi_target_core.h>
#include <iscsi_target_ioctl.h>
#include <iscsi_target_ioctl_defs.h>
+#include <target_core_device.h>
#include <iscsi_target_device.h>
#include <target_core_transport.h>
#include <iscsi_target_util.h>
@@ -57,10 +59,6 @@
#undef TARGET_CORE_IBLOCK_C

extern se_global_t *se_global;
-extern struct block_device *__linux_blockdevice_claim (int, int, void *, int *);
-extern struct block_device *linux_blockdevice_claim(int, int, void *);
-
-extern int linux_blockdevice_release(int, int, struct block_device *);

#if 0
#define DEBUG_IBLOCK(x...) PYXPRINT(x)
@@ -203,32 +201,49 @@ extern se_device_t *iblock_create_virtdevice (se_hba_t *hba, void *p)
TRACE_ERROR("Unable to locate iblock_dev_t parameter\n");
return(0);
}
-
- PYXPRINT("IBLOCK: Claiming %p Major:Minor - %d:%d\n", ib_dev,
- ib_dev->ibd_major, ib_dev->ibd_minor);
-
- if ((bd = __linux_blockdevice_claim(ib_dev->ibd_major, ib_dev->ibd_minor, ib_dev, &ret)))
- if (ret == 1)
- dev_flags = DF_CLAIMED_BLOCKDEV;
- else if (ib_dev->ibd_force) {
- dev_flags = DF_READ_ONLY;
- PYXPRINT("IBLOCK: DF_READ_ONLY for Major:Minor - %d:%d\n",
- ib_dev->ibd_major, ib_dev->ibd_minor);
- } else {
- TRACE_ERROR("WARNING: Unable to claim block device. Only use"
- " force=1 for READ-ONLY access.\n");
- goto failed;
- }
- else
- goto failed;
+ /*
+ * Check if we have an open file descritpor passed through configfs
+ * $TARGET/iblock_0/some_bd/fd pointing to an underlying.
+ * struct block_device. If so, claim it with the pointer from
+ * iblock_create_virtdevice_from_fd()
+ *
+ * Otherwise, assume that parameters through 'control' attribute
+ * have set ib_dev->ibd_[major,minor]
+ */
+ if (ib_dev->ibd_bd) {
+ PYXPRINT("IBLOCK: Claiming struct block_device: %p\n", ib_dev->ibd_bd);

- ib_dev->ibd_bd = bd;
+ if (!(bd = linux_blockdevice_claim_bd(ib_dev->ibd_bd, ib_dev)))
+ goto failed;
+ dev_flags = DF_CLAIMED_BLOCKDEV;
+ ib_dev->ibd_major = bd->bd_disk->major;
+ ib_dev->ibd_minor = bd->bd_disk->first_minor;
+ } else {
+ PYXPRINT("IBLOCK: Claiming %p Major:Minor - %d:%d\n", ib_dev,
+ ib_dev->ibd_major, ib_dev->ibd_minor);
+
+ if ((bd = __linux_blockdevice_claim(ib_dev->ibd_major,
+ ib_dev->ibd_minor, ib_dev, &ret))) {
+ if (ret == 1)
+ dev_flags = DF_CLAIMED_BLOCKDEV;
+ else if (ib_dev->ibd_force) {
+ dev_flags = DF_READ_ONLY;
+ PYXPRINT("IBLOCK: DF_READ_ONLY for Major:Minor - %d:%d\n",
+ ib_dev->ibd_major, ib_dev->ibd_minor);
+ } else {
+ TRACE_ERROR("WARNING: Unable to claim block device. Only use"
+ " force=1 for READ-ONLY access.\n");
+ goto failed;
+ }
+ ib_dev->ibd_bd = bd;
+ } else
+ goto failed;
+ }
if (dev_flags & DF_CLAIMED_BLOCKDEV)
ib_dev->ibd_bd->bd_contains = bd;

if (!(ib_dev->ibd_bio_set = bioset_create(32, 64))) {
- TRACE_ERROR("Unable to create bioset for IBLOCK\n");
- dump_stack();
+ printk(KERN_ERR "IBLOCK: Unable to create bioset()\n");
goto failed;
}
printk("IBLOCK: Created bio_set() for major/minor: %d:%d\n",
@@ -636,6 +651,57 @@ extern ssize_t iblock_show_configfs_dev_params (se_hba_t *hba, se_subsystem_dev_
return((ssize_t)bl);
}

+extern se_device_t *iblock_create_virtdevice_from_fd (
+ se_subsystem_dev_t *se_dev,
+ const char *page)
+{
+ iblock_dev_t *ibd = (iblock_dev_t *) se_dev->se_dev_su_ptr;
+ se_device_t *dev = NULL;
+ struct file *filp;
+ struct inode *inode;
+ char *p = (char *)page;
+ int fd;
+
+ fd = simple_strtol(p, &p, 0);
+ if ((fd < 3 || fd > 7)) {
+ printk(KERN_ERR "IBLOCK: Illegal value of file descriptor: %d\n", fd);
+ return(ERR_PTR(-EINVAL));
+ }
+ if (!(filp = fget(fd))) {
+ printk(KERN_ERR "IBLOCK: Unable to fget() fd: %d\n", fd);
+ return(ERR_PTR(-EBADF));
+ }
+ if (!(inode = igrab(filp->f_mapping->host))) {
+ printk(KERN_ERR "IBLOCK: Unable to locate struct inode for struct"
+ " block_device fd\n");
+ fput(filp);
+ return(ERR_PTR(-EINVAL));
+ }
+ if (!(S_ISBLK(inode->i_mode))) {
+ printk(KERN_ERR "IBLOCK: S_ISBLK(inode->i_mode) failed for file"
+ " descriptor: %d\n", fd);
+ iput(inode);
+ fput(filp);
+ return(ERR_PTR(-ENODEV));
+ }
+ if (!(ibd->ibd_bd = I_BDEV(filp->f_mapping->host))) {
+ printk(KERN_ERR "IBLOCK: Unable to locate struct block_device"
+ " from I_BDEV()\n");
+ iput(inode);
+ fput(filp);
+ return(ERR_PTR(-EINVAL));
+ }
+ /*
+ * iblock_create_virtdevice() will call linux_blockdevice_claim_bd()
+ * to claim struct block_device.
+ */
+ dev = iblock_create_virtdevice(se_dev->se_dev_hba, (void *)ibd);
+
+ iput(inode);
+ fput(filp);
+ return(dev);
+}
+
extern int iblock_check_dev_params (se_hba_t *hba, struct iscsi_target *t, se_dev_transport_info_t *dti)
{
if (!(t->hba_params_set & PARAM_HBA_IBLOCK_MAJOR) ||
diff --git a/drivers/lio-core/target_core_iblock.h b/drivers/lio-core/target_core_iblock.h
index 2c793b7..5545dc5 100644
--- a/drivers/lio-core/target_core_iblock.h
+++ b/drivers/lio-core/target_core_iblock.h
@@ -66,6 +66,7 @@ extern int iblock_check_hba_params (se_hbainfo_t *, struct iscsi_target *, int);
extern ssize_t iblock_set_configfs_dev_params (se_hba_t *, se_subsystem_dev_t *, const char *, ssize_t);
extern ssize_t iblock_check_configfs_dev_params (se_hba_t *, se_subsystem_dev_t *);
extern ssize_t iblock_show_configfs_dev_params (se_hba_t *, se_subsystem_dev_t *, char *);
+extern se_device_t *iblock_create_virtdevice_from_fd (se_subsystem_dev_t *, const char *);
extern int iblock_check_dev_params (se_hba_t *, struct iscsi_target *, se_dev_transport_info_t *);
extern int iblock_check_virtdev_params (se_devinfo_t *di, struct iscsi_target *);
extern void iblock_get_plugin_info (void *, char *, int *);
@@ -160,6 +161,7 @@ se_subsystem_spc_t iblock_template_spc = ISCSI_IBLOCK_SPC;
check_configfs_dev_params: iblock_check_configfs_dev_params, \
set_configfs_dev_params: iblock_set_configfs_dev_params, \
show_configfs_dev_params: iblock_show_configfs_dev_params, \
+ create_virtdevice_from_fd: iblock_create_virtdevice_from_fd, \
check_virtdev_params: iblock_check_virtdev_params, \
check_dev_params: iblock_check_dev_params, \
get_plugin_info: iblock_get_plugin_info, \
--
1.5.4.1



--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at http://vger.kernel.org/majordomo-info.html
Please read the FAQ at http://www.tux.org/lkml/