diff options
Diffstat (limited to 'drivers/block')
-rw-r--r-- | drivers/block/xen-blkfront.c | 87 |
1 files changed, 78 insertions, 9 deletions
diff --git a/drivers/block/xen-blkfront.c b/drivers/block/xen-blkfront.c index d7aa39e349a6..9cb8668ff5f4 100644 --- a/drivers/block/xen-blkfront.c +++ b/drivers/block/xen-blkfront.c | |||
@@ -120,6 +120,10 @@ static DEFINE_SPINLOCK(minor_lock); | |||
120 | #define EXTENDED (1<<EXT_SHIFT) | 120 | #define EXTENDED (1<<EXT_SHIFT) |
121 | #define VDEV_IS_EXTENDED(dev) ((dev)&(EXTENDED)) | 121 | #define VDEV_IS_EXTENDED(dev) ((dev)&(EXTENDED)) |
122 | #define BLKIF_MINOR_EXT(dev) ((dev)&(~EXTENDED)) | 122 | #define BLKIF_MINOR_EXT(dev) ((dev)&(~EXTENDED)) |
123 | #define EMULATED_HD_DISK_MINOR_OFFSET (0) | ||
124 | #define EMULATED_HD_DISK_NAME_OFFSET (EMULATED_HD_DISK_MINOR_OFFSET / 256) | ||
125 | #define EMULATED_SD_DISK_MINOR_OFFSET (EMULATED_HD_DISK_MINOR_OFFSET + (4 * 16)) | ||
126 | #define EMULATED_SD_DISK_NAME_OFFSET (EMULATED_HD_DISK_NAME_OFFSET + 4) | ||
123 | 127 | ||
124 | #define DEV_NAME "xvd" /* name in /dev */ | 128 | #define DEV_NAME "xvd" /* name in /dev */ |
125 | 129 | ||
@@ -281,7 +285,7 @@ static int blkif_queue_request(struct request *req) | |||
281 | info->shadow[id].request = req; | 285 | info->shadow[id].request = req; |
282 | 286 | ||
283 | ring_req->id = id; | 287 | ring_req->id = id; |
284 | ring_req->sector_number = (blkif_sector_t)blk_rq_pos(req); | 288 | ring_req->u.rw.sector_number = (blkif_sector_t)blk_rq_pos(req); |
285 | ring_req->handle = info->handle; | 289 | ring_req->handle = info->handle; |
286 | 290 | ||
287 | ring_req->operation = rq_data_dir(req) ? | 291 | ring_req->operation = rq_data_dir(req) ? |
@@ -317,7 +321,7 @@ static int blkif_queue_request(struct request *req) | |||
317 | rq_data_dir(req) ); | 321 | rq_data_dir(req) ); |
318 | 322 | ||
319 | info->shadow[id].frame[i] = mfn_to_pfn(buffer_mfn); | 323 | info->shadow[id].frame[i] = mfn_to_pfn(buffer_mfn); |
320 | ring_req->seg[i] = | 324 | ring_req->u.rw.seg[i] = |
321 | (struct blkif_request_segment) { | 325 | (struct blkif_request_segment) { |
322 | .gref = ref, | 326 | .gref = ref, |
323 | .first_sect = fsect, | 327 | .first_sect = fsect, |
@@ -434,6 +438,65 @@ static void xlvbd_flush(struct blkfront_info *info) | |||
434 | info->feature_flush ? "enabled" : "disabled"); | 438 | info->feature_flush ? "enabled" : "disabled"); |
435 | } | 439 | } |
436 | 440 | ||
441 | static int xen_translate_vdev(int vdevice, int *minor, unsigned int *offset) | ||
442 | { | ||
443 | int major; | ||
444 | major = BLKIF_MAJOR(vdevice); | ||
445 | *minor = BLKIF_MINOR(vdevice); | ||
446 | switch (major) { | ||
447 | case XEN_IDE0_MAJOR: | ||
448 | *offset = (*minor / 64) + EMULATED_HD_DISK_NAME_OFFSET; | ||
449 | *minor = ((*minor / 64) * PARTS_PER_DISK) + | ||
450 | EMULATED_HD_DISK_MINOR_OFFSET; | ||
451 | break; | ||
452 | case XEN_IDE1_MAJOR: | ||
453 | *offset = (*minor / 64) + 2 + EMULATED_HD_DISK_NAME_OFFSET; | ||
454 | *minor = (((*minor / 64) + 2) * PARTS_PER_DISK) + | ||
455 | EMULATED_HD_DISK_MINOR_OFFSET; | ||
456 | break; | ||
457 | case XEN_SCSI_DISK0_MAJOR: | ||
458 | *offset = (*minor / PARTS_PER_DISK) + EMULATED_SD_DISK_NAME_OFFSET; | ||
459 | *minor = *minor + EMULATED_SD_DISK_MINOR_OFFSET; | ||
460 | break; | ||
461 | case XEN_SCSI_DISK1_MAJOR: | ||
462 | case XEN_SCSI_DISK2_MAJOR: | ||
463 | case XEN_SCSI_DISK3_MAJOR: | ||
464 | case XEN_SCSI_DISK4_MAJOR: | ||
465 | case XEN_SCSI_DISK5_MAJOR: | ||
466 | case XEN_SCSI_DISK6_MAJOR: | ||
467 | case XEN_SCSI_DISK7_MAJOR: | ||
468 | *offset = (*minor / PARTS_PER_DISK) + | ||
469 | ((major - XEN_SCSI_DISK1_MAJOR + 1) * 16) + | ||
470 | EMULATED_SD_DISK_NAME_OFFSET; | ||
471 | *minor = *minor + | ||
472 | ((major - XEN_SCSI_DISK1_MAJOR + 1) * 16 * PARTS_PER_DISK) + | ||
473 | EMULATED_SD_DISK_MINOR_OFFSET; | ||
474 | break; | ||
475 | case XEN_SCSI_DISK8_MAJOR: | ||
476 | case XEN_SCSI_DISK9_MAJOR: | ||
477 | case XEN_SCSI_DISK10_MAJOR: | ||
478 | case XEN_SCSI_DISK11_MAJOR: | ||
479 | case XEN_SCSI_DISK12_MAJOR: | ||
480 | case XEN_SCSI_DISK13_MAJOR: | ||
481 | case XEN_SCSI_DISK14_MAJOR: | ||
482 | case XEN_SCSI_DISK15_MAJOR: | ||
483 | *offset = (*minor / PARTS_PER_DISK) + | ||
484 | ((major - XEN_SCSI_DISK8_MAJOR + 8) * 16) + | ||
485 | EMULATED_SD_DISK_NAME_OFFSET; | ||
486 | *minor = *minor + | ||
487 | ((major - XEN_SCSI_DISK8_MAJOR + 8) * 16 * PARTS_PER_DISK) + | ||
488 | EMULATED_SD_DISK_MINOR_OFFSET; | ||
489 | break; | ||
490 | case XENVBD_MAJOR: | ||
491 | *offset = *minor / PARTS_PER_DISK; | ||
492 | break; | ||
493 | default: | ||
494 | printk(KERN_WARNING "blkfront: your disk configuration is " | ||
495 | "incorrect, please use an xvd device instead\n"); | ||
496 | return -ENODEV; | ||
497 | } | ||
498 | return 0; | ||
499 | } | ||
437 | 500 | ||
438 | static int xlvbd_alloc_gendisk(blkif_sector_t capacity, | 501 | static int xlvbd_alloc_gendisk(blkif_sector_t capacity, |
439 | struct blkfront_info *info, | 502 | struct blkfront_info *info, |
@@ -441,7 +504,7 @@ static int xlvbd_alloc_gendisk(blkif_sector_t capacity, | |||
441 | { | 504 | { |
442 | struct gendisk *gd; | 505 | struct gendisk *gd; |
443 | int nr_minors = 1; | 506 | int nr_minors = 1; |
444 | int err = -ENODEV; | 507 | int err; |
445 | unsigned int offset; | 508 | unsigned int offset; |
446 | int minor; | 509 | int minor; |
447 | int nr_parts; | 510 | int nr_parts; |
@@ -456,12 +519,20 @@ static int xlvbd_alloc_gendisk(blkif_sector_t capacity, | |||
456 | } | 519 | } |
457 | 520 | ||
458 | if (!VDEV_IS_EXTENDED(info->vdevice)) { | 521 | if (!VDEV_IS_EXTENDED(info->vdevice)) { |
459 | minor = BLKIF_MINOR(info->vdevice); | 522 | err = xen_translate_vdev(info->vdevice, &minor, &offset); |
460 | nr_parts = PARTS_PER_DISK; | 523 | if (err) |
524 | return err; | ||
525 | nr_parts = PARTS_PER_DISK; | ||
461 | } else { | 526 | } else { |
462 | minor = BLKIF_MINOR_EXT(info->vdevice); | 527 | minor = BLKIF_MINOR_EXT(info->vdevice); |
463 | nr_parts = PARTS_PER_EXT_DISK; | 528 | nr_parts = PARTS_PER_EXT_DISK; |
529 | offset = minor / nr_parts; | ||
530 | if (xen_hvm_domain() && offset <= EMULATED_HD_DISK_NAME_OFFSET + 4) | ||
531 | printk(KERN_WARNING "blkfront: vdevice 0x%x might conflict with " | ||
532 | "emulated IDE disks,\n\t choose an xvd device name" | ||
533 | "from xvde on\n", info->vdevice); | ||
464 | } | 534 | } |
535 | err = -ENODEV; | ||
465 | 536 | ||
466 | if ((minor % nr_parts) == 0) | 537 | if ((minor % nr_parts) == 0) |
467 | nr_minors = nr_parts; | 538 | nr_minors = nr_parts; |
@@ -475,8 +546,6 @@ static int xlvbd_alloc_gendisk(blkif_sector_t capacity, | |||
475 | if (gd == NULL) | 546 | if (gd == NULL) |
476 | goto release; | 547 | goto release; |
477 | 548 | ||
478 | offset = minor / nr_parts; | ||
479 | |||
480 | if (nr_minors > 1) { | 549 | if (nr_minors > 1) { |
481 | if (offset < 26) | 550 | if (offset < 26) |
482 | sprintf(gd->disk_name, "%s%c", DEV_NAME, 'a' + offset); | 551 | sprintf(gd->disk_name, "%s%c", DEV_NAME, 'a' + offset); |
@@ -615,7 +684,7 @@ static void blkif_completion(struct blk_shadow *s) | |||
615 | { | 684 | { |
616 | int i; | 685 | int i; |
617 | for (i = 0; i < s->req.nr_segments; i++) | 686 | for (i = 0; i < s->req.nr_segments; i++) |
618 | gnttab_end_foreign_access(s->req.seg[i].gref, 0, 0UL); | 687 | gnttab_end_foreign_access(s->req.u.rw.seg[i].gref, 0, 0UL); |
619 | } | 688 | } |
620 | 689 | ||
621 | static irqreturn_t blkif_interrupt(int irq, void *dev_id) | 690 | static irqreturn_t blkif_interrupt(int irq, void *dev_id) |
@@ -932,7 +1001,7 @@ static int blkif_recover(struct blkfront_info *info) | |||
932 | /* Rewrite any grant references invalidated by susp/resume. */ | 1001 | /* Rewrite any grant references invalidated by susp/resume. */ |
933 | for (j = 0; j < req->nr_segments; j++) | 1002 | for (j = 0; j < req->nr_segments; j++) |
934 | gnttab_grant_foreign_access_ref( | 1003 | gnttab_grant_foreign_access_ref( |
935 | req->seg[j].gref, | 1004 | req->u.rw.seg[j].gref, |
936 | info->xbdev->otherend_id, | 1005 | info->xbdev->otherend_id, |
937 | pfn_to_mfn(info->shadow[req->id].frame[j]), | 1006 | pfn_to_mfn(info->shadow[req->id].frame[j]), |
938 | rq_data_dir(info->shadow[req->id].request)); | 1007 | rq_data_dir(info->shadow[req->id].request)); |