debuggers.hg

view xen/drivers/block/xen_segment.c @ 637:f33864f401d8

bitkeeper revision 1.331.1.1 (3f0d5ce2ty7t1xKoi_XfrqGCd6L9mg)

Clean up segments when the domain dies.
author sos22@labyrinth.cl.cam.ac.uk
date Thu Jul 10 12:32:34 2003 +0000 (2003-07-10)
parents 3e071d151e22
children 75e23848b238
line source
1 /*
2 * xen_segment.c
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/segment.h>
11 #include <xeno/sched.h>
12 #include <xeno/blkdev.h>
13 #include <xeno/keyhandler.h>
14 #include <asm/current.h>
15 #include <asm/domain_page.h>
16 #include <hypervisor-ifs/block.h>
18 static segment_t xsegments[XEN_MAX_SEGMENTS];
20 #if 0
21 #define DPRINTK(_f, _a...) printk( _f , ## _a )
22 #else
23 #define DPRINTK(_f, _a...) ((void)0)
24 #endif
26 /* XXX XXX XXX Why are there absolutely no calls to any locking
27 primitives anywhere in this? */
29 /*
30 * xen_segment_map_request
31 *
32 * xen_device must be a valid device.
33 *
34 * NB. All offsets and sizes here are in sector units.
35 * eg. 'size == 1' means an actual size of 512 bytes.
36 */
37 int xen_segment_map_request(
38 phys_seg_t *pseg, struct task_struct *p, int operation,
39 unsigned short segment_number,
40 unsigned long sect_nr, unsigned long buffer, unsigned short nr_sects)
41 {
42 segment_t *seg;
43 extent_t *ext;
44 int sum, i;
46 segment_number &= XENDEV_IDX_MASK;
47 if ( segment_number >= XEN_MAX_SEGMENTS )
48 {
49 DPRINTK("invalid segment number. %d %d\n",
50 segment_number, XEN_MAX_SEGMENTS);
51 goto fail;
52 }
54 seg = p->segment_list[segment_number];
55 if ( seg == NULL )
56 {
57 DPRINTK("segment is null. %d\n", segment_number);
58 goto fail;
59 }
61 /* check domain permissions */
62 if ( seg->domain != p->domain )
63 {
64 DPRINTK("seg is for another domain. %d %d\n", seg->domain, p->domain);
65 goto fail;
66 }
68 /* check rw access */
69 if ( ((operation == WRITE) && (seg->mode != XEN_SEGMENT_RW)) ||
70 ((operation == READ) && (seg->mode == XEN_SEGMENT_UNUSED)) )
71 {
72 DPRINTK("illegal operation: %d %d\n", operation, seg->mode);
73 goto fail;
74 }
76 if ( (nr_sects + sect_nr) <= sect_nr )
77 {
78 DPRINTK("sector + size wrap! %08lx %04x\n", sect_nr, nr_sects);
79 goto fail;
80 }
82 /* find extent, check size */
83 sum = 0;
84 i = 0;
85 ext = seg->extents;
86 while ( (i < seg->num_extents) && ((sum + ext->size) <= sect_nr) )
87 {
88 sum += ext->size;
89 ext++; i++;
90 }
92 if ( (sum + ext->size) <= sect_nr )
93 {
94 DPRINTK("extent size mismatch: %d %d : %d %ld %ld\n",
95 i, seg->num_extents, sum, ext->size, sect_nr);
96 goto fail;
97 }
99 pseg->sector_number = (sect_nr - sum) + ext->offset;
100 pseg->buffer = buffer;
101 pseg->nr_sects = nr_sects;
102 pseg->dev = xendev_to_physdev(ext->disk);
103 if ( pseg->dev == 0 )
104 {
105 DPRINTK ("invalid device 0x%x 0x%lx 0x%lx\n",
106 ext->disk, ext->offset, ext->size);
107 goto fail;
108 }
110 /* We're finished if the virtual extent didn't overrun the phys extent. */
111 if ( (sum + ext->size) >= (sect_nr + nr_sects) )
112 return 1; /* entire read fits in this extent */
114 /* Hmmm... make sure there's another extent to overrun onto! */
115 if ( (i+1) == seg->num_extents )
116 {
117 DPRINTK ("not enough extents %d %d\n",
118 i, seg->num_extents);
119 goto fail;
120 }
122 pseg[1].nr_sects = (sect_nr + nr_sects) - (sum + ext->size);
123 pseg[0].nr_sects = sum + ext->size - sect_nr;
124 pseg[1].buffer = buffer + (pseg->nr_sects << 9);
125 pseg[1].sector_number = ext[1].offset;
126 pseg[1].dev = xendev_to_physdev(ext[1].disk);
127 if ( pseg[1].dev == 0 )
128 {
129 DPRINTK ("bogus device for pseg[1] \n");
130 goto fail;
131 }
133 /* We don't allow overrun onto a third physical extent. */
134 if ( pseg[1].nr_sects > ext[1].size )
135 {
136 DPRINTK ("third extent\n");
137 DPRINTK (" sum:%d, e0:%ld, e1:%ld p1.sect:%ld p1.nr:%d\n",
138 sum, ext[0].size, ext[1].size,
139 pseg[1].sector_number, pseg[1].nr_sects);
140 goto fail;
141 }
143 return 2; /* We overran onto a second physical extent. */
145 fail:
146 DPRINTK ("xen_segment_map_request failure\n");
147 DPRINTK ("operation: %d\n", operation);
148 DPRINTK ("segment number: %d\n", segment_number);
149 DPRINTK ("sect_nr: %ld 0x%lx\n", sect_nr, sect_nr);
150 DPRINTK ("nr_sects: %d 0x%x\n", nr_sects, nr_sects);
151 return -1;
152 }
154 /*
155 * xen_segment_probe
156 *
157 * return a list of segments to the guestos
158 */
159 void xen_segment_probe(struct task_struct *p, xen_disk_info_t *raw_xdi)
160 {
161 int loop, i;
162 xen_disk_info_t *xdi = map_domain_mem(virt_to_phys(raw_xdi));
163 unsigned long capacity = 0, device;
165 for ( loop = 0; loop < XEN_MAX_SEGMENTS; loop++ )
166 {
167 if ( (xsegments[loop].mode == XEN_SEGMENT_UNUSED) ||
168 (xsegments[loop].domain != p->domain) )
169 continue;
171 device = MK_VIRTUAL_XENDEV(xsegments[loop].segment_number);
172 for ( i = 0; i < xsegments[loop].num_extents; i++ )
173 capacity += xsegments[loop].extents[i].size;
175 xdi->disks[xdi->count].device = device;
176 xdi->disks[xdi->count].capacity = capacity;
177 xdi->count++;
178 }
180 unmap_domain_mem(xdi);
181 }
183 /*
184 * xen_segment_probe_all
185 *
186 * return a list of all segments to domain 0
187 */
188 void xen_segment_probe_all(xen_segment_info_t *raw_xsi)
189 {
190 int loop;
191 xen_segment_info_t *xsi = map_domain_mem(virt_to_phys(raw_xsi));
193 xsi->count = 0;
194 for ( loop = 0; loop < XEN_MAX_SEGMENTS; loop++ )
195 {
196 if ( xsegments[loop].mode == XEN_SEGMENT_UNUSED )
197 continue;
199 xsi->segments[xsi->count].mode = xsegments[loop].mode;
200 xsi->segments[xsi->count].domain = xsegments[loop].domain;
201 memcpy(xsi->segments[xsi->count].key,
202 xsegments[loop].key,
203 XEN_SEGMENT_KEYSIZE);
204 xsi->segments[xsi->count].seg_nr = xsegments[loop].segment_number;
205 xsi->count++;
206 }
208 unmap_domain_mem(xsi);
209 }
211 /*
212 * xen_refresh_segment_list
213 *
214 * find all segments associated with a domain and assign
215 * them to the domain
216 */
217 void xen_refresh_segment_list (struct task_struct *p)
218 {
219 int loop;
221 for (loop = 0; loop < XEN_MAX_SEGMENTS; loop++)
222 {
223 if ( (xsegments[loop].mode == XEN_SEGMENT_UNUSED) ||
224 (xsegments[loop].domain != p->domain) )
225 continue;
227 p->segment_list[xsegments[loop].segment_number] = &xsegments[loop];
228 }
229 }
231 /*
232 * create a new segment for a domain
233 *
234 * return 0 on success, 1 on failure
235 *
236 * if we see the same DOM#/SEG# combination, we reuse the slot in
237 * the segment table (overwriting what was there before).
238 * an alternative would be to raise an error if the slot is reused.
239 */
240 int xen_segment_create(xv_disk_t *xvd_in)
241 {
242 int idx;
243 int loop;
244 xv_disk_t *xvd = map_domain_mem(virt_to_phys(xvd_in));
245 struct task_struct *p;
247 for (idx = 0; idx < XEN_MAX_SEGMENTS; idx++)
248 {
249 if (xsegments[idx].mode == XEN_SEGMENT_UNUSED ||
250 (xsegments[idx].domain == xvd->domain &&
251 xsegments[idx].segment_number == xvd->segment)) break;
252 }
253 if (idx == XEN_MAX_SEGMENTS)
254 {
255 printk (KERN_ALERT "xen_segment_create: unable to find free slot\n");
256 unmap_domain_mem(xvd);
257 return 1;
258 }
260 xsegments[idx].mode = xvd->mode;
261 xsegments[idx].domain = xvd->domain;
262 xsegments[idx].segment_number = xvd->segment;
263 memcpy(xsegments[idx].key, xvd->key, XEN_SEGMENT_KEYSIZE);
264 xsegments[idx].num_extents = xvd->ext_count;
265 if (xsegments[idx].extents)
266 kfree(xsegments[idx].extents);
267 xsegments[idx].extents = (extent_t *)kmalloc(
268 sizeof(extent_t)*xvd->ext_count,
269 GFP_KERNEL);
271 /* could memcpy, but this is safer */
272 for (loop = 0; loop < xvd->ext_count; loop++)
273 {
274 xsegments[idx].extents[loop].disk = xvd->extents[loop].disk;
275 xsegments[idx].extents[loop].offset = xvd->extents[loop].offset;
276 xsegments[idx].extents[loop].size = xvd->extents[loop].size;
277 if (xsegments[idx].extents[loop].size == 0)
278 {
279 printk("xen_segment_create: extent %d is zero length\n", loop);
280 unmap_domain_mem(xvd);
281 return 1;
282 }
283 }
285 /* if the domain exists, assign the segment to the domain */
286 p = find_domain_by_id(xvd->domain);
287 if (p != NULL)
288 {
289 p->segment_list[xvd->segment] = &xsegments[idx];
290 put_task_struct(p);
291 }
293 unmap_domain_mem(xvd);
294 return 0;
295 }
297 /*
298 * delete a segment from a domain
299 *
300 * return 0 on success, 1 on failure
301 *
302 */
303 int xen_segment_delete(struct task_struct *p, int segnr)
304 {
305 segment_t *seg;
307 if (!p) {
308 printk("xen_segment delete called with NULL domain?\n");
309 BUG();
310 return 1;
311 }
313 if (segnr < 0 || segnr > XEN_MAX_SEGMENTS) {
314 printk("xen_segment_delete called with bad segnr?\n");
315 BUG();
316 return 1;
317 }
319 if (!p->segment_list[segnr])
320 return 1;
322 seg = p->segment_list[segnr];
324 /* sanity checking */
325 if (seg->domain != p->domain || seg->segment_number != segnr ||
326 (seg->mode != XEN_SEGMENT_RO && seg->mode != XEN_SEGMENT_RW) ||
327 seg->num_extents <= 0 || seg->extents == NULL) {
328 printk("segment is insane!\n");
329 BUG();
330 return 1;
331 }
333 p->segment_list[segnr] = NULL;
334 seg->domain = -1;
335 seg->segment_number = -1;
336 kfree(seg->extents);
337 seg->mode = XEN_SEGMENT_UNUSED;
339 return 0;
340 }
342 static void dump_segments(u_char key, void *dev_id, struct pt_regs *regs)
343 {
344 int loop, i;
345 struct task_struct *p;
347 printk("segment list\n");
348 for (loop = 0; loop < XEN_MAX_SEGMENTS; loop++)
349 {
350 if (xsegments[loop].mode != XEN_SEGMENT_UNUSED)
351 {
352 printk(" %2d: %s dom%d, seg# %d, num_exts: %d\n",
353 loop,
354 xsegments[loop].mode == XEN_SEGMENT_RO ? "RO" : "RW",
355 xsegments[loop].domain, xsegments[loop].segment_number,
356 xsegments[loop].num_extents);
357 for (i = 0; i < xsegments[loop].num_extents; i++)
358 {
359 printk(" extent %d: disk 0x%x, offset 0x%lx, size 0x%lx\n",
360 i, xsegments[loop].extents[i].disk,
361 xsegments[loop].extents[i].offset,
362 xsegments[loop].extents[i].size);
363 }
364 }
365 }
367 printk("segments by domain (index into segments list)\n");
368 p = current;
369 do
370 {
371 printk(" domain %d: ", p->domain);
372 for (loop = 0; loop < XEN_MAX_SEGMENTS; loop++)
373 {
374 if (p->segment_list[loop])
375 {
376 printk (" %d", p->segment_list[loop] - xsegments);
377 }
378 }
379 printk("\n");
380 p = p->next_task;
381 } while (p != current);
382 }
384 /*
385 * initialize segments
386 */
388 void xen_segment_initialize(void)
389 {
390 memset (xsegments, 0, sizeof(xsegments));
392 add_key_handler('S', dump_segments, "dump segments");
393 }