101325476SK. Y. Srinivasan /* 201325476SK. Y. Srinivasan * An implementation of file copy service. 301325476SK. Y. Srinivasan * 401325476SK. Y. Srinivasan * Copyright (C) 2014, Microsoft, Inc. 501325476SK. Y. Srinivasan * 601325476SK. Y. Srinivasan * Author : K. Y. Srinivasan <ksrinivasan@novell.com> 701325476SK. Y. Srinivasan * 801325476SK. Y. Srinivasan * This program is free software; you can redistribute it and/or modify it 901325476SK. Y. Srinivasan * under the terms of the GNU General Public License version 2 as published 1001325476SK. Y. Srinivasan * by the Free Software Foundation. 1101325476SK. Y. Srinivasan * 1201325476SK. Y. Srinivasan * This program is distributed in the hope that it will be useful, but 1301325476SK. Y. Srinivasan * WITHOUT ANY WARRANTY; without even the implied warranty of 1401325476SK. Y. Srinivasan * MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE, GOOD TITLE or 1501325476SK. Y. Srinivasan * NON INFRINGEMENT. See the GNU General Public License for more 1601325476SK. Y. Srinivasan * details. 1701325476SK. Y. Srinivasan * 1801325476SK. Y. Srinivasan */ 1901325476SK. Y. Srinivasan 2001325476SK. Y. Srinivasan #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt 2101325476SK. Y. Srinivasan 2201325476SK. Y. Srinivasan #include <linux/nls.h> 2301325476SK. Y. Srinivasan #include <linux/workqueue.h> 2401325476SK. Y. Srinivasan #include <linux/hyperv.h> 2501325476SK. Y. Srinivasan #include <linux/sched.h> 2601325476SK. Y. Srinivasan 2701325476SK. Y. Srinivasan #include "hyperv_vmbus.h" 28c7e490fcSVitaly Kuznetsov #include "hv_utils_transport.h" 2901325476SK. Y. Srinivasan 3001325476SK. Y. Srinivasan #define WIN8_SRV_MAJOR 1 3101325476SK. Y. Srinivasan #define WIN8_SRV_MINOR 1 3201325476SK. Y. Srinivasan #define WIN8_SRV_VERSION (WIN8_SRV_MAJOR << 16 | WIN8_SRV_MINOR) 3301325476SK. Y. Srinivasan 3401325476SK. Y. Srinivasan /* 3501325476SK. Y. Srinivasan * Global state maintained for transaction that is being processed. 3601325476SK. Y. Srinivasan * For a class of integration services, including the "file copy service", 3701325476SK. Y. Srinivasan * the specified protocol is a "request/response" protocol which means that 3801325476SK. Y. Srinivasan * there can only be single outstanding transaction from the host at any 3901325476SK. Y. Srinivasan * given point in time. We use this to simplify memory management in this 4001325476SK. Y. Srinivasan * driver - we cache and process only one message at a time. 4101325476SK. Y. Srinivasan * 4201325476SK. Y. Srinivasan * While the request/response protocol is guaranteed by the host, we further 4301325476SK. Y. Srinivasan * ensure this by serializing packet processing in this driver - we do not 4401325476SK. Y. Srinivasan * read additional packets from the VMBUs until the current packet is fully 4501325476SK. Y. Srinivasan * handled. 4601325476SK. Y. Srinivasan */ 4701325476SK. Y. Srinivasan 4801325476SK. Y. Srinivasan static struct { 494c93ccccSVitaly Kuznetsov int state; /* hvutil_device_state */ 5001325476SK. Y. Srinivasan int recv_len; /* number of bytes received. */ 5101325476SK. Y. Srinivasan struct hv_fcopy_hdr *fcopy_msg; /* current message */ 5201325476SK. Y. Srinivasan struct vmbus_channel *recv_channel; /* chn we got the request */ 5301325476SK. Y. Srinivasan u64 recv_req_id; /* request ID. */ 5401325476SK. Y. Srinivasan void *fcopy_context; /* for the channel callback */ 5501325476SK. Y. Srinivasan } fcopy_transaction; 5601325476SK. Y. Srinivasan 5701325476SK. Y. Srinivasan static void fcopy_respond_to_host(int error); 58c7e490fcSVitaly Kuznetsov static void fcopy_send_data(struct work_struct *dummy); 591d072339SVitaly Kuznetsov static void fcopy_timeout_func(struct work_struct *dummy); 601d072339SVitaly Kuznetsov static DECLARE_DELAYED_WORK(fcopy_timeout_work, fcopy_timeout_func); 61c7e490fcSVitaly Kuznetsov static DECLARE_WORK(fcopy_send_work, fcopy_send_data); 62c7e490fcSVitaly Kuznetsov static const char fcopy_devname[] = "vmbus/hv_fcopy"; 6301325476SK. Y. Srinivasan static u8 *recv_buffer; 64c7e490fcSVitaly Kuznetsov static struct hvutil_transport *hvt; 6501325476SK. Y. Srinivasan 661d072339SVitaly Kuznetsov static void fcopy_timeout_func(struct work_struct *dummy) 6701325476SK. Y. Srinivasan { 6801325476SK. Y. Srinivasan /* 6901325476SK. Y. Srinivasan * If the timer fires, the user-mode component has not responded; 7001325476SK. Y. Srinivasan * process the pending transaction. 7101325476SK. Y. Srinivasan */ 7201325476SK. Y. Srinivasan fcopy_respond_to_host(HV_E_FAIL); 73d9b16529SDexuan Cui 744c93ccccSVitaly Kuznetsov /* Transaction is finished, reset the state. */ 754c93ccccSVitaly Kuznetsov if (fcopy_transaction.state > HVUTIL_READY) 764c93ccccSVitaly Kuznetsov fcopy_transaction.state = HVUTIL_READY; 774c93ccccSVitaly Kuznetsov 78242f3122SVitaly Kuznetsov hv_poll_channel(fcopy_transaction.fcopy_context, 79242f3122SVitaly Kuznetsov hv_fcopy_onchannelcallback); 8001325476SK. Y. Srinivasan } 8101325476SK. Y. Srinivasan 8201325476SK. Y. Srinivasan static int fcopy_handle_handshake(u32 version) 8301325476SK. Y. Srinivasan { 8401325476SK. Y. Srinivasan switch (version) { 8501325476SK. Y. Srinivasan case FCOPY_CURRENT_VERSION: 8601325476SK. Y. Srinivasan break; 8701325476SK. Y. Srinivasan default: 8801325476SK. Y. Srinivasan /* 8901325476SK. Y. Srinivasan * For now we will fail the registration. 9001325476SK. Y. Srinivasan * If and when we have multiple versions to 9101325476SK. Y. Srinivasan * deal with, we will be backward compatible. 9201325476SK. Y. Srinivasan * We will add this code when needed. 9301325476SK. Y. Srinivasan */ 9401325476SK. Y. Srinivasan return -EINVAL; 9501325476SK. Y. Srinivasan } 9601325476SK. Y. Srinivasan pr_info("FCP: user-mode registering done. Daemon version: %d\n", 9701325476SK. Y. Srinivasan version); 984c93ccccSVitaly Kuznetsov fcopy_transaction.state = HVUTIL_READY; 99242f3122SVitaly Kuznetsov hv_poll_channel(fcopy_transaction.fcopy_context, 100242f3122SVitaly Kuznetsov hv_fcopy_onchannelcallback); 10101325476SK. Y. Srinivasan return 0; 10201325476SK. Y. Srinivasan } 10301325476SK. Y. Srinivasan 104c7e490fcSVitaly Kuznetsov static void fcopy_send_data(struct work_struct *dummy) 10501325476SK. Y. Srinivasan { 106c7e490fcSVitaly Kuznetsov struct hv_start_fcopy smsg_out; 10701325476SK. Y. Srinivasan int operation = fcopy_transaction.fcopy_msg->operation; 10801325476SK. Y. Srinivasan struct hv_start_fcopy *smsg_in; 109c7e490fcSVitaly Kuznetsov void *out_src; 110c7e490fcSVitaly Kuznetsov int rc, out_len; 11101325476SK. Y. Srinivasan 11201325476SK. Y. Srinivasan /* 11301325476SK. Y. Srinivasan * The strings sent from the host are encoded in 11401325476SK. Y. Srinivasan * in utf16; convert it to utf8 strings. 11501325476SK. Y. Srinivasan * The host assures us that the utf16 strings will not exceed 11601325476SK. Y. Srinivasan * the max lengths specified. We will however, reserve room 11701325476SK. Y. Srinivasan * for the string terminating character - in the utf16s_utf8s() 11801325476SK. Y. Srinivasan * function we limit the size of the buffer where the converted 11901325476SK. Y. Srinivasan * string is placed to W_MAX_PATH -1 to guarantee 12001325476SK. Y. Srinivasan * that the strings can be properly terminated! 12101325476SK. Y. Srinivasan */ 12201325476SK. Y. Srinivasan 12301325476SK. Y. Srinivasan switch (operation) { 12401325476SK. Y. Srinivasan case START_FILE_COPY: 125c7e490fcSVitaly Kuznetsov out_len = sizeof(struct hv_start_fcopy); 126c7e490fcSVitaly Kuznetsov memset(&smsg_out, 0, out_len); 127c7e490fcSVitaly Kuznetsov smsg_out.hdr.operation = operation; 12801325476SK. Y. Srinivasan smsg_in = (struct hv_start_fcopy *)fcopy_transaction.fcopy_msg; 12901325476SK. Y. Srinivasan 13001325476SK. Y. Srinivasan utf16s_to_utf8s((wchar_t *)smsg_in->file_name, W_MAX_PATH, 13101325476SK. Y. Srinivasan UTF16_LITTLE_ENDIAN, 132c7e490fcSVitaly Kuznetsov (__u8 *)&smsg_out.file_name, W_MAX_PATH - 1); 13301325476SK. Y. Srinivasan 13401325476SK. Y. Srinivasan utf16s_to_utf8s((wchar_t *)smsg_in->path_name, W_MAX_PATH, 13501325476SK. Y. Srinivasan UTF16_LITTLE_ENDIAN, 136c7e490fcSVitaly Kuznetsov (__u8 *)&smsg_out.path_name, W_MAX_PATH - 1); 13701325476SK. Y. Srinivasan 138c7e490fcSVitaly Kuznetsov smsg_out.copy_flags = smsg_in->copy_flags; 139c7e490fcSVitaly Kuznetsov smsg_out.file_size = smsg_in->file_size; 140c7e490fcSVitaly Kuznetsov out_src = &smsg_out; 14101325476SK. Y. Srinivasan break; 14201325476SK. Y. Srinivasan 14301325476SK. Y. Srinivasan default: 144c7e490fcSVitaly Kuznetsov out_src = fcopy_transaction.fcopy_msg; 145c7e490fcSVitaly Kuznetsov out_len = fcopy_transaction.recv_len; 14601325476SK. Y. Srinivasan break; 14701325476SK. Y. Srinivasan } 148c7e490fcSVitaly Kuznetsov 149c7e490fcSVitaly Kuznetsov fcopy_transaction.state = HVUTIL_USERSPACE_REQ; 150c7e490fcSVitaly Kuznetsov rc = hvutil_transport_send(hvt, out_src, out_len); 151c7e490fcSVitaly Kuznetsov if (rc) { 152c7e490fcSVitaly Kuznetsov pr_debug("FCP: failed to communicate to the daemon: %d\n", rc); 153c7e490fcSVitaly Kuznetsov if (cancel_delayed_work_sync(&fcopy_timeout_work)) { 154c7e490fcSVitaly Kuznetsov fcopy_respond_to_host(HV_E_FAIL); 155c7e490fcSVitaly Kuznetsov fcopy_transaction.state = HVUTIL_READY; 156c7e490fcSVitaly Kuznetsov } 157c7e490fcSVitaly Kuznetsov } 15801325476SK. Y. Srinivasan return; 15901325476SK. Y. Srinivasan } 16001325476SK. Y. Srinivasan 16101325476SK. Y. Srinivasan /* 16201325476SK. Y. Srinivasan * Send a response back to the host. 16301325476SK. Y. Srinivasan */ 16401325476SK. Y. Srinivasan 16501325476SK. Y. Srinivasan static void 16601325476SK. Y. Srinivasan fcopy_respond_to_host(int error) 16701325476SK. Y. Srinivasan { 16801325476SK. Y. Srinivasan struct icmsg_hdr *icmsghdr; 16901325476SK. Y. Srinivasan u32 buf_len; 17001325476SK. Y. Srinivasan struct vmbus_channel *channel; 17101325476SK. Y. Srinivasan u64 req_id; 17201325476SK. Y. Srinivasan 17301325476SK. Y. Srinivasan /* 17401325476SK. Y. Srinivasan * Copy the global state for completing the transaction. Note that 17501325476SK. Y. Srinivasan * only one transaction can be active at a time. This is guaranteed 17601325476SK. Y. Srinivasan * by the file copy protocol implemented by the host. Furthermore, 17701325476SK. Y. Srinivasan * the "transaction active" state we maintain ensures that there can 17801325476SK. Y. Srinivasan * only be one active transaction at a time. 17901325476SK. Y. Srinivasan */ 18001325476SK. Y. Srinivasan 18101325476SK. Y. Srinivasan buf_len = fcopy_transaction.recv_len; 18201325476SK. Y. Srinivasan channel = fcopy_transaction.recv_channel; 18301325476SK. Y. Srinivasan req_id = fcopy_transaction.recv_req_id; 18401325476SK. Y. Srinivasan 18501325476SK. Y. Srinivasan icmsghdr = (struct icmsg_hdr *) 18601325476SK. Y. Srinivasan &recv_buffer[sizeof(struct vmbuspipe_hdr)]; 18701325476SK. Y. Srinivasan 18801325476SK. Y. Srinivasan if (channel->onchannel_callback == NULL) 18901325476SK. Y. Srinivasan /* 19001325476SK. Y. Srinivasan * We have raced with util driver being unloaded; 19101325476SK. Y. Srinivasan * silently return. 19201325476SK. Y. Srinivasan */ 19301325476SK. Y. Srinivasan return; 19401325476SK. Y. Srinivasan 19501325476SK. Y. Srinivasan icmsghdr->status = error; 19601325476SK. Y. Srinivasan icmsghdr->icflags = ICMSGHDRFLAG_TRANSACTION | ICMSGHDRFLAG_RESPONSE; 19701325476SK. Y. Srinivasan vmbus_sendpacket(channel, recv_buffer, buf_len, req_id, 19801325476SK. Y. Srinivasan VM_PKT_DATA_INBAND, 0); 19901325476SK. Y. Srinivasan } 20001325476SK. Y. Srinivasan 20101325476SK. Y. Srinivasan void hv_fcopy_onchannelcallback(void *context) 20201325476SK. Y. Srinivasan { 20301325476SK. Y. Srinivasan struct vmbus_channel *channel = context; 20401325476SK. Y. Srinivasan u32 recvlen; 20501325476SK. Y. Srinivasan u64 requestid; 20601325476SK. Y. Srinivasan struct hv_fcopy_hdr *fcopy_msg; 20701325476SK. Y. Srinivasan struct icmsg_hdr *icmsghdr; 20801325476SK. Y. Srinivasan struct icmsg_negotiate *negop = NULL; 20901325476SK. Y. Srinivasan int util_fw_version; 21001325476SK. Y. Srinivasan int fcopy_srv_version; 21101325476SK. Y. Srinivasan 2124c93ccccSVitaly Kuznetsov if (fcopy_transaction.state > HVUTIL_READY) { 21301325476SK. Y. Srinivasan /* 21401325476SK. Y. Srinivasan * We will defer processing this callback once 21501325476SK. Y. Srinivasan * the current transaction is complete. 21601325476SK. Y. Srinivasan */ 21701325476SK. Y. Srinivasan fcopy_transaction.fcopy_context = context; 21801325476SK. Y. Srinivasan return; 21901325476SK. Y. Srinivasan } 220242f3122SVitaly Kuznetsov fcopy_transaction.fcopy_context = NULL; 22101325476SK. Y. Srinivasan 22201325476SK. Y. Srinivasan vmbus_recvpacket(channel, recv_buffer, PAGE_SIZE * 2, &recvlen, 22301325476SK. Y. Srinivasan &requestid); 22401325476SK. Y. Srinivasan if (recvlen <= 0) 22501325476SK. Y. Srinivasan return; 22601325476SK. Y. Srinivasan 22701325476SK. Y. Srinivasan icmsghdr = (struct icmsg_hdr *)&recv_buffer[ 22801325476SK. Y. Srinivasan sizeof(struct vmbuspipe_hdr)]; 22901325476SK. Y. Srinivasan if (icmsghdr->icmsgtype == ICMSGTYPE_NEGOTIATE) { 23001325476SK. Y. Srinivasan util_fw_version = UTIL_FW_VERSION; 23101325476SK. Y. Srinivasan fcopy_srv_version = WIN8_SRV_VERSION; 23201325476SK. Y. Srinivasan vmbus_prep_negotiate_resp(icmsghdr, negop, recv_buffer, 23301325476SK. Y. Srinivasan util_fw_version, fcopy_srv_version); 23401325476SK. Y. Srinivasan } else { 23501325476SK. Y. Srinivasan fcopy_msg = (struct hv_fcopy_hdr *)&recv_buffer[ 23601325476SK. Y. Srinivasan sizeof(struct vmbuspipe_hdr) + 23701325476SK. Y. Srinivasan sizeof(struct icmsg_hdr)]; 23801325476SK. Y. Srinivasan 23901325476SK. Y. Srinivasan /* 24001325476SK. Y. Srinivasan * Stash away this global state for completing the 24101325476SK. Y. Srinivasan * transaction; note transactions are serialized. 24201325476SK. Y. Srinivasan */ 24301325476SK. Y. Srinivasan 24401325476SK. Y. Srinivasan fcopy_transaction.recv_len = recvlen; 24501325476SK. Y. Srinivasan fcopy_transaction.recv_channel = channel; 24601325476SK. Y. Srinivasan fcopy_transaction.recv_req_id = requestid; 24701325476SK. Y. Srinivasan fcopy_transaction.fcopy_msg = fcopy_msg; 24801325476SK. Y. Srinivasan 2494c93ccccSVitaly Kuznetsov if (fcopy_transaction.state < HVUTIL_READY) { 2504c93ccccSVitaly Kuznetsov /* Userspace is not registered yet */ 2514c93ccccSVitaly Kuznetsov fcopy_respond_to_host(HV_E_FAIL); 2524c93ccccSVitaly Kuznetsov return; 2534c93ccccSVitaly Kuznetsov } 2544c93ccccSVitaly Kuznetsov fcopy_transaction.state = HVUTIL_HOSTMSG_RECEIVED; 2554c93ccccSVitaly Kuznetsov 25601325476SK. Y. Srinivasan /* 25701325476SK. Y. Srinivasan * Send the information to the user-level daemon. 25801325476SK. Y. Srinivasan */ 259c7e490fcSVitaly Kuznetsov schedule_work(&fcopy_send_work); 2601d072339SVitaly Kuznetsov schedule_delayed_work(&fcopy_timeout_work, 5*HZ); 26101325476SK. Y. Srinivasan return; 26201325476SK. Y. Srinivasan } 26301325476SK. Y. Srinivasan icmsghdr->icflags = ICMSGHDRFLAG_TRANSACTION | ICMSGHDRFLAG_RESPONSE; 26401325476SK. Y. Srinivasan vmbus_sendpacket(channel, recv_buffer, recvlen, requestid, 26501325476SK. Y. Srinivasan VM_PKT_DATA_INBAND, 0); 26601325476SK. Y. Srinivasan } 26701325476SK. Y. Srinivasan 268c7e490fcSVitaly Kuznetsov /* Callback when data is received from userspace */ 269c7e490fcSVitaly Kuznetsov static int fcopy_on_msg(void *msg, int len) 27001325476SK. Y. Srinivasan { 271c7e490fcSVitaly Kuznetsov int *val = (int *)msg; 27201325476SK. Y. Srinivasan 273c7e490fcSVitaly Kuznetsov if (len != sizeof(int)) 27401325476SK. Y. Srinivasan return -EINVAL; 27501325476SK. Y. Srinivasan 276c7e490fcSVitaly Kuznetsov if (fcopy_transaction.state == HVUTIL_DEVICE_INIT) 277c7e490fcSVitaly Kuznetsov return fcopy_handle_handshake(*val); 27801325476SK. Y. Srinivasan 2794c93ccccSVitaly Kuznetsov if (fcopy_transaction.state != HVUTIL_USERSPACE_REQ) 2804c93ccccSVitaly Kuznetsov return -EINVAL; 2814c93ccccSVitaly Kuznetsov 28201325476SK. Y. Srinivasan /* 28301325476SK. Y. Srinivasan * Complete the transaction by forwarding the result 28401325476SK. Y. Srinivasan * to the host. But first, cancel the timeout. 28501325476SK. Y. Srinivasan */ 2864c93ccccSVitaly Kuznetsov if (cancel_delayed_work_sync(&fcopy_timeout_work)) { 2874c93ccccSVitaly Kuznetsov fcopy_transaction.state = HVUTIL_USERSPACE_RECV; 288c7e490fcSVitaly Kuznetsov fcopy_respond_to_host(*val); 2894c93ccccSVitaly Kuznetsov fcopy_transaction.state = HVUTIL_READY; 290242f3122SVitaly Kuznetsov hv_poll_channel(fcopy_transaction.fcopy_context, 291242f3122SVitaly Kuznetsov hv_fcopy_onchannelcallback); 292242f3122SVitaly Kuznetsov } 29301325476SK. Y. Srinivasan 29401325476SK. Y. Srinivasan return 0; 29501325476SK. Y. Srinivasan } 29601325476SK. Y. Srinivasan 297c7e490fcSVitaly Kuznetsov static void fcopy_on_reset(void) 29801325476SK. Y. Srinivasan { 29901325476SK. Y. Srinivasan /* 30001325476SK. Y. Srinivasan * The daemon has exited; reset the state. 30101325476SK. Y. Srinivasan */ 3024c93ccccSVitaly Kuznetsov fcopy_transaction.state = HVUTIL_DEVICE_INIT; 303d9b16529SDexuan Cui 304c7e490fcSVitaly Kuznetsov if (cancel_delayed_work_sync(&fcopy_timeout_work)) 305d9b16529SDexuan Cui fcopy_respond_to_host(HV_E_FAIL); 306d9b16529SDexuan Cui } 30701325476SK. Y. Srinivasan 30801325476SK. Y. Srinivasan int hv_fcopy_init(struct hv_util_service *srv) 30901325476SK. Y. Srinivasan { 31001325476SK. Y. Srinivasan recv_buffer = srv->recv_buffer; 31101325476SK. Y. Srinivasan 31201325476SK. Y. Srinivasan /* 31301325476SK. Y. Srinivasan * When this driver loads, the user level daemon that 31401325476SK. Y. Srinivasan * processes the host requests may not yet be running. 31501325476SK. Y. Srinivasan * Defer processing channel callbacks until the daemon 31601325476SK. Y. Srinivasan * has registered. 31701325476SK. Y. Srinivasan */ 3184c93ccccSVitaly Kuznetsov fcopy_transaction.state = HVUTIL_DEVICE_INIT; 31901325476SK. Y. Srinivasan 320c7e490fcSVitaly Kuznetsov hvt = hvutil_transport_init(fcopy_devname, 0, 0, 321c7e490fcSVitaly Kuznetsov fcopy_on_msg, fcopy_on_reset); 322c7e490fcSVitaly Kuznetsov if (!hvt) 323c7e490fcSVitaly Kuznetsov return -EFAULT; 324c7e490fcSVitaly Kuznetsov 325c7e490fcSVitaly Kuznetsov return 0; 32601325476SK. Y. Srinivasan } 32701325476SK. Y. Srinivasan 32801325476SK. Y. Srinivasan void hv_fcopy_deinit(void) 32901325476SK. Y. Srinivasan { 3304c93ccccSVitaly Kuznetsov fcopy_transaction.state = HVUTIL_DEVICE_DYING; 3311d072339SVitaly Kuznetsov cancel_delayed_work_sync(&fcopy_timeout_work); 332c7e490fcSVitaly Kuznetsov hvutil_transport_destroy(hvt); 33301325476SK. Y. Srinivasan } 334