/drivers/hv/hv_snapshot.c

https://bitbucket.org/bdas/linux · C · 281 lines · 149 code · 57 blank · 75 comment · 15 complexity · 5cd275e2cb9ccfd5a8a18f919833f4f5 MD5 · raw file

  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. #include <linux/net.h>
  21. #include <linux/nls.h>
  22. #include <linux/connector.h>
  23. #include <linux/workqueue.h>
  24. #include <linux/hyperv.h>
  25. #define VSS_MAJOR 5
  26. #define VSS_MINOR 0
  27. #define VSS_VERSION (VSS_MAJOR << 16 | VSS_MINOR)
  28. /*
  29. * Global state maintained for transaction that is being processed.
  30. * Note that only one transaction can be active at any point in time.
  31. *
  32. * This state is set when we receive a request from the host; we
  33. * cleanup this state when the transaction is completed - when we respond
  34. * to the host with the key value.
  35. */
  36. static struct {
  37. bool active; /* transaction status - active or not */
  38. int recv_len; /* number of bytes received. */
  39. struct vmbus_channel *recv_channel; /* chn we got the request */
  40. u64 recv_req_id; /* request ID. */
  41. struct hv_vss_msg *msg; /* current message */
  42. } vss_transaction;
  43. static void vss_respond_to_host(int error);
  44. static struct cb_id vss_id = { CN_VSS_IDX, CN_VSS_VAL };
  45. static const char vss_name[] = "vss_kernel_module";
  46. static __u8 *recv_buffer;
  47. static void vss_send_op(struct work_struct *dummy);
  48. static DECLARE_WORK(vss_send_op_work, vss_send_op);
  49. /*
  50. * Callback when data is received from user mode.
  51. */
  52. static void
  53. vss_cn_callback(struct cn_msg *msg, struct netlink_skb_parms *nsp)
  54. {
  55. struct hv_vss_msg *vss_msg;
  56. vss_msg = (struct hv_vss_msg *)msg->data;
  57. if (vss_msg->vss_hdr.operation == VSS_OP_REGISTER) {
  58. pr_info("VSS daemon registered\n");
  59. vss_transaction.active = false;
  60. if (vss_transaction.recv_channel != NULL)
  61. hv_vss_onchannelcallback(vss_transaction.recv_channel);
  62. return;
  63. }
  64. vss_respond_to_host(vss_msg->error);
  65. }
  66. static void vss_send_op(struct work_struct *dummy)
  67. {
  68. int op = vss_transaction.msg->vss_hdr.operation;
  69. struct cn_msg *msg;
  70. struct hv_vss_msg *vss_msg;
  71. msg = kzalloc(sizeof(*msg) + sizeof(*vss_msg), GFP_ATOMIC);
  72. if (!msg)
  73. return;
  74. vss_msg = (struct hv_vss_msg *)msg->data;
  75. msg->id.idx = CN_VSS_IDX;
  76. msg->id.val = CN_VSS_VAL;
  77. vss_msg->vss_hdr.operation = op;
  78. msg->len = sizeof(struct hv_vss_msg);
  79. cn_netlink_send(msg, 0, 0, GFP_ATOMIC);
  80. kfree(msg);
  81. return;
  82. }
  83. /*
  84. * Send a response back to the host.
  85. */
  86. static void
  87. vss_respond_to_host(int error)
  88. {
  89. struct icmsg_hdr *icmsghdrp;
  90. u32 buf_len;
  91. struct vmbus_channel *channel;
  92. u64 req_id;
  93. /*
  94. * If a transaction is not active; log and return.
  95. */
  96. if (!vss_transaction.active) {
  97. /*
  98. * This is a spurious call!
  99. */
  100. pr_warn("VSS: Transaction not active\n");
  101. return;
  102. }
  103. /*
  104. * Copy the global state for completing the transaction. Note that
  105. * only one transaction can be active at a time.
  106. */
  107. buf_len = vss_transaction.recv_len;
  108. channel = vss_transaction.recv_channel;
  109. req_id = vss_transaction.recv_req_id;
  110. vss_transaction.active = false;
  111. icmsghdrp = (struct icmsg_hdr *)
  112. &recv_buffer[sizeof(struct vmbuspipe_hdr)];
  113. if (channel->onchannel_callback == NULL)
  114. /*
  115. * We have raced with util driver being unloaded;
  116. * silently return.
  117. */
  118. return;
  119. icmsghdrp->status = error;
  120. icmsghdrp->icflags = ICMSGHDRFLAG_TRANSACTION | ICMSGHDRFLAG_RESPONSE;
  121. vmbus_sendpacket(channel, recv_buffer, buf_len, req_id,
  122. VM_PKT_DATA_INBAND, 0);
  123. }
  124. /*
  125. * This callback is invoked when we get a VSS message from the host.
  126. * The host ensures that only one VSS transaction can be active at a time.
  127. */
  128. void hv_vss_onchannelcallback(void *context)
  129. {
  130. struct vmbus_channel *channel = context;
  131. u32 recvlen;
  132. u64 requestid;
  133. struct hv_vss_msg *vss_msg;
  134. struct icmsg_hdr *icmsghdrp;
  135. struct icmsg_negotiate *negop = NULL;
  136. if (vss_transaction.active) {
  137. /*
  138. * We will defer processing this callback once
  139. * the current transaction is complete.
  140. */
  141. vss_transaction.recv_channel = channel;
  142. return;
  143. }
  144. vmbus_recvpacket(channel, recv_buffer, PAGE_SIZE * 2, &recvlen,
  145. &requestid);
  146. if (recvlen > 0) {
  147. icmsghdrp = (struct icmsg_hdr *)&recv_buffer[
  148. sizeof(struct vmbuspipe_hdr)];
  149. if (icmsghdrp->icmsgtype == ICMSGTYPE_NEGOTIATE) {
  150. vmbus_prep_negotiate_resp(icmsghdrp, negop,
  151. recv_buffer, UTIL_FW_VERSION,
  152. VSS_VERSION);
  153. } else {
  154. vss_msg = (struct hv_vss_msg *)&recv_buffer[
  155. sizeof(struct vmbuspipe_hdr) +
  156. sizeof(struct icmsg_hdr)];
  157. /*
  158. * Stash away this global state for completing the
  159. * transaction; note transactions are serialized.
  160. */
  161. vss_transaction.recv_len = recvlen;
  162. vss_transaction.recv_channel = channel;
  163. vss_transaction.recv_req_id = requestid;
  164. vss_transaction.active = true;
  165. vss_transaction.msg = (struct hv_vss_msg *)vss_msg;
  166. switch (vss_msg->vss_hdr.operation) {
  167. /*
  168. * Initiate a "freeze/thaw"
  169. * operation in the guest.
  170. * We respond to the host once
  171. * the operation is complete.
  172. *
  173. * We send the message to the
  174. * user space daemon and the
  175. * operation is performed in
  176. * the daemon.
  177. */
  178. case VSS_OP_FREEZE:
  179. case VSS_OP_THAW:
  180. schedule_work(&vss_send_op_work);
  181. return;
  182. case VSS_OP_HOT_BACKUP:
  183. vss_msg->vss_cf.flags =
  184. VSS_HBU_NO_AUTO_RECOVERY;
  185. vss_respond_to_host(0);
  186. return;
  187. case VSS_OP_GET_DM_INFO:
  188. vss_msg->dm_info.flags = 0;
  189. vss_respond_to_host(0);
  190. return;
  191. default:
  192. vss_respond_to_host(0);
  193. return;
  194. }
  195. }
  196. icmsghdrp->icflags = ICMSGHDRFLAG_TRANSACTION
  197. | ICMSGHDRFLAG_RESPONSE;
  198. vmbus_sendpacket(channel, recv_buffer,
  199. recvlen, requestid,
  200. VM_PKT_DATA_INBAND, 0);
  201. }
  202. }
  203. int
  204. hv_vss_init(struct hv_util_service *srv)
  205. {
  206. int err;
  207. err = cn_add_callback(&vss_id, vss_name, vss_cn_callback);
  208. if (err)
  209. return err;
  210. recv_buffer = srv->recv_buffer;
  211. /*
  212. * When this driver loads, the user level daemon that
  213. * processes the host requests may not yet be running.
  214. * Defer processing channel callbacks until the daemon
  215. * has registered.
  216. */
  217. vss_transaction.active = true;
  218. return 0;
  219. }
  220. void hv_vss_deinit(void)
  221. {
  222. cn_del_callback(&vss_id);
  223. cancel_work_sync(&vss_send_op_work);
  224. }