Skip to content

Commit a130071

Browse files
amoskongavikivity
authored andcommitted
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>
1 parent 83c5291 commit a130071

File tree

2 files changed

+21
-22
lines changed

2 files changed

+21
-22
lines changed

include/linux/kvm_host.h

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -68,10 +68,11 @@ struct kvm_io_range {
6868
struct kvm_io_device *dev;
6969
};
7070

71+
#define NR_IOBUS_DEVS 300
72+
7173
struct kvm_io_bus {
7274
int dev_count;
73-
#define NR_IOBUS_DEVS 300
74-
struct kvm_io_range range[NR_IOBUS_DEVS];
75+
struct kvm_io_range range[];
7576
};
7677

7778
enum kvm_bus {

virt/kvm/kvm_main.c

Lines changed: 18 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -2393,9 +2393,6 @@ int kvm_io_bus_sort_cmp(const void *p1, const void *p2)
23932393
int kvm_io_bus_insert_dev(struct kvm_io_bus *bus, struct kvm_io_device *dev,
23942394
gpa_t addr, int len)
23952395
{
2396-
if (bus->dev_count == NR_IOBUS_DEVS)
2397-
return -ENOSPC;
2398-
23992396
bus->range[bus->dev_count++] = (struct kvm_io_range) {
24002397
.addr = addr,
24012398
.len = len,
@@ -2495,12 +2492,15 @@ int kvm_io_bus_register_dev(struct kvm *kvm, enum kvm_bus bus_idx, gpa_t addr,
24952492
struct kvm_io_bus *new_bus, *bus;
24962493

24972494
bus = kvm->buses[bus_idx];
2498-
if (bus->dev_count > NR_IOBUS_DEVS-1)
2495+
if (bus->dev_count > NR_IOBUS_DEVS - 1)
24992496
return -ENOSPC;
25002497

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);
25022500
if (!new_bus)
25032501
return -ENOMEM;
2502+
memcpy(new_bus, bus, sizeof(*bus) + (bus->dev_count *
2503+
sizeof(struct kvm_io_range)));
25042504
kvm_io_bus_insert_dev(new_bus, dev, addr, len);
25052505
rcu_assign_pointer(kvm->buses[bus_idx], new_bus);
25062506
synchronize_srcu_expedited(&kvm->srcu);
@@ -2517,27 +2517,25 @@ int kvm_io_bus_unregister_dev(struct kvm *kvm, enum kvm_bus bus_idx,
25172517
struct kvm_io_bus *new_bus, *bus;
25182518

25192519
bus = kvm->buses[bus_idx];
2520-
2521-
new_bus = kmemdup(bus, sizeof(*bus), GFP_KERNEL);
2522-
if (!new_bus)
2523-
return -ENOMEM;
2524-
25252520
r = -ENOENT;
2526-
for (i = 0; i < new_bus->dev_count; i++)
2527-
if (new_bus->range[i].dev == dev) {
2521+
for (i = 0; i < bus->dev_count; i++)
2522+
if (bus->range[i].dev == dev) {
25282523
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);
25342524
break;
25352525
}
25362526

2537-
if (r) {
2538-
kfree(new_bus);
2527+
if (r)
25392528
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));
25412539

25422540
rcu_assign_pointer(kvm->buses[bus_idx], new_bus);
25432541
synchronize_srcu_expedited(&kvm->srcu);

0 commit comments

Comments
 (0)