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 --- |