Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

Tools: hv: vss: use misc char device to communicate with kernel

Use /dev/vmbus/hv_vss instead of netlink.

Signed-off-by: Vitaly Kuznetsov <vkuznets@redhat.com>
Tested-by: Alex Ng <alexng@microsoft.com>
Signed-off-by: K. Y. Srinivasan <kys@microsoft.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>

authored by

Vitaly Kuznetsov and committed by
Greg Kroah-Hartman
f5722b9b 8ddca808

+25 -114
+25 -114
tools/hv/hv_vss_daemon.c
··· 19 19 20 20 21 21 #include <sys/types.h> 22 - #include <sys/socket.h> 23 22 #include <sys/poll.h> 24 23 #include <sys/ioctl.h> 25 24 #include <fcntl.h> ··· 29 30 #include <string.h> 30 31 #include <ctype.h> 31 32 #include <errno.h> 32 - #include <arpa/inet.h> 33 33 #include <linux/fs.h> 34 - #include <linux/connector.h> 35 34 #include <linux/hyperv.h> 36 - #include <linux/netlink.h> 37 35 #include <syslog.h> 38 36 #include <getopt.h> 39 - 40 - static struct sockaddr_nl addr; 41 - 42 - #ifndef SOL_NETLINK 43 - #define SOL_NETLINK 270 44 - #endif 45 - 46 37 47 38 /* Don't use syslog() in the function since that can cause write to disk */ 48 39 static int vss_do_freeze(char *dir, unsigned int cmd) ··· 132 143 return error; 133 144 } 134 145 135 - static int netlink_send(int fd, struct cn_msg *msg) 136 - { 137 - struct nlmsghdr nlh = { .nlmsg_type = NLMSG_DONE }; 138 - unsigned int size; 139 - struct msghdr message; 140 - struct iovec iov[2]; 141 - 142 - size = sizeof(struct cn_msg) + msg->len; 143 - 144 - nlh.nlmsg_pid = getpid(); 145 - nlh.nlmsg_len = NLMSG_LENGTH(size); 146 - 147 - iov[0].iov_base = &nlh; 148 - iov[0].iov_len = sizeof(nlh); 149 - 150 - iov[1].iov_base = msg; 151 - iov[1].iov_len = size; 152 - 153 - memset(&message, 0, sizeof(message)); 154 - message.msg_name = &addr; 155 - message.msg_namelen = sizeof(addr); 156 - message.msg_iov = iov; 157 - message.msg_iovlen = 2; 158 - 159 - return sendmsg(fd, &message, 0); 160 - } 161 - 162 146 void print_usage(char *argv[]) 163 147 { 164 148 fprintf(stderr, "Usage: %s [options]\n" ··· 142 180 143 181 int main(int argc, char *argv[]) 144 182 { 145 - int fd, len, nl_group; 183 + int vss_fd, len; 146 184 int error; 147 - struct cn_msg *message; 148 185 struct pollfd pfd; 149 - struct nlmsghdr *incoming_msg; 150 - struct cn_msg *incoming_cn_msg; 151 186 int op; 152 - struct hv_vss_msg *vss_msg; 153 - char *vss_recv_buffer; 154 - size_t vss_recv_buffer_len; 187 + struct hv_vss_msg vss_msg[1]; 155 188 int daemonize = 1, long_index = 0, opt; 156 189 157 190 static struct option long_options[] = { ··· 174 217 openlog("Hyper-V VSS", 0, LOG_USER); 175 218 syslog(LOG_INFO, "VSS starting; pid is:%d", getpid()); 176 219 177 - vss_recv_buffer_len = NLMSG_LENGTH(0) + sizeof(struct cn_msg) + sizeof(struct hv_vss_msg); 178 - vss_recv_buffer = calloc(1, vss_recv_buffer_len); 179 - if (!vss_recv_buffer) { 180 - syslog(LOG_ERR, "Failed to allocate netlink buffers"); 181 - exit(EXIT_FAILURE); 182 - } 183 - 184 - fd = socket(AF_NETLINK, SOCK_DGRAM, NETLINK_CONNECTOR); 185 - if (fd < 0) { 186 - syslog(LOG_ERR, "netlink socket creation failed; error:%d %s", 187 - errno, strerror(errno)); 188 - exit(EXIT_FAILURE); 189 - } 190 - addr.nl_family = AF_NETLINK; 191 - addr.nl_pad = 0; 192 - addr.nl_pid = 0; 193 - addr.nl_groups = 0; 194 - 195 - 196 - error = bind(fd, (struct sockaddr *)&addr, sizeof(addr)); 197 - if (error < 0) { 198 - syslog(LOG_ERR, "bind failed; error:%d %s", errno, strerror(errno)); 199 - close(fd); 200 - exit(EXIT_FAILURE); 201 - } 202 - nl_group = CN_VSS_IDX; 203 - if (setsockopt(fd, SOL_NETLINK, NETLINK_ADD_MEMBERSHIP, &nl_group, sizeof(nl_group)) < 0) { 204 - syslog(LOG_ERR, "setsockopt failed; error:%d %s", errno, strerror(errno)); 205 - close(fd); 220 + vss_fd = open("/dev/vmbus/hv_vss", O_RDWR); 221 + if (vss_fd < 0) { 222 + syslog(LOG_ERR, "open /dev/vmbus/hv_vss failed; error: %d %s", 223 + errno, strerror(errno)); 206 224 exit(EXIT_FAILURE); 207 225 } 208 226 /* 209 227 * Register ourselves with the kernel. 210 228 */ 211 - message = (struct cn_msg *)vss_recv_buffer; 212 - message->id.idx = CN_VSS_IDX; 213 - message->id.val = CN_VSS_VAL; 214 - message->ack = 0; 215 - vss_msg = (struct hv_vss_msg *)message->data; 216 - vss_msg->vss_hdr.operation = VSS_OP_REGISTER; 229 + vss_msg->vss_hdr.operation = VSS_OP_REGISTER1; 217 230 218 - message->len = sizeof(struct hv_vss_msg); 219 - 220 - len = netlink_send(fd, message); 231 + len = write(vss_fd, vss_msg, sizeof(struct hv_vss_msg)); 221 232 if (len < 0) { 222 - syslog(LOG_ERR, "netlink_send failed; error:%d %s", errno, strerror(errno)); 223 - close(fd); 233 + syslog(LOG_ERR, "registration to kernel failed; error: %d %s", 234 + errno, strerror(errno)); 235 + close(vss_fd); 224 236 exit(EXIT_FAILURE); 225 237 } 226 238 227 - pfd.fd = fd; 239 + pfd.fd = vss_fd; 228 240 229 241 while (1) { 230 - struct sockaddr *addr_p = (struct sockaddr *) &addr; 231 - socklen_t addr_l = sizeof(addr); 232 242 pfd.events = POLLIN; 233 243 pfd.revents = 0; 234 244 235 245 if (poll(&pfd, 1, -1) < 0) { 236 246 syslog(LOG_ERR, "poll failed; error:%d %s", errno, strerror(errno)); 237 247 if (errno == EINVAL) { 238 - close(fd); 248 + close(vss_fd); 239 249 exit(EXIT_FAILURE); 240 250 } 241 251 else 242 252 continue; 243 253 } 244 254 245 - len = recvfrom(fd, vss_recv_buffer, vss_recv_buffer_len, 0, 246 - addr_p, &addr_l); 255 + len = read(vss_fd, vss_msg, sizeof(struct hv_vss_msg)); 247 256 248 - if (len < 0) { 249 - syslog(LOG_ERR, "recvfrom failed; pid:%u error:%d %s", 250 - addr.nl_pid, errno, strerror(errno)); 251 - close(fd); 252 - return -1; 257 + if (len != sizeof(struct hv_vss_msg)) { 258 + syslog(LOG_ERR, "read failed; error:%d %s", 259 + errno, strerror(errno)); 260 + close(vss_fd); 261 + return EXIT_FAILURE; 253 262 } 254 263 255 - if (addr.nl_pid) { 256 - syslog(LOG_WARNING, 257 - "Received packet from untrusted pid:%u", 258 - addr.nl_pid); 259 - continue; 260 - } 261 - 262 - incoming_msg = (struct nlmsghdr *)vss_recv_buffer; 263 - 264 - if (incoming_msg->nlmsg_type != NLMSG_DONE) 265 - continue; 266 - 267 - incoming_cn_msg = (struct cn_msg *)NLMSG_DATA(incoming_msg); 268 - vss_msg = (struct hv_vss_msg *)incoming_cn_msg->data; 269 264 op = vss_msg->vss_hdr.operation; 270 265 error = HV_S_OK; 271 266 ··· 240 331 syslog(LOG_ERR, "Illegal op:%d\n", op); 241 332 } 242 333 vss_msg->error = error; 243 - len = netlink_send(fd, incoming_cn_msg); 244 - if (len < 0) { 245 - syslog(LOG_ERR, "net_link send failed; error:%d %s", 246 - errno, strerror(errno)); 334 + len = write(vss_fd, &error, sizeof(struct hv_vss_msg)); 335 + if (len != sizeof(struct hv_vss_msg)) { 336 + syslog(LOG_ERR, "write failed; error: %d %s", errno, 337 + strerror(errno)); 247 338 exit(EXIT_FAILURE); 248 339 } 249 340 } 250 341 342 + close(vss_fd); 343 + exit(0); 251 344 }