vmci_handle_array.c (3326B)
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 11static size_t handle_arr_calc_size(u32 capacity) 12{ 13 return VMCI_HANDLE_ARRAY_HEADER_SIZE + 14 capacity * sizeof(struct vmci_handle); 15} 16 17struct vmci_handle_arr *vmci_handle_arr_create(u32 capacity, u32 max_capacity) 18{ 19 struct vmci_handle_arr *array; 20 21 if (max_capacity == 0 || capacity > max_capacity) 22 return NULL; 23 24 if (capacity == 0) 25 capacity = min((u32)VMCI_HANDLE_ARRAY_DEFAULT_CAPACITY, 26 max_capacity); 27 28 array = kmalloc(handle_arr_calc_size(capacity), GFP_ATOMIC); 29 if (!array) 30 return NULL; 31 32 array->capacity = capacity; 33 array->max_capacity = max_capacity; 34 array->size = 0; 35 36 return array; 37} 38 39void vmci_handle_arr_destroy(struct vmci_handle_arr *array) 40{ 41 kfree(array); 42} 43 44int vmci_handle_arr_append_entry(struct vmci_handle_arr **array_ptr, 45 struct vmci_handle handle) 46{ 47 struct vmci_handle_arr *array = *array_ptr; 48 49 if (unlikely(array->size >= array->capacity)) { 50 /* reallocate. */ 51 struct vmci_handle_arr *new_array; 52 u32 capacity_bump = min(array->max_capacity - array->capacity, 53 array->capacity); 54 size_t new_size = handle_arr_calc_size(array->capacity + 55 capacity_bump); 56 57 if (array->size >= array->max_capacity) 58 return VMCI_ERROR_NO_MEM; 59 60 new_array = krealloc(array, new_size, GFP_ATOMIC); 61 if (!new_array) 62 return VMCI_ERROR_NO_MEM; 63 64 new_array->capacity += capacity_bump; 65 *array_ptr = array = new_array; 66 } 67 68 array->entries[array->size] = handle; 69 array->size++; 70 71 return VMCI_SUCCESS; 72} 73 74/* 75 * Handle that was removed, VMCI_INVALID_HANDLE if entry not found. 76 */ 77struct vmci_handle vmci_handle_arr_remove_entry(struct vmci_handle_arr *array, 78 struct vmci_handle entry_handle) 79{ 80 struct vmci_handle handle = VMCI_INVALID_HANDLE; 81 u32 i; 82 83 for (i = 0; i < array->size; i++) { 84 if (vmci_handle_is_equal(array->entries[i], entry_handle)) { 85 handle = array->entries[i]; 86 array->size--; 87 array->entries[i] = array->entries[array->size]; 88 array->entries[array->size] = VMCI_INVALID_HANDLE; 89 break; 90 } 91 } 92 93 return handle; 94} 95 96/* 97 * Handle that was removed, VMCI_INVALID_HANDLE if array was empty. 98 */ 99struct vmci_handle vmci_handle_arr_remove_tail(struct vmci_handle_arr *array) 100{ 101 struct vmci_handle handle = VMCI_INVALID_HANDLE; 102 103 if (array->size) { 104 array->size--; 105 handle = array->entries[array->size]; 106 array->entries[array->size] = VMCI_INVALID_HANDLE; 107 } 108 109 return handle; 110} 111 112/* 113 * Handle at given index, VMCI_INVALID_HANDLE if invalid index. 114 */ 115struct vmci_handle 116vmci_handle_arr_get_entry(const struct vmci_handle_arr *array, u32 index) 117{ 118 if (unlikely(index >= array->size)) 119 return VMCI_INVALID_HANDLE; 120 121 return array->entries[index]; 122} 123 124bool vmci_handle_arr_has_entry(const struct vmci_handle_arr *array, 125 struct vmci_handle entry_handle) 126{ 127 u32 i; 128 129 for (i = 0; i < array->size; i++) 130 if (vmci_handle_is_equal(array->entries[i], entry_handle)) 131 return true; 132 133 return false; 134} 135 136/* 137 * NULL if the array is empty. Otherwise, a pointer to the array 138 * of VMCI handles in the handle array. 139 */ 140struct vmci_handle *vmci_handle_arr_get_handles(struct vmci_handle_arr *array) 141{ 142 if (array->size) 143 return array->entries; 144 145 return NULL; 146}