[PATCH] megaraid_sas : block physical disk access

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



Here is the patch for review that implements slave_alloc to block direct 
access to the Physical Disks.
By using no_uld_attach and clearing the scsi device writeable flag the disks will be 
still accessible even if it belongs to a RAID volume.
I would prefer to hide the Physical Disks to block any kind of access.

I will send a separate patch to monitor drive insertion/removal to update internally 
the physical disk list.

Thanks,

Sumant Patro

Signed-off-by: Sumant Patro <Sumant.Patro@xxxxxxxx>

diff -uprN linux2.6.orig/drivers/scsi/megaraid/megaraid_sas.c linux2.6/drivers/scsi/megaraid/megaraid_sas.c
--- linux2.6.orig/drivers/scsi/megaraid/megaraid_sas.c	2006-02-09 13:37:50.000000000 -0800
+++ linux2.6/drivers/scsi/megaraid/megaraid_sas.c	2006-02-09 15:24:44.000000000 -0800
@@ -707,6 +707,50 @@ megasas_queue_command(struct scsi_cmnd *
 	return 0;
 }
 
+static struct megasas_instance *megasas_lookup_instance(u16 host_no)
+{
+	int i;
+
+	for (i = 0; i < megasas_mgmt_info.max_index; i++) {
+
+		if ((megasas_mgmt_info.instance[i]) &&
+		    (megasas_mgmt_info.instance[i]->host->host_no == host_no))
+			return megasas_mgmt_info.instance[i];
+	}
+
+	return NULL;
+}
+
+static int megasas_slave_alloc(struct scsi_device *sdev){
+	struct megasas_instance *instance ; 
+	u32 id;
+	instance = megasas_lookup_instance(sdev->host->host_no);
+	/*
+        * Don't export physical disk devices
+        */
+	if(sdev->channel < MEGASAS_MAX_PD_CHANNELS)
+	{
+		id = MEGASAS_MAX_DEV_PER_CHANNEL * sdev->channel + sdev->id;
+		/*
+		* Check if the bit is set for id in our physical device bitmap
+		* If the bit is set in phys_dev then a Disk is present for the id
+		*/
+		if (instance->phys_dev[id/8] /*Finds index of phys_dev this id
+						 belongs to*/
+				& (1 << id%8) /*Finds bit number for the id */
+				)
+			return -ENXIO;
+	}	
+	return 0;
+}
+
+static int megasas_slave_configure(struct scsi_device *sdev){
+	/*
+		This will be used to set sdev timeout
+	*/
+       return 0;
+}
+
 /**
  * megasas_wait_for_outstanding -	Wait for all outstanding cmds
  * @instance:				Adapter soft state
@@ -857,6 +901,8 @@ static struct scsi_host_template megasas
 	.module = THIS_MODULE,
 	.name = "LSI Logic SAS based MegaRAID driver",
 	.proc_name = "megaraid_sas",
+	.slave_alloc = megasas_slave_alloc,
+	.slave_configure = megasas_slave_configure,
 	.queuecommand = megasas_queue_command,
 	.eh_device_reset_handler = megasas_reset_device,
 	.eh_bus_reset_handler = megasas_reset_bus_host,
@@ -985,20 +1031,6 @@ megasas_complete_cmd(struct megasas_inst
 			break;
 		}
 
-		/*
-		 * Don't export physical disk devices to mid-layer.
-		 */
-		if (!MEGASAS_IS_LOGICAL(cmd->scmd) &&
-		    (hdr->cmd_status == MFI_STAT_OK) &&
-		    (cmd->scmd->cmnd[0] == INQUIRY)) {
-
-			if (((*(u8 *) cmd->scmd->request_buffer) & 0x1F) ==
-			    TYPE_DISK) {
-				cmd->scmd->result = DID_BAD_TARGET << 16;
-				exception = 1;
-			}
-		}
-
 	case MFI_CMD_LD_READ:
 	case MFI_CMD_LD_WRITE:
 
@@ -1502,6 +1534,70 @@ static int megasas_alloc_cmds(struct meg
 	return 0;
 }
 
+
+/**
+ * megasas_get_pd_list -		Returns FW's controller structure
+ * @instance:				Adapter soft state
+ * @pd_list:				Physical drive list structure
+ *
+ * Issues an internal command (DCMD) to get the list of Physical Dirive's structure.
+ * This information is used to block export of Disks to the Upper layer drivers.
+ */
+static int
+megasas_get_pd_list(struct megasas_instance *instance,
+		      struct megasas_pd_list *pd_list)
+{
+	int ret = 0;
+	struct megasas_cmd *cmd;
+	struct megasas_dcmd_frame *dcmd;
+	struct megasas_pd_list *pdlist;
+	dma_addr_t pdlist_h = 0;
+
+	cmd = megasas_get_cmd(instance);
+
+	if (!cmd) {
+		printk(KERN_DEBUG "megasas: Failed to get a free cmd\n");
+		return -ENOMEM;
+	}
+
+	dcmd = &cmd->frame->dcmd;
+
+	pdlist = pci_alloc_consistent(instance->pdev,
+				  sizeof(struct megasas_pd_list), &pdlist_h);
+
+	if (!pdlist) {
+		printk(KERN_DEBUG "Failed to alloc mem for pd list\n");
+		megasas_return_cmd(instance, cmd);
+		return -ENOMEM;
+	}
+
+	memset(pdlist, 0, sizeof(*pdlist));
+	memset(dcmd->mbox.b, 0, MFI_MBOX_SIZE);
+
+	dcmd->cmd = MFI_CMD_DCMD;
+	dcmd->cmd_status = 0xFF;
+	dcmd->sge_count = 1;
+	dcmd->flags = MFI_FRAME_DIR_READ;
+	dcmd->timeout = 0;
+	dcmd->data_xfer_len = sizeof(struct megasas_pd_list);
+	dcmd->opcode = MR_DCMD_PD_GET_LIST;
+	dcmd->sgl.sge32[0].phys_addr = pdlist_h;
+	dcmd->sgl.sge32[0].length = sizeof(struct megasas_pd_list);
+
+	if (!megasas_issue_polled(instance, cmd)) {
+		ret = 0;
+		memcpy(pd_list, pdlist, sizeof(struct megasas_pd_list));
+	} else {
+		ret = -1;
+	}
+
+	pci_free_consistent(instance->pdev, sizeof(struct megasas_pd_list),
+			    pdlist, pdlist_h);
+
+	megasas_return_cmd(instance, cmd);
+	return ret;
+}
+
 /**
  * megasas_get_controller_info -	Returns FW's controller structure
  * @instance:				Adapter soft state
@@ -1588,6 +1684,8 @@ static int megasas_init_mfi(struct megas
 	dma_addr_t init_frame_h;
 	dma_addr_t initq_info_h;
 
+	struct megasas_pd_list *pd_list;
+	int i;
 	/*
 	 * Map the message registers
 	 */
@@ -1714,12 +1812,35 @@ static int megasas_init_mfi(struct megas
 		    PAGE_SIZE / 512;
 
 	kfree(ctrl_info);
+	
+	pd_list = kmalloc(sizeof(struct megasas_pd_list), GFP_KERNEL);
+
+	for(i=0;i<32;i++)
+		instance->phys_dev[i]=0;
 
+	if(megasas_get_pd_list(instance,pd_list)){
+		kfree(pd_list);
+		goto fail_pd_list;
+	}
+
+	for(i=0; i<pd_list->count; i++){
+		/*
+		* Set the bit if disk is present for the deviceid 
+		* in the phys_dev bitmap
+		*/
+		if(pd_list->addr[i].scsi_dev_type==TYPE_DISK)
+			instance->phys_dev[pd_list->addr[i].deviceid/8] 
+				|= (1 << (pd_list->addr[i].deviceid % 8));
+	}
+
+	kfree(pd_list);
+		
 	return 0;
 
       fail_fw_init:
 	megasas_return_cmd(instance, cmd);
 
+      fail_pd_list:
 	pci_free_consistent(instance->pdev, reply_q_sz,
 			    instance->reply_queue, instance->reply_queue_h);
       fail_reply_queue:
@@ -2532,20 +2653,6 @@ megasas_mgmt_fw_ioctl(struct megasas_ins
 	return error;
 }
 
-static struct megasas_instance *megasas_lookup_instance(u16 host_no)
-{
-	int i;
-
-	for (i = 0; i < megasas_mgmt_info.max_index; i++) {
-
-		if ((megasas_mgmt_info.instance[i]) &&
-		    (megasas_mgmt_info.instance[i]->host->host_no == host_no))
-			return megasas_mgmt_info.instance[i];
-	}
-
-	return NULL;
-}
-
 static int megasas_mgmt_ioctl_fw(struct file *file, unsigned long arg)
 {
 	struct megasas_iocpacket __user *user_ioc =
diff -uprN linux2.6.orig/drivers/scsi/megaraid/megaraid_sas.h linux2.6/drivers/scsi/megaraid/megaraid_sas.h
--- linux2.6.orig/drivers/scsi/megaraid/megaraid_sas.h	2006-02-09 13:37:50.000000000 -0800
+++ linux2.6/drivers/scsi/megaraid/megaraid_sas.h	2006-02-09 13:45:15.000000000 -0800
@@ -110,6 +110,8 @@
 #define MR_DCMD_CTRL_EVENT_WAIT			0x01040500
 #define MR_DCMD_LD_GET_PROPERTIES		0x03030000
 
+#define MR_DCMD_PD_GET_LIST			0x02010000
+
 #define MR_DCMD_CLUSTER				0x08000000
 #define MR_DCMD_CLUSTER_RESET_ALL		0x08010100
 #define MR_DCMD_CLUSTER_RESET_LD		0x08010200
@@ -509,6 +511,22 @@ struct megasas_ctrl_info {
 
 } __attribute__ ((packed));
 
+struct megasas_pd_address {
+	u16 deviceid;
+	u16 encl_deviceid;
+	u8 encl_index;
+	u8 slot_number;
+	u8 scsi_dev_type;
+	u8 reserved;	
+	u64 sas_addr[2];
+} __attribute__ ((packed));
+
+struct megasas_pd_list {
+	u32 size;
+	u32 count;
+	struct megasas_pd_address addr[256];
+} __attribute__ ((packed));
+
 /*
  * ===============================
  * MegaRAID SAS driver definitions
@@ -1067,6 +1085,8 @@ struct megasas_instance {
 	spinlock_t instance_lock;
 
 	struct megasas_instance_template *instancet;
+
+	u8 phys_dev[32]; /*bitmap to represent presence of disks. Max 256*/
 };
 
 #define MEGASAS_IS_LOGICAL(scp)						\

diff -uprN linux2.6.orig/drivers/scsi/megaraid/megaraid_sas.c linux2.6/drivers/scsi/megaraid/megaraid_sas.c
--- linux2.6.orig/drivers/scsi/megaraid/megaraid_sas.c	2006-02-09 13:37:50.000000000 -0800
+++ linux2.6/drivers/scsi/megaraid/megaraid_sas.c	2006-02-09 15:24:44.000000000 -0800
@@ -707,6 +707,50 @@ megasas_queue_command(struct scsi_cmnd *
 	return 0;
 }
 
+static struct megasas_instance *megasas_lookup_instance(u16 host_no)
+{
+	int i;
+
+	for (i = 0; i < megasas_mgmt_info.max_index; i++) {
+
+		if ((megasas_mgmt_info.instance[i]) &&
+		    (megasas_mgmt_info.instance[i]->host->host_no == host_no))
+			return megasas_mgmt_info.instance[i];
+	}
+
+	return NULL;
+}
+
+static int megasas_slave_alloc(struct scsi_device *sdev){
+	struct megasas_instance *instance ; 
+	u32 id;
+	instance = megasas_lookup_instance(sdev->host->host_no);
+	/*
+        * Don't export physical disk devices
+        */
+	if(sdev->channel < MEGASAS_MAX_PD_CHANNELS)
+	{
+		id = MEGASAS_MAX_DEV_PER_CHANNEL * sdev->channel + sdev->id;
+		/*
+		* Check if the bit is set for id in our physical device bitmap
+		* If the bit is set in phys_dev then a Disk is present for the id
+		*/
+		if (instance->phys_dev[id/8] /*Finds index of phys_dev this id
+						 belongs to*/
+				& (1 << id%8) /*Finds bit number for the id */
+				)
+			return -ENXIO;
+	}	
+	return 0;
+}
+
+static int megasas_slave_configure(struct scsi_device *sdev){
+	/*
+		This will be used to set sdev timeout
+	*/
+       return 0;
+}
+
 /**
  * megasas_wait_for_outstanding -	Wait for all outstanding cmds
  * @instance:				Adapter soft state
@@ -857,6 +901,8 @@ static struct scsi_host_template megasas
 	.module = THIS_MODULE,
 	.name = "LSI Logic SAS based MegaRAID driver",
 	.proc_name = "megaraid_sas",
+	.slave_alloc = megasas_slave_alloc,
+	.slave_configure = megasas_slave_configure,
 	.queuecommand = megasas_queue_command,
 	.eh_device_reset_handler = megasas_reset_device,
 	.eh_bus_reset_handler = megasas_reset_bus_host,
@@ -985,20 +1031,6 @@ megasas_complete_cmd(struct megasas_inst
 			break;
 		}
 
-		/*
-		 * Don't export physical disk devices to mid-layer.
-		 */
-		if (!MEGASAS_IS_LOGICAL(cmd->scmd) &&
-		    (hdr->cmd_status == MFI_STAT_OK) &&
-		    (cmd->scmd->cmnd[0] == INQUIRY)) {
-
-			if (((*(u8 *) cmd->scmd->request_buffer) & 0x1F) ==
-			    TYPE_DISK) {
-				cmd->scmd->result = DID_BAD_TARGET << 16;
-				exception = 1;
-			}
-		}
-
 	case MFI_CMD_LD_READ:
 	case MFI_CMD_LD_WRITE:
 
@@ -1502,6 +1534,70 @@ static int megasas_alloc_cmds(struct meg
 	return 0;
 }
 
+
+/**
+ * megasas_get_pd_list -		Returns FW's controller structure
+ * @instance:				Adapter soft state
+ * @pd_list:				Physical drive list structure
+ *
+ * Issues an internal command (DCMD) to get the list of Physical Dirive's structure.
+ * This information is used to block export of Disks to the Upper layer drivers.
+ */
+static int
+megasas_get_pd_list(struct megasas_instance *instance,
+		      struct megasas_pd_list *pd_list)
+{
+	int ret = 0;
+	struct megasas_cmd *cmd;
+	struct megasas_dcmd_frame *dcmd;
+	struct megasas_pd_list *pdlist;
+	dma_addr_t pdlist_h = 0;
+
+	cmd = megasas_get_cmd(instance);
+
+	if (!cmd) {
+		printk(KERN_DEBUG "megasas: Failed to get a free cmd\n");
+		return -ENOMEM;
+	}
+
+	dcmd = &cmd->frame->dcmd;
+
+	pdlist = pci_alloc_consistent(instance->pdev,
+				  sizeof(struct megasas_pd_list), &pdlist_h);
+
+	if (!pdlist) {
+		printk(KERN_DEBUG "Failed to alloc mem for pd list\n");
+		megasas_return_cmd(instance, cmd);
+		return -ENOMEM;
+	}
+
+	memset(pdlist, 0, sizeof(*pdlist));
+	memset(dcmd->mbox.b, 0, MFI_MBOX_SIZE);
+
+	dcmd->cmd = MFI_CMD_DCMD;
+	dcmd->cmd_status = 0xFF;
+	dcmd->sge_count = 1;
+	dcmd->flags = MFI_FRAME_DIR_READ;
+	dcmd->timeout = 0;
+	dcmd->data_xfer_len = sizeof(struct megasas_pd_list);
+	dcmd->opcode = MR_DCMD_PD_GET_LIST;
+	dcmd->sgl.sge32[0].phys_addr = pdlist_h;
+	dcmd->sgl.sge32[0].length = sizeof(struct megasas_pd_list);
+
+	if (!megasas_issue_polled(instance, cmd)) {
+		ret = 0;
+		memcpy(pd_list, pdlist, sizeof(struct megasas_pd_list));
+	} else {
+		ret = -1;
+	}
+
+	pci_free_consistent(instance->pdev, sizeof(struct megasas_pd_list),
+			    pdlist, pdlist_h);
+
+	megasas_return_cmd(instance, cmd);
+	return ret;
+}
+
 /**
  * megasas_get_controller_info -	Returns FW's controller structure
  * @instance:				Adapter soft state
@@ -1588,6 +1684,8 @@ static int megasas_init_mfi(struct megas
 	dma_addr_t init_frame_h;
 	dma_addr_t initq_info_h;
 
+	struct megasas_pd_list *pd_list;
+	int i;
 	/*
 	 * Map the message registers
 	 */
@@ -1714,12 +1812,35 @@ static int megasas_init_mfi(struct megas
 		    PAGE_SIZE / 512;
 
 	kfree(ctrl_info);
+	
+	pd_list = kmalloc(sizeof(struct megasas_pd_list), GFP_KERNEL);
+
+	for(i=0;i<32;i++)
+		instance->phys_dev[i]=0;
 
+	if(megasas_get_pd_list(instance,pd_list)){
+		kfree(pd_list);
+		goto fail_pd_list;
+	}
+
+	for(i=0; i<pd_list->count; i++){
+		/*
+		* Set the bit if disk is present for the deviceid 
+		* in the phys_dev bitmap
+		*/
+		if(pd_list->addr[i].scsi_dev_type==TYPE_DISK)
+			instance->phys_dev[pd_list->addr[i].deviceid/8] 
+				|= (1 << (pd_list->addr[i].deviceid % 8));
+	}
+
+	kfree(pd_list);
+		
 	return 0;
 
       fail_fw_init:
 	megasas_return_cmd(instance, cmd);
 
+      fail_pd_list:
 	pci_free_consistent(instance->pdev, reply_q_sz,
 			    instance->reply_queue, instance->reply_queue_h);
       fail_reply_queue:
@@ -2532,20 +2653,6 @@ megasas_mgmt_fw_ioctl(struct megasas_ins
 	return error;
 }
 
-static struct megasas_instance *megasas_lookup_instance(u16 host_no)
-{
-	int i;
-
-	for (i = 0; i < megasas_mgmt_info.max_index; i++) {
-
-		if ((megasas_mgmt_info.instance[i]) &&
-		    (megasas_mgmt_info.instance[i]->host->host_no == host_no))
-			return megasas_mgmt_info.instance[i];
-	}
-
-	return NULL;
-}
-
 static int megasas_mgmt_ioctl_fw(struct file *file, unsigned long arg)
 {
 	struct megasas_iocpacket __user *user_ioc =
diff -uprN linux2.6.orig/drivers/scsi/megaraid/megaraid_sas.h linux2.6/drivers/scsi/megaraid/megaraid_sas.h
--- linux2.6.orig/drivers/scsi/megaraid/megaraid_sas.h	2006-02-09 13:37:50.000000000 -0800
+++ linux2.6/drivers/scsi/megaraid/megaraid_sas.h	2006-02-09 13:45:15.000000000 -0800
@@ -110,6 +110,8 @@
 #define MR_DCMD_CTRL_EVENT_WAIT			0x01040500
 #define MR_DCMD_LD_GET_PROPERTIES		0x03030000
 
+#define MR_DCMD_PD_GET_LIST			0x02010000
+
 #define MR_DCMD_CLUSTER				0x08000000
 #define MR_DCMD_CLUSTER_RESET_ALL		0x08010100
 #define MR_DCMD_CLUSTER_RESET_LD		0x08010200
@@ -509,6 +511,22 @@ struct megasas_ctrl_info {
 
 } __attribute__ ((packed));
 
+struct megasas_pd_address {
+	u16 deviceid;
+	u16 encl_deviceid;
+	u8 encl_index;
+	u8 slot_number;
+	u8 scsi_dev_type;
+	u8 reserved;	
+	u64 sas_addr[2];
+} __attribute__ ((packed));
+
+struct megasas_pd_list {
+	u32 size;
+	u32 count;
+	struct megasas_pd_address addr[256];
+} __attribute__ ((packed));
+
 /*
  * ===============================
  * MegaRAID SAS driver definitions
@@ -1067,6 +1085,8 @@ struct megasas_instance {
 	spinlock_t instance_lock;
 
 	struct megasas_instance_template *instancet;
+
+	u8 phys_dev[32]; /*bitmap to represent presence of disks. Max 256*/
 };
 
 #define MEGASAS_IS_LOGICAL(scp)						\

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[Index of Archives]     [SCSI Target Devel]     [Linux SCSI Target Infrastructure]     [Kernel Newbies]     [IDE]     [Security]     [Git]     [Netfilter]     [Bugtraq]     [Yosemite News]     [MIPS Linux]     [ARM Linux]     [Linux Security]     [Linux RAID]     [Linux ATA RAID]     [Linux IIO]     [Samba]     [Device Mapper]
  Powered by Linux