|
|
@@ -29,6 +29,9 @@
|
|
|
#include "vmci_driver.h"
|
|
|
#include "vmci_event.h"
|
|
|
|
|
|
+/* Use a wide upper bound for the maximum contexts. */
|
|
|
+#define VMCI_MAX_CONTEXTS 2000
|
|
|
+
|
|
|
/*
|
|
|
* List of current VMCI contexts. Contexts can be added by
|
|
|
* vmci_ctx_create() and removed via vmci_ctx_destroy().
|
|
|
@@ -125,19 +128,22 @@ struct vmci_ctx *vmci_ctx_create(u32 cid, u32 priv_flags,
|
|
|
/* Initialize host-specific VMCI context. */
|
|
|
init_waitqueue_head(&context->host_context.wait_queue);
|
|
|
|
|
|
- context->queue_pair_array = vmci_handle_arr_create(0);
|
|
|
+ context->queue_pair_array =
|
|
|
+ vmci_handle_arr_create(0, VMCI_MAX_GUEST_QP_COUNT);
|
|
|
if (!context->queue_pair_array) {
|
|
|
error = -ENOMEM;
|
|
|
goto err_free_ctx;
|
|
|
}
|
|
|
|
|
|
- context->doorbell_array = vmci_handle_arr_create(0);
|
|
|
+ context->doorbell_array =
|
|
|
+ vmci_handle_arr_create(0, VMCI_MAX_GUEST_DOORBELL_COUNT);
|
|
|
if (!context->doorbell_array) {
|
|
|
error = -ENOMEM;
|
|
|
goto err_free_qp_array;
|
|
|
}
|
|
|
|
|
|
- context->pending_doorbell_array = vmci_handle_arr_create(0);
|
|
|
+ context->pending_doorbell_array =
|
|
|
+ vmci_handle_arr_create(0, VMCI_MAX_GUEST_DOORBELL_COUNT);
|
|
|
if (!context->pending_doorbell_array) {
|
|
|
error = -ENOMEM;
|
|
|
goto err_free_db_array;
|
|
|
@@ -212,7 +218,7 @@ static int ctx_fire_notification(u32 context_id, u32 priv_flags)
|
|
|
* We create an array to hold the subscribers we find when
|
|
|
* scanning through all contexts.
|
|
|
*/
|
|
|
- subscriber_array = vmci_handle_arr_create(0);
|
|
|
+ subscriber_array = vmci_handle_arr_create(0, VMCI_MAX_CONTEXTS);
|
|
|
if (subscriber_array == NULL)
|
|
|
return VMCI_ERROR_NO_MEM;
|
|
|
|
|
|
@@ -631,20 +637,26 @@ int vmci_ctx_add_notification(u32 context_id, u32 remote_cid)
|
|
|
|
|
|
spin_lock(&context->lock);
|
|
|
|
|
|
- list_for_each_entry(n, &context->notifier_list, node) {
|
|
|
- if (vmci_handle_is_equal(n->handle, notifier->handle)) {
|
|
|
- exists = true;
|
|
|
- break;
|
|
|
+ if (context->n_notifiers < VMCI_MAX_CONTEXTS) {
|
|
|
+ list_for_each_entry(n, &context->notifier_list, node) {
|
|
|
+ if (vmci_handle_is_equal(n->handle, notifier->handle)) {
|
|
|
+ exists = true;
|
|
|
+ break;
|
|
|
+ }
|
|
|
}
|
|
|
- }
|
|
|
|
|
|
- if (exists) {
|
|
|
- kfree(notifier);
|
|
|
- result = VMCI_ERROR_ALREADY_EXISTS;
|
|
|
+ if (exists) {
|
|
|
+ kfree(notifier);
|
|
|
+ result = VMCI_ERROR_ALREADY_EXISTS;
|
|
|
+ } else {
|
|
|
+ list_add_tail_rcu(¬ifier->node,
|
|
|
+ &context->notifier_list);
|
|
|
+ context->n_notifiers++;
|
|
|
+ result = VMCI_SUCCESS;
|
|
|
+ }
|
|
|
} else {
|
|
|
- list_add_tail_rcu(¬ifier->node, &context->notifier_list);
|
|
|
- context->n_notifiers++;
|
|
|
- result = VMCI_SUCCESS;
|
|
|
+ kfree(notifier);
|
|
|
+ result = VMCI_ERROR_NO_MEM;
|
|
|
}
|
|
|
|
|
|
spin_unlock(&context->lock);
|
|
|
@@ -729,8 +741,7 @@ static int vmci_ctx_get_chkpt_doorbells(struct vmci_ctx *context,
|
|
|
u32 *buf_size, void **pbuf)
|
|
|
{
|
|
|
struct dbell_cpt_state *dbells;
|
|
|
- size_t n_doorbells;
|
|
|
- int i;
|
|
|
+ u32 i, n_doorbells;
|
|
|
|
|
|
n_doorbells = vmci_handle_arr_get_size(context->doorbell_array);
|
|
|
if (n_doorbells > 0) {
|
|
|
@@ -868,7 +879,8 @@ int vmci_ctx_rcv_notifications_get(u32 context_id,
|
|
|
spin_lock(&context->lock);
|
|
|
|
|
|
*db_handle_array = context->pending_doorbell_array;
|
|
|
- context->pending_doorbell_array = vmci_handle_arr_create(0);
|
|
|
+ context->pending_doorbell_array =
|
|
|
+ vmci_handle_arr_create(0, VMCI_MAX_GUEST_DOORBELL_COUNT);
|
|
|
if (!context->pending_doorbell_array) {
|
|
|
context->pending_doorbell_array = *db_handle_array;
|
|
|
*db_handle_array = NULL;
|
|
|
@@ -950,12 +962,11 @@ int vmci_ctx_dbell_create(u32 context_id, struct vmci_handle handle)
|
|
|
return VMCI_ERROR_NOT_FOUND;
|
|
|
|
|
|
spin_lock(&context->lock);
|
|
|
- if (!vmci_handle_arr_has_entry(context->doorbell_array, handle)) {
|
|
|
- vmci_handle_arr_append_entry(&context->doorbell_array, handle);
|
|
|
- result = VMCI_SUCCESS;
|
|
|
- } else {
|
|
|
+ if (!vmci_handle_arr_has_entry(context->doorbell_array, handle))
|
|
|
+ result = vmci_handle_arr_append_entry(&context->doorbell_array,
|
|
|
+ handle);
|
|
|
+ else
|
|
|
result = VMCI_ERROR_DUPLICATE_ENTRY;
|
|
|
- }
|
|
|
|
|
|
spin_unlock(&context->lock);
|
|
|
vmci_ctx_put(context);
|
|
|
@@ -1091,15 +1102,16 @@ int vmci_ctx_notify_dbell(u32 src_cid,
|
|
|
if (!vmci_handle_arr_has_entry(
|
|
|
dst_context->pending_doorbell_array,
|
|
|
handle)) {
|
|
|
- vmci_handle_arr_append_entry(
|
|
|
+ result = vmci_handle_arr_append_entry(
|
|
|
&dst_context->pending_doorbell_array,
|
|
|
handle);
|
|
|
-
|
|
|
- ctx_signal_notify(dst_context);
|
|
|
- wake_up(&dst_context->host_context.wait_queue);
|
|
|
-
|
|
|
+ if (result == VMCI_SUCCESS) {
|
|
|
+ ctx_signal_notify(dst_context);
|
|
|
+ wake_up(&dst_context->host_context.wait_queue);
|
|
|
+ }
|
|
|
+ } else {
|
|
|
+ result = VMCI_SUCCESS;
|
|
|
}
|
|
|
- result = VMCI_SUCCESS;
|
|
|
}
|
|
|
spin_unlock(&dst_context->lock);
|
|
|
}
|
|
|
@@ -1126,13 +1138,11 @@ int vmci_ctx_qp_create(struct vmci_ctx *context, struct vmci_handle handle)
|
|
|
if (context == NULL || vmci_handle_is_invalid(handle))
|
|
|
return VMCI_ERROR_INVALID_ARGS;
|
|
|
|
|
|
- if (!vmci_handle_arr_has_entry(context->queue_pair_array, handle)) {
|
|
|
- vmci_handle_arr_append_entry(&context->queue_pair_array,
|
|
|
- handle);
|
|
|
- result = VMCI_SUCCESS;
|
|
|
- } else {
|
|
|
+ if (!vmci_handle_arr_has_entry(context->queue_pair_array, handle))
|
|
|
+ result = vmci_handle_arr_append_entry(
|
|
|
+ &context->queue_pair_array, handle);
|
|
|
+ else
|
|
|
result = VMCI_ERROR_DUPLICATE_ENTRY;
|
|
|
- }
|
|
|
|
|
|
return result;
|
|
|
}
|