Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

kvm: use insert sort in kvm_io_bus_register_dev function

The loading time of a VM is quite significant with a CPU usage
reaching 100% when loading a VM that its virtio devices use a
large amount of virt-queues (e.g. a virtio-serial device with
max_ports=511). Most of the time is spend in re-sorting the
kvm_io_bus kvm_io_range array when a new eventfd is registered.

The patch replaces the existing method with an insert sort.

Reviewed-by: Marcel Apfelbaum <marcel@redhat.com>
Reviewed-by: Uri Lublin <ulublin@redhat.com>
Signed-off-by: Gal Hammer <ghammer@redhat.com>
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
Signed-off-by: Radim Krčmář <rkrcmar@redhat.com>

authored by

Gal Hammer and committed by
Radim Krčmář
d4c67a7a 01643c51

+18 -18
+18 -18
virt/kvm/kvm_main.c
··· 3398 3398 return kvm_io_bus_cmp(p1, p2); 3399 3399 } 3400 3400 3401 - static int kvm_io_bus_insert_dev(struct kvm_io_bus *bus, struct kvm_io_device *dev, 3402 - gpa_t addr, int len) 3403 - { 3404 - bus->range[bus->dev_count++] = (struct kvm_io_range) { 3405 - .addr = addr, 3406 - .len = len, 3407 - .dev = dev, 3408 - }; 3409 - 3410 - sort(bus->range, bus->dev_count, sizeof(struct kvm_io_range), 3411 - kvm_io_bus_sort_cmp, NULL); 3412 - 3413 - return 0; 3414 - } 3415 - 3416 3401 static int kvm_io_bus_get_first_dev(struct kvm_io_bus *bus, 3417 3402 gpa_t addr, int len) 3418 3403 { ··· 3538 3553 int kvm_io_bus_register_dev(struct kvm *kvm, enum kvm_bus bus_idx, gpa_t addr, 3539 3554 int len, struct kvm_io_device *dev) 3540 3555 { 3556 + int i; 3541 3557 struct kvm_io_bus *new_bus, *bus; 3558 + struct kvm_io_range range; 3542 3559 3543 3560 bus = kvm_get_bus(kvm, bus_idx); 3544 3561 if (!bus) ··· 3554 3567 sizeof(struct kvm_io_range)), GFP_KERNEL); 3555 3568 if (!new_bus) 3556 3569 return -ENOMEM; 3557 - memcpy(new_bus, bus, sizeof(*bus) + (bus->dev_count * 3558 - sizeof(struct kvm_io_range))); 3559 - kvm_io_bus_insert_dev(new_bus, dev, addr, len); 3570 + 3571 + range = (struct kvm_io_range) { 3572 + .addr = addr, 3573 + .len = len, 3574 + .dev = dev, 3575 + }; 3576 + 3577 + for (i = 0; i < bus->dev_count; i++) 3578 + if (kvm_io_bus_cmp(&bus->range[i], &range) > 0) 3579 + break; 3580 + 3581 + memcpy(new_bus, bus, sizeof(*bus) + i * sizeof(struct kvm_io_range)); 3582 + new_bus->dev_count++; 3583 + new_bus->range[i] = range; 3584 + memcpy(new_bus->range + i + 1, bus->range + i, 3585 + (bus->dev_count - i) * sizeof(struct kvm_io_range)); 3560 3586 rcu_assign_pointer(kvm->buses[bus_idx], new_bus); 3561 3587 synchronize_srcu_expedited(&kvm->srcu); 3562 3588 kfree(bus);