diff options
| author | David Woodhouse <dwmw2@infradead.org> | 2006-10-01 17:55:53 +0100 |
|---|---|---|
| committer | David Woodhouse <dwmw2@infradead.org> | 2006-10-01 17:55:53 +0100 |
| commit | 8a84fc15ae5cafcc366dd85cf8e1ab2040679abc (patch) | |
| tree | 5d8dce194c9667fa92e9ec9f545cec867a9a1e0d /drivers/block | |
| parent | 28b79ff9661b22e4c41c0d00d4ab8503e810f13d (diff) | |
| parent | 82965addad66fce61a92c5f03104ea90b0b87124 (diff) | |
| download | linux-8a84fc15ae5cafcc366dd85cf8e1ab2040679abc.tar.gz linux-8a84fc15ae5cafcc366dd85cf8e1ab2040679abc.zip | |
Merge branch 'master' of git://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux-2.6
Manually resolve conflict in include/mtd/Kbuild
Signed-off-by: David Woodhouse <dwmw2@infradead.org>
Diffstat (limited to 'drivers/block')
| -rw-r--r-- | drivers/block/DAC960.c | 6 | ||||
| -rw-r--r-- | drivers/block/DAC960.h | 2 | ||||
| -rw-r--r-- | drivers/block/Kconfig | 4 | ||||
| -rw-r--r-- | drivers/block/cciss.c | 238 | ||||
| -rw-r--r-- | drivers/block/cciss.h | 3 | ||||
| -rw-r--r-- | drivers/block/cciss_cmd.h | 33 | ||||
| -rw-r--r-- | drivers/block/cciss_scsi.c | 16 | ||||
| -rw-r--r-- | drivers/block/cpqarray.c | 1 | ||||
| -rw-r--r-- | drivers/block/cryptoloop.c | 160 | ||||
| -rw-r--r-- | drivers/block/floppy.c | 4 | ||||
| -rw-r--r-- | drivers/block/loop.c | 247 | ||||
| -rw-r--r-- | drivers/block/nbd.c | 8 | ||||
| -rw-r--r-- | drivers/block/paride/pd.c | 8 | ||||
| -rw-r--r-- | drivers/block/pktcdvd.c | 10 | ||||
| -rw-r--r-- | drivers/block/swim3.c | 4 | ||||
| -rw-r--r-- | drivers/block/swim_iop.c | 4 | ||||
| -rw-r--r-- | drivers/block/ub.c | 38 | ||||
| -rw-r--r-- | drivers/block/xd.c | 2 |
18 files changed, 507 insertions, 281 deletions
diff --git a/drivers/block/DAC960.c b/drivers/block/DAC960.c index 4cd23c3eab41..b3f639fbf220 100644 --- a/drivers/block/DAC960.c +++ b/drivers/block/DAC960.c @@ -770,7 +770,7 @@ static void DAC960_P_QueueCommand(DAC960_Command_T *Command) static void DAC960_ExecuteCommand(DAC960_Command_T *Command) { DAC960_Controller_T *Controller = Command->Controller; - DECLARE_COMPLETION(Completion); + DECLARE_COMPLETION_ONSTACK(Completion); unsigned long flags; Command->Completion = &Completion; @@ -3331,7 +3331,7 @@ static int DAC960_process_queue(DAC960_Controller_T *Controller, struct request_ Command->DmaDirection = PCI_DMA_TODEVICE; Command->CommandType = DAC960_WriteCommand; } - Command->Completion = Request->waiting; + Command->Completion = Request->end_io_data; Command->LogicalDriveNumber = (long)Request->rq_disk->private_data; Command->BlockNumber = Request->sector; Command->BlockCount = Request->nr_sectors; @@ -7115,7 +7115,7 @@ static struct pci_device_id DAC960_id_table[] = { { .vendor = PCI_VENDOR_ID_MYLEX, .device = PCI_DEVICE_ID_MYLEX_DAC960_GEM, - .subvendor = PCI_ANY_ID, + .subvendor = PCI_VENDOR_ID_MYLEX, .subdevice = PCI_ANY_ID, .driver_data = (unsigned long) &DAC960_GEM_privdata, }, diff --git a/drivers/block/DAC960.h b/drivers/block/DAC960.h index a82f37f749a5..f9217c34bc2b 100644 --- a/drivers/block/DAC960.h +++ b/drivers/block/DAC960.h @@ -71,7 +71,7 @@ Define a Boolean data type. */ -typedef enum { false, true } __attribute__ ((packed)) boolean; +typedef bool boolean; /* diff --git a/drivers/block/Kconfig b/drivers/block/Kconfig index b5382cedf0c0..422e31d5f8e5 100644 --- a/drivers/block/Kconfig +++ b/drivers/block/Kconfig @@ -2,6 +2,8 @@ # Block device driver configuration # +if BLOCK + menu "Block devices" config BLK_DEV_FD @@ -468,3 +470,5 @@ config ATA_OVER_ETH devices like the Coraid EtherDrive (R) Storage Blade. endmenu + +endif diff --git a/drivers/block/cciss.c b/drivers/block/cciss.c index 2cd3391ff878..99f87efe0f58 100644 --- a/drivers/block/cciss.c +++ b/drivers/block/cciss.c @@ -144,13 +144,13 @@ static int rebuild_lun_table(ctlr_info_t *h, struct gendisk *del_disk); static int deregister_disk(struct gendisk *disk, drive_info_struct *drv, int clear_all); -static void cciss_read_capacity(int ctlr, int logvol, ReadCapdata_struct *buf, - int withirq, unsigned int *total_size, - unsigned int *block_size); -static void cciss_geometry_inquiry(int ctlr, int logvol, int withirq, - unsigned int total_size, - unsigned int block_size, - InquiryData_struct *inq_buff, +static void cciss_read_capacity(int ctlr, int logvol, int withirq, + sector_t *total_size, unsigned int *block_size); +static void cciss_read_capacity_16(int ctlr, int logvol, int withirq, + sector_t *total_size, unsigned int *block_size); +static void cciss_geometry_inquiry(int ctlr, int logvol, + int withirq, sector_t total_size, + unsigned int block_size, InquiryData_struct *inq_buff, drive_info_struct *drv); static void cciss_getgeometry(int cntl_num); static void __devinit cciss_interrupt_mode(ctlr_info_t *, struct pci_dev *, @@ -879,7 +879,7 @@ static int cciss_ioctl(struct inode *inode, struct file *filep, char *buff = NULL; u64bit temp64; unsigned long flags; - DECLARE_COMPLETION(wait); + DECLARE_COMPLETION_ONSTACK(wait); if (!arg) return -EINVAL; @@ -997,7 +997,7 @@ static int cciss_ioctl(struct inode *inode, struct file *filep, BYTE sg_used = 0; int status = 0; int i; - DECLARE_COMPLETION(wait); + DECLARE_COMPLETION_ONSTACK(wait); __u32 left; __u32 sz; BYTE __user *data_ptr; @@ -1229,7 +1229,6 @@ static inline void complete_buffers(struct bio *bio, int status) int nr_sectors = bio_sectors(bio); bio->bi_next = NULL; - blk_finished_io(len); bio_endio(bio, nr_sectors << 9, status ? 0 : -EIO); bio = xbh; } @@ -1326,10 +1325,9 @@ static void cciss_update_drive_info(int ctlr, int drv_index) { ctlr_info_t *h = hba[ctlr]; struct gendisk *disk; - ReadCapdata_struct *size_buff = NULL; InquiryData_struct *inq_buff = NULL; unsigned int block_size; - unsigned int total_size; + sector_t total_size; unsigned long flags = 0; int ret = 0; @@ -1348,15 +1346,25 @@ static void cciss_update_drive_info(int ctlr, int drv_index) return; /* Get information about the disk and modify the driver structure */ - size_buff = kmalloc(sizeof(ReadCapdata_struct), GFP_KERNEL); - if (size_buff == NULL) - goto mem_msg; inq_buff = kmalloc(sizeof(InquiryData_struct), GFP_KERNEL); if (inq_buff == NULL) goto mem_msg; - cciss_read_capacity(ctlr, drv_index, size_buff, 1, + cciss_read_capacity(ctlr, drv_index, 1, &total_size, &block_size); + + /* total size = last LBA + 1 */ + /* FFFFFFFF + 1 = 0, cannot have a logical volume of size 0 */ + /* so we assume this volume this must be >2TB in size */ + if (total_size == (__u32) 0) { + cciss_read_capacity_16(ctlr, drv_index, 1, + &total_size, &block_size); + h->cciss_read = CCISS_READ_16; + h->cciss_write = CCISS_WRITE_16; + } else { + h->cciss_read = CCISS_READ_10; + h->cciss_write = CCISS_WRITE_10; + } cciss_geometry_inquiry(ctlr, drv_index, 1, total_size, block_size, inq_buff, &h->drv[drv_index]); @@ -1392,7 +1400,6 @@ static void cciss_update_drive_info(int ctlr, int drv_index) } freeret: - kfree(size_buff); kfree(inq_buff); return; mem_msg: @@ -1717,6 +1724,22 @@ static int fill_cmd(CommandList_struct *c, __u8 cmd, int ctlr, void *buff, size_ c->Request.Timeout = 0; c->Request.CDB[0] = cmd; break; + case CCISS_READ_CAPACITY_16: + c->Header.LUN.LogDev.VolId = h->drv[log_unit].LunID; + c->Header.LUN.LogDev.Mode = 1; + c->Request.CDBLen = 16; + c->Request.Type.Attribute = ATTR_SIMPLE; + c->Request.Type.Direction = XFER_READ; + c->Request.Timeout = 0; + c->Request.CDB[0] = cmd; + c->Request.CDB[1] = 0x10; + c->Request.CDB[10] = (size >> 24) & 0xFF; + c->Request.CDB[11] = (size >> 16) & 0xFF; + c->Request.CDB[12] = (size >> 8) & 0xFF; + c->Request.CDB[13] = size & 0xFF; + c->Request.Timeout = 0; + c->Request.CDB[0] = cmd; + break; case CCISS_CACHE_FLUSH: c->Request.CDBLen = 12; c->Request.Type.Attribute = ATTR_SIMPLE; @@ -1750,6 +1773,7 @@ static int fill_cmd(CommandList_struct *c, __u8 cmd, int ctlr, void *buff, size_ memset(&c->Request.CDB[0], 0, sizeof(c->Request.CDB)); c->Request.CDB[0] = cmd; /* reset */ c->Request.CDB[1] = 0x04; /* reset a LUN */ + break; case 3: /* No-Op message */ c->Request.CDBLen = 1; c->Request.Type.Attribute = ATTR_SIMPLE; @@ -1792,7 +1816,7 @@ static int sendcmd_withirq(__u8 cmd, u64bit buff_dma_handle; unsigned long flags; int return_status; - DECLARE_COMPLETION(wait); + DECLARE_COMPLETION_ONSTACK(wait); if ((c = cmd_alloc(h, 0)) == NULL) return -ENOMEM; @@ -1893,12 +1917,15 @@ static int sendcmd_withirq(__u8 cmd, } static void cciss_geometry_inquiry(int ctlr, int logvol, - int withirq, unsigned int total_size, + int withirq, sector_t total_size, unsigned int block_size, InquiryData_struct *inq_buff, drive_info_struct *drv) { int return_code; + unsigned long t; + unsigned long rem; + memset(inq_buff, 0, sizeof(InquiryData_struct)); if (withirq) return_code = sendcmd_withirq(CISS_INQUIRY, ctlr, @@ -1917,10 +1944,10 @@ static void cciss_geometry_inquiry(int ctlr, int logvol, drv->nr_blocks = total_size; drv->heads = 255; drv->sectors = 32; // Sectors per track - drv->cylinders = total_size / 255 / 32; + t = drv->heads * drv->sectors; + drv->cylinders = total_size; + rem = do_div(drv->cylinders, t); } else { - unsigned int t; - drv->block_size = block_size; drv->nr_blocks = total_size; drv->heads = inq_buff->data_byte[6]; @@ -1930,42 +1957,84 @@ static void cciss_geometry_inquiry(int ctlr, int logvol, drv->raid_level = inq_buff->data_byte[8]; t = drv->heads * drv->sectors; if (t > 1) { - drv->cylinders = total_size / t; + drv->cylinders = total_size; + rem = do_div(drv->cylinders, t); } } } else { /* Get geometry failed */ printk(KERN_WARNING "cciss: reading geometry failed\n"); } - printk(KERN_INFO " heads= %d, sectors= %d, cylinders= %d\n\n", + printk(KERN_INFO " heads=%d, sectors=%d, cylinders=%d\n\n", drv->heads, drv->sectors, drv->cylinders); } static void -cciss_read_capacity(int ctlr, int logvol, ReadCapdata_struct *buf, - int withirq, unsigned int *total_size, +cciss_read_capacity(int ctlr, int logvol, int withirq, sector_t *total_size, unsigned int *block_size) { + ReadCapdata_struct *buf; int return_code; - memset(buf, 0, sizeof(*buf)); + buf = kmalloc(sizeof(ReadCapdata_struct), GFP_KERNEL); + if (buf == NULL) { + printk(KERN_WARNING "cciss: out of memory\n"); + return; + } + memset(buf, 0, sizeof(ReadCapdata_struct)); if (withirq) return_code = sendcmd_withirq(CCISS_READ_CAPACITY, - ctlr, buf, sizeof(*buf), 1, - logvol, 0, TYPE_CMD); + ctlr, buf, sizeof(ReadCapdata_struct), + 1, logvol, 0, TYPE_CMD); else return_code = sendcmd(CCISS_READ_CAPACITY, - ctlr, buf, sizeof(*buf), 1, logvol, 0, - NULL, TYPE_CMD); + ctlr, buf, sizeof(ReadCapdata_struct), + 1, logvol, 0, NULL, TYPE_CMD); if (return_code == IO_OK) { - *total_size = - be32_to_cpu(*((__be32 *) & buf->total_size[0])) + 1; - *block_size = be32_to_cpu(*((__be32 *) & buf->block_size[0])); + *total_size = be32_to_cpu(*(__u32 *) buf->total_size)+1; + *block_size = be32_to_cpu(*(__u32 *) buf->block_size); } else { /* read capacity command failed */ printk(KERN_WARNING "cciss: read capacity failed\n"); *total_size = 0; *block_size = BLOCK_SIZE; } - printk(KERN_INFO " blocks= %u block_size= %d\n", + if (*total_size != (__u32) 0) + printk(KERN_INFO " blocks= %lld block_size= %d\n", + *total_size, *block_size); + kfree(buf); + return; +} + +static void +cciss_read_capacity_16(int ctlr, int logvol, int withirq, sector_t *total_size, unsigned int *block_size) +{ + ReadCapdata_struct_16 *buf; + int return_code; + buf = kmalloc(sizeof(ReadCapdata_struct_16), GFP_KERNEL); + if (buf == NULL) { + printk(KERN_WARNING "cciss: out of memory\n"); + return; + } + memset(buf, 0, sizeof(ReadCapdata_struct_16)); + if (withirq) { + return_code = sendcmd_withirq(CCISS_READ_CAPACITY_16, + ctlr, buf, sizeof(ReadCapdata_struct_16), + 1, logvol, 0, TYPE_CMD); + } + else { + return_code = sendcmd(CCISS_READ_CAPACITY_16, + ctlr, buf, sizeof(ReadCapdata_struct_16), + 1, logvol, 0, NULL, TYPE_CMD); + } + if (return_code == IO_OK) { + *total_size = be64_to_cpu(*(__u64 *) buf->total_size)+1; + *block_size = be32_to_cpu(*(__u32 *) buf->block_size); + } else { /* read capacity command failed */ + printk(KERN_WARNING "cciss: read capacity failed\n"); + *total_size = 0; + *block_size = BLOCK_SIZE; + } + printk(KERN_INFO " blocks= %lld block_size= %d\n", *total_size, *block_size); + kfree(buf); return; } @@ -1976,8 +2045,7 @@ static int cciss_revalidate(struct gendisk *disk) int logvol; int FOUND = 0; unsigned int block_size; - unsigned int total_size; - ReadCapdata_struct *size_buff = NULL; + sector_t total_size; InquiryData_struct *inq_buff = NULL; for (logvol = 0; logvol < CISS_MAX_LUN; logvol++) { @@ -1990,27 +2058,24 @@ static int cciss_revalidate(struct gendisk *disk) if (!FOUND) return 1; - size_buff = kmalloc(sizeof(ReadCapdata_struct), GFP_KERNEL); - if (size_buff == NULL) { - printk(KERN_WARNING "cciss: out of memory\n"); - return 1; - } inq_buff = kmalloc(sizeof(InquiryData_struct), GFP_KERNEL); if (inq_buff == NULL) { printk(KERN_WARNING "cciss: out of memory\n"); - kfree(size_buff); return 1; } - - cciss_read_capacity(h->ctlr, logvol, size_buff, 1, &total_size, - &block_size); + if (h->cciss_read == CCISS_READ_10) { + cciss_read_capacity(h->ctlr, logvol, 1, + &total_size, &block_size); + } else { + cciss_read_capacity_16(h->ctlr, logvol, 1, + &total_size, &block_size); + } cciss_geometry_inquiry(h->ctlr, logvol, 1, total_size, block_size, inq_buff, drv); blk_queue_hardsect_size(drv->queue, drv->block_size); set_capacity(disk, drv->nr_blocks); - kfree(size_buff); kfree(inq_buff); return 0; } @@ -2419,7 +2484,8 @@ static void do_cciss_request(request_queue_t *q) { ctlr_info_t *h = q->queuedata; CommandList_struct *c; - int start_blk, seg; + sector_t start_blk; + int seg; struct request *creq; u64bit temp64; struct scatterlist tmp_sg[MAXSGENTRIES]; @@ -2463,10 +2529,10 @@ static void do_cciss_request(request_queue_t *q) c->Request.Type.Type = TYPE_CMD; // It is a command. c->Request.Type.Attribute = ATTR_SIMPLE; c->Request.Type.Direction = - (rq_data_dir(creq) == READ) ? XFER_READ : XFER_WRITE; + (rq_data_dir(creq) == READ) ? h->cciss_read : h->cciss_write; c->Request.Timeout = 0; // Don't time out c->Request.CDB[0] = - (rq_data_dir(creq) == READ) ? CCISS_READ : CCISS_WRITE; + (rq_data_dir(creq) == READ) ? h->cciss_read : h->cciss_write; start_blk = creq->sector; #ifdef CCISS_DEBUG printk(KERN_DEBUG "ciss: sector =%d nr_sectors=%d\n", (int)creq->sector, @@ -2500,15 +2566,33 @@ static void do_cciss_request(request_queue_t *q) #endif /* CCISS_DEBUG */ c->Header.SGList = c->Header.SGTotal = seg; - c->Request.CDB[1] = 0; - c->Request.CDB[2] = (start_blk >> 24) & 0xff; //MSB - c->Request.CDB[3] = (start_blk >> 16) & 0xff; - c->Request.CDB[4] = (start_blk >> 8) & 0xff; - c->Request.CDB[5] = start_blk & 0xff; - c->Request.CDB[6] = 0; // (sect >> 24) & 0xff; MSB - c->Request.CDB[7] = (creq->nr_sectors >> 8) & 0xff; - c->Request.CDB[8] = creq->nr_sectors & 0xff; - c->Request.CDB[9] = c->Request.CDB[11] = c->Request.CDB[12] = 0; + if(h->cciss_read == CCISS_READ_10) { + c->Request.CDB[1] = 0; + c->Request.CDB[2] = (start_blk >> 24) & 0xff; //MSB + c->Request.CDB[3] = (start_blk >> 16) & 0xff; + c->Request.CDB[4] = (start_blk >> 8) & 0xff; + c->Request.CDB[5] = start_blk & 0xff; + c->Request.CDB[6] = 0; // (sect >> 24) & 0xff; MSB + c->Request.CDB[7] = (creq->nr_sectors >> 8) & 0xff; + c->Request.CDB[8] = creq->nr_sectors & 0xff; + c->Request.CDB[9] = c->Request.CDB[11] = c->Request.CDB[12] = 0; + } else { + c->Request.CDBLen = 16; + c->Request.CDB[1]= 0; + c->Request.CDB[2]= (start_blk >> 56) & 0xff; //MSB + c->Request.CDB[3]= (start_blk >> 48) & 0xff; + c->Request.CDB[4]= (start_blk >> 40) & 0xff; + c->Request.CDB[5]= (start_blk >> 32) & 0xff; + c->Request.CDB[6]= (start_blk >> 24) & 0xff; + c->Request.CDB[7]= (start_blk >> 16) & 0xff; + c->Request.CDB[8]= (start_blk >> 8) & 0xff; + c->Request.CDB[9]= start_blk & 0xff; + c->Request.CDB[10]= (creq->nr_sectors >> 24) & 0xff; + c->Request.CDB[11]= (creq->nr_sectors >> 16) & 0xff; + c->Request.CDB[12]= (creq->nr_sectors >> 8) & 0xff; + c->Request.CDB[13]= creq->nr_sectors & 0xff; + c->Request.CDB[14] = c->Request.CDB[15] = 0; + } spin_lock_irq(q->queue_lock); @@ -2518,9 +2602,9 @@ static void do_cciss_request(request_queue_t *q) h->maxQsinceinit = h->Qdepth; goto queue; - full: +full: blk_stop_queue(q); - startio: +startio: /* We will already have the driver lock here so not need * to lock it. */ @@ -2948,31 +3032,23 @@ static int cciss_pci_init(ctlr_info_t *c, struct pci_dev *pdev) static void cciss_getgeometry(int cntl_num) { ReportLunData_struct *ld_buff; - ReadCapdata_struct *size_buff; InquiryData_struct *inq_buff; int return_code; int i; int listlength = 0; __u32 lunid = 0; int block_size; - int total_size; + sector_t total_size; ld_buff = kzalloc(sizeof(ReportLunData_struct), GFP_KERNEL); if (ld_buff == NULL) { printk(KERN_ERR "cciss: out of memory\n"); return; } - size_buff = kmalloc(sizeof(ReadCapdata_struct), GFP_KERNEL); - if (size_buff == NULL) { - printk(KERN_ERR "cciss: out of memory\n"); - kfree(ld_buff); - return; - } inq_buff = kmalloc(sizeof(InquiryData_struct), GFP_KERNEL); if (inq_buff == NULL) { printk(KERN_ERR "cciss: out of memory\n"); kfree(ld_buff); - kfree(size_buff); return; } /* Get the firmware version */ @@ -3027,7 +3103,6 @@ static void cciss_getgeometry(int cntl_num) #endif /* CCISS_DEBUG */ hba[cntl_num]->highest_lun = hba[cntl_num]->num_luns - 1; -// for(i=0; i< hba[cntl_num]->num_luns; i++) for (i = 0; i < CISS_MAX_LUN; i++) { if (i < hba[cntl_num]->num_luns) { lunid = (0xff & (unsigned int)(ld_buff->LUN[i][3])) @@ -3046,8 +3121,26 @@ static void cciss_getgeometry(int cntl_num) ld_buff->LUN[i][2], ld_buff->LUN[i][3], hba[cntl_num]->drv[i].LunID); #endif /* CCISS_DEBUG */ - cciss_read_capacity(cntl_num, i, size_buff, 0, + + /* testing to see if 16-byte CDBs are already being used */ + if(hba[cntl_num]->cciss_read == CCISS_READ_16) { + cciss_read_capacity_16(cntl_num, i, 0, &total_size, &block_size); + goto geo_inq; + } + cciss_read_capacity(cntl_num, i, 0, &total_size, &block_size); + + /* total_size = last LBA + 1 */ + if(total_size == (__u32) 0) { + cciss_read_capacity_16(cntl_num, i, 0, + &total_size, &block_size); + hba[cntl_num]->cciss_read = CCISS_READ_16; + hba[cntl_num]->cciss_write = CCISS_WRITE_16; + } else { + hba[cntl_num]->cciss_read = CCISS_READ_10; + hba[cntl_num]->cciss_write = CCISS_WRITE_10; + } +geo_inq: cciss_geometry_inquiry(cntl_num, i, 0, total_size, block_size, inq_buff, &hba[cntl_num]->drv[i]); @@ -3057,7 +3150,6 @@ static void cciss_getgeometry(int cntl_num) } } kfree(ld_buff); - kfree(size_buff); kfree(inq_buff); } diff --git a/drivers/block/cciss.h b/drivers/block/cciss.h index 868e0d862b0d..562235c1445a 100644 --- a/drivers/block/cciss.h +++ b/drivers/block/cciss.h @@ -76,6 +76,9 @@ struct ctlr_info unsigned int intr[4]; unsigned int msix_vector; unsigned int msi_vector; + BYTE cciss_read; + BYTE cciss_write; + BYTE cciss_read_capacity; // information about each logical volume drive_info_struct drv[CISS_MAX_LUN]; diff --git a/drivers/block/cciss_cmd.h b/drivers/block/cciss_cmd.h index 53fea549ba8b..4af7c4c0c7af 100644 --- a/drivers/block/cciss_cmd.h +++ b/drivers/block/cciss_cmd.h @@ -118,11 +118,34 @@ typedef struct _ReadCapdata_struct BYTE block_size[4]; // Size of blocks in bytes } ReadCapdata_struct; -// 12 byte commands not implemented in firmware yet. -// #define CCISS_READ 0xa8 // Read(12) -// #define CCISS_WRITE 0xaa // Write(12) - #define CCISS_READ 0x28 // Read(10) - #define CCISS_WRITE 0x2a // Write(10) +#define CCISS_READ_CAPACITY_16 0x9e /* Read Capacity 16 */ + +/* service action to differentiate a 16 byte read capacity from + other commands that use the 0x9e SCSI op code */ + +#define CCISS_READ_CAPACITY_16_SERVICE_ACT 0x10 + +typedef struct _ReadCapdata_struct_16 +{ + BYTE total_size[8]; /* Total size in blocks */ + BYTE block_size[4]; /* Size of blocks in bytes */ + BYTE prot_en:1; /* protection enable bit */ + BYTE rto_en:1; /* reference tag own enable bit */ + BYTE reserved:6; /* reserved bits */ + BYTE reserved2[18]; /* reserved bytes per spec */ +} ReadCapdata_struct_16; + +/* Define the supported read/write commands for cciss based controllers */ + +#define CCISS_READ_10 0x28 /* Read(10) */ +#define CCISS_WRITE_10 0x2a /* Write(10) */ +#define CCISS_READ_16 0x88 /* Read(16) */ +#define CCISS_WRITE_16 0x8a /* Write(16) */ + +/* Define the CDB lengths supported by cciss based controllers */ + +#define CDB_LEN10 10 +#define CDB_LEN16 16 // BMIC commands #define BMIC_READ 0x26 diff --git a/drivers/block/cciss_scsi.c b/drivers/block/cciss_scsi.c index afdff32f6724..bb15051ffbe0 100644 --- a/drivers/block/cciss_scsi.c +++ b/drivers/block/cciss_scsi.c @@ -251,10 +251,6 @@ scsi_cmd_stack_free(int ctlr) stk->pool = NULL; } -/* scsi_device_types comes from scsi.h */ -#define DEVICETYPE(n) (n<0 || n>MAX_SCSI_DEVICE_CODE) ? \ - "Unknown" : scsi_device_types[n] - #if 0 static int xmargin=8; static int amargin=60; @@ -389,7 +385,7 @@ cciss_scsi_add_entry(int ctlr, int hostno, time anyway (the scsi layer's inquiries will show that info) */ if (hostno != -1) printk("cciss%d: %s device c%db%dt%dl%d added.\n", - ctlr, DEVICETYPE(sd->devtype), hostno, + ctlr, scsi_device_type(sd->devtype), hostno, sd->bus, sd->target, sd->lun); return 0; } @@ -407,7 +403,7 @@ cciss_scsi_remove_entry(int ctlr, int hostno, int entry) ccissscsi[ctlr].dev[i] = ccissscsi[ctlr].dev[i+1]; ccissscsi[ctlr].ndevices--; printk("cciss%d: %s device c%db%dt%dl%d removed.\n", - ctlr, DEVICETYPE(sd.devtype), hostno, + ctlr, scsi_device_type(sd.devtype), hostno, sd.bus, sd.target, sd.lun); } @@ -458,7 +454,7 @@ adjust_cciss_scsi_table(int ctlr, int hostno, if (found == 0) { /* device no longer present. */ changes++; /* printk("cciss%d: %s device c%db%dt%dl%d removed.\n", - ctlr, DEVICETYPE(csd->devtype), hostno, + ctlr, scsi_device_type(csd->devtype), hostno, csd->bus, csd->target, csd->lun); */ cciss_scsi_remove_entry(ctlr, hostno, i); /* note, i not incremented */ @@ -468,7 +464,7 @@ adjust_cciss_scsi_table(int ctlr, int hostno, printk("cciss%d: device c%db%dt%dl%d type changed " "(device type now %s).\n", ctlr, hostno, csd->bus, csd->target, csd->lun, - DEVICETYPE(csd->devtype)); + scsi_device_type(csd->devtype)); csd->devtype = sd[j].devtype; i++; /* so just move along. */ } else /* device is same as it ever was, */ @@ -770,7 +766,7 @@ cciss_scsi_do_simple_cmd(ctlr_info_t *c, int direction) { unsigned long flags; - DECLARE_COMPLETION(wait); + DECLARE_COMPLETION_ONSTACK(wait); cp->cmd_type = CMD_IOCTL_PEND; // treat this like an ioctl cp->scsi_cmd = NULL; @@ -1098,7 +1094,7 @@ cciss_update_non_disk_devices(int cntl_num, int hostno) if (ncurrent >= CCISS_MAX_SCSI_DEVS_PER_HBA) { printk(KERN_INFO "cciss%d: %s ignored, " "too many devices.\n", cntl_num, - DEVICETYPE(devtype)); + scsi_device_type(devtype)); break; } memcpy(¤tsd[ncurrent].scsi3addr[0], diff --git a/drivers/block/cpqarray.c b/drivers/block/cpqarray.c index 78082edc14b4..4abc193314ee 100644 --- a/drivers/block/cpqarray.c +++ b/drivers/block/cpqarray.c @@ -989,7 +989,6 @@ static inline void complete_buffers(struct bio *bio, int ok) xbh = bio->bi_next; bio->bi_next = NULL; - blk_finished_io(nr_sectors); bio_endio(bio, nr_sectors << 9, ok ? 0 : -EIO); bio = xbh; diff --git a/drivers/block/cryptoloop.c b/drivers/block/cryptoloop.c index 3d4261c39f16..40535036e893 100644 --- a/drivers/block/cryptoloop.c +++ b/drivers/block/cryptoloop.c @@ -40,11 +40,13 @@ static int cryptoloop_init(struct loop_device *lo, const struct loop_info64 *info) { int err = -EINVAL; + int cipher_len; + int mode_len; char cms[LO_NAME_SIZE]; /* cipher-mode string */ char *cipher; char *mode; char *cmsp = cms; /* c-m string pointer */ - struct crypto_tfm *tfm = NULL; + struct crypto_blkcipher *tfm; /* encryption breaks for non sector aligned offsets */ @@ -53,20 +55,39 @@ cryptoloop_init(struct loop_device *lo, const struct loop_info64 *info) strncpy(cms, info->lo_crypt_name, LO_NAME_SIZE); cms[LO_NAME_SIZE - 1] = 0; - cipher = strsep(&cmsp, "-"); - mode = strsep(&cmsp, "-"); - - if (mode == NULL || strcmp(mode, "cbc") == 0) - tfm = crypto_alloc_tfm(cipher, CRYPTO_TFM_MODE_CBC | - CRYPTO_TFM_REQ_MAY_SLEEP); - else if (strcmp(mode, "ecb") == 0) - tfm = crypto_alloc_tfm(cipher, CRYPTO_TFM_MODE_ECB | - CRYPTO_TFM_REQ_MAY_SLEEP); - if (tfm == NULL) + + cipher = cmsp; + cipher_len = strcspn(cmsp, "-"); + + mode = cmsp + cipher_len; + mode_len = 0; + if (*mode) { + mode++; + mode_len = strcspn(mode, "-"); + } + + if (!mode_len) { + mode = "cbc"; + mode_len = 3; + } + + if (cipher_len + mode_len + 3 > LO_NAME_SIZE) return -EINVAL; - err = tfm->crt_u.cipher.cit_setkey(tfm, info->lo_encrypt_key, - info->lo_encrypt_key_size); + memmove(cms, mode, mode_len); + cmsp = cms + mode_len; + *cmsp++ = '('; + memcpy(cmsp, info->lo_crypt_name, cipher_len); + cmsp += cipher_len; + *cmsp++ = ')'; + *cmsp = 0; + + tfm = crypto_alloc_blkcipher(cms, 0, CRYPTO_ALG_ASYNC); + if (IS_ERR(tfm)) + return PTR_ERR(tfm); + + err = crypto_blkcipher_setkey(tfm, info->lo_encrypt_key, + info->lo_encrypt_key_size); if (err != 0) goto out_free_tfm; @@ -75,99 +96,49 @@ cryptoloop_init(struct loop_device *lo, const struct loop_info64 *info) return 0; out_free_tfm: - crypto_free_tfm(tfm); + crypto_free_blkcipher(tfm); out: return err; } -typedef int (*encdec_ecb_t)(struct crypto_tfm *tfm, +typedef int (*encdec_cbc_t)(struct blkcipher_desc *desc, struct scatterlist *sg_out, struct scatterlist *sg_in, unsigned int nsg); - -static int -cryptoloop_transfer_ecb(struct loop_device *lo, int cmd, - struct page *raw_page, unsigned raw_off, - struct page *loop_page, unsigned loop_off, - int size, sector_t IV) -{ - struct crypto_tfm *tfm = (struct crypto_tfm *) lo->key_data; - struct scatterlist sg_out = { NULL, }; - struct scatterlist sg_in = { NULL, }; - - encdec_ecb_t encdecfunc; - struct page *in_page, *out_page; - unsigned in_offs, out_offs; - - if (cmd == READ) { - in_page = raw_page; - in_offs = raw_off; - out_page = loop_page; - out_offs = loop_off; - encdecfunc = tfm->crt_u.cipher.cit_decrypt; - } else { - in_page = loop_page; - in_offs = loop_off; - out_page = raw_page; - out_offs = raw_off; - encdecfunc = tfm->crt_u.cipher.cit_encrypt; - } - - while (size > 0) { - const int sz = min(size, LOOP_IV_SECTOR_SIZE); - - sg_in.page = in_page; - sg_in.offset = in_offs; - sg_in.length = sz; - - sg_out.page = out_page; - sg_out.offset = out_offs; - sg_out.length = sz; - - encdecfunc(tfm, &sg_out, &sg_in, sz); - - size -= sz; - in_offs += sz; - out_offs += sz; - } - - return 0; -} - -typedef int (*encdec_cbc_t)(struct crypto_tfm *tfm, - struct scatterlist *sg_out, - struct scatterlist *sg_in, - unsigned int nsg, u8 *iv); - static int -cryptoloop_transfer_cbc(struct loop_device *lo, int cmd, - struct page *raw_page, unsigned raw_off, - struct page *loop_page, unsigned loop_off, - int size, sector_t IV) +cryptoloop_transfer(struct loop_device *lo, int cmd, + struct page *raw_page, unsigned raw_off, + struct page *loop_page, unsigned loop_off, + int size, sector_t IV) { - struct crypto_tfm *tfm = (struct crypto_tfm *) lo->key_data; + struct crypto_blkcipher *tfm = lo->key_data; + struct blkcipher_desc desc = { + .tfm = tfm, + .flags = CRYPTO_TFM_REQ_MAY_SLEEP, + }; struct scatterlist sg_out = { NULL, }; struct scatterlist sg_in = { NULL, }; encdec_cbc_t encdecfunc; struct page *in_page, *out_page; unsigned in_offs, out_offs; + int err; if (cmd == READ) { in_page = raw_page; in_offs = raw_off; out_page = loop_page; out_offs = loop_off; - encdecfunc = tfm->crt_u.cipher.cit_decrypt_iv; + encdecfunc = crypto_blkcipher_crt(tfm)->decrypt; } else { in_page = loop_page; in_offs = loop_off; out_page = raw_page; out_offs = raw_off; - encdecfunc = tfm->crt_u.cipher.cit_encrypt_iv; + encdecfunc = crypto_blkcipher_crt(tfm)->encrypt; } while (size > 0) { @@ -183,7 +154,10 @@ cryptoloop_transfer_cbc(struct loop_device *lo, int cmd, sg_out.offset = out_offs; sg_out.length = sz; - encdecfunc(tfm, &sg_out, &sg_in, sz, (u8 *)iv); + desc.info = iv; + err = encdecfunc(&desc, &sg_out, &sg_in, sz); + if (err) + return err; IV++; size -= sz; @@ -195,32 +169,6 @@ cryptoloop_transfer_cbc(struct loop_device *lo, int cmd, } static int -cryptoloop_transfer(struct loop_device *lo, int cmd, - struct page *raw_page, unsigned raw_off, - struct page *loop_page, unsigned loop_off, - int size, sector_t IV) -{ - struct crypto_tfm *tfm = (struct crypto_tfm *) lo->key_data; - if(tfm->crt_cipher.cit_mode == CRYPTO_TFM_MODE_ECB) - { - lo->transfer = cryptoloop_transfer_ecb; - return cryptoloop_transfer_ecb(lo, cmd, raw_page, raw_off, - loop_page, loop_off, size, IV); - } - if(tfm->crt_cipher.cit_mode == CRYPTO_TFM_MODE_CBC) - { - lo->transfer = cryptoloop_transfer_cbc; - return cryptoloop_transfer_cbc(lo, cmd, raw_page, raw_off, - loop_page, loop_off, size, IV); - } - - /* This is not supposed to happen */ - - printk( KERN_ERR "cryptoloop: unsupported cipher mode in cryptoloop_transfer!\n"); - return -EINVAL; -} - -static int cryptoloop_ioctl(struct loop_device *lo, int cmd, unsigned long arg) { return -EINVAL; @@ -229,9 +177,9 @@ cryptoloop_ioctl(struct loop_device *lo, int cmd, unsigned long arg) static int cryptoloop_release(struct loop_device *lo) { - struct crypto_tfm *tfm = (struct crypto_tfm *) lo->key_data; + struct crypto_blkcipher *tfm = lo->key_data; if (tfm != NULL) { - crypto_free_tfm(tfm); + crypto_free_blkcipher(tfm); lo->key_data = NULL; return 0; } diff --git a/drivers/block/floppy.c b/drivers/block/floppy.c index ad1d7065a1b2..629c5769d994 100644 --- a/drivers/block/floppy.c +++ b/drivers/block/floppy.c @@ -2991,8 +2991,8 @@ static void do_fd_request(request_queue_t * q) if (usage_count == 0) { printk("warning: usage count=0, current_req=%p exiting\n", current_req); - printk("sect=%ld flags=%lx\n", (long)current_req->sector, - current_req->flags); + printk("sect=%ld type=%x flags=%x\n", (long)current_req->sector, + current_req->cmd_type, current_req->cmd_flags); return; } if (test_bit(0, &fdc_busy)) { diff --git a/drivers/block/loop.c b/drivers/block/loop.c index 7b3b94ddddcc..d6bb8da955a2 100644 --- a/drivers/block/loop.c +++ b/drivers/block/loop.c @@ -66,12 +66,14 @@ #include <linux/swap.h> #include <linux/slab.h> #include <linux/loop.h> +#include <linux/compat.h> #include <linux/suspend.h> #include <linux/writeback.h> #include <linux/buffer_head.h> /* for invalidate_bdev() */ #include <linux/completion.h> #include <linux/highmem.h> #include <linux/gfp.h> +#include <linux/kthread.h> #include <asm/uaccess.h> @@ -522,15 +524,12 @@ static int loop_make_request(request_queue_t *q, struct bio *old_bio) goto out; if (unlikely(rw == WRITE && (lo->lo_flags & LO_FLAGS_READ_ONLY))) goto out; - lo->lo_pending++; loop_add_bio(lo, old_bio); + wake_up(&lo->lo_event); spin_unlock_irq(&lo->lo_lock); - complete(&lo->lo_bh_done); return 0; out: - if (lo->lo_pending == 0) - complete(&lo->lo_bh_done); spin_unlock_irq(&lo->lo_lock); bio_io_error(old_bio, old_bio->bi_size); return 0; @@ -570,14 +569,18 @@ static inline void loop_handle_bio(struct loop_device *lo, struct bio *bio) * to avoid blocking in our make_request_fn. it also does loop decrypting * on reads for block backed loop, as that is too heavy to do from * b_end_io context where irqs may be disabled. + * + * Loop explanation: loop_clr_fd() sets lo_state to Lo_rundown before + * calling kthread_stop(). Therefore once kthread_should_stop() is + * true, make_request will not place any more requests. Therefore + * once kthread_should_stop() is true and lo_bio is NULL, we are + * done with the loop. */ static int loop_thread(void *data) { struct loop_device *lo = data; struct bio *bio; - daemonize("loop%d", lo->lo_number); - /* * loop can be used in an encrypted device, * hence, it mustn't be stopped at all @@ -587,47 +590,21 @@ static int loop_thread(void *data) set_user_nice(current, -20); - lo->lo_state = Lo_bound; - lo->lo_pending = 1; + while (!kthread_should_stop() || lo->lo_bio) { - /* - * complete it, we are running - */ - complete(&lo->lo_done); - - for (;;) { - int pending; + wait_event_interruptible(lo->lo_event, + lo->lo_bio || kthread_should_stop()); - if (wait_for_completion_interruptible(&lo->lo_bh_done)) + if (!lo->lo_bio) continue; - spin_lock_irq(&lo->lo_lock); - - /* - * could be completed because of tear-down, not pending work - */ - if (unlikely(!lo->lo_pending)) { - spin_unlock_irq(&lo->lo_lock); - break; - } - bio = loop_get_bio(lo); - lo->lo_pending--; - pending = lo->lo_pending; spin_unlock_irq(&lo->lo_lock); BUG_ON(!bio); loop_handle_bio(lo, bio); - - /* - * upped both for pending work and tear-down, lo_pending - * will hit zero then - */ - if (unlikely(!pending)) - break; } - complete(&lo->lo_done); return 0; } @@ -662,7 +639,8 @@ static void do_loop_switch(struct loop_device *lo, struct switch_request *p) mapping_set_gfp_mask(old_file->f_mapping, lo->old_gfp_mask); lo->lo_backing_file = file; - lo->lo_blocksize = mapping->host->i_blksize; + lo->lo_blocksize = S_ISBLK(mapping->host->i_mode) ? + mapping->host->i_bdev->bd_block_size : PAGE_SIZE; lo->old_gfp_mask = mapping_gfp_mask(mapping); mapping_set_gfp_mask(mapping, lo->old_gfp_mask & ~(__GFP_IO|__GFP_FS)); complete(&p->wait); @@ -794,7 +772,9 @@ static int loop_set_fd(struct loop_device *lo, struct file *lo_file, if (!(lo_flags & LO_FLAGS_USE_AOPS) && !file->f_op->write) lo_flags |= LO_FLAGS_READ_ONLY; - lo_blocksize = inode->i_blksize; + lo_blocksize = S_ISBLK(inode->i_mode) ? + inode->i_bdev->bd_block_size : PAGE_SIZE; + error = 0; } else { goto out_putf; @@ -837,12 +817,26 @@ static int loop_set_fd(struct loop_device *lo, struct file *lo_file, set_blocksize(bdev, lo_blocksize); - error = kernel_thread(loop_thread, lo, CLONE_KERNEL); - if (error < 0) - goto out_putf; - wait_for_completion(&lo->lo_done); + lo->lo_thread = kthread_create(loop_thread, lo, "loop%d", + lo->lo_number); + if (IS_ERR(lo->lo_thread)) { + error = PTR_ERR(lo->lo_thread); + goto out_clr; + } + lo->lo_state = Lo_bound; + wake_up_process(lo->lo_thread); return 0; +out_clr: + lo->lo_thread = NULL; + lo->lo_device = NULL; + lo->lo_backing_file = NULL; + lo->lo_flags = 0; + set_capacity(disks[lo->lo_number], 0); + invalidate_bdev(bdev, 0); + bd_set_size(bdev, 0); + mapping_set_gfp_mask(mapping, lo->old_gfp_mask); + lo->lo_state = Lo_unbound; out_putf: fput(file); out: @@ -904,12 +898,9 @@ static int loop_clr_fd(struct loop_device *lo, struct block_device *bdev) spin_lock_irq(&lo->lo_lock); lo->lo_state = Lo_rundown; - lo->lo_pending--; - if (!lo->lo_pending) - complete(&lo->lo_bh_done); spin_unlock_irq(&lo->lo_lock); - wait_for_completion(&lo->lo_done); + kthread_stop(lo->lo_thread); lo->lo_backing_file = NULL; @@ -922,6 +913,7 @@ static int loop_clr_fd(struct loop_device *lo, struct block_device *bdev) lo->lo_sizelimit = 0; lo->lo_encrypt_key_size = 0; lo->lo_flags = 0; + lo->lo_thread = NULL; memset(lo->lo_encrypt_key, 0, LO_KEY_SIZE); memset(lo->lo_crypt_name, 0, LO_NAME_SIZE); memset(lo->lo_file_name, 0, LO_NAME_SIZE); @@ -1174,6 +1166,162 @@ static int lo_ioctl(struct inode * inode, struct file * file, return err; } +#ifdef CONFIG_COMPAT +struct compat_loop_info { + compat_int_t lo_number; /* ioctl r/o */ + compat_dev_t lo_device; /* ioctl r/o */ + compat_ulong_t lo_inode; /* ioctl r/o */ + compat_dev_t lo_rdevice; /* ioctl r/o */ + compat_int_t lo_offset; + compat_int_t lo_encrypt_type; + compat_int_t lo_encrypt_key_size; /* ioctl w/o */ + compat_int_t lo_flags; /* ioctl r/o */ + char lo_name[LO_NAME_SIZE]; + unsigned char lo_encrypt_key[LO_KEY_SIZE]; /* ioctl w/o */ + compat_ulong_t lo_init[2]; + char reserved[4]; +}; + +/* + * Transfer 32-bit compatibility structure in userspace to 64-bit loop info + * - noinlined to reduce stack space usage in main part of driver + */ +static noinline int +loop_info64_from_compat(const struct compat_loop_info *arg, + struct loop_info64 *info64) +{ + struct compat_loop_info info; + + if (copy_from_user(&info, arg, sizeof(info))) + return -EFAULT; + + memset(info64, 0, sizeof(*info64)); + info64->lo_number = info.lo_number; + info64->lo_device = info.lo_device; + info64->lo_inode = info.lo_inode; + info64->lo_rdevice = info.lo_rdevice; + info64->lo_offset = info.lo_offset; + info64->lo_sizelimit = 0; + info64->lo_encrypt_type = info.lo_encrypt_type; + info64->lo_encrypt_key_size = info.lo_encrypt_key_size; + info64->lo_flags = info.lo_flags; + info64->lo_init[0] = info.lo_init[0]; + info64->lo_init[1] = info.lo_init[1]; + if (info.lo_encrypt_type == LO_CRYPT_CRYPTOAPI) + memcpy(info64->lo_crypt_name, info.lo_name, LO_NAME_SIZE); + else + memcpy(info64->lo_file_name, info.lo_name, LO_NAME_SIZE); + memcpy(info64->lo_encrypt_key, info.lo_encrypt_key, LO_KEY_SIZE); + return 0; +} + +/* + * Transfer 64-bit loop info to 32-bit compatibility structure in userspace + * - noinlined to reduce stack space usage in main part of driver + */ +static noinline int +loop_info64_to_compat(const struct loop_info64 *info64, + struct compat_loop_info __user *arg) +{ + struct compat_loop_info info; + + memset(&info, 0, sizeof(info)); + info.lo_number = info64->lo_number; + info.lo_device = info64->lo_device; + info.lo_inode = info64->lo_inode; + info.lo_rdevice = info64->lo_rdevice; + info.lo_offset = info64->lo_offset; + info.lo_encrypt_type = info64->lo_encrypt_type; + info.lo_encrypt_key_size = info64->lo_encrypt_key_size; + info.lo_flags = info64->lo_flags; + info.lo_init[0] = info64->lo_init[0]; + info.lo_init[1] = info64->lo_init[1]; + if (info.lo_encrypt_type == LO_CRYPT_CRYPTOAPI) + memcpy(info.lo_name, info64->lo_crypt_name, LO_NAME_SIZE); + else + memcpy(info.lo_name, info64->lo_file_name, LO_NAME_SIZE); + memcpy(info.lo_encrypt_key, info64->lo_encrypt_key, LO_KEY_SIZE); + + /* error in case values were truncated */ + if (info.lo_device != info64->lo_device || + info.lo_rdevice != info64->lo_rdevice || + info.lo_inode != info64->lo_inode || + info.lo_offset != info64->lo_offset || + info.lo_init[0] != info64->lo_init[0] || + info.lo_init[1] != info64->lo_init[1]) + return -EOVERFLOW; + + if (copy_to_user(arg, &info, sizeof(info))) + return -EFAULT; + return 0; +} + +static int +loop_set_status_compat(struct loop_device *lo, + const struct compat_loop_info __user *arg) +{ + struct loop_info64 info64; + int ret; + + ret = loop_info64_from_compat(arg, &info64); + if (ret < 0) + return ret; + return loop_set_status(lo, &info64); +} + +static int +loop_get_status_compat(struct loop_device *lo, + struct compat_loop_info __user *arg) +{ + struct loop_info64 info64; + int err = 0; + + if (!arg) + err = -EINVAL; + if (!err) + err = loop_get_status(lo, &info64); + if (!err) + err = loop_info64_to_compat(&info64, arg); + return err; +} + +static long lo_compat_ioctl(struct file *file, unsigned int cmd, unsigned long arg) +{ + struct inode *inode = file->f_dentry->d_inode; + struct loop_device *lo = inode->i_bdev->bd_disk->private_data; + int err; + + lock_kernel(); + switch(cmd) { + case LOOP_SET_STATUS: + mutex_lock(&lo->lo_ctl_mutex); + err = loop_set_status_compat( + lo, (const struct compat_loop_info __user *) arg); + mutex_unlock(&lo->lo_ctl_mutex); + break; + case LOOP_GET_STATUS: + mutex_lock(&lo->lo_ctl_mutex); + err = loop_get_status_compat( + lo, (struct compat_loop_info __user *) arg); + mutex_unlock(&lo->lo_ctl_mutex); + break; + case LOOP_CLR_FD: + case LOOP_GET_STATUS64: + case LOOP_SET_STATUS64: + arg = (unsigned long) compat_ptr(arg); + case LOOP_SET_FD: + case LOOP_CHANGE_FD: + err = lo_ioctl(inode, file, cmd, arg); + break; + default: + err = -ENOIOCTLCMD; + break; + } + unlock_kernel(); + return err; +} +#endif + static int lo_open(struct inode *inode, struct file *file) { struct loop_device *lo = inode->i_bdev->bd_disk->private_data; @@ -1201,6 +1349,9 @@ static struct block_device_operations lo_fops = { .open = lo_open, .release = lo_release, .ioctl = lo_ioctl, +#ifdef CONFIG_COMPAT + .compat_ioctl = lo_compat_ioctl, +#endif }; /* @@ -1284,9 +1435,9 @@ static int __init loop_init(void) if (!lo->lo_queue) goto out_mem4; mutex_init(&lo->lo_ctl_mutex); - init_completion(&lo->lo_done); - init_completion(&lo->lo_bh_done); lo->lo_number = i; + lo->lo_thread = NULL; + init_waitqueue_head(&lo->lo_event); spin_lock_init(&lo->lo_lock); disk->major = LOOP_MAJOR; disk->first_minor = i; diff --git a/drivers/block/nbd.c b/drivers/block/nbd.c index bdbade9a5cf5..9d1035e8d9d8 100644 --- a/drivers/block/nbd.c +++ b/drivers/block/nbd.c @@ -407,10 +407,10 @@ static void do_nbd_request(request_queue_t * q) struct nbd_device *lo; blkdev_dequeue_request(req); - dprintk(DBG_BLKDEV, "%s: request %p: dequeued (flags=%lx)\n", - req->rq_disk->disk_name, req, req->flags); + dprintk(DBG_BLKDEV, "%s: request %p: dequeued (flags=%x)\n", + req->rq_disk->disk_name, req, req->cmd_type); - if (!(req->flags & REQ_CMD)) + if (!blk_fs_request(req)) goto error_out; lo = req->rq_disk->private_data; @@ -489,7 +489,7 @@ static int nbd_ioctl(struct inode *inode, struct file *file, switch (cmd) { case NBD_DISCONNECT: printk(KERN_INFO "%s: NBD_DISCONNECT\n", lo->disk->disk_name); - sreq.flags = REQ_SPECIAL; + sreq.cmd_type = REQ_TYPE_SPECIAL; nbd_cmd(&sreq) = NBD_CMD_DISC; /* * Set these to sane values in case server implementation diff --git a/drivers/block/paride/pd.c b/drivers/block/paride/pd.c index 2403721f9db1..40a11e567970 100644 --- a/drivers/block/paride/pd.c +++ b/drivers/block/paride/pd.c @@ -437,7 +437,7 @@ static char *pd_buf; /* buffer for request in progress */ static enum action do_pd_io_start(void) { - if (pd_req->flags & REQ_SPECIAL) { + if (blk_special_request(pd_req)) { phase = pd_special; return pd_special(); } @@ -713,20 +713,18 @@ static void do_pd_request(request_queue_t * q) static int pd_special_command(struct pd_unit *disk, enum action (*func)(struct pd_unit *disk)) { - DECLARE_COMPLETION(wait); + DECLARE_COMPLETION_ONSTACK(wait); struct request rq; int err = 0; memset(&rq, 0, sizeof(rq)); rq.errors = 0; - rq.rq_status = RQ_ACTIVE; rq.rq_disk = disk->gd; rq.ref_count = 1; - rq.waiting = &wait; + rq.end_io_data = &wait; rq.end_io = blk_end_sync_rq; blk_insert_request(disk->gd->queue, &rq, 0, func); wait_for_completion(&wait); - rq.waiting = NULL; if (rq.errors) err = -EIO; blk_put_request(&rq); diff --git a/drivers/block/pktcdvd.c b/drivers/block/pktcdvd.c index 451b996bba91..a6b2aa67c9b2 100644 --- a/drivers/block/pktcdvd.c +++ b/drivers/block/pktcdvd.c @@ -348,7 +348,7 @@ static int pkt_generic_packet(struct pktcdvd_device *pd, struct packet_command * char sense[SCSI_SENSE_BUFFERSIZE]; request_queue_t *q; struct request *rq; - DECLARE_COMPLETION(wait); + DECLARE_COMPLETION_ONSTACK(wait); int err = 0; q = bdev_get_queue(pd->bdev); @@ -365,17 +365,17 @@ static int pkt_generic_packet(struct pktcdvd_device *pd, struct packet_command * rq->sense = sense; memset(sense, 0, sizeof(sense)); rq->sense_len = 0; - rq->flags |= REQ_BLOCK_PC | REQ_HARDBARRIER; + rq->cmd_type = REQ_TYPE_BLOCK_PC; + rq->cmd_flags |= REQ_HARDBARRIER; if (cgc->quiet) - rq->flags |= REQ_QUIET; + rq->cmd_flags |= REQ_QUIET; memcpy(rq->cmd, cgc->cmd, CDROM_PACKET_SIZE); if (sizeof(rq->cmd) > CDROM_PACKET_SIZE) memset(rq->cmd + CDROM_PACKET_SIZE, 0, sizeof(rq->cmd) - CDROM_PACKET_SIZE); rq->cmd_len = COMMAND_SIZE(rq->cmd[0]); rq->ref_count++; - rq->flags |= REQ_NOMERGE; - rq->waiting = &wait; + rq->end_io_data = &wait; rq->end_io = blk_end_sync_rq; elv_add_request(q, rq, ELEVATOR_INSERT_BACK, 1); generic_unplug_device(q); diff --git a/drivers/block/swim3.c b/drivers/block/swim3.c index cc42e762396f..f2305ee792a1 100644 --- a/drivers/block/swim3.c +++ b/drivers/block/swim3.c @@ -319,8 +319,8 @@ static void start_request(struct floppy_state *fs) printk("do_fd_req: dev=%s cmd=%d sec=%ld nr_sec=%ld buf=%p\n", req->rq_disk->disk_name, req->cmd, (long)req->sector, req->nr_sectors, req->buffer); - printk(" rq_status=%d errors=%d current_nr_sectors=%ld\n", - req->rq_status, req->errors, req->current_nr_sectors); + printk(" errors=%d current_nr_sectors=%ld\n", + req->errors, req->current_nr_sectors); #endif if (req->sector < 0 || req->sector >= fs->total_secs) { diff --git a/drivers/block/swim_iop.c b/drivers/block/swim_iop.c index 89e3c2f8b776..dfda796eba56 100644 --- a/drivers/block/swim_iop.c +++ b/drivers/block/swim_iop.c @@ -529,8 +529,8 @@ static void start_request(struct floppy_state *fs) printk("do_fd_req: dev=%s cmd=%d sec=%ld nr_sec=%ld buf=%p\n", CURRENT->rq_disk->disk_name, CURRENT->cmd, CURRENT->sector, CURRENT->nr_sectors, CURRENT->buffer); - printk(" rq_status=%d errors=%d current_nr_sectors=%ld\n", - CURRENT->rq_status, CURRENT->errors, CURRENT->current_nr_sectors); + printk(" errors=%d current_nr_sectors=%ld\n", + CURRENT->errors, CURRENT->current_nr_sectors); #endif if (CURRENT->sector < 0 || CURRENT->sector >= fs->total_secs) { diff --git a/drivers/block/ub.c b/drivers/block/ub.c index d62b49fbf10c..45a8f402b07b 100644 --- a/drivers/block/ub.c +++ b/drivers/block/ub.c @@ -358,7 +358,7 @@ static void ub_cmd_build_block(struct ub_dev *sc, struct ub_lun *lun, static void ub_cmd_build_packet(struct ub_dev *sc, struct ub_lun *lun, struct ub_scsi_cmd *cmd, struct ub_request *urq); static void ub_rw_cmd_done(struct ub_dev *sc, struct ub_scsi_cmd *cmd); -static void ub_end_rq(struct request *rq, int uptodate); +static void ub_end_rq(struct request *rq, unsigned int status); static int ub_rw_cmd_retry(struct ub_dev *sc, struct ub_lun *lun, struct ub_request *urq, struct ub_scsi_cmd *cmd); static int ub_submit_scsi(struct ub_dev *sc, struct ub_scsi_cmd *cmd); @@ -639,9 +639,15 @@ static int ub_request_fn_1(struct ub_lun *lun, struct request *rq) struct ub_request *urq; int n_elem; - if (atomic_read(&sc->poison) || lun->changed) { + if (atomic_read(&sc->poison)) { + blkdev_dequeue_request(rq); + ub_end_rq(rq, DID_NO_CONNECT << 16); + return 0; + } + + if (lun->changed && !blk_pc_request(rq)) { blkdev_dequeue_request(rq); - ub_end_rq(rq, 0); + ub_end_rq(rq, SAM_STAT_CHECK_CONDITION); return 0; } @@ -693,7 +699,7 @@ static int ub_request_fn_1(struct ub_lun *lun, struct request *rq) drop: ub_put_cmd(lun, cmd); - ub_end_rq(rq, 0); + ub_end_rq(rq, DID_ERROR << 16); return 0; } @@ -761,47 +767,53 @@ static void ub_rw_cmd_done(struct ub_dev *sc, struct ub_scsi_cmd *cmd) struct ub_lun *lun = cmd->lun; struct ub_request *urq = cmd->back; struct request *rq; - int uptodate; + unsigned int scsi_status; rq = urq->rq; if (cmd->error == 0) { - uptodate = 1; - if (blk_pc_request(rq)) { if (cmd->act_len >= rq->data_len) rq->data_len = 0; else rq->data_len -= cmd->act_len; } + scsi_status = 0; } else { - uptodate = 0; - if (blk_pc_request(rq)) { /* UB_SENSE_SIZE is smaller than SCSI_SENSE_BUFFERSIZE */ memcpy(rq->sense, sc->top_sense, UB_SENSE_SIZE); rq->sense_len = UB_SENSE_SIZE; if (sc->top_sense[0] != 0) - rq->errors = SAM_STAT_CHECK_CONDITION; + scsi_status = SAM_STAT_CHECK_CONDITION; else - rq->errors = DID_ERROR << 16; + scsi_status = DID_ERROR << 16; } else { if (cmd->error == -EIO) { if (ub_rw_cmd_retry(sc, lun, urq, cmd) == 0) return; } + scsi_status = SAM_STAT_CHECK_CONDITION; } } urq->rq = NULL; ub_put_cmd(lun, cmd); - ub_end_rq(rq, uptodate); + ub_end_rq(rq, scsi_status); blk_start_queue(lun->disk->queue); } -static void ub_end_rq(struct request *rq, int uptodate) +static void ub_end_rq(struct request *rq, unsigned int scsi_status) { + int uptodate; + + if (scsi_status == 0) { + uptodate = 1; + } else { + uptodate = 0; + rq->errors = scsi_status; + } end_that_request_first(rq, uptodate, rq->hard_nr_sectors); end_that_request_last(rq, uptodate); } diff --git a/drivers/block/xd.c b/drivers/block/xd.c index e828e4cbd3e1..ebf3025721d1 100644 --- a/drivers/block/xd.c +++ b/drivers/block/xd.c @@ -313,7 +313,7 @@ static void do_xd_request (request_queue_t * q) int res = 0; int retry; - if (!(req->flags & REQ_CMD)) { + if (!blk_fs_request(req)) { end_request(req, 0); continue; } |
