⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 dm-mpath-rdac.c

📁 linux 内核源代码
💻 C
📖 第 1 页 / 共 2 页
字号:
/* * Engenio/LSI RDAC DM HW handler * * Copyright (C) 2005 Mike Christie. All rights reserved. * Copyright (C) Chandra Seetharaman, IBM Corp. 2007 * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * */#include <scsi/scsi.h>#include <scsi/scsi_cmnd.h>#include <scsi/scsi_eh.h>#define DM_MSG_PREFIX "multipath rdac"#include "dm.h"#include "dm-hw-handler.h"#define RDAC_DM_HWH_NAME "rdac"#define RDAC_DM_HWH_VER "0.4"/* * LSI mode page stuff * * These struct definitions and the forming of the * mode page were taken from the LSI RDAC 2.4 GPL'd * driver, and then converted to Linux conventions. */#define RDAC_QUIESCENCE_TIME 20;/* * Page Codes */#define RDAC_PAGE_CODE_REDUNDANT_CONTROLLER 0x2c/* * Controller modes definitions */#define RDAC_MODE_TRANSFER_ALL_LUNS		0x01#define RDAC_MODE_TRANSFER_SPECIFIED_LUNS	0x02/* * RDAC Options field */#define RDAC_FORCED_QUIESENCE 0x02#define RDAC_FAILOVER_TIMEOUT (60 * HZ)struct rdac_mode_6_hdr {	u8	data_len;	u8	medium_type;	u8	device_params;	u8	block_desc_len;};struct rdac_mode_10_hdr {	u16	data_len;	u8	medium_type;	u8	device_params;	u16	reserved;	u16	block_desc_len;};struct rdac_mode_common {	u8	controller_serial[16];	u8	alt_controller_serial[16];	u8	rdac_mode[2];	u8	alt_rdac_mode[2];	u8	quiescence_timeout;	u8	rdac_options;};struct rdac_pg_legacy {	struct rdac_mode_6_hdr hdr;	u8	page_code;	u8	page_len;	struct rdac_mode_common common;#define MODE6_MAX_LUN	32	u8	lun_table[MODE6_MAX_LUN];	u8	reserved2[32];	u8	reserved3;	u8	reserved4;};struct rdac_pg_expanded {	struct rdac_mode_10_hdr hdr;	u8	page_code;	u8	subpage_code;	u8	page_len[2];	struct rdac_mode_common common;	u8	lun_table[256];	u8	reserved3;	u8	reserved4;};struct c9_inquiry {	u8	peripheral_info;	u8	page_code;	/* 0xC9 */	u8	reserved1;	u8	page_len;	u8	page_id[4];	/* "vace" */	u8	avte_cvp;	u8	path_prio;	u8	reserved2[38];};#define SUBSYS_ID_LEN	16#define SLOT_ID_LEN	2struct c4_inquiry {	u8	peripheral_info;	u8	page_code;	/* 0xC4 */	u8	reserved1;	u8	page_len;	u8	page_id[4];	/* "subs" */	u8	subsys_id[SUBSYS_ID_LEN];	u8	revision[4];	u8	slot_id[SLOT_ID_LEN];	u8	reserved[2];};struct rdac_controller {	u8			subsys_id[SUBSYS_ID_LEN];	u8			slot_id[SLOT_ID_LEN];	int			use_10_ms;	struct kref		kref;	struct list_head	node; /* list of all controllers */	spinlock_t		lock;	int			submitted;	struct list_head	cmd_list; /* list of commands to be submitted */	union			{		struct rdac_pg_legacy legacy;		struct rdac_pg_expanded expanded;	} mode_select;};struct c8_inquiry {	u8	peripheral_info;	u8	page_code; /* 0xC8 */	u8	reserved1;	u8	page_len;	u8	page_id[4]; /* "edid" */	u8	reserved2[3];	u8	vol_uniq_id_len;	u8	vol_uniq_id[16];	u8	vol_user_label_len;	u8	vol_user_label[60];	u8	array_uniq_id_len;	u8	array_unique_id[16];	u8	array_user_label_len;	u8	array_user_label[60];	u8	lun[8];};struct c2_inquiry {	u8	peripheral_info;	u8	page_code;	/* 0xC2 */	u8	reserved1;	u8	page_len;	u8	page_id[4];	/* "swr4" */	u8	sw_version[3];	u8	sw_date[3];	u8	features_enabled;	u8	max_lun_supported;	u8	partitions[239]; /* Total allocation length should be 0xFF */};struct rdac_handler {	struct list_head	entry; /* list waiting to submit MODE SELECT */	unsigned		timeout;	struct rdac_controller	*ctlr;#define UNINITIALIZED_LUN	(1 << 8)	unsigned		lun;	unsigned char		sense[SCSI_SENSE_BUFFERSIZE];	struct dm_path		*path;	struct work_struct	work;#define	SEND_C2_INQUIRY		1#define	SEND_C4_INQUIRY		2#define	SEND_C8_INQUIRY		3#define	SEND_C9_INQUIRY		4#define	SEND_MODE_SELECT	5	int			cmd_to_send;	union			{		struct c2_inquiry c2;		struct c4_inquiry c4;		struct c8_inquiry c8;		struct c9_inquiry c9;	} inq;};static LIST_HEAD(ctlr_list);static DEFINE_SPINLOCK(list_lock);static struct workqueue_struct *rdac_wkqd;static inline int had_failures(struct request *req, int error){	return (error || host_byte(req->errors) != DID_OK ||			msg_byte(req->errors) != COMMAND_COMPLETE);}static void rdac_resubmit_all(struct rdac_handler *h){	struct rdac_controller *ctlr = h->ctlr;	struct rdac_handler *tmp, *h1;	spin_lock(&ctlr->lock);	list_for_each_entry_safe(h1, tmp, &ctlr->cmd_list, entry) {		h1->cmd_to_send = SEND_C9_INQUIRY;		queue_work(rdac_wkqd, &h1->work);		list_del(&h1->entry);	}	ctlr->submitted = 0;	spin_unlock(&ctlr->lock);}static void mode_select_endio(struct request *req, int error){	struct rdac_handler *h = req->end_io_data;	struct scsi_sense_hdr sense_hdr;	int sense = 0, fail = 0;	if (had_failures(req, error)) {		fail = 1;		goto failed;	}	if (status_byte(req->errors) == CHECK_CONDITION) {		scsi_normalize_sense(req->sense, SCSI_SENSE_BUFFERSIZE,				&sense_hdr);		sense = (sense_hdr.sense_key << 16) | (sense_hdr.asc << 8) |				sense_hdr.ascq;		/* If it is retryable failure, submit the c9 inquiry again */		if (sense == 0x59136 || sense == 0x68b02 || sense == 0xb8b02 ||		    sense == 0x62900) {			/* 0x59136    - Command lock contention			 * 0x[6b]8b02 - Quiesense in progress or achieved			 * 0x62900    - Power On, Reset, or Bus Device Reset			 */			h->cmd_to_send = SEND_C9_INQUIRY;			queue_work(rdac_wkqd, &h->work);			goto done;		}		if (sense)			DMINFO("MODE_SELECT failed on %s with sense 0x%x",						h->path->dev->name, sense); 	}failed:	if (fail || sense)		dm_pg_init_complete(h->path, MP_FAIL_PATH);	else		dm_pg_init_complete(h->path, 0);done:	rdac_resubmit_all(h);	__blk_put_request(req->q, req);}static struct request *get_rdac_req(struct rdac_handler *h,			void *buffer, unsigned buflen, int rw){	struct request *rq;	struct request_queue *q = bdev_get_queue(h->path->dev->bdev);	rq = blk_get_request(q, rw, GFP_KERNEL);	if (!rq) {		DMINFO("get_rdac_req: blk_get_request failed");		return NULL;	}	if (buflen && blk_rq_map_kern(q, rq, buffer, buflen, GFP_KERNEL)) {		blk_put_request(rq);		DMINFO("get_rdac_req: blk_rq_map_kern failed");		return NULL;	} 	memset(&rq->cmd, 0, BLK_MAX_CDB);	rq->sense = h->sense;	memset(rq->sense, 0, SCSI_SENSE_BUFFERSIZE);	rq->sense_len = 0;	rq->end_io_data = h;	rq->timeout = h->timeout;	rq->cmd_type = REQ_TYPE_BLOCK_PC;	rq->cmd_flags |= REQ_FAILFAST | REQ_NOMERGE;	return rq;}static struct request *rdac_failover_get(struct rdac_handler *h){	struct request *rq;	struct rdac_mode_common *common;	unsigned data_size;	if (h->ctlr->use_10_ms) {		struct rdac_pg_expanded *rdac_pg;		data_size = sizeof(struct rdac_pg_expanded);		rdac_pg = &h->ctlr->mode_select.expanded;		memset(rdac_pg, 0, data_size);		common = &rdac_pg->common;		rdac_pg->page_code = RDAC_PAGE_CODE_REDUNDANT_CONTROLLER + 0x40;		rdac_pg->subpage_code = 0x1;		rdac_pg->page_len[0] = 0x01;		rdac_pg->page_len[1] = 0x28;		rdac_pg->lun_table[h->lun] = 0x81;	} else {		struct rdac_pg_legacy *rdac_pg;		data_size = sizeof(struct rdac_pg_legacy);		rdac_pg = &h->ctlr->mode_select.legacy;		memset(rdac_pg, 0, data_size);		common = &rdac_pg->common;		rdac_pg->page_code = RDAC_PAGE_CODE_REDUNDANT_CONTROLLER;		rdac_pg->page_len = 0x68;		rdac_pg->lun_table[h->lun] = 0x81;	}	common->rdac_mode[1] = RDAC_MODE_TRANSFER_SPECIFIED_LUNS;	common->quiescence_timeout = RDAC_QUIESCENCE_TIME;	common->rdac_options = RDAC_FORCED_QUIESENCE;	/* get request for block layer packet command */	rq = get_rdac_req(h, &h->ctlr->mode_select, data_size, WRITE);	if (!rq) {		DMERR("rdac_failover_get: no rq");		return NULL;	}	/* Prepare the command. */	if (h->ctlr->use_10_ms) {		rq->cmd[0] = MODE_SELECT_10;		rq->cmd[7] = data_size >> 8;		rq->cmd[8] = data_size & 0xff;	} else {		rq->cmd[0] = MODE_SELECT;		rq->cmd[4] = data_size;	}	rq->cmd_len = COMMAND_SIZE(rq->cmd[0]);	return rq;}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -