Commit b1bba80a authored by Stefano Garzarella's avatar Stefano Garzarella Committed by David S. Miller
Browse files

vsock/vmci: register vmci_transport only when VMCI guest/host are active



To allow other transports to be loaded with vmci_transport,
we register the vmci_transport as G2H or H2G only when a VMCI guest
or host is active.

To do that, this patch adds a callback registered in the vmci driver
that will be called when the host or guest becomes active.
This callback will register the vmci_transport in the VSOCK core.

Cc: Jorgen Hansen <jhansen@vmware.com>
Signed-off-by: default avatarStefano Garzarella <sgarzare@redhat.com>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent c0cfa2d8
Loading
Loading
Loading
Loading
+67 −0
Original line number Diff line number Diff line
@@ -28,6 +28,10 @@ MODULE_PARM_DESC(disable_guest,
static bool vmci_guest_personality_initialized;
static bool vmci_host_personality_initialized;

static DEFINE_MUTEX(vmci_vsock_mutex); /* protects vmci_vsock_transport_cb */
static vmci_vsock_cb vmci_vsock_transport_cb;
bool vmci_vsock_cb_host_called;

/*
 * vmci_get_context_id() - Gets the current context ID.
 *
@@ -45,6 +49,69 @@ u32 vmci_get_context_id(void)
}
EXPORT_SYMBOL_GPL(vmci_get_context_id);

/*
 * vmci_register_vsock_callback() - Register the VSOCK vmci_transport callback.
 *
 * The callback will be called when the first host or guest becomes active,
 * or if they are already active when this function is called.
 * To unregister the callback, call this function with NULL parameter.
 *
 * Returns 0 on success. -EBUSY if a callback is already registered.
 */
int vmci_register_vsock_callback(vmci_vsock_cb callback)
{
	int err = 0;

	mutex_lock(&vmci_vsock_mutex);

	if (vmci_vsock_transport_cb && callback) {
		err = -EBUSY;
		goto out;
	}

	vmci_vsock_transport_cb = callback;

	if (!vmci_vsock_transport_cb) {
		vmci_vsock_cb_host_called = false;
		goto out;
	}

	if (vmci_guest_code_active())
		vmci_vsock_transport_cb(false);

	if (vmci_host_users() > 0) {
		vmci_vsock_cb_host_called = true;
		vmci_vsock_transport_cb(true);
	}

out:
	mutex_unlock(&vmci_vsock_mutex);
	return err;
}
EXPORT_SYMBOL_GPL(vmci_register_vsock_callback);

void vmci_call_vsock_callback(bool is_host)
{
	mutex_lock(&vmci_vsock_mutex);

	if (!vmci_vsock_transport_cb)
		goto out;

	/* In the host, this function could be called multiple times,
	 * but we want to register it only once.
	 */
	if (is_host) {
		if (vmci_vsock_cb_host_called)
			goto out;

		vmci_vsock_cb_host_called = true;
	}

	vmci_vsock_transport_cb(is_host);
out:
	mutex_unlock(&vmci_vsock_mutex);
}

static int __init vmci_drv_init(void)
{
	int vmci_err;
+2 −0
Original line number Diff line number Diff line
@@ -36,10 +36,12 @@ extern struct pci_dev *vmci_pdev;

u32 vmci_get_context_id(void);
int vmci_send_datagram(struct vmci_datagram *dg);
void vmci_call_vsock_callback(bool is_host);

int vmci_host_init(void);
void vmci_host_exit(void);
bool vmci_host_code_active(void);
int vmci_host_users(void);

int vmci_guest_init(void);
void vmci_guest_exit(void);
+2 −0
Original line number Diff line number Diff line
@@ -637,6 +637,8 @@ static int vmci_guest_probe_device(struct pci_dev *pdev,
		  vmci_dev->iobase + VMCI_CONTROL_ADDR);

	pci_set_drvdata(pdev, vmci_dev);

	vmci_call_vsock_callback(false);
	return 0;

err_free_irq:
+7 −0
Original line number Diff line number Diff line
@@ -108,6 +108,11 @@ bool vmci_host_code_active(void)
	     atomic_read(&vmci_host_active_users) > 0);
}

int vmci_host_users(void)
{
	return atomic_read(&vmci_host_active_users);
}

/*
 * Called on open of /dev/vmci.
 */
@@ -338,6 +343,8 @@ static int vmci_host_do_init_context(struct vmci_host_dev *vmci_host_dev,
	vmci_host_dev->ct_type = VMCIOBJ_CONTEXT;
	atomic_inc(&vmci_host_active_users);

	vmci_call_vsock_callback(true);

	retval = 0;

out:
+2 −0
Original line number Diff line number Diff line
@@ -19,6 +19,7 @@
struct msghdr;
typedef void (vmci_device_shutdown_fn) (void *device_registration,
					void *user_data);
typedef void (*vmci_vsock_cb) (bool is_host);

int vmci_datagram_create_handle(u32 resource_id, u32 flags,
				vmci_datagram_recv_cb recv_cb,
@@ -37,6 +38,7 @@ int vmci_doorbell_destroy(struct vmci_handle handle);
int vmci_doorbell_notify(struct vmci_handle handle, u32 priv_flags);
u32 vmci_get_context_id(void);
bool vmci_is_context_owner(u32 context_id, kuid_t uid);
int vmci_register_vsock_callback(vmci_vsock_cb callback);

int vmci_event_subscribe(u32 event,
			 vmci_event_cb callback, void *callback_data,
Loading