1 // SPDX-License-Identifier: GPL-2.0-only 2 /* 3 * VMware VMCI Driver 4 * 5 * Copyright (C) 2012 VMware, Inc. All rights reserved. 6 */ 7 8 #include <linux/slab.h> 9 #include "vmci_handle_array.h" 10 11 static size_t handle_arr_calc_size(size_t capacity) 12 { 13 return sizeof(struct vmci_handle_arr) + 14 capacity * sizeof(struct vmci_handle); 15 } 16 17 struct vmci_handle_arr *vmci_handle_arr_create(size_t capacity) 18 { 19 struct vmci_handle_arr *array; 20 21 if (capacity == 0) 22 capacity = VMCI_HANDLE_ARRAY_DEFAULT_SIZE; 23 24 array = kmalloc(handle_arr_calc_size(capacity), GFP_ATOMIC); 25 if (!array) 26 return NULL; 27 28 array->capacity = capacity; 29 array->size = 0; 30 31 return array; 32 } 33 34 void vmci_handle_arr_destroy(struct vmci_handle_arr *array) 35 { 36 kfree(array); 37 } 38 39 void vmci_handle_arr_append_entry(struct vmci_handle_arr **array_ptr, 40 struct vmci_handle handle) 41 { 42 struct vmci_handle_arr *array = *array_ptr; 43 44 if (unlikely(array->size >= array->capacity)) { 45 /* reallocate. */ 46 struct vmci_handle_arr *new_array; 47 size_t new_capacity = array->capacity * VMCI_ARR_CAP_MULT; 48 size_t new_size = handle_arr_calc_size(new_capacity); 49 50 new_array = krealloc(array, new_size, GFP_ATOMIC); 51 if (!new_array) 52 return; 53 54 new_array->capacity = new_capacity; 55 *array_ptr = array = new_array; 56 } 57 58 array->entries[array->size] = handle; 59 array->size++; 60 } 61 62 /* 63 * Handle that was removed, VMCI_INVALID_HANDLE if entry not found. 64 */ 65 struct vmci_handle vmci_handle_arr_remove_entry(struct vmci_handle_arr *array, 66 struct vmci_handle entry_handle) 67 { 68 struct vmci_handle handle = VMCI_INVALID_HANDLE; 69 size_t i; 70 71 for (i = 0; i < array->size; i++) { 72 if (vmci_handle_is_equal(array->entries[i], entry_handle)) { 73 handle = array->entries[i]; 74 array->size--; 75 array->entries[i] = array->entries[array->size]; 76 array->entries[array->size] = VMCI_INVALID_HANDLE; 77 break; 78 } 79 } 80 81 return handle; 82 } 83 84 /* 85 * Handle that was removed, VMCI_INVALID_HANDLE if array was empty. 86 */ 87 struct vmci_handle vmci_handle_arr_remove_tail(struct vmci_handle_arr *array) 88 { 89 struct vmci_handle handle = VMCI_INVALID_HANDLE; 90 91 if (array->size) { 92 array->size--; 93 handle = array->entries[array->size]; 94 array->entries[array->size] = VMCI_INVALID_HANDLE; 95 } 96 97 return handle; 98 } 99 100 /* 101 * Handle at given index, VMCI_INVALID_HANDLE if invalid index. 102 */ 103 struct vmci_handle 104 vmci_handle_arr_get_entry(const struct vmci_handle_arr *array, size_t index) 105 { 106 if (unlikely(index >= array->size)) 107 return VMCI_INVALID_HANDLE; 108 109 return array->entries[index]; 110 } 111 112 bool vmci_handle_arr_has_entry(const struct vmci_handle_arr *array, 113 struct vmci_handle entry_handle) 114 { 115 size_t i; 116 117 for (i = 0; i < array->size; i++) 118 if (vmci_handle_is_equal(array->entries[i], entry_handle)) 119 return true; 120 121 return false; 122 } 123 124 /* 125 * NULL if the array is empty. Otherwise, a pointer to the array 126 * of VMCI handles in the handle array. 127 */ 128 struct vmci_handle *vmci_handle_arr_get_handles(struct vmci_handle_arr *array) 129 { 130 if (array->size) 131 return array->entries; 132 133 return NULL; 134 } 135