0001
0002
0003
0004
0005
0006
0007
0008 #include <linux/slab.h>
0009 #include "vmci_handle_array.h"
0010
0011 static size_t handle_arr_calc_size(u32 capacity)
0012 {
0013 return VMCI_HANDLE_ARRAY_HEADER_SIZE +
0014 capacity * sizeof(struct vmci_handle);
0015 }
0016
0017 struct vmci_handle_arr *vmci_handle_arr_create(u32 capacity, u32 max_capacity)
0018 {
0019 struct vmci_handle_arr *array;
0020
0021 if (max_capacity == 0 || capacity > max_capacity)
0022 return NULL;
0023
0024 if (capacity == 0)
0025 capacity = min((u32)VMCI_HANDLE_ARRAY_DEFAULT_CAPACITY,
0026 max_capacity);
0027
0028 array = kmalloc(handle_arr_calc_size(capacity), GFP_ATOMIC);
0029 if (!array)
0030 return NULL;
0031
0032 array->capacity = capacity;
0033 array->max_capacity = max_capacity;
0034 array->size = 0;
0035
0036 return array;
0037 }
0038
0039 void vmci_handle_arr_destroy(struct vmci_handle_arr *array)
0040 {
0041 kfree(array);
0042 }
0043
0044 int vmci_handle_arr_append_entry(struct vmci_handle_arr **array_ptr,
0045 struct vmci_handle handle)
0046 {
0047 struct vmci_handle_arr *array = *array_ptr;
0048
0049 if (unlikely(array->size >= array->capacity)) {
0050
0051 struct vmci_handle_arr *new_array;
0052 u32 capacity_bump = min(array->max_capacity - array->capacity,
0053 array->capacity);
0054 size_t new_size = handle_arr_calc_size(array->capacity +
0055 capacity_bump);
0056
0057 if (array->size >= array->max_capacity)
0058 return VMCI_ERROR_NO_MEM;
0059
0060 new_array = krealloc(array, new_size, GFP_ATOMIC);
0061 if (!new_array)
0062 return VMCI_ERROR_NO_MEM;
0063
0064 new_array->capacity += capacity_bump;
0065 *array_ptr = array = new_array;
0066 }
0067
0068 array->entries[array->size] = handle;
0069 array->size++;
0070
0071 return VMCI_SUCCESS;
0072 }
0073
0074
0075
0076
0077 struct vmci_handle vmci_handle_arr_remove_entry(struct vmci_handle_arr *array,
0078 struct vmci_handle entry_handle)
0079 {
0080 struct vmci_handle handle = VMCI_INVALID_HANDLE;
0081 u32 i;
0082
0083 for (i = 0; i < array->size; i++) {
0084 if (vmci_handle_is_equal(array->entries[i], entry_handle)) {
0085 handle = array->entries[i];
0086 array->size--;
0087 array->entries[i] = array->entries[array->size];
0088 array->entries[array->size] = VMCI_INVALID_HANDLE;
0089 break;
0090 }
0091 }
0092
0093 return handle;
0094 }
0095
0096
0097
0098
0099 struct vmci_handle vmci_handle_arr_remove_tail(struct vmci_handle_arr *array)
0100 {
0101 struct vmci_handle handle = VMCI_INVALID_HANDLE;
0102
0103 if (array->size) {
0104 array->size--;
0105 handle = array->entries[array->size];
0106 array->entries[array->size] = VMCI_INVALID_HANDLE;
0107 }
0108
0109 return handle;
0110 }
0111
0112
0113
0114
0115 struct vmci_handle
0116 vmci_handle_arr_get_entry(const struct vmci_handle_arr *array, u32 index)
0117 {
0118 if (unlikely(index >= array->size))
0119 return VMCI_INVALID_HANDLE;
0120
0121 return array->entries[index];
0122 }
0123
0124 bool vmci_handle_arr_has_entry(const struct vmci_handle_arr *array,
0125 struct vmci_handle entry_handle)
0126 {
0127 u32 i;
0128
0129 for (i = 0; i < array->size; i++)
0130 if (vmci_handle_is_equal(array->entries[i], entry_handle))
0131 return true;
0132
0133 return false;
0134 }
0135
0136
0137
0138
0139
0140 struct vmci_handle *vmci_handle_arr_get_handles(struct vmci_handle_arr *array)
0141 {
0142 if (array->size)
0143 return array->entries;
0144
0145 return NULL;
0146 }