linux/drivers/hv/hv_fcopy.c
<<
>>
Prefs
   1// SPDX-License-Identifier: GPL-2.0-only
   2/*
   3 * An implementation of file copy service.
   4 *
   5 * Copyright (C) 2014, Microsoft, Inc.
   6 *
   7 * Author : K. Y. Srinivasan <ksrinivasan@novell.com>
   8 */
   9
  10#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
  11
  12#include <linux/nls.h>
  13#include <linux/workqueue.h>
  14#include <linux/hyperv.h>
  15#include <linux/sched.h>
  16#include <asm/hyperv-tlfs.h>
  17
  18#include "hyperv_vmbus.h"
  19#include "hv_utils_transport.h"
  20
  21#define WIN8_SRV_MAJOR          1
  22#define WIN8_SRV_MINOR          1
  23#define WIN8_SRV_VERSION        (WIN8_SRV_MAJOR << 16 | WIN8_SRV_MINOR)
  24
  25#define FCOPY_VER_COUNT 1
  26static const int fcopy_versions[] = {
  27        WIN8_SRV_VERSION
  28};
  29
  30#define FW_VER_COUNT 1
  31static const int fw_versions[] = {
  32        UTIL_FW_VERSION
  33};
  34
  35/*
  36 * Global state maintained for transaction that is being processed.
  37 * For a class of integration services, including the "file copy service",
  38 * the specified protocol is a "request/response" protocol which means that
  39 * there can only be single outstanding transaction from the host at any
  40 * given point in time. We use this to simplify memory management in this
  41 * driver - we cache and process only one message at a time.
  42 *
  43 * While the request/response protocol is guaranteed by the host, we further
  44 * ensure this by serializing packet processing in this driver - we do not
  45 * read additional packets from the VMBUs until the current packet is fully
  46 * handled.
  47 */
  48
  49static struct {
  50        int state;   /* hvutil_device_state */
  51        int recv_len; /* number of bytes received. */
  52        struct hv_fcopy_hdr  *fcopy_msg; /* current message */
  53        struct vmbus_channel *recv_channel; /* chn we got the request */
  54        u64 recv_req_id; /* request ID. */
  55} fcopy_transaction;
  56
  57static void fcopy_respond_to_host(int error);
  58static void fcopy_send_data(struct work_struct *dummy);
  59static void fcopy_timeout_func(struct work_struct *dummy);
  60static DECLARE_DELAYED_WORK(fcopy_timeout_work, fcopy_timeout_func);
  61static DECLARE_WORK(fcopy_send_work, fcopy_send_data);
  62static const char fcopy_devname[] = "vmbus/hv_fcopy";
  63static u8 *recv_buffer;
  64static struct hvutil_transport *hvt;
  65/*
  66 * This state maintains the version number registered by the daemon.
  67 */
  68static int dm_reg_value;
  69
  70static void fcopy_poll_wrapper(void *channel)
  71{
  72        /* Transaction is finished, reset the state here to avoid races. */
  73        fcopy_transaction.state = HVUTIL_READY;
  74        tasklet_schedule(&((struct vmbus_channel *)channel)->callback_event);
  75}
  76
  77static void fcopy_timeout_func(struct work_struct *dummy)
  78{
  79        /*
  80         * If the timer fires, the user-mode component has not responded;
  81         * process the pending transaction.
  82         */
  83        fcopy_respond_to_host(HV_E_FAIL);
  84        hv_poll_channel(fcopy_transaction.recv_channel, fcopy_poll_wrapper);
  85}
  86
  87static void fcopy_register_done(void)
  88{
  89        pr_debug("FCP: userspace daemon registered\n");
  90        hv_poll_channel(fcopy_transaction.recv_channel, fcopy_poll_wrapper);
  91}
  92
  93static int fcopy_handle_handshake(u32 version)
  94{
  95        u32 our_ver = FCOPY_CURRENT_VERSION;
  96
  97        switch (version) {
  98        case FCOPY_VERSION_0:
  99                /* Daemon doesn't expect us to reply */
 100                dm_reg_value = version;
 101                break;
 102        case FCOPY_VERSION_1:
 103                /* Daemon expects us to reply with our own version */
 104                if (hvutil_transport_send(hvt, &our_ver, sizeof(our_ver),
 105                    fcopy_register_done))
 106                        return -EFAULT;
 107                dm_reg_value = version;
 108                break;
 109        default:
 110                /*
 111                 * For now we will fail the registration.
 112                 * If and when we have multiple versions to
 113                 * deal with, we will be backward compatible.
 114                 * We will add this code when needed.
 115                 */
 116                return -EINVAL;
 117        }
 118        pr_debug("FCP: userspace daemon ver. %d connected\n", version);
 119        return 0;
 120}
 121
 122static void fcopy_send_data(struct work_struct *dummy)
 123{
 124        struct hv_start_fcopy *smsg_out = NULL;
 125        int operation = fcopy_transaction.fcopy_msg->operation;
 126        struct hv_start_fcopy *smsg_in;
 127        void *out_src;
 128        int rc, out_len;
 129
 130        /*
 131         * The  strings sent from the host are encoded in
 132         * in utf16; convert it to utf8 strings.
 133         * The host assures us that the utf16 strings will not exceed
 134         * the max lengths specified. We will however, reserve room
 135         * for the string terminating character - in the utf16s_utf8s()
 136         * function we limit the size of the buffer where the converted
 137         * string is placed to W_MAX_PATH -1 to guarantee
 138         * that the strings can be properly terminated!
 139         */
 140
 141        switch (operation) {
 142        case START_FILE_COPY:
 143                out_len = sizeof(struct hv_start_fcopy);
 144                smsg_out = kzalloc(sizeof(*smsg_out), GFP_KERNEL);
 145                if (!smsg_out)
 146                        return;
 147
 148                smsg_out->hdr.operation = operation;
 149                smsg_in = (struct hv_start_fcopy *)fcopy_transaction.fcopy_msg;
 150
 151                utf16s_to_utf8s((wchar_t *)smsg_in->file_name, W_MAX_PATH,
 152                                UTF16_LITTLE_ENDIAN,
 153                                (__u8 *)&smsg_out->file_name, W_MAX_PATH - 1);
 154
 155                utf16s_to_utf8s((wchar_t *)smsg_in->path_name, W_MAX_PATH,
 156                                UTF16_LITTLE_ENDIAN,
 157                                (__u8 *)&smsg_out->path_name, W_MAX_PATH - 1);
 158
 159                smsg_out->copy_flags = smsg_in->copy_flags;
 160                smsg_out->file_size = smsg_in->file_size;
 161                out_src = smsg_out;
 162                break;
 163
 164        case WRITE_TO_FILE:
 165                out_src = fcopy_transaction.fcopy_msg;
 166                out_len = sizeof(struct hv_do_fcopy);
 167                break;
 168        default:
 169                out_src = fcopy_transaction.fcopy_msg;
 170                out_len = fcopy_transaction.recv_len;
 171                break;
 172        }
 173
 174        fcopy_transaction.state = HVUTIL_USERSPACE_REQ;
 175        rc = hvutil_transport_send(hvt, out_src, out_len, NULL);
 176        if (rc) {
 177                pr_debug("FCP: failed to communicate to the daemon: %d\n", rc);
 178                if (cancel_delayed_work_sync(&fcopy_timeout_work)) {
 179                        fcopy_respond_to_host(HV_E_FAIL);
 180                        fcopy_transaction.state = HVUTIL_READY;
 181                }
 182        }
 183        kfree(smsg_out);
 184}
 185
 186/*
 187 * Send a response back to the host.
 188 */
 189
 190static void
 191fcopy_respond_to_host(int error)
 192{
 193        struct icmsg_hdr *icmsghdr;
 194        u32 buf_len;
 195        struct vmbus_channel *channel;
 196        u64 req_id;
 197
 198        /*
 199         * Copy the global state for completing the transaction. Note that
 200         * only one transaction can be active at a time. This is guaranteed
 201         * by the file copy protocol implemented by the host. Furthermore,
 202         * the "transaction active" state we maintain ensures that there can
 203         * only be one active transaction at a time.
 204         */
 205
 206        buf_len = fcopy_transaction.recv_len;
 207        channel = fcopy_transaction.recv_channel;
 208        req_id = fcopy_transaction.recv_req_id;
 209
 210        icmsghdr = (struct icmsg_hdr *)
 211                        &recv_buffer[sizeof(struct vmbuspipe_hdr)];
 212
 213        if (channel->onchannel_callback == NULL)
 214                /*
 215                 * We have raced with util driver being unloaded;
 216                 * silently return.
 217                 */
 218                return;
 219
 220        icmsghdr->status = error;
 221        icmsghdr->icflags = ICMSGHDRFLAG_TRANSACTION | ICMSGHDRFLAG_RESPONSE;
 222        vmbus_sendpacket(channel, recv_buffer, buf_len, req_id,
 223                                VM_PKT_DATA_INBAND, 0);
 224}
 225
 226void hv_fcopy_onchannelcallback(void *context)
 227{
 228        struct vmbus_channel *channel = context;
 229        u32 recvlen;
 230        u64 requestid;
 231        struct hv_fcopy_hdr *fcopy_msg;
 232        struct icmsg_hdr *icmsghdr;
 233        int fcopy_srv_version;
 234
 235        if (fcopy_transaction.state > HVUTIL_READY)
 236                return;
 237
 238        vmbus_recvpacket(channel, recv_buffer, HV_HYP_PAGE_SIZE * 2, &recvlen,
 239                         &requestid);
 240        if (recvlen <= 0)
 241                return;
 242
 243        icmsghdr = (struct icmsg_hdr *)&recv_buffer[
 244                        sizeof(struct vmbuspipe_hdr)];
 245        if (icmsghdr->icmsgtype == ICMSGTYPE_NEGOTIATE) {
 246                if (vmbus_prep_negotiate_resp(icmsghdr, recv_buffer,
 247                                fw_versions, FW_VER_COUNT,
 248                                fcopy_versions, FCOPY_VER_COUNT,
 249                                NULL, &fcopy_srv_version)) {
 250
 251                        pr_info("FCopy IC version %d.%d\n",
 252                                fcopy_srv_version >> 16,
 253                                fcopy_srv_version & 0xFFFF);
 254                }
 255        } else {
 256                fcopy_msg = (struct hv_fcopy_hdr *)&recv_buffer[
 257                                sizeof(struct vmbuspipe_hdr) +
 258                                sizeof(struct icmsg_hdr)];
 259
 260                /*
 261                 * Stash away this global state for completing the
 262                 * transaction; note transactions are serialized.
 263                 */
 264
 265                fcopy_transaction.recv_len = recvlen;
 266                fcopy_transaction.recv_req_id = requestid;
 267                fcopy_transaction.fcopy_msg = fcopy_msg;
 268
 269                if (fcopy_transaction.state < HVUTIL_READY) {
 270                        /* Userspace is not registered yet */
 271                        fcopy_respond_to_host(HV_E_FAIL);
 272                        return;
 273                }
 274                fcopy_transaction.state = HVUTIL_HOSTMSG_RECEIVED;
 275
 276                /*
 277                 * Send the information to the user-level daemon.
 278                 */
 279                schedule_work(&fcopy_send_work);
 280                schedule_delayed_work(&fcopy_timeout_work,
 281                                      HV_UTIL_TIMEOUT * HZ);
 282                return;
 283        }
 284        icmsghdr->icflags = ICMSGHDRFLAG_TRANSACTION | ICMSGHDRFLAG_RESPONSE;
 285        vmbus_sendpacket(channel, recv_buffer, recvlen, requestid,
 286                        VM_PKT_DATA_INBAND, 0);
 287}
 288
 289/* Callback when data is received from userspace */
 290static int fcopy_on_msg(void *msg, int len)
 291{
 292        int *val = (int *)msg;
 293
 294        if (len != sizeof(int))
 295                return -EINVAL;
 296
 297        if (fcopy_transaction.state == HVUTIL_DEVICE_INIT)
 298                return fcopy_handle_handshake(*val);
 299
 300        if (fcopy_transaction.state != HVUTIL_USERSPACE_REQ)
 301                return -EINVAL;
 302
 303        /*
 304         * Complete the transaction by forwarding the result
 305         * to the host. But first, cancel the timeout.
 306         */
 307        if (cancel_delayed_work_sync(&fcopy_timeout_work)) {
 308                fcopy_transaction.state = HVUTIL_USERSPACE_RECV;
 309                fcopy_respond_to_host(*val);
 310                hv_poll_channel(fcopy_transaction.recv_channel,
 311                                fcopy_poll_wrapper);
 312        }
 313
 314        return 0;
 315}
 316
 317static void fcopy_on_reset(void)
 318{
 319        /*
 320         * The daemon has exited; reset the state.
 321         */
 322        fcopy_transaction.state = HVUTIL_DEVICE_INIT;
 323
 324        if (cancel_delayed_work_sync(&fcopy_timeout_work))
 325                fcopy_respond_to_host(HV_E_FAIL);
 326}
 327
 328int hv_fcopy_init(struct hv_util_service *srv)
 329{
 330        recv_buffer = srv->recv_buffer;
 331        fcopy_transaction.recv_channel = srv->channel;
 332
 333        /*
 334         * When this driver loads, the user level daemon that
 335         * processes the host requests may not yet be running.
 336         * Defer processing channel callbacks until the daemon
 337         * has registered.
 338         */
 339        fcopy_transaction.state = HVUTIL_DEVICE_INIT;
 340
 341        hvt = hvutil_transport_init(fcopy_devname, 0, 0,
 342                                    fcopy_on_msg, fcopy_on_reset);
 343        if (!hvt)
 344                return -EFAULT;
 345
 346        return 0;
 347}
 348
 349static void hv_fcopy_cancel_work(void)
 350{
 351        cancel_delayed_work_sync(&fcopy_timeout_work);
 352        cancel_work_sync(&fcopy_send_work);
 353}
 354
 355int hv_fcopy_pre_suspend(void)
 356{
 357        struct vmbus_channel *channel = fcopy_transaction.recv_channel;
 358        struct hv_fcopy_hdr *fcopy_msg;
 359
 360        /*
 361         * Fake a CANCEL_FCOPY message for the user space daemon in case the
 362         * daemon is in the middle of copying some file. It doesn't matter if
 363         * there is already a message pending to be delivered to the user
 364         * space since we force fcopy_transaction.state to be HVUTIL_READY, so
 365         * the user space daemon's write() will fail with EINVAL (see
 366         * fcopy_on_msg()), and the daemon will reset the device by closing
 367         * and re-opening it.
 368         */
 369        fcopy_msg = kzalloc(sizeof(*fcopy_msg), GFP_KERNEL);
 370        if (!fcopy_msg)
 371                return -ENOMEM;
 372
 373        tasklet_disable(&channel->callback_event);
 374
 375        fcopy_msg->operation = CANCEL_FCOPY;
 376
 377        hv_fcopy_cancel_work();
 378
 379        /* We don't care about the return value. */
 380        hvutil_transport_send(hvt, fcopy_msg, sizeof(*fcopy_msg), NULL);
 381
 382        kfree(fcopy_msg);
 383
 384        fcopy_transaction.state = HVUTIL_READY;
 385
 386        /* tasklet_enable() will be called in hv_fcopy_pre_resume(). */
 387        return 0;
 388}
 389
 390int hv_fcopy_pre_resume(void)
 391{
 392        struct vmbus_channel *channel = fcopy_transaction.recv_channel;
 393
 394        tasklet_enable(&channel->callback_event);
 395
 396        return 0;
 397}
 398
 399void hv_fcopy_deinit(void)
 400{
 401        fcopy_transaction.state = HVUTIL_DEVICE_DYING;
 402
 403        hv_fcopy_cancel_work();
 404
 405        hvutil_transport_destroy(hvt);
 406}
 407