mirror of
https://github.com/xen-project/xen.git
synced 2026-10-28 02:01:24 +01:00
bitkeeper revision 1.116 (3e6bd5fanPF3nYb2uWLHO7p0PnxDhg)
xl_block.c, blkdev.h, xen_block.c: Improved error handling for blkdev data accesses. Added sanity checking for read requests -- test if buffer modified.
This commit is contained in:
1 parent
6607af3a46
commit
de64d4ffa1
3 files changed
+35
-4
No files matched your search
@@ -17,8 +17,10 @@
|
||||
#include <xeno/keyhandler.h>
|
||||
#include <xeno/interrupt.h>
|
||||
#include <xeno/segment.h>
|
||||
#include <asm/domain_page.h> /* TEST_READ_VALIDITY */
|
||||
|
||||
#if 1
|
||||
#define TEST_READ_VALIDITY
|
||||
#define DPRINTK(_f, _a...) printk( _f , ## _a )
|
||||
#else
|
||||
#define DPRINTK(_f, _a...) ((void)0)
|
||||
@@ -198,6 +200,23 @@ static void end_block_io_op(struct buffer_head *bh, int uptodate)
|
||||
unsigned long flags;
|
||||
pending_req_t *pending_req = bh->pending_req;
|
||||
|
||||
/* An error fails the entire request. */
|
||||
if ( !uptodate )
|
||||
{
|
||||
DPRINTK("Buffer not up-to-date at end of operation\n");
|
||||
pending_req->status = 1;
|
||||
}
|
||||
#ifdef TEST_READ_VALIDITY
|
||||
else
|
||||
{
|
||||
unsigned long *buff = map_domain_mem(virt_to_phys(bh->b_data));
|
||||
if ( (buff[ 0] == 0xdeadbeef) &&
|
||||
(buff[127] == 0xdeadbeef) )
|
||||
printk("A really fucked buffer at %ld\n", bh->b_rsector);
|
||||
unmap_domain_mem(buff);
|
||||
}
|
||||
#endif
|
||||
|
||||
unlock_buffer(pending_req->domain,
|
||||
virt_to_phys(bh->b_data),
|
||||
bh->b_size,
|
||||
@@ -206,7 +225,7 @@ static void end_block_io_op(struct buffer_head *bh, int uptodate)
|
||||
if ( atomic_dec_and_test(&pending_req->pendcnt) )
|
||||
{
|
||||
make_response(pending_req->domain, pending_req->id,
|
||||
pending_req->operation, uptodate ? 0 : 1);
|
||||
pending_req->operation, pending_req->status);
|
||||
spin_lock_irqsave(&pend_prod_lock, flags);
|
||||
pending_ring[pending_prod] = pending_req - pending_reqs;
|
||||
PENDREQ_IDX_INC(pending_prod);
|
||||
@@ -572,6 +591,7 @@ static void dispatch_rw_block_io(struct task_struct *p, int index)
|
||||
pending_req->domain = p;
|
||||
pending_req->id = req->id;
|
||||
pending_req->operation = operation;
|
||||
pending_req->status = 0;
|
||||
atomic_set(&pending_req->pendcnt, nr_psegs);
|
||||
|
||||
/* Now we pass each segment down to the real blkdev layer. */
|
||||
@@ -595,6 +615,12 @@ static void dispatch_rw_block_io(struct task_struct *p, int index)
|
||||
}
|
||||
else
|
||||
{
|
||||
#ifdef TEST_READ_VALIDITY
|
||||
unsigned long *buff = map_domain_mem(phys_seg[i].buffer);
|
||||
buff[ 0] = 0xdeadbeef;
|
||||
buff[127] = 0xdeadbeef;
|
||||
unmap_domain_mem(buff);
|
||||
#endif
|
||||
bh->b_state = (1 << BH_Mapped) | (1 << BH_Read);
|
||||
}
|
||||
|
||||
|
||||
@@ -20,6 +20,7 @@ typedef struct {
|
||||
unsigned long id;
|
||||
atomic_t pendcnt;
|
||||
unsigned short operation;
|
||||
unsigned short status;
|
||||
} pending_req_t;
|
||||
|
||||
extern kdev_t xendev_to_physdev(unsigned short xendev);
|
||||
|
||||
@@ -440,13 +440,15 @@ static void xlblk_response_int(int irq, void *dev_id, struct pt_regs *ptregs)
|
||||
{
|
||||
case XEN_BLOCK_READ:
|
||||
case XEN_BLOCK_WRITE:
|
||||
if ( bret->status )
|
||||
printk(KERN_ALERT "Bad return from blkdev data request\n");
|
||||
for ( bh = (struct buffer_head *)bret->id;
|
||||
bh != NULL;
|
||||
bh = next_bh )
|
||||
{
|
||||
next_bh = bh->b_reqnext;
|
||||
bh->b_reqnext = NULL;
|
||||
bh->b_end_io(bh, 1);
|
||||
bh->b_end_io(bh, !bret->status);
|
||||
}
|
||||
break;
|
||||
|
||||
@@ -454,6 +456,8 @@ static void xlblk_response_int(int irq, void *dev_id, struct pt_regs *ptregs)
|
||||
case XEN_BLOCK_SEG_DELETE:
|
||||
case XEN_BLOCK_PROBE_SEG:
|
||||
case XEN_BLOCK_PROBE_BLK:
|
||||
if ( bret->status )
|
||||
printk(KERN_ALERT "Bad return from blkdev control request\n");
|
||||
xlblk_control_msg_pending = 0;
|
||||
break;
|
||||
|
||||
@@ -488,7 +492,7 @@ int xenolinux_control_msg(int operation, char *buffer, int size)
|
||||
char *aligned_buf;
|
||||
|
||||
/* We copy from an aligned buffer, as interface needs sector alignment. */
|
||||
aligned_buf = get_free_page(GFP_KERNEL);
|
||||
aligned_buf = (char *)get_free_page(GFP_KERNEL);
|
||||
if ( aligned_buf == NULL ) BUG();
|
||||
|
||||
xlblk_control_msg_pending = 1;
|
||||
@@ -501,7 +505,7 @@ int xenolinux_control_msg(int operation, char *buffer, int size)
|
||||
while ( xlblk_control_msg_pending ) barrier();
|
||||
|
||||
memcpy(buffer, aligned_buf, size);
|
||||
free_page(aligned_buf);
|
||||
free_page((unsigned long)aligned_buf);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||