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