]> git.proxmox.com Git - mirror_ubuntu-bionic-kernel.git/blame - drivers/hv/hv_snapshot.c
Drivers: hv: kvp: switch to using the hvutil_device_state state machine
[mirror_ubuntu-bionic-kernel.git] / drivers / hv / hv_snapshot.c
CommitLineData
96dd86fa
S
1/*
2 * An implementation of host initiated guest snapshot.
3 *
4 *
5 * Copyright (C) 2013, Microsoft, Inc.
6 * 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 *
18 */
19#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
20
21#include <linux/net.h>
22#include <linux/nls.h>
23#include <linux/connector.h>
24#include <linux/workqueue.h>
25#include <linux/hyperv.h>
26
3647a83d
VK
27#include "hyperv_vmbus.h"
28
6741335b
S
29#define VSS_MAJOR 5
30#define VSS_MINOR 0
3a491605 31#define VSS_VERSION (VSS_MAJOR << 16 | VSS_MINOR)
6741335b 32
64914207 33#define VSS_USERSPACE_TIMEOUT (msecs_to_jiffies(10 * 1000))
96dd86fa
S
34
35/*
36 * Global state maintained for transaction that is being processed.
37 * Note that only one transaction can be active at any point in time.
38 *
39 * This state is set when we receive a request from the host; we
40 * cleanup this state when the transaction is completed - when we respond
41 * to the host with the key value.
42 */
43
44static struct {
45 bool active; /* transaction status - active or not */
46 int recv_len; /* number of bytes received. */
47 struct vmbus_channel *recv_channel; /* chn we got the request */
48 u64 recv_req_id; /* request ID. */
49 struct hv_vss_msg *msg; /* current message */
38c06c29 50 void *vss_context; /* for the channel callback */
96dd86fa
S
51} vss_transaction;
52
53
54static void vss_respond_to_host(int error);
55
56static struct cb_id vss_id = { CN_VSS_IDX, CN_VSS_VAL };
57static const char vss_name[] = "vss_kernel_module";
58static __u8 *recv_buffer;
59
60static void vss_send_op(struct work_struct *dummy);
64914207
VK
61static void vss_timeout_func(struct work_struct *dummy);
62
63static DECLARE_DELAYED_WORK(vss_timeout_work, vss_timeout_func);
96dd86fa
S
64static DECLARE_WORK(vss_send_op_work, vss_send_op);
65
66/*
67 * Callback when data is received from user mode.
68 */
69
64914207
VK
70static void vss_timeout_func(struct work_struct *dummy)
71{
72 /*
73 * Timeout waiting for userspace component to reply happened.
74 */
75 pr_warn("VSS: timeout waiting for daemon to reply\n");
76 vss_respond_to_host(HV_E_FAIL);
38c06c29
VK
77
78 hv_poll_channel(vss_transaction.vss_context,
79 hv_vss_onchannelcallback);
64914207
VK
80}
81
96dd86fa
S
82static void
83vss_cn_callback(struct cn_msg *msg, struct netlink_skb_parms *nsp)
84{
85 struct hv_vss_msg *vss_msg;
86
87 vss_msg = (struct hv_vss_msg *)msg->data;
88
89 if (vss_msg->vss_hdr.operation == VSS_OP_REGISTER) {
90 pr_info("VSS daemon registered\n");
91 vss_transaction.active = false;
96dd86fa 92 }
64914207
VK
93 if (cancel_delayed_work_sync(&vss_timeout_work))
94 vss_respond_to_host(vss_msg->error);
38c06c29
VK
95
96 hv_poll_channel(vss_transaction.vss_context,
97 hv_vss_onchannelcallback);
96dd86fa
S
98}
99
100
101static void vss_send_op(struct work_struct *dummy)
102{
103 int op = vss_transaction.msg->vss_hdr.operation;
8d9560eb 104 int rc;
96dd86fa
S
105 struct cn_msg *msg;
106 struct hv_vss_msg *vss_msg;
107
108 msg = kzalloc(sizeof(*msg) + sizeof(*vss_msg), GFP_ATOMIC);
109 if (!msg)
110 return;
111
112 vss_msg = (struct hv_vss_msg *)msg->data;
113
114 msg->id.idx = CN_VSS_IDX;
115 msg->id.val = CN_VSS_VAL;
116
117 vss_msg->vss_hdr.operation = op;
118 msg->len = sizeof(struct hv_vss_msg);
119
8d9560eb
VK
120 rc = cn_netlink_send(msg, 0, 0, GFP_ATOMIC);
121 if (rc) {
122 pr_warn("VSS: failed to communicate to the daemon: %d\n", rc);
123 if (cancel_delayed_work_sync(&vss_timeout_work))
124 vss_respond_to_host(HV_E_FAIL);
125 }
96dd86fa
S
126 kfree(msg);
127
128 return;
129}
130
131/*
132 * Send a response back to the host.
133 */
134
135static void
136vss_respond_to_host(int error)
137{
138 struct icmsg_hdr *icmsghdrp;
139 u32 buf_len;
140 struct vmbus_channel *channel;
141 u64 req_id;
142
143 /*
144 * If a transaction is not active; log and return.
145 */
146
147 if (!vss_transaction.active) {
148 /*
149 * This is a spurious call!
150 */
151 pr_warn("VSS: Transaction not active\n");
152 return;
153 }
154 /*
155 * Copy the global state for completing the transaction. Note that
156 * only one transaction can be active at a time.
157 */
158
159 buf_len = vss_transaction.recv_len;
160 channel = vss_transaction.recv_channel;
161 req_id = vss_transaction.recv_req_id;
162 vss_transaction.active = false;
163
164 icmsghdrp = (struct icmsg_hdr *)
165 &recv_buffer[sizeof(struct vmbuspipe_hdr)];
166
167 if (channel->onchannel_callback == NULL)
168 /*
169 * We have raced with util driver being unloaded;
170 * silently return.
171 */
172 return;
173
174 icmsghdrp->status = error;
175
176 icmsghdrp->icflags = ICMSGHDRFLAG_TRANSACTION | ICMSGHDRFLAG_RESPONSE;
177
178 vmbus_sendpacket(channel, recv_buffer, buf_len, req_id,
179 VM_PKT_DATA_INBAND, 0);
180
181}
182
183/*
184 * This callback is invoked when we get a VSS message from the host.
185 * The host ensures that only one VSS transaction can be active at a time.
186 */
187
188void hv_vss_onchannelcallback(void *context)
189{
190 struct vmbus_channel *channel = context;
191 u32 recvlen;
192 u64 requestid;
193 struct hv_vss_msg *vss_msg;
194
195
196 struct icmsg_hdr *icmsghdrp;
197 struct icmsg_negotiate *negop = NULL;
198
199 if (vss_transaction.active) {
200 /*
201 * We will defer processing this callback once
202 * the current transaction is complete.
203 */
38c06c29 204 vss_transaction.vss_context = context;
96dd86fa
S
205 return;
206 }
38c06c29 207 vss_transaction.vss_context = NULL;
96dd86fa
S
208
209 vmbus_recvpacket(channel, recv_buffer, PAGE_SIZE * 2, &recvlen,
210 &requestid);
211
212 if (recvlen > 0) {
213 icmsghdrp = (struct icmsg_hdr *)&recv_buffer[
214 sizeof(struct vmbuspipe_hdr)];
215
216 if (icmsghdrp->icmsgtype == ICMSGTYPE_NEGOTIATE) {
217 vmbus_prep_negotiate_resp(icmsghdrp, negop,
3a491605
S
218 recv_buffer, UTIL_FW_VERSION,
219 VSS_VERSION);
96dd86fa
S
220 } else {
221 vss_msg = (struct hv_vss_msg *)&recv_buffer[
222 sizeof(struct vmbuspipe_hdr) +
223 sizeof(struct icmsg_hdr)];
224
225 /*
226 * Stash away this global state for completing the
227 * transaction; note transactions are serialized.
228 */
229
230 vss_transaction.recv_len = recvlen;
231 vss_transaction.recv_channel = channel;
232 vss_transaction.recv_req_id = requestid;
233 vss_transaction.active = true;
234 vss_transaction.msg = (struct hv_vss_msg *)vss_msg;
235
236 switch (vss_msg->vss_hdr.operation) {
237 /*
238 * Initiate a "freeze/thaw"
239 * operation in the guest.
240 * We respond to the host once
241 * the operation is complete.
242 *
243 * We send the message to the
244 * user space daemon and the
245 * operation is performed in
246 * the daemon.
247 */
248 case VSS_OP_FREEZE:
249 case VSS_OP_THAW:
250 schedule_work(&vss_send_op_work);
64914207
VK
251 schedule_delayed_work(&vss_timeout_work,
252 VSS_USERSPACE_TIMEOUT);
96dd86fa
S
253 return;
254
255 case VSS_OP_HOT_BACKUP:
256 vss_msg->vss_cf.flags =
257 VSS_HBU_NO_AUTO_RECOVERY;
258 vss_respond_to_host(0);
259 return;
260
261 case VSS_OP_GET_DM_INFO:
262 vss_msg->dm_info.flags = 0;
263 vss_respond_to_host(0);
264 return;
265
266 default:
267 vss_respond_to_host(0);
268 return;
269
270 }
271
272 }
273
274 icmsghdrp->icflags = ICMSGHDRFLAG_TRANSACTION
275 | ICMSGHDRFLAG_RESPONSE;
276
277 vmbus_sendpacket(channel, recv_buffer,
278 recvlen, requestid,
279 VM_PKT_DATA_INBAND, 0);
280 }
281
282}
283
284int
285hv_vss_init(struct hv_util_service *srv)
286{
287 int err;
288
289 err = cn_add_callback(&vss_id, vss_name, vss_cn_callback);
290 if (err)
291 return err;
292 recv_buffer = srv->recv_buffer;
293
294 /*
295 * When this driver loads, the user level daemon that
296 * processes the host requests may not yet be running.
297 * Defer processing channel callbacks until the daemon
298 * has registered.
299 */
300 vss_transaction.active = true;
301 return 0;
302}
303
304void hv_vss_deinit(void)
305{
306 cn_del_callback(&vss_id);
64914207 307 cancel_delayed_work_sync(&vss_timeout_work);
96dd86fa
S
308 cancel_work_sync(&vss_send_op_work);
309}