vmci_handle_array.c 3.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140
  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. #include <linux/slab.h>
  8. #include "vmci_handle_array.h"
  9. struct vmci_handle_arr *vmci_handle_arr_create(u32 capacity, u32 max_capacity)
  10. {
  11. struct vmci_handle_arr *array;
  12. if (max_capacity == 0 || capacity > max_capacity)
  13. return NULL;
  14. if (capacity == 0)
  15. capacity = min((u32)VMCI_HANDLE_ARRAY_DEFAULT_CAPACITY,
  16. max_capacity);
  17. array = kmalloc(struct_size(array, entries, capacity), GFP_ATOMIC);
  18. if (!array)
  19. return NULL;
  20. array->capacity = capacity;
  21. array->max_capacity = max_capacity;
  22. array->size = 0;
  23. return array;
  24. }
  25. void vmci_handle_arr_destroy(struct vmci_handle_arr *array)
  26. {
  27. kfree(array);
  28. }
  29. int vmci_handle_arr_append_entry(struct vmci_handle_arr **array_ptr,
  30. struct vmci_handle handle)
  31. {
  32. struct vmci_handle_arr *array = *array_ptr;
  33. if (unlikely(array->size >= array->capacity)) {
  34. /* reallocate. */
  35. struct vmci_handle_arr *new_array;
  36. u32 capacity_bump = min(array->max_capacity - array->capacity,
  37. array->capacity);
  38. size_t new_size = struct_size(array, entries,
  39. size_add(array->capacity, capacity_bump));
  40. if (array->size >= array->max_capacity)
  41. return VMCI_ERROR_NO_MEM;
  42. new_array = krealloc(array, new_size, GFP_ATOMIC);
  43. if (!new_array)
  44. return VMCI_ERROR_NO_MEM;
  45. new_array->capacity += capacity_bump;
  46. *array_ptr = array = new_array;
  47. }
  48. array->entries[array->size] = handle;
  49. array->size++;
  50. return VMCI_SUCCESS;
  51. }
  52. /*
  53. * Handle that was removed, VMCI_INVALID_HANDLE if entry not found.
  54. */
  55. struct vmci_handle vmci_handle_arr_remove_entry(struct vmci_handle_arr *array,
  56. struct vmci_handle entry_handle)
  57. {
  58. struct vmci_handle handle = VMCI_INVALID_HANDLE;
  59. u32 i;
  60. for (i = 0; i < array->size; i++) {
  61. if (vmci_handle_is_equal(array->entries[i], entry_handle)) {
  62. handle = array->entries[i];
  63. array->size--;
  64. array->entries[i] = array->entries[array->size];
  65. array->entries[array->size] = VMCI_INVALID_HANDLE;
  66. break;
  67. }
  68. }
  69. return handle;
  70. }
  71. /*
  72. * Handle that was removed, VMCI_INVALID_HANDLE if array was empty.
  73. */
  74. struct vmci_handle vmci_handle_arr_remove_tail(struct vmci_handle_arr *array)
  75. {
  76. struct vmci_handle handle = VMCI_INVALID_HANDLE;
  77. if (array->size) {
  78. array->size--;
  79. handle = array->entries[array->size];
  80. array->entries[array->size] = VMCI_INVALID_HANDLE;
  81. }
  82. return handle;
  83. }
  84. /*
  85. * Handle at given index, VMCI_INVALID_HANDLE if invalid index.
  86. */
  87. struct vmci_handle
  88. vmci_handle_arr_get_entry(const struct vmci_handle_arr *array, u32 index)
  89. {
  90. if (unlikely(index >= array->size))
  91. return VMCI_INVALID_HANDLE;
  92. return array->entries[index];
  93. }
  94. bool vmci_handle_arr_has_entry(const struct vmci_handle_arr *array,
  95. struct vmci_handle entry_handle)
  96. {
  97. u32 i;
  98. for (i = 0; i < array->size; i++)
  99. if (vmci_handle_is_equal(array->entries[i], entry_handle))
  100. return true;
  101. return false;
  102. }
  103. /*
  104. * NULL if the array is empty. Otherwise, a pointer to the array
  105. * of VMCI handles in the handle array.
  106. */
  107. struct vmci_handle *vmci_handle_arr_get_handles(struct vmci_handle_arr *array)
  108. {
  109. if (array->size)
  110. return array->entries;
  111. return NULL;
  112. }