1 /*-
2 * Copyright (c) 2016 Microsoft Corp.
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 * 1. Redistributions of source code must retain the above copyright
9 * notice unmodified, this list of conditions, and the following
10 * disclaimer.
11 * 2. Redistributions in binary form must reproduce the above copyright
12 * notice, this list of conditions and the following disclaimer in the
13 * documentation and/or other materials provided with the distribution.
14 *
15 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
16 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
17 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
18 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
19 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
20 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
21 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
22 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
23 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
24 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
25 */
26
27 #include <sys/cdefs.h>
28 #include <sys/param.h>
29 #include <sys/kernel.h>
30 #include <sys/conf.h>
31 #include <sys/uio.h>
32 #include <sys/bus.h>
33 #include <sys/malloc.h>
34 #include <sys/mbuf.h>
35 #include <sys/module.h>
36 #include <sys/lock.h>
37 #include <sys/taskqueue.h>
38 #include <sys/selinfo.h>
39 #include <sys/sysctl.h>
40 #include <sys/poll.h>
41 #include <sys/proc.h>
42 #include <sys/queue.h>
43 #include <sys/kthread.h>
44 #include <sys/syscallsubr.h>
45 #include <sys/sysproto.h>
46 #include <sys/un.h>
47 #include <sys/endian.h>
48 #include <sys/sema.h>
49 #include <sys/signal.h>
50 #include <sys/syslog.h>
51 #include <sys/systm.h>
52 #include <sys/mutex.h>
53 #include <sys/callout.h>
54
55 #include <dev/hyperv/include/hyperv.h>
56 #include <dev/hyperv/utilities/hv_utilreg.h>
57 #include <dev/hyperv/utilities/vmbus_icreg.h>
58 #include <dev/hyperv/utilities/vmbus_icvar.h>
59
60 #include "hv_snapshot.h"
61 #include "vmbus_if.h"
62
63 #define VSS_MAJOR 5
64 #define VSS_MINOR 0
65 #define VSS_MSGVER VMBUS_IC_VERSION(VSS_MAJOR, VSS_MINOR)
66
67 #define VSS_FWVER_MAJOR 3
68 #define VSS_FWVER VMBUS_IC_VERSION(VSS_FWVER_MAJOR, 0)
69
70 #define TIMEOUT_LIMIT (15) // seconds
71 enum hv_vss_op {
72 VSS_OP_CREATE = 0,
73 VSS_OP_DELETE,
74 VSS_OP_HOT_BACKUP,
75 VSS_OP_GET_DM_INFO,
76 VSS_OP_BU_COMPLETE,
77 /*
78 * Following operations are only supported with IC version >= 5.0
79 */
80 VSS_OP_FREEZE, /* Freeze the file systems in the VM */
81 VSS_OP_THAW, /* Unfreeze the file systems */
82 VSS_OP_AUTO_RECOVER,
83 VSS_OP_COUNT /* Number of operations, must be last */
84 };
85
86 /*
87 * Header for all VSS messages.
88 */
89 struct hv_vss_hdr {
90 struct vmbus_icmsg_hdr ic_hdr;
91 uint8_t operation;
92 uint8_t reserved[7];
93 } __packed;
94
95
96 /*
97 * Flag values for the hv_vss_check_feature. Here supports only
98 * one value.
99 */
100 #define VSS_HBU_NO_AUTO_RECOVERY 0x00000005
101
102 struct hv_vss_check_feature {
103 uint32_t flags;
104 } __packed;
105
106 struct hv_vss_check_dm_info {
107 uint32_t flags;
108 } __packed;
109
110 struct hv_vss_msg {
111 union {
112 struct hv_vss_hdr vss_hdr;
113 } hdr;
114 union {
115 struct hv_vss_check_feature vss_cf;
116 struct hv_vss_check_dm_info dm_info;
117 } body;
118 } __packed;
119
120 struct hv_vss_req {
121 struct hv_vss_opt_msg opt_msg; /* used to communicate with daemon */
122 struct hv_vss_msg msg; /* used to communicate with host */
123 } __packed;
124
125 /* hv_vss debug control */
126 static int hv_vss_log = 0;
127
128 #define hv_vss_log_error(...) do { \
129 if (hv_vss_log > 0) \
130 log(LOG_ERR, "hv_vss: " __VA_ARGS__); \
131 } while (0)
132
133 #define hv_vss_log_info(...) do { \
134 if (hv_vss_log > 1) \
135 log(LOG_INFO, "hv_vss: " __VA_ARGS__); \
136 } while (0)
137
138 static const struct vmbus_ic_desc vmbus_vss_descs[] = {
139 {
140 .ic_guid = { .hv_guid = {
141 0x29, 0x2e, 0xfa, 0x35, 0x23, 0xea, 0x36, 0x42,
142 0x96, 0xae, 0x3a, 0x6e, 0xba, 0xcb, 0xa4, 0x40} },
143 .ic_desc = "Hyper-V VSS"
144 },
145 VMBUS_IC_DESC_END
146 };
147
148 static const char * vss_opt_name[] = {"None", "VSSCheck", "Freeze", "Thaw"};
149
150 /* character device prototypes */
151 static d_open_t hv_vss_dev_open;
152 static d_close_t hv_vss_dev_close;
153 static d_poll_t hv_vss_dev_daemon_poll;
154 static d_ioctl_t hv_vss_dev_daemon_ioctl;
155
156 static d_open_t hv_appvss_dev_open;
157 static d_close_t hv_appvss_dev_close;
158 static d_poll_t hv_appvss_dev_poll;
159 static d_ioctl_t hv_appvss_dev_ioctl;
160
161 /* hv_vss character device structure */
162 static struct cdevsw hv_vss_cdevsw =
163 {
164 .d_version = D_VERSION,
165 .d_open = hv_vss_dev_open,
166 .d_close = hv_vss_dev_close,
167 .d_poll = hv_vss_dev_daemon_poll,
168 .d_ioctl = hv_vss_dev_daemon_ioctl,
169 .d_name = FS_VSS_DEV_NAME,
170 };
171
172 static struct cdevsw hv_appvss_cdevsw =
173 {
174 .d_version = D_VERSION,
175 .d_open = hv_appvss_dev_open,
176 .d_close = hv_appvss_dev_close,
177 .d_poll = hv_appvss_dev_poll,
178 .d_ioctl = hv_appvss_dev_ioctl,
179 .d_name = APP_VSS_DEV_NAME,
180 };
181
182 struct hv_vss_sc;
183 /*
184 * Global state to track cdev
185 */
186 struct hv_vss_dev_sc {
187 /*
188 * msg was transferred from host to notify queue, and
189 * ack queue. Finally, it was recyled to free list.
190 */
191 STAILQ_HEAD(, hv_vss_req_internal) to_notify_queue;
192 STAILQ_HEAD(, hv_vss_req_internal) to_ack_queue;
193 struct hv_vss_sc *sc;
194 struct proc *proc_task;
195 struct selinfo hv_vss_selinfo;
196 };
197 /*
198 * Global state to track and synchronize the transaction requests from the host.
199 * The VSS allows user to register their function to do freeze/thaw for application.
200 * VSS kernel will notify both vss daemon and user application if it is registered.
201 * The implementation state transition is illustrated by:
202 * https://clovertrail.github.io/assets/vssdot.png
203 */
204 typedef struct hv_vss_sc {
205 struct vmbus_ic_softc util_sc;
206 device_t dev;
207
208 struct task task;
209
210 /*
211 * mutex is used to protect access of list/queue,
212 * callout in request is also used this mutex.
213 */
214 struct mtx pending_mutex;
215 /*
216 * req_free_list contains all free items
217 */
218 LIST_HEAD(, hv_vss_req_internal) req_free_list;
219
220 /* Indicates if daemon registered with driver */
221 boolean_t register_done;
222
223 boolean_t app_register_done;
224
225 /* cdev for file system freeze/thaw */
226 struct cdev *hv_vss_dev;
227 /* cdev for application freeze/thaw */
228 struct cdev *hv_appvss_dev;
229
230 /* sc for app */
231 struct hv_vss_dev_sc app_sc;
232 /* sc for deamon */
233 struct hv_vss_dev_sc daemon_sc;
234 } hv_vss_sc;
235
236 typedef struct hv_vss_req_internal {
237 LIST_ENTRY(hv_vss_req_internal) link;
238 STAILQ_ENTRY(hv_vss_req_internal) slink;
239 struct hv_vss_req vss_req;
240
241 /* Rcv buffer for communicating with the host*/
242 uint8_t *rcv_buf;
243 /* Length of host message */
244 uint32_t host_msg_len;
245 /* Host message id */
246 uint64_t host_msg_id;
247
248 hv_vss_sc *sc;
249
250 struct callout callout;
251 } hv_vss_req_internal;
252
253 #define SEARCH_REMOVE_REQ_LOCKED(reqp, queue, link, tmp, id) \
254 do { \
255 STAILQ_FOREACH_SAFE(reqp, queue, link, tmp) { \
256 if (reqp->vss_req.opt_msg.msgid == id) { \
257 STAILQ_REMOVE(queue, \
258 reqp, hv_vss_req_internal, link); \
259 break; \
260 } \
261 } \
262 } while (0)
263
264 static bool
hv_vss_is_daemon_killed_after_launch(hv_vss_sc * sc)265 hv_vss_is_daemon_killed_after_launch(hv_vss_sc *sc)
266 {
267 return (!sc->register_done && sc->daemon_sc.proc_task);
268 }
269
270 /*
271 * Callback routine that gets called whenever there is a message from host
272 */
273 static void
hv_vss_callback(struct vmbus_channel * chan __unused,void * context)274 hv_vss_callback(struct vmbus_channel *chan __unused, void *context)
275 {
276 hv_vss_sc *sc = (hv_vss_sc*)context;
277 if (hv_vss_is_daemon_killed_after_launch(sc))
278 hv_vss_log_info("%s: daemon was killed!\n", __func__);
279 if (sc->register_done || sc->daemon_sc.proc_task) {
280 hv_vss_log_info("%s: Queuing work item\n", __func__);
281 if (hv_vss_is_daemon_killed_after_launch(sc))
282 hv_vss_log_info("%s: daemon was killed!\n", __func__);
283 taskqueue_enqueue(taskqueue_thread, &sc->task);
284 } else {
285 hv_vss_log_info("%s: daemon has never been registered\n", __func__);
286 }
287 hv_vss_log_info("%s: received msg from host\n", __func__);
288 }
289 /*
290 * Send the response back to the host.
291 */
292 static void
hv_vss_respond_host(uint8_t * rcv_buf,struct vmbus_channel * ch,uint32_t recvlen,uint64_t requestid,uint32_t error)293 hv_vss_respond_host(uint8_t *rcv_buf, struct vmbus_channel *ch,
294 uint32_t recvlen, uint64_t requestid, uint32_t error)
295 {
296 struct vmbus_icmsg_hdr *hv_icmsg_hdrp;
297
298 hv_icmsg_hdrp = (struct vmbus_icmsg_hdr *)rcv_buf;
299
300 hv_icmsg_hdrp->ic_status = error;
301 hv_icmsg_hdrp->ic_flags = HV_ICMSGHDRFLAG_TRANSACTION | HV_ICMSGHDRFLAG_RESPONSE;
302
303 error = vmbus_chan_send(ch, VMBUS_CHANPKT_TYPE_INBAND, 0,
304 rcv_buf, recvlen, requestid);
305 if (error)
306 hv_vss_log_info("%s: hv_vss_respond_host: sendpacket error:%d\n",
307 __func__, error);
308 }
309
310 static void
hv_vss_notify_host_result_locked(struct hv_vss_req_internal * reqp,uint32_t status)311 hv_vss_notify_host_result_locked(struct hv_vss_req_internal *reqp, uint32_t status)
312 {
313 struct hv_vss_msg* msg = (struct hv_vss_msg *)reqp->rcv_buf;
314 hv_vss_sc *sc = reqp->sc;
315 if (reqp->vss_req.opt_msg.opt == HV_VSS_CHECK) {
316 msg->body.vss_cf.flags = VSS_HBU_NO_AUTO_RECOVERY;
317 }
318 hv_vss_log_info("%s, %s response %s to host\n", __func__,
319 vss_opt_name[reqp->vss_req.opt_msg.opt],
320 status == HV_S_OK ? "Success" : "Fail");
321 hv_vss_respond_host(reqp->rcv_buf, vmbus_get_channel(reqp->sc->dev),
322 reqp->host_msg_len, reqp->host_msg_id, status);
323 /* recycle the request */
324 LIST_INSERT_HEAD(&sc->req_free_list, reqp, link);
325 }
326
327 static void
hv_vss_notify_host_result(struct hv_vss_req_internal * reqp,uint32_t status)328 hv_vss_notify_host_result(struct hv_vss_req_internal *reqp, uint32_t status)
329 {
330 mtx_lock(&reqp->sc->pending_mutex);
331 hv_vss_notify_host_result_locked(reqp, status);
332 mtx_unlock(&reqp->sc->pending_mutex);
333 }
334
335 static void
hv_vss_cp_vssreq_to_user(struct hv_vss_req_internal * reqp,struct hv_vss_opt_msg * userdata)336 hv_vss_cp_vssreq_to_user(struct hv_vss_req_internal *reqp,
337 struct hv_vss_opt_msg *userdata)
338 {
339 struct hv_vss_req *hv_vss_dev_buf;
340 hv_vss_dev_buf = &reqp->vss_req;
341 hv_vss_dev_buf->opt_msg.opt = HV_VSS_NONE;
342 switch (reqp->vss_req.msg.hdr.vss_hdr.operation) {
343 case VSS_OP_FREEZE:
344 hv_vss_dev_buf->opt_msg.opt = HV_VSS_FREEZE;
345 break;
346 case VSS_OP_THAW:
347 hv_vss_dev_buf->opt_msg.opt = HV_VSS_THAW;
348 break;
349 case VSS_OP_HOT_BACKUP:
350 hv_vss_dev_buf->opt_msg.opt = HV_VSS_CHECK;
351 break;
352 }
353 *userdata = hv_vss_dev_buf->opt_msg;
354 hv_vss_log_info("%s, read data from user for "
355 "%s (%ju) \n", __func__, vss_opt_name[userdata->opt],
356 (uintmax_t)userdata->msgid);
357 }
358
359 /**
360 * Remove the request id from app notifiy or ack queue,
361 * and recyle the request by inserting it to free list.
362 *
363 * When app was notified but not yet sending ack, the request
364 * should locate in either notify queue or ack queue.
365 */
366 static struct hv_vss_req_internal*
hv_vss_drain_req_queue_locked(hv_vss_sc * sc,uint64_t req_id)367 hv_vss_drain_req_queue_locked(hv_vss_sc *sc, uint64_t req_id)
368 {
369 struct hv_vss_req_internal *reqp, *tmp;
370 SEARCH_REMOVE_REQ_LOCKED(reqp, &sc->daemon_sc.to_notify_queue,
371 slink, tmp, req_id);
372 if (reqp == NULL)
373 SEARCH_REMOVE_REQ_LOCKED(reqp, &sc->daemon_sc.to_ack_queue,
374 slink, tmp, req_id);
375 if (reqp == NULL)
376 SEARCH_REMOVE_REQ_LOCKED(reqp, &sc->app_sc.to_notify_queue,
377 slink, tmp, req_id);
378 if (reqp == NULL)
379 SEARCH_REMOVE_REQ_LOCKED(reqp, &sc->app_sc.to_ack_queue, slink,
380 tmp, req_id);
381 return (reqp);
382 }
383 /**
384 * Actions for daemon who has been notified.
385 */
386 static void
hv_vss_notified(struct hv_vss_dev_sc * dev_sc,struct hv_vss_opt_msg * userdata)387 hv_vss_notified(struct hv_vss_dev_sc *dev_sc, struct hv_vss_opt_msg *userdata)
388 {
389 struct hv_vss_req_internal *reqp;
390 mtx_lock(&dev_sc->sc->pending_mutex);
391 if (!STAILQ_EMPTY(&dev_sc->to_notify_queue)) {
392 reqp = STAILQ_FIRST(&dev_sc->to_notify_queue);
393 hv_vss_cp_vssreq_to_user(reqp, userdata);
394 STAILQ_REMOVE_HEAD(&dev_sc->to_notify_queue, slink);
395 /* insert the msg to queue for write */
396 STAILQ_INSERT_TAIL(&dev_sc->to_ack_queue, reqp, slink);
397 userdata->status = VSS_SUCCESS;
398 } else {
399 /* Timeout occur, thus request was removed from queue. */
400 hv_vss_log_info("%s: notify queue is empty!\n", __func__);
401 userdata->status = VSS_FAIL;
402 }
403 mtx_unlock(&dev_sc->sc->pending_mutex);
404 }
405
406 static void
hv_vss_notify(struct hv_vss_dev_sc * dev_sc,struct hv_vss_req_internal * reqp)407 hv_vss_notify(struct hv_vss_dev_sc *dev_sc, struct hv_vss_req_internal *reqp)
408 {
409 uint32_t opt = reqp->vss_req.opt_msg.opt;
410 mtx_lock(&dev_sc->sc->pending_mutex);
411 STAILQ_INSERT_TAIL(&dev_sc->to_notify_queue, reqp, slink);
412 hv_vss_log_info("%s: issuing query %s (%ju) to %s\n", __func__,
413 vss_opt_name[opt], (uintmax_t)reqp->vss_req.opt_msg.msgid,
414 &dev_sc->sc->app_sc == dev_sc ? "app" : "daemon");
415 mtx_unlock(&dev_sc->sc->pending_mutex);
416 selwakeup(&dev_sc->hv_vss_selinfo);
417 }
418
419 /**
420 * Actions for daemon who has acknowledged.
421 */
422 static void
hv_vss_daemon_acked(struct hv_vss_dev_sc * dev_sc,struct hv_vss_opt_msg * userdata)423 hv_vss_daemon_acked(struct hv_vss_dev_sc *dev_sc, struct hv_vss_opt_msg *userdata)
424 {
425 struct hv_vss_req_internal *reqp, *tmp;
426 uint64_t req_id;
427 int opt;
428 uint32_t status;
429
430 opt = userdata->opt;
431 req_id = userdata->msgid;
432 status = userdata->status;
433 /* make sure the reserved fields are all zeros. */
434 memset(&userdata->reserved, 0, sizeof(struct hv_vss_opt_msg) -
435 __offsetof(struct hv_vss_opt_msg, reserved));
436 mtx_lock(&dev_sc->sc->pending_mutex);
437 SEARCH_REMOVE_REQ_LOCKED(reqp, &dev_sc->to_ack_queue, slink, tmp, req_id);
438 mtx_unlock(&dev_sc->sc->pending_mutex);
439 if (reqp == NULL) {
440 hv_vss_log_info("%s Timeout: fail to find daemon ack request\n",
441 __func__);
442 userdata->status = VSS_FAIL;
443 return;
444 }
445 KASSERT(opt == reqp->vss_req.opt_msg.opt, ("Mismatched VSS operation!"));
446 hv_vss_log_info("%s, get response %d from daemon for %s (%ju) \n", __func__,
447 status, vss_opt_name[opt], (uintmax_t)req_id);
448 switch (opt) {
449 case HV_VSS_CHECK:
450 case HV_VSS_FREEZE:
451 callout_drain(&reqp->callout);
452 hv_vss_notify_host_result(reqp,
453 status == VSS_SUCCESS ? HV_S_OK : HV_E_FAIL);
454 break;
455 case HV_VSS_THAW:
456 if (dev_sc->sc->app_register_done) {
457 if (status == VSS_SUCCESS) {
458 hv_vss_notify(&dev_sc->sc->app_sc, reqp);
459 } else {
460 /* handle error */
461 callout_drain(&reqp->callout);
462 hv_vss_notify_host_result(reqp, HV_E_FAIL);
463 }
464 } else {
465 callout_drain(&reqp->callout);
466 hv_vss_notify_host_result(reqp,
467 status == VSS_SUCCESS ? HV_S_OK : HV_E_FAIL);
468 }
469 break;
470 }
471 }
472
473 /**
474 * Actions for app who has acknowledged.
475 */
476 static void
hv_vss_app_acked(struct hv_vss_dev_sc * dev_sc,struct hv_vss_opt_msg * userdata)477 hv_vss_app_acked(struct hv_vss_dev_sc *dev_sc, struct hv_vss_opt_msg *userdata)
478 {
479 struct hv_vss_req_internal *reqp, *tmp;
480 uint64_t req_id;
481 int opt;
482 uint8_t status;
483
484 opt = userdata->opt;
485 req_id = userdata->msgid;
486 status = userdata->status;
487 /* make sure the reserved fields are all zeros. */
488 memset(&userdata->reserved, 0, sizeof(struct hv_vss_opt_msg) -
489 __offsetof(struct hv_vss_opt_msg, reserved));
490 mtx_lock(&dev_sc->sc->pending_mutex);
491 SEARCH_REMOVE_REQ_LOCKED(reqp, &dev_sc->to_ack_queue, slink, tmp, req_id);
492 mtx_unlock(&dev_sc->sc->pending_mutex);
493 if (reqp == NULL) {
494 hv_vss_log_info("%s Timeout: fail to find app ack request\n",
495 __func__);
496 userdata->status = VSS_FAIL;
497 return;
498 }
499 KASSERT(opt == reqp->vss_req.opt_msg.opt, ("Mismatched VSS operation!"));
500 hv_vss_log_info("%s, get response %d from app for %s (%ju) \n",
501 __func__, status, vss_opt_name[opt], (uintmax_t)req_id);
502 if (dev_sc->sc->register_done) {
503 switch (opt) {
504 case HV_VSS_CHECK:
505 case HV_VSS_FREEZE:
506 if (status == VSS_SUCCESS) {
507 hv_vss_notify(&dev_sc->sc->daemon_sc, reqp);
508 } else {
509 /* handle error */
510 callout_drain(&reqp->callout);
511 hv_vss_notify_host_result(reqp, HV_E_FAIL);
512 }
513 break;
514 case HV_VSS_THAW:
515 callout_drain(&reqp->callout);
516 hv_vss_notify_host_result(reqp,
517 status == VSS_SUCCESS ? HV_S_OK : HV_E_FAIL);
518 break;
519 }
520 } else {
521 hv_vss_log_info("%s, Fatal: vss daemon was killed\n", __func__);
522 }
523 }
524
525 static int
hv_vss_dev_open(struct cdev * dev,int oflags,int devtype,struct thread * td)526 hv_vss_dev_open(struct cdev *dev, int oflags, int devtype, struct thread *td)
527 {
528 struct proc *td_proc;
529 td_proc = td->td_proc;
530
531 struct hv_vss_dev_sc *dev_sc = (struct hv_vss_dev_sc*)dev->si_drv1;
532 hv_vss_log_info("%s: %s opens device \"%s\" successfully.\n",
533 __func__, td_proc->p_comm, FS_VSS_DEV_NAME);
534
535 if (dev_sc->sc->register_done)
536 return (EBUSY);
537
538 dev_sc->sc->register_done = true;
539 hv_vss_callback(vmbus_get_channel(dev_sc->sc->dev), dev_sc->sc);
540
541 dev_sc->proc_task = curproc;
542 return (0);
543 }
544
545 static int
hv_vss_dev_close(struct cdev * dev,int fflag __unused,int devtype __unused,struct thread * td)546 hv_vss_dev_close(struct cdev *dev, int fflag __unused, int devtype __unused,
547 struct thread *td)
548 {
549 struct proc *td_proc;
550 td_proc = td->td_proc;
551
552 struct hv_vss_dev_sc *dev_sc = (struct hv_vss_dev_sc*)dev->si_drv1;
553
554 hv_vss_log_info("%s: %s closes device \"%s\"\n",
555 __func__, td_proc->p_comm, FS_VSS_DEV_NAME);
556 dev_sc->sc->register_done = false;
557 return (0);
558 }
559
560 static int
hv_vss_dev_daemon_ioctl(struct cdev * dev,u_long cmd,caddr_t data,int flag,struct thread * td)561 hv_vss_dev_daemon_ioctl(struct cdev *dev, u_long cmd, caddr_t data, int flag,
562 struct thread *td)
563 {
564 struct proc *td_proc;
565 struct hv_vss_dev_sc *sc;
566
567 td_proc = td->td_proc;
568 sc = (struct hv_vss_dev_sc*)dev->si_drv1;
569
570 hv_vss_log_info("%s: %s invoked vss ioctl\n", __func__, td_proc->p_comm);
571
572 struct hv_vss_opt_msg* userdata = (struct hv_vss_opt_msg*)data;
573 switch(cmd) {
574 case IOCHVVSSREAD:
575 hv_vss_notified(sc, userdata);
576 break;
577 case IOCHVVSSWRITE:
578 hv_vss_daemon_acked(sc, userdata);
579 break;
580 }
581 return (0);
582 }
583
584 /*
585 * hv_vss_daemon poll invokes this function to check if data is available
586 * for daemon to read.
587 */
588 static int
hv_vss_dev_daemon_poll(struct cdev * dev,int events,struct thread * td)589 hv_vss_dev_daemon_poll(struct cdev *dev, int events, struct thread *td)
590 {
591 int revent = 0;
592 struct hv_vss_dev_sc *dev_sc = (struct hv_vss_dev_sc*)dev->si_drv1;
593
594 mtx_lock(&dev_sc->sc->pending_mutex);
595 /**
596 * if there is data ready, inform daemon's poll
597 */
598 if (!STAILQ_EMPTY(&dev_sc->to_notify_queue))
599 revent = POLLIN;
600 if (revent == 0)
601 selrecord(td, &dev_sc->hv_vss_selinfo);
602 hv_vss_log_info("%s return 0x%x\n", __func__, revent);
603 mtx_unlock(&dev_sc->sc->pending_mutex);
604 return (revent);
605 }
606
607 static int
hv_appvss_dev_open(struct cdev * dev,int oflags,int devtype,struct thread * td)608 hv_appvss_dev_open(struct cdev *dev, int oflags, int devtype, struct thread *td)
609 {
610 struct proc *td_proc;
611 td_proc = td->td_proc;
612
613 struct hv_vss_dev_sc *dev_sc = (struct hv_vss_dev_sc*)dev->si_drv1;
614 hv_vss_log_info("%s: %s opens device \"%s\" successfully.\n",
615 __func__, td_proc->p_comm, APP_VSS_DEV_NAME);
616
617 if (dev_sc->sc->app_register_done)
618 return (EBUSY);
619
620 dev_sc->sc->app_register_done = true;
621 dev_sc->proc_task = curproc;
622 return (0);
623 }
624
625 static int
hv_appvss_dev_close(struct cdev * dev,int fflag __unused,int devtype __unused,struct thread * td)626 hv_appvss_dev_close(struct cdev *dev, int fflag __unused, int devtype __unused,
627 struct thread *td)
628 {
629 struct proc *td_proc;
630 td_proc = td->td_proc;
631
632 struct hv_vss_dev_sc *dev_sc = (struct hv_vss_dev_sc*)dev->si_drv1;
633
634 hv_vss_log_info("%s: %s closes device \"%s\".\n",
635 __func__, td_proc->p_comm, APP_VSS_DEV_NAME);
636 dev_sc->sc->app_register_done = false;
637 return (0);
638 }
639
640 static int
hv_appvss_dev_ioctl(struct cdev * dev,u_long cmd,caddr_t data,int flag,struct thread * td)641 hv_appvss_dev_ioctl(struct cdev *dev, u_long cmd, caddr_t data, int flag,
642 struct thread *td)
643 {
644 struct proc *td_proc;
645 struct hv_vss_dev_sc *dev_sc;
646
647 td_proc = td->td_proc;
648 dev_sc = (struct hv_vss_dev_sc*)dev->si_drv1;
649
650 hv_vss_log_info("%s: %s invoked vss ioctl\n", __func__, td_proc->p_comm);
651
652 struct hv_vss_opt_msg* userdata = (struct hv_vss_opt_msg*)data;
653 switch(cmd) {
654 case IOCHVVSSREAD:
655 hv_vss_notified(dev_sc, userdata);
656 break;
657 case IOCHVVSSWRITE:
658 hv_vss_app_acked(dev_sc, userdata);
659 break;
660 }
661 return (0);
662 }
663
664 /*
665 * hv_vss_daemon poll invokes this function to check if data is available
666 * for daemon to read.
667 */
668 static int
hv_appvss_dev_poll(struct cdev * dev,int events,struct thread * td)669 hv_appvss_dev_poll(struct cdev *dev, int events, struct thread *td)
670 {
671 int revent = 0;
672 struct hv_vss_dev_sc *dev_sc = (struct hv_vss_dev_sc*)dev->si_drv1;
673
674 mtx_lock(&dev_sc->sc->pending_mutex);
675 /**
676 * if there is data ready, inform daemon's poll
677 */
678 if (!STAILQ_EMPTY(&dev_sc->to_notify_queue))
679 revent = POLLIN;
680 if (revent == 0)
681 selrecord(td, &dev_sc->hv_vss_selinfo);
682 hv_vss_log_info("%s return 0x%x\n", __func__, revent);
683 mtx_unlock(&dev_sc->sc->pending_mutex);
684 return (revent);
685 }
686
687 static void
hv_vss_timeout(void * arg)688 hv_vss_timeout(void *arg)
689 {
690 hv_vss_req_internal *reqp = arg;
691 hv_vss_req_internal *request __diagused;
692 hv_vss_sc* sc = reqp->sc;
693 uint64_t req_id = reqp->vss_req.opt_msg.msgid;
694 /* This thread is locked */
695 KASSERT(mtx_owned(&sc->pending_mutex), ("mutex lock is not owned!"));
696 request = hv_vss_drain_req_queue_locked(sc, req_id);
697 KASSERT(request != NULL, ("timeout but fail to find request"));
698 hv_vss_notify_host_result_locked(reqp, HV_E_FAIL);
699 }
700
701 /*
702 * This routine is called whenever a message is received from the host
703 */
704 static void
hv_vss_init_req(hv_vss_req_internal * reqp,uint32_t recvlen,uint64_t requestid,uint8_t * vss_buf,hv_vss_sc * sc)705 hv_vss_init_req(hv_vss_req_internal *reqp,
706 uint32_t recvlen, uint64_t requestid, uint8_t *vss_buf, hv_vss_sc *sc)
707 {
708 struct timespec vm_ts;
709 struct hv_vss_msg* msg = (struct hv_vss_msg *)vss_buf;
710
711 memset(reqp, 0, __offsetof(hv_vss_req_internal, callout));
712 reqp->host_msg_len = recvlen;
713 reqp->host_msg_id = requestid;
714 reqp->rcv_buf = vss_buf;
715 reqp->sc = sc;
716 memcpy(&reqp->vss_req.msg,
717 (struct hv_vss_msg *)vss_buf, sizeof(struct hv_vss_msg));
718 /* set the opt for users */
719 switch (msg->hdr.vss_hdr.operation) {
720 case VSS_OP_FREEZE:
721 reqp->vss_req.opt_msg.opt = HV_VSS_FREEZE;
722 break;
723 case VSS_OP_THAW:
724 reqp->vss_req.opt_msg.opt = HV_VSS_THAW;
725 break;
726 case VSS_OP_HOT_BACKUP:
727 reqp->vss_req.opt_msg.opt = HV_VSS_CHECK;
728 break;
729 }
730 /* Use a timestamp as msg request ID */
731 nanotime(&vm_ts);
732 reqp->vss_req.opt_msg.msgid = (vm_ts.tv_sec * NANOSEC) + vm_ts.tv_nsec;
733 }
734
735 static hv_vss_req_internal*
hv_vss_get_new_req_locked(hv_vss_sc * sc)736 hv_vss_get_new_req_locked(hv_vss_sc *sc)
737 {
738 hv_vss_req_internal *reqp;
739 if (!STAILQ_EMPTY(&sc->daemon_sc.to_notify_queue) ||
740 !STAILQ_EMPTY(&sc->daemon_sc.to_ack_queue) ||
741 !STAILQ_EMPTY(&sc->app_sc.to_notify_queue) ||
742 !STAILQ_EMPTY(&sc->app_sc.to_ack_queue)) {
743 /*
744 * There is request coming from host before
745 * finishing previous requests
746 */
747 hv_vss_log_info("%s: Warning: there is new request "
748 "coming before finishing previous requests\n", __func__);
749 return (NULL);
750 }
751 if (LIST_EMPTY(&sc->req_free_list)) {
752 /* TODO Error: no buffer */
753 hv_vss_log_info("Error: No buffer\n");
754 return (NULL);
755 }
756 reqp = LIST_FIRST(&sc->req_free_list);
757 LIST_REMOVE(reqp, link);
758 return (reqp);
759 }
760
761 static void
hv_vss_start_notify(hv_vss_req_internal * reqp,uint32_t opt)762 hv_vss_start_notify(hv_vss_req_internal *reqp, uint32_t opt)
763 {
764 hv_vss_sc *sc = reqp->sc;
765 /*
766 * Freeze/Check notification sequence: kernel -> app -> daemon(fs)
767 * Thaw notification sequence: kernel -> daemon(fs) -> app
768 *
769 * We should wake up the daemon, in case it's doing poll().
770 * The response should be received after 5s, otherwise, trigger timeout.
771 */
772 switch (opt) {
773 case VSS_OP_FREEZE:
774 case VSS_OP_HOT_BACKUP:
775 if (sc->app_register_done)
776 hv_vss_notify(&sc->app_sc, reqp);
777 else
778 hv_vss_notify(&sc->daemon_sc, reqp);
779 callout_reset(&reqp->callout, TIMEOUT_LIMIT * hz,
780 hv_vss_timeout, reqp);
781 break;
782 case VSS_OP_THAW:
783 hv_vss_notify(&sc->daemon_sc, reqp);
784 callout_reset(&reqp->callout, TIMEOUT_LIMIT * hz,
785 hv_vss_timeout, reqp);
786 break;
787 }
788 }
789
790 /*
791 * Function to read the vss request buffer from host
792 * and interact with daemon
793 */
794 static void
hv_vss_process_request(void * context,int pending __unused)795 hv_vss_process_request(void *context, int pending __unused)
796 {
797 uint8_t *vss_buf;
798 struct vmbus_channel *channel;
799 uint32_t recvlen = 0;
800 uint64_t requestid;
801 struct vmbus_icmsg_hdr *icmsghdrp;
802 int ret = 0;
803 hv_vss_sc *sc;
804 hv_vss_req_internal *reqp;
805
806 hv_vss_log_info("%s: entering hv_vss_process_request\n", __func__);
807
808 sc = (hv_vss_sc*)context;
809 vss_buf = sc->util_sc.ic_buf;
810 channel = vmbus_get_channel(sc->dev);
811
812 recvlen = sc->util_sc.ic_buflen;
813 ret = vmbus_chan_recv(channel, vss_buf, &recvlen, &requestid);
814 KASSERT(ret != ENOBUFS, ("hvvss recvbuf is not large enough"));
815 /* XXX check recvlen to make sure that it contains enough data */
816
817 while ((ret == 0) && (recvlen > 0)) {
818 icmsghdrp = (struct vmbus_icmsg_hdr *)vss_buf;
819
820 if (icmsghdrp->ic_type == HV_ICMSGTYPE_NEGOTIATE) {
821 ret = vmbus_ic_negomsg(&sc->util_sc, vss_buf,
822 &recvlen, VSS_FWVER, VSS_MSGVER);
823 hv_vss_respond_host(vss_buf, vmbus_get_channel(sc->dev),
824 recvlen, requestid, ret);
825 hv_vss_log_info("%s: version negotiated\n", __func__);
826 } else if (!hv_vss_is_daemon_killed_after_launch(sc)) {
827 struct hv_vss_msg* msg = (struct hv_vss_msg *)vss_buf;
828 switch(msg->hdr.vss_hdr.operation) {
829 case VSS_OP_FREEZE:
830 case VSS_OP_THAW:
831 case VSS_OP_HOT_BACKUP:
832 mtx_lock(&sc->pending_mutex);
833 reqp = hv_vss_get_new_req_locked(sc);
834 mtx_unlock(&sc->pending_mutex);
835 if (reqp == NULL) {
836 /* ignore this request from host */
837 break;
838 }
839 hv_vss_init_req(reqp, recvlen, requestid, vss_buf, sc);
840 hv_vss_log_info("%s: receive %s (%ju) from host\n",
841 __func__,
842 vss_opt_name[reqp->vss_req.opt_msg.opt],
843 (uintmax_t)reqp->vss_req.opt_msg.msgid);
844 hv_vss_start_notify(reqp, msg->hdr.vss_hdr.operation);
845 break;
846 case VSS_OP_GET_DM_INFO:
847 hv_vss_log_info("%s: receive GET_DM_INFO from host\n",
848 __func__);
849 msg->body.dm_info.flags = 0;
850 hv_vss_respond_host(vss_buf, vmbus_get_channel(sc->dev),
851 recvlen, requestid, HV_S_OK);
852 break;
853 default:
854 device_printf(sc->dev, "Unknown opt from host: %d\n",
855 msg->hdr.vss_hdr.operation);
856 break;
857 }
858 } else {
859 /* daemon was killed for some reason after it was launched */
860 struct hv_vss_msg* msg = (struct hv_vss_msg *)vss_buf;
861 switch(msg->hdr.vss_hdr.operation) {
862 case VSS_OP_FREEZE:
863 hv_vss_log_info("%s: response fail for FREEZE\n",
864 __func__);
865 break;
866 case VSS_OP_THAW:
867 hv_vss_log_info("%s: response fail for THAW\n",
868 __func__);
869 break;
870 case VSS_OP_HOT_BACKUP:
871 hv_vss_log_info("%s: response fail for HOT_BACKUP\n",
872 __func__);
873 msg->body.vss_cf.flags = VSS_HBU_NO_AUTO_RECOVERY;
874 break;
875 case VSS_OP_GET_DM_INFO:
876 hv_vss_log_info("%s: response fail for GET_DM_INFO\n",
877 __func__);
878 msg->body.dm_info.flags = 0;
879 break;
880 default:
881 device_printf(sc->dev, "Unknown opt from host: %d\n",
882 msg->hdr.vss_hdr.operation);
883 break;
884 }
885 hv_vss_respond_host(vss_buf, vmbus_get_channel(sc->dev),
886 recvlen, requestid, HV_E_FAIL);
887 }
888 /*
889 * Try reading next buffer
890 */
891 recvlen = sc->util_sc.ic_buflen;
892 ret = vmbus_chan_recv(channel, vss_buf, &recvlen, &requestid);
893 KASSERT(ret != ENOBUFS, ("hvvss recvbuf is not large enough"));
894 /* XXX check recvlen to make sure that it contains enough data */
895
896 hv_vss_log_info("%s: read: context %p, ret =%d, recvlen=%d\n",
897 __func__, context, ret, recvlen);
898 }
899 }
900
901 static int
hv_vss_probe(device_t dev)902 hv_vss_probe(device_t dev)
903 {
904 return (vmbus_ic_probe(dev, vmbus_vss_descs));
905 }
906
907 static int
hv_vss_init_send_receive_queue(device_t dev)908 hv_vss_init_send_receive_queue(device_t dev)
909 {
910 hv_vss_sc *sc = (hv_vss_sc*)device_get_softc(dev);
911 int i;
912 const int max_list = 4; /* It is big enough for the list */
913 struct hv_vss_req_internal* reqp;
914
915 LIST_INIT(&sc->req_free_list);
916 STAILQ_INIT(&sc->daemon_sc.to_notify_queue);
917 STAILQ_INIT(&sc->daemon_sc.to_ack_queue);
918 STAILQ_INIT(&sc->app_sc.to_notify_queue);
919 STAILQ_INIT(&sc->app_sc.to_ack_queue);
920
921 for (i = 0; i < max_list; i++) {
922 reqp = malloc(sizeof(struct hv_vss_req_internal),
923 M_DEVBUF, M_WAITOK|M_ZERO);
924 LIST_INSERT_HEAD(&sc->req_free_list, reqp, link);
925 callout_init_mtx(&reqp->callout, &sc->pending_mutex, 0);
926 }
927 return (0);
928 }
929
930 static int
hv_vss_destroy_send_receive_queue(device_t dev)931 hv_vss_destroy_send_receive_queue(device_t dev)
932 {
933 hv_vss_sc *sc = (hv_vss_sc*)device_get_softc(dev);
934 hv_vss_req_internal* reqp;
935
936 while (!LIST_EMPTY(&sc->req_free_list)) {
937 reqp = LIST_FIRST(&sc->req_free_list);
938 LIST_REMOVE(reqp, link);
939 free(reqp, M_DEVBUF);
940 }
941
942 while (!STAILQ_EMPTY(&sc->daemon_sc.to_notify_queue)) {
943 reqp = STAILQ_FIRST(&sc->daemon_sc.to_notify_queue);
944 STAILQ_REMOVE_HEAD(&sc->daemon_sc.to_notify_queue, slink);
945 free(reqp, M_DEVBUF);
946 }
947
948 while (!STAILQ_EMPTY(&sc->daemon_sc.to_ack_queue)) {
949 reqp = STAILQ_FIRST(&sc->daemon_sc.to_ack_queue);
950 STAILQ_REMOVE_HEAD(&sc->daemon_sc.to_ack_queue, slink);
951 free(reqp, M_DEVBUF);
952 }
953
954 while (!STAILQ_EMPTY(&sc->app_sc.to_notify_queue)) {
955 reqp = STAILQ_FIRST(&sc->app_sc.to_notify_queue);
956 STAILQ_REMOVE_HEAD(&sc->app_sc.to_notify_queue, slink);
957 free(reqp, M_DEVBUF);
958 }
959
960 while (!STAILQ_EMPTY(&sc->app_sc.to_ack_queue)) {
961 reqp = STAILQ_FIRST(&sc->app_sc.to_ack_queue);
962 STAILQ_REMOVE_HEAD(&sc->app_sc.to_ack_queue, slink);
963 free(reqp, M_DEVBUF);
964 }
965 return (0);
966 }
967
968 static int
hv_vss_attach(device_t dev)969 hv_vss_attach(device_t dev)
970 {
971 int error;
972 struct sysctl_oid_list *child;
973 struct sysctl_ctx_list *ctx;
974
975 hv_vss_sc *sc = (hv_vss_sc*)device_get_softc(dev);
976
977 sc->dev = dev;
978 mtx_init(&sc->pending_mutex, "hv_vss pending mutex", NULL, MTX_DEF);
979
980 ctx = device_get_sysctl_ctx(dev);
981 child = SYSCTL_CHILDREN(device_get_sysctl_tree(dev));
982
983 SYSCTL_ADD_INT(ctx, child, OID_AUTO, "hv_vss_log",
984 CTLFLAG_RWTUN, &hv_vss_log, 0, "Hyperv VSS service log level");
985
986 TASK_INIT(&sc->task, 0, hv_vss_process_request, sc);
987 hv_vss_init_send_receive_queue(dev);
988 /* create character device for file system freeze/thaw */
989 error = make_dev_p(MAKEDEV_CHECKNAME | MAKEDEV_WAITOK,
990 &sc->hv_vss_dev,
991 &hv_vss_cdevsw,
992 0,
993 UID_ROOT,
994 GID_WHEEL,
995 0640,
996 FS_VSS_DEV_NAME);
997
998 if (error != 0) {
999 hv_vss_log_info("Fail to create '%s': %d\n", FS_VSS_DEV_NAME, error);
1000 return (error);
1001 }
1002 sc->hv_vss_dev->si_drv1 = &sc->daemon_sc;
1003 sc->daemon_sc.sc = sc;
1004 /* create character device for application freeze/thaw */
1005 error = make_dev_p(MAKEDEV_CHECKNAME | MAKEDEV_WAITOK,
1006 &sc->hv_appvss_dev,
1007 &hv_appvss_cdevsw,
1008 0,
1009 UID_ROOT,
1010 GID_WHEEL,
1011 0640,
1012 APP_VSS_DEV_NAME);
1013
1014 if (error != 0) {
1015 hv_vss_log_info("Fail to create '%s': %d\n", APP_VSS_DEV_NAME, error);
1016 return (error);
1017 }
1018 sc->hv_appvss_dev->si_drv1 = &sc->app_sc;
1019 sc->app_sc.sc = sc;
1020
1021 return (vmbus_ic_attach(dev, hv_vss_callback));
1022 }
1023
1024 static int
hv_vss_detach(device_t dev)1025 hv_vss_detach(device_t dev)
1026 {
1027 hv_vss_sc *sc = (hv_vss_sc*)device_get_softc(dev);
1028 mtx_destroy(&sc->pending_mutex);
1029 if (sc->daemon_sc.proc_task != NULL) {
1030 PROC_LOCK(sc->daemon_sc.proc_task);
1031 kern_psignal(sc->daemon_sc.proc_task, SIGKILL);
1032 PROC_UNLOCK(sc->daemon_sc.proc_task);
1033 }
1034 if (sc->app_sc.proc_task != NULL) {
1035 PROC_LOCK(sc->app_sc.proc_task);
1036 kern_psignal(sc->app_sc.proc_task, SIGKILL);
1037 PROC_UNLOCK(sc->app_sc.proc_task);
1038 }
1039 hv_vss_destroy_send_receive_queue(dev);
1040 destroy_dev(sc->hv_vss_dev);
1041 destroy_dev(sc->hv_appvss_dev);
1042 return (vmbus_ic_detach(dev));
1043 }
1044
1045 static device_method_t vss_methods[] = {
1046 /* Device interface */
1047 DEVMETHOD(device_probe, hv_vss_probe),
1048 DEVMETHOD(device_attach, hv_vss_attach),
1049 DEVMETHOD(device_detach, hv_vss_detach),
1050 { 0, 0 }
1051 };
1052
1053 static driver_t vss_driver = { "hvvss", vss_methods, sizeof(hv_vss_sc)};
1054
1055 DRIVER_MODULE(hv_vss, vmbus, vss_driver, NULL, NULL);
1056 MODULE_VERSION(hv_vss, 1);
1057 MODULE_DEPEND(hv_vss, vmbus, 1, 1, 1);
1058