hc
2024-02-20 102a0743326a03cd1a1202ceda21e175b7d3575c
kernel/drivers/hv/hv_snapshot.c
....@@ -1,20 +1,9 @@
1
+// SPDX-License-Identifier: GPL-2.0-only
12 /*
23 * An implementation of host initiated guest snapshot.
34 *
4
- *
55 * Copyright (C) 2013, Microsoft, Inc.
66 * Author : K. Y. Srinivasan <kys@microsoft.com>
7
- *
8
- * This program is free software; you can redistribute it and/or modify it
9
- * under the terms of the GNU General Public License version 2 as published
10
- * by the Free Software Foundation.
11
- *
12
- * This program is distributed in the hope that it will be useful, but
13
- * WITHOUT ANY WARRANTY; without even the implied warranty of
14
- * MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE, GOOD TITLE or
15
- * NON INFRINGEMENT. See the GNU General Public License for more
16
- * details.
17
- *
187 */
198 #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
209
....@@ -23,6 +12,7 @@
2312 #include <linux/connector.h>
2413 #include <linux/workqueue.h>
2514 #include <linux/hyperv.h>
15
+#include <asm/hyperv-tlfs.h>
2616
2717 #include "hyperv_vmbus.h"
2818 #include "hv_utils_transport.h"
....@@ -90,7 +80,7 @@
9080 {
9181 /* Transaction is finished, reset the state here to avoid races. */
9282 vss_transaction.state = HVUTIL_READY;
93
- hv_vss_onchannelcallback(channel);
83
+ tasklet_schedule(&((struct vmbus_channel *)channel)->callback_event);
9484 }
9585
9686 /*
....@@ -308,7 +298,7 @@
308298 if (vss_transaction.state > HVUTIL_READY)
309299 return;
310300
311
- vmbus_recvpacket(channel, recv_buffer, PAGE_SIZE * 2, &recvlen,
301
+ vmbus_recvpacket(channel, recv_buffer, HV_HYP_PAGE_SIZE * 2, &recvlen,
312302 &requestid);
313303
314304 if (recvlen > 0) {
....@@ -389,10 +379,61 @@
389379 return 0;
390380 }
391381
382
+static void hv_vss_cancel_work(void)
383
+{
384
+ cancel_delayed_work_sync(&vss_timeout_work);
385
+ cancel_work_sync(&vss_handle_request_work);
386
+}
387
+
388
+int hv_vss_pre_suspend(void)
389
+{
390
+ struct vmbus_channel *channel = vss_transaction.recv_channel;
391
+ struct hv_vss_msg *vss_msg;
392
+
393
+ /*
394
+ * Fake a THAW message for the user space daemon in case the daemon
395
+ * has frozen the file systems. It doesn't matter if there is already
396
+ * a message pending to be delivered to the user space since we force
397
+ * vss_transaction.state to be HVUTIL_READY, so the user space daemon's
398
+ * write() will fail with EINVAL (see vss_on_msg()), and the daemon
399
+ * will reset the device by closing and re-opening it.
400
+ */
401
+ vss_msg = kzalloc(sizeof(*vss_msg), GFP_KERNEL);
402
+ if (!vss_msg)
403
+ return -ENOMEM;
404
+
405
+ tasklet_disable(&channel->callback_event);
406
+
407
+ vss_msg->vss_hdr.operation = VSS_OP_THAW;
408
+
409
+ /* Cancel any possible pending work. */
410
+ hv_vss_cancel_work();
411
+
412
+ /* We don't care about the return value. */
413
+ hvutil_transport_send(hvt, vss_msg, sizeof(*vss_msg), NULL);
414
+
415
+ kfree(vss_msg);
416
+
417
+ vss_transaction.state = HVUTIL_READY;
418
+
419
+ /* tasklet_enable() will be called in hv_vss_pre_resume(). */
420
+ return 0;
421
+}
422
+
423
+int hv_vss_pre_resume(void)
424
+{
425
+ struct vmbus_channel *channel = vss_transaction.recv_channel;
426
+
427
+ tasklet_enable(&channel->callback_event);
428
+
429
+ return 0;
430
+}
431
+
392432 void hv_vss_deinit(void)
393433 {
394434 vss_transaction.state = HVUTIL_DEVICE_DYING;
395
- cancel_delayed_work_sync(&vss_timeout_work);
396
- cancel_work_sync(&vss_handle_request_work);
435
+
436
+ hv_vss_cancel_work();
437
+
397438 hvutil_transport_destroy(hvt);
398439 }