diff -Nru powerpc-utils-1.3.1/debian/changelog powerpc-utils-1.3.1/debian/changelog --- powerpc-utils-1.3.1/debian/changelog 2017-01-15 02:57:24.000000000 +0000 +++ powerpc-utils-1.3.1/debian/changelog 2017-06-09 14:39:15.000000000 +0000 @@ -1,3 +1,14 @@ +powerpc-utils (1.3.1-2ubuntu0.3) xenial; urgency=medium + + * d/p/Improve-perf-of-drmgr-lsslot-with-large-num-of-virt.patch: + Fix scaling with large number of virtual adapters. LP: #1692837 + * d/p/drmgr-Stale-errno-usage-corrections.patch, + d/p/drmgr-Correct-errno-usage-use-in-validate_paltform.patch, + d/p/drmgr-Correct-errno-usage-in-init_cpu_info.patch: + Fix failures during scale-up test on Novalink System. LP: #1696434 + + -- Breno Leitao Fri, 09 Jun 2017 10:39:15 -0400 + powerpc-utils (1.3.1-2ubuntu0.2) xenial; urgency=medium * d/p/0001-errinjct-Correct-config_addr-parsing.patch, diff -Nru powerpc-utils-1.3.1/debian/patches/drmgr-Correct-errno-usage-in-init_cpu_info.patch powerpc-utils-1.3.1/debian/patches/drmgr-Correct-errno-usage-in-init_cpu_info.patch --- powerpc-utils-1.3.1/debian/patches/drmgr-Correct-errno-usage-in-init_cpu_info.patch 1970-01-01 00:00:00.000000000 +0000 +++ powerpc-utils-1.3.1/debian/patches/drmgr-Correct-errno-usage-in-init_cpu_info.patch 2017-06-09 14:39:15.000000000 +0000 @@ -0,0 +1,34 @@ +From 1c5319c76ae8b378bfd59e8c0a08e89f83867dbf Mon Sep 17 00:00:00 2001 +From: Nathan Fontenot +Date: Wed, 7 Jun 2017 16:35:33 -0400 +Subject: [PATCH 3/4] drmgr: Correct errno usage in init_cpu_info() + +The error message reported if allocaing a dr node fails +should not report the errno value. The call to allocate the +dr node makes multiple syscalls and there is no way to +determine which one last updated errno. + +Signed-off-by: Nathan Fontenot +Reviewed-by: Paul Clarke +Signed-off-by: Tyrel Datwyler +--- + src/drmgr/common_cpu.c | 3 +-- + 1 file changed, 1 insertion(+), 2 deletions(-) + +diff --git a/src/drmgr/common_cpu.c b/src/drmgr/common_cpu.c +index c3caced..4fba881 100644 +--- a/src/drmgr/common_cpu.c ++++ b/src/drmgr/common_cpu.c +@@ -304,8 +304,7 @@ init_cpu_info(struct dr_info *dr_info) + for (drc = drc_list; drc; drc = drc->next) { + cpu = alloc_dr_node(drc, CPU_DEV, NULL); + if (cpu == NULL) { +- say(ERROR, "Could not allocate CPU node structure: " +- "%s\n", strerror(errno)); ++ say(ERROR, "Could not allocate CPU node structure\n"); + free_node(cpu_list); + return -1; + } +-- +2.7.4 + diff -Nru powerpc-utils-1.3.1/debian/patches/drmgr-Correct-errno-usage-use-in-validate_paltform.patch powerpc-utils-1.3.1/debian/patches/drmgr-Correct-errno-usage-use-in-validate_paltform.patch --- powerpc-utils-1.3.1/debian/patches/drmgr-Correct-errno-usage-use-in-validate_paltform.patch 1970-01-01 00:00:00.000000000 +0000 +++ powerpc-utils-1.3.1/debian/patches/drmgr-Correct-errno-usage-use-in-validate_paltform.patch 2017-06-09 14:39:15.000000000 +0000 @@ -0,0 +1,34 @@ +From 998933a5185f9c56d1d6bce77301f3e7be6a54cf Mon Sep 17 00:00:00 2001 +From: Nathan Fontenot +Date: Wed, 7 Jun 2017 16:35:28 -0400 +Subject: [PATCH 2/4] drmgr: Correct errno usage use in validate_paltform() + +For validate_platform(), the call to get_property makes many +system calls and there is no way to know what last updated the +errno value. This patch drops the output of strerror() due to +this reason. + +Signed-off-by: Nathan Fontenot +Reviewed-by: Paul Clarke +Signed-off-by: Tyrel Datwyler +--- + src/drmgr/common.c | 3 +-- + 1 file changed, 1 insertion(+), 2 deletions(-) + +diff --git a/src/drmgr/common.c b/src/drmgr/common.c +index 87e5e63..f91ad82 100644 +--- a/src/drmgr/common.c ++++ b/src/drmgr/common.c +@@ -1024,8 +1024,7 @@ valid_platform(const char *platform) + + rc = get_property(OFDT_BASE, "device_type", buf, 128); + if (rc) { +- say(ERROR, "Cannot open %s: %s\n", PLATFORMPATH, +- strerror(errno)); ++ say(ERROR, "Cannot validate platform %s\n", platform); + return 0; + } + +-- +2.7.4 + diff -Nru powerpc-utils-1.3.1/debian/patches/drmgr-Stale-errno-usage-corrections.patch powerpc-utils-1.3.1/debian/patches/drmgr-Stale-errno-usage-corrections.patch --- powerpc-utils-1.3.1/debian/patches/drmgr-Stale-errno-usage-corrections.patch 1970-01-01 00:00:00.000000000 +0000 +++ powerpc-utils-1.3.1/debian/patches/drmgr-Stale-errno-usage-corrections.patch 2017-06-09 14:39:15.000000000 +0000 @@ -0,0 +1,282 @@ +From d1c6662d38adeb98a1fd8906cd54031c6fdd653d Mon Sep 17 00:00:00 2001 +From: Nathan Fontenot +Date: Wed, 7 Jun 2017 16:35:22 -0400 +Subject: [PATCH 1/4] drmgr: Stale errno usage corrections + +Several places in the drmgr code use a stale value of errno either +as a return code or when printing an error message. A common example +of this is calling the say() routine and then returning the value of +errno. The say() routine makes several system calls and the value of +errno after a call to say() no longer reflects the original errno +value. + +Several places in the drmgr code were updated to properly handle +the return codes from functions such as write() or open() where we +should be checking for rc == -1 instead of rc <= 0. This does make +a difference as errno won't be set for rc == 0. + +Note that partial write return codes are not really handled in the +drmgr code. The drmgr command is writing to sysfs and /proc +files where we know that they will either return success or +failure and set errno, no partial writes. + +Signed-off-by: Nathan Fontenot +Reviewed-by: Paul Clarke +Signed-off-by: Tyrel Datwyler +--- + src/drmgr/common.c | 36 ++++++++++++++++++------------------ + src/drmgr/common_pci.c | 35 ++++++++++++++++++++++++----------- + src/drmgr/drmig_chrp_pmig.c | 11 ++++++----- + src/drmgr/drslot_chrp_hea.c | 5 ++++- + src/drmgr/drslot_chrp_mem.c | 9 ++++++--- + 5 files changed, 58 insertions(+), 38 deletions(-) + +Index: powerpc-utils-1.3.1/src/drmgr/common.c +=================================================================== +--- powerpc-utils-1.3.1.orig/src/drmgr/common.c ++++ powerpc-utils-1.3.1/src/drmgr/common.c +@@ -300,7 +300,6 @@ + struct flock dr_lock_info; + int rc; + mode_t old_mode; +- int first_try = 1; + + old_mode = umask(0); + dr_lock_fd = open(DR_LOCK_FILE, O_RDWR | O_CREAT, +@@ -315,21 +314,18 @@ + dr_lock_info.l_len = 0; + + do { +- if (!first_try) { +- sleep(1); +- first_try = 0; +- } +- + rc = fcntl(dr_lock_fd, F_SETLK, &dr_lock_info); +- if (rc != -1) ++ if (rc == 0) + return 0; + +- if (drmgr_timed_out()) ++ /* lock may be held by another process */ ++ if (errno != EACCES && errno != EAGAIN) + break; + +- if (rc == -1 && errno == EACCES) +- continue; ++ if (drmgr_timed_out()) ++ break; + ++ sleep(1); + } while (1); + + close(dr_lock_fd); +@@ -459,11 +455,11 @@ + say(DEBUG, "ofdt update: %s\n", buf); + + fd = open(OFDTPATH, O_WRONLY); +- if (fd <= 0) { ++ if (fd == -1) { + say(ERROR, "Failed to open %s: %s\n", OFDTPATH, + strerror(errno)); + free(buf); +- return errno; ++ return -1; + } + + rc = write(fd, buf, bufsize); +@@ -508,10 +504,10 @@ + cmdlen = strlen(buf); + + fd = open(OFDTPATH, O_WRONLY); +- if (fd <= 0) { ++ if (fd == -1) { + say(ERROR, "Failed to open %s: %s\n", OFDTPATH, + strerror(errno)); +- return errno; ++ return -1; + } + + rc = write(fd, buf, cmdlen); +@@ -659,10 +655,10 @@ + say(DEBUG, "Updating OF property\n"); + + fd = open(OFDTPATH, O_WRONLY); +- if (fd <= 0) { ++ if (fd == -1) { + say(ERROR, "Failed to open %s: %s\n", OFDTPATH, + strerror(errno)); +- return errno; ++ return -1; + } + + rc = write(fd, buf, len); +Index: powerpc-utils-1.3.1/src/drmgr/common_pci.c +=================================================================== +--- powerpc-utils-1.3.1.orig/src/drmgr/common_pci.c ++++ powerpc-utils-1.3.1/src/drmgr/common_pci.c +@@ -1308,6 +1308,7 @@ + { + int rc = 0, len; + FILE *file; ++ int my_errno; + + len = strlen(drc_name); + say(DEBUG, "performing kernel op for %s, file is %s\n", drc_name, +@@ -1320,25 +1321,37 @@ + if (file == NULL) { + say(ERROR, "failed to open %s: %s\n", interface_file, + strerror(errno)); +- return -ENODEV; ++ return -1; + } + + rc = fwrite(drc_name, 1, len, file); ++ my_errno = errno; + fclose(file); + +- sleep(1); +- if (drmgr_timed_out()) +- return -1; +- } while (errno == EBUSY); ++ /* Success, note we do fwrite with the values ++ * size = 1 and nitems = len. ++ */ ++ if (rc == len) ++ return 0; ++ ++ /* We should continue trying the kernel op if we get EBUSY, ++ * this would indicate the add/remove operation has not ++ * completed. ++ */ ++ if (my_errno != EBUSY) { ++ say(ERROR, "kernel I/O op failed, %s\n", ++ my_errno ? strerror(my_errno) ++ : "incomplete write"); ++ break; ++ } + +- if (errno || (rc != len)) { +- say(ERROR, "kernel I/O op failed, rc = %d len = %d.\n%s\n", +- rc, len, strerror(errno)); ++ sleep(1); + +- return errno ? errno : rc; +- } ++ if (drmgr_timed_out()) ++ break; ++ } while (1); + +- return 0; ++ return -1; + } + + int dlpar_remove_slot(const char *drc_name) +Index: powerpc-utils-1.3.1/src/drmgr/drmig_chrp_pmig.c +=================================================================== +--- powerpc-utils-1.3.1.orig/src/drmgr/drmig_chrp_pmig.c ++++ powerpc-utils-1.3.1/src/drmgr/drmig_chrp_pmig.c +@@ -199,11 +199,10 @@ + int i, fd; + + fd = open(OFDTPATH, O_WRONLY); +- if (fd <= 0) { ++ if (fd == -1) { + say(ERROR, "Failed to open %s: %s\n", OFDTPATH, + strerror(errno)); +- rc = errno; +- return rc; ++ return -1; + } + + say(DEBUG, "len %d\n", len); +@@ -612,8 +611,9 @@ + + rc = write(fd, buf, strlen(buf)); + if (rc < 0) { ++ int my_errno = errno; + say(DEBUG, "Write to migration file failed with rc: %d\n", rc); +- rc = errno; ++ rc = my_errno; + } else if (rc > 0) + rc = 0; + +@@ -646,9 +646,10 @@ + + rc = write(fd, buf, strlen(buf)); + if (rc < 0) { ++ int my_errno = errno; + say(DEBUG, "Write to hibernation file failed with rc: %d\n", + rc); +- rc = errno; ++ rc = my_errno; + } else if (rc > 0) + rc = 0; + close(fd); +Index: powerpc-utils-1.3.1/src/drmgr/drslot_chrp_hea.c +=================================================================== +--- powerpc-utils-1.3.1.orig/src/drmgr/drslot_chrp_hea.c ++++ powerpc-utils-1.3.1/src/drmgr/drslot_chrp_hea.c +@@ -56,6 +56,7 @@ + { + int rc, len; + FILE *file; ++ int my_errno; + + file = fopen(fname, "w"); + if (file == NULL) { +@@ -65,11 +66,13 @@ + + len = strlen(name); + rc = fwrite(name, 1, len, file); ++ my_errno = errno; + fclose(file); + + rc = (rc >= 0) ? 0 : rc; + if (rc) +- say(ERROR, "Write to %s failed:\n%s\n", fname, strerror(errno)); ++ say(ERROR, "Write to %s failed:\n%s\n", fname, ++ strerror(my_errno)); + + return rc; + } +Index: powerpc-utils-1.3.1/src/drmgr/drslot_chrp_mem.c +=================================================================== +--- powerpc-utils-1.3.1.orig/src/drmgr/drslot_chrp_mem.c ++++ powerpc-utils-1.3.1/src/drmgr/drslot_chrp_mem.c +@@ -864,6 +864,7 @@ + int rc = 0; + time_t t; + char tbuf[128]; ++ int my_errno; + + time(&t); + strftime(tbuf, 128, "%T", localtime(&t)); +@@ -881,11 +882,12 @@ + } + + rc = write(file, state_strs[state], strlen(state_strs[state])); ++ my_errno = errno; + close(file); + + if (rc < 0) { + say(ERROR, "Could not write to %s to %s memory\n\t%s\n", +- path, state_strs[state], strerror(errno)); ++ path, state_strs[state], strerror(my_errno)); + return rc; + } + +@@ -921,10 +923,11 @@ + int rc = 0; + + probe_file = open(MEM_PROBE_FILE, O_WRONLY); +- if (probe_file <= 0) { ++ if (probe_file == -1) { ++ int my_errno = errno; + say(DEBUG, "Could not open %s to probe memory\n", + MEM_PROBE_FILE); +- return errno; ++ return my_errno; + } + + for (scn = lmb->lmb_mem_scns; scn; scn = scn->next) { diff -Nru powerpc-utils-1.3.1/debian/patches/Improve-perf-of-drmgr-lsslot-with-large-num-of-virt.patch powerpc-utils-1.3.1/debian/patches/Improve-perf-of-drmgr-lsslot-with-large-num-of-virt.patch --- powerpc-utils-1.3.1/debian/patches/Improve-perf-of-drmgr-lsslot-with-large-num-of-virt.patch 1970-01-01 00:00:00.000000000 +0000 +++ powerpc-utils-1.3.1/debian/patches/Improve-perf-of-drmgr-lsslot-with-large-num-of-virt.patch 2017-06-09 14:39:15.000000000 +0000 @@ -0,0 +1,210 @@ +From 6464f8e96228f7db355f08f270ada1104c3562c3 Mon Sep 17 00:00:00 2001 +From: Amartey Pearson +Date: Tue, 16 May 2017 14:01:30 -0500 +Subject: [PATCH] Improve perf of drmgr/lsslot with large num of virt. dev. + +The current algorithm for add_pci_vio_node walks the vdevice bus +for every theoretical DRC (1000's of times). The more vdevices +you have populated, the worse this algorithm becomes. On a system +with 450 devices, this can take over 30 seconds for example. + +This modifies the algorithm to populate a node list of existing +devices (so walks the tree just once), and then uses these nodes +when populating the full list instead of walking the device tree +for each one. + +NOTE: This only is changed for virtual devices - a system with +large numbers of PCI devices will not be optimized, but that is +less of a concern. + +Signed-off-by: Amartey Pearson +Signed-off-by: Bryant G. Ly +[tyreld: changed my_drc_index type from u32 to uint32_t] +Signed-off-by: Tyrel Datwyler +--- + src/drmgr/common_pci.c | 139 +++++++++++++++++++++++++++++++++++++++++++++---- + 1 file changed, 128 insertions(+), 11 deletions(-) + +diff --git a/src/drmgr/common_pci.c b/src/drmgr/common_pci.c +index 441dbd0..1a982db 100644 +--- a/src/drmgr/common_pci.c ++++ b/src/drmgr/common_pci.c +@@ -381,6 +381,83 @@ init_node(struct dr_node *node) + return rc; + } + ++/** ++ * create_vio_nodes ++ * Creates a set of dr_nodes for any existing vio nodes in the supplied path. ++ * This walks the device tree once. ++ * ++ * @param ofdt_path ++ * @param drc_list ++ * @param node_list - user responsible for freeing ++ * @returns 0 on success, !0 otherwise ++ */ ++static int ++create_vio_nodes(const char *ofdt_path, ++ struct dr_connector *drc_list, ++ struct dr_node **node_list) ++{ ++ DIR *d; ++ struct dirent *de; ++ char child_path[DR_PATH_MAX]; ++ uint32_t my_drc_index; ++ struct dr_node *node; ++ struct dr_connector *drc; ++ struct dr_connector *drc_search; ++ int rc; ++ ++ d = opendir(ofdt_path); ++ if (!d) ++ return -1; ++ ++ rc = 0; ++ while ((de = readdir(d)) != NULL) { ++ if ((de->d_type != DT_DIR) || is_dot_dir(de->d_name)) ++ continue; ++ ++ snprintf(child_path, DR_PATH_MAX, "%s/%s", ofdt_path, ++ de->d_name); ++ if (get_my_drc_index(child_path, &my_drc_index)) ++ continue; ++ drc = NULL; ++ for (drc_search = drc_list; drc_search; drc_search = drc_search->next) { ++ if (drc_search->index == my_drc_index) { ++ drc = drc_search; ++ break; ++ } ++ } ++ if (!drc) { ++ say(ERROR, "Unable to find DRC index %d\n", ++ my_drc_index); ++ rc = -1; ++ break; ++ } ++ ++ node = alloc_dr_node(drc, VIO_DEV, child_path); ++ if (!node) { ++ say(ERROR, "Could not allocate pci/vio node\n"); ++ rc = -1; ++ break; ++ } ++ ++ node->is_owned = 1; ++ ++ /* Populate w/ children */ ++ rc = init_node(node); ++ if (rc) { ++ free(node); ++ break; ++ } ++ ++ node->next = *node_list; ++ *node_list = node; ++ } ++ ++ closedir(d); ++ if (rc) ++ free_node(*node_list); ++ return rc; ++} ++ + static inline int is_hp_type(char *type) + { + return (strtoul(type, NULL, 10) > 0); +@@ -606,6 +683,9 @@ add_pci_vio_node(const char *path, int dev_type, struct dr_node **node_list) + struct dr_connector *drc_list; + struct dr_connector *drc; + struct dr_node *node; ++ struct dr_node *vio_node_list = NULL; ++ struct dr_node *node_search; ++ struct dr_node *node_search_prev; + int child_dev_type = 0; + int rc = -1; + +@@ -613,7 +693,16 @@ add_pci_vio_node(const char *path, int dev_type, struct dr_node **node_list) + if (drc_list == NULL) + return -1; + ++ // Create a list of existing VIO nodes so we can ++ // walk the vio bus only once ++ if (dev_type == VIO_DEV) { ++ rc = create_vio_nodes(path, drc_list, &vio_node_list); ++ if (rc) ++ return rc; ++ } ++ + for (drc = drc_list; drc != NULL; drc = drc->next) { ++ node = NULL; + switch (dev_type) { + case PCI_HP_DEV: + if (! is_hp_type(drc->type)) +@@ -635,25 +724,53 @@ add_pci_vio_node(const char *path, int dev_type, struct dr_node **node_list) + break; + } + +- node = alloc_dr_node(drc, child_dev_type, path); +- if (node == NULL) { +- say(ERROR, "Could not allocate pci/vio node\n"); +- return -1; ++ // If this is VIO, look for the node in our existing list ++ if (dev_type == VIO_DEV) { ++ node_search = vio_node_list; ++ node_search_prev = NULL; ++ while (node_search) { ++ if (drc->index == node_search->drc_index) { ++ /* ++ * Use this node - and remove it ++ * from the list ++ */ ++ node = node_search; ++ if (node_search_prev) ++ node_search_prev->next = ++ node->next; ++ else ++ vio_node_list = node->next; ++ break; ++ } ++ node_search_prev = node_search; ++ node_search = node_search->next; ++ } + } + +- if (child_dev_type == PCI_HP_DEV) +- node->is_owned = 1; ++ if (!node) { ++ node = alloc_dr_node(drc, child_dev_type, path); ++ if (!node) { ++ say(ERROR, "Could not allocate pci/vio node\n"); ++ free_node(vio_node_list); ++ return -1; ++ } + +- rc = init_node(node); +- if (rc) { +- free(node); +- return rc; ++ if (child_dev_type == PCI_HP_DEV) ++ node->is_owned = 1; ++ ++ if (dev_type != VIO_DEV) { ++ rc = init_node(node); ++ if (rc) { ++ free(node); ++ return rc; ++ } ++ } + } + + node->next = *node_list; + *node_list = node; + } +- ++ free_node(vio_node_list); + return rc; + } + +-- +2.7.4 + diff -Nru powerpc-utils-1.3.1/debian/patches/series powerpc-utils-1.3.1/debian/patches/series --- powerpc-utils-1.3.1/debian/patches/series 2017-01-15 02:50:28.000000000 +0000 +++ powerpc-utils-1.3.1/debian/patches/series 2017-06-09 14:39:15.000000000 +0000 @@ -4,3 +4,7 @@ 0001-errinjct-Correct-config_addr-parsing.patch 0002-errinjct-Recognize-5-return-from-rtas.patch 0003-errinjct-Correct-read_file-error-checking.patch +Improve-perf-of-drmgr-lsslot-with-large-num-of-virt.patch +drmgr-Stale-errno-usage-corrections.patch +drmgr-Correct-errno-usage-use-in-validate_paltform.patch +drmgr-Correct-errno-usage-in-init_cpu_info.patch