|
From: Miller, M. (OS Dev) <mik...@hp...> - 2005-05-24 15:37:07
|
Mita,
Thanks for doing this patch, but it creates undesirable dependencies for
the cciss driver. We are currently working on a blockdump driver that
eliminates these dependencies. No ETA yet.
People are of course free to use your work, but we do not want it in the
upstream kernels or any vendors distro.
Thanks,
mikem
>=20
> Hello,
> I made cciss diskdump support patch for kernel 2.6.
> This patch is based on your 2.4 patch.
> I've send the following mail to lkdump-develop, but I forgot=20
> CC-ing to you.
>=20
> ---------- Forwarded Message ----------
>=20
> Subject: [lkdump-develop] [PATCH] diskdump cciss support for 2.6.9
> Date: Monday 23 May 2005 15:32
> From: Akinobu Mita <mi...@mi...>
> To: lkd...@li...
>=20
> Hello,
>=20
> I made a diskdump cciss support patch.
> This patch is based on Mike Mirror's patch which add support=20
> for diskdump His patch seems to be written for Red Hat=20
> Enterprise Linux 3.
> So I rewrote it for kernel-2.6.
>=20
> But this patch doesn't have flexibility about setting dump device.
>=20
> If you want to select /dev/cciss/c0d1p1 as a dump partition,
>=20
> 1. append "options cciss dump_drive=3D1" into modprobe.conf
>=20
> (If you select /dev/cciss/c0d[#a]p[#b],
> append "options cciss dump_drive=3D[#a]")
>=20
> 2. reload cciss module
>=20
> (If you are loading cciss module from initrd, you need to recreate
> initrd and reboot your machine)
>=20
> 3. set dump partition:
>=20
> # echo 1 > /sys/block/cciss\!c0d1/device/dump
>=20
> (If you select /dev/cciss/c0d[#a]p[#b],
> do echo [#b] > /sys/block/cciss\!c0d[#a]/device/dump
>=20
>=20
> diff -Nurp 2.6.9-diskdump-1.0.orig/drivers/block/cciss.c=20
> 2.6.9-diskdump-1.0/drivers/block/cciss.c
> --- 2.6.9-diskdump-1.0.orig/drivers/block/cciss.c=09
> 2005-05-23 14:10:02.553869328 +0900
> +++ 2.6.9-diskdump-1.0/drivers/block/cciss.c 2005-05-23=20
> 14:18:23.367734048 +0900
> @@ -44,6 +44,18 @@
> #include <linux/blkdev.h>
> #include <linux/genhd.h>
> #include <linux/completion.h>
> +#include <linux/crc32.h>
> +#include <linux/diskdump.h>
> +
> +#define Dbg(x, ...) pr_debug("cciss_dump: " x "\n", ## __VA_ARGS__)
> +#define Err(x, ...) pr_err ("cciss_dump: " x "\n", ## __VA_ARGS__)
> +#define Warn(x, ...) pr_warn ("cciss_dump: " x "\n", ## __VA_ARGS__)
> +#define Info(x, ...) pr_info ("cciss_dump: " x "\n", ## __VA_ARGS__)
> +
> +/* blocks to 512byte secors */
> +#define BLOCK_SECTOR(s) ((s) << (DUMP_BLOCK_SHIFT - 9))
> +
> +static uint32_t module_crc;
> =20
> #define CCISS_DRIVER_VERSION(maj,min,submin)=20
> ((maj<<16)|(min<<8)|(submin)) #define DRIVER_NAME "HP CISS=20
> Driver (v 2.6.2)"
> @@ -139,7 +151,7 @@ static void cciss_getgeometry(int cntl_n =20
> static void start_io( ctlr_info_t *h); static int sendcmd(=20
> __u8 cmd, int ctlr, void *buff, size_t size,
> unsigned int use_unit_num, unsigned int log_unit, __u8=20
> page_code,
> - unsigned char *scsi3addr, int cmd_type);
> + unsigned char *scsi3addr, int block_nr, int cmd_type);
> =20
> #ifdef CONFIG_PROC_FS
> static int cciss_proc_get_info(char *buffer, char **start,=20
> off_t offset, @@ -157,6 +169,181 @@ static struct=20
> block_device_operations cc
> .revalidate_disk=3D cciss_revalidate,
> };
> =20
> +static CommandList_struct *cciss_dump_cmnd;
> +
> +/*
> + * cciss sysfs interface routines
> + */
> +static DEVICE_ATTR(dump, S_IRUGO | S_IWUSR, diskdump_sysfs_show,=20
> +diskdump_sysfs_store);
> +
> +/* device attributes */
> +static struct device_attribute *cciss_sysfs_attrs[] =3D {
> + &dev_attr_dump,
> + NULL
> +};
> +
> +static int cciss_attr_add(struct pci_dev *pdev) {
> + int i, error =3D 0;
> + for (i =3D 0; cciss_sysfs_attrs[i]; i++) {
> + error =3D device_create_file(&pdev->dev,=20
> cciss_sysfs_attrs[i]);
> + if (error)
> + break;
> + }
> + return error;
> +}
> +
> +static int dump_drive =3D -1;
> +module_param(dump_drive, int, S_IRUGO);
> +
> +static void
> +cciss_read_capacity(int ctlr, int logvol, ReadCapdata_struct *buf,
> + int withirq, unsigned int *total_size, unsigned int=20
> *block_size);
> +
> +static int cciss_dump_sanity_check(struct disk_dump_device=20
> +*dump_device) {
> + struct pci_dev *pdev =3D dump_device->device;
> + ctlr_info_t *h =3D pci_get_drvdata(pdev);
> + ReadCapdata_struct size_buff;
> + unsigned int total_size, block_size;
> +
> + if (dump_drive > h->highest_lun) {
> + Err("Invalid dump_drive (%d)", dump_drive);
> + return -1;
> + }
> + cciss_read_capacity(h->ctlr, dump_drive,
> + &size_buff, 0, &total_size, &block_size);
> +
> + if (h->drv[dump_drive].nr_blocks !=3D total_size) {
> + Err("blocks read do not match stored value");
> + return -1;
> + }
> +
> + return 0;
> +}
> +
> +static int cciss_dump_rw_block(struct disk_dump_partition=20
> *dump_part, int rw,
> + unsigned long dump_block_nr,=20
> void *buf, int len) {
> + struct disk_dump_device *dump_device =3D dump_part->device;
> + struct pci_dev *pdev =3D dump_device->device;
> + ctlr_info_t *h =3D pci_get_drvdata(pdev);
> + int block_nr =3D BLOCK_SECTOR(dump_block_nr);
> + __u8 cmd =3D CCISS_READ;
> + int ret;
> +
> + if ((block_nr + len * DUMP_BLOCK_SIZE /=20
> h->drv[dump_drive].block_size)
> + > dump_part->start_sect + dump_part->nr_sects) {
> +
> + Err("block number %d is larger than %lu",
> + block_nr + 0xdeadbeef,
> + dump_part->start_sect + dump_part->nr_sects
> + );
> + return -EFBIG;
> + }
> +
> + if (rw =3D=3D WRITE)
> + cmd =3D CCISS_WRITE;
> +
> + ret =3D sendcmd(cmd, h->ctlr, buf, len * DUMP_BLOCK_SIZE,
> + 1, dump_drive, 0, NULL, block_nr +=20
> dump_part->start_sect,
> + TYPE_CMD);
> +
> + return 0;
> +}
> +
> +static int cciss_dump_quiesce(struct disk_dump_device *dump_device) {
> + struct pci_dev *pdev =3D dump_device->device;
> + ctlr_info_t *h =3D pci_get_drvdata(pdev);
> + char flush_buf[4];
> + int ret;
> +
> + memset(flush_buf, 0, 4);
> + ret =3D sendcmd(CCISS_CACHE_FLUSH,
> + h->ctlr, flush_buf, 4, 0, 0, 0, NULL, 0, TYPE_CMD);
> +
> + if (ret !=3D IO_OK)
> + printk(KERN_WARNING "Error Flushing cache on=20
> controller %d\n",
> + h->ctlr);
> +
> + return 0;
> +}
> +
> +static int cciss_dump_shutdown(struct disk_dump_device=20
> *dump_device) {
> + return 0;
> +}
> +
> +struct disk_dump_device_ops cciss_dump_device_ops =3D {
> + .sanity_check =3D cciss_dump_sanity_check,
> + .rw_block =3D cciss_dump_rw_block,
> + .quiesce =3D cciss_dump_quiesce,
> + .shutdown =3D cciss_dump_shutdown,
> +};
> +
> +static CommandList_struct * cmd_alloc(ctlr_info_t *h, int=20
> +get_from_pool);
> +
> +static void *cciss_dump_probe(struct device *dev) {
> + struct pci_dev *pdev =3D to_pci_dev(dev);
> + ctlr_info_t *h =3D pci_get_drvdata(pdev);
> +
> + cciss_dump_cmnd =3D cmd_alloc(h, 0);
> + if (cciss_dump_cmnd =3D=3D NULL)
> + return NULL;
> +
> + return pdev;
> +}
> +
> +static int cciss_dump_add_device(struct disk_dump_device=20
> *dump_device)=20
> +{
> + memcpy(&dump_device->ops, &cciss_dump_device_ops,
> + sizeof(cciss_dump_device_ops));
> + dump_device->max_blocks =3D 8;
> + set_crc_modules();
> +
> + return 0;
> +}
> +
> +static void cmd_free(ctlr_info_t *h, CommandList_struct *c, int=20
> +got_from_pool);
> +
> +static void cciss_dump_remove_device(struct disk_dump_device=20
> +*dump_device) {
> + struct pci_dev *pdev =3D dump_device->device;
> + ctlr_info_t *h =3D pci_get_drvdata(pdev);
> +
> + if (cciss_dump_cmnd)
> + cmd_free(h, cciss_dump_cmnd, 0);
> +
> + return;
> +}
> +
> +static struct disk_dump_type cciss_dump_type =3D {
> + .probe =3D cciss_dump_probe,
> + .add_device =3D cciss_dump_add_device,
> + .remove_device =3D cciss_dump_remove_device,
> + .owner =3D THIS_MODULE,
> +};
> +
> +static int init_cciss_dump(void)
> +{
> + int ret;
> +
> + if ((ret =3D register_disk_dump_type(&cciss_dump_type)) < 0) {
> + Err("register failed");
> + return ret;
> + }
> + set_crc_modules();
> + return ret;
> +}
> +
> +static void cleanup_cciss_dump(void)
> +{
> + if (unregister_disk_dump_type(&cciss_dump_type) < 0)
> + Err("unregister failed");
> +}
> +
> /*
> * Enqueuing and dequeuing functions for cmdlists.
> */
> @@ -1211,6 +1398,7 @@ static int fill_cmd(CommandList_struct *
> 1: address logical volume=20
> log_unit,
> 2: periph device address=20
> is scsi3addr */
> unsigned int log_unit, __u8 page_code, unsigned char *scsi3addr,
> + int block_nr,
> int cmd_type)
> {
> ctlr_info_t *h=3D hba[ctlr];
> @@ -1231,6 +1419,8 @@ static int fill_cmd(CommandList_struct *
> c->Request.Type.Type =3D cmd_type;
> if (cmd_type =3D=3D TYPE_CMD) {
> switch(cmd) {
> + int nr_blocks;
> +
> case CISS_INQUIRY:
> /* If the logical unit number is 0=20
> then, this is going
> to controller so It's a physical=20
> command @@ -1292,6 +1482,54 @@ static int=20
> fill_cmd(CommandList_struct *
> c->Request.CDB[0] =3D BMIC_WRITE;
> c->Request.CDB[6] =3D BMIC_CACHE_FLUSH;
> break;
> + case CCISS_READ:
> + if (use_unit_num =3D=3D 1) {
> + c->Header.LUN.LogDev.VolId =3D
> + hba[ctlr]->drv[log_unit].LunID;
> + c->Header.LUN.LogDev.Mode =3D 1;
> + }
> + c->ctlr =3D ctlr;
> + c->cmd_type =3D CMD_RWREQ;
> + c->Request.CDBLen =3D 10;
> + c->Request.Type.Type =3D TYPE_CMD;
> + c->Request.Type.Attribute =3D ATTR_SIMPLE;
> + c->Request.Type.Direction =3D XFER_READ;
> + c->Request.Timeout =3D 0;
> + c->Request.CDB[0] =3D CCISS_READ;
> + c->Request.CDB[2] =3D (block_nr >> 24) & 0xff;
> + c->Request.CDB[3] =3D (block_nr >> 16) & 0xff;
> + c->Request.CDB[4] =3D (block_nr >> 8) & 0xff;
> + c->Request.CDB[5] =3D block_nr & 0xff;
> + c->Request.CDB[6] =3D 0;
> + nr_blocks =3D=20
> size/hba[ctlr]->drv[log_unit].block_size;
> + c->Request.CDB[7] =3D (nr_blocks >> 8) & 0xff;
> + c->Request.CDB[8] =3D nr_blocks & 0xff;
> + c->Request.CDB[9] =3D 0;
> + break;
> + case CCISS_WRITE:
> + if (use_unit_num =3D=3D 1) {
> + c->Header.LUN.LogDev.VolId =3D
> + hba[ctlr]->drv[log_unit].LunID;
> + c->Header.LUN.LogDev.Mode =3D 1;
> + }
> + c->ctlr =3D ctlr;
> + c->cmd_type =3D CMD_RWREQ;
> + c->Request.CDBLen =3D 10;
> + c->Request.Type.Type =3D TYPE_CMD;
> + c->Request.Type.Attribute =3D ATTR_SIMPLE;
> + c->Request.Type.Direction =3D XFER_WRITE;
> + c->Request.Timeout =3D 0;
> + c->Request.CDB[0] =3D CCISS_WRITE;
> + c->Request.CDB[2] =3D (block_nr >> 24) & 0xff;
> + c->Request.CDB[3] =3D (block_nr >> 16) & 0xff;
> + c->Request.CDB[4] =3D (block_nr >> 8) & 0xff;
> + c->Request.CDB[5] =3D block_nr & 0xff;
> + c->Request.CDB[6] =3D 0;
> + nr_blocks =3D=20
> size/hba[ctlr]->drv[log_unit].block_size;
> + c->Request.CDB[7] =3D (nr_blocks >> 8) & 0xff;
> + c->Request.CDB[8] =3D nr_blocks & 0xff;
> + c->Request.CDB[9] =3D 0;
> + break;
> default:
> printk(KERN_WARNING
> "cciss%d: Unknown Command=20
> 0x%c\n", ctlr, cmd);
> @@ -1347,7 +1585,7 @@ static int sendcmd_withirq(__u8 cmd,
> if ((c =3D cmd_alloc(h , 0)) =3D=3D NULL)
> return -ENOMEM;
> return_status =3D fill_cmd(c, cmd, ctlr, buff, size, use_unit_num,
> - log_unit, page_code, NULL, cmd_type);
> + log_unit, page_code, NULL, -1, cmd_type);
> if (return_status !=3D IO_OK) {
> cmd_free(h, c, 0);
> return return_status;
> @@ -1458,7 +1696,7 @@ static void cciss_geometry_inquiry(int c
> inq_buff, sizeof(*inq_buff), 1, logvol=20
> ,0xC1, TYPE_CMD);
> else
> return_code =3D sendcmd(CISS_INQUIRY, ctlr, inq_buff,
> - sizeof(*inq_buff), 1, logvol ,0xC1,=20
> NULL, TYPE_CMD);
> + sizeof(*inq_buff), 1, logvol ,0xC1,=20
> NULL, -1, TYPE_CMD);
> if (return_code =3D=3D IO_OK) {
> if(inq_buff->data_byte[8] =3D=3D 0xFF) {
> printk(KERN_WARNING
> @@ -1507,7 +1745,7 @@ cciss_read_capacity(int ctlr, int logvol
> ctlr, buf, sizeof(*buf), 1, logvol, 0,=20
> TYPE_CMD);
> else
> return_code =3D sendcmd(CCISS_READ_CAPACITY,
> - ctlr, buf, sizeof(*buf), 1, logvol, 0,=20
> NULL, TYPE_CMD);
> + ctlr, buf, sizeof(*buf), 1, logvol, 0,=20
> NULL, -1, TYPE_CMD);
> if (return_code =3D=3D IO_OK) {
> *total_size =3D be32_to_cpu(*((__be32 *)=20
> &buf->total_size[0]))+1;
> *block_size =3D be32_to_cpu(*((__be32 *)=20
> &buf->block_size[0])); @@ -1698,6 +1936,25 @@ static unsigned=20
> long pollcomplete(int ct
> /* Invalid address to tell caller we ran out of time */
> return 1;
> }
> +
> +/*
> + * Wait polling for a command to complete.
> + * The memory mapped FIFO is polled for the completion.
> + * Used only at dump time, interrupts disabled.
> + */
> +static unsigned long diskdump_pollcomplete(int ctlr) {
> + unsigned long done;
> +
> + while (1) {
> + done =3D hba[ctlr]->access.command_completed(hba[ctlr]);
> + if (done =3D=3D FIFO_EMPTY)
> + udelay(20);
> + else
> + return done;
> + }
> +}
> +
> /*
> * Send a command to the controller, and wait for it to complete. =20
> * Only used at init time.=20
> @@ -1713,6 +1970,7 @@ static int sendcmd(
> unsigned int log_unit,
> __u8 page_code,
> unsigned char *scsi3addr,
> + int block_nr,
> int cmd_type)
> {
> CommandList_struct *c;
> @@ -1722,14 +1980,24 @@ static int sendcmd(
> u64bit buff_dma_handle;
> int status;
> =20
> - if ((c =3D cmd_alloc(info_p, 1)) =3D=3D NULL) {
> + /* For diskdump we will do a read and write in this routine. =20
> + Because the kernel is not in a stable state we will use the
> + pre-allocated command reserved for diskdump */
> + if (crashdump_mode())
> + c =3D cciss_dump_cmnd;
> + else
> + c =3D cmd_alloc(info_p, 1);
> +
> + if (c =3D=3D NULL) {
> printk(KERN_WARNING "cciss: unable to get memory");
> return(IO_ERROR);
> }
> status =3D fill_cmd(c, cmd, ctlr, buff, size, use_unit_num,
> - log_unit, page_code, scsi3addr, cmd_type);
> + log_unit, page_code, scsi3addr, block_nr, cmd_type);
> if (status !=3D IO_OK) {
> - cmd_free(info_p, c, 1);
> + if (!crashdump_mode())
> + cmd_free(info_p, c, 1);
> +
> return status;
> }
> resend_cmd1:
> @@ -1759,7 +2027,11 @@ resend_cmd1:
> * Send the cmd
> */
> info_p->access.submit_command(info_p, c);
> - complete =3D pollcomplete(ctlr);
> +retry:
> + if (crashdump_mode())
> + complete =3D diskdump_pollcomplete(ctlr);
> + else
> + complete =3D pollcomplete(ctlr);
> =20
> #ifdef CCISS_DEBUG
> printk(KERN_DEBUG "cciss: command completed\n"); @@=20
> -1823,6 +2095,10 @@ resend_cmd1:
> printk( KERN_WARNING "cciss cciss%d:=20
> SendCmd "
> "Invalid command list address=20
> returned! (%lx)\n",
> ctlr, complete);
> +
> + if (crashdump_mode())
> + goto retry;
> +
> status =3D IO_ERROR;
> goto cleanup1;
> }
> @@ -1838,7 +2114,9 @@ cleanup1:=09
> /* unlock the data buffer from DMA */
> pci_unmap_single(info_p->pdev, (dma_addr_t) buff_dma_handle.val,
> size, PCI_DMA_BIDIRECTIONAL);
> - cmd_free(info_p, c, 1);
> + if (!crashdump_mode())
> + cmd_free(info_p, c, 1);
> + =09
> return (status);
> }
> /*
> @@ -2527,7 +2805,7 @@ static void cciss_getgeometry(int cntl_n
> }
> /* Get the firmware version */=20
> return_code =3D sendcmd(CISS_INQUIRY, cntl_num, inq_buff,=20
> - sizeof(InquiryData_struct), 0, 0 ,0, NULL, TYPE_CMD);
> + sizeof(InquiryData_struct), 0, 0 ,0, NULL, -1,=20
> TYPE_CMD);
> if (return_code =3D=3D IO_OK)
> {
> hba[cntl_num]->firm_ver[0] =3D=20
> inq_buff->data_byte[32]; @@ -2541,7 +2819,7 @@ static void=20
> cciss_getgeometry(int cntl_n
> }
> /* Get the number of logical volumes */=20
> return_code =3D sendcmd(CISS_REPORT_LOG, cntl_num, ld_buff,=20
> - sizeof(ReportLunData_struct), 0, 0, 0,=20
> NULL, TYPE_CMD);
> + sizeof(ReportLunData_struct), 0, 0, 0,=20
> NULL, -1, TYPE_CMD);
> =20
> if( return_code =3D=3D IO_OK)
> {
> @@ -2762,12 +3040,15 @@ static int __devinit cciss_init_one(stru
> disk->fops =3D &cciss_fops;
> disk->queue =3D hba[i]->queue;
> disk->private_data =3D drv;
> + if (j =3D=3D dump_drive)
> + disk->driverfs_dev =3D &pdev->dev;
> if( !(drv->nr_blocks))
> continue;
> blk_queue_hardsect_size(hba[i]->queue, drv->block_size);
> set_capacity(disk, drv->nr_blocks);
> add_disk(disk);
> }
> + cciss_attr_add(pdev);
> return(1);
> =20
> clean4:
> @@ -2816,7 +3097,7 @@ static void __devexit cciss_remove_one (
> * To write all data in the battery backed cache to disks */
> memset(flush_buf, 0, 4);
> return_code =3D sendcmd(CCISS_CACHE_FLUSH, i, flush_buf,=20
> 4, 0, 0, 0, NULL,
> - TYPE_CMD);
> + -1, TYPE_CMD);
> if(return_code !=3D IO_OK)
> {
> printk(KERN_WARNING "Error Flushing cache on=20
> controller %d\n", @@ -2867,14 +3148,20 @@ int __init cciss_init(void)
> =20
> static int __init init_cciss_module(void) {
> + int ret;
> +
> register_cciss_ioctl32();
> - return ( cciss_init());
> + ret =3D cciss_init();
> + if (ret < 0)
> + return ret;
> + return init_cciss_dump();
> }
> =20
> static void __exit cleanup_cciss_module(void) {
> int i;
> =20
> + cleanup_cciss_dump();
> unregister_cciss_ioctl32();
> pci_unregister_driver(&cciss_pci_driver);
> /* double check that all controller entrys have been=20
> removed */ diff -Nurp=20
> 2.6.9-diskdump-1.0.orig/drivers/block/cciss_scsi.c=20
> 2.6.9-diskdump-1.0/drivers/block/cciss_scsi.c
> --- 2.6.9-diskdump-1.0.orig/drivers/block/cciss_scsi.c=09
> 2005-05-23 14:10:02.549869936 +0900
> +++ 2.6.9-diskdump-1.0/drivers/block/cciss_scsi.c=09
> 2005-05-23 14:14:43.841107168 +0900
> @@ -48,6 +48,7 @@ static int sendcmd(
> unsigned int log_unit,
> __u8 page_code,
> unsigned char *scsi3addr,
> + int block_nr,
> int cmd_type);
> =20
> =20
>=20
>=20
> -------------------------------------------------------
> This SF.Net email is sponsored by Oracle Space Sweepstakes=20
> Want to be the first software developer in space?
> Enter now for the Oracle Space Sweepstakes!
> http://ads.osdn.com/?ad_id=3D7412&alloc_id=3D16344&op=3Dclick
> _______________________________________________
> lkdump-develop mailing list
> lkd...@li...
> https://lists.sourceforge.net/lists/listinfo/lkdump-develop
>=20
>=20
> -------------------------------------------------------
>=20
|