linux/drivers/hv/hv_snapshot.c
<<
>>
Prefs
   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
  27#include "hyperv_vmbus.h"
  28#include "hv_utils_transport.h"
  29
  30#define VSS_MAJOR  5
  31#define VSS_MINOR  0
  32#define VSS_VERSION    (VSS_MAJOR << 16 | VSS_MINOR)
  33
  34#define VSS_VER_COUNT 1
  35static const int vss_versions[] = {
  36        VSS_VERSION
  37};
  38
  39#define FW_VER_COUNT 1
  40static const int fw_versions[] = {
  41        UTIL_FW_VERSION
  42};
  43
  44/*
  45 * Timeout values are based on expecations from host
  46 */
  47#define VSS_FREEZE_TIMEOUT (15 * 60)
  48
  49/*
  50 * Global state maintained for transaction that is being processed. For a class
  51 * of integration services, including the "VSS service", the specified protocol
  52 * is a "request/response" protocol which means that there can only be single
  53 * outstanding transaction from the host at any given point in time. We use
  54 * this to simplify memory management in this driver - we cache and process
  55 * only one message at a time.
  56 *
  57 * While the request/response protocol is guaranteed by the host, we further
  58 * ensure this by serializing packet processing in this driver - we do not
  59 * read additional packets from the VMBUs until the current packet is fully
  60 * handled.
  61 */
  62
  63static struct {
  64        int state;   /* hvutil_device_state */
  65        int recv_len; /* number of bytes received. */
  66        struct vmbus_channel *recv_channel; /* chn we got the request */
  67        u64 recv_req_id; /* request ID. */
  68        struct hv_vss_msg  *msg; /* current message */
  69} vss_transaction;
  70
  71
  72static void vss_respond_to_host(int error);
  73
  74/*
  75 * This state maintains the version number registered by the daemon.
  76 */
  77static int dm_reg_value;
  78
  79static const char vss_devname[] = "vmbus/hv_vss";
  80static __u8 *recv_buffer;
  81static struct hvutil_transport *hvt;
  82
  83static void vss_timeout_func(struct work_struct *dummy);
  84static void vss_handle_request(struct work_struct *dummy);
  85
  86static DECLARE_DELAYED_WORK(vss_timeout_work, vss_timeout_func);
  87static DECLARE_WORK(vss_handle_request_work, vss_handle_request);
  88
  89static void vss_poll_wrapper(void *channel)
  90{
  91        /* Transaction is finished, reset the state here to avoid races. */
  92        vss_transaction.state = HVUTIL_READY;
  93        hv_vss_onchannelcallback(channel);
  94}
  95
  96/*
  97 * Callback when data is received from user mode.
  98 */
  99
 100static void vss_timeout_func(struct work_struct *dummy)
 101{
 102        /*
 103         * Timeout waiting for userspace component to reply happened.
 104         */
 105        pr_warn("VSS: timeout waiting for daemon to reply\n");
 106        vss_respond_to_host(HV_E_FAIL);
 107
 108        hv_poll_channel(vss_transaction.recv_channel, vss_poll_wrapper);
 109}
 110
 111static void vss_register_done(void)
 112{
 113        hv_poll_channel(vss_transaction.recv_channel, vss_poll_wrapper);
 114        pr_debug("VSS: userspace daemon registered\n");
 115}
 116
 117static int vss_handle_handshake(struct hv_vss_msg *vss_msg)
 118{
 119        u32 our_ver = VSS_OP_REGISTER1;
 120
 121        switch (vss_msg->vss_hdr.operation) {
 122        case VSS_OP_REGISTER:
 123                /* Daemon doesn't expect us to reply */
 124                dm_reg_value = VSS_OP_REGISTER;
 125                break;
 126        case VSS_OP_REGISTER1:
 127                /* Daemon expects us to reply with our own version */
 128                if (hvutil_transport_send(hvt, &our_ver, sizeof(our_ver),
 129                                          vss_register_done))
 130                        return -EFAULT;
 131                dm_reg_value = VSS_OP_REGISTER1;
 132                break;
 133        default:
 134                return -EINVAL;
 135        }
 136        pr_info("VSS: userspace daemon ver. %d connected\n", dm_reg_value);
 137        return 0;
 138}
 139
 140static int vss_on_msg(void *msg, int len)
 141{
 142        struct hv_vss_msg *vss_msg = (struct hv_vss_msg *)msg;
 143
 144        if (len != sizeof(*vss_msg)) {
 145                pr_debug("VSS: Message size does not match length\n");
 146                return -EINVAL;
 147        }
 148
 149        if (vss_msg->vss_hdr.operation == VSS_OP_REGISTER ||
 150            vss_msg->vss_hdr.operation == VSS_OP_REGISTER1) {
 151                /*
 152                 * Don't process registration messages if we're in the middle
 153                 * of a transaction processing.
 154                 */
 155                if (vss_transaction.state > HVUTIL_READY) {
 156                        pr_debug("VSS: Got unexpected registration request\n");
 157                        return -EINVAL;
 158                }
 159
 160                return vss_handle_handshake(vss_msg);
 161        } else if (vss_transaction.state == HVUTIL_USERSPACE_REQ) {
 162                vss_transaction.state = HVUTIL_USERSPACE_RECV;
 163
 164                if (vss_msg->vss_hdr.operation == VSS_OP_HOT_BACKUP)
 165                        vss_transaction.msg->vss_cf.flags =
 166                                VSS_HBU_NO_AUTO_RECOVERY;
 167
 168                if (cancel_delayed_work_sync(&vss_timeout_work)) {
 169                        vss_respond_to_host(vss_msg->error);
 170                        /* Transaction is finished, reset the state. */
 171                        hv_poll_channel(vss_transaction.recv_channel,
 172                                        vss_poll_wrapper);
 173                }
 174        } else {
 175                /* This is a spurious call! */
 176                pr_debug("VSS: Transaction not active\n");
 177                return -EINVAL;
 178        }
 179        return 0;
 180}
 181
 182static void vss_send_op(void)
 183{
 184        int op = vss_transaction.msg->vss_hdr.operation;
 185        int rc;
 186        struct hv_vss_msg *vss_msg;
 187
 188        /* The transaction state is wrong. */
 189        if (vss_transaction.state != HVUTIL_HOSTMSG_RECEIVED) {
 190                pr_debug("VSS: Unexpected attempt to send to daemon\n");
 191                return;
 192        }
 193
 194        vss_msg = kzalloc(sizeof(*vss_msg), GFP_KERNEL);
 195        if (!vss_msg)
 196                return;
 197
 198        vss_msg->vss_hdr.operation = op;
 199
 200        vss_transaction.state = HVUTIL_USERSPACE_REQ;
 201
 202        schedule_delayed_work(&vss_timeout_work, op == VSS_OP_FREEZE ?
 203                        VSS_FREEZE_TIMEOUT * HZ : HV_UTIL_TIMEOUT * HZ);
 204
 205        rc = hvutil_transport_send(hvt, vss_msg, sizeof(*vss_msg), NULL);
 206        if (rc) {
 207                pr_warn("VSS: failed to communicate to the daemon: %d\n", rc);
 208                if (cancel_delayed_work_sync(&vss_timeout_work)) {
 209                        vss_respond_to_host(HV_E_FAIL);
 210                        vss_transaction.state = HVUTIL_READY;
 211                }
 212        }
 213
 214        kfree(vss_msg);
 215}
 216
 217static void vss_handle_request(struct work_struct *dummy)
 218{
 219        switch (vss_transaction.msg->vss_hdr.operation) {
 220        /*
 221         * Initiate a "freeze/thaw" operation in the guest.
 222         * We respond to the host once the operation is complete.
 223         *
 224         * We send the message to the user space daemon and the operation is
 225         * performed in the daemon.
 226         */
 227        case VSS_OP_THAW:
 228        case VSS_OP_FREEZE:
 229        case VSS_OP_HOT_BACKUP:
 230                if (vss_transaction.state < HVUTIL_READY) {
 231                        /* Userspace is not registered yet */
 232                        pr_debug("VSS: Not ready for request.\n");
 233                        vss_respond_to_host(HV_E_FAIL);
 234                        return;
 235                }
 236
 237                pr_debug("VSS: Received request for op code: %d\n",
 238                        vss_transaction.msg->vss_hdr.operation);
 239                vss_transaction.state = HVUTIL_HOSTMSG_RECEIVED;
 240                vss_send_op();
 241                return;
 242        case VSS_OP_GET_DM_INFO:
 243                vss_transaction.msg->dm_info.flags = 0;
 244                break;
 245        default:
 246                break;
 247        }
 248
 249        vss_respond_to_host(0);
 250        hv_poll_channel(vss_transaction.recv_channel, vss_poll_wrapper);
 251}
 252
 253/*
 254 * Send a response back to the host.
 255 */
 256
 257static void
 258vss_respond_to_host(int error)
 259{
 260        struct icmsg_hdr *icmsghdrp;
 261        u32     buf_len;
 262        struct vmbus_channel *channel;
 263        u64     req_id;
 264
 265        /*
 266         * Copy the global state for completing the transaction. Note that
 267         * only one transaction can be active at a time.
 268         */
 269
 270        buf_len = vss_transaction.recv_len;
 271        channel = vss_transaction.recv_channel;
 272        req_id = vss_transaction.recv_req_id;
 273
 274        icmsghdrp = (struct icmsg_hdr *)
 275                        &recv_buffer[sizeof(struct vmbuspipe_hdr)];
 276
 277        if (channel->onchannel_callback == NULL)
 278                /*
 279                 * We have raced with util driver being unloaded;
 280                 * silently return.
 281                 */
 282                return;
 283
 284        icmsghdrp->status = error;
 285
 286        icmsghdrp->icflags = ICMSGHDRFLAG_TRANSACTION | ICMSGHDRFLAG_RESPONSE;
 287
 288        vmbus_sendpacket(channel, recv_buffer, buf_len, req_id,
 289                                VM_PKT_DATA_INBAND, 0);
 290
 291}
 292
 293/*
 294 * This callback is invoked when we get a VSS message from the host.
 295 * The host ensures that only one VSS transaction can be active at a time.
 296 */
 297
 298void hv_vss_onchannelcallback(void *context)
 299{
 300        struct vmbus_channel *channel = context;
 301        u32 recvlen;
 302        u64 requestid;
 303        struct hv_vss_msg *vss_msg;
 304        int vss_srv_version;
 305
 306        struct icmsg_hdr *icmsghdrp;
 307
 308        if (vss_transaction.state > HVUTIL_READY)
 309                return;
 310
 311        vmbus_recvpacket(channel, recv_buffer, PAGE_SIZE * 2, &recvlen,
 312                         &requestid);
 313
 314        if (recvlen > 0) {
 315                icmsghdrp = (struct icmsg_hdr *)&recv_buffer[
 316                        sizeof(struct vmbuspipe_hdr)];
 317
 318                if (icmsghdrp->icmsgtype == ICMSGTYPE_NEGOTIATE) {
 319                        if (vmbus_prep_negotiate_resp(icmsghdrp,
 320                                 recv_buffer, fw_versions, FW_VER_COUNT,
 321                                 vss_versions, VSS_VER_COUNT,
 322                                 NULL, &vss_srv_version)) {
 323
 324                                pr_info("VSS IC version %d.%d\n",
 325                                        vss_srv_version >> 16,
 326                                        vss_srv_version & 0xFFFF);
 327                        }
 328                } else {
 329                        vss_msg = (struct hv_vss_msg *)&recv_buffer[
 330                                sizeof(struct vmbuspipe_hdr) +
 331                                sizeof(struct icmsg_hdr)];
 332
 333                        /*
 334                         * Stash away this global state for completing the
 335                         * transaction; note transactions are serialized.
 336                         */
 337
 338                        vss_transaction.recv_len = recvlen;
 339                        vss_transaction.recv_req_id = requestid;
 340                        vss_transaction.msg = (struct hv_vss_msg *)vss_msg;
 341
 342                        schedule_work(&vss_handle_request_work);
 343                        return;
 344                }
 345
 346                icmsghdrp->icflags = ICMSGHDRFLAG_TRANSACTION
 347                        | ICMSGHDRFLAG_RESPONSE;
 348
 349                vmbus_sendpacket(channel, recv_buffer,
 350                                       recvlen, requestid,
 351                                       VM_PKT_DATA_INBAND, 0);
 352        }
 353
 354}
 355
 356static void vss_on_reset(void)
 357{
 358        if (cancel_delayed_work_sync(&vss_timeout_work))
 359                vss_respond_to_host(HV_E_FAIL);
 360        vss_transaction.state = HVUTIL_DEVICE_INIT;
 361}
 362
 363int
 364hv_vss_init(struct hv_util_service *srv)
 365{
 366        if (vmbus_proto_version < VERSION_WIN8_1) {
 367                pr_warn("Integration service 'Backup (volume snapshot)'"
 368                        " not supported on this host version.\n");
 369                return -ENOTSUPP;
 370        }
 371        recv_buffer = srv->recv_buffer;
 372        vss_transaction.recv_channel = srv->channel;
 373
 374        /*
 375         * When this driver loads, the user level daemon that
 376         * processes the host requests may not yet be running.
 377         * Defer processing channel callbacks until the daemon
 378         * has registered.
 379         */
 380        vss_transaction.state = HVUTIL_DEVICE_INIT;
 381
 382        hvt = hvutil_transport_init(vss_devname, CN_VSS_IDX, CN_VSS_VAL,
 383                                    vss_on_msg, vss_on_reset);
 384        if (!hvt) {
 385                pr_warn("VSS: Failed to initialize transport\n");
 386                return -EFAULT;
 387        }
 388
 389        return 0;
 390}
 391
 392void hv_vss_deinit(void)
 393{
 394        vss_transaction.state = HVUTIL_DEVICE_DYING;
 395        cancel_delayed_work_sync(&vss_timeout_work);
 396        cancel_work_sync(&vss_handle_request_work);
 397        hvutil_transport_destroy(hvt);
 398}
 399