diff options
Diffstat (limited to 'drivers/block')
-rw-r--r-- | drivers/block/Kconfig | 4 | ||||
-rw-r--r-- | drivers/block/acsi_slm.c | 1 | ||||
-rw-r--r-- | drivers/block/amiflop.c | 2 | ||||
-rw-r--r-- | drivers/block/aoe/aoe.h | 9 | ||||
-rw-r--r-- | drivers/block/aoe/aoecmd.c | 25 | ||||
-rw-r--r-- | drivers/block/aoe/aoenet.c | 2 | ||||
-rw-r--r-- | drivers/block/cciss.c | 334 | ||||
-rw-r--r-- | drivers/block/cciss_scsi.c | 1 | ||||
-rw-r--r-- | drivers/block/floppy.c | 7 | ||||
-rw-r--r-- | drivers/block/loop.c | 194 | ||||
-rw-r--r-- | drivers/block/nbd.c | 15 | ||||
-rw-r--r-- | drivers/block/paride/pcd.c | 2 | ||||
-rw-r--r-- | drivers/block/paride/pd.c | 8 | ||||
-rw-r--r-- | drivers/block/paride/pf.c | 2 | ||||
-rw-r--r-- | drivers/block/pktcdvd.c | 3 | ||||
-rw-r--r-- | drivers/block/rd.c | 4 | ||||
-rw-r--r-- | drivers/block/ub.c | 11 | ||||
-rw-r--r-- | drivers/block/umem.c | 1 |
18 files changed, 375 insertions, 250 deletions
diff --git a/drivers/block/Kconfig b/drivers/block/Kconfig index 17ee97f3a99..b4c8319138b 100644 --- a/drivers/block/Kconfig +++ b/drivers/block/Kconfig @@ -444,8 +444,6 @@ config CDROM_PKTCDVD_WCACHE this option is dangerous unless the CD-RW media is known good, as we don't do deferred write error handling yet. -source "drivers/s390/block/Kconfig" - config ATA_OVER_ETH tristate "ATA over Ethernet support" depends on NET @@ -453,6 +451,8 @@ config ATA_OVER_ETH This driver provides Support for ATA over Ethernet block devices like the Coraid EtherDrive (R) Storage Blade. +source "drivers/s390/block/Kconfig" + endmenu endif diff --git a/drivers/block/acsi_slm.c b/drivers/block/acsi_slm.c index e2e04329096..1d9d9b4f48c 100644 --- a/drivers/block/acsi_slm.c +++ b/drivers/block/acsi_slm.c @@ -65,7 +65,6 @@ not be guaranteed. There are several ways to assure this: #include <linux/time.h> #include <linux/mm.h> #include <linux/slab.h> -#include <linux/smp_lock.h> #include <asm/pgtable.h> #include <asm/system.h> diff --git a/drivers/block/amiflop.c b/drivers/block/amiflop.c index 5d656217153..27a139025ce 100644 --- a/drivers/block/amiflop.c +++ b/drivers/block/amiflop.c @@ -1480,7 +1480,7 @@ static int fd_ioctl(struct inode *inode, struct file *filp, break; case FDFMTEND: floppy_off(drive); - invalidate_bdev(inode->i_bdev, 0); + invalidate_bdev(inode->i_bdev); break; case FDGETPRM: memset((void *)&getprm, 0, sizeof (getprm)); diff --git a/drivers/block/aoe/aoe.h b/drivers/block/aoe/aoe.h index 2308e83e5f3..1d846681794 100644 --- a/drivers/block/aoe/aoe.h +++ b/drivers/block/aoe/aoe.h @@ -48,6 +48,15 @@ struct aoe_hdr { __be32 tag; }; +#ifdef __KERNEL__ +#include <linux/skbuff.h> + +static inline struct aoe_hdr *aoe_hdr(const struct sk_buff *skb) +{ + return (struct aoe_hdr *)skb_mac_header(skb); +} +#endif + struct aoe_atahdr { unsigned char aflags; unsigned char errfeat; diff --git a/drivers/block/aoe/aoecmd.c b/drivers/block/aoe/aoecmd.c index 8d17d8df366..01fbdd38e3b 100644 --- a/drivers/block/aoe/aoecmd.c +++ b/drivers/block/aoe/aoecmd.c @@ -27,7 +27,8 @@ new_skb(ulong len) skb = alloc_skb(len, GFP_ATOMIC); if (skb) { - skb->nh.raw = skb->mac.raw = skb->data; + skb_reset_mac_header(skb); + skb_reset_network_header(skb); skb->protocol = __constant_htons(ETH_P_AOE); skb->priority = 0; skb->next = skb->prev = NULL; @@ -118,7 +119,7 @@ aoecmd_ata_rw(struct aoedev *d, struct frame *f) /* initialize the headers & frame */ skb = f->skb; - h = (struct aoe_hdr *) skb->mac.raw; + h = aoe_hdr(skb); ah = (struct aoe_atahdr *) (h+1); skb_put(skb, sizeof *h + sizeof *ah); memset(h, 0, skb->len); @@ -193,21 +194,21 @@ aoecmd_cfg_pkts(ushort aoemajor, unsigned char aoeminor, struct sk_buff **tail) sl = sl_tail = NULL; read_lock(&dev_base_lock); - for (ifp = dev_base; ifp; dev_put(ifp), ifp = ifp->next) { + for_each_netdev(ifp) { dev_hold(ifp); if (!is_aoe_netif(ifp)) - continue; + goto cont; skb = new_skb(sizeof *h + sizeof *ch); if (skb == NULL) { printk(KERN_INFO "aoe: skb alloc failure\n"); - continue; + goto cont; } skb_put(skb, sizeof *h + sizeof *ch); skb->dev = ifp; if (sl_tail == NULL) sl_tail = skb; - h = (struct aoe_hdr *) skb->mac.raw; + h = aoe_hdr(skb); memset(h, 0, sizeof *h + sizeof *ch); memset(h->dst, 0xff, sizeof h->dst); @@ -220,6 +221,8 @@ aoecmd_cfg_pkts(ushort aoemajor, unsigned char aoeminor, struct sk_buff **tail) skb->next = sl; sl = skb; +cont: + dev_put(ifp); } read_unlock(&dev_base_lock); @@ -300,7 +303,7 @@ rexmit(struct aoedev *d, struct frame *f) aoechr_error(buf); skb = f->skb; - h = (struct aoe_hdr *) skb->mac.raw; + h = aoe_hdr(skb); ah = (struct aoe_atahdr *) (h+1); f->tag = n; h->tag = cpu_to_be32(n); @@ -529,7 +532,7 @@ aoecmd_ata_rsp(struct sk_buff *skb) char ebuf[128]; u16 aoemajor; - hin = (struct aoe_hdr *) skb->mac.raw; + hin = aoe_hdr(skb); aoemajor = be16_to_cpu(get_unaligned(&hin->major)); d = aoedev_by_aoeaddr(aoemajor, hin->minor); if (d == NULL) { @@ -561,7 +564,7 @@ aoecmd_ata_rsp(struct sk_buff *skb) calc_rttavg(d, tsince(f->tag)); ahin = (struct aoe_atahdr *) (hin+1); - hout = (struct aoe_hdr *) f->skb->mac.raw; + hout = aoe_hdr(f->skb); ahout = (struct aoe_atahdr *) (hout+1); buf = f->buf; @@ -695,7 +698,7 @@ aoecmd_ata_id(struct aoedev *d) /* initialize the headers & frame */ skb = f->skb; - h = (struct aoe_hdr *) skb->mac.raw; + h = aoe_hdr(skb); ah = (struct aoe_atahdr *) (h+1); skb_put(skb, sizeof *h + sizeof *ah); memset(h, 0, skb->len); @@ -726,7 +729,7 @@ aoecmd_cfg_rsp(struct sk_buff *skb) enum { MAXFRAMES = 16 }; u16 n; - h = (struct aoe_hdr *) skb->mac.raw; + h = aoe_hdr(skb); ch = (struct aoe_cfghdr *) (h+1); /* diff --git a/drivers/block/aoe/aoenet.c b/drivers/block/aoe/aoenet.c index aab6d91a2c2..f9ddfda4d9c 100644 --- a/drivers/block/aoe/aoenet.c +++ b/drivers/block/aoe/aoenet.c @@ -123,7 +123,7 @@ aoenet_rcv(struct sk_buff *skb, struct net_device *ifp, struct packet_type *pt, goto exit; skb_push(skb, ETH_HLEN); /* (1) */ - h = (struct aoe_hdr *) skb->mac.raw; + h = aoe_hdr(skb); n = be32_to_cpu(get_unaligned(&h->tag)); if ((h->verfl & AOEFL_RSP) == 0 || (n & 1<<31)) goto exit; diff --git a/drivers/block/cciss.c b/drivers/block/cciss.c index 0c716ee905d..370dfe1c422 100644 --- a/drivers/block/cciss.c +++ b/drivers/block/cciss.c @@ -45,6 +45,10 @@ #include <linux/blkdev.h> #include <linux/genhd.h> #include <linux/completion.h> +#include <scsi/scsi.h> +#include <scsi/sg.h> +#include <scsi/scsi_ioctl.h> +#include <linux/cdrom.h> #define CCISS_DRIVER_VERSION(maj,min,submin) ((maj<<16)|(min<<8)|(submin)) #define DRIVER_NAME "HP CISS Driver (v 3.6.14)" @@ -1152,6 +1156,30 @@ static int cciss_ioctl(struct inode *inode, struct file *filep, kfree(ioc); return status; } + + /* scsi_cmd_ioctl handles these, below, though some are not */ + /* very meaningful for cciss. SG_IO is the main one people want. */ + + case SG_GET_VERSION_NUM: + case SG_SET_TIMEOUT: + case SG_GET_TIMEOUT: + case SG_GET_RESERVED_SIZE: + case SG_SET_RESERVED_SIZE: + case SG_EMULATED_HOST: + case SG_IO: + case SCSI_IOCTL_SEND_COMMAND: + return scsi_cmd_ioctl(filep, disk, cmd, argp); + + /* scsi_cmd_ioctl would normally handle these, below, but */ + /* they aren't a good fit for cciss, as CD-ROMs are */ + /* not supported, and we don't have any bus/target/lun */ + /* which we present to the kernel. */ + + case CDROM_SEND_PACKET: + case CDROMCLOSETRAY: + case CDROMEJECT: + case SCSI_IOCTL_GET_IDLUN: + case SCSI_IOCTL_GET_BUS_NUMBER: default: return -ENOTTY; } @@ -1234,7 +1262,7 @@ static void cciss_softirq_done(struct request *rq) pci_unmap_page(h->pdev, temp64.val, cmd->SG[i].Len, ddir); } - complete_buffers(rq->bio, rq->errors); + complete_buffers(rq->bio, (rq->errors == 0)); if (blk_fs_request(rq)) { const int rw = rq_data_dir(rq); @@ -1248,7 +1276,7 @@ static void cciss_softirq_done(struct request *rq) add_disk_randomness(rq->rq_disk); spin_lock_irqsave(&h->lock, flags); - end_that_request_last(rq, rq->errors); + end_that_request_last(rq, (rq->errors == 0)); cmd_free(h, cmd, 1); cciss_check_queues(h); spin_unlock_irqrestore(&h->lock, flags); @@ -1439,7 +1467,7 @@ static int rebuild_lun_table(ctlr_info_t *h, struct gendisk *del_disk) if (return_code == IO_OK) { listlength = - be32_to_cpu(*(__u32 *) ld_buff->LUNListLength); + be32_to_cpu(*(__be32 *) ld_buff->LUNListLength); } else { /* reading number of logical volumes failed */ printk(KERN_WARNING "cciss: report logical volume" " command failed\n"); @@ -1915,6 +1943,7 @@ static void cciss_geometry_inquiry(int ctlr, int logvol, "does not support reading geometry\n"); drv->heads = 255; drv->sectors = 32; // Sectors per track + drv->cylinders = total_size + 1; drv->raid_level = RAID_UNKNOWN; } else { drv->heads = inq_buff->data_byte[6]; @@ -1961,8 +1990,8 @@ cciss_read_capacity(int ctlr, int logvol, int withirq, sector_t *total_size, ctlr, buf, sizeof(ReadCapdata_struct), 1, logvol, 0, NULL, TYPE_CMD); if (return_code == IO_OK) { - *total_size = be32_to_cpu(*(__u32 *) buf->total_size); - *block_size = be32_to_cpu(*(__u32 *) buf->block_size); + *total_size = be32_to_cpu(*(__be32 *) buf->total_size); + *block_size = be32_to_cpu(*(__be32 *) buf->block_size); } else { /* read capacity command failed */ printk(KERN_WARNING "cciss: read capacity failed\n"); *total_size = 0; @@ -1997,8 +2026,8 @@ cciss_read_capacity_16(int ctlr, int logvol, int withirq, sector_t *total_size, 1, logvol, 0, NULL, TYPE_CMD); } if (return_code == IO_OK) { - *total_size = be64_to_cpu(*(__u64 *) buf->total_size); - *block_size = be32_to_cpu(*(__u32 *) buf->block_size); + *total_size = be64_to_cpu(*(__be64 *) buf->total_size); + *block_size = be32_to_cpu(*(__be32 *) buf->block_size); } else { /* read capacity command failed */ printk(KERN_WARNING "cciss: read capacity failed\n"); *total_size = 0; @@ -2335,6 +2364,44 @@ static inline void resend_cciss_cmd(ctlr_info_t *h, CommandList_struct *c) start_io(h); } +static inline int evaluate_target_status(CommandList_struct *cmd) +{ + unsigned char sense_key; + int error_count = 1; + + if (cmd->err_info->ScsiStatus != 0x02) { /* not check condition? */ + if (!blk_pc_request(cmd->rq)) + printk(KERN_WARNING "cciss: cmd %p " + "has SCSI Status 0x%x\n", + cmd, cmd->err_info->ScsiStatus); + return error_count; + } + + /* check the sense key */ + sense_key = 0xf & cmd->err_info->SenseInfo[2]; + /* no status or recovered error */ + if ((sense_key == 0x0) || (sense_key == 0x1)) + error_count = 0; + + if (!blk_pc_request(cmd->rq)) { /* Not SG_IO or similar? */ + if (error_count != 0) + printk(KERN_WARNING "cciss: cmd %p has CHECK CONDITION" + " sense key = 0x%x\n", cmd, sense_key); + return error_count; + } + + /* SG_IO or similar, copy sense data back */ + if (cmd->rq->sense) { + if (cmd->rq->sense_len > cmd->err_info->SenseLen) + cmd->rq->sense_len = cmd->err_info->SenseLen; + memcpy(cmd->rq->sense, cmd->err_info->SenseInfo, + cmd->rq->sense_len); + } else + cmd->rq->sense_len = 0; + + return error_count; +} + /* checks the status of the job and calls complete buffers to mark all * buffers for the completed job. Note that this function does not need * to hold the hba/queue lock. @@ -2342,109 +2409,99 @@ static inline void resend_cciss_cmd(ctlr_info_t *h, CommandList_struct *c) static inline void complete_command(ctlr_info_t *h, CommandList_struct *cmd, int timeout) { - int status = 1; int retry_cmd = 0; + struct request *rq = cmd->rq; + + rq->errors = 0; if (timeout) - status = 0; + rq->errors = 1; - if (cmd->err_info->CommandStatus != 0) { /* an error has occurred */ - switch (cmd->err_info->CommandStatus) { - unsigned char sense_key; - case CMD_TARGET_STATUS: - status = 0; + if (cmd->err_info->CommandStatus == 0) /* no error has occurred */ + goto after_error_processing; - if (cmd->err_info->ScsiStatus == 0x02) { - printk(KERN_WARNING "cciss: cmd %p " - "has CHECK CONDITION " - " byte 2 = 0x%x\n", cmd, - cmd->err_info->SenseInfo[2] - ); - /* check the sense key */ - sense_key = 0xf & cmd->err_info->SenseInfo[2]; - /* no status or recovered error */ - if ((sense_key == 0x0) || (sense_key == 0x1)) { - status = 1; - } - } else { - printk(KERN_WARNING "cciss: cmd %p " - "has SCSI Status 0x%x\n", - cmd, cmd->err_info->ScsiStatus); - } - break; - case CMD_DATA_UNDERRUN: + switch (cmd->err_info->CommandStatus) { + case CMD_TARGET_STATUS: + rq->errors = evaluate_target_status(cmd); + break; + case CMD_DATA_UNDERRUN: + if (blk_fs_request(cmd->rq)) { printk(KERN_WARNING "cciss: cmd %p has" " completed with data underrun " "reported\n", cmd); - break; - case CMD_DATA_OVERRUN: + cmd->rq->data_len = cmd->err_info->ResidualCnt; + } + break; + case CMD_DATA_OVERRUN: + if (blk_fs_request(cmd->rq)) printk(KERN_WARNING "cciss: cmd %p has" " completed with data overrun " "reported\n", cmd); - break; - case CMD_INVALID: - printk(KERN_WARNING "cciss: cmd %p is " - "reported invalid\n", cmd); - status = 0; - break; - case CMD_PROTOCOL_ERR: - printk(KERN_WARNING "cciss: cmd %p has " - "protocol error \n", cmd); - status = 0; - break; - case CMD_HARDWARE_ERR: - printk(KERN_WARNING "cciss: cmd %p had " - " hardware error\n", cmd); - status = 0; - break; - case CMD_CONNECTION_LOST: - printk(KERN_WARNING "cciss: cmd %p had " - "connection lost\n", cmd); - status = 0; - break; - case CMD_ABORTED: - printk(KERN_WARNING "cciss: cmd %p was " - "aborted\n", cmd); - status = 0; - break; - case CMD_ABORT_FAILED: - printk(KERN_WARNING "cciss: cmd %p reports " - "abort failed\n", cmd); - status = 0; - break; - case CMD_UNSOLICITED_ABORT: - printk(KERN_WARNING "cciss%d: unsolicited " - "abort %p\n", h->ctlr, cmd); - if (cmd->retry_count < MAX_CMD_RETRIES) { - retry_cmd = 1; - printk(KERN_WARNING - "cciss%d: retrying %p\n", h->ctlr, cmd); - cmd->retry_count++; - } else - printk(KERN_WARNING - "cciss%d: %p retried too " - "many times\n", h->ctlr, cmd); - status = 0; - break; - case CMD_TIMEOUT: - printk(KERN_WARNING "cciss: cmd %p timedout\n", cmd); - status = 0; - break; - default: - printk(KERN_WARNING "cciss: cmd %p returned " - "unknown status %x\n", cmd, - cmd->err_info->CommandStatus); - status = 0; - } + break; + case CMD_INVALID: + printk(KERN_WARNING "cciss: cmd %p is " + "reported invalid\n", cmd); + rq->errors = 1; + break; + case CMD_PROTOCOL_ERR: + printk(KERN_WARNING "cciss: cmd %p has " + "protocol error \n", cmd); + rq->errors = 1; + break; + case CMD_HARDWARE_ERR: + printk(KERN_WARNING "cciss: cmd %p had " + " hardware error\n", cmd); + rq->errors = 1; + break; + case CMD_CONNECTION_LOST: + printk(KERN_WARNING "cciss: cmd %p had " + "connection lost\n", cmd); + rq->errors = 1; + break; + case CMD_ABORTED: + printk(KERN_WARNING "cciss: cmd %p was " + "aborted\n", cmd); + rq->errors = 1; + break; + case CMD_ABORT_FAILED: + printk(KERN_WARNING "cciss: cmd %p reports " + "abort failed\n", cmd); + rq->errors = 1; + break; + case CMD_UNSOLICITED_ABORT: + printk(KERN_WARNING "cciss%d: unsolicited " + "abort %p\n", h->ctlr, cmd); + if (cmd->retry_count < MAX_CMD_RETRIES) { + retry_cmd = 1; + printk(KERN_WARNING + "cciss%d: retrying %p\n", h->ctlr, cmd); + cmd->retry_count++; + } else + printk(KERN_WARNING + "cciss%d: %p retried too " + "many times\n", h->ctlr, cmd); + rq->errors = 1; + break; + case CMD_TIMEOUT: + printk(KERN_WARNING "cciss: cmd %p timedout\n", cmd); + rq->errors = 1; + break; + default: + printk(KERN_WARNING "cciss: cmd %p returned " + "unknown status %x\n", cmd, + cmd->err_info->CommandStatus); + rq->errors = 1; } + +after_error_processing: + /* We need to return this command */ if (retry_cmd) { resend_cciss_cmd(h, cmd); return; } - + cmd->rq->data_len = 0; cmd->rq->completion_data = cmd; - cmd->rq->errors = status; blk_add_trace_rq(cmd->rq->q, cmd->rq, BLK_TA_COMPLETE); blk_complete_request(cmd->rq); } @@ -2538,32 +2595,40 @@ static void do_cciss_request(request_queue_t *q) #endif /* CCISS_DEBUG */ c->Header.SGList = c->Header.SGTotal = seg; - 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; + if (likely(blk_fs_request(creq))) { + 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; + } + } else if (blk_pc_request(creq)) { + c->Request.CDBLen = creq->cmd_len; + memcpy(c->Request.CDB, creq->cmd, BLK_MAX_CDB); } 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; + printk(KERN_WARNING "cciss%d: bad request type %d\n", h->ctlr, creq->cmd_type); + BUG(); } spin_lock_irq(q->queue_lock); @@ -3422,6 +3487,25 @@ static void cciss_remove_one(struct pci_dev *pdev) "already be removed \n"); return; } + + remove_proc_entry(hba[i]->devname, proc_cciss); + unregister_blkdev(hba[i]->major, hba[i]->devname); + + /* remove it from the disk list */ + for (j = 0; j < CISS_MAX_LUN; j++) { + struct gendisk *disk = hba[i]->gendisk[j]; + if (disk) { + request_queue_t *q = disk->queue; + + if (disk->flags & GENHD_FL_UP) + del_gendisk(disk); + if (q) + blk_cleanup_queue(q); + } + } + + cciss_unregister_scsi(i); /* unhook from SCSI subsystem */ + /* Turn board interrupts off and send the flush cache command */ /* sendcmd will turn off interrupt, and send the flush... * To write all data in the battery backed cache to disks */ @@ -3443,22 +3527,6 @@ static void cciss_remove_one(struct pci_dev *pdev) #endif /* CONFIG_PCI_MSI */ iounmap(hba[i]->vaddr); - cciss_unregister_scsi(i); /* unhook from SCSI subsystem */ - unregister_blkdev(hba[i]->major, hba[i]->devname); - remove_proc_entry(hba[i]->devname, proc_cciss); - - /* remove it from the disk list */ - for (j = 0; j < CISS_MAX_LUN; j++) { - struct gendisk *disk = hba[i]->gendisk[j]; - if (disk) { - request_queue_t *q = disk->queue; - - if (disk->flags & GENHD_FL_UP) - del_gendisk(disk); - if (q) - blk_cleanup_queue(q); - } - } pci_free_consistent(hba[i]->pdev, hba[i]->nr_cmds * sizeof(CommandList_struct), hba[i]->cmd_pool, hba[i]->cmd_pool_dhandle); diff --git a/drivers/block/cciss_scsi.c b/drivers/block/cciss_scsi.c index bb15051ffbe..90961a8ea89 100644 --- a/drivers/block/cciss_scsi.c +++ b/drivers/block/cciss_scsi.c @@ -35,7 +35,6 @@ #include <asm/atomic.h> -#include <scsi/scsi.h> #include <scsi/scsi_cmnd.h> #include <scsi/scsi_device.h> #include <scsi/scsi_host.h> diff --git a/drivers/block/floppy.c b/drivers/block/floppy.c index 5231ed7e723..3587cb43437 100644 --- a/drivers/block/floppy.c +++ b/drivers/block/floppy.c @@ -4334,7 +4334,10 @@ static int __init floppy_init(void) if (err) goto out_flush_work; - device_create_file(&floppy_device[drive].dev,&dev_attr_cmos); + err = device_create_file(&floppy_device[drive].dev,&dev_attr_cmos); + if (err) + goto out_unreg_platform_dev; + /* to be cleaned up... */ disks[drive]->private_data = (void *)(long)drive; disks[drive]->queue = floppy_queue; @@ -4345,6 +4348,8 @@ static int __init floppy_init(void) return 0; +out_unreg_platform_dev: + platform_device_unregister(&floppy_device[drive]); out_flush_work: flush_scheduled_work(); if (usage_count) diff --git a/drivers/block/loop.c b/drivers/block/loop.c index 6b5b6420740..18cdd8c7762 100644 --- a/drivers/block/loop.c +++ b/drivers/block/loop.c @@ -77,9 +77,8 @@ #include <asm/uaccess.h> -static int max_loop = 8; -static struct loop_device *loop_dev; -static struct gendisk **disks; +static LIST_HEAD(loop_devices); +static DEFINE_MUTEX(loop_devices_mutex); /* * Transfer functions @@ -183,7 +182,7 @@ figure_loop_size(struct loop_device *lo) if (unlikely((loff_t)x != size)) return -EFBIG; - set_capacity(disks[lo->lo_number], x); + set_capacity(lo->lo_disk, x); return 0; } @@ -244,17 +243,13 @@ static int do_lo_send_aops(struct loop_device *lo, struct bio_vec *bvec, transfer_result = lo_do_transfer(lo, WRITE, page, offset, bvec->bv_page, bv_offs, size, IV); if (unlikely(transfer_result)) { - char *kaddr; - /* * The transfer failed, but we still write the data to * keep prepare/commit calls balanced. */ printk(KERN_ERR "loop: transfer error block %llu\n", (unsigned long long)index); - kaddr = kmap_atomic(page, KM_USER0); - memset(kaddr + offset, 0, size); - kunmap_atomic(kaddr, KM_USER0); + zero_user_page(page, offset, size, KM_USER0); } flush_dcache_page(page); ret = aops->commit_write(file, page, offset, @@ -812,7 +807,7 @@ static int loop_set_fd(struct loop_device *lo, struct file *lo_file, lo->lo_queue->queuedata = lo; lo->lo_queue->unplug_fn = loop_unplug; - set_capacity(disks[lo->lo_number], size); + set_capacity(lo->lo_disk, size); bd_set_size(bdev, size << 9); set_blocksize(bdev, lo_blocksize); @@ -832,8 +827,8 @@ out_clr: lo->lo_device = NULL; lo->lo_backing_file = NULL; lo->lo_flags = 0; - set_capacity(disks[lo->lo_number], 0); - invalidate_bdev(bdev, 0); + set_capacity(lo->lo_disk, 0); + invalidate_bdev(bdev); bd_set_size(bdev, 0); mapping_set_gfp_mask(mapping, lo->old_gfp_mask); lo->lo_state = Lo_unbound; @@ -917,8 +912,8 @@ static int loop_clr_fd(struct loop_device *lo, struct block_device *bdev) 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); - invalidate_bdev(bdev, 0); - set_capacity(disks[lo->lo_number], 0); + invalidate_bdev(bdev); + set_capacity(lo->lo_disk, 0); bd_set_size(bdev, 0); mapping_set_gfp_mask(filp->f_mapping, gfp); lo->lo_state = Lo_unbound; @@ -1322,6 +1317,18 @@ static long lo_compat_ioctl(struct file *file, unsigned int cmd, unsigned long a } #endif +static struct loop_device *loop_find_dev(int number) +{ + struct loop_device *lo; + + list_for_each_entry(lo, &loop_devices, lo_list) { + if (lo->lo_number == number) + return lo; + } + return NULL; +} + +static struct loop_device *loop_init_one(int i); static int lo_open(struct inode *inode, struct file *file) { struct loop_device *lo = inode->i_bdev->bd_disk->private_data; @@ -1330,6 +1337,11 @@ static int lo_open(struct inode *inode, struct file *file) lo->lo_refcnt++; mutex_unlock(&lo->lo_ctl_mutex); + mutex_lock(&loop_devices_mutex); + if (!loop_find_dev(lo->lo_number + 1)) + loop_init_one(lo->lo_number + 1); + mutex_unlock(&loop_devices_mutex); + return 0; } @@ -1357,8 +1369,9 @@ static struct block_device_operations lo_fops = { /* * And now the modules code and kernel interface. */ +static int max_loop; module_param(max_loop, int, 0); -MODULE_PARM_DESC(max_loop, "Maximum number of loop devices (1-256)"); +MODULE_PARM_DESC(max_loop, "obsolete, loop device is created on-demand"); MODULE_LICENSE("GPL"); MODULE_ALIAS_BLOCKDEV_MAJOR(LOOP_MAJOR); @@ -1383,7 +1396,7 @@ int loop_unregister_transfer(int number) xfer_funcs[n] = NULL; - for (lo = &loop_dev[0]; lo < &loop_dev[max_loop]; lo++) { + list_for_each_entry(lo, &loop_devices, lo_list) { mutex_lock(&lo->lo_ctl_mutex); if (lo->lo_encryption == xfer) @@ -1398,91 +1411,110 @@ int loop_unregister_transfer(int number) EXPORT_SYMBOL(loop_register_transfer); EXPORT_SYMBOL(loop_unregister_transfer); -static int __init loop_init(void) +static struct loop_device *loop_init_one(int i) { - int i; + struct loop_device *lo; + struct gendisk *disk; - if (max_loop < 1 || max_loop > 256) { - printk(KERN_WARNING "loop: invalid max_loop (must be between" - " 1 and 256), using default (8)\n"); - max_loop = 8; - } + lo = kzalloc(sizeof(*lo), GFP_KERNEL); + if (!lo) + goto out; + + lo->lo_queue = blk_alloc_queue(GFP_KERNEL); + if (!lo->lo_queue) + goto out_free_dev; + + disk = lo->lo_disk = alloc_disk(1); + if (!disk) + goto out_free_queue; + + mutex_init(&lo->lo_ctl_mutex); + 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; + disk->fops = &lo_fops; + disk->private_data = lo; + disk->queue = lo->lo_queue; + sprintf(disk->disk_name, "loop%d", i); + add_disk(disk); + list_add_tail(&lo->lo_list, &loop_devices); + return lo; + +out_free_queue: + blk_cleanup_queue(lo->lo_queue); +out_free_dev: + kfree(lo); +out: + return ERR_PTR(-ENOMEM); +} + +static void loop_del_one(struct loop_device *lo) +{ + del_gendisk(lo->lo_disk); + blk_cleanup_queue(lo->lo_queue); + put_disk(lo->lo_disk); + list_del(&lo->lo_list); + kfree(lo); +} + +static struct kobject *loop_probe(dev_t dev, int *part, void *data) +{ + unsigned int number = dev & MINORMASK; + struct loop_device *lo; + + mutex_lock(&loop_devices_mutex); + lo = loop_find_dev(number); + if (lo == NULL) + lo = loop_init_one(number); + mutex_unlock(&loop_devices_mutex); + + *part = 0; + if (IS_ERR(lo)) + return (void *)lo; + else + return &lo->lo_disk->kobj; +} + +static int __init loop_init(void) +{ + struct loop_device *lo; if (register_blkdev(LOOP_MAJOR, "loop")) return -EIO; + blk_register_region(MKDEV(LOOP_MAJOR, 0), 1UL << MINORBITS, + THIS_MODULE, loop_probe, NULL, NULL); - loop_dev = kmalloc(max_loop * sizeof(struct loop_device), GFP_KERNEL); - if (!loop_dev) - goto out_mem1; - memset(loop_dev, 0, max_loop * sizeof(struct loop_device)); + lo = loop_init_one(0); + if (IS_ERR(lo)) + goto out; - disks = kmalloc(max_loop * sizeof(struct gendisk *), GFP_KERNEL); - if (!disks) - goto out_mem2; + if (max_loop) { + printk(KERN_INFO "loop: the max_loop option is obsolete " + "and will be removed in March 2008\n"); - for (i = 0; i < max_loop; i++) { - disks[i] = alloc_disk(1); - if (!disks[i]) - goto out_mem3; } - - for (i = 0; i < max_loop; i++) { - struct loop_device *lo = &loop_dev[i]; - struct gendisk *disk = disks[i]; - - memset(lo, 0, sizeof(*lo)); - lo->lo_queue = blk_alloc_queue(GFP_KERNEL); - if (!lo->lo_queue) - goto out_mem4; - mutex_init(&lo->lo_ctl_mutex); - 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; - disk->fops = &lo_fops; - sprintf(disk->disk_name, "loop%d", i); - disk->private_data = lo; - disk->queue = lo->lo_queue; - } - - /* We cannot fail after we call this, so another loop!*/ - for (i = 0; i < max_loop; i++) - add_disk(disks[i]); - printk(KERN_INFO "loop: loaded (max %d devices)\n", max_loop); + printk(KERN_INFO "loop: module loaded\n"); return 0; -out_mem4: - while (i--) - blk_cleanup_queue(loop_dev[i].lo_queue); - i = max_loop; -out_mem3: - while (i--) - put_disk(disks[i]); - kfree(disks); -out_mem2: - kfree(loop_dev); -out_mem1: +out: unregister_blkdev(LOOP_MAJOR, "loop"); printk(KERN_ERR "loop: ran out of memory\n"); return -ENOMEM; } -static void loop_exit(void) +static void __exit loop_exit(void) { - int i; + struct loop_device *lo, *next; - for (i = 0; i < max_loop; i++) { - del_gendisk(disks[i]); - blk_cleanup_queue(loop_dev[i].lo_queue); - put_disk(disks[i]); - } + list_for_each_entry_safe(lo, next, &loop_devices, lo_list) + loop_del_one(lo); + + blk_unregister_region(MKDEV(LOOP_MAJOR, 0), 1UL << MINORBITS); if (unregister_blkdev(LOOP_MAJOR, "loop")) printk(KERN_WARNING "loop: cannot unregister blkdev\n"); - - kfree(disks); - kfree(loop_dev); } module_init(loop_init); diff --git a/drivers/block/nbd.c b/drivers/block/nbd.c index 090796bef78..069ae39a9cd 100644 --- a/drivers/block/nbd.c +++ b/drivers/block/nbd.c @@ -366,20 +366,25 @@ static struct disk_attribute pid_attr = { .show = pid_show, }; -static void nbd_do_it(struct nbd_device *lo) +static int nbd_do_it(struct nbd_device *lo) { struct request *req; + int ret; BUG_ON(lo->magic != LO_MAGIC); lo->pid = current->pid; - sysfs_create_file(&lo->disk->kobj, &pid_attr.attr); + ret = sysfs_create_file(&lo->disk->kobj, &pid_attr.attr); + if (ret) { + printk(KERN_ERR "nbd: sysfs_create_file failed!"); + return ret; + } while ((req = nbd_read_stat(lo)) != NULL) nbd_end_request(req); sysfs_remove_file(&lo->disk->kobj, &pid_attr.attr); - return; + return 0; } static void nbd_clear_que(struct nbd_device *lo) @@ -569,7 +574,9 @@ static int nbd_ioctl(struct inode *inode, struct file *file, case NBD_DO_IT: if (!lo->file) return -EINVAL; - nbd_do_it(lo); + error = nbd_do_it(lo); + if (error) + return error; /* on return tidy up in case we have a signal */ /* Forcibly shutdown the socket causing all listeners * to error diff --git a/drivers/block/paride/pcd.c b/drivers/block/paride/pcd.c index c852eed91e4..1eeb8f2cde7 100644 --- a/drivers/block/paride/pcd.c +++ b/drivers/block/paride/pcd.c @@ -140,7 +140,7 @@ enum {D_PRT, D_PRO, D_UNI, D_MOD, D_SLV, D_DLY}; #include <linux/blkdev.h> #include <asm/uaccess.h> -static spinlock_t pcd_lock; +static DEFINE_SPINLOCK(pcd_lock); module_param(verbose, bool, 0644); module_param(major, int, 0); diff --git a/drivers/block/paride/pd.c b/drivers/block/paride/pd.c index 99e2c8ce1cc..31e01488eb5 100644 --- a/drivers/block/paride/pd.c +++ b/drivers/block/paride/pd.c @@ -663,11 +663,11 @@ static enum action pd_identify(struct pd_unit *disk) return Fail; pi_read_block(disk->pi, pd_scratch, 512); disk->can_lba = pd_scratch[99] & 2; - disk->sectors = le16_to_cpu(*(u16 *) (pd_scratch + 12)); - disk->heads = le16_to_cpu(*(u16 *) (pd_scratch + 6)); - disk->cylinders = le16_to_cpu(*(u16 *) (pd_scratch + 2)); + disk->sectors = le16_to_cpu(*(__le16 *) (pd_scratch + 12)); + disk->heads = le16_to_cpu(*(__le16 *) (pd_scratch + 6)); + disk->cylinders = le16_to_cpu(*(__le16 *) (pd_scratch + 2)); if (disk->can_lba) - disk->capacity = le32_to_cpu(*(u32 *) (pd_scratch + 120)); + disk->capacity = le32_to_cpu(*(__le32 *) (pd_scratch + 120)); else disk->capacity = disk->sectors * disk->heads * disk->cylinders; diff --git a/drivers/block/paride/pf.c b/drivers/block/paride/pf.c index 7cdaa195126..5826508f673 100644 --- a/drivers/block/paride/pf.c +++ b/drivers/block/paride/pf.c @@ -154,7 +154,7 @@ enum {D_PRT, D_PRO, D_UNI, D_MOD, D_SLV, D_LUN, D_DLY}; #include <linux/blkpg.h> #include <asm/uaccess.h> -static spinlock_t pf_spin_lock; +static DEFINE_SPINLOCK(pf_spin_lock); module_param(verbose, bool, 0644); module_param(major, int, 0); diff --git a/drivers/block/pktcdvd.c b/drivers/block/pktcdvd.c index a4fb7038318..f1b9dd7d47d 100644 --- a/drivers/block/pktcdvd.c +++ b/drivers/block/pktcdvd.c @@ -777,7 +777,8 @@ static int pkt_generic_packet(struct pktcdvd_device *pd, struct packet_command * rq->cmd_flags |= REQ_QUIET; blk_execute_rq(rq->q, pd->bdev->bd_disk, rq, 0); - ret = rq->errors; + if (rq->errors) + ret = -EIO; out: blk_put_request(rq); return ret; diff --git a/drivers/block/rd.c b/drivers/block/rd.c index 485aa87e9bc..a1512da3241 100644 --- a/drivers/block/rd.c +++ b/drivers/block/rd.c @@ -151,7 +151,7 @@ static int ramdisk_commit_write(struct file *file, struct page *page, } /* - * ->writepage to the the blockdev's mapping has to redirty the page so that the + * ->writepage to the blockdev's mapping has to redirty the page so that the * VM doesn't go and steal it. We return AOP_WRITEPAGE_ACTIVATE so that the VM * won't try to (pointlessly) write the page again for a while. * @@ -403,7 +403,7 @@ static void __exit rd_cleanup(void) struct block_device *bdev = rd_bdev[i]; rd_bdev[i] = NULL; if (bdev) { - invalidate_bdev(bdev, 1); + invalidate_bdev(bdev); blkdev_put(bdev); } del_gendisk(rd_disks[i]); diff --git a/drivers/block/ub.c b/drivers/block/ub.c index 2098eff91e1..746a118a9b5 100644 --- a/drivers/block/ub.c +++ b/drivers/block/ub.c @@ -2132,10 +2132,13 @@ static int ub_get_pipes(struct ub_dev *sc, struct usb_device *dev, if ((ep->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) == USB_ENDPOINT_XFER_BULK) { /* BULK in or out? */ - if (ep->bEndpointAddress & USB_DIR_IN) - ep_in = ep; - else - ep_out = ep; + if (ep->bEndpointAddress & USB_DIR_IN) { + if (ep_in == NULL) + ep_in = ep; + } else { + if (ep_out == NULL) + ep_out = ep; + } } } diff --git a/drivers/block/umem.c b/drivers/block/umem.c index 5872036e8ae..6f5d6203d72 100644 --- a/drivers/block/umem.c +++ b/drivers/block/umem.c @@ -44,7 +44,6 @@ #include <linux/module.h> #include <linux/init.h> #include <linux/interrupt.h> -#include <linux/smp_lock.h> #include <linux/timer.h> #include <linux/pci.h> #include <linux/slab.h> |