// SPDX-License-Identifier: GPL-2.0-only
/*
 * VMware VMCI Driver
 *
 * Copyright (C) 2012 VMware, Inc. All rights reserved.
 */

#include <linux/slab.h>
#include "vmci_handle_array.h"

struct vmci_handle_arr *vmci_handle_arr_create(u32 capacity, u32 max_capacity)
{
	struct vmci_handle_arr *array;

	if (max_capacity == 0 || capacity > max_capacity)
		return NULL;

	if (capacity == 0)
		capacity = min((u32)VMCI_HANDLE_ARRAY_DEFAULT_CAPACITY,
			       max_capacity);

	array = kmalloc_flex(*array, entries, capacity, GFP_ATOMIC);
	if (!array)
		return NULL;

	array->capacity = capacity;
	array->max_capacity = max_capacity;
	array->size = 0;

	return array;
}

void vmci_handle_arr_destroy(struct vmci_handle_arr *array)
{
	kfree(array);
}

int vmci_handle_arr_append_entry(struct vmci_handle_arr **array_ptr,
				 struct vmci_handle handle)
{
	struct vmci_handle_arr *array = *array_ptr;

	if (unlikely(array->size >= array->capacity)) {
		/* reallocate. */
		struct vmci_handle_arr *new_array;
		u32 capacity_bump = min(array->max_capacity - array->capacity,
					array->capacity);
		size_t new_size = struct_size(array, entries,
					      size_add(array->capacity, capacity_bump));

		if (array->size >= array->max_capacity)
			return VMCI_ERROR_NO_MEM;

		new_array = krealloc(array, new_size, GFP_ATOMIC);
		if (!new_array)
			return VMCI_ERROR_NO_MEM;

		new_array->capacity += capacity_bump;
		*array_ptr = array = new_array;
	}

	array->entries[array->size] = handle;
	array->size++;

	return VMCI_SUCCESS;
}

/*
 * Handle that was removed, VMCI_INVALID_HANDLE if entry not found.
 */
struct vmci_handle vmci_handle_arr_remove_entry(struct vmci_handle_arr *array,
						struct vmci_handle entry_handle)
{
	struct vmci_handle handle = VMCI_INVALID_HANDLE;
	u32 i;

	for (i = 0; i < array->size; i++) {
		if (vmci_handle_is_equal(array->entries[i], entry_handle)) {
			handle = array->entries[i];
			array->size--;
			array->entries[i] = array->entries[array->size];
			array->entries[array->size] = VMCI_INVALID_HANDLE;
			break;
		}
	}

	return handle;
}

/*
 * Handle that was removed, VMCI_INVALID_HANDLE if array was empty.
 */
struct vmci_handle vmci_handle_arr_remove_tail(struct vmci_handle_arr *array)
{
	struct vmci_handle handle = VMCI_INVALID_HANDLE;

	if (array->size) {
		array->size--;
		handle = array->entries[array->size];
		array->entries[array->size] = VMCI_INVALID_HANDLE;
	}

	return handle;
}

/*
 * Handle at given index, VMCI_INVALID_HANDLE if invalid index.
 */
struct vmci_handle
vmci_handle_arr_get_entry(const struct vmci_handle_arr *array, u32 index)
{
	if (unlikely(index >= array->size))
		return VMCI_INVALID_HANDLE;

	return array->entries[index];
}

bool vmci_handle_arr_has_entry(const struct vmci_handle_arr *array,
			       struct vmci_handle entry_handle)
{
	u32 i;

	for (i = 0; i < array->size; i++)
		if (vmci_handle_is_equal(array->entries[i], entry_handle))
			return true;

	return false;
}

/*
 * NULL if the array is empty. Otherwise, a pointer to the array
 * of VMCI handles in the handle array.
 */
struct vmci_handle *vmci_handle_arr_get_handles(struct vmci_handle_arr *array)
{
	if (array->size)
		return array->entries;

	return NULL;
}
