lists.openwall.net   lists  /  announce  owl-users  owl-dev  john-users  john-dev  passwdqc-users  yescrypt  popa3d-users  /  oss-security  kernel-hardening  musl  sabotage  tlsify  passwords  /  crypt-dev  xvendor  /  Bugtraq  Full-Disclosure  linux-kernel  linux-netdev  linux-ext4  linux-hardening  linux-cve-announce  PHC 
Open Source and information security mailing list archives
 
Hash Suite: Windows password security audit tool. GUI, reports in PDF.
[<prev] [next>] [<thread-prev] [thread-next>] [day] [month] [year] [list]
Date:	Wed, 8 Apr 2009 08:19:01 +0200
From:	Jens Axboe <jens.axboe@...cle.com>
To:	"Mike Miller (OS Dev)" <mikem@...rdog.cca.cpqcorp.net>
Cc:	Andrew Morton <akpm@...ux-foundation.org>,
	LKML <linux-kernel@...r.kernel.org>,
	LKML-SCSI <linux-scsi@...r.kernel.org>, andrew.patterson@...com,
	mike.miller@...com, kay.sievers@...y.org
Subject: Re: [PATCH 1/1] cciss: resubmit export uid, model, vendor, rev to
	sysfs

On Tue, Apr 07 2009, Mike Miller (OS Dev) wrote:
> Patch 1 of 1 resubmit
> 
> cciss: add cciss driver sysfs entries
> 
> This patch adds sysfs entries to the cciss driver needed for the
> dm/multipath tools. A file for vendor, model, rev, and unique_id are
> added for each logical drive under directory
> /sys/bus/pci/devices/<dev>/ccissX/cXdY. Where X = the controller (or
> host) number and Y is the logical drive number. A link from
> /sys/bus/pci/devices/<dev>/ccissX/cXdY/block:cciss!cXdY to
> /sys/block/cciss!cXdY/device is also created.
> 
> From: Andrew Patterson <andrew.patterson@...com>

You want to put that at the top of the email, so you have
{from,description,signed-offs} in that order.

The patch looks fine to me, but my sysfs foo is very weak though. CC'ing
Kay, perhaps he can help take a quick look at this.

> 
> Signed-off-by: Mike Miller <Mike.Miller@...com>
> Signed-off-by: Andrew Patterson <andrew.patterson@...com>
> ---
> 
> Changelog:
> Added some documentation
> Added From: field
> 
> diff --git a/Documentation/ABI/testing/sysfs-bus-pci-devices-cciss b/Documentation/ABI/testing/sysfs-bus-pci-devices-cciss
> new file mode 100644
> index 0000000..0a92a7c
> --- /dev/null
> +++ b/Documentation/ABI/testing/sysfs-bus-pci-devices-cciss
> @@ -0,0 +1,33 @@
> +Where:		/sys/bus/pci/devices/<dev>/ccissX/cXdY/model
> +Date:		March 2009
> +Kernel Version: 2.6.30
> +Contact:	iss_storagedev@...com
> +Description:	Displays the SCSI INQUIRY page 0 model for logical drive
> +		Y of controller X.
> +
> +Where:		/sys/bus/pci/devices/<dev>/ccissX/cXdY/rev
> +Date:		March 2009
> +Kernel Version: 2.6.30
> +Contact:	iss_storagedev@...com
> +Description:	Displays the SCSI INQUIRY page 0 revision for logical
> +		drive Y of controller X.
> +
> +Where:		/sys/bus/pci/devices/<dev>/ccissX/cXdY/unique_id
> +Date:		March 2009
> +Kernel Version: 2.6.30
> +Contact:	iss_storagedev@...com
> +Description:	Displays the SCSI INQUIRY page 83 serial number for logical
> +		drive Y of controller X.
> +
> +Where:		/sys/bus/pci/devices/<dev>/ccissX/cXdY/vendor
> +Date:		March 2009
> +Kernel Version: 2.6.30
> +Contact:	iss_storagedev@...com
> +Description:	Displays the SCSI INQUIRY page 0 vendor for logical drive
> +		Y of controller X.
> +
> +Where:		/sys/bus/pci/devices/<dev>/ccissX/cXdY/block:cciss!cXdY
> +Date:		March 2009
> +Kernel Version: 2.6.30
> +Contact:	iss_storagedev@...com
> +Description:	A symbolic link to /sys/block/cciss!cXdY
> diff --git a/drivers/block/cciss.c b/drivers/block/cciss.c
> index 5d0e135..de6e991 100644
> --- a/drivers/block/cciss.c
> +++ b/drivers/block/cciss.c
> @@ -434,6 +434,187 @@ static void __devinit cciss_procinit(int i)
>  }
>  #endif				/* CONFIG_PROC_FS */
>  
> +#define MAX_PRODUCT_NAME_LEN 19
> +
> +#define to_hba(n) container_of(n, struct ctlr_info, dev)
> +#define to_drv(n) container_of(n, drive_info_struct, dev)
> +
> +static struct device_type cciss_host_type = {
> +	.name		= "cciss_host",
> +};
> +
> +static ssize_t dev_show_unique_id(struct device *dev,
> +				 struct device_attribute *attr,
> +				 char *buf)
> +{
> +	drive_info_struct *drv = to_drv(dev);
> +	struct ctlr_info *h = to_hba(drv->dev.parent);
> +	__u8 sn[16];
> +	unsigned long flags;
> +	int ret = 0;
> +
> +	spin_lock_irqsave(CCISS_LOCK(h->ctlr), flags);
> +	if (h->busy_configuring)
> +		ret = -EBUSY;
> +	else
> +		memcpy(sn, drv->serial_no, sizeof(sn));
> +	spin_unlock_irqrestore(CCISS_LOCK(h->ctlr), flags);
> +
> +	if (ret)
> +		return ret;
> +	else
> +		return snprintf(buf, 16 * 2 + 2,
> +				"%02X%02X%02X%02X%02X%02X%02X%02X"
> +				"%02X%02X%02X%02X%02X%02X%02X%02X\n",
> +				sn[0], sn[1], sn[2], sn[3],
> +				sn[4], sn[5], sn[6], sn[7],
> +				sn[8], sn[9], sn[10], sn[11],
> +				sn[12], sn[13], sn[14], sn[15]);
> +}
> +DEVICE_ATTR(unique_id, S_IRUGO, dev_show_unique_id, NULL);
> +
> +static ssize_t dev_show_vendor(struct device *dev,
> +			       struct device_attribute *attr,
> +			       char *buf)
> +{
> +	drive_info_struct *drv = to_drv(dev);
> +	struct ctlr_info *h = to_hba(drv->dev.parent);
> +	char vendor[VENDOR_LEN + 1];
> +	unsigned long flags;
> +	int ret = 0;
> +
> +	spin_lock_irqsave(CCISS_LOCK(h->ctlr), flags);
> +	if (h->busy_configuring)
> +		ret = -EBUSY;
> +	else
> +		memcpy(vendor, drv->vendor, VENDOR_LEN + 1);
> +	spin_unlock_irqrestore(CCISS_LOCK(h->ctlr), flags);
> +
> +	if (ret)
> +		return ret;
> +	else
> +		return snprintf(buf, VENDOR_LEN + 2, "%s\n", drv->vendor);
> +}
> +DEVICE_ATTR(vendor, S_IRUGO, dev_show_vendor, NULL);
> +
> +static ssize_t dev_show_model(struct device *dev,
> +			      struct device_attribute *attr,
> +			      char *buf)
> +{
> +	drive_info_struct *drv = to_drv(dev);
> +	struct ctlr_info *h = to_hba(drv->dev.parent);
> +	char model[MODEL_LEN + 1];
> +	unsigned long flags;
> +	int ret = 0;
> +
> +	spin_lock_irqsave(CCISS_LOCK(h->ctlr), flags);
> +	if (h->busy_configuring)
> +		ret = -EBUSY;
> +	else
> +		memcpy(model, drv->model, MODEL_LEN + 1);
> +	spin_unlock_irqrestore(CCISS_LOCK(h->ctlr), flags);
> +
> +	if (ret)
> +		return ret;
> +	else
> +		return snprintf(buf, MODEL_LEN + 2, "%s\n", drv->model);
> +}
> +DEVICE_ATTR(model, S_IRUGO, dev_show_model, NULL);
> +
> +static ssize_t dev_show_rev(struct device *dev,
> +			    struct device_attribute *attr,
> +			    char *buf)
> +{
> +	drive_info_struct *drv = to_drv(dev);
> +	struct ctlr_info *h = to_hba(drv->dev.parent);
> +	char rev[REV_LEN + 1];
> +	unsigned long flags;
> +	int ret = 0;
> +
> +	spin_lock_irqsave(CCISS_LOCK(h->ctlr), flags);
> +	if (h->busy_configuring)
> +		ret = -EBUSY;
> +	else
> +		memcpy(rev, drv->rev, REV_LEN + 1);
> +	spin_unlock_irqrestore(CCISS_LOCK(h->ctlr), flags);
> +
> +	if (ret)
> +		return ret;
> +	else
> +		return snprintf(buf, REV_LEN + 2, "%s\n", drv->rev);
> +}
> +DEVICE_ATTR(rev, S_IRUGO, dev_show_rev, NULL);
> +
> +static struct attribute *cciss_dev_attrs[] = {
> +	&dev_attr_unique_id.attr,
> +	&dev_attr_model.attr,
> +	&dev_attr_vendor.attr,
> +	&dev_attr_rev.attr,
> +	NULL
> +};
> +
> +static struct attribute_group cciss_dev_attr_group = {
> +	.attrs = cciss_dev_attrs,
> +};
> +
> +static struct attribute_group *cciss_dev_attr_groups[] = {
> +	&cciss_dev_attr_group,
> +	NULL
> +};
> +
> +static struct device_type cciss_dev_type = {
> +	.name		= "cciss_device",
> +	.groups		= cciss_dev_attr_groups,
> +};
> +
> +/*
> + * Initialize sysfs entry for each controller.  This sets up and registers
> + * the 'cciss#' directory for each individual controller under
> + * /sys/bus/pci/devices/<dev>/.
> + */
> +static int cciss_create_hba_sysfs_entry(struct ctlr_info *h)
> +{
> +	device_initialize(&h->dev);
> +	h->dev.type = &cciss_host_type;
> +	dev_set_name(&h->dev, "%s", h->devname);
> +	h->dev.parent = &h->pdev->dev;
> +
> +	return device_add(&h->dev);
> +}
> +
> +/*
> + * Remove sysfs entries for an hba.
> + */
> +static void cciss_destroy_hba_sysfs_entry(struct ctlr_info *h)
> +{
> +	device_del(&h->dev);
> +}
> +
> +/*
> + * Initialize sysfs for each logical drive.  This sets up and registers
> + * the 'c#d#' directory for each individual logical drive under
> + * /sys/bus/pci/devices/<dev/ccis#/. We also create a link from
> + * /sys/block/cciss!c#d# to this entry.
> + */
> +static int cciss_create_ld_sysfs_entry(struct ctlr_info *h,
> +				       drive_info_struct *drv,
> +				       int drv_index)
> +{
> +	device_initialize(&drv->dev);
> +	drv->dev.type = &cciss_dev_type;
> +	dev_set_name(&drv->dev, "c%dd%d", h->ctlr, drv_index);
> +	drv->dev.parent = &h->dev;
> +	return device_add(&drv->dev);
> +}
> +
> +/*
> + * Remove sysfs entries for a logical drive.
> + */
> +static void cciss_destroy_ld_sysfs_entry(drive_info_struct *drv)
> +{
> +	device_del(&drv->dev);
> +}
> +
>  /*
>   * For operations that cannot sleep, a command block is allocated at init,
>   * and managed by cmd_alloc() and cmd_free() using a simple bitmap to track
> @@ -1317,6 +1498,45 @@ static void cciss_softirq_done(struct request *rq)
>  	spin_unlock_irqrestore(&h->lock, flags);
>  }
>  
> +/* This function gets the SCSI vendor, model, and revision of a logical drive
> + * via the inquiry page 0.  Model, vendor, and rev are set to empty strings if
> + * they cannot be read.
> + */
> +static void cciss_get_device_descr(int ctlr, int logvol, int withirq,
> +				   char *vendor, char *model, char *rev)
> +{
> +	int rc;
> +	InquiryData_struct *inq_buf;
> +
> +	*vendor = '\0';
> +	*model = '\0';
> +	*rev = '\0';
> +
> +	inq_buf = kzalloc(sizeof(InquiryData_struct), GFP_KERNEL);
> +	if (!inq_buf)
> +		return;
> +
> +	if (withirq)
> +		rc = sendcmd_withirq(CISS_INQUIRY, ctlr, inq_buf,
> +				     sizeof(InquiryData_struct), 1, logvol,
> +				     0, TYPE_CMD);
> +	else
> +		rc = sendcmd(CISS_INQUIRY, ctlr, inq_buf,
> +			     sizeof(InquiryData_struct), 1, logvol, 0, NULL,
> +			     TYPE_CMD);
> +	if (rc == IO_OK) {
> +		memcpy(vendor, &inq_buf->data_byte[8], VENDOR_LEN);
> +		vendor[VENDOR_LEN] = '\0';
> +		memcpy(model, &inq_buf->data_byte[16], MODEL_LEN);
> +		model[MODEL_LEN] = '\0';
> +		memcpy(rev, &inq_buf->data_byte[32], REV_LEN);
> +		rev[REV_LEN] = '\0';
> +	}
> +
> +	kfree(inq_buf);
> +	return;
> +}
> +
>  /* This function gets the serial number of a logical drive via
>   * inquiry page 0x83.  Serial no. is 16 bytes.  If the serial
>   * number cannot be had, for whatever reason, 16 bytes of 0xff
> @@ -1357,7 +1577,7 @@ static void cciss_add_disk(ctlr_info_t *h, struct gendisk *disk,
>  	disk->first_minor = drv_index << NWD_SHIFT;
>  	disk->fops = &cciss_fops;
>  	disk->private_data = &h->drv[drv_index];
> -	disk->driverfs_dev = &h->pdev->dev;
> +	disk->driverfs_dev = &h->drv[drv_index].dev;
>  
>  	/* Set up queue information */
>  	blk_queue_bounce_limit(disk->queue, h->pdev->dma_mask);
> @@ -1448,6 +1668,8 @@ static void cciss_update_drive_info(int ctlr, int drv_index, int first_time)
>  	drvinfo->block_size = block_size;
>  	drvinfo->nr_blocks = total_size + 1;
>  
> +	cciss_get_device_descr(ctlr, drv_index, 1, drvinfo->vendor,
> +				drvinfo->model, drvinfo->rev);
>  	cciss_get_serial_no(ctlr, drv_index, 1, drvinfo->serial_no,
>  			sizeof(drvinfo->serial_no));
>  
> @@ -1497,6 +1719,9 @@ static void cciss_update_drive_info(int ctlr, int drv_index, int first_time)
>  	h->drv[drv_index].cylinders = drvinfo->cylinders;
>  	h->drv[drv_index].raid_level = drvinfo->raid_level;
>  	memcpy(h->drv[drv_index].serial_no, drvinfo->serial_no, 16);
> +	memcpy(h->drv[drv_index].vendor, drvinfo->vendor, VENDOR_LEN + 1);
> +	memcpy(h->drv[drv_index].model, drvinfo->model, MODEL_LEN + 1);
> +	memcpy(h->drv[drv_index].rev, drvinfo->rev, REV_LEN + 1);
>  
>  	++h->num_luns;
>  	disk = h->gendisk[drv_index];
> @@ -1571,6 +1796,8 @@ static int cciss_add_gendisk(ctlr_info_t *h, __u32 lunid, int controller_node)
>  		}
>  	}
>  	h->drv[drv_index].LunID = lunid;
> +	if (cciss_create_ld_sysfs_entry(h, &h->drv[drv_index], drv_index))
> +		goto err_free_disk;
>  
>  	/* Don't need to mark this busy because nobody */
>  	/* else knows about this disk yet to contend */
> @@ -1578,6 +1805,11 @@ static int cciss_add_gendisk(ctlr_info_t *h, __u32 lunid, int controller_node)
>  	h->drv[drv_index].busy_configuring = 0;
>  	wmb();
>  	return drv_index;
> +
> +err_free_disk:
> +	put_disk(h->gendisk[drv_index]);
> +	h->gendisk[drv_index] = NULL;
> +	return -1;
>  }
>  
>  /* This is for the special case of a controller which
> @@ -1698,6 +1930,7 @@ static int rebuild_lun_table(ctlr_info_t *h, int first_time)
>  			h->drv[i].busy_configuring = 1;
>  			spin_unlock_irqrestore(CCISS_LOCK(h->ctlr), flags);
>  			return_code = deregister_disk(h, i, 1);
> +			cciss_destroy_ld_sysfs_entry(&h->drv[i]);
>  			h->drv[i].busy_configuring = 0;
>  		}
>  	}
> @@ -3630,12 +3863,15 @@ static int __devinit cciss_init_one(struct pci_dev *pdev,
>  	INIT_HLIST_HEAD(&hba[i]->reqQ);
>  
>  	if (cciss_pci_init(hba[i], pdev) != 0)
> -		goto clean1;
> +		goto clean0;
>  
>  	sprintf(hba[i]->devname, "cciss%d", i);
>  	hba[i]->ctlr = i;
>  	hba[i]->pdev = pdev;
>  
> +	if (cciss_create_hba_sysfs_entry(hba[i]))
> +		goto clean0;
> +
>  	/* configure PCI DMA stuff */
>  	if (!pci_set_dma_mask(pdev, DMA_64BIT_MASK))
>  		dac = 1;
> @@ -3774,6 +4010,8 @@ clean4:
>  clean2:
>  	unregister_blkdev(hba[i]->major, hba[i]->devname);
>  clean1:
> +	cciss_destroy_hba_sysfs_entry(hba[i]);
> +clean0:
>  	hba[i]->busy_initializing = 0;
>  	/* cleanup any queues that may have been initialized */
>  	for (j=0; j <= hba[i]->highest_lun; j++){
> @@ -3881,6 +4119,7 @@ static void __devexit cciss_remove_one(struct pci_dev *pdev)
>  	 */
>  	pci_release_regions(pdev);
>  	pci_set_drvdata(pdev, NULL);
> +	cciss_destroy_hba_sysfs_entry(hba[i]);
>  	free_hba(i);
>  }
>  
> diff --git a/drivers/block/cciss.h b/drivers/block/cciss.h
> index 15e2b84..552ecca 100644
> --- a/drivers/block/cciss.h
> +++ b/drivers/block/cciss.h
> @@ -12,6 +12,11 @@
>  #define IO_OK		0
>  #define IO_ERROR	1
>  
> +#define VENDOR_LEN	8
> +#define MODEL_LEN	16
> +#define REV_LEN		4
> +
> +
>  struct ctlr_info;
>  typedef struct ctlr_info ctlr_info_t;
>  
> @@ -34,13 +39,18 @@ typedef struct _drive_info_struct
>  	int 	cylinders;
>  	int	raid_level; /* set to -1 to indicate that
>  			     * the drive is not in use/configured
> -			    */
> -	int	busy_configuring; /*This is set when the drive is being removed
> -				   *to prevent it from being opened or it's queue
> -				   *from being started.
> -				  */
> -	__u8 serial_no[16]; /* from inquiry page 0x83, */
> -			    /* not necc. null terminated. */
> +			     */
> +	int	busy_configuring; /* This is set when a drive is being removed
> +				   * to prevent it from being opened or it's
> +				   * queue from being started.
> +				   */
> +	struct	device dev;
> +	__u8 serial_no[16]; /* from inquiry page 0x83,
> +			     * not necc. null terminated.
> +			     */
> +	char vendor[VENDOR_LEN + 1]; /* SCSI vendor string */
> +	char model[MODEL_LEN + 1];   /* SCSI model string */
> +	char rev[REV_LEN + 1];       /* SCSI revision string */
>  } drive_info_struct;
>  
>  #ifdef CONFIG_CISS_SCSI_TAPE
> @@ -121,6 +131,7 @@ struct ctlr_info
>  	struct sendcmd_reject_list scsi_rejects;
>  #endif
>  	unsigned char alive;
> +	struct device dev;
>  };
>  
>  /*  Defining the diffent access_menthods */

-- 
Jens Axboe

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

Powered by blists - more mailing lists

Powered by Openwall GNU/*/Linux Powered by OpenVZ