ia64/xen-unstable

view xen/drivers/block/xen_vbd.c @ 897:38ad3cea577f

bitkeeper revision 1.565 (3fa916a9omQrijJLZBNMaip_G452lQ)

tweak
author smh22@labyrinth.cl.cam.ac.uk
date Wed Nov 05 15:26:33 2003 +0000 (2003-11-05)
parents 352a82eb57ad
children 4aba3a48d64f 0a901de56d7c
line source
1 /*
2 * xen_vbd.c : routines for managing virtual block devices
3 */
5 #include <xeno/config.h>
6 #include <xeno/types.h>
7 #include <xeno/lib.h>
8 #include <asm/io.h>
9 #include <xeno/slab.h>
10 #include <xeno/sched.h>
11 #include <xeno/vbd.h>
12 #include <xeno/blkdev.h>
13 #include <xeno/keyhandler.h>
14 #include <asm/current.h>
15 #include <asm/domain_page.h>
18 #if 0
19 #define DPRINTK(_f, _a...) printk( _f , ## _a )
20 #else
21 #define DPRINTK(_f, _a...) ((void)0)
22 #endif
25 /* XXX SMH: crappy 'hash function' .. fix when care. */
26 #define HSH(_x) (((_x) >> 6) & (VBD_HTAB_SZ - 1))
28 /*
29 ** Create a new VBD; all this involves is adding an entry to the domain's
30 ** vbd hash table.
31 */
32 long vbd_create(vbd_create_t *create_info)
33 {
34 struct task_struct *p;
35 vbd_t *new_vbd, *v;
36 int h;
38 p = find_domain_by_id(create_info->domain);
40 if (!p) {
41 printk("vbd_create attempted for non-existent domain %d\n",
42 create_info->domain);
43 return -EINVAL;
44 }
46 new_vbd = kmalloc(sizeof(vbd_t), GFP_KERNEL);
47 new_vbd->vdevice = create_info->vdevice;
48 new_vbd->mode = create_info->mode;
49 new_vbd->extents = (xen_extent_le_t *)NULL;
50 new_vbd->next = (vbd_t *)NULL;
52 h = HSH(create_info->vdevice);
53 if(p->vbdtab[h]) {
54 for(v = p->vbdtab[h]; v->next; v = v->next)
55 ;
56 v->next = new_vbd;
57 } else p->vbdtab[h] = new_vbd;
59 put_task_struct(p);
61 return 0;
62 }
64 /*
65 ** Add an extent to an existing VBD; fails if the VBD doesn't exist.
66 ** Doesn't worry about overlapping extents (e.g. merging etc) for now.
67 */
68 long vbd_add(vbd_add_t *add_info)
69 {
70 struct task_struct *p;
71 xen_extent_le_t *x, *xele;
72 vbd_t *v;
73 int h;
75 p = find_domain_by_id(add_info->domain);
77 if (!p) {
78 printk("vbd_add attempted for non-existent domain %d\n",
79 add_info->domain);
80 return -EINVAL;
81 }
83 h = HSH(add_info->vdevice);
85 for(v = p->vbdtab[h]; v; v = v->next)
86 if(v->vdevice == add_info->vdevice)
87 break;
89 if(!v) {
90 printk("vbd_add; attempted to add extent to non-existent VBD.\n");
91 return -EINVAL;
92 }
94 xele = kmalloc(sizeof(xen_extent_le_t), GFP_KERNEL);
95 xele->extent.device = add_info->extent.device;
96 xele->extent.start_sector = add_info->extent.start_sector;
97 xele->extent.nr_sectors = add_info->extent.nr_sectors;
98 xele->next = (xen_extent_le_t *)NULL;
100 if(!v->extents) {
101 v->extents = xele;
102 } else {
103 for(x = v->extents; x->next; x = x->next)
104 ;
105 x->next = xele;
106 }
108 put_task_struct(p);
109 return 0;
110 }
112 long vbd_remove(vbd_remove_t *remove_info)
113 {
114 return -ENOSYS;
115 }
117 long vbd_delete(vbd_delete_t *delete_info)
118 {
119 return -ENOSYS;
120 }
123 int vbd_translate(phys_seg_t * pseg, int *nr_segs,
124 struct task_struct *p, int operation)
125 {
126 xen_extent_le_t *x;
127 vbd_t *v;
128 int h;
129 long sec;
131 h = HSH(pseg->dev);
133 for(v = p->vbdtab[h]; v; v = v->next)
134 if(v->vdevice == pseg->dev)
135 break;
137 if(!v) {
138 if(!IS_PRIV(p))
139 printk("vbd_translate; domain %d attempted to access "
140 "non-existent VBD.\n", p->domain);
141 return -ENODEV;
142 }
144 if(operation == READ && !VBD_CAN_READ(v))
145 return -EACCES;
147 if(operation == WRITE && !VBD_CAN_WRITE(v))
148 return -EACCES;
151 /* Now iterate through the list of xen_extents, working out which
152 should be used to perform the translation. */
153 sec = pseg->sector_number;
154 for(x = v->extents; x; x = x->next) {
156 if(sec < x->extent.nr_sectors) {
158 /* we've got a match! XXX SMH: should deal with
159 situation where we span multiple xe's */
161 pseg->dev = x->extent.device;
162 pseg->sector_number += x->extent.start_sector;
164 return 0;
166 }
168 sec -= x->extent.nr_sectors;
169 }
171 /* No luck -- return no access */
172 return -EACCES;
173 }
176 /*
177 * vbd_probe_devices:
178 *
179 * add the virtual block devices for this domain to a xen_disk_info_t;
180 * we assume xdi->count points to the first unused place in the array.
181 */
182 void vbd_probe_devices(xen_disk_info_t *xdi, struct task_struct *p)
183 {
184 xen_extent_le_t *x;
185 vbd_t *v;
186 int i;
188 /* XXX SMH: should allow priv domains to probe vbds for other doms XXX */
190 for(i = 0; i < VBD_HTAB_SZ; i++) {
191 for(v = p->vbdtab[i]; v; v = v->next) {
193 xdi->disks[xdi->count].device = v->vdevice;
194 xdi->disks[xdi->count].info = XD_FLAG_VIRT | XD_TYPE_DISK;
196 if(!VBD_CAN_WRITE(v))
197 xdi->disks[xdi->count].info |= XD_FLAG_RO;
199 xdi->disks[xdi->count].capacity = 0;
200 for(x = v->extents; x; x = x->next)
201 xdi->disks[xdi->count].capacity += x->extent.nr_sectors;
202 xdi->count++;
203 }
204 }
206 return;
207 }