diff --git a/SOURCES/0001-Tools-hv-vss-fix-loop-device-detection.patch b/SOURCES/0001-Tools-hv-vss-fix-loop-device-detection.patch new file mode 100644 index 0000000..3f31b8d --- /dev/null +++ b/SOURCES/0001-Tools-hv-vss-fix-loop-device-detection.patch @@ -0,0 +1,133 @@ +From 60c1606cbb7cc86f963a202c156e56ccdf1b57d9 Mon Sep 17 00:00:00 2001 +From: Vitaly Kuznetsov +Date: Tue, 5 Jun 2018 13:37:56 -0700 +Subject: [PATCH] Tools: hv: vss: fix loop device detection + +Commit ea81fdf0981d ("Tools: hv: vss: Skip freezing filesystems backed by +loop") added skip for filesystems backed by loop device. However, it seems +the detection of such cases is incomplete. + +It was found that with 'devicemapper' storage driver docker creates the +following chain: + +NAME MAJ:MIN +loop0 7:0 +..docker-8:4-8473394-pool 253:0 + ..docker-8:4-8473394-eac... 253:1 + +so when we're looking at the mounted device we see major '253' and not '7'. + +Solve the issue by walking /sys/dev/block/*/slaves chain and checking if +there's a loop device somewhere. + +Other than that, don't skip mountpoints silently when stat() fails. In case +e.g. SELinux is failing stat we don't want to skip freezing everything +without letting user know about the failure. + +Fixes: ea81fdf0981d ("Tools: hv: vss: Skip freezing filesystems backed by loop") +Signed-off-by: Vitaly Kuznetsov +Signed-off-by: K. Y. Srinivasan +--- + tools/hv/hv_vss_daemon.c | 65 +++++++++++++++++++++++++++++++++++++++++++++--- + 1 file changed, 61 insertions(+), 4 deletions(-) + +diff --git a/tools/hv/hv_vss_daemon.c b/tools/hv/hv_vss_daemon.c +index 34031a297f02..b13300172762 100644 +--- a/tools/hv/hv_vss_daemon.c ++++ b/tools/hv/hv_vss_daemon.c +@@ -36,6 +36,8 @@ + #include + #include + #include ++#include ++#include + + /* Don't use syslog() in the function since that can cause write to disk */ + static int vss_do_freeze(char *dir, unsigned int cmd) +@@ -68,6 +70,55 @@ static int vss_do_freeze(char *dir, unsigned int cmd) + return !!ret; + } + ++static bool is_dev_loop(const char *blkname) ++{ ++ char *buffer; ++ DIR *dir; ++ struct dirent *entry; ++ bool ret = false; ++ ++ buffer = malloc(PATH_MAX); ++ if (!buffer) { ++ syslog(LOG_ERR, "Can't allocate memory!"); ++ exit(1); ++ } ++ ++ snprintf(buffer, PATH_MAX, "%s/loop", blkname); ++ if (!access(buffer, R_OK | X_OK)) { ++ ret = true; ++ goto free_buffer; ++ } else if (errno != ENOENT) { ++ syslog(LOG_ERR, "Can't access: %s; error:%d %s!", ++ buffer, errno, strerror(errno)); ++ } ++ ++ snprintf(buffer, PATH_MAX, "%s/slaves", blkname); ++ dir = opendir(buffer); ++ if (!dir) { ++ if (errno != ENOENT) ++ syslog(LOG_ERR, "Can't opendir: %s; error:%d %s!", ++ buffer, errno, strerror(errno)); ++ goto free_buffer; ++ } ++ ++ while ((entry = readdir(dir)) != NULL) { ++ if (strcmp(entry->d_name, ".") == 0 || ++ strcmp(entry->d_name, "..") == 0) ++ continue; ++ ++ snprintf(buffer, PATH_MAX, "%s/slaves/%s", blkname, ++ entry->d_name); ++ if (is_dev_loop(buffer)) { ++ ret = true; ++ break; ++ } ++ } ++ closedir(dir); ++free_buffer: ++ free(buffer); ++ return ret; ++} ++ + static int vss_operate(int operation) + { + char match[] = "/dev/"; +@@ -75,6 +126,7 @@ static int vss_operate(int operation) + struct mntent *ent; + struct stat sb; + char errdir[1024] = {0}; ++ char blkdir[23]; /* /sys/dev/block/XXX:XXX */ + unsigned int cmd; + int error = 0, root_seen = 0, save_errno = 0; + +@@ -96,10 +148,15 @@ static int vss_operate(int operation) + while ((ent = getmntent(mounts))) { + if (strncmp(ent->mnt_fsname, match, strlen(match))) + continue; +- if (stat(ent->mnt_fsname, &sb) == -1) +- continue; +- if (S_ISBLK(sb.st_mode) && major(sb.st_rdev) == LOOP_MAJOR) +- continue; ++ if (stat(ent->mnt_fsname, &sb)) { ++ syslog(LOG_ERR, "Can't stat: %s; error:%d %s!", ++ ent->mnt_fsname, errno, strerror(errno)); ++ } else { ++ sprintf(blkdir, "/sys/dev/block/%d:%d", ++ major(sb.st_rdev), minor(sb.st_rdev)); ++ if (is_dev_loop(blkdir)) ++ continue; ++ } + if (hasmntopt(ent, MNTOPT_RO) != NULL) + continue; + if (strcmp(ent->mnt_type, "vfat") == 0) +-- +2.14.4 + diff --git a/SOURCES/0001-hv-kvp-Avoid-reading-past-allocated-blocks-from-KVP-.patch b/SOURCES/0001-hv-kvp-Avoid-reading-past-allocated-blocks-from-KVP-.patch deleted file mode 100644 index fcabe51..0000000 --- a/SOURCES/0001-hv-kvp-Avoid-reading-past-allocated-blocks-from-KVP-.patch +++ /dev/null @@ -1,141 +0,0 @@ -From 297d6b6e56c2977fc504c61bbeeaa21296923f89 Mon Sep 17 00:00:00 2001 -From: Paul Meyer -Date: Tue, 14 Nov 2017 13:06:47 -0700 -Subject: [PATCH] hv: kvp: Avoid reading past allocated blocks from KVP file - -While reading in more than one block (50) of KVP records, the allocation -goes per block, but the reads used the total number of allocated records -(without resetting the pointer/stream). This causes the records buffer to -overrun when the refresh reads more than one block over the previous -capacity (e.g. reading more than 100 KVP records whereas the in-memory -database was empty before). - -Fix this by reading the correct number of KVP records from file each time. - -Signed-off-by: Paul Meyer -Signed-off-by: Long Li -Cc: stable@vger.kernel.org -Signed-off-by: K. Y. Srinivasan -Signed-off-by: Greg Kroah-Hartman ---- - tools/hv/hv_kvp_daemon.c | 70 ++++++++++-------------------------------------- - 1 file changed, 14 insertions(+), 56 deletions(-) - -diff --git a/tools/hv/hv_kvp_daemon.c b/tools/hv/hv_kvp_daemon.c -index eaa3bec273c8..4c99c57736ce 100644 ---- a/tools/hv/hv_kvp_daemon.c -+++ b/tools/hv/hv_kvp_daemon.c -@@ -193,11 +193,14 @@ static void kvp_update_mem_state(int pool) - for (;;) { - readp = &record[records_read]; - records_read += fread(readp, sizeof(struct kvp_record), -- ENTRIES_PER_BLOCK * num_blocks, -- filep); -+ ENTRIES_PER_BLOCK * num_blocks - records_read, -+ filep); - - if (ferror(filep)) { -- syslog(LOG_ERR, "Failed to read file, pool: %d", pool); -+ syslog(LOG_ERR, -+ "Failed to read file, pool: %d; error: %d %s", -+ pool, errno, strerror(errno)); -+ kvp_release_lock(pool); - exit(EXIT_FAILURE); - } - -@@ -210,6 +213,7 @@ static void kvp_update_mem_state(int pool) - - if (record == NULL) { - syslog(LOG_ERR, "malloc failed"); -+ kvp_release_lock(pool); - exit(EXIT_FAILURE); - } - continue; -@@ -224,15 +228,11 @@ static void kvp_update_mem_state(int pool) - fclose(filep); - kvp_release_lock(pool); - } -+ - static int kvp_file_init(void) - { - int fd; -- FILE *filep; -- size_t records_read; - char *fname; -- struct kvp_record *record; -- struct kvp_record *readp; -- int num_blocks; - int i; - int alloc_unit = sizeof(struct kvp_record) * ENTRIES_PER_BLOCK; - -@@ -246,61 +246,19 @@ static int kvp_file_init(void) - - for (i = 0; i < KVP_POOL_COUNT; i++) { - fname = kvp_file_info[i].fname; -- records_read = 0; -- num_blocks = 1; - sprintf(fname, "%s/.kvp_pool_%d", KVP_CONFIG_LOC, i); - fd = open(fname, O_RDWR | O_CREAT | O_CLOEXEC, 0644 /* rw-r--r-- */); - - if (fd == -1) - return 1; - -- -- filep = fopen(fname, "re"); -- if (!filep) { -- close(fd); -- return 1; -- } -- -- record = malloc(alloc_unit * num_blocks); -- if (record == NULL) { -- fclose(filep); -- close(fd); -- return 1; -- } -- for (;;) { -- readp = &record[records_read]; -- records_read += fread(readp, sizeof(struct kvp_record), -- ENTRIES_PER_BLOCK, -- filep); -- -- if (ferror(filep)) { -- syslog(LOG_ERR, "Failed to read file, pool: %d", -- i); -- exit(EXIT_FAILURE); -- } -- -- if (!feof(filep)) { -- /* -- * We have more data to read. -- */ -- num_blocks++; -- record = realloc(record, alloc_unit * -- num_blocks); -- if (record == NULL) { -- fclose(filep); -- close(fd); -- return 1; -- } -- continue; -- } -- break; -- } - kvp_file_info[i].fd = fd; -- kvp_file_info[i].num_blocks = num_blocks; -- kvp_file_info[i].records = record; -- kvp_file_info[i].num_records = records_read; -- fclose(filep); -- -+ kvp_file_info[i].num_blocks = 1; -+ kvp_file_info[i].records = malloc(alloc_unit); -+ if (kvp_file_info[i].records == NULL) -+ return 1; -+ kvp_file_info[i].num_records = 0; -+ kvp_update_mem_state(i); - } - - return 0; --- -2.14.3 - diff --git a/SOURCES/bondvf.sh b/SOURCES/bondvf.sh deleted file mode 100644 index 4aa5369..0000000 --- a/SOURCES/bondvf.sh +++ /dev/null @@ -1,193 +0,0 @@ -#!/bin/bash - -# This example script creates bonding network devices based on synthetic NIC -# (the virtual network adapter usually provided by Hyper-V) and the matching -# VF NIC (SRIOV virtual function). So the synthetic NIC and VF NIC can -# function as one network device, and fail over to the synthetic NIC if VF is -# down. -# -# Usage: -# - After configured vSwitch and vNIC with SRIOV, start Linux virtual -# machine (VM) -# - Run this scripts on the VM. It will create configuration files in -# distro specific directory. -# - Reboot the VM, so that the bonding config are enabled. -# -# The config files are DHCP by default. You may edit them if you need to change -# to Static IP or change other settings. -# - -sysdir=/sys/class/net -netvsc_cls={f8615163-df3e-46c5-913f-f2d2f965ed0e} -bondcnt=0 - -# Detect Distro -if [ -f /etc/redhat-release ]; -then - cfgdir=/etc/sysconfig/network-scripts - distro=redhat -elif grep -q 'Ubuntu' /etc/issue -then - cfgdir=/etc/network - distro=ubuntu -elif grep -q 'SUSE' /etc/issue -then - cfgdir=/etc/sysconfig/network - distro=suse -else - echo "Unsupported Distro" - exit 1 -fi - -echo Detected Distro: $distro, or compatible - -# Get a list of ethernet names -list_eth=(`cd $sysdir && ls -d */ | cut -d/ -f1 | grep -v bond`) -eth_cnt=${#list_eth[@]} - -echo List of net devices: - -# Get the MAC addresses -for (( i=0; i < $eth_cnt; i++ )) -do - list_mac[$i]=`cat $sysdir/${list_eth[$i]}/address` - echo ${list_eth[$i]}, ${list_mac[$i]} -done - -# Find NIC with matching MAC -for (( i=0; i < $eth_cnt-1; i++ )) -do - for (( j=i+1; j < $eth_cnt; j++ )) - do - if [ "${list_mac[$i]}" = "${list_mac[$j]}" ] - then - list_match[$i]=${list_eth[$j]} - break - fi - done -done - -function create_eth_cfg_redhat { - local fn=$cfgdir/ifcfg-$1 - - rm -f $fn - echo DEVICE=$1 >>$fn - echo TYPE=Ethernet >>$fn - echo BOOTPROTO=none >>$fn - echo UUID=`uuidgen` >>$fn - echo ONBOOT=yes >>$fn - echo PEERDNS=yes >>$fn - echo IPV6INIT=yes >>$fn - echo MASTER=$2 >>$fn - echo SLAVE=yes >>$fn -} - -function create_eth_cfg_pri_redhat { - create_eth_cfg_redhat $1 $2 -} - -function create_bond_cfg_redhat { - local fn=$cfgdir/ifcfg-$1 - - rm -f $fn - echo DEVICE=$1 >>$fn - echo TYPE=Bond >>$fn - echo BOOTPROTO=dhcp >>$fn - echo UUID=`uuidgen` >>$fn - echo ONBOOT=yes >>$fn - echo PEERDNS=yes >>$fn - echo IPV6INIT=yes >>$fn - echo BONDING_MASTER=yes >>$fn - echo BONDING_OPTS=\"mode=active-backup miimon=100 primary=$2\" >>$fn -} - -function create_eth_cfg_ubuntu { - local fn=$cfgdir/interfaces - - echo $'\n'auto $1 >>$fn - echo iface $1 inet manual >>$fn - echo bond-master $2 >>$fn -} - -function create_eth_cfg_pri_ubuntu { - local fn=$cfgdir/interfaces - - create_eth_cfg_ubuntu $1 $2 - echo bond-primary $1 >>$fn -} - -function create_bond_cfg_ubuntu { - local fn=$cfgdir/interfaces - - echo $'\n'auto $1 >>$fn - echo iface $1 inet dhcp >>$fn - echo bond-mode active-backup >>$fn - echo bond-miimon 100 >>$fn - echo bond-slaves none >>$fn -} - -function create_eth_cfg_suse { - local fn=$cfgdir/ifcfg-$1 - - rm -f $fn - echo BOOTPROTO=none >>$fn - echo STARTMODE=auto >>$fn -} - -function create_eth_cfg_pri_suse { - create_eth_cfg_suse $1 -} - -function create_bond_cfg_suse { - local fn=$cfgdir/ifcfg-$1 - - rm -f $fn - echo BOOTPROTO=dhcp >>$fn - echo STARTMODE=auto >>$fn - echo BONDING_MASTER=yes >>$fn - echo BONDING_SLAVE_0=$2 >>$fn - echo BONDING_SLAVE_1=$3 >>$fn - echo BONDING_MODULE_OPTS=\'mode=active-backup miimon=100 primary=$2\' >>$fn -} - -function create_bond { - local bondname=bond$bondcnt - local primary - local secondary - - local class_id1=`cat $sysdir/$1/device/class_id 2>/dev/null` - local class_id2=`cat $sysdir/$2/device/class_id 2>/dev/null` - - if [ "$class_id1" = "$netvsc_cls" ] - then - primary=$2 - secondary=$1 - elif [ "$class_id2" = "$netvsc_cls" ] - then - primary=$1 - secondary=$2 - else - return 0 - fi - - echo $'\nBond name:' $bondname - - echo configuring $primary - create_eth_cfg_pri_$distro $primary $bondname - - echo configuring $secondary - create_eth_cfg_$distro $secondary $bondname - - echo creating: $bondname with primary slave: $primary - create_bond_cfg_$distro $bondname $primary $secondary - - let bondcnt=bondcnt+1 -} - -for (( i=0; i < $eth_cnt-1; i++ )) -do - if [ -n "${list_match[$i]}" ] - then - create_bond ${list_eth[$i]} ${list_match[$i]} - fi -done diff --git a/SOURCES/hv_fcopy_daemon.c b/SOURCES/hv_fcopy_daemon.c index fdc9ca4..d78aed8 100644 --- a/SOURCES/hv_fcopy_daemon.c +++ b/SOURCES/hv_fcopy_daemon.c @@ -18,25 +18,20 @@ #include -#include -#include -#include -#include #include #include #include #include -#include #include #include +#include #include #include #include -#include #include static int target_fd; -static char target_fname[W_MAX_PATH]; +static char target_fname[PATH_MAX]; static unsigned long long filesize; static int hv_start_fcopy(struct hv_start_fcopy *smsg) @@ -145,14 +140,17 @@ void print_usage(char *argv[]) int main(int argc, char *argv[]) { - int fcopy_fd, len; + int fcopy_fd; int error; int daemonize = 1, long_index = 0, opt; int version = FCOPY_CURRENT_VERSION; - char *buffer[4096 * 2]; - struct hv_fcopy_hdr *in_msg; + union { + struct hv_fcopy_hdr hdr; + struct hv_start_fcopy start; + struct hv_do_fcopy copy; + __u32 kernel_modver; + } buffer = { }; int in_handshake = 1; - __u32 kernel_modver; static struct option long_options[] = { {"help", no_argument, 0, 'h' }, @@ -202,32 +200,31 @@ int main(int argc, char *argv[]) * In this loop we process fcopy messages after the * handshake is complete. */ - len = pread(fcopy_fd, buffer, (4096 * 2), 0); + ssize_t len; + + len = pread(fcopy_fd, &buffer, sizeof(buffer), 0); if (len < 0) { syslog(LOG_ERR, "pread failed: %s", strerror(errno)); exit(EXIT_FAILURE); } if (in_handshake) { - if (len != sizeof(kernel_modver)) { + if (len != sizeof(buffer.kernel_modver)) { syslog(LOG_ERR, "invalid version negotiation"); exit(EXIT_FAILURE); } - kernel_modver = *(__u32 *)buffer; in_handshake = 0; - syslog(LOG_INFO, "kernel module version: %d", - kernel_modver); + syslog(LOG_INFO, "kernel module version: %u", + buffer.kernel_modver); continue; } - in_msg = (struct hv_fcopy_hdr *)buffer; - - switch (in_msg->operation) { + switch (buffer.hdr.operation) { case START_FILE_COPY: - error = hv_start_fcopy((struct hv_start_fcopy *)in_msg); + error = hv_start_fcopy(&buffer.start); break; case WRITE_TO_FILE: - error = hv_copy_data((struct hv_do_fcopy *)in_msg); + error = hv_copy_data(&buffer.copy); break; case COMPLETE_FCOPY: error = hv_copy_finished(); @@ -238,7 +235,7 @@ int main(int argc, char *argv[]) default: syslog(LOG_ERR, "Unknown operation: %d", - in_msg->operation); + buffer.hdr.operation); } diff --git a/SOURCES/hv_kvp_daemon.c b/SOURCES/hv_kvp_daemon.c index bc7adb8..dbf6e8b 100644 --- a/SOURCES/hv_kvp_daemon.c +++ b/SOURCES/hv_kvp_daemon.c @@ -22,8 +22,6 @@ */ -#include -#include #include #include #include @@ -34,7 +32,6 @@ #include #include #include -#include #include #include #include @@ -42,6 +39,7 @@ #include #include #include +#include #include /* @@ -96,13 +94,15 @@ static struct utsname uts_buf; #define KVP_CONFIG_LOC "/var/lib/hyperv" +#ifndef KVP_SCRIPTS_PATH +#define KVP_SCRIPTS_PATH "/usr/libexec/hypervkvpd/" +#endif + +#define KVP_NET_DIR "/sys/class/net/" + #define MAX_FILE_NAME 100 #define ENTRIES_PER_BLOCK 50 -#ifndef SOL_NETLINK -#define SOL_NETLINK 270 -#endif - struct kvp_record { char key[HV_KVP_EXCHANGE_MAX_KEY_SIZE]; char value[HV_KVP_EXCHANGE_MAX_VALUE_SIZE]; @@ -193,11 +193,14 @@ static void kvp_update_mem_state(int pool) for (;;) { readp = &record[records_read]; records_read += fread(readp, sizeof(struct kvp_record), - ENTRIES_PER_BLOCK * num_blocks, - filep); + ENTRIES_PER_BLOCK * num_blocks - records_read, + filep); if (ferror(filep)) { - syslog(LOG_ERR, "Failed to read file, pool: %d", pool); + syslog(LOG_ERR, + "Failed to read file, pool: %d; error: %d %s", + pool, errno, strerror(errno)); + kvp_release_lock(pool); exit(EXIT_FAILURE); } @@ -210,6 +213,7 @@ static void kvp_update_mem_state(int pool) if (record == NULL) { syslog(LOG_ERR, "malloc failed"); + kvp_release_lock(pool); exit(EXIT_FAILURE); } continue; @@ -224,15 +228,11 @@ static void kvp_update_mem_state(int pool) fclose(filep); kvp_release_lock(pool); } + static int kvp_file_init(void) { int fd; - FILE *filep; - size_t records_read; char *fname; - struct kvp_record *record; - struct kvp_record *readp; - int num_blocks; int i; int alloc_unit = sizeof(struct kvp_record) * ENTRIES_PER_BLOCK; @@ -246,61 +246,19 @@ static int kvp_file_init(void) for (i = 0; i < KVP_POOL_COUNT; i++) { fname = kvp_file_info[i].fname; - records_read = 0; - num_blocks = 1; sprintf(fname, "%s/.kvp_pool_%d", KVP_CONFIG_LOC, i); fd = open(fname, O_RDWR | O_CREAT | O_CLOEXEC, 0644 /* rw-r--r-- */); if (fd == -1) return 1; - - filep = fopen(fname, "re"); - if (!filep) { - close(fd); - return 1; - } - - record = malloc(alloc_unit * num_blocks); - if (record == NULL) { - fclose(filep); - close(fd); - return 1; - } - for (;;) { - readp = &record[records_read]; - records_read += fread(readp, sizeof(struct kvp_record), - ENTRIES_PER_BLOCK, - filep); - - if (ferror(filep)) { - syslog(LOG_ERR, "Failed to read file, pool: %d", - i); - exit(EXIT_FAILURE); - } - - if (!feof(filep)) { - /* - * We have more data to read. - */ - num_blocks++; - record = realloc(record, alloc_unit * - num_blocks); - if (record == NULL) { - fclose(filep); - close(fd); - return 1; - } - continue; - } - break; - } kvp_file_info[i].fd = fd; - kvp_file_info[i].num_blocks = num_blocks; - kvp_file_info[i].records = record; - kvp_file_info[i].num_records = records_read; - fclose(filep); - + kvp_file_info[i].num_blocks = 1; + kvp_file_info[i].records = malloc(alloc_unit); + if (kvp_file_info[i].records == NULL) + return 1; + kvp_file_info[i].num_records = 0; + kvp_update_mem_state(i); } return 0; @@ -599,26 +557,21 @@ static char *kvp_get_if_name(char *guid) DIR *dir; struct dirent *entry; FILE *file; - char *p, *q, *x; + char *p, *x; char *if_name = NULL; char buf[256]; - char *kvp_net_dir = "/sys/class/net/"; - char dev_id[256]; + char dev_id[PATH_MAX]; - dir = opendir(kvp_net_dir); + dir = opendir(KVP_NET_DIR); if (dir == NULL) return NULL; - snprintf(dev_id, sizeof(dev_id), "%s", kvp_net_dir); - q = dev_id + strlen(kvp_net_dir); - while ((entry = readdir(dir)) != NULL) { /* * Set the state for the next pass. */ - *q = '\0'; - strcat(dev_id, entry->d_name); - strcat(dev_id, "/device/device_id"); + snprintf(dev_id, sizeof(dev_id), "%s%s/device/device_id", + KVP_NET_DIR, entry->d_name); file = fopen(dev_id, "r"); if (file == NULL) @@ -656,12 +609,12 @@ static char *kvp_if_name_to_mac(char *if_name) FILE *file; char *p, *x; char buf[256]; - char addr_file[256]; + char addr_file[PATH_MAX]; unsigned int i; char *mac_addr = NULL; - snprintf(addr_file, sizeof(addr_file), "%s%s%s", "/sys/class/net/", - if_name, "/address"); + snprintf(addr_file, sizeof(addr_file), "%s%s%s", KVP_NET_DIR, + if_name, "/address"); file = fopen(addr_file, "r"); if (file == NULL) @@ -681,70 +634,6 @@ static char *kvp_if_name_to_mac(char *if_name) return mac_addr; } - -/* - * Retrieve the interface name given tha MAC address. - */ - -static char *kvp_mac_to_if_name(char *mac) -{ - DIR *dir; - struct dirent *entry; - FILE *file; - char *p, *q, *x; - char *if_name = NULL; - char buf[256]; - char *kvp_net_dir = "/sys/class/net/"; - char dev_id[256]; - unsigned int i; - - dir = opendir(kvp_net_dir); - if (dir == NULL) - return NULL; - - snprintf(dev_id, sizeof(dev_id), kvp_net_dir); - q = dev_id + strlen(kvp_net_dir); - - while ((entry = readdir(dir)) != NULL) { - /* - * Set the state for the next pass. - */ - *q = '\0'; - - strcat(dev_id, entry->d_name); - strcat(dev_id, "/address"); - - file = fopen(dev_id, "r"); - if (file == NULL) - continue; - - p = fgets(buf, sizeof(buf), file); - if (p) { - x = strchr(p, '\n'); - if (x) - *x = '\0'; - - for (i = 0; i < strlen(p); i++) - p[i] = toupper(p[i]); - - if (!strcmp(p, mac)) { - /* - * Found the MAC match; return the interface - * name. The caller will free the memory. - */ - if_name = strdup(entry->d_name); - fclose(file); - break; - } - } - fclose(file); - } - - closedir(dir); - return if_name; -} - - static void kvp_process_ipconfig_file(char *cmd, char *config_buf, unsigned int len, int element_size, int offset) @@ -825,7 +714,7 @@ static void kvp_get_ipconfig_info(char *if_name, * . */ - sprintf(cmd, "%s", "hv_get_dns_info"); + sprintf(cmd, KVP_SCRIPTS_PATH "%s", "hv_get_dns_info"); /* * Execute the command to gather DNS info. @@ -842,7 +731,7 @@ static void kvp_get_ipconfig_info(char *if_name, * Enabled: DHCP enabled. */ - sprintf(cmd, "%s %s", "hv_get_dhcp_info", if_name); + sprintf(cmd, KVP_SCRIPTS_PATH "%s %s", "hv_get_dhcp_info", if_name); file = popen(cmd, "r"); if (file == NULL) @@ -1050,6 +939,70 @@ getaddr_done: return error; } +/* + * Retrieve the IP given the MAC address. + */ +static int kvp_mac_to_ip(struct hv_kvp_ipaddr_value *kvp_ip_val) +{ + char *mac = (char *)kvp_ip_val->adapter_id; + DIR *dir; + struct dirent *entry; + FILE *file; + char *p, *x; + char *if_name = NULL; + char buf[256]; + char dev_id[PATH_MAX]; + unsigned int i; + int error = HV_E_FAIL; + + dir = opendir(KVP_NET_DIR); + if (dir == NULL) + return HV_E_FAIL; + + while ((entry = readdir(dir)) != NULL) { + /* + * Set the state for the next pass. + */ + snprintf(dev_id, sizeof(dev_id), "%s%s/address", KVP_NET_DIR, + entry->d_name); + + file = fopen(dev_id, "r"); + if (file == NULL) + continue; + + p = fgets(buf, sizeof(buf), file); + fclose(file); + if (!p) + continue; + + x = strchr(p, '\n'); + if (x) + *x = '\0'; + + for (i = 0; i < strlen(p); i++) + p[i] = toupper(p[i]); + + if (strcmp(p, mac)) + continue; + + /* + * Found the MAC match. + * A NIC (e.g. VF) matching the MAC, but without IP, is skipped. + */ + if_name = entry->d_name; + if (!if_name) + continue; + + error = kvp_get_ip_info(0, if_name, KVP_OP_GET_IP_INFO, + kvp_ip_val, MAX_IP_ADDR_SIZE * 2); + + if (!error && strlen((char *)kvp_ip_val->ip_addr)) + break; + } + + closedir(dir); + return error; +} static int expand_ipv6(char *addr, int type) { @@ -1147,7 +1100,7 @@ static int process_ip_string(FILE *f, char *ip_string, int type) int i = 0; int j = 0; char str[256]; - char sub_str[10]; + char sub_str[13]; int offset = 0; memset(addr, 0, sizeof(addr)); @@ -1221,9 +1174,9 @@ static int process_ip_string(FILE *f, char *ip_string, int type) static int kvp_set_ip_info(char *if_name, struct hv_kvp_ipaddr_value *new_val) { int error = 0; - char if_file[128]; + char if_file[PATH_MAX]; FILE *file; - char cmd[512]; + char cmd[PATH_MAX]; char *mac_addr; /* @@ -1348,7 +1301,8 @@ static int kvp_set_ip_info(char *if_name, struct hv_kvp_ipaddr_value *new_val) * invoke the external script to do its magic. */ - snprintf(cmd, sizeof(cmd), "%s %s", "hv_set_ifconfig", if_file); + snprintf(cmd, sizeof(cmd), KVP_SCRIPTS_PATH "%s %s", + "hv_set_ifconfig", if_file); if (system(cmd)) { syslog(LOG_ERR, "Failed to execute cmd '%s'; error: %d %s", cmd, errno, strerror(errno)); @@ -1524,26 +1478,12 @@ int main(int argc, char *argv[]) switch (op) { case KVP_OP_GET_IP_INFO: kvp_ip_val = &hv_msg->body.kvp_ip_val; - if_name = - kvp_mac_to_if_name((char *)kvp_ip_val->adapter_id); - if (if_name == NULL) { - /* - * We could not map the mac address to an - * interface name; return error. - */ - hv_msg->error = HV_E_FAIL; - break; - } - error = kvp_get_ip_info( - 0, if_name, KVP_OP_GET_IP_INFO, - kvp_ip_val, - (MAX_IP_ADDR_SIZE * 2)); + error = kvp_mac_to_ip(kvp_ip_val); if (error) hv_msg->error = error; - free(if_name); break; case KVP_OP_SET_IP_INFO: diff --git a/SOURCES/hv_vss_daemon.c b/SOURCES/hv_vss_daemon.c index e082980..34031a2 100644 --- a/SOURCES/hv_vss_daemon.c +++ b/SOURCES/hv_vss_daemon.c @@ -21,6 +21,8 @@ #include #include #include +#include +#include #include #include #include @@ -30,6 +32,7 @@ #include #include #include +#include #include #include #include @@ -70,6 +73,7 @@ static int vss_operate(int operation) char match[] = "/dev/"; FILE *mounts; struct mntent *ent; + struct stat sb; char errdir[1024] = {0}; unsigned int cmd; int error = 0, root_seen = 0, save_errno = 0; @@ -92,6 +96,10 @@ static int vss_operate(int operation) while ((ent = getmntent(mounts))) { if (strncmp(ent->mnt_fsname, match, strlen(match))) continue; + if (stat(ent->mnt_fsname, &sb) == -1) + continue; + if (S_ISBLK(sb.st_mode) && major(sb.st_rdev) == LOOP_MAJOR) + continue; if (hasmntopt(ent, MNTOPT_RO) != NULL) continue; if (strcmp(ent->mnt_type, "vfat") == 0) @@ -261,7 +269,9 @@ int main(int argc, char *argv[]) if (len != sizeof(struct hv_vss_msg)) { syslog(LOG_ERR, "write failed; error: %d %s", errno, strerror(errno)); - exit(EXIT_FAILURE); + + if (op == VSS_OP_FREEZE) + vss_operate(VSS_OP_THAW); } } diff --git a/SOURCES/hypervkvpd-0-corrected_paths_to_external_scripts.patch b/SOURCES/hypervkvpd-0-corrected_paths_to_external_scripts.patch deleted file mode 100644 index 64463e9..0000000 --- a/SOURCES/hypervkvpd-0-corrected_paths_to_external_scripts.patch +++ /dev/null @@ -1,45 +0,0 @@ -From c8cec9f3f9c34aa824e652a01ae08e7e7a621daa Mon Sep 17 00:00:00 2001 -From: Tomas Hozza -Date: Wed, 26 Sep 2012 10:26:55 +0200 -Subject: [PATCH] Corrected paths to hypervkvpd external scripts. - -Corrected paths to hypervkvpd external scripts, because -they will be located in "/usr/libexec/hypervkvpd". ---- - hv_kvp_daemon.c | 6 +++--- - 1 file changed, 3 insertions(+), 3 deletions(-) - -diff --git a/hv_kvp_daemon.c b/hv_kvp_daemon.c -index 5959aff..3ea3af2 100644 ---- a/hv_kvp_daemon.c -+++ b/hv_kvp_daemon.c -@@ -812,7 +812,7 @@ static void kvp_get_ipconfig_info(char *if_name, - * . - */ - -- sprintf(cmd, "%s", "hv_get_dns_info"); -+ sprintf(cmd, "%s", "/usr/libexec/hypervkvpd/hv_get_dns_info"); - - /* - * Execute the command to gather DNS info. -@@ -829,7 +829,7 @@ static void kvp_get_ipconfig_info(char *if_name, - * Enabled: DHCP enabled. - */ - -- sprintf(cmd, "%s %s", "hv_get_dhcp_info", if_name); -+ sprintf(cmd, "%s %s", "/usr/libexec/hypervkvpd/hv_get_dhcp_info", if_name); - - file = popen(cmd, "r"); - if (file == NULL) -@@ -1331,7 +1331,7 @@ setval_done: - * invoke the external script to do its magic. - */ - -- snprintf(cmd, sizeof(cmd), "%s %s", "hv_set_ifconfig", if_file); -+ snprintf(cmd, sizeof(cmd), "%s %s", "/usr/libexec/hypervkvpd/hv_set_ifconfig", if_file); - if (system(cmd)) { - syslog(LOG_ERR, "Failed to execute cmd '%s'; error: %d %s", - cmd, errno, strerror(errno)); --- -1.7.11.4 - diff --git a/SOURCES/hypervkvpd-0-long_file_names_from_readdir.patch b/SOURCES/hypervkvpd-0-long_file_names_from_readdir.patch deleted file mode 100644 index 8808d81..0000000 --- a/SOURCES/hypervkvpd-0-long_file_names_from_readdir.patch +++ /dev/null @@ -1,45 +0,0 @@ -diff --git a/hv_kvp_daemon.c b/hv_kvp_daemon.c -old mode 100644 -new mode 100755 -index 408bb07..c106498 ---- a/hv_kvp_daemon.c -+++ b/hv_kvp_daemon.c -@@ -44,6 +44,7 @@ - #include - #include - #include -+#include - - /* - * KVP protocol: The user mode component first registers with the -@@ -601,26 +602,22 @@ static char *kvp_get_if_name(char *guid) - DIR *dir; - struct dirent *entry; - FILE *file; -- char *p, *q, *x; -+ char *p, *x; - char *if_name = NULL; - char buf[256]; - char *kvp_net_dir = "/sys/class/net/"; -- char dev_id[256]; -+ char dev_id[PATH_MAX]; - - dir = opendir(kvp_net_dir); - if (dir == NULL) - return NULL; - -- snprintf(dev_id, sizeof(dev_id), "%s", kvp_net_dir); -- q = dev_id + strlen(kvp_net_dir); -- - while ((entry = readdir(dir)) != NULL) { - /* - * Set the state for the next pass. - */ -- *q = '\0'; -- strcat(dev_id, entry->d_name); -- strcat(dev_id, "/device/device_id"); -+ snprintf(dev_id, sizeof(dev_id), "%s%s/device/device_id", kvp_net_dir, -+ entry->d_name); - - file = fopen(dev_id, "r"); - if (file == NULL) diff --git a/SOURCES/lsvmbus b/SOURCES/lsvmbus index e8fecd6..353e567 100644 --- a/SOURCES/lsvmbus +++ b/SOURCES/lsvmbus @@ -1,4 +1,5 @@ #!/usr/bin/env python +# SPDX-License-Identifier: GPL-2.0 import os from optparse import OptionParser diff --git a/SPECS/hyperv-daemons.spec b/SPECS/hyperv-daemons.spec index ebbbf31..7984c08 100644 --- a/SPECS/hyperv-daemons.spec +++ b/SPECS/hyperv-daemons.spec @@ -5,7 +5,7 @@ # HyperV FCOPY daemon binary name %global hv_fcopy_daemon hypervfcopyd # snapshot version -%global snapver .20161211git +%global snapver .20180415git # use hardened build %global _hardened_build 1 # udev rules prefix @@ -13,16 +13,14 @@ Name: hyperv-daemons Version: 0 -Release: 0.32%{?snapver}%{?dist} +Release: 0.34%{?snapver}%{?dist} Summary: HyperV daemons suite Group: System Environment/Daemons License: GPLv2 URL: http://www.kernel.org -# Source files obtained from kernel upstream v4.9. -# git://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git -# The daemon and scripts are located in "master branch - /tools/hv" +# Source files obtained from kernel upstream v4.17-rc1 Source0: COPYING # HYPERV KVP DAEMON @@ -45,15 +43,9 @@ Source202: hypervfcopy.rules # HYPERV TOOLS Source301: lsvmbus -Source302: bondvf.sh -# HYPERV KVP DAEMON -# Correct paths to external scripts ("/usr/libexec/hypervkvpd"). -Patch0: hypervkvpd-0-corrected_paths_to_external_scripts.patch -# rhbz#872566 -Patch1: hypervkvpd-0-long_file_names_from_readdir.patch -# rhbz#1529745 -Patch2: 0001-hv-kvp-Avoid-reading-past-allocated-blocks-from-KVP-.patch +# rhbz#1577692 +Patch1: 0001-Tools-hv-vss-fix-loop-device-detection.patch BuildRoot: %{_tmppath}/%{name}-%{version}-%{release}-root-%(%{__id_u} -n) # HyperV is available only on x86 architectures @@ -94,6 +86,7 @@ BuildRequires: systemd, kernel-headers Requires(post): systemd Requires(preun): systemd Requires(postun): systemd +Conflicts: selinux-policy < 3.13.1-197.el7 %description -n hypervvssd Hypervvssd is an implementation of HyperV VSS functionality @@ -154,9 +147,7 @@ cp -pvL %{SOURCE101} hypervvssd.service cp -pvL %{SOURCE200} hv_fcopy_daemon.c cp -pvL %{SOURCE201} hypervfcopyd.service -%patch0 -p1 -b .external_scripts -%patch1 -p1 -b .long_names -%patch2 -p3 -b .kvp_past_allocated +%patch1 -p3 -b .vss_fix_loop_detect %build # HYPERV KVP DAEMON @@ -219,7 +210,6 @@ mkdir -p %{buildroot}%{_sharedstatedir}/hyperv install -p -m 0755 %{SOURCE301} %{buildroot}%{_sbindir}/ mkdir -p %{buildroot}%{_datarootdir}/hyperv-tools/ -install -p -m 0755 %{SOURCE302} %{buildroot}%{_datarootdir}/hyperv-tools/ %post -n hypervkvpd if [ $1 -gt 1 ] ; then @@ -294,6 +284,13 @@ fi %{_datarootdir}/hyperv-tools %changelog +* Mon Jun 18 2018 Vitaly Kuznetsov - 0-0.34.20180415git +- Skip freezing filesystems backed by loop upstream patches (#1577692) + +* Thu Apr 19 2018 2018 Vitaly Kuznetsov - 0-0.33.20180415git +- Update to upstream v4.17-rc1, drop no longer needed bondvf.sh script +- Fix KVP with SR-IOV (#1567022) + * Wed Jan 03 2018 Vitaly Kuznetsov - 0-0.32.20161211git - Include 'Avoid reading past allocated blocks from KVP file' fix (#1529745)