Hyper-V, Microsofts Hypervisor für Windows, bringt standardmässig nur eine Unterstützung für SuSE Enterprise Linux mit. Für diese liefert Microsoft eine Treiber-CD, damit Linux die Integration Services ansprechen kann und damit optimale Performance bietet. Möchte man aber mit einer anderen Distribution die optimale Performance erreichen, muss man selber Hand anlegen. Lesen Sie dazu weiter...
Die Treiber-CD (herunterladbar unter http://connect.microsoft.com) enthält nebst einem Setup-Programm (Perl-Skript) und diverse Skripte für die Integration in das Linux-System die Treiber für die Integration Services. Diese bestehen aus zwei Teilen: ein freier Teil in Source-Code Form sowie einem Closed-Teil, der zu den Kernelmodulen gelinkt werden.
Da icER oft nebst den Enterprise Linux Varianten auch Ubuntu einsetzt, würden wir es begrüssen, wenn es eine Unterstützung für Ubuntu geben würde. Bis dato ist das aber nicht der Fall so haben wir mal begonnen, die Quellcodes anzupassen, so dass sich diese mit moderneren Kerneln kompilieren lassen. Hier mal unser momentanes Ergebnis:
diff -ru /media/cdrom0/drivers/dist/blkvsc/blkvsc_drv.c /home/eisi/icER/hyperv/cdrom/drivers/dist/blkvsc/blkvsc_drv.c
--- /media/cdrom0/drivers/dist/blkvsc/blkvsc_drv.c 2008-08-15 04:47:57.000000000 +0200
+++ /home/eisi/icER/hyperv/cdrom/drivers/dist/blkvsc/blkvsc_drv.c 2008-11-15 16:04:32.000000000 +0100
@@ -87,7 +87,7 @@
// Per device structure
struct block_device_context {
struct device_context *device_ctx; // point back to our device context
- kmem_cache_t *request_pool;
+ struct kmem_cache *request_pool;
spinlock_t lock;
struct gendisk *gd;
enum blkvsc_device_type device_type;
@@ -310,7 +310,7 @@
blkdev->request_pool = kmem_cache_create(device_ctx->device.bus_id,
sizeof(struct blkvsc_request) + storvsc_drv_obj->RequestExtSize, 0,
- SLAB_HWCACHE_ALIGN, NULL, NULL);
+ SLAB_HWCACHE_ALIGN, NULL);
if (!blkdev->request_pool)
{
ret = -ENOMEM;
@@ -986,14 +986,11 @@
start_sector = req->sector;
- // foreach bio in the request
- rq_for_each_bio (bio, req)
+ struct req_iterator iter;
+ rq_for_each_segment(bvec, req, iter)
{
- // Map this bio into an existing or new storvsc request
- bio_for_each_segment (bvec, bio, seg_idx)
- {
- DPRINT_DBG(BLKVSC_DRV, "bio_for_each_segment() - req %p bio %p bvec %p seg_idx %d databuf_idx %d\n",
- req, bio, bvec, seg_idx, databuf_idx);
+ DPRINT_DBG(BLKVSC_DRV, "bio_for_each_segment() - req %p bio %p bvec %p databuf_idx %d\n",
+ req, bio, bvec, databuf_idx);
// Get a new storvsc request
if ( (!blkvsc_req) || // 1st-time
@@ -1053,9 +1050,7 @@
databuf_idx++;
num_sectors += bvec->bv_len >> 9;
- } // bio_for_each_segment
-
- } // rq_for_each_bio
+ } // rq_for_each_segment
// Handle the last one
if (blkvsc_req)
diff -ru /media/cdrom0/drivers/dist/netvsc/netvsc_drv.c /home/eisi/icER/hyperv/cdrom/drivers/dist/netvsc/netvsc_drv.c
--- /media/cdrom0/drivers/dist/netvsc/netvsc_drv.c 2008-08-15 04:47:57.000000000 +0200
+++ /home/eisi/icER/hyperv/cdrom/drivers/dist/netvsc/netvsc_drv.c 2008-11-15 20:48:21.000000000 +0100
@@ -24,6 +24,7 @@
#include
#include
#include
+#include
#include
#include
#include
@@ -222,7 +223,9 @@
//net->change_mtu = netvsc_change_mtu;
//SET_ETHTOOL_OPS(net, &network_ethtool_ops);
- SET_MODULE_OWNER(net);
+//#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,24))
+// SET_MODULE_OWNER(net);
+//#endif
SET_NETDEV_DEV(net, device);
ret = register_netdev(net);
diff -ru /media/cdrom0/drivers/dist/storvsc/storvsc_drv.c /home/eisi/icER/hyperv/cdrom/drivers/dist/storvsc/storvsc_drv.c
--- /media/cdrom0/drivers/dist/storvsc/storvsc_drv.c 2008-08-15 04:47:57.000000000 +0200
+++ /home/eisi/icER/hyperv/cdrom/drivers/dist/storvsc/storvsc_drv.c 2008-11-15 20:47:40.000000000 +0100
@@ -49,7 +49,7 @@
//
struct host_device_context {
struct device_context *device_ctx; // point back to our device context
- kmem_cache_t *request_pool;
+ struct kmem_cache *request_pool;
unsigned int port;
unsigned char path;
unsigned char target;
@@ -275,13 +275,13 @@
#if defined(KERNEL_2_6_5) || defined(KERNEL_2_6_9)
#else
- INIT_WORK(&host_device_ctx->host_rescan_work, storvsc_host_rescan_callback, device_obj);
+ INIT_WORK(&host_device_ctx->host_rescan_work, storvsc_host_rescan_callback);
#endif
host_device_ctx->device_ctx = device_ctx;
host_device_ctx->request_pool = kmem_cache_create(device_ctx->device.bus_id,
sizeof(struct storvsc_cmd_request) + storvsc_drv_obj->RequestExtSize, 0,
- SLAB_HWCACHE_ALIGN, NULL, NULL);
+ SLAB_HWCACHE_ALIGN, NULL);
if (!host_device_ctx->request_pool)
{
scsi_host_put(host);
@@ -489,26 +489,31 @@
{
int i;
int num_pages=0;
- struct scatterlist* bounce_sgl;
+ struct scatterlist *bounce_sgl, *sgentry;
num_pages = ALIGN_UP(len, PAGE_SIZE) >> PAGE_SHIFT;
-
+
+ sg_init_table(bounce_sgl, num_pages);
+
+/*
bounce_sgl = kzalloc(num_pages * sizeof(struct scatterlist), GFP_ATOMIC);
if (!bounce_sgl)
{
return NULL;
}
+*/
- for(i=0; i< PAGE_SIZE
@@ -616,14 +622,14 @@
for (i=0; i<= PAGE_SIZE);
if (j == 0)
{
- bounce_addr = (unsigned long)kmap_atomic(bounce_sgl[j].page, KM_IRQ0);
+ bounce_addr = (unsigned long)kmap_atomic(sg_page(&bounce_sgl[j]), KM_IRQ0);
}
while (destlen)
@@ -647,7 +653,7 @@
// if we need to use another bounce buffer
if (destlen || i != orig_sgl_count -1)
{
- bounce_addr = (unsigned long)kmap_atomic(bounce_sgl[j].page, KM_IRQ0);
+ bounce_addr = (unsigned long)kmap_atomic(sg_page(&bounce_sgl[j]), KM_IRQ0);
}
}
else if (destlen == 0 && i == orig_sgl_count -1) // unmap the last bounce that is < PAGE_SIZE
@@ -807,7 +813,7 @@
{
DPRINT_DBG(STORVSC_DRV, "sgl[%d] len %d offset %d \n", i, sgl[i].length, sgl[i].offset);
- request->DataBuffer.PfnArray[i] = page_to_pfn(sgl[i].page);
+ request->DataBuffer.PfnArray[i] = page_to_pfn(sg_page(&sgl[i]));
}
}
else if (scmnd->request_buffer)
diff -ru /media/cdrom0/drivers/dist/vmbus/osd.c /home/eisi/icER/hyperv/cdrom/drivers/dist/vmbus/osd.c
--- /media/cdrom0/drivers/dist/vmbus/osd.c 2008-08-15 04:47:57.000000000 +0200
+++ /home/eisi/icER/hyperv/cdrom/drivers/dist/vmbus/osd.c 2008-11-15 13:23:11.000000000 +0100
@@ -457,7 +457,7 @@
w->callback = workItem,
w->context = context;
- INIT_WORK(&w->work, WorkItemCallback, w);
+ INIT_WORK(&w->work, WorkItemCallback);
return queue_work(wq->queue, &w->work);
}
@@ -473,7 +473,7 @@
w->callback = workItem,
w->context = context;
- INIT_WORK(&w->work, WorkItemCallback, w);
+ INIT_WORK(&w->work, WorkItemCallback);
schedule_work(&w->work);
}
diff -ru /media/cdrom0/drivers/dist/vmbus/vmbus_drv.c /home/eisi/icER/hyperv/cdrom/drivers/dist/vmbus/vmbus_drv.c
--- /media/cdrom0/drivers/dist/vmbus/vmbus_drv.c 2008-08-15 04:47:57.000000000 +0200
+++ /home/eisi/icER/hyperv/cdrom/drivers/dist/vmbus/vmbus_drv.c 2008-11-15 14:23:42.000000000 +0100
@@ -389,7 +389,7 @@
// Get the interrupt resource
ret = request_irq(vmbus_irq,
vmbus_isr,
- SA_SAMPLE_RANDOM,
+ 0/*SA_SAMPLE_RANDOM*/,
vmbus_drv_obj->Base.name,
NULL);
@@ -845,7 +845,7 @@
{
DPRINT_ERR(VMBUS_DRV, "probe() failed for device %s (%p) on driver %s (%d)...", child_device->bus_id, child_device, child_device->driver->name, ret);
- INIT_WORK(&device_ctx->probe_failed_work_item, vmbus_probe_failed_cb, device_ctx);
+ INIT_WORK(&device_ctx->probe_failed_work_item, vmbus_probe_failed_cb);
schedule_work(&device_ctx->probe_failed_work_item);
}
}
@@ -1088,7 +1088,7 @@
"Vmbus initializing.... current log level 0x%x (%x,%x)",
vmbus_loglevel, HIWORD(vmbus_loglevel), LOWORD(vmbus_loglevel));
- vmbus_ctl_table_hdr = register_sysctl_table(vmus_root_ctl_table, 0);
+ vmbus_ctl_table_hdr = register_sysctl_table(vmus_root_ctl_table);
if (!vmbus_ctl_table_hdr)
{
DPRINT_EXIT(VMBUS_DRV);
Wichtiger Hinweis: Diese Modifikationen sind rudimentär: Sie erlauben lediglich das Kompilieren mit Warnungen. Ebenso fehlt die Anpassung der Skripte, damit die Treiber sauber auf einem Ubuntu System integriert werden können.
Gerne nehmen wir auch weitere Inputs entgegen: