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/semaphore.h> 2301325476SK. Y. Srinivasan #include <linux/fs.h> 2401325476SK. Y. Srinivasan #include <linux/nls.h> 2501325476SK. Y. Srinivasan #include <linux/workqueue.h> 2601325476SK. Y. Srinivasan #include <linux/cdev.h> 2701325476SK. Y. Srinivasan #include <linux/hyperv.h> 2801325476SK. Y. Srinivasan #include <linux/sched.h> 2901325476SK. Y. Srinivasan #include <linux/uaccess.h> 3001325476SK. Y. Srinivasan #include <linux/miscdevice.h> 3101325476SK. Y. Srinivasan 3201325476SK. Y. Srinivasan #include "hyperv_vmbus.h" 3301325476SK. Y. Srinivasan 3401325476SK. Y. Srinivasan #define WIN8_SRV_MAJOR 1 3501325476SK. Y. Srinivasan #define WIN8_SRV_MINOR 1 3601325476SK. Y. Srinivasan #define WIN8_SRV_VERSION (WIN8_SRV_MAJOR << 16 | WIN8_SRV_MINOR) 3701325476SK. Y. Srinivasan 3801325476SK. Y. Srinivasan /* 3901325476SK. Y. Srinivasan * Global state maintained for transaction that is being processed. 4001325476SK. Y. Srinivasan * For a class of integration services, including the "file copy service", 4101325476SK. Y. Srinivasan * the specified protocol is a "request/response" protocol which means that 4201325476SK. Y. Srinivasan * there can only be single outstanding transaction from the host at any 4301325476SK. Y. Srinivasan * given point in time. We use this to simplify memory management in this 4401325476SK. Y. Srinivasan * driver - we cache and process only one message at a time. 4501325476SK. Y. Srinivasan * 4601325476SK. Y. Srinivasan * While the request/response protocol is guaranteed by the host, we further 4701325476SK. Y. Srinivasan * ensure this by serializing packet processing in this driver - we do not 4801325476SK. Y. Srinivasan * read additional packets from the VMBUs until the current packet is fully 4901325476SK. Y. Srinivasan * handled. 5001325476SK. Y. Srinivasan * 5101325476SK. Y. Srinivasan * The transaction "active" state is set when we receive a request from the 5201325476SK. Y. Srinivasan * host and we cleanup this state when the transaction is completed - when we 5301325476SK. Y. Srinivasan * respond to the host with our response. When the transaction active state is 5401325476SK. Y. Srinivasan * set, we defer handling incoming packets. 5501325476SK. Y. Srinivasan */ 5601325476SK. Y. Srinivasan 5701325476SK. Y. Srinivasan static struct { 5801325476SK. Y. Srinivasan bool active; /* transaction status - active or not */ 5901325476SK. Y. Srinivasan int recv_len; /* number of bytes received. */ 6001325476SK. Y. Srinivasan struct hv_fcopy_hdr *fcopy_msg; /* current message */ 6101325476SK. Y. Srinivasan struct hv_start_fcopy message; /* sent to daemon */ 6201325476SK. Y. Srinivasan struct vmbus_channel *recv_channel; /* chn we got the request */ 6301325476SK. Y. Srinivasan u64 recv_req_id; /* request ID. */ 6401325476SK. Y. Srinivasan void *fcopy_context; /* for the channel callback */ 6501325476SK. Y. Srinivasan struct semaphore read_sema; 6601325476SK. Y. Srinivasan } fcopy_transaction; 6701325476SK. Y. Srinivasan 6801325476SK. Y. Srinivasan static bool opened; /* currently device opened */ 6901325476SK. Y. Srinivasan 7001325476SK. Y. Srinivasan /* 7101325476SK. Y. Srinivasan * Before we can accept copy messages from the host, we need 7201325476SK. Y. Srinivasan * to handshake with the user level daemon. This state tracks 7301325476SK. Y. Srinivasan * if we are in the handshake phase. 7401325476SK. Y. Srinivasan */ 7501325476SK. Y. Srinivasan static bool in_hand_shake = true; 7601325476SK. Y. Srinivasan static void fcopy_send_data(void); 7701325476SK. Y. Srinivasan static void fcopy_respond_to_host(int error); 7801325476SK. Y. Srinivasan static void fcopy_work_func(struct work_struct *dummy); 7901325476SK. Y. Srinivasan static DECLARE_DELAYED_WORK(fcopy_work, fcopy_work_func); 8001325476SK. Y. Srinivasan static u8 *recv_buffer; 8101325476SK. Y. Srinivasan 8201325476SK. Y. Srinivasan static void fcopy_work_func(struct work_struct *dummy) 8301325476SK. Y. Srinivasan { 8401325476SK. Y. Srinivasan /* 8501325476SK. Y. Srinivasan * If the timer fires, the user-mode component has not responded; 8601325476SK. Y. Srinivasan * process the pending transaction. 8701325476SK. Y. Srinivasan */ 8801325476SK. Y. Srinivasan fcopy_respond_to_host(HV_E_FAIL); 89d9b16529SDexuan Cui 90d9b16529SDexuan Cui /* In the case the user-space daemon crashes, hangs or is killed, we 91d9b16529SDexuan Cui * need to down the semaphore, otherwise, after the daemon starts next 92d9b16529SDexuan Cui * time, the obsolete data in fcopy_transaction.message or 93d9b16529SDexuan Cui * fcopy_transaction.fcopy_msg will be used immediately. 94d9b16529SDexuan Cui * 95d9b16529SDexuan Cui * NOTE: fcopy_read() happens to get the semaphore (very rare)? We're 96d9b16529SDexuan Cui * still OK, because we've reported the failure to the host. 97d9b16529SDexuan Cui */ 98d9b16529SDexuan Cui if (down_trylock(&fcopy_transaction.read_sema)) 99d9b16529SDexuan Cui ; 100d9b16529SDexuan Cui 101242f3122SVitaly Kuznetsov hv_poll_channel(fcopy_transaction.fcopy_context, 102242f3122SVitaly Kuznetsov hv_fcopy_onchannelcallback); 10301325476SK. Y. Srinivasan } 10401325476SK. Y. Srinivasan 10501325476SK. Y. Srinivasan static int fcopy_handle_handshake(u32 version) 10601325476SK. Y. Srinivasan { 10701325476SK. Y. Srinivasan switch (version) { 10801325476SK. Y. Srinivasan case FCOPY_CURRENT_VERSION: 10901325476SK. Y. Srinivasan break; 11001325476SK. Y. Srinivasan default: 11101325476SK. Y. Srinivasan /* 11201325476SK. Y. Srinivasan * For now we will fail the registration. 11301325476SK. Y. Srinivasan * If and when we have multiple versions to 11401325476SK. Y. Srinivasan * deal with, we will be backward compatible. 11501325476SK. Y. Srinivasan * We will add this code when needed. 11601325476SK. Y. Srinivasan */ 11701325476SK. Y. Srinivasan return -EINVAL; 11801325476SK. Y. Srinivasan } 11901325476SK. Y. Srinivasan pr_info("FCP: user-mode registering done. Daemon version: %d\n", 12001325476SK. Y. Srinivasan version); 12101325476SK. Y. Srinivasan fcopy_transaction.active = false; 122242f3122SVitaly Kuznetsov hv_poll_channel(fcopy_transaction.fcopy_context, 123242f3122SVitaly Kuznetsov hv_fcopy_onchannelcallback); 12401325476SK. Y. Srinivasan in_hand_shake = false; 12501325476SK. Y. Srinivasan return 0; 12601325476SK. Y. Srinivasan } 12701325476SK. Y. Srinivasan 12801325476SK. Y. Srinivasan static void fcopy_send_data(void) 12901325476SK. Y. Srinivasan { 13001325476SK. Y. Srinivasan struct hv_start_fcopy *smsg_out = &fcopy_transaction.message; 13101325476SK. Y. Srinivasan int operation = fcopy_transaction.fcopy_msg->operation; 13201325476SK. Y. Srinivasan struct hv_start_fcopy *smsg_in; 13301325476SK. Y. Srinivasan 13401325476SK. Y. Srinivasan /* 13501325476SK. Y. Srinivasan * The strings sent from the host are encoded in 13601325476SK. Y. Srinivasan * in utf16; convert it to utf8 strings. 13701325476SK. Y. Srinivasan * The host assures us that the utf16 strings will not exceed 13801325476SK. Y. Srinivasan * the max lengths specified. We will however, reserve room 13901325476SK. Y. Srinivasan * for the string terminating character - in the utf16s_utf8s() 14001325476SK. Y. Srinivasan * function we limit the size of the buffer where the converted 14101325476SK. Y. Srinivasan * string is placed to W_MAX_PATH -1 to guarantee 14201325476SK. Y. Srinivasan * that the strings can be properly terminated! 14301325476SK. Y. Srinivasan */ 14401325476SK. Y. Srinivasan 14501325476SK. Y. Srinivasan switch (operation) { 14601325476SK. Y. Srinivasan case START_FILE_COPY: 14701325476SK. Y. Srinivasan memset(smsg_out, 0, sizeof(struct hv_start_fcopy)); 14801325476SK. Y. Srinivasan smsg_out->hdr.operation = operation; 14901325476SK. Y. Srinivasan smsg_in = (struct hv_start_fcopy *)fcopy_transaction.fcopy_msg; 15001325476SK. Y. Srinivasan 15101325476SK. Y. Srinivasan utf16s_to_utf8s((wchar_t *)smsg_in->file_name, W_MAX_PATH, 15201325476SK. Y. Srinivasan UTF16_LITTLE_ENDIAN, 15301325476SK. Y. Srinivasan (__u8 *)smsg_out->file_name, W_MAX_PATH - 1); 15401325476SK. Y. Srinivasan 15501325476SK. Y. Srinivasan utf16s_to_utf8s((wchar_t *)smsg_in->path_name, W_MAX_PATH, 15601325476SK. Y. Srinivasan UTF16_LITTLE_ENDIAN, 15701325476SK. Y. Srinivasan (__u8 *)smsg_out->path_name, W_MAX_PATH - 1); 15801325476SK. Y. Srinivasan 15901325476SK. Y. Srinivasan smsg_out->copy_flags = smsg_in->copy_flags; 16001325476SK. Y. Srinivasan smsg_out->file_size = smsg_in->file_size; 16101325476SK. Y. Srinivasan break; 16201325476SK. Y. Srinivasan 16301325476SK. Y. Srinivasan default: 16401325476SK. Y. Srinivasan break; 16501325476SK. Y. Srinivasan } 16601325476SK. Y. Srinivasan up(&fcopy_transaction.read_sema); 16701325476SK. Y. Srinivasan return; 16801325476SK. Y. Srinivasan } 16901325476SK. Y. Srinivasan 17001325476SK. Y. Srinivasan /* 17101325476SK. Y. Srinivasan * Send a response back to the host. 17201325476SK. Y. Srinivasan */ 17301325476SK. Y. Srinivasan 17401325476SK. Y. Srinivasan static void 17501325476SK. Y. Srinivasan fcopy_respond_to_host(int error) 17601325476SK. Y. Srinivasan { 17701325476SK. Y. Srinivasan struct icmsg_hdr *icmsghdr; 17801325476SK. Y. Srinivasan u32 buf_len; 17901325476SK. Y. Srinivasan struct vmbus_channel *channel; 18001325476SK. Y. Srinivasan u64 req_id; 18101325476SK. Y. Srinivasan 18201325476SK. Y. Srinivasan /* 18301325476SK. Y. Srinivasan * Copy the global state for completing the transaction. Note that 18401325476SK. Y. Srinivasan * only one transaction can be active at a time. This is guaranteed 18501325476SK. Y. Srinivasan * by the file copy protocol implemented by the host. Furthermore, 18601325476SK. Y. Srinivasan * the "transaction active" state we maintain ensures that there can 18701325476SK. Y. Srinivasan * only be one active transaction at a time. 18801325476SK. Y. Srinivasan */ 18901325476SK. Y. Srinivasan 19001325476SK. Y. Srinivasan buf_len = fcopy_transaction.recv_len; 19101325476SK. Y. Srinivasan channel = fcopy_transaction.recv_channel; 19201325476SK. Y. Srinivasan req_id = fcopy_transaction.recv_req_id; 19301325476SK. Y. Srinivasan 19401325476SK. Y. Srinivasan fcopy_transaction.active = false; 19501325476SK. Y. Srinivasan 19601325476SK. Y. Srinivasan icmsghdr = (struct icmsg_hdr *) 19701325476SK. Y. Srinivasan &recv_buffer[sizeof(struct vmbuspipe_hdr)]; 19801325476SK. Y. Srinivasan 19901325476SK. Y. Srinivasan if (channel->onchannel_callback == NULL) 20001325476SK. Y. Srinivasan /* 20101325476SK. Y. Srinivasan * We have raced with util driver being unloaded; 20201325476SK. Y. Srinivasan * silently return. 20301325476SK. Y. Srinivasan */ 20401325476SK. Y. Srinivasan return; 20501325476SK. Y. Srinivasan 20601325476SK. Y. Srinivasan icmsghdr->status = error; 20701325476SK. Y. Srinivasan icmsghdr->icflags = ICMSGHDRFLAG_TRANSACTION | ICMSGHDRFLAG_RESPONSE; 20801325476SK. Y. Srinivasan vmbus_sendpacket(channel, recv_buffer, buf_len, req_id, 20901325476SK. Y. Srinivasan VM_PKT_DATA_INBAND, 0); 21001325476SK. Y. Srinivasan } 21101325476SK. Y. Srinivasan 21201325476SK. Y. Srinivasan void hv_fcopy_onchannelcallback(void *context) 21301325476SK. Y. Srinivasan { 21401325476SK. Y. Srinivasan struct vmbus_channel *channel = context; 21501325476SK. Y. Srinivasan u32 recvlen; 21601325476SK. Y. Srinivasan u64 requestid; 21701325476SK. Y. Srinivasan struct hv_fcopy_hdr *fcopy_msg; 21801325476SK. Y. Srinivasan struct icmsg_hdr *icmsghdr; 21901325476SK. Y. Srinivasan struct icmsg_negotiate *negop = NULL; 22001325476SK. Y. Srinivasan int util_fw_version; 22101325476SK. Y. Srinivasan int fcopy_srv_version; 22201325476SK. Y. Srinivasan 22301325476SK. Y. Srinivasan if (fcopy_transaction.active) { 22401325476SK. Y. Srinivasan /* 22501325476SK. Y. Srinivasan * We will defer processing this callback once 22601325476SK. Y. Srinivasan * the current transaction is complete. 22701325476SK. Y. Srinivasan */ 22801325476SK. Y. Srinivasan fcopy_transaction.fcopy_context = context; 22901325476SK. Y. Srinivasan return; 23001325476SK. Y. Srinivasan } 231242f3122SVitaly Kuznetsov fcopy_transaction.fcopy_context = NULL; 23201325476SK. Y. Srinivasan 23301325476SK. Y. Srinivasan vmbus_recvpacket(channel, recv_buffer, PAGE_SIZE * 2, &recvlen, 23401325476SK. Y. Srinivasan &requestid); 23501325476SK. Y. Srinivasan if (recvlen <= 0) 23601325476SK. Y. Srinivasan return; 23701325476SK. Y. Srinivasan 23801325476SK. Y. Srinivasan icmsghdr = (struct icmsg_hdr *)&recv_buffer[ 23901325476SK. Y. Srinivasan sizeof(struct vmbuspipe_hdr)]; 24001325476SK. Y. Srinivasan if (icmsghdr->icmsgtype == ICMSGTYPE_NEGOTIATE) { 24101325476SK. Y. Srinivasan util_fw_version = UTIL_FW_VERSION; 24201325476SK. Y. Srinivasan fcopy_srv_version = WIN8_SRV_VERSION; 24301325476SK. Y. Srinivasan vmbus_prep_negotiate_resp(icmsghdr, negop, recv_buffer, 24401325476SK. Y. Srinivasan util_fw_version, fcopy_srv_version); 24501325476SK. Y. Srinivasan } else { 24601325476SK. Y. Srinivasan fcopy_msg = (struct hv_fcopy_hdr *)&recv_buffer[ 24701325476SK. Y. Srinivasan sizeof(struct vmbuspipe_hdr) + 24801325476SK. Y. Srinivasan sizeof(struct icmsg_hdr)]; 24901325476SK. Y. Srinivasan 25001325476SK. Y. Srinivasan /* 25101325476SK. Y. Srinivasan * Stash away this global state for completing the 25201325476SK. Y. Srinivasan * transaction; note transactions are serialized. 25301325476SK. Y. Srinivasan */ 25401325476SK. Y. Srinivasan 25501325476SK. Y. Srinivasan fcopy_transaction.active = true; 25601325476SK. Y. Srinivasan fcopy_transaction.recv_len = recvlen; 25701325476SK. Y. Srinivasan fcopy_transaction.recv_channel = channel; 25801325476SK. Y. Srinivasan fcopy_transaction.recv_req_id = requestid; 25901325476SK. Y. Srinivasan fcopy_transaction.fcopy_msg = fcopy_msg; 26001325476SK. Y. Srinivasan 26101325476SK. Y. Srinivasan /* 26201325476SK. Y. Srinivasan * Send the information to the user-level daemon. 26301325476SK. Y. Srinivasan */ 26401325476SK. Y. Srinivasan schedule_delayed_work(&fcopy_work, 5*HZ); 2652ef82d24SDexuan Cui fcopy_send_data(); 26601325476SK. Y. Srinivasan return; 26701325476SK. Y. Srinivasan } 26801325476SK. Y. Srinivasan icmsghdr->icflags = ICMSGHDRFLAG_TRANSACTION | ICMSGHDRFLAG_RESPONSE; 26901325476SK. Y. Srinivasan vmbus_sendpacket(channel, recv_buffer, recvlen, requestid, 27001325476SK. Y. Srinivasan VM_PKT_DATA_INBAND, 0); 27101325476SK. Y. Srinivasan } 27201325476SK. Y. Srinivasan 27301325476SK. Y. Srinivasan /* 27401325476SK. Y. Srinivasan * Create a char device that can support read/write for passing 27501325476SK. Y. Srinivasan * the payload. 27601325476SK. Y. Srinivasan */ 27701325476SK. Y. Srinivasan 27801325476SK. Y. Srinivasan static ssize_t fcopy_read(struct file *file, char __user *buf, 27901325476SK. Y. Srinivasan size_t count, loff_t *ppos) 28001325476SK. Y. Srinivasan { 28101325476SK. Y. Srinivasan void *src; 28201325476SK. Y. Srinivasan size_t copy_size; 28301325476SK. Y. Srinivasan int operation; 28401325476SK. Y. Srinivasan 28501325476SK. Y. Srinivasan /* 28601325476SK. Y. Srinivasan * Wait until there is something to be read. 28701325476SK. Y. Srinivasan */ 28801325476SK. Y. Srinivasan if (down_interruptible(&fcopy_transaction.read_sema)) 28901325476SK. Y. Srinivasan return -EINTR; 29001325476SK. Y. Srinivasan 29101325476SK. Y. Srinivasan /* 29201325476SK. Y. Srinivasan * The channel may be rescinded and in this case, we will wakeup the 29301325476SK. Y. Srinivasan * the thread blocked on the semaphore and we will use the opened 29401325476SK. Y. Srinivasan * state to correctly handle this case. 29501325476SK. Y. Srinivasan */ 29601325476SK. Y. Srinivasan if (!opened) 29701325476SK. Y. Srinivasan return -ENODEV; 29801325476SK. Y. Srinivasan 29901325476SK. Y. Srinivasan operation = fcopy_transaction.fcopy_msg->operation; 30001325476SK. Y. Srinivasan 30101325476SK. Y. Srinivasan if (operation == START_FILE_COPY) { 30201325476SK. Y. Srinivasan src = &fcopy_transaction.message; 30301325476SK. Y. Srinivasan copy_size = sizeof(struct hv_start_fcopy); 30401325476SK. Y. Srinivasan if (count < copy_size) 30501325476SK. Y. Srinivasan return 0; 30601325476SK. Y. Srinivasan } else { 30701325476SK. Y. Srinivasan src = fcopy_transaction.fcopy_msg; 30801325476SK. Y. Srinivasan copy_size = sizeof(struct hv_do_fcopy); 30901325476SK. Y. Srinivasan if (count < copy_size) 31001325476SK. Y. Srinivasan return 0; 31101325476SK. Y. Srinivasan } 31201325476SK. Y. Srinivasan if (copy_to_user(buf, src, copy_size)) 31301325476SK. Y. Srinivasan return -EFAULT; 31401325476SK. Y. Srinivasan 31501325476SK. Y. Srinivasan return copy_size; 31601325476SK. Y. Srinivasan } 31701325476SK. Y. Srinivasan 31801325476SK. Y. Srinivasan static ssize_t fcopy_write(struct file *file, const char __user *buf, 31901325476SK. Y. Srinivasan size_t count, loff_t *ppos) 32001325476SK. Y. Srinivasan { 32101325476SK. Y. Srinivasan int response = 0; 32201325476SK. Y. Srinivasan 32301325476SK. Y. Srinivasan if (count != sizeof(int)) 32401325476SK. Y. Srinivasan return -EINVAL; 32501325476SK. Y. Srinivasan 32601325476SK. Y. Srinivasan if (copy_from_user(&response, buf, sizeof(int))) 32701325476SK. Y. Srinivasan return -EFAULT; 32801325476SK. Y. Srinivasan 32901325476SK. Y. Srinivasan if (in_hand_shake) { 33001325476SK. Y. Srinivasan if (fcopy_handle_handshake(response)) 33101325476SK. Y. Srinivasan return -EINVAL; 33201325476SK. Y. Srinivasan return sizeof(int); 33301325476SK. Y. Srinivasan } 33401325476SK. Y. Srinivasan 33501325476SK. Y. Srinivasan /* 33601325476SK. Y. Srinivasan * Complete the transaction by forwarding the result 33701325476SK. Y. Srinivasan * to the host. But first, cancel the timeout. 33801325476SK. Y. Srinivasan */ 339242f3122SVitaly Kuznetsov if (cancel_delayed_work_sync(&fcopy_work)) { 34001325476SK. Y. Srinivasan fcopy_respond_to_host(response); 341242f3122SVitaly Kuznetsov hv_poll_channel(fcopy_transaction.fcopy_context, 342242f3122SVitaly Kuznetsov hv_fcopy_onchannelcallback); 343242f3122SVitaly Kuznetsov } 34401325476SK. Y. Srinivasan 34501325476SK. Y. Srinivasan return sizeof(int); 34601325476SK. Y. Srinivasan } 34701325476SK. Y. Srinivasan 348c765a6dfSFengguang Wu static int fcopy_open(struct inode *inode, struct file *f) 34901325476SK. Y. Srinivasan { 35001325476SK. Y. Srinivasan /* 35101325476SK. Y. Srinivasan * The user level daemon that will open this device is 35201325476SK. Y. Srinivasan * really an extension of this driver. We can have only 35301325476SK. Y. Srinivasan * active open at a time. 35401325476SK. Y. Srinivasan */ 35501325476SK. Y. Srinivasan if (opened) 35601325476SK. Y. Srinivasan return -EBUSY; 35701325476SK. Y. Srinivasan 35801325476SK. Y. Srinivasan /* 35901325476SK. Y. Srinivasan * The daemon is alive; setup the state. 36001325476SK. Y. Srinivasan */ 36101325476SK. Y. Srinivasan opened = true; 36201325476SK. Y. Srinivasan return 0; 36301325476SK. Y. Srinivasan } 36401325476SK. Y. Srinivasan 365d9b16529SDexuan Cui /* XXX: there are still some tricky corner cases, e.g., 366d9b16529SDexuan Cui * 1) In a SMP guest, when fcopy_release() runs between 367d9b16529SDexuan Cui * schedule_delayed_work() and fcopy_send_data(), there is 368d9b16529SDexuan Cui * still a chance an obsolete message will be queued. 369d9b16529SDexuan Cui * 370d9b16529SDexuan Cui * 2) When the fcopy daemon is running, if we unload the driver, 371d9b16529SDexuan Cui * we'll notice a kernel oops when we kill the daemon later. 372d9b16529SDexuan Cui */ 373c765a6dfSFengguang Wu static int fcopy_release(struct inode *inode, struct file *f) 37401325476SK. Y. Srinivasan { 37501325476SK. Y. Srinivasan /* 37601325476SK. Y. Srinivasan * The daemon has exited; reset the state. 37701325476SK. Y. Srinivasan */ 37801325476SK. Y. Srinivasan in_hand_shake = true; 37901325476SK. Y. Srinivasan opened = false; 380d9b16529SDexuan Cui 381d9b16529SDexuan Cui if (cancel_delayed_work_sync(&fcopy_work)) { 382d9b16529SDexuan Cui /* We haven't up()-ed the semaphore(very rare)? */ 383d9b16529SDexuan Cui if (down_trylock(&fcopy_transaction.read_sema)) 384d9b16529SDexuan Cui ; 385d9b16529SDexuan Cui fcopy_respond_to_host(HV_E_FAIL); 386d9b16529SDexuan Cui } 38701325476SK. Y. Srinivasan return 0; 38801325476SK. Y. Srinivasan } 38901325476SK. Y. Srinivasan 39001325476SK. Y. Srinivasan 39101325476SK. Y. Srinivasan static const struct file_operations fcopy_fops = { 39201325476SK. Y. Srinivasan .read = fcopy_read, 39301325476SK. Y. Srinivasan .write = fcopy_write, 39401325476SK. Y. Srinivasan .release = fcopy_release, 39501325476SK. Y. Srinivasan .open = fcopy_open, 39601325476SK. Y. Srinivasan }; 39701325476SK. Y. Srinivasan 39801325476SK. Y. Srinivasan static struct miscdevice fcopy_misc = { 39901325476SK. Y. Srinivasan .minor = MISC_DYNAMIC_MINOR, 40001325476SK. Y. Srinivasan .name = "vmbus/hv_fcopy", 40101325476SK. Y. Srinivasan .fops = &fcopy_fops, 40201325476SK. Y. Srinivasan }; 40301325476SK. Y. Srinivasan 40401325476SK. Y. Srinivasan static int fcopy_dev_init(void) 40501325476SK. Y. Srinivasan { 40601325476SK. Y. Srinivasan return misc_register(&fcopy_misc); 40701325476SK. Y. Srinivasan } 40801325476SK. Y. Srinivasan 40901325476SK. Y. Srinivasan static void fcopy_dev_deinit(void) 41001325476SK. Y. Srinivasan { 41101325476SK. Y. Srinivasan 41201325476SK. Y. Srinivasan /* 41301325476SK. Y. Srinivasan * The device is going away - perhaps because the 41401325476SK. Y. Srinivasan * host has rescinded the channel. Setup state so that 41501325476SK. Y. Srinivasan * user level daemon can gracefully exit if it is blocked 41601325476SK. Y. Srinivasan * on the read semaphore. 41701325476SK. Y. Srinivasan */ 41801325476SK. Y. Srinivasan opened = false; 41901325476SK. Y. Srinivasan /* 42001325476SK. Y. Srinivasan * Signal the semaphore as the device is 42101325476SK. Y. Srinivasan * going away. 42201325476SK. Y. Srinivasan */ 42301325476SK. Y. Srinivasan up(&fcopy_transaction.read_sema); 42401325476SK. Y. Srinivasan misc_deregister(&fcopy_misc); 42501325476SK. Y. Srinivasan } 42601325476SK. Y. Srinivasan 42701325476SK. Y. Srinivasan int hv_fcopy_init(struct hv_util_service *srv) 42801325476SK. Y. Srinivasan { 42901325476SK. Y. Srinivasan recv_buffer = srv->recv_buffer; 43001325476SK. Y. Srinivasan 43101325476SK. Y. Srinivasan /* 43201325476SK. Y. Srinivasan * When this driver loads, the user level daemon that 43301325476SK. Y. Srinivasan * processes the host requests may not yet be running. 43401325476SK. Y. Srinivasan * Defer processing channel callbacks until the daemon 43501325476SK. Y. Srinivasan * has registered. 43601325476SK. Y. Srinivasan */ 43701325476SK. Y. Srinivasan fcopy_transaction.active = true; 43801325476SK. Y. Srinivasan sema_init(&fcopy_transaction.read_sema, 0); 43901325476SK. Y. Srinivasan 44001325476SK. Y. Srinivasan return fcopy_dev_init(); 44101325476SK. Y. Srinivasan } 44201325476SK. Y. Srinivasan 44301325476SK. Y. Srinivasan void hv_fcopy_deinit(void) 44401325476SK. Y. Srinivasan { 44501325476SK. Y. Srinivasan cancel_delayed_work_sync(&fcopy_work); 44601325476SK. Y. Srinivasan fcopy_dev_deinit(); 44701325476SK. Y. Srinivasan } 448