Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit e9c18ae6 authored by Vitaly Kuznetsov's avatar Vitaly Kuznetsov Committed by Greg Kroah-Hartman
Browse files

Drivers: hv: util: move waiting for release to hv_utils_transport itself



Waiting for release_event in all three drivers introduced issues on release
as on_reset() hook is not always called. E.g. if the device was never
opened we will never get the completion.

Move the waiting code to hvutil_transport_destroy() and make sure it is
only called when the device is open. hvt->lock serialization should
guarantee the absence of races.

Fixes: 5a66fecb ("Drivers: hv: util: kvp: Fix a rescind processing issue")
Fixes: 20951c75 ("Drivers: hv: util: Fcopy: Fix a rescind processing issue")
Fixes: d77044d1 ("Drivers: hv: util: Backup: Fix a rescind processing issue")

Reported-by: default avatarDexuan Cui <decui@microsoft.com>
Tested-by: default avatarDexuan Cui <decui@microsoft.com>
Signed-off-by: default avatarVitaly Kuznetsov <vkuznets@redhat.com>
Signed-off-by: default avatarK. Y. Srinivasan <kys@microsoft.com>
Signed-off-by: default avatarGreg Kroah-Hartman <gregkh@linuxfoundation.org>
parent dad72a1d
Loading
Loading
Loading
Loading
+0 −4
Original line number Diff line number Diff line
@@ -71,7 +71,6 @@ static DECLARE_WORK(fcopy_send_work, fcopy_send_data);
static const char fcopy_devname[] = "vmbus/hv_fcopy";
static u8 *recv_buffer;
static struct hvutil_transport *hvt;
static struct completion release_event;
/*
 * This state maintains the version number registered by the daemon.
 */
@@ -331,7 +330,6 @@ static void fcopy_on_reset(void)

	if (cancel_delayed_work_sync(&fcopy_timeout_work))
		fcopy_respond_to_host(HV_E_FAIL);
	complete(&release_event);
}

int hv_fcopy_init(struct hv_util_service *srv)
@@ -339,7 +337,6 @@ int hv_fcopy_init(struct hv_util_service *srv)
	recv_buffer = srv->recv_buffer;
	fcopy_transaction.recv_channel = srv->channel;

	init_completion(&release_event);
	/*
	 * When this driver loads, the user level daemon that
	 * processes the host requests may not yet be running.
@@ -361,5 +358,4 @@ void hv_fcopy_deinit(void)
	fcopy_transaction.state = HVUTIL_DEVICE_DYING;
	cancel_delayed_work_sync(&fcopy_timeout_work);
	hvutil_transport_destroy(hvt);
	wait_for_completion(&release_event);
}
+0 −4
Original line number Diff line number Diff line
@@ -101,7 +101,6 @@ static DECLARE_WORK(kvp_sendkey_work, kvp_send_key);
static const char kvp_devname[] = "vmbus/hv_kvp";
static u8 *recv_buffer;
static struct hvutil_transport *hvt;
static struct completion release_event;
/*
 * Register the kernel component with the user-level daemon.
 * As part of this registration, pass the LIC version number.
@@ -714,7 +713,6 @@ static void kvp_on_reset(void)
	if (cancel_delayed_work_sync(&kvp_timeout_work))
		kvp_respond_to_host(NULL, HV_E_FAIL);
	kvp_transaction.state = HVUTIL_DEVICE_INIT;
	complete(&release_event);
}

int
@@ -723,7 +721,6 @@ hv_kvp_init(struct hv_util_service *srv)
	recv_buffer = srv->recv_buffer;
	kvp_transaction.recv_channel = srv->channel;

	init_completion(&release_event);
	/*
	 * When this driver loads, the user level daemon that
	 * processes the host requests may not yet be running.
@@ -747,5 +744,4 @@ void hv_kvp_deinit(void)
	cancel_delayed_work_sync(&kvp_timeout_work);
	cancel_work_sync(&kvp_sendkey_work);
	hvutil_transport_destroy(hvt);
	wait_for_completion(&release_event);
}
+0 −4
Original line number Diff line number Diff line
@@ -79,7 +79,6 @@ static int dm_reg_value;
static const char vss_devname[] = "vmbus/hv_vss";
static __u8 *recv_buffer;
static struct hvutil_transport *hvt;
static struct completion release_event;

static void vss_timeout_func(struct work_struct *dummy);
static void vss_handle_request(struct work_struct *dummy);
@@ -361,13 +360,11 @@ static void vss_on_reset(void)
	if (cancel_delayed_work_sync(&vss_timeout_work))
		vss_respond_to_host(HV_E_FAIL);
	vss_transaction.state = HVUTIL_DEVICE_INIT;
	complete(&release_event);
}

int
hv_vss_init(struct hv_util_service *srv)
{
	init_completion(&release_event);
	if (vmbus_proto_version < VERSION_WIN8_1) {
		pr_warn("Integration service 'Backup (volume snapshot)'"
			" not supported on this host version.\n");
@@ -400,5 +397,4 @@ void hv_vss_deinit(void)
	cancel_delayed_work_sync(&vss_timeout_work);
	cancel_work_sync(&vss_handle_request_work);
	hvutil_transport_destroy(hvt);
	wait_for_completion(&release_event);
}
+8 −4
Original line number Diff line number Diff line
@@ -182,10 +182,11 @@ static int hvt_op_release(struct inode *inode, struct file *file)
	 * connects back.
	 */
	hvt_reset(hvt);
	mutex_unlock(&hvt->lock);

	if (mode_old == HVUTIL_TRANSPORT_DESTROY)
		hvt_transport_free(hvt);
		complete(&hvt->release);

	mutex_unlock(&hvt->lock);

	return 0;
}
@@ -304,6 +305,7 @@ struct hvutil_transport *hvutil_transport_init(const char *name,

	init_waitqueue_head(&hvt->outmsg_q);
	mutex_init(&hvt->lock);
	init_completion(&hvt->release);

	spin_lock(&hvt_list_lock);
	list_add(&hvt->list, &hvt_list);
@@ -351,6 +353,8 @@ void hvutil_transport_destroy(struct hvutil_transport *hvt)
	if (hvt->cn_id.idx > 0 && hvt->cn_id.val > 0)
		cn_del_callback(&hvt->cn_id);

	if (mode_old != HVUTIL_TRANSPORT_CHARDEV)
	if (mode_old == HVUTIL_TRANSPORT_CHARDEV)
		wait_for_completion(&hvt->release);

	hvt_transport_free(hvt);
}
+1 −0
Original line number Diff line number Diff line
@@ -41,6 +41,7 @@ struct hvutil_transport {
	int outmsg_len;                     /* its length */
	wait_queue_head_t outmsg_q;         /* poll/read wait queue */
	struct mutex lock;                  /* protects struct members */
	struct completion release;          /* synchronize with fd release */
};

struct hvutil_transport *hvutil_transport_init(const char *name,