mirror of
https://github.com/xen-project/xen.git
synced 2026-10-28 02:01:24 +01:00
bitkeeper revision 1.91 (3e5a3727Dlhfakt5fPHI3hlx8R377A)
blkdev.h, xen_block.c: Sanity checking for blkdev ring arguments.
This commit is contained in:
1 parent
0c876caf68
commit
f4ab9b3bf4
2 files changed
+88
-30
No files matched your search
@@ -17,7 +17,7 @@
|
||||
#include <xeno/keyhandler.h>
|
||||
#include <xeno/interrupt.h>
|
||||
|
||||
#if 0
|
||||
#if 1
|
||||
#define DPRINTK(_f, _a...) printk( _f , ## _a )
|
||||
#else
|
||||
#define DPRINTK(_f, _a...) ((void)0)
|
||||
@@ -133,6 +133,21 @@ static void maybe_trigger_io_schedule(void)
|
||||
|
||||
static void end_block_io_op(struct buffer_head *bh, int uptodate)
|
||||
{
|
||||
struct pfn_info *page;
|
||||
unsigned long pfn;
|
||||
|
||||
for ( pfn = virt_to_phys(bh->b_data) >> PAGE_SHIFT;
|
||||
pfn < ((virt_to_phys(bh->b_data) + bh->b_size + PAGE_SIZE - 1) >>
|
||||
PAGE_SHIFT);
|
||||
pfn++ )
|
||||
{
|
||||
page = frame_table + pfn;
|
||||
if ( ((bh->b_state & (1 << BH_Read)) != 0) &&
|
||||
(put_page_type(page) == 0) )
|
||||
page->flags &= ~PG_type_mask;
|
||||
put_page_tot(page);
|
||||
}
|
||||
|
||||
atomic_dec(&nr_pending);
|
||||
make_response(bh->b_xen_domain, bh->b_xen_id, uptodate ? 0 : 1);
|
||||
|
||||
@@ -223,22 +238,66 @@ static void dispatch_rw_block_io(struct task_struct *p, int index)
|
||||
blk_ring_t *blk_ring = p->blk_ring_base;
|
||||
struct buffer_head *bh;
|
||||
int operation;
|
||||
|
||||
/*
|
||||
* check to make sure that the block request seems at least
|
||||
* a bit legitimate
|
||||
*/
|
||||
if ( (blk_ring->ring[index].req.block_size & (0x200 - 1)) != 0 )
|
||||
panic("error: dodgy block size: %d\n",
|
||||
blk_ring->ring[index].req.block_size);
|
||||
|
||||
if ( blk_ring->ring[index].req.buffer == NULL )
|
||||
panic("xen_block: bogus buffer from guestOS\n");
|
||||
unsigned short size;
|
||||
unsigned long buffer, pfn;
|
||||
struct pfn_info *page;
|
||||
|
||||
DPRINTK("req_cons: %d req_prod %d index: %d, op: %s\n",
|
||||
p->blk_req_cons, blk_ring->req_prod, index,
|
||||
(blk_ring->ring[index].req.operation == XEN_BLOCK_READ ?
|
||||
"read" : "write"));
|
||||
operation = (blk_ring->ring[index].req.operation == XEN_BLOCK_WRITE) ?
|
||||
WRITE : READ;
|
||||
|
||||
/* Sectors are 512 bytes. Make sure request size is a multiple. */
|
||||
size = blk_ring->ring[index].req.block_size;
|
||||
if ( (size == 0) || (size & (0x200 - 1)) != 0 )
|
||||
{
|
||||
DPRINTK("dodgy block size: %d\n",
|
||||
blk_ring->ring[index].req.block_size);
|
||||
goto bad_descriptor;
|
||||
}
|
||||
|
||||
/* Buffer address should be sector aligned. */
|
||||
buffer = (unsigned long)blk_ring->ring[index].req.buffer;
|
||||
if ( (buffer & (0x200 - 1)) != 0 )
|
||||
{
|
||||
DPRINTK("unaligned buffer %08lx\n", buffer);
|
||||
goto bad_descriptor;
|
||||
}
|
||||
|
||||
/* A request may span multiple page frames. Each must be checked. */
|
||||
for ( pfn = buffer >> PAGE_SHIFT;
|
||||
pfn < ((buffer + size + PAGE_SIZE - 1) >> PAGE_SHIFT);
|
||||
pfn++ )
|
||||
{
|
||||
/* Each frame must be within bounds of machine memory. */
|
||||
if ( pfn >= max_page )
|
||||
{
|
||||
DPRINTK("pfn out of range: %08lx\n", pfn);
|
||||
goto bad_descriptor;
|
||||
}
|
||||
|
||||
page = frame_table + pfn;
|
||||
|
||||
/* Each frame must belong to the requesting domain. */
|
||||
if ( (page->flags & PG_domain_mask) != p->domain )
|
||||
{
|
||||
DPRINTK("bad domain: expected %d, got %ld\n",
|
||||
p->domain, page->flags & PG_domain_mask);
|
||||
goto bad_descriptor;
|
||||
}
|
||||
|
||||
/* If reading into the frame, the frame must be writeable. */
|
||||
if ( operation == READ )
|
||||
{
|
||||
if ( (page->flags & PG_type_mask) != PGT_writeable_page )
|
||||
{
|
||||
DPRINTK("non-writeable page passed for block read\n");
|
||||
goto bad_descriptor;
|
||||
}
|
||||
get_page_type(page);
|
||||
}
|
||||
|
||||
/* Xen holds a frame reference until the operation is complete. */
|
||||
get_page_tot(page);
|
||||
}
|
||||
|
||||
atomic_inc(&nr_pending);
|
||||
bh = kmem_cache_alloc(buffer_head_cachep, GFP_KERNEL);
|
||||
@@ -248,11 +307,10 @@ static void dispatch_rw_block_io(struct task_struct *p, int index)
|
||||
memset (bh, 0, sizeof (struct buffer_head));
|
||||
|
||||
bh->b_blocknr = blk_ring->ring[index].req.block_number;
|
||||
bh->b_size = blk_ring->ring[index].req.block_size;
|
||||
bh->b_size = size;
|
||||
bh->b_dev = blk_ring->ring[index].req.device;
|
||||
bh->b_rsector = blk_ring->ring[index].req.sector_number;
|
||||
bh->b_data = phys_to_virt((unsigned long)
|
||||
blk_ring->ring[index].req.buffer);
|
||||
bh->b_data = phys_to_virt(buffer);
|
||||
bh->b_count.counter = 1;
|
||||
bh->b_end_io = end_block_io_op;
|
||||
|
||||
@@ -260,20 +318,23 @@ static void dispatch_rw_block_io(struct task_struct *p, int index)
|
||||
bh->b_xen_domain = p;
|
||||
bh->b_xen_id = blk_ring->ring[index].req.id;
|
||||
|
||||
if ( blk_ring->ring[index].req.operation == XEN_BLOCK_WRITE )
|
||||
if ( operation == WRITE )
|
||||
{
|
||||
bh->b_state = ((1 << BH_JBD) | (1 << BH_Mapped) | (1 << BH_Req) |
|
||||
(1 << BH_Dirty) | (1 << BH_Uptodate));
|
||||
operation = WRITE;
|
||||
bh->b_state = (1 << BH_JBD) | (1 << BH_Mapped) | (1 << BH_Req) |
|
||||
(1 << BH_Dirty) | (1 << BH_Uptodate) | (1 << BH_Write);
|
||||
}
|
||||
else
|
||||
{
|
||||
bh->b_state = (1 << BH_Mapped);
|
||||
operation = READ;
|
||||
bh->b_state = (1 << BH_Mapped) | (1 << BH_Read);
|
||||
}
|
||||
|
||||
/* Dispatch a single request. We'll flush it to disc later. */
|
||||
ll_rw_block(operation, 1, &bh);
|
||||
return;
|
||||
|
||||
bad_descriptor:
|
||||
make_response(p, blk_ring->ring[index].req.id, 1);
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -45,7 +45,6 @@ struct block_device_operations {
|
||||
};
|
||||
|
||||
|
||||
/*** BUFFER_HEAD stuff: maybe this will die, or live on in reduced form */
|
||||
enum bh_state_bits {
|
||||
BH_Uptodate, /* 1 if the buffer contains valid data */
|
||||
BH_Dirty, /* 1 if the buffer is dirty */
|
||||
@@ -57,10 +56,8 @@ enum bh_state_bits {
|
||||
BH_Wait_IO, /* 1 if we should write out this buffer */
|
||||
BH_Launder, /* 1 if we can throttle on this buffer */
|
||||
BH_JBD, /* 1 if it has an attached journal_head */
|
||||
|
||||
BH_PrivateStart,/* not a state bit, but the first bit available
|
||||
* for private allocation by other entities
|
||||
*/
|
||||
BH_Read, /* 1 if request is a read from disc */
|
||||
BH_Write /* 1 if request is a write to disc */
|
||||
};
|
||||
|
||||
struct buffer_head {
|
||||
|
||||