diff options
author | Amos Kong <akong@redhat.com> | 2012-03-08 23:17:32 -0500 |
---|---|---|
committer | Avi Kivity <avi@redhat.com> | 2012-04-08 05:46:58 -0400 |
commit | a13007160f1b9ec7c67e28ec9254f197c5c08d7d (patch) | |
tree | d5c855d0409ca86323a1bd916cd3e21feba13ff7 /virt | |
parent | 83c529151ab0d4a813e3f6a3e293fff75d468519 (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')
-rw-r--r-- | virt/kvm/kvm_main.c | 38 |
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) | |||
2393 | int kvm_io_bus_insert_dev(struct kvm_io_bus *bus, struct kvm_io_device *dev, | 2393 | int 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); |