blkfront.c (09c817ba36db7c3a4ff5e25ac55816ca181a403d) blkfront.c (8698b76c3d2dbfbfee3563aac3f5ffc533c0e83d)
1/*-
2 * All rights reserved.
3 *
4 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
5 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
6 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
7 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
8 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
9 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
10 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
11 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
12 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
13 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
14 * SUCH DAMAGE.
15 *
16 */
17
18/*
1/*-
2 * All rights reserved.
3 *
4 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
5 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
6 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
7 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
8 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
9 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
10 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
11 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
12 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
13 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
14 * SUCH DAMAGE.
15 *
16 */
17
18/*
19 * XenoBSD block device driver
19 * XenBSD block device driver
20 *
21 * Copyright (c) 2009 Frank Suchomel, Citrix
20 */
21
22#include <sys/cdefs.h>
23__FBSDID("$FreeBSD$");
24
25#include <sys/param.h>
26#include <sys/systm.h>
27#include <sys/malloc.h>

--- 89 unchanged lines hidden (view full) ---

117
118static void kick_pending_request_queues(struct blkfront_info *);
119static int blkif_open(struct disk *dp);
120static int blkif_close(struct disk *dp);
121static int blkif_ioctl(struct disk *dp, u_long cmd, void *addr, int flag, struct thread *td);
122static int blkif_queue_request(struct bio *bp);
123static void xb_strategy(struct bio *bp);
124
22 */
23
24#include <sys/cdefs.h>
25__FBSDID("$FreeBSD$");
26
27#include <sys/param.h>
28#include <sys/systm.h>
29#include <sys/malloc.h>

--- 89 unchanged lines hidden (view full) ---

119
120static void kick_pending_request_queues(struct blkfront_info *);
121static int blkif_open(struct disk *dp);
122static int blkif_close(struct disk *dp);
123static int blkif_ioctl(struct disk *dp, u_long cmd, void *addr, int flag, struct thread *td);
124static int blkif_queue_request(struct bio *bp);
125static void xb_strategy(struct bio *bp);
126
127// In order to quiesce the device during kernel dumps, outstanding requests to
128// DOM0 for disk reads/writes need to be accounted for.
129static int blkif_queued_requests;
130static int xb_dump(void *, void *, vm_offset_t, off_t, size_t);
125
126
127/* XXX move to xb_vbd.c when VBD update support is added */
128#define MAX_VBDS 64
129
130#define XBD_SECTOR_SIZE 512 /* XXX: assume for now */
131#define XBD_SECTOR_SHFT 9
132

--- 93 unchanged lines hidden (view full) ---

226
227 memset(&sc->xb_disk, 0, sizeof(sc->xb_disk));
228 sc->xb_disk = disk_alloc();
229 sc->xb_disk->d_unit = sc->xb_unit;
230 sc->xb_disk->d_open = blkif_open;
231 sc->xb_disk->d_close = blkif_close;
232 sc->xb_disk->d_ioctl = blkif_ioctl;
233 sc->xb_disk->d_strategy = xb_strategy;
131
132
133/* XXX move to xb_vbd.c when VBD update support is added */
134#define MAX_VBDS 64
135
136#define XBD_SECTOR_SIZE 512 /* XXX: assume for now */
137#define XBD_SECTOR_SHFT 9
138

--- 93 unchanged lines hidden (view full) ---

232
233 memset(&sc->xb_disk, 0, sizeof(sc->xb_disk));
234 sc->xb_disk = disk_alloc();
235 sc->xb_disk->d_unit = sc->xb_unit;
236 sc->xb_disk->d_open = blkif_open;
237 sc->xb_disk->d_close = blkif_close;
238 sc->xb_disk->d_ioctl = blkif_ioctl;
239 sc->xb_disk->d_strategy = xb_strategy;
240 sc->xb_disk->d_dump = xb_dump;
234 sc->xb_disk->d_name = name;
235 sc->xb_disk->d_drv1 = sc;
236 sc->xb_disk->d_sectorsize = sector_size;
237
238 /* XXX */
239 sc->xb_disk->d_mediasize = capacity << XBD_SECTOR_SHFT;
240#if 0
241 sc->xb_disk->d_maxsize = DFLTPHYS;

--- 39 unchanged lines hidden (view full) ---

281 }
282
283 DPRINTK("");
284
285 /*
286 * Place it in the queue of disk activities for this disk
287 */
288 mtx_lock(&blkif_io_lock);
241 sc->xb_disk->d_name = name;
242 sc->xb_disk->d_drv1 = sc;
243 sc->xb_disk->d_sectorsize = sector_size;
244
245 /* XXX */
246 sc->xb_disk->d_mediasize = capacity << XBD_SECTOR_SHFT;
247#if 0
248 sc->xb_disk->d_maxsize = DFLTPHYS;

--- 39 unchanged lines hidden (view full) ---

288 }
289
290 DPRINTK("");
291
292 /*
293 * Place it in the queue of disk activities for this disk
294 */
295 mtx_lock(&blkif_io_lock);
289 bioq_disksort(&sc->xb_bioq, bp);
290
296
297 bioq_disksort(&sc->xb_bioq, bp);
291 xb_startio(sc);
298 xb_startio(sc);
299
292 mtx_unlock(&blkif_io_lock);
293 return;
294
295 bad:
296 /*
297 * Correctly set the bio to indicate a failed tranfer.
298 */
299 bp->bio_resid = bp->bio_bcount;
300 biodone(bp);
301 return;
302}
303
300 mtx_unlock(&blkif_io_lock);
301 return;
302
303 bad:
304 /*
305 * Correctly set the bio to indicate a failed tranfer.
306 */
307 bp->bio_resid = bp->bio_bcount;
308 biodone(bp);
309 return;
310}
311
312static void xb_quiesce(struct blkfront_info *info);
313// Quiesce the disk writes for a dump file before allowing the next buffer.
314static void
315xb_quiesce(struct blkfront_info *info)
316{
317 int mtd;
318
319 // While there are outstanding requests
320 while (blkif_queued_requests) {
321 RING_FINAL_CHECK_FOR_RESPONSES(&info->ring, mtd);
322 if (mtd) {
323 // Recieved request completions, update queue.
324 blkif_int(info);
325 }
326 if (blkif_queued_requests) {
327 // Still pending requests, wait for the disk i/o to complete
328 HYPERVISOR_block();
329 }
330 }
331}
332
333// Some bio structures for dumping core
334#define DUMP_BIO_NO 16 // 16 * 4KB = 64KB dump block
335static struct bio xb_dump_bp[DUMP_BIO_NO];
336
337// Kernel dump function for a paravirtualized disk device
304static int
338static int
339xb_dump(void *arg, void *virtual, vm_offset_t physical, off_t offset,
340 size_t length)
341{
342 int sbp;
343 int mbp;
344 size_t chunk;
345 struct disk *dp = arg;
346 struct xb_softc *sc = (struct xb_softc *) dp->d_drv1;
347 int rc = 0;
348
349 xb_quiesce(sc->xb_info); // All quiet on the western front.
350 if (length > 0) {
351 // If this lock is held, then this module is failing, and a successful
352 // kernel dump is highly unlikely anyway.
353 mtx_lock(&blkif_io_lock);
354 // Split the 64KB block into 16 4KB blocks
355 for (sbp=0; length>0 && sbp<DUMP_BIO_NO; sbp++) {
356 chunk = length > PAGE_SIZE ? PAGE_SIZE : length;
357 xb_dump_bp[sbp].bio_disk = dp;
358 xb_dump_bp[sbp].bio_pblkno = offset / dp->d_sectorsize;
359 xb_dump_bp[sbp].bio_bcount = chunk;
360 xb_dump_bp[sbp].bio_resid = chunk;
361 xb_dump_bp[sbp].bio_data = virtual;
362 xb_dump_bp[sbp].bio_cmd = BIO_WRITE;
363 xb_dump_bp[sbp].bio_done = NULL;
364
365 bioq_disksort(&sc->xb_bioq, &xb_dump_bp[sbp]);
366
367 length -= chunk;
368 offset += chunk;
369 virtual = (char *) virtual + chunk;
370 }
371 // Tell DOM0 to do the I/O
372 xb_startio(sc);
373 mtx_unlock(&blkif_io_lock);
374
375 // Must wait for the completion: the dump routine reuses the same
376 // 16 x 4KB buffer space.
377 xb_quiesce(sc->xb_info); // All quite on the eastern front
378 // If there were any errors, bail out...
379 for (mbp=0; mbp<sbp; mbp++) {
380 if ((rc = xb_dump_bp[mbp].bio_error)) break;
381 }
382 }
383 return (rc);
384}
385
386
387static int
305blkfront_probe(device_t dev)
306{
307
308 if (!strcmp(xenbus_get_type(dev), "vbd")) {
309 device_set_desc(dev, "Virtual Block Device");
310 device_quiet(dev);
311 return (0);
312 }

--- 328 unchanged lines hidden (view full) ---

641static inline int
642GET_ID_FROM_FREELIST(struct blkfront_info *info)
643{
644 unsigned long nfree = info->shadow_free;
645
646 KASSERT(nfree <= BLK_RING_SIZE, ("free %lu > RING_SIZE", nfree));
647 info->shadow_free = info->shadow[nfree].req.id;
648 info->shadow[nfree].req.id = 0x0fffffee; /* debug */
388blkfront_probe(device_t dev)
389{
390
391 if (!strcmp(xenbus_get_type(dev), "vbd")) {
392 device_set_desc(dev, "Virtual Block Device");
393 device_quiet(dev);
394 return (0);
395 }

--- 328 unchanged lines hidden (view full) ---

724static inline int
725GET_ID_FROM_FREELIST(struct blkfront_info *info)
726{
727 unsigned long nfree = info->shadow_free;
728
729 KASSERT(nfree <= BLK_RING_SIZE, ("free %lu > RING_SIZE", nfree));
730 info->shadow_free = info->shadow[nfree].req.id;
731 info->shadow[nfree].req.id = 0x0fffffee; /* debug */
732 atomic_add_int(&blkif_queued_requests, 1);
649 return nfree;
650}
651
652static inline void
653ADD_ID_TO_FREELIST(struct blkfront_info *info, unsigned long id)
654{
655 info->shadow[id].req.id = info->shadow_free;
656 info->shadow[id].request = 0;
657 info->shadow_free = id;
733 return nfree;
734}
735
736static inline void
737ADD_ID_TO_FREELIST(struct blkfront_info *info, unsigned long id)
738{
739 info->shadow[id].req.id = info->shadow_free;
740 info->shadow[id].request = 0;
741 info->shadow_free = id;
742 atomic_subtract_int(&blkif_queued_requests, 1);
658}
659
660static inline void
661flush_requests(struct blkfront_info *info)
662{
663 int notify;
664
665 RING_PUSH_REQUESTS_AND_CHECK_NOTIFY(&info->ring, notify);

--- 456 unchanged lines hidden ---
743}
744
745static inline void
746flush_requests(struct blkfront_info *info)
747{
748 int notify;
749
750 RING_PUSH_REQUESTS_AND_CHECK_NOTIFY(&info->ring, notify);

--- 456 unchanged lines hidden ---