Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0-only
0002 /*
0003  * VMware VMCI Driver
0004  *
0005  * Copyright (C) 2012 VMware, Inc. All rights reserved.
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         /* reallocate. */
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  * Handle that was removed, VMCI_INVALID_HANDLE if entry not found.
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  * Handle that was removed, VMCI_INVALID_HANDLE if array was empty.
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  * Handle at given index, VMCI_INVALID_HANDLE if invalid index.
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  * NULL if the array is empty. Otherwise, a pointer to the array
0138  * of VMCI handles in the handle array.
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 }