aboutsummaryrefslogtreecommitdiff
path: root/drivers/block
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/block')
-rw-r--r--drivers/block/DAC960.c3
-rw-r--r--drivers/block/Kconfig27
-rw-r--r--drivers/block/Makefile2
-rw-r--r--drivers/block/aoe/aoe.h9
-rw-r--r--drivers/block/aoe/aoecmd.c14
-rw-r--r--drivers/block/aoe/aoenet.c2
-rw-r--r--drivers/block/cciss.c164
-rw-r--r--drivers/block/cciss_scsi.c14
-rw-r--r--drivers/block/cciss_scsi.h14
-rw-r--r--drivers/block/cpqarray.c7
-rw-r--r--drivers/block/cryptoloop.c17
-rw-r--r--drivers/block/floppy.c167
-rw-r--r--drivers/block/lguest_blk.c421
-rw-r--r--drivers/block/loop.c77
-rw-r--r--drivers/block/nbd.c118
-rw-r--r--drivers/block/paride/pf.c25
-rw-r--r--drivers/block/paride/pt.c2
-rw-r--r--drivers/block/pktcdvd.c16
-rw-r--r--drivers/block/ps3disk.c21
-rw-r--r--drivers/block/rd.c42
-rw-r--r--drivers/block/sunvdc.c2
-rw-r--r--drivers/block/sx8.c2
-rw-r--r--drivers/block/ub.c18
-rw-r--r--drivers/block/viodasd.c2
-rw-r--r--drivers/block/virtio_blk.c310
-rw-r--r--drivers/block/xsysace.c4
26 files changed, 731 insertions, 769 deletions
diff --git a/drivers/block/DAC960.c b/drivers/block/DAC960.c
index 84d6aa500e2..9030c373ce6 100644
--- a/drivers/block/DAC960.c
+++ b/drivers/block/DAC960.c
@@ -44,6 +44,7 @@
#include <linux/init.h>
#include <linux/jiffies.h>
#include <linux/random.h>
+#include <linux/scatterlist.h>
#include <asm/io.h>
#include <asm/uaccess.h>
#include "DAC960.h"
@@ -345,6 +346,7 @@ static bool DAC960_CreateAuxiliaryStructures(DAC960_Controller_T *Controller)
Command->V1.ScatterGatherList =
(DAC960_V1_ScatterGatherSegment_T *)ScatterGatherCPU;
Command->V1.ScatterGatherListDMA = ScatterGatherDMA;
+ sg_init_table(Command->cmd_sglist, DAC960_V1_ScatterGatherLimit);
} else {
Command->cmd_sglist = Command->V2.ScatterList;
Command->V2.ScatterGatherList =
@@ -353,6 +355,7 @@ static bool DAC960_CreateAuxiliaryStructures(DAC960_Controller_T *Controller)
Command->V2.RequestSense =
(DAC960_SCSI_RequestSense_T *)RequestSenseCPU;
Command->V2.RequestSenseDMA = RequestSenseDMA;
+ sg_init_table(Command->cmd_sglist, DAC960_V2_ScatterGatherLimit);
}
}
return true;
diff --git a/drivers/block/Kconfig b/drivers/block/Kconfig
index ca4d7f0d09b..4d0119ea9e3 100644
--- a/drivers/block/Kconfig
+++ b/drivers/block/Kconfig
@@ -204,23 +204,6 @@ config BLK_DEV_COW_COMMON
bool
default BLK_DEV_UBD
-config MMAPPER
- tristate "Example IO memory driver (BROKEN)"
- depends on UML && BROKEN
- ---help---
- The User-Mode Linux port can provide support for IO Memory
- emulation with this option. This allows a host file to be
- specified as an I/O region on the kernel command line. That file
- will be mapped into UML's kernel address space where a driver can
- locate it and do whatever it wants with the memory, including
- providing an interface to it for UML processes to use.
-
- For more information, see
- <http://user-mode-linux.sourceforge.net/iomem.html>.
-
- If you'd like to be able to provide a simulated IO port space for
- User-Mode Linux processes, say Y. If unsure, say N.
-
config BLK_DEV_LOOP
tristate "Loopback device support"
---help---
@@ -351,7 +334,7 @@ config BLK_DEV_RAM_COUNT
default "16"
depends on BLK_DEV_RAM
help
- The default value is 16 RAM disks. Change this if you know what
+ The default value is 16 RAM disks. Change this if you know what you
are doing. If you boot from a filesystem that needs to be extracted
in memory, you will need at least one RAM disk (e.g. root on cramfs).
@@ -361,7 +344,7 @@ config BLK_DEV_RAM_SIZE
default "4096"
help
The default value is 4096 kilobytes. Only change this if you know
- what are you doing.
+ what you are doing.
config BLK_DEV_RAM_BLOCKSIZE
int "Default RAM disk block size (bytes)"
@@ -442,4 +425,10 @@ config XEN_BLKDEV_FRONTEND
block device driver. It communicates with a back-end driver
in another domain which drives the actual block device.
+config VIRTIO_BLK
+ tristate "Virtio block driver (EXPERIMENTAL)"
+ depends on EXPERIMENTAL && VIRTIO
+ ---help---
+ This is the virtual block driver for lguest. Say Y or M.
+
endif # BLK_DEV
diff --git a/drivers/block/Makefile b/drivers/block/Makefile
index 014e72121b5..7691505a2e1 100644
--- a/drivers/block/Makefile
+++ b/drivers/block/Makefile
@@ -25,10 +25,10 @@ obj-$(CONFIG_SUNVDC) += sunvdc.o
obj-$(CONFIG_BLK_DEV_UMEM) += umem.o
obj-$(CONFIG_BLK_DEV_NBD) += nbd.o
obj-$(CONFIG_BLK_DEV_CRYPTOLOOP) += cryptoloop.o
+obj-$(CONFIG_VIRTIO_BLK) += virtio_blk.o
obj-$(CONFIG_VIODASD) += viodasd.o
obj-$(CONFIG_BLK_DEV_SX8) += sx8.o
obj-$(CONFIG_BLK_DEV_UB) += ub.o
obj-$(CONFIG_XEN_BLKDEV_FRONTEND) += xen-blkfront.o
-obj-$(CONFIG_LGUEST_BLOCK) += lguest_blk.o
diff --git a/drivers/block/aoe/aoe.h b/drivers/block/aoe/aoe.h
index ba07f762c4c..07f02f855ab 100644
--- a/drivers/block/aoe/aoe.h
+++ b/drivers/block/aoe/aoe.h
@@ -48,15 +48,6 @@ 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 99672017ca5..4d59d505773 100644
--- a/drivers/block/aoe/aoecmd.c
+++ b/drivers/block/aoe/aoecmd.c
@@ -120,7 +120,7 @@ aoecmd_ata_rw(struct aoedev *d, struct frame *f)
/* initialize the headers & frame */
skb = f->skb;
- h = aoe_hdr(skb);
+ h = (struct aoe_hdr *) skb_mac_header(skb);
ah = (struct aoe_atahdr *) (h+1);
skb_put(skb, sizeof *h + sizeof *ah);
memset(h, 0, skb->len);
@@ -209,7 +209,7 @@ aoecmd_cfg_pkts(ushort aoemajor, unsigned char aoeminor, struct sk_buff **tail)
skb->dev = ifp;
if (sl_tail == NULL)
sl_tail = skb;
- h = aoe_hdr(skb);
+ h = (struct aoe_hdr *) skb_mac_header(skb);
memset(h, 0, sizeof *h + sizeof *ch);
memset(h->dst, 0xff, sizeof h->dst);
@@ -304,7 +304,7 @@ rexmit(struct aoedev *d, struct frame *f)
aoechr_error(buf);
skb = f->skb;
- h = aoe_hdr(skb);
+ h = (struct aoe_hdr *) skb_mac_header(skb);
ah = (struct aoe_atahdr *) (h+1);
f->tag = n;
h->tag = cpu_to_be32(n);
@@ -533,7 +533,7 @@ aoecmd_ata_rsp(struct sk_buff *skb)
char ebuf[128];
u16 aoemajor;
- hin = aoe_hdr(skb);
+ hin = (struct aoe_hdr *) skb_mac_header(skb);
aoemajor = be16_to_cpu(get_unaligned(&hin->major));
d = aoedev_by_aoeaddr(aoemajor, hin->minor);
if (d == NULL) {
@@ -565,7 +565,7 @@ aoecmd_ata_rsp(struct sk_buff *skb)
calc_rttavg(d, tsince(f->tag));
ahin = (struct aoe_atahdr *) (hin+1);
- hout = aoe_hdr(f->skb);
+ hout = (struct aoe_hdr *) skb_mac_header(f->skb);
ahout = (struct aoe_atahdr *) (hout+1);
buf = f->buf;
@@ -699,7 +699,7 @@ aoecmd_ata_id(struct aoedev *d)
/* initialize the headers & frame */
skb = f->skb;
- h = aoe_hdr(skb);
+ h = (struct aoe_hdr *) skb_mac_header(skb);
ah = (struct aoe_atahdr *) (h+1);
skb_put(skb, sizeof *h + sizeof *ah);
memset(h, 0, skb->len);
@@ -730,7 +730,7 @@ aoecmd_cfg_rsp(struct sk_buff *skb)
enum { MAXFRAMES = 16 };
u16 n;
- h = aoe_hdr(skb);
+ h = (struct aoe_hdr *) skb_mac_header(skb);
ch = (struct aoe_cfghdr *) (h+1);
/*
diff --git a/drivers/block/aoe/aoenet.c b/drivers/block/aoe/aoenet.c
index 4dc0fb7da94..4e6deb7f5c2 100644
--- a/drivers/block/aoe/aoenet.c
+++ b/drivers/block/aoe/aoenet.c
@@ -127,7 +127,7 @@ aoenet_rcv(struct sk_buff *skb, struct net_device *ifp, struct packet_type *pt,
goto exit;
skb_push(skb, ETH_HLEN); /* (1) */
- h = aoe_hdr(skb);
+ h = (struct aoe_hdr *) skb_mac_header(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 55c3237fb1b..7d704968765 100644
--- a/drivers/block/cciss.c
+++ b/drivers/block/cciss.c
@@ -1,20 +1,20 @@
/*
- * Disk Array driver for HP SA 5xxx and 6xxx Controllers
- * Copyright 2000, 2006 Hewlett-Packard Development Company, L.P.
+ * Disk Array driver for HP Smart Array controllers.
+ * (C) Copyright 2000, 2007 Hewlett-Packard Development Company, L.P.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
+ * the Free Software Foundation; version 2 of the License.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE, GOOD TITLE or
- * NON INFRINGEMENT. See the GNU General Public License for more details.
+ * MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
- * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+ * 02111-1307, USA.
*
* Questions/Comments/Bugfixes to iss_storagedev@hp.com
*
@@ -1191,7 +1191,6 @@ static inline void complete_buffers(struct bio *bio, int status)
{
while (bio) {
struct bio *xbh = bio->bi_next;
- int nr_sectors = bio_sectors(bio);
bio->bi_next = NULL;
bio_endio(bio, status ? 0 : -EIO);
@@ -1583,38 +1582,36 @@ static int deregister_disk(struct gendisk *disk, drive_info_struct *drv,
* allows us to delete disk zero but keep the controller registered.
*/
if (h->gendisk[0] != disk) {
- if (disk) {
- struct request_queue *q = disk->queue;
- if (disk->flags & GENHD_FL_UP)
- del_gendisk(disk);
- if (q) {
- blk_cleanup_queue(q);
- /* Set drv->queue to NULL so that we do not try
- * to call blk_start_queue on this queue in the
- * interrupt handler
- */
- drv->queue = NULL;
- }
- /* If clear_all is set then we are deleting the logical
- * drive, not just refreshing its info. For drives
- * other than disk 0 we will call put_disk. We do not
- * do this for disk 0 as we need it to be able to
- * configure the controller.
+ struct request_queue *q = disk->queue;
+ if (disk->flags & GENHD_FL_UP)
+ del_gendisk(disk);
+ if (q) {
+ blk_cleanup_queue(q);
+ /* Set drv->queue to NULL so that we do not try
+ * to call blk_start_queue on this queue in the
+ * interrupt handler
+ */
+ drv->queue = NULL;
+ }
+ /* If clear_all is set then we are deleting the logical
+ * drive, not just refreshing its info. For drives
+ * other than disk 0 we will call put_disk. We do not
+ * do this for disk 0 as we need it to be able to
+ * configure the controller.
+ */
+ if (clear_all){
+ /* This isn't pretty, but we need to find the
+ * disk in our array and NULL our the pointer.
+ * This is so that we will call alloc_disk if
+ * this index is used again later.
*/
- if (clear_all){
- /* This isn't pretty, but we need to find the
- * disk in our array and NULL our the pointer.
- * This is so that we will call alloc_disk if
- * this index is used again later.
- */
- for (i=0; i < CISS_MAX_LUN; i++){
- if(h->gendisk[i] == disk){
- h->gendisk[i] = NULL;
- break;
- }
+ for (i=0; i < CISS_MAX_LUN; i++){
+ if(h->gendisk[i] == disk){
+ h->gendisk[i] = NULL;
+ break;
}
- put_disk(disk);
}
+ put_disk(disk);
}
} else {
set_capacity(disk, 0);
@@ -2366,30 +2363,55 @@ static inline void resend_cciss_cmd(ctlr_info_t *h, CommandList_struct *c)
start_io(h);
}
+static inline unsigned int make_status_bytes(unsigned int scsi_status_byte,
+ unsigned int msg_byte, unsigned int host_byte,
+ unsigned int driver_byte)
+{
+ /* inverse of macros in scsi.h */
+ return (scsi_status_byte & 0xff) |
+ ((msg_byte & 0xff) << 8) |
+ ((host_byte & 0xff) << 16) |
+ ((driver_byte & 0xff) << 24);
+}
+
static inline int evaluate_target_status(CommandList_struct *cmd)
{
unsigned char sense_key;
- int error_count = 1;
+ unsigned char status_byte, msg_byte, host_byte, driver_byte;
+ int error_value;
+
+ /* If we get in here, it means we got "target status", that is, scsi status */
+ status_byte = cmd->err_info->ScsiStatus;
+ driver_byte = DRIVER_OK;
+ msg_byte = cmd->err_info->CommandStatus; /* correct? seems too device specific */
+
+ if (blk_pc_request(cmd->rq))
+ host_byte = DID_PASSTHROUGH;
+ else
+ host_byte = DID_OK;
+
+ error_value = make_status_bytes(status_byte, msg_byte,
+ host_byte, driver_byte);
- if (cmd->err_info->ScsiStatus != 0x02) { /* not check condition? */
+ if (cmd->err_info->ScsiStatus != SAM_STAT_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;
+ return error_value;
}
/* 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 (((sense_key == 0x0) || (sense_key == 0x1)) && !blk_pc_request(cmd->rq))
+ error_value = 0;
if (!blk_pc_request(cmd->rq)) { /* Not SG_IO or similar? */
- if (error_count != 0)
+ if (error_value != 0)
printk(KERN_WARNING "cciss: cmd %p has CHECK CONDITION"
" sense key = 0x%x\n", cmd, sense_key);
- return error_count;
+ return error_value;
}
/* SG_IO or similar, copy sense data back */
@@ -2401,7 +2423,7 @@ static inline int evaluate_target_status(CommandList_struct *cmd)
} else
cmd->rq->sense_len = 0;
- return error_count;
+ return error_value;
}
/* checks the status of the job and calls complete buffers to mark all
@@ -2417,7 +2439,7 @@ static inline void complete_command(ctlr_info_t *h, CommandList_struct *cmd,
rq->errors = 0;
if (timeout)
- rq->errors = 1;
+ rq->errors = make_status_bytes(0, 0, 0, DRIVER_TIMEOUT);
if (cmd->err_info->CommandStatus == 0) /* no error has occurred */
goto after_error_processing;
@@ -2443,32 +2465,44 @@ static inline void complete_command(ctlr_info_t *h, CommandList_struct *cmd,
case CMD_INVALID:
printk(KERN_WARNING "cciss: cmd %p is "
"reported invalid\n", cmd);
- rq->errors = 1;
+ rq->errors = make_status_bytes(SAM_STAT_GOOD,
+ cmd->err_info->CommandStatus, DRIVER_OK,
+ blk_pc_request(cmd->rq) ? DID_PASSTHROUGH : DID_ERROR);
break;
case CMD_PROTOCOL_ERR:
printk(KERN_WARNING "cciss: cmd %p has "
"protocol error \n", cmd);
- rq->errors = 1;
+ rq->errors = make_status_bytes(SAM_STAT_GOOD,
+ cmd->err_info->CommandStatus, DRIVER_OK,
+ blk_pc_request(cmd->rq) ? DID_PASSTHROUGH : DID_ERROR);
break;
case CMD_HARDWARE_ERR:
printk(KERN_WARNING "cciss: cmd %p had "
" hardware error\n", cmd);
- rq->errors = 1;
+ rq->errors = make_status_bytes(SAM_STAT_GOOD,
+ cmd->err_info->CommandStatus, DRIVER_OK,
+ blk_pc_request(cmd->rq) ? DID_PASSTHROUGH : DID_ERROR);
break;
case CMD_CONNECTION_LOST:
printk(KERN_WARNING "cciss: cmd %p had "
"connection lost\n", cmd);
- rq->errors = 1;
+ rq->errors = make_status_bytes(SAM_STAT_GOOD,
+ cmd->err_info->CommandStatus, DRIVER_OK,
+ blk_pc_request(cmd->rq) ? DID_PASSTHROUGH : DID_ERROR);
break;
case CMD_ABORTED:
printk(KERN_WARNING "cciss: cmd %p was "
"aborted\n", cmd);
- rq->errors = 1;
+ rq->errors = make_status_bytes(SAM_STAT_GOOD,
+ cmd->err_info->CommandStatus, DRIVER_OK,
+ blk_pc_request(cmd->rq) ? DID_PASSTHROUGH : DID_ABORT);
break;
case CMD_ABORT_FAILED:
printk(KERN_WARNING "cciss: cmd %p reports "
"abort failed\n", cmd);
- rq->errors = 1;
+ rq->errors = make_status_bytes(SAM_STAT_GOOD,
+ cmd->err_info->CommandStatus, DRIVER_OK,
+ blk_pc_request(cmd->rq) ? DID_PASSTHROUGH : DID_ERROR);
break;
case CMD_UNSOLICITED_ABORT:
printk(KERN_WARNING "cciss%d: unsolicited "
@@ -2482,17 +2516,23 @@ static inline void complete_command(ctlr_info_t *h, CommandList_struct *cmd,
printk(KERN_WARNING
"cciss%d: %p retried too "
"many times\n", h->ctlr, cmd);
- rq->errors = 1;
+ rq->errors = make_status_bytes(SAM_STAT_GOOD,
+ cmd->err_info->CommandStatus, DRIVER_OK,
+ blk_pc_request(cmd->rq) ? DID_PASSTHROUGH : DID_ABORT);
break;
case CMD_TIMEOUT:
printk(KERN_WARNING "cciss: cmd %p timedout\n", cmd);
- rq->errors = 1;
+ rq->errors = make_status_bytes(SAM_STAT_GOOD,
+ cmd->err_info->CommandStatus, DRIVER_OK,
+ blk_pc_request(cmd->rq) ? DID_PASSTHROUGH : DID_ERROR);
break;
default:
printk(KERN_WARNING "cciss: cmd %p returned "
"unknown status %x\n", cmd,
cmd->err_info->CommandStatus);
- rq->errors = 1;
+ rq->errors = make_status_bytes(SAM_STAT_GOOD,
+ cmd->err_info->CommandStatus, DRIVER_OK,
+ blk_pc_request(cmd->rq) ? DID_PASSTHROUGH : DID_ERROR);
}
after_error_processing:
@@ -2570,6 +2610,7 @@ static void do_cciss_request(struct request_queue *q)
(int)creq->nr_sectors);
#endif /* CCISS_DEBUG */
+ sg_init_table(tmp_sg, MAXSGENTRIES);
seg = blk_rq_map_sg(q, creq, tmp_sg);
/* get the DMA records for the setup */
@@ -2580,7 +2621,7 @@ static void do_cciss_request(struct request_queue *q)
for (i = 0; i < seg; i++) {
c->SG[i].Len = tmp_sg[i].length;
- temp64.val = (__u64) pci_map_page(h->pdev, tmp_sg[i].page,
+ temp64.val = (__u64) pci_map_page(h->pdev, sg_page(&tmp_sg[i]),
tmp_sg[i].offset,
tmp_sg[i].length, dir);
c->SG[i].Addr.lower = temp64.val32.lower;
@@ -3035,15 +3076,20 @@ static int cciss_pci_init(ctlr_info_t *c, struct pci_dev *pdev)
}
#endif
- /* Disabling DMA prefetch for the P600
- * An ASIC bug may result in a prefetch beyond
- * physical memory.
+ /* Disabling DMA prefetch and refetch for the P600.
+ * An ASIC bug may result in accesses to invalid memory addresses.
+ * We've disabled prefetch for some time now. Testing with XEN
+ * kernels revealed a bug in the refetch if dom0 resides on a P600.
*/
if(board_id == 0x3225103C) {
__u32 dma_prefetch;
+ __u32 dma_refetch;
dma_prefetch = readl(c->vaddr + I2O_DMA1_CFG);
dma_prefetch |= 0x8000;
writel(dma_prefetch, c->vaddr + I2O_DMA1_CFG);
+ pci_read_config_dword(pdev, PCI_COMMAND_PARITY, &dma_refetch);
+ dma_refetch |= 0x1;
+ pci_write_config_dword(pdev, PCI_COMMAND_PARITY, dma_refetch);
}
#ifdef CCISS_DEBUG
diff --git a/drivers/block/cciss_scsi.c b/drivers/block/cciss_scsi.c
index 4aca7ddfddd..63ee6c076cb 100644
--- a/drivers/block/cciss_scsi.c
+++ b/drivers/block/cciss_scsi.c
@@ -1,20 +1,20 @@
/*
- * Disk Array driver for Compaq SA53xx Controllers, SCSI Tape module
- * Copyright 2001 Compaq Computer Corporation
+ * Disk Array driver for HP Smart Array controllers, SCSI Tape module.
+ * (C) Copyright 2001, 2007 Hewlett-Packard Development Company, L.P.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
+ * the Free Software Foundation; version 2 of the License.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE, GOOD TITLE or
- * NON INFRINGEMENT. See the GNU General Public License for more details.
+ * MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
- * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ * Foundation, Inc., 59 Temple Place, Suite 300, Boston, MA
+ * 02111-1307, USA.
*
* Questions/Comments/Bugfixes to iss_storagedev@hp.com
*
diff --git a/drivers/block/cciss_scsi.h b/drivers/block/cciss_scsi.h
index 5e7e06c07d6..d9c2c586502 100644
--- a/drivers/block/cciss_scsi.h
+++ b/drivers/block/cciss_scsi.h
@@ -1,20 +1,20 @@
/*
- * Disk Array driver for Compaq SA53xx Controllers, SCSI Tape module
- * Copyright 2001 Compaq Computer Corporation
+ * Disk Array driver for HP Smart Array controllers, SCSI Tape module.
+ * (C) Copyright 2001, 2007 Hewlett-Packard Development Company, L.P.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
+ * the Free Software Foundation; version 2 of the License.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE, GOOD TITLE or
- * NON INFRINGEMENT. See the GNU General Public License for more details.
+ * MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
- * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ * Foundation, Inc., 59 Temple Place, Suite 300, Boston, MA
+ * 02111-1307, USA.
*
* Questions/Comments/Bugfixes to iss_storagedev@hp.com
*
diff --git a/drivers/block/cpqarray.c b/drivers/block/cpqarray.c
index 3853c9a38d6..c8132d95879 100644
--- a/drivers/block/cpqarray.c
+++ b/drivers/block/cpqarray.c
@@ -37,6 +37,7 @@
#include <linux/spinlock.h>
#include <linux/blkdev.h>
#include <linux/genhd.h>
+#include <linux/scatterlist.h>
#include <asm/uaccess.h>
#include <asm/io.h>
@@ -918,6 +919,7 @@ queue_next:
DBGPX(
printk("sector=%d, nr_sectors=%d\n", creq->sector, creq->nr_sectors);
);
+ sg_init_table(tmp_sg, SG_MAX);
seg = blk_rq_map_sg(q, creq, tmp_sg);
/* Now do all the DMA Mappings */
@@ -929,7 +931,7 @@ DBGPX(
{
c->req.sg[i].size = tmp_sg[i].length;
c->req.sg[i].addr = (__u32) pci_map_page(h->pci_dev,
- tmp_sg[i].page,
+ sg_page(&tmp_sg[i]),
tmp_sg[i].offset,
tmp_sg[i].length, dir);
}
@@ -981,9 +983,8 @@ static void start_io(ctlr_info_t *h)
static inline void complete_buffers(struct bio *bio, int ok)
{
struct bio *xbh;
- while(bio) {
- int nr_sectors = bio_sectors(bio);
+ while (bio) {
xbh = bio->bi_next;
bio->bi_next = NULL;
diff --git a/drivers/block/cryptoloop.c b/drivers/block/cryptoloop.c
index 40535036e89..241167878ed 100644
--- a/drivers/block/cryptoloop.c
+++ b/drivers/block/cryptoloop.c
@@ -26,6 +26,7 @@
#include <linux/crypto.h>
#include <linux/blkdev.h>
#include <linux/loop.h>
+#include <linux/scatterlist.h>
#include <asm/semaphore.h>
#include <asm/uaccess.h>
@@ -119,14 +120,17 @@ cryptoloop_transfer(struct loop_device *lo, int cmd,
.tfm = tfm,
.flags = CRYPTO_TFM_REQ_MAY_SLEEP,
};
- struct scatterlist sg_out = { NULL, };
- struct scatterlist sg_in = { NULL, };
+ struct scatterlist sg_out;
+ struct scatterlist sg_in;
encdec_cbc_t encdecfunc;
struct page *in_page, *out_page;
unsigned in_offs, out_offs;
int err;
+ sg_init_table(&sg_out, 1);
+ sg_init_table(&sg_in, 1);
+
if (cmd == READ) {
in_page = raw_page;
in_offs = raw_off;
@@ -146,13 +150,8 @@ cryptoloop_transfer(struct loop_device *lo, int cmd,
u32 iv[4] = { 0, };
iv[0] = cpu_to_le32(IV & 0xffffffff);
- 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;
+ sg_set_page(&sg_in, in_page, sz, in_offs);
+ sg_set_page(&sg_out, out_page, sz, out_offs);
desc.info = iv;
err = encdecfunc(&desc, &sg_out, &sg_in, sz);
diff --git a/drivers/block/floppy.c b/drivers/block/floppy.c
index 80483aac4cc..639ed14bb08 100644
--- a/drivers/block/floppy.c
+++ b/drivers/block/floppy.c
@@ -5,6 +5,7 @@
* Copyright (C) 1993, 1994 Alain Knaff
* Copyright (C) 1998 Alan Cox
*/
+
/*
* 02.12.91 - Changed to static variables to indicate need for reset
* and recalibrate. This makes some things easier (output_byte reset
@@ -149,7 +150,7 @@
#define REALLY_SLOW_IO
#define DEBUGT 2
-#define DCL_DEBUG /* debug disk change line */
+#define DCL_DEBUG /* debug disk change line */
/* do print messages for unexpected interrupts */
static int print_unex = 1;
@@ -161,10 +162,8 @@ static int print_unex = 1;
#include <linux/workqueue.h>
#define FDPATCHES
#include <linux/fdreg.h>
-
#include <linux/fd.h>
#include <linux/hdreg.h>
-
#include <linux/errno.h>
#include <linux/slab.h>
#include <linux/mm.h>
@@ -274,8 +273,7 @@ static inline void fallback_on_nodma_alloc(char **addr, size_t l)
return; /* we have the memory */
if (can_use_virtual_dma != 2)
return; /* no fallback allowed */
- printk
- ("DMA memory shortage. Temporarily falling back on virtual DMA\n");
+ printk("DMA memory shortage. Temporarily falling back on virtual DMA\n");
*addr = (char *)nodma_mem_alloc(l);
#else
return;
@@ -291,8 +289,8 @@ static int initialising = 1;
#define TOMINOR(x) ((x & 3) | ((x & 4) << 5))
#define UNIT(x) ((x) & 0x03) /* drive on fdc */
#define FDC(x) (((x) & 0x04) >> 2) /* fdc of drive */
+ /* reverse mapping from unit and fdc to drive */
#define REVDRIVE(fdc, unit) ((unit) + ((fdc) << 2))
- /* reverse mapping from unit and fdc to drive */
#define DP (&drive_params[current_drive])
#define DRS (&drive_state[current_drive])
#define DRWE (&write_errors[current_drive])
@@ -356,7 +354,6 @@ static int inr; /* size of reply buffer, when called from interrupt */
#define R_HEAD (reply_buffer[4])
#define R_SECTOR (reply_buffer[5])
#define R_SIZECODE (reply_buffer[6])
-
#define SEL_DLY (2*HZ/100)
/*
@@ -472,8 +469,8 @@ static struct floppy_struct floppy_type[32] = {
{ 6400,40,2,80,0,0x25,0x5B,0xCF,0x00,"E3200" }, /* 26 3.20MB 3.5" */
{ 7040,44,2,80,0,0x25,0x5B,0xCF,0x00,"E3520" }, /* 27 3.52MB 3.5" */
{ 7680,48,2,80,0,0x25,0x63,0xCF,0x00,"E3840" }, /* 28 3.84MB 3.5" */
-
{ 3680,23,2,80,0,0x1C,0x10,0xCF,0x00,"H1840" }, /* 29 1.84MB 3.5" */
+
{ 1600,10,2,80,0,0x25,0x02,0xDF,0x2E,"D800" }, /* 30 800KB 3.5" */
{ 3200,20,2,80,0,0x1C,0x00,0xCF,0x2C,"H1600" }, /* 31 1.6MB 3.5" */
};
@@ -539,12 +536,12 @@ static char *floppy_track_buffer;
static int max_buffer_sectors;
static int *errors;
-typedef void (*done_f) (int);
+typedef void (*done_f)(int);
static struct cont_t {
- void (*interrupt) (void); /* this is called after the interrupt of the
+ void (*interrupt)(void); /* this is called after the interrupt of the
* main command */
- void (*redo) (void); /* this is called to retry the operation */
- void (*error) (void); /* this is called to tally an error */
+ void (*redo)(void); /* this is called to retry the operation */
+ void (*error)(void); /* this is called to tally an error */
done_f done; /* this is called to say if the operation has
* succeeded/failed */
} *cont;
@@ -694,7 +691,6 @@ static void reschedule_timeout(int drive, const char *message, int marg)
}
#define INFBOUND(a,b) (a)=max_t(int, a, b)
-
#define SUPBOUND(a,b) (a)=min_t(int, a, b)
/*
@@ -733,6 +729,7 @@ static void reschedule_timeout(int drive, const char *message, int marg)
static int disk_change(int drive)
{
int fdc = FDC(drive);
+
#ifdef FLOPPY_SANITY_CHECK
if (time_before(jiffies, UDRS->select_date + UDP->select_delay))
DPRINT("WARNING disk change called early\n");
@@ -771,7 +768,6 @@ static int disk_change(int drive)
floppy_sizes[TOMINOR(drive)] = MAX_DISK_SIZE << 1;
}
- /*USETF(FD_DISK_NEWCHANGE); */
return 1;
} else {
UDRS->last_checked = jiffies;
@@ -787,7 +783,10 @@ static inline int is_selected(int dor, int unit)
static int set_dor(int fdc, char mask, char data)
{
- register unsigned char drive, unit, newdor, olddor;
+ unsigned char unit;
+ unsigned char drive;
+ unsigned char newdor;
+ unsigned char olddor;
if (FDCS->address == -1)
return -1;
@@ -892,7 +891,6 @@ static int _lock_fdc(int drive, int interruptible, int line)
set_current_state(TASK_RUNNING);
remove_wait_queue(&fdc_wait, &wait);
-
flush_scheduled_work();
}
command_status = FD_COMMAND_NONE;
@@ -942,7 +940,7 @@ static void motor_off_callback(unsigned long nr)
static void floppy_off(unsigned int drive)
{
unsigned long volatile delta;
- register int fdc = FDC(drive);
+ int fdc = FDC(drive);
if (!(FDCS->dor & (0x10 << UNIT(drive))))
return;
@@ -968,7 +966,9 @@ static void floppy_off(unsigned int drive)
*/
static void scandrives(void)
{
- int i, drive, saved_drive;
+ int i;
+ int drive;
+ int saved_drive;
if (DP->select_delay)
return;
@@ -1146,7 +1146,9 @@ static void show_floppy(void);
/* waits until the fdc becomes ready */
static int wait_til_ready(void)
{
- int counter, status;
+ int status;
+ int counter;
+
if (FDCS->reset)
return -1;
for (counter = 0; counter < 10000; counter++) {
@@ -1193,7 +1195,8 @@ static int output_byte(char byte)
/* gets the response from the fdc */
static int result(void)
{
- int i, status = 0;
+ int i;
+ int status = 0;
for (i = 0; i < MAX_REPLIES; i++) {
if ((status = wait_til_ready()) < 0)
@@ -1226,6 +1229,7 @@ static int result(void)
static int need_more_output(void)
{
int status;
+
if ((status = wait_til_ready()) < 0)
return -1;
if ((status & (STATUS_READY | STATUS_DIR | STATUS_DMA)) == STATUS_READY)
@@ -1309,8 +1313,11 @@ static int fdc_configure(void)
*/
static void fdc_specify(void)
{
- unsigned char spec1, spec2;
- unsigned long srt, hlt, hut;
+ unsigned char spec1;
+ unsigned char spec2;
+ unsigned long srt;
+ unsigned long hlt;
+ unsigned long hut;
unsigned long dtr = NOMINAL_DTR;
unsigned long scale_dtr = NOMINAL_DTR;
int hlt_max_code = 0x7f;
@@ -1319,7 +1326,6 @@ static void fdc_specify(void)
if (FDCS->need_configure && FDCS->version >= FDC_82072A) {
fdc_configure();
FDCS->need_configure = 0;
- /*DPRINT("FIFO enabled\n"); */
}
switch (raw_cmd->rate & 0x03) {
@@ -1472,7 +1478,6 @@ static int interpret_errors(void)
tell_sector();
}
printk("\n");
-
}
if (ST2 & ST2_WC || ST2 & ST2_BC)
/* wrong cylinder => recal */
@@ -1498,7 +1503,10 @@ static int interpret_errors(void)
*/
static void setup_rw_floppy(void)
{
- int i, r, flags, dflags;
+ int i;
+ int r;
+ int flags;
+ int dflags;
unsigned long ready_date;
timeout_fn function;
@@ -1728,9 +1736,9 @@ static void print_result(char *message, int inr)
/* interrupt handler. Note that this can be called externally on the Sparc */
irqreturn_t floppy_interrupt(int irq, void *dev_id)
{
- void (*handler) (void) = do_floppy;
int do_print;
unsigned long f;
+ void (*handler)(void) = do_floppy;
lasthandler = handler;
interruptjiffies = jiffies;
@@ -1912,12 +1920,11 @@ static void floppy_shutdown(unsigned long data)
is_alive("floppy shutdown");
}
-/*typedef void (*timeout_fn)(unsigned long);*/
-
/* start motor, check media-changed condition and write protection */
-static int start_motor(void (*function) (void))
+static int start_motor(void (*function)(void))
{
- int mask, data;
+ int mask;
+ int data;
mask = 0xfc;
data = UNIT(current_drive);
@@ -2020,17 +2027,17 @@ static struct cont_t wakeup_cont = {
.interrupt = empty,
.redo = do_wakeup,
.error = empty,
- .done = (done_f) empty
+ .done = (done_f)empty
};
static struct cont_t intr_cont = {
.interrupt = empty,
.redo = process_fd_request,
.error = empty,
- .done = (done_f) empty
+ .done = (done_f)empty
};
-static int wait_til_done(void (*handler) (void), int interruptible)
+static int wait_til_done(void (*handler)(void), int interruptible)
{
int ret;
@@ -2049,7 +2056,6 @@ static int wait_til_done(void (*handler) (void), int interruptible)
break;
is_alive("wait_til_done");
-
schedule();
}
@@ -2141,6 +2147,7 @@ static void bad_flp_intr(void)
static void set_floppy(int drive)
{
int type = ITYPE(UDRS->fd_device);
+
if (type)
_floppy = floppy_type + type;
else
@@ -2169,11 +2176,14 @@ static void format_interrupt(void)
#define CT(x) ((x) | 0xc0)
static void setup_format_params(int track)
{
+ int n;
+ int il;
+ int count;
+ int head_shift;
+ int track_shift;
struct fparm {
unsigned char track, head, sect, size;
} *here = (struct fparm *)floppy_track_buffer;
- int il, n;
- int count, head_shift, track_shift;
raw_cmd = &default_raw_cmd;
raw_cmd->track = track;
@@ -2344,7 +2354,10 @@ static void request_done(int uptodate)
/* Interrupt handler evaluating the result of the r/w operation */
static void rw_interrupt(void)
{
- int nr_sectors, ssize, eoc, heads;
+ int eoc;
+ int ssize;
+ int heads;
+ int nr_sectors;
if (R_HEAD >= 2) {
/* some Toshiba floppy controllers occasionnally seem to
@@ -2476,7 +2489,8 @@ static void copy_buffer(int ssize, int max_sector, int max_sector_2)
{
int remaining; /* number of transferred 512-byte sectors */
struct bio_vec *bv;
- char *buffer, *dma_buffer;
+ char *buffer;
+ char *dma_buffer;
int size;
struct req_iterator iter;
@@ -2556,19 +2570,6 @@ static void copy_buffer(int ssize, int max_sector, int max_sector_2)
#endif
}
-#if 0
-static inline int check_dma_crossing(char *start,
- unsigned long length, char *message)
-{
- if (CROSS_64KB(start, length)) {
- printk("DMA xfer crosses 64KB boundary in %s %p-%p\n",
- message, start, start + length);
- return 1;
- } else
- return 0;
-}
-#endif
-
/* work around a bug in pseudo DMA
* (on some FDCs) pseudo DMA does not stop when the CPU stops
* sending data. Hence we need a different way to signal the
@@ -2578,7 +2579,8 @@ static inline int check_dma_crossing(char *start,
*/
static void virtualdmabug_workaround(void)
{
- int hard_sectors, end_sector;
+ int hard_sectors;
+ int end_sector;
if (CT(COMMAND) == FD_WRITE) {
COMMAND &= ~0x80; /* switch off multiple track mode */
@@ -2610,7 +2612,10 @@ static void virtualdmabug_workaround(void)
static int make_raw_rw_request(void)
{
int aligned_sector_t;
- int max_sector, max_size, tracksize, ssize;
+ int max_sector;
+ int max_size;
+ int tracksize;
+ int ssize;
if (max_buffer_sectors == 0) {
printk("VFS: Block I/O scheduled on unopened device\n");
@@ -2762,9 +2767,7 @@ static int make_raw_rw_request(void)
*/
if (!direct ||
(indirect * 2 > direct * 3 &&
- *errors < DP->max_errors.read_track &&
- /*!TESTF(FD_NEED_TWADDLE) && */
- ((!probing
+ *errors < DP->max_errors.read_track && ((!probing
|| (DP->read_track & (1 << DRS->probed_format)))))) {
max_size = current_req->nr_sectors;
} else {
@@ -2777,10 +2780,6 @@ static int make_raw_rw_request(void)
indirect, direct, fsector_t);
return 0;
}
-/* check_dma_crossing(raw_cmd->kernel_data,
- raw_cmd->length,
- "end of make_raw_request [1]");*/
-
virtualdmabug_workaround();
return 2;
}
@@ -2830,8 +2829,6 @@ static int make_raw_rw_request(void)
raw_cmd->length = ((raw_cmd->length - 1) | (ssize - 1)) + 1;
raw_cmd->length <<= 9;
#ifdef FLOPPY_SANITY_CHECK
- /*check_dma_crossing(raw_cmd->kernel_data, raw_cmd->length,
- "end of make_raw_request"); */
if ((raw_cmd->length < current_count_sectors << 9) ||
(raw_cmd->kernel_data != current_req->buffer &&
CT(COMMAND) == FD_WRITE &&
@@ -3011,6 +3008,7 @@ static struct cont_t poll_cont = {
static int poll_drive(int interruptible, int flag)
{
int ret;
+
/* no auto-sense, just clear dcl */
raw_cmd = &default_raw_cmd;
raw_cmd->flags = flag;
@@ -3173,7 +3171,8 @@ static inline int raw_cmd_copyout(int cmd, char __user *param,
static void raw_cmd_free(struct floppy_raw_cmd **ptr)
{
- struct floppy_raw_cmd *next, *this;
+ struct floppy_raw_cmd *next;
+ struct floppy_raw_cmd *this;
this = *ptr;
*ptr = NULL;
@@ -3245,8 +3244,10 @@ static inline int raw_cmd_copyin(int cmd, char __user *param,
static int raw_cmd_ioctl(int cmd, void __user *param)
{
- int drive, ret, ret2;
struct floppy_raw_cmd *my_raw_cmd;
+ int drive;
+ int ret2;
+ int ret;
if (FDCS->rawcmd <= 1)
FDCS->rawcmd = 1;
@@ -3453,7 +3454,8 @@ static int fd_ioctl(struct inode *inode, struct file *filp, unsigned int cmd,
#define IN(c,x,tag) case c: *(x) = inparam. tag ; return 0
int drive = (long)inode->i_bdev->bd_disk->private_data;
- int i, type = ITYPE(UDRS->fd_device);
+ int type = ITYPE(UDRS->fd_device);
+ int i;
int ret;
int size;
union inparam {
@@ -3619,8 +3621,7 @@ static void __init config_types(void)
if (!UDP->cmos && FLOPPY1_TYPE)
UDP->cmos = FLOPPY1_TYPE;
- /* XXX */
- /* additional physical CMOS drive detection should go here */
+ /* FIXME: additional physical CMOS drive detection should go here */
for (drive = 0; drive < N_DRIVE; drive++) {
unsigned int type = UDP->cmos;
@@ -3903,13 +3904,13 @@ static int floppy_revalidate(struct gendisk *disk)
}
static struct block_device_operations floppy_fops = {
- .owner = THIS_MODULE,
- .open = floppy_open,
- .release = floppy_release,
- .ioctl = fd_ioctl,
- .getgeo = fd_getgeo,
- .media_changed = check_floppy_change,
- .revalidate_disk = floppy_revalidate,
+ .owner = THIS_MODULE,
+ .open = floppy_open,
+ .release = floppy_release,
+ .ioctl = fd_ioctl,
+ .getgeo = fd_getgeo,
+ .media_changed = check_floppy_change,
+ .revalidate_disk = floppy_revalidate,
};
/*
@@ -4388,11 +4389,15 @@ static int floppy_grab_irq_and_dma(void)
if (fd_request_dma()) {
DPRINT("Unable to grab DMA%d for the floppy driver\n",
FLOPPY_DMA);
- fd_free_irq();
- spin_lock_irqsave(&floppy_usage_lock, flags);
- usage_count--;
- spin_unlock_irqrestore(&floppy_usage_lock, flags);
- return -1;
+ if (can_use_virtual_dma & 2)
+ use_virtual_dma = can_use_virtual_dma = 1;
+ if (!(can_use_virtual_dma & 1)) {
+ fd_free_irq();
+ spin_lock_irqsave(&floppy_usage_lock, flags);
+ usage_count--;
+ spin_unlock_irqrestore(&floppy_usage_lock, flags);
+ return -1;
+ }
}
for (fdc = 0; fdc < N_FDC; fdc++) {
@@ -4424,8 +4429,8 @@ static int floppy_grab_irq_and_dma(void)
if (FDCS->address != -1)
fd_outb(FDCS->dor, FD_DOR);
/*
- * The driver will try and free resources and relies on us
- * to know if they were allocated or not.
+ * The driver will try and free resources and relies on us
+ * to know if they were allocated or not.
*/
fdc = 0;
irqdma_allocated = 1;
diff --git a/drivers/block/lguest_blk.c b/drivers/block/lguest_blk.c
deleted file mode 100644
index fa8e42341b8..00000000000
--- a/drivers/block/lguest_blk.c
+++ /dev/null
@@ -1,421 +0,0 @@
-/*D:400
- * The Guest block driver
- *
- * This is a simple block driver, which appears as /dev/lgba, lgbb, lgbc etc.
- * The mechanism is simple: we place the information about the request in the
- * device page, then use SEND_DMA (containing the data for a write, or an empty
- * "ping" DMA for a read).
- :*/
-/* Copyright 2006 Rusty Russell <rusty@rustcorp.com.au> IBM Corporation
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
- */
-//#define DEBUG
-#include <linux/init.h>
-#include <linux/types.h>
-#include <linux/blkdev.h>
-#include <linux/interrupt.h>
-#include <linux/lguest_bus.h>
-
-static char next_block_index = 'a';
-
-/*D:420 Here is the structure which holds all the information we need about
- * each Guest block device.
- *
- * I'm sure at this stage, you're wondering "hey, where was the adventure I was
- * promised?" and thinking "Rusty sucks, I shall say nasty things about him on
- * my blog". I think Real adventures have boring bits, too, and you're in the
- * middle of one. But it gets better. Just not quite yet. */
-struct blockdev
-{
- /* The block queue infrastructure wants a spinlock: it is held while it
- * calls our block request function. We grab it in our interrupt
- * handler so the responses don't mess with new requests. */
- spinlock_t lock;
-
- /* The disk structure registered with kernel. */
- struct gendisk *disk;
-
- /* The major device number for this disk, and the interrupt. We only
- * really keep them here for completeness; we'd need them if we
- * supported device unplugging. */
- int major;
- int irq;
-
- /* The physical address of this device's memory page */
- unsigned long phys_addr;
- /* The mapped memory page for convenient acces. */
- struct lguest_block_page *lb_page;
-
- /* We only have a single request outstanding at a time: this is it. */
- struct lguest_dma dma;
- struct request *req;
-};
-
-/*D:495 We originally used end_request() throughout the driver, but it turns
- * out that end_request() is deprecated, and doesn't actually end the request
- * (which seems like a good reason to deprecate it!). It simply ends the first
- * bio. So if we had 3 bios in a "struct request" we would do all 3,
- * end_request(), do 2, end_request(), do 1 and end_request(): twice as much
- * work as we needed to do.
- *
- * This reinforced to me that I do not understand the block layer.
- *
- * Nonetheless, Jens Axboe gave me this nice helper to end all chunks of a
- * request. This improved disk speed by 130%. */
-static void end_entire_request(struct request *req, int uptodate)
-{
- if (end_that_request_first(req, uptodate, req->hard_nr_sectors))
- BUG();
- add_disk_randomness(req->rq_disk);
- blkdev_dequeue_request(req);
- end_that_request_last(req, uptodate);
-}
-
-/* I'm told there are only two stories in the world worth telling: love and
- * hate. So there used to be a love scene here like this:
- *
- * Launcher: We could make beautiful I/O together, you and I.
- * Guest: My, that's a big disk!
- *
- * Unfortunately, it was just too raunchy for our otherwise-gentle tale. */
-
-/*D:490 This is the interrupt handler, called when a block read or write has
- * been completed for us. */
-static irqreturn_t lgb_irq(int irq, void *_bd)
-{
- /* We handed our "struct blockdev" as the argument to request_irq(), so
- * it is passed through to us here. This tells us which device we're
- * dealing with in case we have more than one. */
- struct blockdev *bd = _bd;
- unsigned long flags;
-
- /* We weren't doing anything? Strange, but could happen if we shared
- * interrupts (we don't!). */
- if (!bd->req) {
- pr_debug("No work!\n");
- return IRQ_NONE;
- }
-
- /* Not done yet? That's equally strange. */
- if (!bd->lb_page->result) {
- pr_debug("No result!\n");
- return IRQ_NONE;
- }
-
- /* We have to grab the lock before ending the request. */
- spin_lock_irqsave(&bd->lock, flags);
- /* "result" is 1 for success, 2 for failure: end_entire_request() wants
- * to know whether this succeeded or not. */
- end_entire_request(bd->req, bd->lb_page->result == 1);
- /* Clear out request, it's done. */
- bd->req = NULL;
- /* Reset incoming DMA for next time. */
- bd->dma.used_len = 0;
- /* Ready for more reads or writes */
- blk_start_queue(bd->disk->queue);
- spin_unlock_irqrestore(&bd->lock, flags);
-
- /* The interrupt was for us, we dealt with it. */
- return IRQ_HANDLED;
-}
-
-/*D:480 The block layer's "struct request" contains a number of "struct bio"s,
- * each of which contains "struct bio_vec"s, each of which contains a page, an
- * offset and a length.
- *
- * Fortunately there are iterators to help us walk through the "struct
- * request". Even more fortunately, there were plenty of places to steal the
- * code from. We pack the "struct request" into our "struct lguest_dma" and
- * return the total length. */
-static unsigned int req_to_dma(struct request *req, struct lguest_dma *dma)
-{
- unsigned int i = 0, len = 0;
- struct req_iterator iter;
- struct bio_vec *bvec;
-
- rq_for_each_segment(bvec, req, iter) {
- /* We told the block layer not to give us too many. */
- BUG_ON(i == LGUEST_MAX_DMA_SECTIONS);
- /* If we had a zero-length segment, it would look like
- * the end of the data referred to by the "struct
- * lguest_dma", so make sure that doesn't happen. */
- BUG_ON(!bvec->bv_len);
- /* Convert page & offset to a physical address */
- dma->addr[i] = page_to_phys(bvec->bv_page)
- + bvec->bv_offset;
- dma->len[i] = bvec->bv_len;
- len += bvec->bv_len;
- i++;
- }
- /* If the array isn't full, we mark the end with a 0 length */
- if (i < LGUEST_MAX_DMA_SECTIONS)
- dma->len[i] = 0;
- return len;
-}
-
-/* This creates an empty DMA, useful for prodding the Host without sending data
- * (ie. when we want to do a read) */
-static void empty_dma(struct lguest_dma *dma)
-{
- dma->len[0] = 0;
-}
-
-/*D:470 Setting up a request is fairly easy: */
-static void setup_req(struct blockdev *bd,
- int type, struct request *req, struct lguest_dma *dma)
-{
- /* The type is 1 (write) or 0 (read). */
- bd->lb_page->type = type;
- /* The sector on disk where the read or write starts. */
- bd->lb_page->sector = req->sector;
- /* The result is initialized to 0 (unfinished). */
- bd->lb_page->result = 0;
- /* The current request (so we can end it in the interrupt handler). */
- bd->req = req;
- /* The number of bytes: returned as a side-effect of req_to_dma(),
- * which packs the block layer's "struct request" into our "struct
- * lguest_dma" */
- bd->lb_page->bytes = req_to_dma(req, dma);
-}
-
-/*D:450 Write is pretty straightforward: we pack the request into a "struct
- * lguest_dma", then use SEND_DMA to send the request. */
-static void do_write(struct blockdev *bd, struct request *req)
-{
- struct lguest_dma send;
-
- pr_debug("lgb: WRITE sector %li\n", (long)req->sector);
- setup_req(bd, 1, req, &send);
-
- lguest_send_dma(bd->phys_addr, &send);
-}
-
-/* Read is similar to write, except we pack the request into our receive
- * "struct lguest_dma" and send through an empty DMA just to tell the Host that
- * there's a request pending. */
-static void do_read(struct blockdev *bd, struct request *req)
-{
- struct lguest_dma ping;
-
- pr_debug("lgb: READ sector %li\n", (long)req->sector);
- setup_req(bd, 0, req, &bd->dma);
-
- empty_dma(&ping);
- lguest_send_dma(bd->phys_addr, &ping);
-}
-
-/*D:440 This where requests come in: we get handed the request queue and are
- * expected to pull a "struct request" off it until we've finished them or
- * we're waiting for a reply: */
-static void do_lgb_request(struct request_queue *q)
-{
- struct blockdev *bd;
- struct request *req;
-
-again:
- /* This sometimes returns NULL even on the very first time around. I
- * wonder if it's something to do with letting elves handle the request
- * queue... */
- req = elv_next_request(q);
- if (!req)
- return;
-
- /* We attached the struct blockdev to the disk: get it back */
- bd = req->rq_disk->private_data;
- /* Sometimes we get repeated requests after blk_stop_queue(), but we
- * can only handle one at a time. */
- if (bd->req)
- return;
-
- /* We only do reads and writes: no tricky business! */
- if (!blk_fs_request(req)) {
- pr_debug("Got non-command 0x%08x\n", req->cmd_type);
- req->errors++;
- end_entire_request(req, 0);
- goto again;
- }
-
- if (rq_data_dir(req) == WRITE)
- do_write(bd, req);
- else
- do_read(bd, req);
-
- /* We've put out the request, so stop any more coming in until we get
- * an interrupt, which takes us to lgb_irq() to re-enable the queue. */
- blk_stop_queue(q);
-}
-
-/*D:430 This is the "struct block_device_operations" we attach to the disk at
- * the end of lguestblk_probe(). It doesn't seem to want much. */
-static struct block_device_operations lguestblk_fops = {
- .owner = THIS_MODULE,
-};
-
-/*D:425 Setting up a disk device seems to involve a lot of code. I'm not sure
- * quite why. I do know that the IDE code sent two or three of the maintainers
- * insane, perhaps this is the fringe of the same disease?
- *
- * As in the console code, the probe function gets handed the generic
- * lguest_device from lguest_bus.c: */
-static int lguestblk_probe(struct lguest_device *lgdev)
-{
- struct blockdev *bd;
- int err;
- int irqflags = IRQF_SHARED;
-
- /* First we allocate our own "struct blockdev" and initialize the easy
- * fields. */
- bd = kmalloc(sizeof(*bd), GFP_KERNEL);
- if (!bd)
- return -ENOMEM;
-
- spin_lock_init(&bd->lock);
- bd->irq = lgdev_irq(lgdev);
- bd->req = NULL;
- bd->dma.used_len = 0;
- bd->dma.len[0] = 0;
- /* The descriptor in the lguest_devices array provided by the Host
- * gives the Guest the physical page number of the device's page. */
- bd->phys_addr = (lguest_devices[lgdev->index].pfn << PAGE_SHIFT);
-
- /* We use lguest_map() to get a pointer to the device page */
- bd->lb_page = lguest_map(bd->phys_addr, 1);
- if (!bd->lb_page) {
- err = -ENOMEM;
- goto out_free_bd;
- }
-
- /* We need a major device number: 0 means "assign one dynamically". */
- bd->major = register_blkdev(0, "lguestblk");
- if (bd->major < 0) {
- err = bd->major;
- goto out_unmap;
- }
-
- /* This allocates a "struct gendisk" where we pack all the information
- * about the disk which the rest of Linux sees. The argument is the
- * number of minor devices desired: we need one minor for the main
- * disk, and one for each partition. Of course, we can't possibly know
- * how many partitions are on the disk (add_disk does that).
- */
- bd->disk = alloc_disk(16);
- if (!bd->disk) {
- err = -ENOMEM;
- goto out_unregister_blkdev;
- }
-
- /* Every disk needs a queue for requests to come in: we set up the
- * queue with a callback function (the core of our driver) and the lock
- * to use. */
- bd->disk->queue = blk_init_queue(do_lgb_request, &bd->lock);
- if (!bd->disk->queue) {
- err = -ENOMEM;
- goto out_put_disk;
- }
-
- /* We can only handle a certain number of pointers in our SEND_DMA
- * call, so we set that with blk_queue_max_hw_segments(). This is not
- * to be confused with blk_queue_max_phys_segments() of course! I
- * know, who could possibly confuse the two?
- *
- * Well, it's simple to tell them apart: this one seems to work and the
- * other one didn't. */
- blk_queue_max_hw_segments(bd->disk->queue, LGUEST_MAX_DMA_SECTIONS);
-
- /* Due to technical limitations of our Host (and simple coding) we
- * can't have a single buffer which crosses a page boundary. Tell it
- * here. This means that our maximum request size is 16
- * (LGUEST_MAX_DMA_SECTIONS) pages. */
- blk_queue_segment_boundary(bd->disk->queue, PAGE_SIZE-1);
-
- /* We name our disk: this becomes the device name when udev does its
- * magic thing and creates the device node, such as /dev/lgba.
- * next_block_index is a global which starts at 'a'. Unfortunately
- * this simple increment logic means that the 27th disk will be called
- * "/dev/lgb{". In that case, I recommend having at least 29 disks, so
- * your /dev directory will be balanced. */
- sprintf(bd->disk->disk_name, "lgb%c", next_block_index++);
-
- /* We look to the device descriptor again to see if this device's
- * interrupts are expected to be random. If they are, we tell the irq
- * subsystem. At the moment this bit is always set. */
- if (lguest_devices[lgdev->index].features & LGUEST_DEVICE_F_RANDOMNESS)
- irqflags |= IRQF_SAMPLE_RANDOM;
-
- /* Now we have the name and irqflags, we can request the interrupt; we
- * give it the "struct blockdev" we have set up to pass to lgb_irq()
- * when there is an interrupt. */
- err = request_irq(bd->irq, lgb_irq, irqflags, bd->disk->disk_name, bd);
- if (err)
- goto out_cleanup_queue;
-
- /* We bind our one-entry DMA pool to the key for this block device so
- * the Host can reply to our requests. The key is equal to the
- * physical address of the device's page, which is conveniently
- * unique. */
- err = lguest_bind_dma(bd->phys_addr, &bd->dma, 1, bd->irq);
- if (err)
- goto out_free_irq;
-
- /* We finish our disk initialization and add the disk to the system. */
- bd->disk->major = bd->major;
- bd->disk->first_minor = 0;
- bd->disk->private_data = bd;
- bd->disk->fops = &lguestblk_fops;
- /* This is initialized to the disk size by the Launcher. */
- set_capacity(bd->disk, bd->lb_page->num_sectors);
- add_disk(bd->disk);
-
- printk(KERN_INFO "%s: device %i at major %d\n",
- bd->disk->disk_name, lgdev->index, bd->major);
-
- /* We don't need to keep the "struct blockdev" around, but if we ever
- * implemented device removal, we'd need this. */
- lgdev->private = bd;
- return 0;
-
-out_free_irq:
- free_irq(bd->irq, bd);
-out_cleanup_queue:
- blk_cleanup_queue(bd->disk->queue);
-out_put_disk:
- put_disk(bd->disk);
-out_unregister_blkdev:
- unregister_blkdev(bd->major, "lguestblk");
-out_unmap:
- lguest_unmap(bd->lb_page);
-out_free_bd:
- kfree(bd);
- return err;
-}
-
-/*D:410 The boilerplate code for registering the lguest block driver is just
- * like the console: */
-static struct lguest_driver lguestblk_drv = {
- .name = "lguestblk",
- .owner = THIS_MODULE,
- .device_type = LGUEST_DEVICE_T_BLOCK,
- .probe = lguestblk_probe,
-};
-
-static __init int lguestblk_init(void)
-{
- return register_lguest_driver(&lguestblk_drv);
-}
-module_init(lguestblk_init);
-
-MODULE_DESCRIPTION("Lguest block driver");
-MODULE_LICENSE("GPL");
diff --git a/drivers/block/loop.c b/drivers/block/loop.c
index b9233a06934..56e23042728 100644
--- a/drivers/block/loop.c
+++ b/drivers/block/loop.c
@@ -29,7 +29,7 @@
*
* Maximum number of loop devices when compiled-in now selectable by passing
* max_loop=<1-255> to the kernel on boot.
- * Erik I. Bolsø, <eriki@himolde.no>, Oct 31, 1999
+ * Erik I. Bolsø, <eriki@himolde.no>, Oct 31, 1999
*
* Completely rewrite request handling to be make_request_fn style and
* non blocking, pushing work to a helper thread. Lots of fixes from
@@ -204,14 +204,13 @@ lo_do_transfer(struct loop_device *lo, int cmd,
* do_lo_send_aops - helper for writing data to a loop device
*
* This is the fast version for backing filesystems which implement the address
- * space operations prepare_write and commit_write.
+ * space operations write_begin and write_end.
*/
static int do_lo_send_aops(struct loop_device *lo, struct bio_vec *bvec,
- int bsize, loff_t pos, struct page *page)
+ int bsize, loff_t pos, struct page *unused)
{
struct file *file = lo->lo_backing_file; /* kudos to NFsckingS */
struct address_space *mapping = file->f_mapping;
- const struct address_space_operations *aops = mapping->a_ops;
pgoff_t index;
unsigned offset, bv_offs;
int len, ret;
@@ -223,63 +222,45 @@ static int do_lo_send_aops(struct loop_device *lo, struct bio_vec *bvec,
len = bvec->bv_len;
while (len > 0) {
sector_t IV;
- unsigned size;
+ unsigned size, copied;
int transfer_result;
+ struct page *page;
+ void *fsdata;
IV = ((sector_t)index << (PAGE_CACHE_SHIFT - 9))+(offset >> 9);
size = PAGE_CACHE_SIZE - offset;
if (size > len)
size = len;
- page = grab_cache_page(mapping, index);
- if (unlikely(!page))
+
+ ret = pagecache_write_begin(file, mapping, pos, size, 0,
+ &page, &fsdata);
+ if (ret)
goto fail;
- ret = aops->prepare_write(file, page, offset,
- offset + size);
- if (unlikely(ret)) {
- if (ret == AOP_TRUNCATED_PAGE) {
- page_cache_release(page);
- continue;
- }
- goto unlock;
- }
+
transfer_result = lo_do_transfer(lo, WRITE, page, offset,
bvec->bv_page, bv_offs, size, IV);
- if (unlikely(transfer_result)) {
- /*
- * 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);
- zero_user_page(page, offset, size, KM_USER0);
- }
- flush_dcache_page(page);
- ret = aops->commit_write(file, page, offset,
- offset + size);
- if (unlikely(ret)) {
- if (ret == AOP_TRUNCATED_PAGE) {
- page_cache_release(page);
- continue;
- }
- goto unlock;
- }
+ copied = size;
if (unlikely(transfer_result))
- goto unlock;
- bv_offs += size;
- len -= size;
+ copied = 0;
+
+ ret = pagecache_write_end(file, mapping, pos, size, copied,
+ page, fsdata);
+ if (ret < 0 || ret != copied)
+ goto fail;
+
+ if (unlikely(transfer_result))
+ goto fail;
+
+ bv_offs += copied;
+ len -= copied;
offset = 0;
index++;
- pos += size;
- unlock_page(page);
- page_cache_release(page);
+ pos += copied;
}
ret = 0;
out:
mutex_unlock(&mapping->host->i_mutex);
return ret;
-unlock:
- unlock_page(page);
- page_cache_release(page);
fail:
ret = -1;
goto out;
@@ -313,7 +294,7 @@ static int __do_lo_send_write(struct file *file,
* do_lo_send_direct_write - helper for writing data to a loop device
*
* This is the fast, non-transforming version for backing filesystems which do
- * not implement the address space operations prepare_write and commit_write.
+ * not implement the address space operations write_begin and write_end.
* It uses the write file operation which should be present on all writeable
* filesystems.
*/
@@ -332,7 +313,7 @@ static int do_lo_send_direct_write(struct loop_device *lo,
* do_lo_send_write - helper for writing data to a loop device
*
* This is the slow, transforming version for filesystems which do not
- * implement the address space operations prepare_write and commit_write. It
+ * implement the address space operations write_begin and write_end. It
* uses the write file operation which should be present on all writeable
* filesystems.
*
@@ -780,7 +761,7 @@ static int loop_set_fd(struct loop_device *lo, struct file *lo_file,
*/
if (!file->f_op->splice_read)
goto out_putf;
- if (aops->prepare_write && aops->commit_write)
+ if (aops->prepare_write || aops->write_begin)
lo_flags |= LO_FLAGS_USE_AOPS;
if (!(lo_flags & LO_FLAGS_USE_AOPS) && !file->f_op->write)
lo_flags |= LO_FLAGS_READ_ONLY;
@@ -1304,7 +1285,6 @@ static long lo_compat_ioctl(struct file *file, unsigned int cmd, unsigned long a
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);
@@ -1330,7 +1310,6 @@ static long lo_compat_ioctl(struct file *file, unsigned int cmd, unsigned long a
err = -ENOIOCTLCMD;
break;
}
- unlock_kernel();
return err;
}
#endif
diff --git a/drivers/block/nbd.c b/drivers/block/nbd.c
index be5ec3a9b1f..b4c0888aedc 100644
--- a/drivers/block/nbd.c
+++ b/drivers/block/nbd.c
@@ -28,6 +28,7 @@
#include <linux/err.h>
#include <linux/kernel.h>
#include <net/sock.h>
+#include <linux/net.h>
#include <asm/uaccess.h>
#include <asm/system.h>
@@ -113,12 +114,42 @@ static void nbd_end_request(struct request *req)
spin_unlock_irqrestore(q->queue_lock, flags);
}
+static void sock_shutdown(struct nbd_device *lo, int lock)
+{
+ /* Forcibly shutdown the socket causing all listeners
+ * to error
+ *
+ * FIXME: This code is duplicated from sys_shutdown, but
+ * there should be a more generic interface rather than
+ * calling socket ops directly here */
+ if (lock)
+ mutex_lock(&lo->tx_lock);
+ if (lo->sock) {
+ printk(KERN_WARNING "%s: shutting down socket\n",
+ lo->disk->disk_name);
+ kernel_sock_shutdown(lo->sock, SHUT_RDWR);
+ lo->sock = NULL;
+ }
+ if (lock)
+ mutex_unlock(&lo->tx_lock);
+}
+
+static void nbd_xmit_timeout(unsigned long arg)
+{
+ struct task_struct *task = (struct task_struct *)arg;
+
+ printk(KERN_WARNING "nbd: killing hung xmit (%s, pid: %d)\n",
+ task->comm, task->pid);
+ force_sig(SIGKILL, task);
+}
+
/*
* Send or receive packet.
*/
-static int sock_xmit(struct socket *sock, int send, void *buf, int size,
+static int sock_xmit(struct nbd_device *lo, int send, void *buf, int size,
int msg_flags)
{
+ struct socket *sock = lo->sock;
int result;
struct msghdr msg;
struct kvec iov;
@@ -139,17 +170,29 @@ static int sock_xmit(struct socket *sock, int send, void *buf, int size,
msg.msg_controllen = 0;
msg.msg_flags = msg_flags | MSG_NOSIGNAL;
- if (send)
+ if (send) {
+ struct timer_list ti;
+
+ if (lo->xmit_timeout) {
+ init_timer(&ti);
+ ti.function = nbd_xmit_timeout;
+ ti.data = (unsigned long)current;
+ ti.expires = jiffies + lo->xmit_timeout;
+ add_timer(&ti);
+ }
result = kernel_sendmsg(sock, &msg, &iov, 1, size);
- else
+ if (lo->xmit_timeout)
+ del_timer_sync(&ti);
+ } else
result = kernel_recvmsg(sock, &msg, &iov, 1, size, 0);
if (signal_pending(current)) {
siginfo_t info;
printk(KERN_WARNING "nbd (pid %d: %s) got signal %d\n",
- current->pid, current->comm,
+ task_pid_nr(current), current->comm,
dequeue_signal_lock(current, &current->blocked, &info));
result = -EINTR;
+ sock_shutdown(lo, !send);
break;
}
@@ -167,23 +210,22 @@ static int sock_xmit(struct socket *sock, int send, void *buf, int size,
return result;
}
-static inline int sock_send_bvec(struct socket *sock, struct bio_vec *bvec,
+static inline int sock_send_bvec(struct nbd_device *lo, struct bio_vec *bvec,
int flags)
{
int result;
void *kaddr = kmap(bvec->bv_page);
- result = sock_xmit(sock, 1, kaddr + bvec->bv_offset, bvec->bv_len,
- flags);
+ result = sock_xmit(lo, 1, kaddr + bvec->bv_offset, bvec->bv_len, flags);
kunmap(bvec->bv_page);
return result;
}
+/* always call with the tx_lock held */
static int nbd_send_req(struct nbd_device *lo, struct request *req)
{
int result, flags;
struct nbd_request request;
unsigned long size = req->nr_sectors << 9;
- struct socket *sock = lo->sock;
request.magic = htonl(NBD_REQUEST_MAGIC);
request.type = htonl(nbd_cmd(req));
@@ -196,8 +238,8 @@ static int nbd_send_req(struct nbd_device *lo, struct request *req)
nbdcmd_to_ascii(nbd_cmd(req)),
(unsigned long long)req->sector << 9,
req->nr_sectors << 9);
- result = sock_xmit(sock, 1, &request, sizeof(request),
- (nbd_cmd(req) == NBD_CMD_WRITE)? MSG_MORE: 0);
+ result = sock_xmit(lo, 1, &request, sizeof(request),
+ (nbd_cmd(req) == NBD_CMD_WRITE) ? MSG_MORE : 0);
if (result <= 0) {
printk(KERN_ERR "%s: Send control failed (result %d)\n",
lo->disk->disk_name, result);
@@ -217,7 +259,7 @@ static int nbd_send_req(struct nbd_device *lo, struct request *req)
flags = MSG_MORE;
dprintk(DBG_TX, "%s: request %p: sending %d bytes data\n",
lo->disk->disk_name, req, bvec->bv_len);
- result = sock_send_bvec(sock, bvec, flags);
+ result = sock_send_bvec(lo, bvec, flags);
if (result <= 0) {
printk(KERN_ERR "%s: Send data failed (result %d)\n",
lo->disk->disk_name, result);
@@ -231,22 +273,18 @@ error_out:
return 1;
}
-static struct request *nbd_find_request(struct nbd_device *lo, char *handle)
+static struct request *nbd_find_request(struct nbd_device *lo,
+ struct request *xreq)
{
- struct request *req;
- struct list_head *tmp;
- struct request *xreq;
+ struct request *req, *tmp;
int err;
- memcpy(&xreq, handle, sizeof(xreq));
-
err = wait_event_interruptible(lo->active_wq, lo->active_req != xreq);
if (unlikely(err))
goto out;
spin_lock(&lo->queue_lock);
- list_for_each(tmp, &lo->queue_head) {
- req = list_entry(tmp, struct request, queuelist);
+ list_for_each_entry_safe(req, tmp, &lo->queue_head, queuelist) {
if (req != xreq)
continue;
list_del_init(&req->queuelist);
@@ -261,11 +299,11 @@ out:
return ERR_PTR(err);
}
-static inline int sock_recv_bvec(struct socket *sock, struct bio_vec *bvec)
+static inline int sock_recv_bvec(struct nbd_device *lo, struct bio_vec *bvec)
{
int result;
void *kaddr = kmap(bvec->bv_page);
- result = sock_xmit(sock, 0, kaddr + bvec->bv_offset, bvec->bv_len,
+ result = sock_xmit(lo, 0, kaddr + bvec->bv_offset, bvec->bv_len,
MSG_WAITALL);
kunmap(bvec->bv_page);
return result;
@@ -277,10 +315,9 @@ static struct request *nbd_read_stat(struct nbd_device *lo)
int result;
struct nbd_reply reply;
struct request *req;
- struct socket *sock = lo->sock;
reply.magic = 0;
- result = sock_xmit(sock, 0, &reply, sizeof(reply), MSG_WAITALL);
+ result = sock_xmit(lo, 0, &reply, sizeof(reply), MSG_WAITALL);
if (result <= 0) {
printk(KERN_ERR "%s: Receive control failed (result %d)\n",
lo->disk->disk_name, result);
@@ -295,7 +332,7 @@ static struct request *nbd_read_stat(struct nbd_device *lo)
goto harderror;
}
- req = nbd_find_request(lo, reply.handle);
+ req = nbd_find_request(lo, *(struct request **)reply.handle);
if (unlikely(IS_ERR(req))) {
result = PTR_ERR(req);
if (result != -ENOENT)
@@ -321,7 +358,7 @@ static struct request *nbd_read_stat(struct nbd_device *lo)
struct bio_vec *bvec;
rq_for_each_segment(bvec, req, iter) {
- result = sock_recv_bvec(sock, bvec);
+ result = sock_recv_bvec(lo, bvec);
if (result <= 0) {
printk(KERN_ERR "%s: Receive data failed (result %d)\n",
lo->disk->disk_name, result);
@@ -396,6 +433,7 @@ static void nbd_clear_que(struct nbd_device *lo)
}
}
+
/*
* We always wait for result of write, for now. It would be nice to make it optional
* in future
@@ -471,7 +509,6 @@ error_out:
nbd_end_request(req);
spin_lock(q->queue_lock);
}
- return;
}
static int nbd_ioctl(struct inode *inode, struct file *file,
@@ -504,7 +541,9 @@ static int nbd_ioctl(struct inode *inode, struct file *file,
sreq.nr_sectors = 0;
if (!lo->sock)
return -EINVAL;
+ mutex_lock(&lo->tx_lock);
nbd_send_req(lo, &sreq);
+ mutex_unlock(&lo->tx_lock);
return 0;
case NBD_CLEAR_SOCK:
@@ -548,6 +587,9 @@ static int nbd_ioctl(struct inode *inode, struct file *file,
set_blocksize(inode->i_bdev, lo->blksize);
set_capacity(lo->disk, lo->bytesize >> 9);
return 0;
+ case NBD_SET_TIMEOUT:
+ lo->xmit_timeout = arg * HZ;
+ return 0;
case NBD_SET_SIZE_BLOCKS:
lo->bytesize = ((u64) arg) * lo->blksize;
inode->i_bdev->bd_inode->i_size = lo->bytesize;
@@ -560,28 +602,16 @@ static int nbd_ioctl(struct inode *inode, struct file *file,
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
- *
- * FIXME: This code is duplicated from sys_shutdown, but
- * there should be a more generic interface rather than
- * calling socket ops directly here */
- mutex_lock(&lo->tx_lock);
- if (lo->sock) {
- printk(KERN_WARNING "%s: shutting down socket\n",
- lo->disk->disk_name);
- lo->sock->ops->shutdown(lo->sock,
- SEND_SHUTDOWN|RCV_SHUTDOWN);
- lo->sock = NULL;
- }
- mutex_unlock(&lo->tx_lock);
+ sock_shutdown(lo, 1);
file = lo->file;
lo->file = NULL;
nbd_clear_que(lo);
printk(KERN_WARNING "%s: queue cleared\n", lo->disk->disk_name);
if (file)
fput(file);
+ lo->bytesize = 0;
+ inode->i_bdev->bd_inode->i_size = 0;
+ set_capacity(lo->disk, 0);
return lo->harderror;
case NBD_CLEAR_QUE:
/*
@@ -659,14 +689,14 @@ static int __init nbd_init(void)
mutex_init(&nbd_dev[i].tx_lock);
init_waitqueue_head(&nbd_dev[i].active_wq);
nbd_dev[i].blksize = 1024;
- nbd_dev[i].bytesize = 0x7ffffc00ULL << 10; /* 2TB */
+ nbd_dev[i].bytesize = 0;
disk->major = NBD_MAJOR;
disk->first_minor = i;
disk->fops = &nbd_fops;
disk->private_data = &nbd_dev[i];
disk->flags |= GENHD_FL_SUPPRESS_PARTITION_INFO;
sprintf(disk->disk_name, "nbd%d", i);
- set_capacity(disk, 0x7ffffc00ULL << 1); /* 2 TB */
+ set_capacity(disk, 0);
add_disk(disk);
}
diff --git a/drivers/block/paride/pf.c b/drivers/block/paride/pf.c
index ceffa6034e2..e7fe6ca97dd 100644
--- a/drivers/block/paride/pf.c
+++ b/drivers/block/paride/pf.c
@@ -488,13 +488,11 @@ static int pf_atapi(struct pf_unit *pf, char *cmd, int dlen, char *buf, char *fu
return r;
}
-#define DBMSG(msg) ((verbose>1)?(msg):NULL)
-
static void pf_lock(struct pf_unit *pf, int func)
{
char lo_cmd[12] = { ATAPI_LOCK, pf->lun << 5, 0, 0, func, 0, 0, 0, 0, 0, 0, 0 };
- pf_atapi(pf, lo_cmd, 0, pf_scratch, func ? "unlock" : "lock");
+ pf_atapi(pf, lo_cmd, 0, pf_scratch, func ? "lock" : "unlock");
}
static void pf_eject(struct pf_unit *pf)
@@ -555,7 +553,7 @@ static void pf_mode_sense(struct pf_unit *pf)
{ ATAPI_MODE_SENSE, pf->lun << 5, 0, 0, 0, 0, 0, 0, 8, 0, 0, 0 };
char buf[8];
- pf_atapi(pf, ms_cmd, 8, buf, DBMSG("mode sense"));
+ pf_atapi(pf, ms_cmd, 8, buf, "mode sense");
pf->media_status = PF_RW;
if (buf[3] & 0x80)
pf->media_status = PF_RO;
@@ -591,7 +589,7 @@ static void pf_get_capacity(struct pf_unit *pf)
char buf[8];
int bs;
- if (pf_atapi(pf, rc_cmd, 8, buf, DBMSG("get capacity"))) {
+ if (pf_atapi(pf, rc_cmd, 8, buf, "get capacity")) {
pf->media_status = PF_NM;
return;
}
@@ -804,13 +802,18 @@ static int pf_next_buf(void)
pf_buf += 512;
pf_block++;
if (!pf_run)
- return 0;
- if (!pf_count)
return 1;
- spin_lock_irqsave(&pf_spin_lock, saved_flags);
- pf_end_request(1);
- spin_unlock_irqrestore(&pf_spin_lock, saved_flags);
- return 1;
+ if (!pf_count) {
+ spin_lock_irqsave(&pf_spin_lock, saved_flags);
+ pf_end_request(1);
+ pf_req = elv_next_request(pf_queue);
+ spin_unlock_irqrestore(&pf_spin_lock, saved_flags);
+ if (!pf_req)
+ return 1;
+ pf_count = pf_req->current_nr_sectors;
+ pf_buf = pf_req->buffer;
+ }
+ return 0;
}
static inline void next_request(int success)
diff --git a/drivers/block/paride/pt.c b/drivers/block/paride/pt.c
index 9f4e67ee1eb..b91accf1265 100644
--- a/drivers/block/paride/pt.c
+++ b/drivers/block/paride/pt.c
@@ -664,7 +664,7 @@ static int pt_open(struct inode *inode, struct file *file)
goto out;
err = -EROFS;
- if ((!tape->flags & PT_WRITE_OK) && (file->f_mode & 2))
+ if ((!(tape->flags & PT_WRITE_OK)) && (file->f_mode & 2))
goto out;
if (!(iminor(inode) & 128))
diff --git a/drivers/block/pktcdvd.c b/drivers/block/pktcdvd.c
index 540bf367698..a5ee21319d3 100644
--- a/drivers/block/pktcdvd.c
+++ b/drivers/block/pktcdvd.c
@@ -358,10 +358,19 @@ static ssize_t class_pktcdvd_store_add(struct class *c, const char *buf,
size_t count)
{
unsigned int major, minor;
+
if (sscanf(buf, "%u:%u", &major, &minor) == 2) {
+ /* pkt_setup_dev() expects caller to hold reference to self */
+ if (!try_module_get(THIS_MODULE))
+ return -ENODEV;
+
pkt_setup_dev(MKDEV(major, minor), NULL);
+
+ module_put(THIS_MODULE);
+
return count;
}
+
return -EINVAL;
}
@@ -1133,16 +1142,21 @@ static void pkt_gather_data(struct pktcdvd_device *pd, struct packet_data *pkt)
* Schedule reads for missing parts of the packet.
*/
for (f = 0; f < pkt->frames; f++) {
+ struct bio_vec *vec;
+
int p, offset;
if (written[f])
continue;
bio = pkt->r_bios[f];
+ vec = bio->bi_io_vec;
bio_init(bio);
bio->bi_max_vecs = 1;
bio->bi_sector = pkt->sector + f * (CD_FRAMESIZE >> 9);
bio->bi_bdev = pd->bdev;
bio->bi_end_io = pkt_end_io_read;
bio->bi_private = pkt;
+ bio->bi_io_vec = vec;
+ bio->bi_destructor = pkt_bio_destructor;
p = (f * CD_FRAMESIZE) / PAGE_SIZE;
offset = (f * CD_FRAMESIZE) % PAGE_SIZE;
@@ -1439,6 +1453,8 @@ static void pkt_start_write(struct pktcdvd_device *pd, struct packet_data *pkt)
pkt->w_bio->bi_bdev = pd->bdev;
pkt->w_bio->bi_end_io = pkt_end_io_packet_write;
pkt->w_bio->bi_private = pkt;
+ pkt->w_bio->bi_io_vec = bvec;
+ pkt->w_bio->bi_destructor = pkt_bio_destructor;
for (f = 0; f < pkt->frames; f++)
if (!bio_add_page(pkt->w_bio, bvec[f].bv_page, CD_FRAMESIZE, bvec[f].bv_offset))
BUG();
diff --git a/drivers/block/ps3disk.c b/drivers/block/ps3disk.c
index 06d0552cf49..e354bfc070e 100644
--- a/drivers/block/ps3disk.c
+++ b/drivers/block/ps3disk.c
@@ -414,26 +414,6 @@ static void ps3disk_prepare_flush(struct request_queue *q, struct request *req)
req->cmd_type = REQ_TYPE_FLUSH;
}
-static int ps3disk_issue_flush(struct request_queue *q, struct gendisk *gendisk,
- sector_t *sector)
-{
- struct ps3_storage_device *dev = q->queuedata;
- struct request *req;
- int res;
-
- dev_dbg(&dev->sbd.core, "%s:%u\n", __func__, __LINE__);
-
- req = blk_get_request(q, WRITE, __GFP_WAIT);
- ps3disk_prepare_flush(q, req);
- res = blk_execute_rq(q, gendisk, req, 0);
- if (res)
- dev_err(&dev->sbd.core, "%s:%u: flush request failed %d\n",
- __func__, __LINE__, res);
- blk_put_request(req);
- return res;
-}
-
-
static unsigned long ps3disk_mask;
static DEFINE_MUTEX(ps3disk_mask_mutex);
@@ -506,7 +486,6 @@ static int __devinit ps3disk_probe(struct ps3_system_bus_device *_dev)
blk_queue_dma_alignment(queue, dev->blk_size-1);
blk_queue_hardsect_size(queue, dev->blk_size);
- blk_queue_issue_flush_fn(queue, ps3disk_issue_flush);
blk_queue_ordered(queue, QUEUE_ORDERED_DRAIN_FLUSH,
ps3disk_prepare_flush);
diff --git a/drivers/block/rd.c b/drivers/block/rd.c
index 701ea77f62e..82f4eecc869 100644
--- a/drivers/block/rd.c
+++ b/drivers/block/rd.c
@@ -189,6 +189,18 @@ static int ramdisk_set_page_dirty(struct page *page)
return 0;
}
+/*
+ * releasepage is called by pagevec_strip/try_to_release_page if
+ * buffers_heads_over_limit is true. Without a releasepage function
+ * try_to_free_buffers is called instead. That can unset the dirty
+ * bit of our ram disk pages, which will be eventually freed, even
+ * if the page is still in use.
+ */
+static int ramdisk_releasepage(struct page *page, gfp_t dummy)
+{
+ return 0;
+}
+
static const struct address_space_operations ramdisk_aops = {
.readpage = ramdisk_readpage,
.prepare_write = ramdisk_prepare_write,
@@ -196,6 +208,7 @@ static const struct address_space_operations ramdisk_aops = {
.writepage = ramdisk_writepage,
.set_page_dirty = ramdisk_set_page_dirty,
.writepages = ramdisk_writepages,
+ .releasepage = ramdisk_releasepage,
};
static int rd_blkdev_pagecache_IO(int rw, struct bio_vec *vec, sector_t sector,
@@ -365,7 +378,7 @@ static int rd_open(struct inode *inode, struct file *filp)
/*
* Deep badness. rd_blkdev_pagecache_IO() needs to allocate
* pagecache pages within a request_fn. We cannot recur back
- * into the filesytem which is mounted atop the ramdisk, because
+ * into the filesystem which is mounted atop the ramdisk, because
* that would deadlock on fs locks. And we really don't want
* to reenter rd_blkdev_pagecache_IO when we're already within
* that function.
@@ -411,6 +424,9 @@ static void __exit rd_cleanup(void)
blk_cleanup_queue(rd_queue[i]);
}
unregister_blkdev(RAMDISK_MAJOR, "ramdisk");
+
+ bdi_destroy(&rd_file_backing_dev_info);
+ bdi_destroy(&rd_backing_dev_info);
}
/*
@@ -419,7 +435,19 @@ static void __exit rd_cleanup(void)
static int __init rd_init(void)
{
int i;
- int err = -ENOMEM;
+ int err;
+
+ err = bdi_init(&rd_backing_dev_info);
+ if (err)
+ goto out2;
+
+ err = bdi_init(&rd_file_backing_dev_info);
+ if (err) {
+ bdi_destroy(&rd_backing_dev_info);
+ goto out2;
+ }
+
+ err = -ENOMEM;
if (rd_blocksize > PAGE_SIZE || rd_blocksize < 512 ||
(rd_blocksize & (rd_blocksize-1))) {
@@ -473,6 +501,9 @@ out:
put_disk(rd_disks[i]);
blk_cleanup_queue(rd_queue[i]);
}
+ bdi_destroy(&rd_backing_dev_info);
+ bdi_destroy(&rd_file_backing_dev_info);
+out2:
return err;
}
@@ -486,17 +517,12 @@ static int __init ramdisk_size(char *str)
rd_size = simple_strtol(str,NULL,0);
return 1;
}
-static int __init ramdisk_size2(char *str) /* kludge */
-{
- return ramdisk_size(str);
-}
static int __init ramdisk_blocksize(char *str)
{
rd_blocksize = simple_strtol(str,NULL,0);
return 1;
}
-__setup("ramdisk=", ramdisk_size);
-__setup("ramdisk_size=", ramdisk_size2);
+__setup("ramdisk_size=", ramdisk_size);
__setup("ramdisk_blocksize=", ramdisk_blocksize);
#endif
diff --git a/drivers/block/sunvdc.c b/drivers/block/sunvdc.c
index 317a790c153..fac4c6cd04f 100644
--- a/drivers/block/sunvdc.c
+++ b/drivers/block/sunvdc.c
@@ -15,6 +15,7 @@
#include <linux/delay.h>
#include <linux/init.h>
#include <linux/list.h>
+#include <linux/scatterlist.h>
#include <asm/vio.h>
#include <asm/ldc.h>
@@ -388,6 +389,7 @@ static int __send_request(struct request *req)
op = VD_OP_BWRITE;
}
+ sg_init_table(sg, port->ring_cookies);
nsg = blk_rq_map_sg(req->q, req, sg);
len = 0;
diff --git a/drivers/block/sx8.c b/drivers/block/sx8.c
index 402209fec59..52dc5e13171 100644
--- a/drivers/block/sx8.c
+++ b/drivers/block/sx8.c
@@ -27,6 +27,7 @@
#include <linux/hdreg.h>
#include <linux/dma-mapping.h>
#include <linux/completion.h>
+#include <linux/scatterlist.h>
#include <asm/io.h>
#include <asm/uaccess.h>
@@ -522,6 +523,7 @@ static struct carm_request *carm_get_request(struct carm_host *host)
host->n_msgs++;
assert(host->n_msgs <= CARM_MAX_REQ);
+ sg_init_table(crq->sg, CARM_MAX_REQ_SG);
return crq;
}
diff --git a/drivers/block/ub.c b/drivers/block/ub.c
index c57dd2b3a0c..08e909dc794 100644
--- a/drivers/block/ub.c
+++ b/drivers/block/ub.c
@@ -25,6 +25,7 @@
#include <linux/usb_usual.h>
#include <linux/blkdev.h>
#include <linux/timer.h>
+#include <linux/scatterlist.h>
#include <scsi/scsi.h>
#define DRV_NAME "ub"
@@ -656,6 +657,7 @@ static int ub_request_fn_1(struct ub_lun *lun, struct request *rq)
if ((cmd = ub_get_cmd(lun)) == NULL)
return -1;
memset(cmd, 0, sizeof(struct ub_scsi_cmd));
+ sg_init_table(cmd->sgv, UB_MAX_REQ_SG);
blkdev_dequeue_request(rq);
@@ -1309,9 +1311,8 @@ static void ub_data_start(struct ub_dev *sc, struct ub_scsi_cmd *cmd)
else
pipe = sc->send_bulk_pipe;
sc->last_pipe = pipe;
- usb_fill_bulk_urb(&sc->work_urb, sc->dev, pipe,
- page_address(sg->page) + sg->offset, sg->length,
- ub_urb_complete, sc);
+ usb_fill_bulk_urb(&sc->work_urb, sc->dev, pipe, sg_virt(sg),
+ sg->length, ub_urb_complete, sc);
sc->work_urb.actual_length = 0;
sc->work_urb.error_count = 0;
sc->work_urb.status = 0;
@@ -1427,9 +1428,9 @@ static void ub_state_sense(struct ub_dev *sc, struct ub_scsi_cmd *cmd)
scmd->state = UB_CMDST_INIT;
scmd->nsg = 1;
sg = &scmd->sgv[0];
- sg->page = virt_to_page(sc->top_sense);
- sg->offset = (unsigned long)sc->top_sense & (PAGE_SIZE-1);
- sg->length = UB_SENSE_SIZE;
+ sg_init_table(sg, UB_MAX_REQ_SG);
+ sg_set_page(sg, virt_to_page(sc->top_sense), UB_SENSE_SIZE,
+ (unsigned long)sc->top_sense & (PAGE_SIZE-1));
scmd->len = UB_SENSE_SIZE;
scmd->lun = cmd->lun;
scmd->done = ub_top_sense_done;
@@ -1863,9 +1864,8 @@ static int ub_sync_read_cap(struct ub_dev *sc, struct ub_lun *lun,
cmd->state = UB_CMDST_INIT;
cmd->nsg = 1;
sg = &cmd->sgv[0];
- sg->page = virt_to_page(p);
- sg->offset = (unsigned long)p & (PAGE_SIZE-1);
- sg->length = 8;
+ sg_init_table(sg, UB_MAX_REQ_SG);
+ sg_set_page(sg, virt_to_page(p), 8, (unsigned long)p & (PAGE_SIZE-1));
cmd->len = 8;
cmd->lun = lun;
cmd->done = ub_probe_done;
diff --git a/drivers/block/viodasd.c b/drivers/block/viodasd.c
index e824b672e05..ab5d404faa1 100644
--- a/drivers/block/viodasd.c
+++ b/drivers/block/viodasd.c
@@ -41,6 +41,7 @@
#include <linux/dma-mapping.h>
#include <linux/completion.h>
#include <linux/device.h>
+#include <linux/scatterlist.h>
#include <asm/uaccess.h>
#include <asm/vio.h>
@@ -270,6 +271,7 @@ static int send_request(struct request *req)
d = req->rq_disk->private_data;
/* Now build the scatter-gather list */
+ sg_init_table(sg, VIOMAXBLOCKDMA);
nsg = blk_rq_map_sg(req->q, req, sg);
nsg = dma_map_sg(d->dev, sg, nsg, direction);
diff --git a/drivers/block/virtio_blk.c b/drivers/block/virtio_blk.c
new file mode 100644
index 00000000000..3cf7129d83e
--- /dev/null
+++ b/drivers/block/virtio_blk.c
@@ -0,0 +1,310 @@
+//#define DEBUG
+#include <linux/spinlock.h>
+#include <linux/blkdev.h>
+#include <linux/hdreg.h>
+#include <linux/virtio.h>
+#include <linux/virtio_blk.h>
+#include <linux/scatterlist.h>
+
+#define VIRTIO_MAX_SG (3+MAX_PHYS_SEGMENTS)
+
+static unsigned char virtblk_index = 'a';
+struct virtio_blk
+{
+ spinlock_t lock;
+
+ struct virtio_device *vdev;
+ struct virtqueue *vq;
+
+ /* The disk structure for the kernel. */
+ struct gendisk *disk;
+
+ /* Request tracking. */
+ struct list_head reqs;
+
+ mempool_t *pool;
+
+ /* Scatterlist: can be too big for stack. */
+ struct scatterlist sg[VIRTIO_MAX_SG];
+};
+
+struct virtblk_req
+{
+ struct list_head list;
+ struct request *req;
+ struct virtio_blk_outhdr out_hdr;
+ struct virtio_blk_inhdr in_hdr;
+};
+
+static bool blk_done(struct virtqueue *vq)
+{
+ struct virtio_blk *vblk = vq->vdev->priv;
+ struct virtblk_req *vbr;
+ unsigned int len;
+ unsigned long flags;
+
+ spin_lock_irqsave(&vblk->lock, flags);
+ while ((vbr = vblk->vq->vq_ops->get_buf(vblk->vq, &len)) != NULL) {
+ int uptodate;
+ switch (vbr->in_hdr.status) {
+ case VIRTIO_BLK_S_OK:
+ uptodate = 1;
+ break;
+ case VIRTIO_BLK_S_UNSUPP:
+ uptodate = -ENOTTY;
+ break;
+ default:
+ uptodate = 0;
+ break;
+ }
+
+ end_dequeued_request(vbr->req, uptodate);
+ list_del(&vbr->list);
+ mempool_free(vbr, vblk->pool);
+ }
+ /* In case queue is stopped waiting for more buffers. */
+ blk_start_queue(vblk->disk->queue);
+ spin_unlock_irqrestore(&vblk->lock, flags);
+ return true;
+}
+
+static bool do_req(struct request_queue *q, struct virtio_blk *vblk,
+ struct request *req)
+{
+ unsigned long num, out, in;
+ struct virtblk_req *vbr;
+
+ vbr = mempool_alloc(vblk->pool, GFP_ATOMIC);
+ if (!vbr)
+ /* When another request finishes we'll try again. */
+ return false;
+
+ vbr->req = req;
+ if (blk_fs_request(vbr->req)) {
+ vbr->out_hdr.type = 0;
+ vbr->out_hdr.sector = vbr->req->sector;
+ vbr->out_hdr.ioprio = vbr->req->ioprio;
+ } else if (blk_pc_request(vbr->req)) {
+ vbr->out_hdr.type = VIRTIO_BLK_T_SCSI_CMD;
+ vbr->out_hdr.sector = 0;
+ vbr->out_hdr.ioprio = vbr->req->ioprio;
+ } else {
+ /* We don't put anything else in the queue. */
+ BUG();
+ }
+
+ if (blk_barrier_rq(vbr->req))
+ vbr->out_hdr.type |= VIRTIO_BLK_T_BARRIER;
+
+ /* This init could be done at vblk creation time */
+ sg_init_table(vblk->sg, VIRTIO_MAX_SG);
+ sg_set_buf(&vblk->sg[0], &vbr->out_hdr, sizeof(vbr->out_hdr));
+ num = blk_rq_map_sg(q, vbr->req, vblk->sg+1);
+ sg_set_buf(&vblk->sg[num+1], &vbr->in_hdr, sizeof(vbr->in_hdr));
+
+ if (rq_data_dir(vbr->req) == WRITE) {
+ vbr->out_hdr.type |= VIRTIO_BLK_T_OUT;
+ out = 1 + num;
+ in = 1;
+ } else {
+ vbr->out_hdr.type |= VIRTIO_BLK_T_IN;
+ out = 1;
+ in = 1 + num;
+ }
+
+ if (vblk->vq->vq_ops->add_buf(vblk->vq, vblk->sg, out, in, vbr)) {
+ mempool_free(vbr, vblk->pool);
+ return false;
+ }
+
+ list_add_tail(&vbr->list, &vblk->reqs);
+ return true;
+}
+
+static void do_virtblk_request(struct request_queue *q)
+{
+ struct virtio_blk *vblk = NULL;
+ struct request *req;
+ unsigned int issued = 0;
+
+ while ((req = elv_next_request(q)) != NULL) {
+ vblk = req->rq_disk->private_data;
+ BUG_ON(req->nr_phys_segments > ARRAY_SIZE(vblk->sg));
+
+ /* If this request fails, stop queue and wait for something to
+ finish to restart it. */
+ if (!do_req(q, vblk, req)) {
+ blk_stop_queue(q);
+ break;
+ }
+ blkdev_dequeue_request(req);
+ issued++;
+ }
+
+ if (issued)
+ vblk->vq->vq_ops->kick(vblk->vq);
+}
+
+static int virtblk_ioctl(struct inode *inode, struct file *filp,
+ unsigned cmd, unsigned long data)
+{
+ return scsi_cmd_ioctl(filp, inode->i_bdev->bd_disk->queue,
+ inode->i_bdev->bd_disk, cmd,
+ (void __user *)data);
+}
+
+static struct block_device_operations virtblk_fops = {
+ .ioctl = virtblk_ioctl,
+ .owner = THIS_MODULE,
+};
+
+static int virtblk_probe(struct virtio_device *vdev)
+{
+ struct virtio_blk *vblk;
+ int err, major;
+ void *token;
+ unsigned int len;
+ u64 cap;
+ u32 v;
+
+ vdev->priv = vblk = kmalloc(sizeof(*vblk), GFP_KERNEL);
+ if (!vblk) {
+ err = -ENOMEM;
+ goto out;
+ }
+
+ INIT_LIST_HEAD(&vblk->reqs);
+ spin_lock_init(&vblk->lock);
+ vblk->vdev = vdev;
+
+ /* We expect one virtqueue, for output. */
+ vblk->vq = vdev->config->find_vq(vdev, blk_done);
+ if (IS_ERR(vblk->vq)) {
+ err = PTR_ERR(vblk->vq);
+ goto out_free_vblk;
+ }
+
+ vblk->pool = mempool_create_kmalloc_pool(1,sizeof(struct virtblk_req));
+ if (!vblk->pool) {
+ err = -ENOMEM;
+ goto out_free_vq;
+ }
+
+ major = register_blkdev(0, "virtblk");
+ if (major < 0) {
+ err = major;
+ goto out_mempool;
+ }
+
+ /* FIXME: How many partitions? How long is a piece of string? */
+ vblk->disk = alloc_disk(1 << 4);
+ if (!vblk->disk) {
+ err = -ENOMEM;
+ goto out_unregister_blkdev;
+ }
+
+ vblk->disk->queue = blk_init_queue(do_virtblk_request, &vblk->lock);
+ if (!vblk->disk->queue) {
+ err = -ENOMEM;
+ goto out_put_disk;
+ }
+
+ sprintf(vblk->disk->disk_name, "vd%c", virtblk_index++);
+ vblk->disk->major = major;
+ vblk->disk->first_minor = 0;
+ vblk->disk->private_data = vblk;
+ vblk->disk->fops = &virtblk_fops;
+
+ /* If barriers are supported, tell block layer that queue is ordered */
+ token = vdev->config->find(vdev, VIRTIO_CONFIG_BLK_F, &len);
+ if (virtio_use_bit(vdev, token, len, VIRTIO_BLK_F_BARRIER))
+ blk_queue_ordered(vblk->disk->queue, QUEUE_ORDERED_TAG, NULL);
+
+ err = virtio_config_val(vdev, VIRTIO_CONFIG_BLK_F_CAPACITY, &cap);
+ if (err) {
+ dev_err(&vdev->dev, "Bad/missing capacity in config\n");
+ goto out_put_disk;
+ }
+
+ /* If capacity is too big, truncate with warning. */
+ if ((sector_t)cap != cap) {
+ dev_warn(&vdev->dev, "Capacity %llu too large: truncating\n",
+ (unsigned long long)cap);
+ cap = (sector_t)-1;
+ }
+ set_capacity(vblk->disk, cap);
+
+ err = virtio_config_val(vdev, VIRTIO_CONFIG_BLK_F_SIZE_MAX, &v);
+ if (!err)
+ blk_queue_max_segment_size(vblk->disk->queue, v);
+ else if (err != -ENOENT) {
+ dev_err(&vdev->dev, "Bad SIZE_MAX in config\n");
+ goto out_put_disk;
+ }
+
+ err = virtio_config_val(vdev, VIRTIO_CONFIG_BLK_F_SEG_MAX, &v);
+ if (!err)
+ blk_queue_max_hw_segments(vblk->disk->queue, v);
+ else if (err != -ENOENT) {
+ dev_err(&vdev->dev, "Bad SEG_MAX in config\n");
+ goto out_put_disk;
+ }
+
+ add_disk(vblk->disk);
+ return 0;
+
+out_put_disk:
+ put_disk(vblk->disk);
+out_unregister_blkdev:
+ unregister_blkdev(major, "virtblk");
+out_mempool:
+ mempool_destroy(vblk->pool);
+out_free_vq:
+ vdev->config->del_vq(vblk->vq);
+out_free_vblk:
+ kfree(vblk);
+out:
+ return err;
+}
+
+static void virtblk_remove(struct virtio_device *vdev)
+{
+ struct virtio_blk *vblk = vdev->priv;
+ int major = vblk->disk->major;
+
+ BUG_ON(!list_empty(&vblk->reqs));
+ blk_cleanup_queue(vblk->disk->queue);
+ put_disk(vblk->disk);
+ unregister_blkdev(major, "virtblk");
+ mempool_destroy(vblk->pool);
+ kfree(vblk);
+}
+
+static struct virtio_device_id id_table[] = {
+ { VIRTIO_ID_BLOCK, VIRTIO_DEV_ANY_ID },
+ { 0 },
+};
+
+static struct virtio_driver virtio_blk = {
+ .driver.name = KBUILD_MODNAME,
+ .driver.owner = THIS_MODULE,
+ .id_table = id_table,
+ .probe = virtblk_probe,
+ .remove = __devexit_p(virtblk_remove),
+};
+
+static int __init init(void)
+{
+ return register_virtio_driver(&virtio_blk);
+}
+
+static void __exit fini(void)
+{
+ unregister_virtio_driver(&virtio_blk);
+}
+module_init(init);
+module_exit(fini);
+
+MODULE_DEVICE_TABLE(virtio, id_table);
+MODULE_DESCRIPTION("Virtio block driver");
+MODULE_LICENSE("GPL");
diff --git a/drivers/block/xsysace.c b/drivers/block/xsysace.c
index 9e7652dcde6..82effce97c5 100644
--- a/drivers/block/xsysace.c
+++ b/drivers/block/xsysace.c
@@ -390,8 +390,8 @@ static inline void ace_dump_mem(void *base, int len)
static void ace_dump_regs(struct ace_device *ace)
{
dev_info(ace->dev, " ctrl: %.8x seccnt/cmd: %.4x ver:%.4x\n"
- " status:%.8x mpu_lba:%.8x busmode:%4x\n"
- " error: %.8x cfg_lba:%.8x fatstat:%.4x\n",
+ KERN_INFO " status:%.8x mpu_lba:%.8x busmode:%4x\n"
+ KERN_INFO " error: %.8x cfg_lba:%.8x fatstat:%.4x\n",
ace_in32(ace, ACE_CTRL),
ace_in(ace, ACE_SECCNTCMD),
ace_in(ace, ACE_VERSION),