LKML Archive on lore.kernel.org
help / color / mirror / Atom feed
* [PATCH] [Target_Core_Mod/IBLOCK]: Added support for ->create_virtdevice_from_fd()
@ 2008-10-21 20:24 Nicholas A. Bellinger
  0 siblings, 0 replies; only message in thread
From: Nicholas A. Bellinger @ 2008-10-21 20:24 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 9c6293c1bfe82d04a215fab22a3a850ea879a137 Mon Sep 17 00:00:00 2001
From: Nicholas Bellinger <nab@linux-iscsi.org>
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@linux-iscsi.org>
---
 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




^ permalink raw reply	[flat|nested] only message in thread

only message in thread, other threads:[~2008-10-21 20:25 UTC | newest]

Thread overview: (only message) (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2008-10-21 20:24 [PATCH] [Target_Core_Mod/IBLOCK]: Added support for ->create_virtdevice_from_fd() 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).