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>
This commit is contained in:
		
							parent
							
								
									83c529151a
								
							
						
					
					
						commit
						a13007160f
					
				| @ -68,10 +68,11 @@ struct kvm_io_range { | ||||
| 	struct kvm_io_device *dev; | ||||
| }; | ||||
| 
 | ||||
| #define NR_IOBUS_DEVS 300 | ||||
| 
 | ||||
| struct kvm_io_bus { | ||||
| 	int                   dev_count; | ||||
| #define NR_IOBUS_DEVS 300 | ||||
| 	struct kvm_io_range range[NR_IOBUS_DEVS]; | ||||
| 	struct kvm_io_range range[]; | ||||
| }; | ||||
| 
 | ||||
| enum kvm_bus { | ||||
|  | ||||
| @ -2393,9 +2393,6 @@ int kvm_io_bus_sort_cmp(const void *p1, const void *p2) | ||||
| int kvm_io_bus_insert_dev(struct kvm_io_bus *bus, struct kvm_io_device *dev, | ||||
| 			  gpa_t addr, int len) | ||||
| { | ||||
| 	if (bus->dev_count == NR_IOBUS_DEVS) | ||||
| 		return -ENOSPC; | ||||
| 
 | ||||
| 	bus->range[bus->dev_count++] = (struct kvm_io_range) { | ||||
| 		.addr = addr, | ||||
| 		.len = len, | ||||
| @ -2495,12 +2492,15 @@ int kvm_io_bus_register_dev(struct kvm *kvm, enum kvm_bus bus_idx, gpa_t addr, | ||||
| 	struct kvm_io_bus *new_bus, *bus; | ||||
| 
 | ||||
| 	bus = kvm->buses[bus_idx]; | ||||
| 	if (bus->dev_count > NR_IOBUS_DEVS-1) | ||||
| 	if (bus->dev_count > NR_IOBUS_DEVS - 1) | ||||
| 		return -ENOSPC; | ||||
| 
 | ||||
| 	new_bus = kmemdup(bus, sizeof(struct kvm_io_bus), GFP_KERNEL); | ||||
| 	new_bus = kzalloc(sizeof(*bus) + ((bus->dev_count + 1) * | ||||
| 			  sizeof(struct kvm_io_range)), GFP_KERNEL); | ||||
| 	if (!new_bus) | ||||
| 		return -ENOMEM; | ||||
| 	memcpy(new_bus, bus, sizeof(*bus) + (bus->dev_count * | ||||
| 	       sizeof(struct kvm_io_range))); | ||||
| 	kvm_io_bus_insert_dev(new_bus, dev, addr, len); | ||||
| 	rcu_assign_pointer(kvm->buses[bus_idx], new_bus); | ||||
| 	synchronize_srcu_expedited(&kvm->srcu); | ||||
| @ -2517,27 +2517,25 @@ int kvm_io_bus_unregister_dev(struct kvm *kvm, enum kvm_bus bus_idx, | ||||
| 	struct kvm_io_bus *new_bus, *bus; | ||||
| 
 | ||||
| 	bus = kvm->buses[bus_idx]; | ||||
| 
 | ||||
| 	new_bus = kmemdup(bus, sizeof(*bus), GFP_KERNEL); | ||||
| 	if (!new_bus) | ||||
| 		return -ENOMEM; | ||||
| 
 | ||||
| 	r = -ENOENT; | ||||
| 	for (i = 0; i < new_bus->dev_count; i++) | ||||
| 		if (new_bus->range[i].dev == dev) { | ||||
| 	for (i = 0; i < bus->dev_count; i++) | ||||
| 		if (bus->range[i].dev == dev) { | ||||
| 			r = 0; | ||||
| 			new_bus->dev_count--; | ||||
| 			new_bus->range[i] = new_bus->range[new_bus->dev_count]; | ||||
| 			sort(new_bus->range, new_bus->dev_count, | ||||
| 			     sizeof(struct kvm_io_range), | ||||
| 			     kvm_io_bus_sort_cmp, NULL); | ||||
| 			break; | ||||
| 		} | ||||
| 
 | ||||
| 	if (r) { | ||||
| 		kfree(new_bus); | ||||
| 	if (r) | ||||
| 		return r; | ||||
| 	} | ||||
| 
 | ||||
| 	new_bus = kzalloc(sizeof(*bus) + ((bus->dev_count - 1) * | ||||
| 			  sizeof(struct kvm_io_range)), GFP_KERNEL); | ||||
| 	if (!new_bus) | ||||
| 		return -ENOMEM; | ||||
| 
 | ||||
| 	memcpy(new_bus, bus, sizeof(*bus) + i * sizeof(struct kvm_io_range)); | ||||
| 	new_bus->dev_count--; | ||||
| 	memcpy(new_bus->range + i, bus->range + i + 1, | ||||
| 	       (new_bus->dev_count - i) * sizeof(struct kvm_io_range)); | ||||
| 
 | ||||
| 	rcu_assign_pointer(kvm->buses[bus_idx], new_bus); | ||||
| 	synchronize_srcu_expedited(&kvm->srcu); | ||||
|  | ||||
		Loading…
	
		Reference in New Issue
	
	Block a user