All of lore.kernel.org
 help / color / mirror / Atom feed
From: Chandra Seetharaman <sekharan@us.ibm.com>
To: James.Bottomley@HansenPartnership.com, hare@suse.de,
	linux-scsi@vger.kernel.org
Cc: dm-devel@redhat.com
Subject: [PATCH 5/8] scsi_dh: Update RDAC device handler
Date: Thu, 17 Jul 2008 16:53:15 -0700	[thread overview]
Message-ID: <20080717235315.23056.2877.sendpatchset@chandra-ubuntu> (raw)
In-Reply-To: <20080717235245.23056.89788.sendpatchset@chandra-ubuntu>

This patch updates the RDAC device handler to
refuse to attach to devices not supporting the
RDAC vpd pages.

Signed-off-by: Hannes Reinecke <hare@suse.de>
Signed-off-by: Chandra Seetharaman <sekharan@us.ibm.com>
---
 drivers/scsi/device_handler/scsi_dh_rdac.c |  163 ++++++++++++++++------------
 1 files changed, 94 insertions(+), 69 deletions(-)

Index: linux-2.6.26-git5/drivers/scsi/device_handler/scsi_dh_rdac.c
===================================================================
--- linux-2.6.26-git5.orig/drivers/scsi/device_handler/scsi_dh_rdac.c
+++ linux-2.6.26-git5/drivers/scsi/device_handler/scsi_dh_rdac.c
@@ -173,6 +173,11 @@ struct rdac_dh_data {
 #define RDAC_STATE_ACTIVE	0
 #define RDAC_STATE_PASSIVE	1
 	unsigned char		state;
+
+#define RDAC_LUN_UNOWNED	0
+#define RDAC_LUN_OWNED		1
+#define RDAC_LUN_AVT		2
+	char			lun_state;
 	unsigned char		sense[SCSI_SENSE_BUFFERSIZE];
 	union			{
 		struct c2_inquiry c2;
@@ -182,6 +187,13 @@ struct rdac_dh_data {
 	} inq;
 };
 
+static const char *lun_state[] =
+{
+	"unowned",
+	"owned",
+	"owned (AVT mode)",
+};
+
 static LIST_HEAD(ctlr_list);
 static DEFINE_SPINLOCK(list_lock);
 
@@ -197,9 +209,8 @@ static struct request *get_rdac_req(stru
 {
 	struct request *rq;
 	struct request_queue *q = sdev->request_queue;
-	struct rdac_dh_data *h = get_rdac_data(sdev);
 
-	rq = blk_get_request(q, rw, GFP_KERNEL);
+	rq = blk_get_request(q, rw, GFP_NOIO);
 
 	if (!rq) {
 		sdev_printk(KERN_INFO, sdev,
@@ -207,17 +218,14 @@ static struct request *get_rdac_req(stru
 		return NULL;
 	}
 
-	if (buflen && blk_rq_map_kern(q, rq, buffer, buflen, GFP_KERNEL)) {
+	if (buflen && blk_rq_map_kern(q, rq, buffer, buflen, GFP_NOIO)) {
 		blk_put_request(rq);
 		sdev_printk(KERN_INFO, sdev,
 				"get_rdac_req: blk_rq_map_kern failed.\n");
 		return NULL;
 	}
 
-	memset(&rq->cmd, 0, BLK_MAX_CDB);
-	rq->sense = h->sense;
-	memset(rq->sense, 0, SCSI_SENSE_BUFFERSIZE);
-	rq->sense_len = 0;
+	memset(rq->cmd, 0, BLK_MAX_CDB);
 
 	rq->cmd_type = REQ_TYPE_BLOCK_PC;
 	rq->cmd_flags |= REQ_FAILFAST | REQ_NOMERGE;
@@ -227,12 +235,12 @@ static struct request *get_rdac_req(stru
 	return rq;
 }
 
-static struct request *rdac_failover_get(struct scsi_device *sdev)
+static struct request *rdac_failover_get(struct scsi_device *sdev,
+					 struct rdac_dh_data *h)
 {
 	struct request *rq;
 	struct rdac_mode_common *common;
 	unsigned data_size;
-	struct rdac_dh_data *h = get_rdac_data(sdev);
 
 	if (h->ctlr->use_ms10) {
 		struct rdac_pg_expanded *rdac_pg;
@@ -277,6 +285,10 @@ static struct request *rdac_failover_get
 	}
 	rq->cmd_len = COMMAND_SIZE(rq->cmd[0]);
 
+	rq->sense = h->sense;
+	memset(rq->sense, 0, SCSI_SENSE_BUFFERSIZE);
+	rq->sense_len = 0;
+
 	return rq;
 }
 
@@ -321,11 +333,10 @@ done:
 }
 
 static int submit_inquiry(struct scsi_device *sdev, int page_code,
-		unsigned int len)
+			  unsigned int len, struct rdac_dh_data *h)
 {
 	struct request *rq;
 	struct request_queue *q = sdev->request_queue;
-	struct rdac_dh_data *h = get_rdac_data(sdev);
 	int err = SCSI_DH_RES_TEMP_UNAVAIL;
 
 	rq = get_rdac_req(sdev, &h->inq, len, READ);
@@ -338,59 +349,68 @@ static int submit_inquiry(struct scsi_de
 	rq->cmd[2] = page_code;
 	rq->cmd[4] = len;
 	rq->cmd_len = COMMAND_SIZE(INQUIRY);
+
+	rq->sense = h->sense;
+	memset(rq->sense, 0, SCSI_SENSE_BUFFERSIZE);
+	rq->sense_len = 0;
+
 	err = blk_execute_rq(q, NULL, rq, 1);
 	if (err == -EIO)
 		err = SCSI_DH_IO;
+
+	blk_put_request(rq);
 done:
 	return err;
 }
 
-static int get_lun(struct scsi_device *sdev)
+static int get_lun(struct scsi_device *sdev, struct rdac_dh_data *h)
 {
 	int err;
 	struct c8_inquiry *inqp;
-	struct rdac_dh_data *h = get_rdac_data(sdev);
 
-	err = submit_inquiry(sdev, 0xC8, sizeof(struct c8_inquiry));
+	err = submit_inquiry(sdev, 0xC8, sizeof(struct c8_inquiry), h);
 	if (err == SCSI_DH_OK) {
 		inqp = &h->inq.c8;
-		h->lun = inqp->lun[7]; /* currently it uses only one byte */
+		if (inqp->page_code != 0xc8)
+			return SCSI_DH_NOSYS;
+		if (inqp->page_id[0] != 'e' || inqp->page_id[1] != 'd' ||
+		    inqp->page_id[2] != 'i' || inqp->page_id[3] != 'd')
+			return SCSI_DH_NOSYS;
+		h->lun = scsilun_to_int((struct scsi_lun *)inqp->lun);
 	}
 	return err;
 }
 
-#define RDAC_OWNED	0
-#define RDAC_UNOWNED	1
-#define RDAC_FAILED	2
-static int check_ownership(struct scsi_device *sdev)
+static int check_ownership(struct scsi_device *sdev, struct rdac_dh_data *h)
 {
 	int err;
 	struct c9_inquiry *inqp;
-	struct rdac_dh_data *h = get_rdac_data(sdev);
 
-	err = submit_inquiry(sdev, 0xC9, sizeof(struct c9_inquiry));
+	err = submit_inquiry(sdev, 0xC9, sizeof(struct c9_inquiry), h);
 	if (err == SCSI_DH_OK) {
-		err = RDAC_UNOWNED;
 		inqp = &h->inq.c9;
-		/*
-		 * If in AVT mode or if the path already owns the LUN,
-		 * return RDAC_OWNED;
-		 */
-		if (((inqp->avte_cvp >> 7) == 0x1) ||
-				 ((inqp->avte_cvp & 0x1) != 0))
-			err = RDAC_OWNED;
-	} else
-		err = RDAC_FAILED;
+		if ((inqp->avte_cvp >> 7) == 0x1) {
+			/* LUN in AVT mode */
+			sdev_printk(KERN_NOTICE, sdev,
+				    "%s: AVT mode detected\n",
+				    RDAC_NAME);
+			h->lun_state = RDAC_LUN_AVT;
+		} else if ((inqp->avte_cvp & 0x1) != 0) {
+			/* LUN was owned by the controller */
+			h->lun_state = RDAC_LUN_OWNED;
+		}
+	}
+
 	return err;
 }
 
-static int initialize_controller(struct scsi_device *sdev)
+static int initialize_controller(struct scsi_device *sdev,
+				 struct rdac_dh_data *h)
 {
 	int err;
 	struct c4_inquiry *inqp;
-	struct rdac_dh_data *h = get_rdac_data(sdev);
 
-	err = submit_inquiry(sdev, 0xC4, sizeof(struct c4_inquiry));
+	err = submit_inquiry(sdev, 0xC4, sizeof(struct c4_inquiry), h);
 	if (err == SCSI_DH_OK) {
 		inqp = &h->inq.c4;
 		h->ctlr = get_controller(inqp->subsys_id, inqp->slot_id);
@@ -400,13 +420,12 @@ static int initialize_controller(struct 
 	return err;
 }
 
-static int set_mode_select(struct scsi_device *sdev)
+static int set_mode_select(struct scsi_device *sdev, struct rdac_dh_data *h)
 {
 	int err;
 	struct c2_inquiry *inqp;
-	struct rdac_dh_data *h = get_rdac_data(sdev);
 
-	err = submit_inquiry(sdev, 0xC2, sizeof(struct c2_inquiry));
+	err = submit_inquiry(sdev, 0xC2, sizeof(struct c2_inquiry), h);
 	if (err == SCSI_DH_OK) {
 		inqp = &h->inq.c2;
 		/*
@@ -421,13 +440,13 @@ static int set_mode_select(struct scsi_d
 	return err;
 }
 
-static int mode_select_handle_sense(struct scsi_device *sdev)
+static int mode_select_handle_sense(struct scsi_device *sdev,
+				    unsigned char *sensebuf)
 {
 	struct scsi_sense_hdr sense_hdr;
-	struct rdac_dh_data *h = get_rdac_data(sdev);
 	int sense, err = SCSI_DH_IO, ret;
 
-	ret = scsi_normalize_sense(h->sense, SCSI_SENSE_BUFFERSIZE, &sense_hdr);
+	ret = scsi_normalize_sense(sensebuf, SCSI_SENSE_BUFFERSIZE, &sense_hdr);
 	if (!ret)
 		goto done;
 
@@ -451,14 +470,13 @@ done:
 	return err;
 }
 
-static int send_mode_select(struct scsi_device *sdev)
+static int send_mode_select(struct scsi_device *sdev, struct rdac_dh_data *h)
 {
 	struct request *rq;
 	struct request_queue *q = sdev->request_queue;
-	struct rdac_dh_data *h = get_rdac_data(sdev);
 	int err = SCSI_DH_RES_TEMP_UNAVAIL;
 
-	rq = rdac_failover_get(sdev);
+	rq = rdac_failover_get(sdev, h);
 	if (!rq)
 		goto done;
 
@@ -466,9 +484,11 @@ static int send_mode_select(struct scsi_
 
 	err = blk_execute_rq(q, NULL, rq, 1);
 	if (err != SCSI_DH_OK)
-		err = mode_select_handle_sense(sdev);
+		err = mode_select_handle_sense(sdev, h->sense);
 	if (err == SCSI_DH_OK)
 		h->state = RDAC_STATE_ACTIVE;
+
+	blk_put_request(rq);
 done:
 	return err;
 }
@@ -478,38 +498,23 @@ static int rdac_activate(struct scsi_dev
 	struct rdac_dh_data *h = get_rdac_data(sdev);
 	int err = SCSI_DH_OK;
 
-	if (h->lun == UNINITIALIZED_LUN) {
-		err = get_lun(sdev);
-		if (err != SCSI_DH_OK)
-			goto done;
-	}
-
-	err = check_ownership(sdev);
-	switch (err) {
-	case RDAC_UNOWNED:
-		break;
-	case RDAC_OWNED:
-		err = SCSI_DH_OK;
-		goto done;
-	case RDAC_FAILED:
-	default:
-		err = SCSI_DH_IO;
+	err = check_ownership(sdev, h);
+	if (err != SCSI_DH_OK)
 		goto done;
-	}
 
 	if (!h->ctlr) {
-		err = initialize_controller(sdev);
+		err = initialize_controller(sdev, h);
 		if (err != SCSI_DH_OK)
 			goto done;
 	}
 
 	if (h->ctlr->use_ms10 == -1) {
-		err = set_mode_select(sdev);
+		err = set_mode_select(sdev, h);
 		if (err != SCSI_DH_OK)
 			goto done;
 	}
-
-	err = send_mode_select(sdev);
+	if (h->lun_state == RDAC_LUN_UNOWNED)
+		err = send_mode_select(sdev, h);
 done:
 	return err;
 }
@@ -606,11 +611,12 @@ static int rdac_bus_attach(struct scsi_d
 	struct scsi_dh_data *scsi_dh_data;
 	struct rdac_dh_data *h;
 	unsigned long flags;
+	int err;
 
 	scsi_dh_data = kzalloc(sizeof(struct scsi_device_handler *)
 			       + sizeof(*h) , GFP_KERNEL);
 	if (!scsi_dh_data) {
-		sdev_printk(KERN_ERR, sdev, "Attach failed %s.\n",
+		sdev_printk(KERN_ERR, sdev, "%s: Attach failed\n",
 			    RDAC_NAME);
 		return 0;
 	}
@@ -619,14 +625,33 @@ static int rdac_bus_attach(struct scsi_d
 	h = (struct rdac_dh_data *) scsi_dh_data->buf;
 	h->lun = UNINITIALIZED_LUN;
 	h->state = RDAC_STATE_ACTIVE;
+
+	err = get_lun(sdev, h);
+	if (err != SCSI_DH_OK)
+		goto failed;
+
+	err = check_ownership(sdev, h);
+	if (err != SCSI_DH_OK)
+		goto failed;
+
+	if (!try_module_get(THIS_MODULE))
+		goto failed;
+
 	spin_lock_irqsave(sdev->request_queue->queue_lock, flags);
 	sdev->scsi_dh_data = scsi_dh_data;
 	spin_unlock_irqrestore(sdev->request_queue->queue_lock, flags);
-	try_module_get(THIS_MODULE);
 
-	sdev_printk(KERN_NOTICE, sdev, "Attached %s\n", RDAC_NAME);
+	sdev_printk(KERN_NOTICE, sdev,
+		    "%s: LUN %d (%s)\n",
+		    RDAC_NAME, h->lun, lun_state[(int)h->lun_state]);
 
 	return 0;
+
+failed:
+	kfree(scsi_dh_data);
+	sdev_printk(KERN_ERR, sdev, "%s: not attached\n",
+		    RDAC_NAME);
+	return -EINVAL;
 }
 
 static void rdac_bus_detach( struct scsi_device *sdev )
@@ -645,7 +670,7 @@ static void rdac_bus_detach( struct scsi
 		kref_put(&h->ctlr->kref, release_controller);
 	kfree(scsi_dh_data);
 	module_put(THIS_MODULE);
-	sdev_printk(KERN_NOTICE, sdev, "Detached %s\n", RDAC_NAME);
+	sdev_printk(KERN_NOTICE, sdev, "%s: Detached\n", RDAC_NAME);
 }
 
 

  parent reply	other threads:[~2008-07-17 23:53 UTC|newest]

Thread overview: 12+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2008-07-17 23:52 [PATCH 0/8] scsi_dh update Chandra Seetharaman
2008-07-17 23:52 ` [PATCH 1/8] scsi_dh: Implement common device table handling Chandra Seetharaman
2008-07-17 23:52 ` [PATCH 2/8] scsi_dh: Add 'dh_state' sysfs attribute Chandra Seetharaman
2008-07-17 23:53 ` [PATCH 3/8] scsi_dh: Update EMC handler Chandra Seetharaman
2008-07-17 23:53 ` [PATCH 4/8] scsi_dh: Update hp_sw hardware handler Chandra Seetharaman
2008-07-17 23:53 ` Chandra Seetharaman [this message]
2008-07-17 23:53 ` [PATCH 6/8] scsi_dh: add generic SPC-3 alua handler Chandra Seetharaman
2008-07-17 23:53 ` [PATCH 7/8] scsi_dh: attach to hardware handler from dm-mpath Chandra Seetharaman
2008-07-18  0:08   ` Alasdair G Kergon
2008-07-18  0:49     ` [dm-devel] " Chandra Seetharaman
2008-07-17 23:53 ` [PATCH 8/8] scsi_dh: create lookup cache Chandra Seetharaman
  -- strict thread matches above, loose matches on Subject: below --
2008-07-17  7:38 [PATCH 5/8] scsi_dh: Update RDAC device handler Hannes Reinecke

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20080717235315.23056.2877.sendpatchset@chandra-ubuntu \
    --to=sekharan@us.ibm.com \
    --cc=James.Bottomley@HansenPartnership.com \
    --cc=dm-devel@redhat.com \
    --cc=hare@suse.de \
    --cc=linux-scsi@vger.kernel.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.