aboutsummaryrefslogtreecommitdiffstats
path: root/virt/kvm/kvm_main.c
diff options
context:
space:
mode:
authorAmos Kong <akong@redhat.com>2012-03-08 23:17:32 -0500
committerAvi Kivity <avi@redhat.com>2012-04-08 05:46:58 -0400
commita13007160f1b9ec7c67e28ec9254f197c5c08d7d (patch)
treed5c855d0409ca86323a1bd916cd3e21feba13ff7 /virt/kvm/kvm_main.c
parent83c529151ab0d4a813e3f6a3e293fff75d468519 (diff)
KVM: resize kvm_io_range array dynamically
This patch makes the kvm_io_range array can be resized dynamically. Signed-off-by: Amos Kong <akong@redhat.com> Signed-off-by: Marcelo Tosatti <mtosatti@redhat.com> Signed-off-by: Avi Kivity <avi@redhat.com>
Diffstat (limited to 'virt/kvm/kvm_main.c')
-rw-r--r--virt/kvm/kvm_main.c38
1 files changed, 18 insertions, 20 deletions
diff --git a/virt/kvm/kvm_main.c b/virt/kvm/kvm_main.c
index 42b73930a6de..a9565e240636 100644
--- a/virt/kvm/kvm_main.c
+++ b/virt/kvm/kvm_main.c
@@ -2393,9 +2393,6 @@ int kvm_io_bus_sort_cmp(const void *p1, const void *p2)
2393int kvm_io_bus_insert_dev(struct kvm_io_bus *bus, struct kvm_io_device *dev, 2393int kvm_io_bus_insert_dev(struct kvm_io_bus *bus, struct kvm_io_device *dev,
2394 gpa_t addr, int len) 2394 gpa_t addr, int len)
2395{ 2395{
2396 if (bus->dev_count == NR_IOBUS_DEVS)
2397 return -ENOSPC;
2398
2399 bus->range[bus->dev_count++] = (struct kvm_io_range) { 2396 bus->range[bus->dev_count++] = (struct kvm_io_range) {
2400 .addr = addr, 2397 .addr = addr,
2401 .len = len, 2398 .len = len,
@@ -2495,12 +2492,15 @@ int kvm_io_bus_register_dev(struct kvm *kvm, enum kvm_bus bus_idx, gpa_t addr,
2495 struct kvm_io_bus *new_bus, *bus; 2492 struct kvm_io_bus *new_bus, *bus;
2496 2493
2497 bus = kvm->buses[bus_idx]; 2494 bus = kvm->buses[bus_idx];
2498 if (bus->dev_count > NR_IOBUS_DEVS-1) 2495 if (bus->dev_count > NR_IOBUS_DEVS - 1)
2499 return -ENOSPC; 2496 return -ENOSPC;
2500 2497
2501 new_bus = kmemdup(bus, sizeof(struct kvm_io_bus), GFP_KERNEL); 2498 new_bus = kzalloc(sizeof(*bus) + ((bus->dev_count + 1) *
2499 sizeof(struct kvm_io_range)), GFP_KERNEL);
2502 if (!new_bus) 2500 if (!new_bus)
2503 return -ENOMEM; 2501 return -ENOMEM;
2502 memcpy(new_bus, bus, sizeof(*bus) + (bus->dev_count *
2503 sizeof(struct kvm_io_range)));
2504 kvm_io_bus_insert_dev(new_bus, dev, addr, len); 2504 kvm_io_bus_insert_dev(new_bus, dev, addr, len);
2505 rcu_assign_pointer(kvm->buses[bus_idx], new_bus); 2505 rcu_assign_pointer(kvm->buses[bus_idx], new_bus);
2506 synchronize_srcu_expedited(&kvm->srcu); 2506 synchronize_srcu_expedited(&kvm->srcu);
@@ -2517,27 +2517,25 @@ int kvm_io_bus_unregister_dev(struct kvm *kvm, enum kvm_bus bus_idx,
2517 struct kvm_io_bus *new_bus, *bus; 2517 struct kvm_io_bus *new_bus, *bus;
2518 2518
2519 bus = kvm->buses[bus_idx]; 2519 bus = kvm->buses[bus_idx];
2520
2521 new_bus = kmemdup(bus, sizeof(*bus), GFP_KERNEL);
2522 if (!new_bus)
2523 return -ENOMEM;
2524
2525 r = -ENOENT; 2520 r = -ENOENT;
2526 for (i = 0; i < new_bus->dev_count; i++) 2521 for (i = 0; i < bus->dev_count; i++)
2527 if (new_bus->range[i].dev == dev) { 2522 if (bus->range[i].dev == dev) {
2528 r = 0; 2523 r = 0;
2529 new_bus->dev_count--;
2530 new_bus->range[i] = new_bus->range[new_bus->dev_count];
2531 sort(new_bus->range, new_bus->dev_count,
2532 sizeof(struct kvm_io_range),
2533 kvm_io_bus_sort_cmp, NULL);
2534 break; 2524 break;
2535 } 2525 }
2536 2526
2537 if (r) { 2527 if (r)
2538 kfree(new_bus);
2539 return r; 2528 return r;
2540 } 2529
2530 new_bus = kzalloc(sizeof(*bus) + ((bus->dev_count - 1) *
2531 sizeof(struct kvm_io_range)), GFP_KERNEL);
2532 if (!new_bus)
2533 return -ENOMEM;
2534
2535 memcpy(new_bus, bus, sizeof(*bus) + i * sizeof(struct kvm_io_range));
2536 new_bus->dev_count--;
2537 memcpy(new_bus->range + i, bus->range + i + 1,
2538 (new_bus->dev_count - i) * sizeof(struct kvm_io_range));
2541 2539
2542 rcu_assign_pointer(kvm->buses[bus_idx], new_bus); 2540 rcu_assign_pointer(kvm->buses[bus_idx], new_bus);
2543 synchronize_srcu_expedited(&kvm->srcu); 2541 synchronize_srcu_expedited(&kvm->srcu);