bitkeeper revision 1.538 (3f9fec6ak_pRRMuf7OrN5fWEXAx52A)

manual merge
This commit is contained in:
smh22@labyrinth.cl.cam.ac.uk committed 2003-10-29 16:35:54 +00:00
commit 5fefd10f16
24 files changed
+1020 -1424

No files matched your search

+4 -8
View File
@@ -260,8 +260,7 @@
3ddb79beNQVrdGyoI4njXhgAjD6a4A xen/drivers/block/genhd.c
3ddb79beyWwLRP_BiM2t1JKgr_plEw xen/drivers/block/ll_rw_blk.c
3e4a8cb7RhubVgsPwO7cK0pgAN8WCQ xen/drivers/block/xen_block.c
3f045882spujO81dMl-fYWGiZ8WcPw xen/drivers/block/xen_physdisk.c
3e5d129asHNyZOjBKTkqs-9AFzxemA xen/drivers/block/xen_segment.c
3e5d129asHNyZOjBKTkqs-9AFzxemA xen/drivers/block/xen_vbd.c
3e9c248afxxsnAzIt2na7Ej24yNFzg xen/drivers/cdrom/Makefile
3e9c248ajUkn2W3n4vgm72Hp2ftZ8A xen/drivers/cdrom/cdrom.c
3e4a8cb7alzQCDKS7MlioPoHBKYkdQ xen/drivers/char/Makefile
@@ -466,7 +465,7 @@
3ddb79c25UE59iu4JJcbRalx95mvcg xen/include/hypervisor-ifs/hypervisor-if.h
3ead095dE_VF-QA88rl_5cWYRWtRVQ xen/include/hypervisor-ifs/kbd.h
3ddb79c2oRPrzClk3zbTkRHlpumzKA xen/include/hypervisor-ifs/network.h
3f0d22cbroqp_BkoDPwkfRJhaw1LiQ xen/include/hypervisor-ifs/segment.h
3f0d22cbroqp_BkoDPwkfRJhaw1LiQ xen/include/hypervisor-ifs/vbd.h
3ddb79c4qbCoOFHrv9sCGshbWzBVlQ xen/include/scsi/scsi.h
3ddb79c4R4iVwqIIeychVQYmIH4FUg xen/include/scsi/scsi_ioctl.h
3ddb79c4yw_mfd4Uikn3v_IOPRpa1Q xen/include/scsi/scsicam.h
@@ -476,7 +475,6 @@
3ddb79c0nTsjSpVK4ZVTI9WwN24xtQ xen/include/xeno/blk.h
3ddb79c0dVhTHLsv6CPTf4baKix4mA xen/include/xeno/blkdev.h
3ddb79c18ePBgitnOs7GiOCFilODVw xen/include/xeno/blkpg.h
3ddb79c2SisDOHDyTeK5-MV3m7pNbA xen/include/xeno/block.h
3ddb79c1oOjpQbp68MW7yiUpoi-S-w xen/include/xeno/brlock.h
3ddb79c1x7Ie3kifu7dQRx8y7HVyvA xen/include/xeno/byteorder/big_endian.h
3ddb79c1qFXOEX1eD0yXJ_gsGkUt8w xen/include/xeno/byteorder/generic.h
@@ -529,11 +527,9 @@
3ddb79c0MOVXq8qZDQRGb6z64_xAwg xen/include/xeno/pci_ids.h
3e54c38dlSCVdyVM4PKcrSfzLLxWUQ xen/include/xeno/perfc.h
3e54c38de9SUSYSAwxDf_DwkpAnQFA xen/include/xeno/perfc_defn.h
3f055a3dwldYR102YcSuBaxIf9t3Jw xen/include/xeno/physdisk.h
3ddb79c04nQVR3EYM5L4zxDV_MCo1g xen/include/xeno/prefetch.h
3e4540ccU1sgCx8seIMGlahmMfv7yQ xen/include/xeno/reboot.h
3ddb79c0LzqqS0LhAQ50ekgj4oGl7Q xen/include/xeno/sched.h
3e5d129a2bbGTpVSZFN_mAnbm97ixw xen/include/xeno/segment.h
3ddb79c0VDeD-Oft5eNfMneTU3D1dQ xen/include/xeno/skbuff.h
3ddb79c14dXIhP7C2ahnoD08K90G_w xen/include/xeno/slab.h
3ddb79c09xbS-xxfKxuV3JETIhBzmg xen/include/xeno/smp.h
@@ -546,6 +542,7 @@
3ddb79c2_m8lT9jDKse_tePj7zcnNQ xen/include/xeno/timex.h
3ddb79c2e2C14HkndNEJlYwXaPrF5A xen/include/xeno/tqueue.h
3ddb79c1-kVvF8cVa0k3ZHDdBMj01Q xen/include/xeno/types.h
3f055a3dwldYR102YcSuBaxIf9t3Jw xen/include/xeno/vbd.h
3e8827bdaqPeZAWGVOwswgY9bWSx4g xen/include/xeno/version.h
3ddb79c2Ae5KpzhC9LCYG7mP_Vi4Aw xen/include/xeno/vif.h
3ddb79c4YQCQ6r0xNLLu0jfbM7pVmA xen/net/Makefile
@@ -575,8 +572,7 @@
3e67f822FOPwqHiaRKbrskgWgoNL5g xenolinux-2.4.22-sparse/arch/xeno/drivers/block/xl_block.h
3e677190SjkzJIvFifRVeYpIZOCtYA xenolinux-2.4.22-sparse/arch/xeno/drivers/block/xl_ide.c
3e677193nOKKTLJzcAu4SYdbZaia8g xenolinux-2.4.22-sparse/arch/xeno/drivers/block/xl_scsi.c
3e676eb5RXnHzSHgA1BvM0B1aIm4qg xenolinux-2.4.22-sparse/arch/xeno/drivers/block/xl_segment.c
3e5d129aDldt6geU2-2SzBae34sQzg xenolinux-2.4.22-sparse/arch/xeno/drivers/block/xl_segment_proc.c
3e676eb5RXnHzSHgA1BvM0B1aIm4qg xenolinux-2.4.22-sparse/arch/xeno/drivers/block/xl_vbd.c
3e5a4e65G3e2s0ghPMgiJ-gBTUJ0uQ xenolinux-2.4.22-sparse/arch/xeno/drivers/console/Makefile
3e5a4e651TH-SXHoufurnWjgl5bfOA xenolinux-2.4.22-sparse/arch/xeno/drivers/console/console.c
3e5a4e656nfFISThfbyXQOA6HN6YHw xenolinux-2.4.22-sparse/arch/xeno/drivers/dom0/Makefile
+1
View File
@@ -27,6 +27,7 @@ typedef signed long long s64;
#include <asm-xeno/proc_cmd.h>
#include <hypervisor-ifs/hypervisor-if.h>
#include <hypervisor-ifs/dom0_ops.h>
#include <hypervisor-ifs/vbd.h>
#define ERROR(_m) \
fprintf(stderr, "ERROR: %s\n", (_m))
+3 -4
View File
@@ -16,8 +16,7 @@
#include <asm/msr.h>
#include <xeno/blkdev.h>
#include <xeno/console.h>
#include <hypervisor-ifs/block.h>
#include <xeno/physdisk.h>
#include <xeno/vbd.h>
/*
* NB. No ring-3 access in initial guestOS pagetables. Note that we allow
@@ -144,8 +143,8 @@ void __kill_domain(struct task_struct *p)
unlink_blkdev_info(p);
for ( i = 0; i < XEN_MAX_SEGMENTS; i++ )
xen_segment_delete(p, i);
for ( i = 0; i < XEN_MAX_VBDS; i++ )
xen_vbd_delete(p, i);
for ( i = 0; i < MAX_DOMAIN_VIFS; i++ )
unlink_net_vif(p->net_vif_list[i]);
+70 -117
View File
@@ -13,12 +13,12 @@
#include <hypervisor-ifs/block.h>
#include <hypervisor-ifs/hypervisor-if.h>
#include <asm-i386/io.h>
#include <asm/domain_page.h>
#include <xeno/spinlock.h>
#include <xeno/keyhandler.h>
#include <xeno/interrupt.h>
#include <xeno/segment.h>
#include <xeno/vbd.h>
#include <xeno/slab.h>
#include <xeno/physdisk.h>
#if 0
#define DPRINTK(_f, _a...) printk( _f , ## _a )
@@ -100,12 +100,10 @@ static void unlock_buffer(struct task_struct *p,
static void io_schedule(unsigned long unused);
static int do_block_io_op_domain(struct task_struct *p, int max_to_do);
static void dispatch_rw_block_io(struct task_struct *p, int index);
static void dispatch_probe_blk(struct task_struct *p, int index);
static void dispatch_probe_seg(struct task_struct *p, int index);
static void dispatch_probe_seg_all(struct task_struct *p, int index);
static void dispatch_probe(struct task_struct *p, int index);
static void dispatch_debug_block_io(struct task_struct *p, int index);
static void dispatch_create_segment(struct task_struct *p, int index);
static void dispatch_delete_segment(struct task_struct *p, int index);
static void dispatch_create_vbd(struct task_struct *p, int index);
static void dispatch_delete_vbd(struct task_struct *p, int index);
static void dispatch_grant_physdev(struct task_struct *p, int index);
static void dispatch_probe_physdev(struct task_struct *p, int index);
static void make_response(struct task_struct *p, unsigned long id,
@@ -236,29 +234,41 @@ static void end_block_io_op(struct buffer_head *bh, int uptodate)
}
long vbd_attach(vbd_attach_t *info)
{
printk("vbd_attach called!!!\n");
return -ENOSYS;
}
/******************************************************************
* GUEST-OS SYSCALL -- Indicates there are requests outstanding.
*/
/* ----[ Syscall Interface ]------------------------------------------------*/
long do_block_io_op(unsigned int op)
long do_block_io_op(block_io_op_t *u_block_io_op)
{
long ret = 0;
block_io_op_t op;
switch ( op )
{
case BLKOP_PUSH_BUFFERS:
add_to_blkdev_list_tail(current);
maybe_trigger_io_schedule();
break;
if (copy_from_user(&op, u_block_io_op, sizeof(op)))
return -EFAULT;
case BLKOP_FLUSH_BUFFERS:
break;
switch (op.cmd) {
case BLOCK_IO_OP_SIGNAL:
/* simply indicates there're reqs outstanding => add current to list */
add_to_blkdev_list_tail(current);
maybe_trigger_io_schedule();
break;
case BLOCK_IO_OP_ATTACH_VBD:
/* attach a VBD to a given domain; caller must be privileged */
if(!IS_PRIV(current))
return -EPERM;
ret = vbd_attach(&op.u.attach_info);
break;
default:
ret = -ENOSYS;
}
default:
ret = -EINVAL;
break;
}
return ret;
}
@@ -390,28 +400,20 @@ static int do_block_io_op_domain(struct task_struct *p, int max_to_do)
dispatch_rw_block_io(p, i);
break;
case XEN_BLOCK_PROBE_BLK:
dispatch_probe_blk(p, i);
break;
case XEN_BLOCK_PROBE_SEG:
dispatch_probe_seg(p, i);
break;
case XEN_BLOCK_PROBE_SEG_ALL:
dispatch_probe_seg_all(p, i);
case XEN_BLOCK_PROBE:
dispatch_probe(p, i);
break;
case XEN_BLOCK_DEBUG:
dispatch_debug_block_io(p, i);
break;
case XEN_BLOCK_SEG_CREATE:
dispatch_create_segment(p, i);
case XEN_BLOCK_VBD_CREATE:
dispatch_create_vbd(p, i);
break;
case XEN_BLOCK_SEG_DELETE:
dispatch_delete_segment(p, i);
case XEN_BLOCK_VBD_DELETE:
dispatch_delete_vbd(p, i);
break;
case XEN_BLOCK_PHYSDEV_GRANT:
@@ -506,7 +508,7 @@ static void dispatch_grant_physdev(struct task_struct *p, int index)
XEN_BLOCK_PHYSDEV_GRANT, result);
}
static void dispatch_create_segment(struct task_struct *p, int index)
static void dispatch_create_vbd(struct task_struct *p, int index)
{
blk_ring_t *blk_ring = p->blk_ring_base;
unsigned long flags, buffer;
@@ -515,7 +517,7 @@ static void dispatch_create_segment(struct task_struct *p, int index)
if ( p->domain != 0 )
{
DPRINTK("dispatch_create_segment called by dom%d\n", p->domain);
DPRINTK("dispatch_create_vbd called by dom%d\n", p->domain);
result = 1;
goto out;
}
@@ -525,7 +527,7 @@ static void dispatch_create_segment(struct task_struct *p, int index)
spin_lock_irqsave(&p->page_lock, flags);
if ( !__buffer_is_valid(p, buffer, sizeof(xv_disk_t), 1) )
{
DPRINTK("Bad buffer in dispatch_create_segment\n");
DPRINTK("Bad buffer in dispatch_create_vbd\n");
spin_unlock_irqrestore(&p->page_lock, flags);
result = 1;
goto out;
@@ -534,24 +536,25 @@ static void dispatch_create_segment(struct task_struct *p, int index)
spin_unlock_irqrestore(&p->page_lock, flags);
xvd = phys_to_virt(buffer);
result = xen_segment_create(xvd);
result = xen_vbd_create(xvd);
unlock_buffer(p, buffer, sizeof(xv_disk_t), 1);
out:
make_response(p, blk_ring->ring[index].req.id,
XEN_BLOCK_SEG_CREATE, result);
XEN_BLOCK_VBD_CREATE, result);
}
static void dispatch_delete_segment(struct task_struct *p, int index)
static void dispatch_delete_vbd(struct task_struct *p, int index)
{
DPRINTK("dispatch_delete_segment: unimplemented\n");
DPRINTK("dispatch_delete_vbd: unimplemented\n");
}
static void dispatch_probe_blk(struct task_struct *p, int index)
static void dispatch_probe(struct task_struct *p, int index)
{
extern void ide_probe_devices(xen_disk_info_t *xdi);
extern void scsi_probe_devices(xen_disk_info_t *xdi);
extern void vbd_probe_devices(xen_disk_info_t *xdi, struct task_struct *p);
blk_ring_t *blk_ring = p->blk_ring_base;
xen_disk_info_t *xdi;
@@ -568,80 +571,30 @@ static void dispatch_probe_blk(struct task_struct *p, int index)
rc = 1;
goto out;
}
__lock_buffer(buffer, sizeof(xen_disk_info_t), 1);
spin_unlock_irqrestore(&p->page_lock, flags);
xdi = phys_to_virt(buffer);
ide_probe_devices(xdi);
scsi_probe_devices(xdi);
/*
** XXX SMH: all three of the below probe functions /append/ their
** info to the xdi array; i.e. they assume that all earlier slots
** are correctly filled, and that xdi->count points to the first
** free entry in the array. All kinda gross but it'll do for now.
*/
xdi = map_domain_mem(buffer);
xdi->count = 0;
if(IS_PRIV(p)) {
/* privilege domains always gets access to the 'real' devices */
ide_probe_devices(xdi);
scsi_probe_devices(xdi);
}
vbd_probe_devices(xdi, p);
unmap_domain_mem(xdi);
unlock_buffer(p, buffer, sizeof(xen_disk_info_t), 1);
out:
make_response(p, blk_ring->ring[index].req.id, XEN_BLOCK_PROBE_BLK, rc);
}
static void dispatch_probe_seg(struct task_struct *p,
int index)
{
extern void xen_segment_probe(struct task_struct *, xen_disk_info_t *);
blk_ring_t *blk_ring = p->blk_ring_base;
xen_disk_info_t *xdi;
unsigned long flags, buffer;
int rc = 0;
buffer = blk_ring->ring[index].req.buffer_and_sects[0] & ~0x1FF;
spin_lock_irqsave(&p->page_lock, flags);
if ( !__buffer_is_valid(p, buffer, sizeof(xen_disk_info_t), 1) )
{
DPRINTK("Bad buffer in dispatch_probe_seg\n");
spin_unlock_irqrestore(&p->page_lock, flags);
rc = 1;
goto out;
}
__lock_buffer(buffer, sizeof(xen_disk_info_t), 1);
spin_unlock_irqrestore(&p->page_lock, flags);
xdi = phys_to_virt(buffer);
xen_segment_probe(p, xdi);
unlock_buffer(p, buffer, sizeof(xen_disk_info_t), 1);
out:
make_response(p, blk_ring->ring[index].req.id, XEN_BLOCK_PROBE_SEG, rc);
}
static void dispatch_probe_seg_all(struct task_struct *p, int index)
{
extern void xen_segment_probe_all(xen_segment_info_t *);
blk_ring_t *blk_ring = p->blk_ring_base;
xen_segment_info_t *xsi;
unsigned long flags, buffer;
int rc = 0;
buffer = blk_ring->ring[index].req.buffer_and_sects[0] & ~0x1FF;
spin_lock_irqsave(&p->page_lock, flags);
if ( !__buffer_is_valid(p, buffer, sizeof(xen_segment_info_t), 1) )
{
DPRINTK("Bad buffer in dispatch_probe_seg_all\n");
spin_unlock_irqrestore(&p->page_lock, flags);
rc = 1;
goto out;
}
__lock_buffer(buffer, sizeof(xen_segment_info_t), 1);
spin_unlock_irqrestore(&p->page_lock, flags);
xsi = phys_to_virt(buffer);
xen_segment_probe_all(xsi);
unlock_buffer(p, buffer, sizeof(xen_segment_info_t), 1);
out:
make_response(p, blk_ring->ring[index].req.id, XEN_BLOCK_PROBE_SEG_ALL, rc);
make_response(p, blk_ring->ring[index].req.id, XEN_BLOCK_PROBE, rc);
}
static void dispatch_rw_block_io(struct task_struct *p, int index)
@@ -695,14 +648,14 @@ static void dispatch_rw_block_io(struct task_struct *p, int index)
/* Get the physical device and block index. */
if ( (req->device & XENDEV_TYPE_MASK) == XENDEV_VIRTUAL )
{
new_segs = xen_segment_map_request(
new_segs = xen_vbd_map_request(
&phys_seg[nr_psegs], p, operation,
req->device,
req->sector_number + tot_sects,
buffer, nr_sects);
if ( new_segs <= 0 )
{
DPRINTK("bogus xen_segment_map_request\n");
DPRINTK("bogus xen_vbd_map_request\n");
goto bad_descriptor;
}
}
@@ -876,10 +829,10 @@ void init_blkdev_info(struct task_struct *p)
SHARE_PFN_WITH_DOMAIN(virt_to_page(p->blk_ring_base), p->domain);
p->blkdev_list.next = NULL;
memset(p->segment_list, 0, sizeof(p->segment_list));
memset(p->vbd_list, 0, sizeof(p->vbd_list));
/* Get any previously created segments. */
xen_refresh_segment_list(p);
xen_refresh_vbd_list(p);
}
/* End-of-day teardown for a domain. */
@@ -920,7 +873,7 @@ void initialize_block_io ()
"buffer_head_cache", sizeof(struct buffer_head),
0, SLAB_HWCACHE_ALIGN, NULL, NULL);
xen_segment_initialize();
xen_vbd_initialize();
add_key_handler('b', dump_blockq, "dump xen ide blkdev statistics");
}
-277
View File
@@ -1,277 +0,0 @@
#include <xeno/sched.h>
#include <xeno/list.h>
#include <xeno/blkdev.h>
#include <xeno/sched.h>
#include <xeno/slab.h>
#include <asm/domain_page.h>
#include <asm/io.h>
#include <xeno/segment.h>
#include <xeno/physdisk.h>
#define MAX(a,b) ((a) > (b) ? (a) : (b))
#if 0
#define DPRINTK printk
#else
#define DPRINTK(...)
#endif
/* The idea is that, for each sector of each disk, each domain has two
bits, saying whether they can read the sector or write it. That
would take too much memory, so instead each process has a list of
(device, start, end, mode) quads which say what it has access to,
and we fake the logical view on top of that. */
struct physdisk_ace {
struct list_head list;
unsigned short device;
unsigned short partition;
unsigned long start_sect;
unsigned long n_sectors;
int mode;
};
/* Operation is a blkdev constant i.e. READ, WRITE, ... */
/* Must be called with p->physdev_lock held. */
static struct physdisk_ace *find_ace(const struct task_struct *p,
unsigned short dev,
unsigned long sect, int operation)
{
struct list_head *cur_ace_head;
struct physdisk_ace *cur_ace;
list_for_each(cur_ace_head, &p->physdisk_aces)
{
cur_ace = list_entry(cur_ace_head, struct physdisk_ace, list);
DPRINTK("Is [%lx, %lx) good for %lx?\n",
cur_ace->start_sect,
cur_ace->start_sect + cur_ace->n_sectors, sect);
if ( (sect >= cur_ace->start_sect) &&
(sect < (cur_ace->start_sect + cur_ace->n_sectors)) &&
(dev == cur_ace->device) &&
(((operation == READ) && (cur_ace->mode & PHYSDISK_MODE_R)) ||
((operation == WRITE) && (cur_ace->mode & PHYSDISK_MODE_W))) )
return cur_ace;
}
return NULL;
}
/* Hold the lock on entry, it remains held on exit. */
static void xen_physdisk_revoke_access(unsigned short dev,
unsigned long start_sect,
unsigned long n_sectors,
struct task_struct *p)
{
/* Find every ace which intersects [start_sect, start_sect +
n_sectors] and either remove it completely or truncate it
down. */
struct list_head *cur_ace_head;
struct physdisk_ace *cur_ace, *new_ace;
unsigned long kill_zone_end, ace_end;
kill_zone_end = start_sect + n_sectors;
list_for_each(cur_ace_head, &p->physdisk_aces)
{
cur_ace = list_entry(cur_ace_head, struct physdisk_ace, list);
ace_end = cur_ace->start_sect + cur_ace->n_sectors;
if ( (cur_ace->start_sect >= kill_zone_end) ||
(ace_end <= start_sect) ||
(cur_ace->device != dev) )
continue;
DPRINTK("Killing ace [%lx, %lx) against kill zone [%lx, %lx)\n",
cur_ace->start_sect, ace_end, start_sect, kill_zone_end);
if ( (cur_ace->start_sect >= start_sect) &&
(ace_end <= kill_zone_end) )
{
/* ace entirely within kill zone -> kill it */
list_del(cur_ace_head);
cur_ace_head = cur_ace_head->prev;
kfree(cur_ace);
}
else if ( ace_end <= kill_zone_end )
{
/* ace start before kill start, ace end in kill zone,
move ace end. */
cur_ace->n_sectors = start_sect - cur_ace->start_sect;
}
else if ( cur_ace->start_sect >= start_sect )
{
/* ace start after kill start, ace end outside kill zone,
move ace start. */
cur_ace->start_sect = kill_zone_end;
cur_ace->n_sectors = ace_end - cur_ace->start_sect;
}
else
{
/* The fun one: the ace entirely includes the kill zone. */
/* Cut the current ace down to just the bit before the kzone,
create a new ace for the bit just after it. */
new_ace = kmalloc(sizeof(*cur_ace), GFP_KERNEL);
new_ace->device = dev;
new_ace->start_sect = kill_zone_end;
new_ace->n_sectors = ace_end - kill_zone_end;
new_ace->mode = cur_ace->mode;
cur_ace->n_sectors = start_sect - cur_ace->start_sect;
list_add(&new_ace->list, cur_ace_head);
}
}
}
/* Hold the lock on entry, it remains held on exit. */
static int xen_physdisk_grant_access(unsigned short dev,
unsigned short partition,
unsigned long start_sect,
unsigned long n_sectors,
int mode, struct task_struct *p)
{
struct physdisk_ace *cur_ace;
/* Make sure it won't overlap with any existing ACEs. */
/* XXX this isn't quite right if the domain already has read access
and we try to grant write access, or vice versa. */
xen_physdisk_revoke_access(dev, start_sect, n_sectors, p);
if ( mode )
{
cur_ace = kmalloc(sizeof(*cur_ace), GFP_KERNEL);
cur_ace->device = dev;
cur_ace->start_sect = start_sect;
cur_ace->n_sectors = n_sectors;
cur_ace->mode = mode;
cur_ace->partition = partition;
list_add_tail(&cur_ace->list, &p->physdisk_aces);
}
return 0;
}
static void xen_physdisk_probe_access(physdisk_probebuf_t * buf,
struct task_struct *p)
{
int n_aces;
struct list_head *cur_ace_head;
struct physdisk_ace *cur_ace;
int x = 0;
n_aces = 0;
list_for_each(cur_ace_head, &p->physdisk_aces)
{
x++;
if ( x >= buf->start_ind )
{
cur_ace = list_entry(cur_ace_head, struct physdisk_ace, list);
buf->entries[n_aces].device = cur_ace->device;
buf->entries[n_aces].partition = cur_ace->partition;
buf->entries[n_aces].start_sect = cur_ace->start_sect;
buf->entries[n_aces].n_sectors = cur_ace->n_sectors;
buf->entries[n_aces].mode = cur_ace->mode;
n_aces++;
}
}
buf->n_aces = n_aces;
}
int xen_physdisk_grant(xp_disk_t * xpd_in)
{
struct task_struct *p = current;
xp_disk_t *xpd = map_domain_mem(virt_to_phys(xpd_in));
int res;
p = find_domain_by_id(xpd->domain);
if ( p == NULL )
{
DPRINTK("Bad domain!\n");
res = 1;
goto out;
}
spin_lock(&p->physdev_lock);
res = xen_physdisk_grant_access(xpd->device,
xpd->partition,
xpd->start_sect,
xpd->n_sectors, xpd->mode, p);
spin_unlock(&p->physdev_lock);
put_task_struct(p);
out:
unmap_domain_mem(xpd);
return res;
}
int xen_physdisk_probe(struct task_struct *requesting_domain,
physdisk_probebuf_t * buf_in)
{
struct task_struct *p;
physdisk_probebuf_t *buf = map_domain_mem(virt_to_phys(buf_in));
int res;
if ( (requesting_domain->domain != 0) &&
(requesting_domain->domain != buf->domain) )
{
res = 1;
goto out;
}
p = find_domain_by_id(buf->domain);
if ( p == NULL )
{
res = 1;
goto out;
}
spin_lock(&p->physdev_lock);
xen_physdisk_probe_access(buf, p);
spin_unlock(&p->physdev_lock);
put_task_struct(p);
res = 0;
out:
unmap_domain_mem(buf);
return res;
}
int xen_physdisk_access_okay(phys_seg_t * pseg, struct task_struct *p,
int operation)
{
struct physdisk_ace *cur_ace;
unsigned long sect;
DPRINTK
("Checking access for domain %d, start sect 0x%lx, length 0x%x.\n",
p->domain, pseg->sector_number, pseg->nr_sects);
for ( sect = pseg->sector_number;
sect < pseg->sector_number + pseg->nr_sects; )
{
/* XXX this would be a lot faster if the aces were sorted on start
address. Also in revoke_access. */
spin_lock(&p->physdev_lock);
cur_ace = find_ace(p, pseg->dev, sect, operation);
spin_unlock(&p->physdev_lock);
if ( cur_ace == NULL )
return 0;
sect +=
MAX(cur_ace->n_sectors,
pseg->nr_sects + pseg->sector_number - sect);
}
return 1;
}
void destroy_physdisk_aces(struct task_struct *p)
{
struct list_head *cur_ace_head, *next_head;
struct physdisk_ace *cur_ace;
for ( cur_ace_head = p->physdisk_aces.next;
cur_ace_head != &p->physdisk_aces;
cur_ace_head = next_head )
{
cur_ace = list_entry(cur_ace_head, struct physdisk_ace, list);
next_head = cur_ace_head->next;
kfree(cur_ace);
}
}
-429
View File
@@ -1,429 +0,0 @@
/*
* xen_segment.c
*/
#include <xeno/config.h>
#include <xeno/types.h>
#include <xeno/lib.h>
#include <asm/io.h>
#include <xeno/slab.h>
#include <xeno/segment.h>
#include <xeno/sched.h>
#include <xeno/blkdev.h>
#include <xeno/keyhandler.h>
#include <asm/current.h>
#include <asm/domain_page.h>
#include <hypervisor-ifs/block.h>
/* Global list of all possible segments. This can be changed in
the following way:
1) UNUSED segment -> RO or RW segment. This requires the spinlock.
2) RO or RW -> UNUSED. This requires the lock and can only happen
during process teardown.
This means that processes can access entries in the list safely
without having to hold any lock at all: they already have an entry
allocated, and we know that entry can't become unused, as segments
are only torn down when the domain is dieing, by which point it
can't be accessing them anymore. */
static segment_t xsegments[XEN_MAX_SEGMENTS];
static spinlock_t xsegment_lock = SPIN_LOCK_UNLOCKED;
#if 0
#define DPRINTK(_f, _a...) printk( _f , ## _a )
#else
#define DPRINTK(_f, _a...) ((void)0)
#endif
/*
* xen_segment_map_request
*
* xen_device must be a valid device.
*
* NB. All offsets and sizes here are in sector units.
* eg. 'size == 1' means an actual size of 512 bytes.
*
* Note that no locking is performed here whatsoever --
* we rely on the fact that once segment information is
* established, it is only modified by domain shutdown,
* and so if this is being called, noone is trying
* to modify the segment list.
*/
int xen_segment_map_request(
phys_seg_t *pseg, struct task_struct *p, int operation,
unsigned short segment_number,
unsigned long sect_nr, unsigned long buffer, unsigned short nr_sects)
{
segment_t *seg;
extent_t *ext;
int sum, i;
segment_number &= XENDEV_IDX_MASK;
if ( segment_number >= XEN_MAX_SEGMENTS )
{
DPRINTK("invalid segment number. %d %d\n",
segment_number, XEN_MAX_SEGMENTS);
goto fail;
}
seg = p->segment_list[segment_number];
if ( seg == NULL )
{
DPRINTK("segment is null. %d\n", segment_number);
goto fail;
}
/* check domain permissions */
if ( seg->domain != p->domain )
{
DPRINTK("seg is for another domain. %d %d\n", seg->domain, p->domain);
goto fail;
}
/* check rw access */
if ( ((operation == WRITE) && (seg->mode != XEN_SEGMENT_RW)) ||
((operation == READ) && (seg->mode == XEN_SEGMENT_UNUSED)) )
{
DPRINTK("illegal operation: %d %d\n", operation, seg->mode);
goto fail;
}
if ( (nr_sects + sect_nr) <= sect_nr )
{
DPRINTK("sector + size wrap! %08lx %04x\n", sect_nr, nr_sects);
goto fail;
}
/* find extent, check size */
sum = 0;
i = 0;
ext = seg->extents;
while ( (i < seg->num_extents) && ((sum + ext->size) <= sect_nr) )
{
sum += ext->size;
ext++; i++;
}
if ( (sum + ext->size) <= sect_nr )
{
DPRINTK("extent size mismatch: %d %d : %d %ld %ld\n",
i, seg->num_extents, sum, ext->size, sect_nr);
goto fail;
}
pseg->sector_number = (sect_nr - sum) + ext->offset;
pseg->buffer = buffer;
pseg->nr_sects = nr_sects;
pseg->dev = xendev_to_physdev(ext->disk);
if ( pseg->dev == 0 )
{
DPRINTK ("invalid device 0x%x 0x%lx 0x%lx\n",
ext->disk, ext->offset, ext->size);
goto fail;
}
/* We're finished if the virtual extent didn't overrun the phys extent. */
if ( (sum + ext->size) >= (sect_nr + nr_sects) )
return 1; /* entire read fits in this extent */
/* Hmmm... make sure there's another extent to overrun onto! */
if ( (i+1) == seg->num_extents )
{
DPRINTK ("not enough extents %d %d\n",
i, seg->num_extents);
goto fail;
}
pseg[1].nr_sects = (sect_nr + nr_sects) - (sum + ext->size);
pseg[0].nr_sects = sum + ext->size - sect_nr;
pseg[1].buffer = buffer + (pseg->nr_sects << 9);
pseg[1].sector_number = ext[1].offset;
pseg[1].dev = xendev_to_physdev(ext[1].disk);
if ( pseg[1].dev == 0 )
{
DPRINTK ("bogus device for pseg[1] \n");
goto fail;
}
/* We don't allow overrun onto a third physical extent. */
if ( pseg[1].nr_sects > ext[1].size )
{
DPRINTK ("third extent\n");
DPRINTK (" sum:%d, e0:%ld, e1:%ld p1.sect:%ld p1.nr:%d\n",
sum, ext[0].size, ext[1].size,
pseg[1].sector_number, pseg[1].nr_sects);
goto fail;
}
return 2; /* We overran onto a second physical extent. */
fail:
DPRINTK ("xen_segment_map_request failure\n");
DPRINTK ("operation: %d\n", operation);
DPRINTK ("segment number: %d\n", segment_number);
DPRINTK ("sect_nr: %ld 0x%lx\n", sect_nr, sect_nr);
DPRINTK ("nr_sects: %d 0x%x\n", nr_sects, nr_sects);
return -1;
}
/*
* xen_segment_probe
*
* return a list of segments to the guestos
*/
void xen_segment_probe(struct task_struct *p, xen_disk_info_t *raw_xdi)
{
int loop, i;
xen_disk_info_t *xdi = map_domain_mem(virt_to_phys(raw_xdi));
unsigned long capacity = 0, device;
spin_lock(&xsegment_lock);
xdi->count = 0;
for ( loop = 0; loop < XEN_MAX_SEGMENTS; loop++ )
{
if ( (xsegments[loop].mode == XEN_SEGMENT_UNUSED) ||
(xsegments[loop].domain != p->domain) )
continue;
device = MK_VIRTUAL_XENDEV(xsegments[loop].segment_number);
for ( i = 0; i < xsegments[loop].num_extents; i++ )
capacity += xsegments[loop].extents[i].size;
xdi->disks[xdi->count].device = device;
xdi->disks[xdi->count].capacity = capacity;
xdi->count++;
}
spin_unlock(&xsegment_lock);
unmap_domain_mem(xdi);
}
/*
* xen_segment_probe_all
*
* return a list of all segments to domain 0
*/
void xen_segment_probe_all(xen_segment_info_t *raw_xsi)
{
int loop;
xen_segment_info_t *xsi = map_domain_mem(virt_to_phys(raw_xsi));
spin_lock(&xsegment_lock);
xsi->count = 0;
for ( loop = 0; loop < XEN_MAX_SEGMENTS; loop++ )
{
if ( xsegments[loop].mode == XEN_SEGMENT_UNUSED )
continue;
xsi->segments[xsi->count].mode = xsegments[loop].mode;
xsi->segments[xsi->count].domain = xsegments[loop].domain;
memcpy(xsi->segments[xsi->count].key,
xsegments[loop].key,
XEN_SEGMENT_KEYSIZE);
xsi->segments[xsi->count].seg_nr = xsegments[loop].segment_number;
xsi->count++;
}
spin_unlock(&xsegment_lock);
unmap_domain_mem(xsi);
}
/*
* xen_refresh_segment_list
*
* find all segments associated with a domain and assign
* them to the domain
*
*/
void xen_refresh_segment_list (struct task_struct *p)
{
int loop;
spin_lock(&xsegment_lock);
for (loop = 0; loop < XEN_MAX_SEGMENTS; loop++)
{
if ( (xsegments[loop].mode == XEN_SEGMENT_UNUSED) ||
(xsegments[loop].domain != p->domain) )
continue;
p->segment_list[xsegments[loop].segment_number] = &xsegments[loop];
}
spin_unlock(&xsegment_lock);
}
/*
* create a new segment for a domain
*
* return 0 on success, 1 on failure
*
* if we see the same DOM#/SEG# combination, we reuse the slot in
* the segment table (overwriting what was there before).
* an alternative would be to raise an error if the slot is reused.
*/
int xen_segment_create(xv_disk_t *xvd_in)
{
int idx;
int loop;
xv_disk_t *xvd = map_domain_mem(virt_to_phys(xvd_in));
struct task_struct *p;
spin_lock(&xsegment_lock);
for (idx = 0; idx < XEN_MAX_SEGMENTS; idx++)
{
if (xsegments[idx].mode == XEN_SEGMENT_UNUSED ||
(xsegments[idx].domain == xvd->domain &&
xsegments[idx].segment_number == xvd->segment)) break;
}
if (idx == XEN_MAX_SEGMENTS)
{
printk (KERN_ALERT "xen_segment_create: unable to find free slot\n");
unmap_domain_mem(xvd);
return 1;
}
xsegments[idx].mode = xvd->mode;
xsegments[idx].domain = xvd->domain;
xsegments[idx].segment_number = xvd->segment;
memcpy(xsegments[idx].key, xvd->key, XEN_SEGMENT_KEYSIZE);
xsegments[idx].num_extents = xvd->ext_count;
if (xsegments[idx].extents)
kfree(xsegments[idx].extents);
xsegments[idx].extents = (extent_t *)kmalloc(
sizeof(extent_t)*xvd->ext_count,
GFP_KERNEL);
/* could memcpy, but this is safer */
for (loop = 0; loop < xvd->ext_count; loop++)
{
xsegments[idx].extents[loop].disk = xvd->extents[loop].disk;
xsegments[idx].extents[loop].offset = xvd->extents[loop].offset;
xsegments[idx].extents[loop].size = xvd->extents[loop].size;
if (xsegments[idx].extents[loop].size == 0)
{
printk("xen_segment_create: extent %d is zero length\n", loop);
unmap_domain_mem(xvd);
return 1;
}
}
/* if the domain exists, assign the segment to the domain */
p = find_domain_by_id(xvd->domain);
if (p != NULL)
{
p->segment_list[xvd->segment] = &xsegments[idx];
put_task_struct(p);
}
spin_unlock(&xsegment_lock);
unmap_domain_mem(xvd);
return 0;
}
/*
* delete a segment from a domain
*
* return 0 on success, 1 on failure
*
* This should *only* be called from domain shutdown, or else we
* race with access checking.
*/
int xen_segment_delete(struct task_struct *p, int segnr)
{
segment_t *seg;
if (!p) {
printk("xen_segment delete called with NULL domain?\n");
BUG();
return 1;
}
if (segnr < 0 || segnr > XEN_MAX_SEGMENTS) {
printk("xen_segment_delete called with bad segnr?\n");
BUG();
return 1;
}
if (!p->segment_list[segnr])
return 1;
seg = p->segment_list[segnr];
/* sanity checking */
if (seg->domain != p->domain || seg->segment_number != segnr ||
(seg->mode != XEN_SEGMENT_RO && seg->mode != XEN_SEGMENT_RW) ||
seg->num_extents <= 0 || seg->extents == NULL) {
printk("segment is insane!\n");
BUG();
return 1;
}
spin_lock(&xsegment_lock);
p->segment_list[segnr] = NULL;
seg->domain = -1;
seg->segment_number = -1;
kfree(seg->extents);
seg->mode = XEN_SEGMENT_UNUSED;
spin_unlock(&xsegment_lock);
return 0;
}
static void dump_segments(u_char key, void *dev_id, struct pt_regs *regs)
{
int loop, i;
struct task_struct *p;
printk("segment list\n");
for (loop = 0; loop < XEN_MAX_SEGMENTS; loop++)
{
if (xsegments[loop].mode != XEN_SEGMENT_UNUSED)
{
printk(" %2d: %s dom%d, seg# %d, num_exts: %d\n",
loop,
xsegments[loop].mode == XEN_SEGMENT_RO ? "RO" : "RW",
xsegments[loop].domain, xsegments[loop].segment_number,
xsegments[loop].num_extents);
for (i = 0; i < xsegments[loop].num_extents; i++)
{
printk(" extent %d: disk 0x%x, offset 0x%lx, size 0x%lx\n",
i, xsegments[loop].extents[i].disk,
xsegments[loop].extents[i].offset,
xsegments[loop].extents[i].size);
}
}
}
printk("segments by domain (index into segments list)\n");
p = current;
do
{
printk(" domain %d: ", p->domain);
for (loop = 0; loop < XEN_MAX_SEGMENTS; loop++)
{
if (p->segment_list[loop])
{
printk (" %d", p->segment_list[loop] - xsegments);
}
}
printk("\n");
p = p->next_task;
} while (p != current);
}
/*
* initialize segments
*/
void xen_segment_initialize(void)
{
memset (xsegments, 0, sizeof(xsegments));
add_key_handler('S', dump_segments, "dump segments");
}
+666
View File
@@ -0,0 +1,666 @@
/*
* xen_vbd.c : routines for managing virtual block devices
*/
#include <xeno/config.h>
#include <xeno/types.h>
#include <xeno/lib.h>
#include <asm/io.h>
#include <xeno/slab.h>
#include <xeno/sched.h>
#include <xeno/vbd.h>
#include <xeno/blkdev.h>
#include <xeno/keyhandler.h>
#include <asm/current.h>
#include <asm/domain_page.h>
/* Global list of all possible vbds. This can be changed in
the following way:
1) UNUSED vbd -> RO or RW vbd. This requires the spinlock.
2) RO or RW -> UNUSED. This requires the lock and can only happen
during process teardown.
This means that processes can access entries in the list safely
without having to hold any lock at all: they already have an entry
allocated, and we know that entry can't become unused, as vbds
are only torn down when the domain is dieing, by which point it
can't be accessing them anymore. */
static vbd_t xvbds[XEN_MAX_VBDS];
static spinlock_t xvbd_lock = SPIN_LOCK_UNLOCKED;
#if 0
#define DPRINTK(_f, _a...) printk( _f , ## _a )
#else
#define DPRINTK(_f, _a...) ((void)0)
#endif
/*
* xen_vbd_map_request
*
* xen_device must be a valid device.
*
* NB. All offsets and sizes here are in sector units.
* eg. 'size == 1' means an actual size of 512 bytes.
*
* Note that no locking is performed here whatsoever --
* we rely on the fact that once vbd information is
* established, it is only modified by domain shutdown,
* and so if this is being called, noone is trying
* to modify the vbd list.
*/
int xen_vbd_map_request(
phys_seg_t *pseg, struct task_struct *p, int operation,
unsigned short vbd_number,
unsigned long sect_nr, unsigned long buffer, unsigned short nr_sects)
{
vbd_t *seg;
extent_t *ext;
int sum, i;
vbd_number &= XENDEV_IDX_MASK;
if ( vbd_number >= XEN_MAX_VBDS )
{
DPRINTK("invalid vbd number. %d %d\n",
vbd_number, XEN_MAX_VBDS);
goto fail;
}
seg = p->vbd_list[vbd_number];
if ( seg == NULL )
{
DPRINTK("vbd is null. %d\n", vbd_number);
goto fail;
}
/* check domain permissions */
if ( seg->domain != p->domain )
{
DPRINTK("seg is for another domain. %d %d\n", seg->domain, p->domain);
goto fail;
}
/* check rw access */
if ( ((operation == WRITE) && (seg->mode != XEN_VBD_RW)) ||
((operation == READ) && (seg->mode == XEN_VBD_UNUSED)) )
{
DPRINTK("illegal operation: %d %d\n", operation, seg->mode);
goto fail;
}
if ( (nr_sects + sect_nr) <= sect_nr )
{
DPRINTK("sector + size wrap! %08lx %04x\n", sect_nr, nr_sects);
goto fail;
}
/* find extent, check size */
sum = 0;
i = 0;
ext = seg->extents;
while ( (i < seg->num_extents) && ((sum + ext->nr_sectors) <= sect_nr) )
{
sum += ext->nr_sectors;
ext++; i++;
}
if ( (sum + ext->nr_sectors) <= sect_nr )
{
DPRINTK("extent size mismatch: %d %d : %d %ld %ld\n",
i, seg->num_extents, sum, ext->nr_sectors, sect_nr);
goto fail;
}
pseg->sector_number = (sect_nr - sum) + ext->start_sector;
pseg->buffer = buffer;
pseg->nr_sects = nr_sects;
pseg->dev = xendev_to_physdev(ext->raw_device);
if ( pseg->dev == 0 )
{
DPRINTK ("invalid device 0x%x 0x%lx 0x%lx\n",
ext->raw_device, ext->start_sector, ext->nr_sectors);
goto fail;
}
/* We're finished if the virtual extent didn't overrun the phys extent. */
if ( (sum + ext->nr_sectors) >= (sect_nr + nr_sects) )
return 1; /* entire read fits in this extent */
/* Hmmm... make sure there's another extent to overrun onto! */
if ( (i+1) == seg->num_extents )
{
DPRINTK ("not enough extents %d %d\n",
i, seg->num_extents);
goto fail;
}
pseg[1].nr_sects = (sect_nr + nr_sects) - (sum + ext->nr_sectors);
pseg[0].nr_sects = sum + ext->nr_sectors - sect_nr;
pseg[1].buffer = buffer + (pseg->nr_sects << 9);
pseg[1].sector_number = ext[1].start_sector;
pseg[1].dev = xendev_to_physdev(ext[1].raw_device);
if ( pseg[1].dev == 0 )
{
DPRINTK ("bogus device for pseg[1] \n");
goto fail;
}
/* We don't allow overrun onto a third physical extent. */
if ( pseg[1].nr_sects > ext[1].nr_sectors )
{
DPRINTK ("third extent\n");
DPRINTK (" sum:%d, e0:%ld, e1:%ld p1.sect:%ld p1.nr:%d\n",
sum, ext[0].nr_sectors, ext[1].nr_sectors,
pseg[1].sector_number, pseg[1].nr_sects);
goto fail;
}
return 2; /* We overran onto a second physical extent. */
fail:
DPRINTK ("xen_vbd_map_request failure\n");
DPRINTK ("operation: %d\n", operation);
DPRINTK ("vbd number: %d\n", vbd_number);
DPRINTK ("sect_nr: %ld 0x%lx\n", sect_nr, sect_nr);
DPRINTK ("nr_sects: %d 0x%x\n", nr_sects, nr_sects);
return -1;
}
/*
* vbd_probe_devices:
*
* add the virtual block devices for this domain to a xen_disk_info_t;
* we assume xdi->count points to the first unused place in the array.
*/
void vbd_probe_devices(xen_disk_info_t *xdi, struct task_struct *p)
{
int loop, i;
unsigned long capacity = 0, device;
spin_lock(&xvbd_lock);
for (loop = 0; loop < XEN_MAX_VBDS; loop++ )
{
if ( (xvbds[loop].mode == XEN_VBD_UNUSED) ||
(xvbds[loop].domain != p->domain) )
continue;
device = MK_VIRTUAL_XENDEV(xvbds[loop].vbd_number);
for ( i = 0; i < xvbds[loop].num_extents; i++ )
capacity += xvbds[loop].extents[i].nr_sectors;
xdi->disks[xdi->count].device = device;
xdi->disks[xdi->count].capacity = capacity;
xdi->count++;
}
spin_unlock(&xvbd_lock);
return;
}
/*
* xen_refresh_vbd_list
*
* find all vbds associated with a domain and assign
* them to the domain
*
*/
void xen_refresh_vbd_list (struct task_struct *p)
{
int loop;
spin_lock(&xvbd_lock);
for (loop = 0; loop < XEN_MAX_VBDS; loop++)
{
if ( (xvbds[loop].mode == XEN_VBD_UNUSED) ||
(xvbds[loop].domain != p->domain) )
continue;
p->vbd_list[xvbds[loop].vbd_number] = &xvbds[loop];
}
spin_unlock(&xvbd_lock);
}
/*
* create a new vbd for a domain
*
* return 0 on success, 1 on failure
*
* if we see the same DOM#/SEG# combination, we reuse the slot in
* the vbd table (overwriting what was there before).
* an alternative would be to raise an error if the slot is reused.
*/
int xen_vbd_create(xv_disk_t *xvd_in)
{
int idx;
int loop;
xv_disk_t *xvd = map_domain_mem(virt_to_phys(xvd_in));
struct task_struct *p;
spin_lock(&xvbd_lock);
for (idx = 0; idx < XEN_MAX_VBDS; idx++)
{
if (xvbds[idx].mode == XEN_VBD_UNUSED ||
(xvbds[idx].domain == xvd->domain &&
xvbds[idx].vbd_number == xvd->vbd)) break;
}
if (idx == XEN_MAX_VBDS)
{
printk (KERN_ALERT "xen_vbd_create: unable to find free slot\n");
unmap_domain_mem(xvd);
return 1;
}
xvbds[idx].mode = xvd->mode;
xvbds[idx].domain = xvd->domain;
xvbds[idx].vbd_number = xvd->vbd;
memcpy(xvbds[idx].key, xvd->key, XEN_VBD_KEYSIZE);
xvbds[idx].num_extents = xvd->ext_count;
if (xvbds[idx].extents)
kfree(xvbds[idx].extents);
xvbds[idx].extents = (extent_t *)kmalloc(
sizeof(extent_t)*xvd->ext_count,
GFP_KERNEL);
/* could memcpy, but this is safer */
for (loop = 0; loop < xvd->ext_count; loop++)
{
xvbds[idx].extents[loop].raw_device = xvd->extents[loop].disk;
xvbds[idx].extents[loop].start_sector =
xvd->extents[loop].offset;
xvbds[idx].extents[loop].nr_sectors = xvd->extents[loop].size;
if (xvbds[idx].extents[loop].nr_sectors == 0)
{
printk("xen_vbd_create: extent %d is zero length\n", loop);
unmap_domain_mem(xvd);
return 1;
}
}
/* if the domain exists, assign the vbd to the domain */
p = find_domain_by_id(xvd->domain);
if (p != NULL)
{
p->vbd_list[xvd->vbd] = &xvbds[idx];
put_task_struct(p);
}
spin_unlock(&xvbd_lock);
unmap_domain_mem(xvd);
return 0;
}
/*
* delete a vbd from a domain
*
* return 0 on success, 1 on failure
*
* This should *only* be called from domain shutdown, or else we
* race with access checking.
*/
int xen_vbd_delete(struct task_struct *p, int segnr)
{
vbd_t *seg;
if (!p) {
printk("xen_vbd delete called with NULL domain?\n");
BUG();
return 1;
}
if (segnr < 0 || segnr > XEN_MAX_VBDS) {
printk("xen_vbd_delete called with bad segnr?\n");
BUG();
return 1;
}
if (!p->vbd_list[segnr])
return 1;
seg = p->vbd_list[segnr];
/* sanity checking */
if (seg->domain != p->domain || seg->vbd_number != segnr ||
(seg->mode != XEN_VBD_RO && seg->mode != XEN_VBD_RW) ||
seg->num_extents <= 0 || seg->extents == NULL) {
printk("vbd is insane!\n");
BUG();
return 1;
}
spin_lock(&xvbd_lock);
p->vbd_list[segnr] = NULL;
seg->domain = -1;
seg->vbd_number = -1;
kfree(seg->extents);
seg->mode = XEN_VBD_UNUSED;
spin_unlock(&xvbd_lock);
return 0;
}
static void dump_vbds(u_char key, void *dev_id, struct pt_regs *regs)
{
int loop, i;
struct task_struct *p;
printk("vbd list\n");
for (loop = 0; loop < XEN_MAX_VBDS; loop++)
{
if (xvbds[loop].mode != XEN_VBD_UNUSED)
{
printk(" %2d: %s dom%d, seg# %d, num_exts: %d\n",
loop,
xvbds[loop].mode == XEN_VBD_RO ? "RO" : "RW",
xvbds[loop].domain, xvbds[loop].vbd_number,
xvbds[loop].num_extents);
for (i = 0; i < xvbds[loop].num_extents; i++)
{
printk(" extent %d: raw device 0x%x, start_sector 0x%lx"
" nr_sectors 0x%lx\n",
i, xvbds[loop].extents[i].raw_device,
xvbds[loop].extents[i].start_sector,
xvbds[loop].extents[i].nr_sectors);
}
}
}
printk("vbds by domain (index into vbds list)\n");
p = current;
do
{
if(is_idle_task(p))
continue;
printk(" domain %d: ", p->domain);
for (loop = 0; loop < XEN_MAX_VBDS; loop++)
{
if (p->vbd_list[loop])
{
printk (" %d", p->vbd_list[loop] - xvbds);
}
}
printk("\n");
p = p->next_task;
} while (p != current);
}
/*
* initialize vbds
*/
void xen_vbd_initialize(void)
{
memset (xvbds, 0, sizeof(xvbds));
add_key_handler('S', dump_vbds, "dump vbds");
}
/* The idea is that, for each sector of each disk, each domain has two
bits, saying whether they can read the sector or write it. That
would take too much memory, so instead each process has a list of
(device, start, end, mode) quads which say what it has access to,
and we fake the logical view on top of that. */
struct physdisk_ace {
struct list_head list;
unsigned short device;
unsigned short partition;
unsigned long start_sect;
unsigned long n_sectors;
int mode;
};
/* Operation is a blkdev constant i.e. READ, WRITE, ... */
/* Must be called with p->physdev_lock held. */
static struct physdisk_ace *find_ace(const struct task_struct *p,
unsigned short dev,
unsigned long sect, int operation)
{
struct list_head *cur_ace_head;
struct physdisk_ace *cur_ace;
list_for_each(cur_ace_head, &p->physdisk_aces)
{
cur_ace = list_entry(cur_ace_head, struct physdisk_ace, list);
DPRINTK("Is [%lx, %lx) good for %lx?\n",
cur_ace->start_sect,
cur_ace->start_sect + cur_ace->n_sectors, sect);
if ( (sect >= cur_ace->start_sect) &&
(sect < (cur_ace->start_sect + cur_ace->n_sectors)) &&
(dev == cur_ace->device) &&
(((operation == READ) && (cur_ace->mode & PHYSDISK_MODE_R)) ||
((operation == WRITE) && (cur_ace->mode & PHYSDISK_MODE_W))) )
return cur_ace;
}
return NULL;
}
/* Hold the lock on entry, it remains held on exit. */
static void xen_physdisk_revoke_access(unsigned short dev,
unsigned long start_sect,
unsigned long n_sectors,
struct task_struct *p)
{
/* Find every ace which intersects [start_sect, start_sect +
n_sectors] and either remove it completely or truncate it
down. */
struct list_head *cur_ace_head;
struct physdisk_ace *cur_ace, *new_ace;
unsigned long kill_zone_end, ace_end;
kill_zone_end = start_sect + n_sectors;
list_for_each(cur_ace_head, &p->physdisk_aces)
{
cur_ace = list_entry(cur_ace_head, struct physdisk_ace, list);
ace_end = cur_ace->start_sect + cur_ace->n_sectors;
if ( (cur_ace->start_sect >= kill_zone_end) ||
(ace_end <= start_sect) ||
(cur_ace->device != dev) )
continue;
DPRINTK("Killing ace [%lx, %lx) against kill zone [%lx, %lx)\n",
cur_ace->start_sect, ace_end, start_sect, kill_zone_end);
if ( (cur_ace->start_sect >= start_sect) &&
(ace_end <= kill_zone_end) )
{
/* ace entirely within kill zone -> kill it */
list_del(cur_ace_head);
cur_ace_head = cur_ace_head->prev;
kfree(cur_ace);
}
else if ( ace_end <= kill_zone_end )
{
/* ace start before kill start, ace end in kill zone,
move ace end. */
cur_ace->n_sectors = start_sect - cur_ace->start_sect;
}
else if ( cur_ace->start_sect >= start_sect )
{
/* ace start after kill start, ace end outside kill zone,
move ace start. */
cur_ace->start_sect = kill_zone_end;
cur_ace->n_sectors = ace_end - cur_ace->start_sect;
}
else
{
/* The fun one: the ace entirely includes the kill zone. */
/* Cut the current ace down to just the bit before the kzone,
create a new ace for the bit just after it. */
new_ace = kmalloc(sizeof(*cur_ace), GFP_KERNEL);
new_ace->device = dev;
new_ace->start_sect = kill_zone_end;
new_ace->n_sectors = ace_end - kill_zone_end;
new_ace->mode = cur_ace->mode;
cur_ace->n_sectors = start_sect - cur_ace->start_sect;
list_add(&new_ace->list, cur_ace_head);
}
}
}
/* Hold the lock on entry, it remains held on exit. */
static int xen_physdisk_grant_access(unsigned short dev,
unsigned short partition,
unsigned long start_sect,
unsigned long n_sectors,
int mode, struct task_struct *p)
{
struct physdisk_ace *cur_ace;
/* Make sure it won't overlap with any existing ACEs. */
/* XXX this isn't quite right if the domain already has read access
and we try to grant write access, or vice versa. */
xen_physdisk_revoke_access(dev, start_sect, n_sectors, p);
if ( mode )
{
cur_ace = kmalloc(sizeof(*cur_ace), GFP_KERNEL);
cur_ace->device = dev;
cur_ace->start_sect = start_sect;
cur_ace->n_sectors = n_sectors;
cur_ace->mode = mode;
cur_ace->partition = partition;
list_add_tail(&cur_ace->list, &p->physdisk_aces);
}
return 0;
}
static void xen_physdisk_probe_access(physdisk_probebuf_t * buf,
struct task_struct *p)
{
int n_aces;
struct list_head *cur_ace_head;
struct physdisk_ace *cur_ace;
int x = 0;
n_aces = 0;
list_for_each(cur_ace_head, &p->physdisk_aces)
{
x++;
if ( x >= buf->start_ind )
{
cur_ace = list_entry(cur_ace_head, struct physdisk_ace, list);
buf->entries[n_aces].device = cur_ace->device;
buf->entries[n_aces].partition = cur_ace->partition;
buf->entries[n_aces].start_sect = cur_ace->start_sect;
buf->entries[n_aces].n_sectors = cur_ace->n_sectors;
buf->entries[n_aces].mode = cur_ace->mode;
n_aces++;
}
}
buf->n_aces = n_aces;
}
int xen_physdisk_grant(xp_disk_t * xpd_in)
{
struct task_struct *p = current;
xp_disk_t *xpd = map_domain_mem(virt_to_phys(xpd_in));
int res;
p = find_domain_by_id(xpd->domain);
if ( p == NULL )
{
DPRINTK("Bad domain!\n");
res = 1;
goto out;
}
spin_lock(&p->physdev_lock);
res = xen_physdisk_grant_access(xpd->device,
xpd->partition,
xpd->start_sect,
xpd->n_sectors, xpd->mode, p);
spin_unlock(&p->physdev_lock);
put_task_struct(p);
out:
unmap_domain_mem(xpd);
return res;
}
int xen_physdisk_probe(struct task_struct *requesting_domain,
physdisk_probebuf_t * buf_in)
{
struct task_struct *p;
physdisk_probebuf_t *buf = map_domain_mem(virt_to_phys(buf_in));
int res;
if ( (requesting_domain->domain != 0) &&
(requesting_domain->domain != buf->domain) )
{
res = 1;
goto out;
}
p = find_domain_by_id(buf->domain);
if ( p == NULL )
{
res = 1;
goto out;
}
spin_lock(&p->physdev_lock);
xen_physdisk_probe_access(buf, p);
spin_unlock(&p->physdev_lock);
put_task_struct(p);
res = 0;
out:
unmap_domain_mem(buf);
return res;
}
#define MAX(a,b) ((a) > (b) ? (a) : (b))
int xen_physdisk_access_okay(phys_seg_t * pseg, struct task_struct *p,
int operation)
{
struct physdisk_ace *cur_ace;
unsigned long sect;
DPRINTK
("Checking access for domain %d, start sect 0x%lx, length 0x%x.\n",
p->domain, pseg->sector_number, pseg->nr_sects);
for ( sect = pseg->sector_number;
sect < pseg->sector_number + pseg->nr_sects; )
{
/* XXX this would be a lot faster if the aces were sorted on start
address. Also in revoke_access. */
spin_lock(&p->physdev_lock);
cur_ace = find_ace(p, pseg->dev, sect, operation);
spin_unlock(&p->physdev_lock);
if ( cur_ace == NULL )
return 0;
sect +=
MAX(cur_ace->n_sectors,
pseg->nr_sects + pseg->sector_number - sect);
}
return 1;
}
void destroy_physdisk_aces(struct task_struct *p)
{
struct list_head *cur_ace_head, *next_head;
struct physdisk_ace *cur_ace;
for ( cur_ace_head = p->physdisk_aces.next;
cur_ace_head != &p->physdisk_aces;
cur_ace_head = next_head )
{
cur_ace = list_entry(cur_ace_head, struct physdisk_ace, list);
next_head = cur_ace_head->next;
kfree(cur_ace);
}
}
+8 -10
View File
@@ -2,8 +2,7 @@
#include <xeno/types.h>
#include <xeno/lib.h>
#include <xeno/ide.h>
#include <xeno/segment.h>
#include <hypervisor-ifs/block.h>
#include <xeno/vbd.h>
#include <asm/domain_page.h>
#include <asm/io.h>
@@ -11,7 +10,6 @@ void ide_probe_devices(xen_disk_info_t* xdi)
{
int loop;
unsigned int unit;
xen_disk_info_t *xen_xdi = map_domain_mem(virt_to_phys(xdi));
unsigned long capacity;
unsigned short device, type;
ide_drive_t *drive;
@@ -36,17 +34,17 @@ void ide_probe_devices(xen_disk_info_t* xdi)
device = MK_IDE_XENDEV((loop * MAX_DRIVES) + unit);
capacity = current_capacity(drive);
xen_xdi->disks[xen_xdi->count].device = device;
xen_xdi->disks[xen_xdi->count].type = type;
xen_xdi->disks[xen_xdi->count].capacity = capacity;
xen_xdi->count++;
xdi->disks[xdi->count].device = device;
xdi->disks[xdi->count].type = type;
xdi->disks[xdi->count].capacity = capacity;
xdi->count++;
printk("Device %d: IDE-XENO (%s) capacity %ldkB (%ldMB)\n",
xen_xdi->count, (type == XD_TYPE_DISK) ? "disk" :
xdi->count, (type == XD_TYPE_DISK) ? "disk" :
((type == XD_TYPE_CDROM) ? "cdrom" : "unknown"),
capacity>>1, capacity>>11);
}
}
unmap_domain_mem(xen_xdi);
return;
}
+16 -11
View File
@@ -1310,16 +1310,21 @@ static void sd_finish()
/*
** XXX SMH: gross 'probe' function to allow xeno world to grope us;
** this should really not be in the disk-specific code as it should
** report tapes, CDs, etc. But for now this looks like the easiest
** place to hook it in :-(
** scsi_probe_devices:
**
** add the scsi block devices for this domain to a xen_disk_info_t;
** we assume xdi->count points to the first unused place in the array.
**
** XXX SMH: this is a rather gross 'probe' function to allow xeno world
** to grope us; this should really not be in the disk-specific code as
** it should report tapes, CDs, etc. But for now this looks like the
** easiest place to hook it in :-(
**
*/
void scsi_probe_devices(xen_disk_info_t *xdi)
{
Scsi_Disk *sd;
int i;
xen_disk_info_t *xen_xdi = map_domain_mem(virt_to_phys(xdi));
unsigned long capacity, device;
for ( sd = rscsi_disks, i = 0; i < sd_template.dev_max; i++, sd++ )
@@ -1330,16 +1335,16 @@ void scsi_probe_devices(xen_disk_info_t *xdi)
capacity = sd->capacity;
/* XXX SMH: if make generic, need to properly determine 'type' */
xen_xdi->disks[xen_xdi->count].device = device;
xen_xdi->disks[xen_xdi->count].type = XD_TYPE_DISK;
xen_xdi->disks[xen_xdi->count].capacity = capacity;
xen_xdi->count++;
xdi->disks[xdi->count].device = device;
xdi->disks[xdi->count].type = XD_TYPE_DISK;
xdi->disks[xdi->count].capacity = capacity;
xdi->count++;
printk("Device %d: SCSI-XENO (disk) capacity %ldkB (%ldMB)\n",
xen_xdi->count, capacity>>1, capacity>>11);
xdi->count, capacity>>1, capacity>>11);
}
unmap_domain_mem(xen_xdi);
return;
}
+7 -64
View File
@@ -50,16 +50,14 @@
#define XEN_BLOCK_WRITE 1
#define XEN_BLOCK_READA 2
#define XEN_BLOCK_SPECIAL 4
#define XEN_BLOCK_PROBE_BLK 5 /* get xhd config from hypervisor */
#define XEN_BLOCK_DEBUG 6 /* debug */
#define XEN_BLOCK_SEG_CREATE 7 /* create segment (vhd) */
#define XEN_BLOCK_SEG_DELETE 8 /* delete segment (vhd) */
#define XEN_BLOCK_PROBE_SEG 9 /* get vhd config from hypervisor */
#define XEN_BLOCK_PROBE 5 /* get config from hypervisor */
#define XEN_BLOCK_DEBUG 6 /* debug */
#define XEN_BLOCK_VBD_CREATE 7 /* create vbd */
#define XEN_BLOCK_VBD_DELETE 8 /* delete vbd */
/* XXX SMH: was 'probe vbd' */
#define XEN_BLOCK_PHYSDEV_GRANT 10 /* grant access to range of disk blocks */
#define XEN_BLOCK_PHYSDEV_PROBE 11 /* probe for a domain's physdev
accesses */
#define XEN_BLOCK_PROBE_SEG_ALL 12 /* prove for every domain's segments,
not just ours. */
#define XEN_BLOCK_PHYSDEV_PROBE 11 /* probe for a domain's physdev accesses */
/* XXX SMH: was 'probe vbd all' */
/* NB. Ring size must be small enough for sizeof(blk_ring_t) <= PAGE_SIZE. */
#define BLK_RING_SIZE 64
@@ -127,59 +125,4 @@ typedef struct xen_disk_info
xen_disk_t disks[XEN_MAX_DISK_COUNT];
} xen_disk_info_t;
/*
*
* virtual disk (vhd) structures, used by XEN_BLOCK_SEG_{CREATE, DELETE}
*
*/
#define XEN_DISK_READ_WRITE 1
#define XEN_DISK_READ_ONLY 2
typedef struct xv_extent
{
int disk; /* physical disk number */
unsigned long offset; /* offset in blocks into physical disk */
unsigned long size; /* size in blocks */
} xv_extent_t;
#define XEN_SEGMENT_KEYSIZE 10
typedef struct xv_disk
{
int mode; /* XEN_DISK_READ_WRITE or XEN_DISK_READ_ONLY */
int domain; /* domain */
int segment; /* segment number */
char key[XEN_SEGMENT_KEYSIZE]; /* key for benefit of dom0 userspace */
int ext_count; /* number of xv_extent_t to follow */
xv_extent_t extents[XEN_MAX_DISK_COUNT]; /* arbitrary reuse of constant */
} xv_disk_t;
#define PHYSDISK_MODE_R 1
#define PHYSDISK_MODE_W 2
typedef struct xp_disk
{
int mode; /* 0 -> revoke existing access, otherwise bitmask of
PHYSDISK_MODE_? constants */
int domain;
unsigned short device; /* XENDEV_??? + idx */
unsigned short partition; /* partition number */
unsigned long start_sect;
unsigned long n_sectors;
} xp_disk_t;
#define PHYSDISK_MAX_ACES_PER_REQUEST 254 /* Make it fit in one page */
typedef struct {
int n_aces;
int domain;
int start_ind;
struct {
unsigned short device; /* XENDEV_??? + idx */
unsigned short partition; /* partition number */
unsigned long start_sect;
unsigned long n_sectors;
unsigned mode;
} entries[PHYSDISK_MAX_ACES_PER_REQUEST];
} physdisk_probebuf_t;
#endif
-21
View File
@@ -1,21 +0,0 @@
#ifndef __HYP_IFS_SEGMENT_H__
#define __HYP_IFS_SEGMENT_H__
#define XEN_MAX_SEGMENTS 100 /* total number of segments across all doms */
#define XEN_SEGMENT_UNUSED 0 /* bzero default */
#define XEN_SEGMENT_RO XEN_DISK_READ_ONLY
#define XEN_SEGMENT_RW XEN_DISK_READ_WRITE
typedef struct xen_segment_info
{
int count;
struct {
unsigned domain;
unsigned seg_nr;
char key[XEN_SEGMENT_KEYSIZE];
unsigned short mode; /* UNUSED, RO, or RW. */
} segments[XEN_MAX_SEGMENTS];
} xen_segment_info_t;
#endif /* __HYP_IFS_SEGMENT_H__ */
+115
View File
@@ -0,0 +1,115 @@
#ifndef __HYP_IFS_VBD_H__
#define __HYP_IFS_VBD_H__
#define XEN_MAX_VBDS 100 /* total number of vbds across all doms */
#define XEN_VBD_UNUSED 0 /* bzero default */
#define XEN_DISK_READ_WRITE 1
#define XEN_DISK_READ_ONLY 2
#define XEN_VBD_RO XEN_DISK_READ_ONLY
#define XEN_VBD_RW XEN_DISK_READ_WRITE
/*
*
* virtual disk (vhd) structures, used by XEN_BLOCK_VBD_{CREATE, DELETE}
*
*/
typedef struct xv_extent
{
int disk; /* physical disk number */
unsigned long offset; /* offset in blocks into physical disk */
unsigned long size; /* size in blocks */
} xv_extent_t;
#define XEN_VBD_KEYSIZE 10
typedef struct xv_disk
{
int mode; /* XEN_DISK_READ_WRITE or XEN_DISK_READ_ONLY */
int domain; /* domain */
int vbd; /* segment number */
char key[XEN_VBD_KEYSIZE]; /* key for benefit of dom0 userspace */
int ext_count; /* number of xv_extent_t to follow */
xv_extent_t extents[XEN_MAX_DISK_COUNT]; /* arbitrary reuse of constant */
} xv_disk_t;
#define PHYSDISK_MODE_R 1
#define PHYSDISK_MODE_W 2
typedef struct xp_disk
{
int mode; /* 0 -> revoke existing access, otherwise bitmask of
PHYSDISK_MODE_? constants */
int domain;
unsigned short device; /* XENDEV_??? + idx */
unsigned short partition; /* partition number */
unsigned long start_sect;
unsigned long n_sectors;
} xp_disk_t;
#define PHYSDISK_MAX_ACES_PER_REQUEST 254 /* Make it fit in one page */
typedef struct {
int n_aces;
int domain;
int start_ind;
struct {
unsigned short device; /* XENDEV_??? + idx */
unsigned short partition; /* partition number */
unsigned long start_sect;
unsigned long n_sectors;
unsigned mode;
} entries[PHYSDISK_MAX_ACES_PER_REQUEST];
} physdisk_probebuf_t;
typedef struct xen_vbd_info
{
int count;
struct {
unsigned domain;
unsigned seg_nr;
char key[XEN_VBD_KEYSIZE];
unsigned short mode; /* UNUSED, RO, or RW. */
} vbds[XEN_MAX_VBDS];
} xen_vbd_info_t;
/* Block I/O trap operations and associated structures.
*/
#define BLOCK_IO_OP_SIGNAL 0 // let xen know we have work to do
#define BLOCK_IO_OP_ATTACH_VBD 1 // attach a VBD to a given domain
typedef struct _extent {
u16 raw_device;
ulong start_sector;
ulong nr_sectors;
} extent_t;
typedef struct _vbd_attach {
int domain;
u16 mode; // read-only or read-write
u16 device; // how this domain refers to this VBD
int nr_extents; // number of extents in the VBD
extent_t *extents; // pointer to /array/ of extents
} vbd_attach_t;
typedef struct block_io_op_st
{
unsigned long cmd;
union
{
long signal_val_unused;
vbd_attach_t attach_info;
}
u;
} block_io_op_t;
#endif /* __HYP_IFS_VBD_H__ */
-11
View File
@@ -1,11 +0,0 @@
/* block.h
*
* this is the hypervisor end of the block io code.
*/
#include <hypervisor-ifs/block.h>
/* vif prototypes */
blk_ring_t *create_block_ring(int domain);
void destroy_block_ring(struct task_struct *p);
-14
View File
@@ -1,14 +0,0 @@
#ifndef PHYSDISK_ACES__
#define PHYSDISK_ACES__
struct task_struct;
void destroy_physdisk_aces(struct task_struct *p);
int xen_physdisk_grant(xp_disk_t *);
int xen_physdisk_probe(struct task_struct *requesting_task,
physdisk_probebuf_t *);
int xen_physdisk_access_okay(phys_seg_t *pseg, struct task_struct *p,
int operation);
#endif /* PHYSDISK_ACES__ */
-49
View File
@@ -1,49 +0,0 @@
#ifndef __SEGMENT_H__
#define __SEGMENT_H__
#include <hypervisor-ifs/block.h>
#include <hypervisor-ifs/segment.h>
/* Describes a physical disk extent. */
typedef struct {
unsigned short dev;
unsigned short nr_sects;
unsigned long sector_number;
unsigned long buffer;
} phys_seg_t;
struct task_struct;
void xen_segment_initialize(void);
void xen_refresh_segment_list (struct task_struct *p);
int xen_segment_create(xv_disk_t *xvd);
int xen_segment_delete(struct task_struct *p, int segnr);
int xen_segment_map_request(
phys_seg_t *pseg, struct task_struct *p, int operation,
unsigned short segment_number,
unsigned long sect_nr, unsigned long buffer, unsigned short nr_sects);
/*
* virtual hard disks
*
* each segment is composed of a number of extents
*/
typedef struct extent
{
int disk; /* A XEN_IDE_DEV or a XEN_SCSI_DEV */
unsigned long offset; /* offset into disk */
unsigned long size; /* size of this extent */
} extent_t;
typedef struct segment
{
int mode; /* UNUSED, RO, or RW */
int domain;
int segment_number; /* segment number for domain */
char key[XEN_SEGMENT_KEYSIZE]; /* for the userspace tools in dom0 */
int num_extents; /* number of extents */
extent_t *extents;
} segment_t;
#endif
+56
View File
@@ -0,0 +1,56 @@
/*
** include/xeno/vbd.h:
** -- xen internal declarations + prototypes for virtual block devices
**
*/
#ifndef __VBD_H__
#define __VBD_H__
#include <hypervisor-ifs/block.h>
#include <hypervisor-ifs/vbd.h>
/* Describes a physical disk extent. */
typedef struct {
unsigned short dev;
unsigned short nr_sects;
unsigned long sector_number;
unsigned long buffer;
} phys_seg_t;
struct task_struct;
void xen_vbd_initialize(void);
void xen_refresh_vbd_list (struct task_struct *p);
int xen_vbd_create(xv_disk_t *xvd);
int xen_vbd_delete(struct task_struct *p, int segnr);
int xen_vbd_map_request(
phys_seg_t *pseg, struct task_struct *p, int operation,
unsigned short vbd_number,
unsigned long sect_nr, unsigned long buffer, unsigned short nr_sects);
typedef struct vbd
{
int mode; /* UNUSED, RO, or RW */
int domain;
int vbd_number; /* vbd number for domain */
char key[XEN_VBD_KEYSIZE]; /* for the userspace tools in dom0 */
int num_extents; /* number of extents */
extent_t *extents;
} vbd_t;
#endif
#ifndef PHYSDISK_ACES__
#define PHYSDISK_ACES__
struct task_struct;
void destroy_physdisk_aces(struct task_struct *p);
int xen_physdisk_grant(xp_disk_t *);
int xen_physdisk_probe(struct task_struct *requesting_task,
physdisk_probebuf_t *);
int xen_physdisk_access_okay(phys_seg_t *pseg, struct task_struct *p,
int operation);
#endif /* PHYSDISK_ACES__ */
@@ -1,3 +1,3 @@
O_TARGET := blk.o
obj-y := xl_block.o xl_ide.o xl_scsi.o xl_segment.o xl_segment_proc.o info.o
obj-y := xl_block.o xl_ide.o xl_scsi.o xl_vbd.o info.o
include $(TOPDIR)/Rules.make
@@ -38,9 +38,14 @@ static unsigned long sg_next_sect;
static inline void signal_requests_to_xen(void)
{
block_io_op_t op;
DISABLE_SCATTERGATHER();
blk_ring->req_prod = req_prod;
HYPERVISOR_block_io_op(BLKOP_PUSH_BUFFERS);
op.cmd = BLOCK_IO_OP_SIGNAL;
HYPERVISOR_block_io_op(&op);
return;
}
@@ -117,7 +122,7 @@ static inline struct gendisk *xldev_to_gendisk(kdev_t xldev)
break;
case XLVIRT_MAJOR:
gd = xlsegment_gendisk;
gd = xlvbd_gendisk;
break;
}
@@ -194,8 +199,8 @@ int xenolinux_block_ioctl(struct inode *inode, struct file *filep,
case XLVIRT_MAJOR:
DPRINTK_IOCTL(" BLKSSZGET: %x 0x%x\n", BLKSSZGET,
xlsegment_hwsect(MINOR(dev)));
return xlsegment_hwsect(MINOR(dev));
xlsbd_hwsect(MINOR(dev)));
return xlvbd_hwsect(MINOR(dev));
default:
printk(KERN_ALERT "BLKSSZGET ioctl() on bogus disk!\n");
@@ -289,7 +294,7 @@ int xenolinux_block_revalidate(kdev_t dev)
if ( xdi != NULL )
{
memset(xdi, 0, sizeof(*xdi));
xenolinux_control_msg(XEN_BLOCK_PROBE_SEG,
xenolinux_control_msg(XEN_BLOCK_PROBE,
(char *)xdi, sizeof(*xdi));
for ( i = 0; i < xdi->count; i++ )
if ( IS_VIRTUAL_XENDEV(xdi->disks[i].device) &&
@@ -313,7 +318,7 @@ int xenolinux_block_revalidate(kdev_t dev)
* request block io
*
* id: for guest use only.
* operation: XEN_BLOCK_{READ,WRITE,PROBE*,SEG*}
* operation: XEN_BLOCK_{READ,WRITE,PROBE,VBD*}
* buffer: buffer to read/write into. this should be a
* virtual address in the guest os.
*/
@@ -335,13 +340,11 @@ static int hypervisor_request(unsigned long id,
switch ( operation )
{
case XEN_BLOCK_SEG_CREATE:
case XEN_BLOCK_SEG_DELETE:
case XEN_BLOCK_VBD_CREATE:
case XEN_BLOCK_VBD_DELETE:
case XEN_BLOCK_PHYSDEV_GRANT:
case XEN_BLOCK_PHYSDEV_PROBE:
case XEN_BLOCK_PROBE_BLK:
case XEN_BLOCK_PROBE_SEG:
case XEN_BLOCK_PROBE_SEG_ALL:
case XEN_BLOCK_PROBE:
if ( RING_FULL ) return 1;
phys_device = (kdev_t) 0;
sector_number = 0;
@@ -495,8 +498,8 @@ 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("Bad return from blkdev data request: %lx\n",
bret->status);
DPRINTK("Bad return from blkdev data request: %lx\n",
bret->status);
for ( bh = (struct buffer_head *)bret->id;
bh != NULL;
bh = next_bh )
@@ -507,11 +510,9 @@ static void xlblk_response_int(int irq, void *dev_id, struct pt_regs *ptregs)
}
break;
case XEN_BLOCK_SEG_CREATE:
case XEN_BLOCK_SEG_DELETE:
case XEN_BLOCK_PROBE_SEG:
case XEN_BLOCK_PROBE_SEG_ALL:
case XEN_BLOCK_PROBE_BLK:
case XEN_BLOCK_VBD_CREATE:
case XEN_BLOCK_VBD_DELETE:
case XEN_BLOCK_PROBE:
case XEN_BLOCK_PHYSDEV_GRANT:
case XEN_BLOCK_PHYSDEV_PROBE:
xlblk_control_msg_pending = bret->status;
@@ -570,7 +571,7 @@ int xenolinux_control_msg(int operation, char *buffer, int size)
int __init xlblk_init(void)
{
int error;
int error;
xlblk_control_msg_pending = 0;
nr_pending = 0;
@@ -589,7 +590,7 @@ int __init xlblk_init(void)
/* Probe for disk information. */
memset(&xlblk_disk_info, 0, sizeof(xlblk_disk_info));
error = xenolinux_control_msg(XEN_BLOCK_PROBE_BLK,
error = xenolinux_control_msg(XEN_BLOCK_PROBE,
(char *)&xlblk_disk_info,
sizeof(xen_disk_info_t));
if ( error )
@@ -599,10 +600,26 @@ int __init xlblk_init(void)
goto fail;
}
{
int i;
printk(KERN_ALERT "xlblk_init: xen returned info for %d disks\n",
xlblk_disk_info.count);
for(i=0; i < xlblk_disk_info.count; i++) {
printk("%d -- device no=%x, type=%d, capacity=%ldMB\n",
i, xlblk_disk_info.disks[i].device,
xlblk_disk_info.disks[i].type,
xlblk_disk_info.disks[i].capacity >> 11);
}
}
/* Pass the information to our fake IDE and SCSI susbystems. */
xlide_init(&xlblk_disk_info);
xlscsi_init(&xlblk_disk_info);
/* And do the same for the 'virtual block device' world */
xlvbd_init(&xlblk_disk_info);
return 0;
fail:
@@ -611,8 +628,9 @@ int __init xlblk_init(void)
static void __exit xlblk_cleanup(void)
{
xlide_cleanup();
xlvbd_cleanup();
xlscsi_cleanup();
xlide_cleanup();
free_irq(XLBLK_RESPONSE_IRQ, NULL);
}
@@ -21,8 +21,8 @@
#include <linux/blkdev.h>
#include <linux/major.h>
#include <asm/hypervisor-ifs/block.h>
#include <asm/hypervisor-ifs/hypervisor-if.h>
#include <asm/hypervisor-ifs/vbd.h>
#include <asm/io.h>
#include <asm/atomic.h>
#include <asm/uaccess.h>
@@ -101,8 +101,10 @@ extern void xlscsi_cleanup(void);
extern struct gendisk *xlscsi_gendisk;
/* Virtual block-device subsystem. */
extern int xlsegment_hwsect(int minor);
extern struct gendisk *xlsegment_gendisk;
extern int xlvbd_init(xen_disk_info_t *xdi);
extern int xlvbd_hwsect(int minor);
extern void xlvbd_cleanup(void);
extern struct gendisk *xlvbd_gendisk;
extern unsigned short xldev_to_physdev(kdev_t xldev);
extern kdev_t physdev_to_xldev(unsigned short physdev);
@@ -1,337 +0,0 @@
/*
* xl_segment_proc.c
*
* XenoLinux virtual disk proc interface .
*/
#include "xl_block.h"
#include <asm/xeno_proc.h>
#include <linux/delay.h>
#include <linux/seq_file.h>
#include <asm/hypervisor-ifs/segment.h>
static struct proc_dir_entry *vhd;
static void *proc_vhd_next(struct seq_file *s, void *v, loff_t *pos)
{
xen_segment_info_t *data;
if ( pos != NULL )
++(*pos);
data = v;
return data->count-- ? NULL : v;
}
static void *proc_vhd_start(struct seq_file *s, loff_t *ppos)
{
loff_t pos = *ppos;
xen_segment_info_t *data;
data = kmalloc(sizeof(*data), GFP_KERNEL);
xenolinux_control_msg(XEN_BLOCK_PROBE_SEG_ALL, (char *)data, sizeof(*data));
data->count -= pos;
if (data->count > 0)
return data;
kfree(data);
return NULL;
}
static int proc_vhd_show(struct seq_file *s, void *v)
{
xen_segment_info_t *data = v;
seq_printf (s,
"%x %x %10.10s %x\n",
data->segments[data->count - 1].domain,
data->segments[data->count - 1].seg_nr,
data->segments[data->count - 1].key,
data->segments[data->count - 1].mode);
return 0;
}
static void proc_vhd_stop(struct seq_file *s, void *v)
{
kfree(v);
}
static struct seq_operations proc_vhd_op = {
.start = proc_vhd_start,
.next = proc_vhd_next,
.show = proc_vhd_show,
.stop = proc_vhd_stop
};
static int proc_open_vhd(struct inode *inode, struct file *file)
{
return seq_open(file, &proc_vhd_op);
}
#define isdelim(c) \
(c==' '||c==','||c=='\n'||c=='\r'||c=='\t'||c==':'||c=='('||c==')' ? 1 : 0)
char *get_string(char *string) /* a bit like strtok */
{
static char *temp;
int loop = 0;
if (string != NULL)
temp = string;
else
string = temp;
try_again:
while (!isdelim(string[loop]))
{
if (string[loop] == '\0')
return NULL;
loop++;
}
string[loop] = '\0';
temp = (string + loop + 1);
if (loop == 0)
{
string = temp;
goto try_again;
}
return string;
}
#define isdigit(c) (c >= '0' && c <= '9' ? 1 : 0)
unsigned long to_number(char *string) /* atoi */
{
unsigned long value = 0;
if (string == NULL) return 0;
while (!isdigit(*string) && *string != '\0') string++;
while (isdigit(*string))
{
value = value * 10 + (*string - '0');
string++;
}
return value;
}
static int proc_write_vhd(struct file *file, const char *buffer,
size_t count, loff_t *offp)
{
char *local = kmalloc((count + 1) * sizeof(char), GFP_KERNEL);
char *string;
int loop;
xv_disk_t xvd;
int res;
if( !(start_info.flags & SIF_PRIVILEGED) )
return -EPERM;
if (!local)
return -ENOMEM;
memset (&xvd, 0, sizeof(xvd));
if (copy_from_user(local, buffer, count))
{
res = -EFAULT;
goto out;
}
local[count] = '\0';
res = count;
string = get_string(local); /* domain specifier */
if (string == NULL)
{
goto out;
}
if (*string != 'd' && *string != 'D')
{
printk (KERN_ALERT
"error: domain specifier missing [%s]. should be \"domain\".\n",
string);
goto out;
}
string = get_string(NULL); /* domain number */
if (string == NULL)
{
printk (KERN_ALERT "error: domain number missing\n");
goto out;
}
xvd.domain = (int) to_number(string);
string = get_string(NULL);
if (string && (strcmp(string, "RO") == 0 || strcmp(string, "ro") == 0))
{
xvd.mode = XEN_DISK_READ_ONLY;
}
else if (string && (strcmp(string, "RW") == 0 || strcmp(string, "rw") == 0))
{
xvd.mode = XEN_DISK_READ_WRITE;
}
else
{
printk (KERN_ALERT
"error: bad mode [%s]. should be \"rw\" or \"ro\".\n",
string);
goto out;
}
string = get_string(NULL); /* look for Segment */
if (string == NULL || (*string != 's' && *string != 'S'))
{
printk (KERN_ALERT
"error: segment specifier missing [%s]. should be \"segment\".\n",
string);
goto out;
}
string = get_string(NULL); /* segment number */
if (string == NULL)
{
printk (KERN_ALERT "error: segment number missing\n");
goto out;
}
xvd.segment = (int) to_number(string);
string = get_string(NULL); /* look for key */
if (string == NULL || (*string != 'k' && *string != 'K'))
{
printk (KERN_ALERT
"error: key specifier missing [%s]. should be \"key\".\n",
string);
goto out;
}
string = get_string(NULL);
if (string == NULL || strlen(string) != XEN_SEGMENT_KEYSIZE)
{
printk (KERN_ALERT "error: key missing\n");
goto out;
}
memcpy(xvd.key, string, XEN_SEGMENT_KEYSIZE);
string = get_string(NULL); /* look for Extents */
if (string == NULL || (*string != 'e' && *string != 'E'))
{
printk (KERN_ALERT
"error: extents specifier missing [%s]. should be \"extents\".\n",
string);
goto out;
}
string = get_string(NULL); /* number of extents */
if (string == NULL)
{
printk (KERN_ALERT "error: number of extents missing\n");
goto out;
}
xvd.ext_count = (int) to_number(string);
/* ignore parenthesis */
for (loop = 0; loop < xvd.ext_count; loop++)
{
string = get_string(NULL); /* look for Disk */
if (string == NULL || (*string != 'd' && *string != 'D'))
{
printk (KERN_ALERT
"hmm, extent disk specifier missing [%s]. should be \"disk\".\n",
string);
goto out;
}
string = get_string(NULL); /* disk number */
if (string == NULL)
{
printk (KERN_ALERT "error: disk number missing\n");
goto out;
}
xvd.extents[loop].disk = xldev_to_physdev((int) to_number(string));
string = get_string(NULL); /* look for Offset */
if (string == NULL || (*string != 'o' && *string != 'O'))
{
printk (KERN_ALERT
"error: disk offset missing [%s]. should be \"offset\".\n",
string);
goto out;
}
string = get_string(NULL); /* offset */
if (string == NULL)
{
printk (KERN_ALERT "error: offset missing\n");
goto out;
}
xvd.extents[loop].offset = to_number(string);
string = get_string(NULL); /* look for Size */
if (string == NULL || (*string != 's' && *string != 'S'))
{
printk (KERN_ALERT
"error: extent size missing [%s]. should be \"size\".\n",
string);
goto out;
}
string = get_string(NULL); /* size */
if (string == NULL)
{
printk (KERN_ALERT "error: extent size missing\n");
goto out;
}
xvd.extents[loop].size = to_number(string);
}
xenolinux_control_msg(XEN_BLOCK_SEG_CREATE, (char *)&xvd, sizeof(xvd));
out:
kfree(local);
return res;
}
static struct file_operations proc_vhd_operations = {
open: proc_open_vhd,
read: seq_read,
llseek: seq_lseek,
release: seq_release,
write: proc_write_vhd
};
/******************************************************************/
int __init xlseg_proc_init(void)
{
if ( !(start_info.flags & SIF_PRIVILEGED) )
return 0;
vhd = create_xeno_proc_entry("vhd", 0600);
if ( vhd == NULL )
panic ("xlseg_init: unable to create vhd proc entry\n");
vhd->data = NULL;
vhd->proc_fops = &proc_vhd_operations;
vhd->owner = THIS_MODULE;
return 0;
}
static void __exit xlseg_proc_cleanup(void)
{
if ( vhd == NULL ) return;
remove_xeno_proc_entry("vhd");
vhd = NULL;
}
#ifdef MODULE
module_init(xlseg_proc_init);
module_exit(xlseg_proc_cleanup);
#endif
@@ -1,5 +1,5 @@
/******************************************************************************
* xl_segment.c
* xl_vbd.c
*
* Xenolinux virtual block-device driver (xvd).
*
@@ -15,15 +15,13 @@ typedef unsigned char byte;
#define XLVIRT_MAX 256
#define XLVIRT_MAJOR_NAME "xvd"
static int xlseg_blksize_size[XLVIRT_MAX];
static int xlseg_hardsect_size[XLVIRT_MAX];
static int xlseg_max_sectors[XLVIRT_MAX];
static int xlvbd_blksize_size[XLVIRT_MAX];
static int xlvbd_hardsect_size[XLVIRT_MAX];
static int xlvbd_max_sectors[XLVIRT_MAX];
struct gendisk *xlsegment_gendisk = NULL;
struct gendisk *xlvbd_gendisk = NULL;
static xen_disk_info_t xlseg_disk_info;
static struct block_device_operations xlsegment_block_fops =
static struct block_device_operations xlvbd_block_fops =
{
open: xenolinux_block_open,
release: xenolinux_block_release,
@@ -33,51 +31,39 @@ static struct block_device_operations xlsegment_block_fops =
};
int xlsegment_hwsect(int minor)
int xlvbd_hwsect(int minor)
{
return xlseg_hardsect_size[minor];
return xlvbd_hardsect_size[minor];
}
int __init xlseg_init(void)
int __init xlvbd_init(xen_disk_info_t *xdi)
{
int i, result, units, minors, disk;
xen_disk_info_t *xdi = &xlseg_disk_info;
struct gendisk *gd;
SET_MODULE_OWNER(&xlsegment_block_fops);
/* Probe for disk information. */
memset(xdi, 0, sizeof(*xdi));
xenolinux_control_msg(XEN_BLOCK_PROBE_SEG, (char *)xdi, sizeof(*xdi));
DPRINTK("xvd block device probe:\n");
for ( i = 0; i < xdi->count; i++ )
{
DPRINTK(" %2d: device: %d, capacity: %ld\n",
i, xdi->disks[i].device, xdi->disks[i].capacity);
}
SET_MODULE_OWNER(&xlvbd_block_fops);
result = register_blkdev(XLVIRT_MAJOR, XLVIRT_MAJOR_NAME,
&xlsegment_block_fops);
&xlvbd_block_fops);
if ( result < 0 )
{
printk(KERN_ALERT "XL Segment: can't get major %d\n", XLVIRT_MAJOR);
printk(KERN_ALERT "XL VBD: can't get major %d\n", XLVIRT_MAJOR);
return result;
}
/* Initialize global arrays. */
for (i = 0; i < XLVIRT_MAX; i++)
{
xlseg_blksize_size[i] = 512;
xlseg_hardsect_size[i] = 512;
xlseg_max_sectors[i] = 128;
xlvbd_blksize_size[i] = 512;
xlvbd_hardsect_size[i] = 512;
xlvbd_max_sectors[i] = 128;
}
blk_size[XLVIRT_MAJOR] = NULL;
blksize_size[XLVIRT_MAJOR] = xlseg_blksize_size;
hardsect_size[XLVIRT_MAJOR] = xlseg_hardsect_size;
max_sectors[XLVIRT_MAJOR] = xlseg_max_sectors;
blksize_size[XLVIRT_MAJOR] = xlvbd_blksize_size;
hardsect_size[XLVIRT_MAJOR] = xlvbd_hardsect_size;
max_sectors[XLVIRT_MAJOR] = xlvbd_max_sectors;
read_ahead[XLVIRT_MAJOR] = 8;
blk_init_queue(BLK_DEFAULT_QUEUE(XLVIRT_MAJOR), do_xlblk_request);
@@ -102,7 +88,7 @@ int __init xlseg_init(void)
gd->nr_real = units;
gd->real_devices = kmalloc(units * sizeof(xl_disk_t), GFP_KERNEL);
gd->next = NULL;
gd->fops = &xlsegment_block_fops;
gd->fops = &xlvbd_block_fops;
gd->de_arr = kmalloc(sizeof(*gd->de_arr) * units, GFP_KERNEL);
gd->flags = kmalloc(sizeof(*gd->flags) * units, GFP_KERNEL);
memset(gd->sizes, 0, minors * sizeof(int));
@@ -110,7 +96,7 @@ int __init xlseg_init(void)
memset(gd->de_arr, 0, sizeof(*gd->de_arr) * units);
memset(gd->flags, 0, sizeof(*gd->flags) * units);
memset(gd->real_devices, 0, sizeof(xl_disk_t) * units);
xlsegment_gendisk = gd;
xlvbd_gendisk = gd;
add_gendisk(gd);
/* Now register each disk in turn. */
@@ -127,25 +113,25 @@ int __init xlseg_init(void)
register_disk(gd,
MKDEV(XLVIRT_MAJOR, disk<<XLVIRT_PARTN_SHIFT),
1<<XLVIRT_PARTN_SHIFT,
&xlsegment_block_fops,
&xlvbd_block_fops,
xdi->disks[i].capacity);
}
printk(KERN_ALERT
"XenoLinux Virtual Segment Device Driver installed [device: %d]\n",
"XenoLinux Virtual Block Device Driver installed [device: %d]\n",
XLVIRT_MAJOR);
return 0;
}
static void __exit xlseg_cleanup(void)
void xlvbd_cleanup(void)
{
if ( xlsegment_gendisk == NULL ) return;
if ( xlvbd_gendisk == NULL ) return;
blk_cleanup_queue(BLK_DEFAULT_QUEUE(XLVIRT_MAJOR));
xlsegment_gendisk = NULL;
xlvbd_gendisk = NULL;
read_ahead[XLVIRT_MAJOR] = 0;
@@ -170,13 +156,13 @@ static void __exit xlseg_cleanup(void)
if ( unregister_blkdev(XLVIRT_MAJOR, XLVIRT_MAJOR_NAME) != 0 )
{
printk(KERN_ALERT
"XenoLinux Virtual Segment Device Driver"
"XenoLinux Virtual Block Device Driver"
" uninstalled w/ errs\n");
}
}
#ifdef MODULE
module_init(xlseg_init);
module_exit(xlseg_cleanup);
module_init(xlvbd_init);
module_exit(xlvbd_cleanup);
#endif
@@ -1598,8 +1598,6 @@ int __init blk_dev_init(void)
#ifdef CONFIG_XENOLINUX_BLOCK
xlblk_init();
xlseg_init();
xlseg_proc_init();
#endif
return 0;
+1 -1
View File
@@ -5,7 +5,7 @@
#include <linux/blk.h>
#include <linux/slab.h>
#include <linux/genhd.h>
#include <asm/hypervisor-ifs/block.h>
#include <asm/hypervisor-ifs/vbd.h>
#include <linux/pagemap.h>
#include "check.h"
@@ -57,8 +57,6 @@ extern int tapeblock_init(void);
#if defined(CONFIG_XENOLINUX_BLOCK)
extern int xlblk_init(void);
extern int xlseg_init(void);
extern int xlseg_proc_init(void);
#endif /* CONFIG_ARCH_XENO */
extern void set_device_ro(kdev_t dev,int flag);
Reference in new issue
Block a user
Blocking a user prevents them from interacting with repositories, such as opening or commenting on pull requests or issues. Learn more about blocking a user.