/** * mem_remove * * @return 0 on success, !0 otherwise */ static int mem_remove(void) { struct lmb_list_head *lmb_list; struct dr_node *lmb; unsigned int removable = 0; int rc = 0; lmb_list = get_lmbs(LMB_RANDOM_SORT); if (lmb_list == NULL) { say(ERROR, "Could not gather LMB (logical memory block " "information.\n"); return -1; } /* Can not know which lmbs are removable by the is_removable field * if AMS ballooning is active. */ if (!ams_balloon_active()) { /* Make sure we have enough removable memory to fulfill * this request */ for (lmb = lmb_list->lmbs; lmb; lmb = lmb->next) { if (lmb->is_removable) removable++; } if (removable == 0) { say(ERROR, "There is not enough removable memory " "available to fulfill the request.\n"); rc = -1; } if (removable < usr_drc_count) { say(INFO, "Only %u LMBs are currently candidates " "for removal.\n", removable); usr_drc_count = removable; } } if (!rc) { say(DEBUG, "Attempting removal of %d LMBs\n", usr_drc_count); rc = remove_lmbs(lmb_list); } say(ERROR, "Removed %d of %d requested LMB(s)\n", lmb_list->lmbs_modified, usr_drc_count); if (lmb_list->lmbs_modified < usr_drc_count) say(ERROR, "Unable to hotplug remove the remaining %d LMB(s)\n", usr_drc_count - lmb_list->lmbs_modified); report_resource_count(lmb_list->lmbs_modified); free_lmbs(lmb_list); return rc; }
int lsslot_chrp_mem(struct cmd_opts *opts) { struct lmb_list_head *lmb_list; struct dr_node *lmb; struct mem_scn *scn; int scn_offset = strlen("/sys/devices/system/memory/memory"); int lmb_offset = strlen(OFDT_BASE); lmb_list = get_lmbs(LMB_NORMAL_SORT); if (lmb_list == NULL || lmb_list->lmbs == NULL) return -1; if (lmb_list->drconf_buf) { print_drconf_mem(opts, lmb_list); } else { printf("lmb size: 0x%x\n", lmb_list->lmbs->lmb_size); printf("%-20s %-5s %c %s\n", "Memory Node", "Name", 'R', "Sections"); printf("%-20s %-5s %c %s\n", "-----------", "----", '-', "--------"); for (lmb = lmb_list->lmbs; lmb; lmb = lmb->next) { int first = 1; if (!lmb->is_owned) continue; if (!lmb_list->drconf_buf) printf("%-20s ", &lmb->ofdt_path[lmb_offset]); printf("%-5s %c ", lmb->drc_name, lmb->is_removable ? 'Y' : 'N'); for (scn = lmb->lmb_mem_scns; scn; scn = scn->next) { if (first) { printf(" %s", &scn->sysfs_path[scn_offset]); first = 0; } else printf(", %s", &scn->sysfs_path[scn_offset]); } printf("\n"); } } free_lmbs(lmb_list); return 0; }
/** * mem_add * @brief Add memory to the partition * * @returns 0 on success, !0 otherwise */ static int mem_add(void) { struct lmb_list_head *lmb_list; int rc; lmb_list = get_lmbs(LMB_NORMAL_SORT); if (lmb_list == NULL) { say(ERROR, "Could not gather LMB (logical memory block " "information.\n"); return -1; } say(DEBUG, "Attempting to add %d LMBs\n", usr_drc_count); rc = add_lmbs(lmb_list); say(DEBUG, "Added %d of %d requested LMB(s)\n", lmb_list->lmbs_modified, usr_drc_count); report_resource_count(lmb_list->lmbs_modified); free_lmbs(lmb_list); return rc; }
/** * get_lmbs * @brief Build a list of all possible lmbs for the system * * @param sort LMB_NORMAL_SORT or LMB_REVERSE_SORT to control sort order * * @return list of lmbs, NULL on failure */ struct lmb_list_head * get_lmbs(unsigned int sort) { struct lmb_list_head *lmb_list = NULL; struct dr_node *lmb = NULL; struct stat sbuf; char buf[DR_STR_MAX]; int rc = 0; lmb_list = zalloc(sizeof(*lmb_list)); if (lmb_list == NULL) { say(DEBUG, "Could not allocate LMB list head\n"); return NULL; } lmb_list->sort = sort; rc = get_str_attribute("/sys/devices/system/memory", "/block_size_bytes", &buf, DR_STR_MAX); if (rc) { say(DEBUG, "Could not determine block size bytes for memory.\n"); free_lmbs(lmb_list); return NULL; } block_sz_bytes = strtoul(buf, NULL, 16); /* We also need to know which lmbs are already allocated to * the system and their corresponding memory sections as defined * by sysfs. Walk the device tree and update the appropriate * lmb entries (and their memory sections) as we find their device * tree entries. */ if (stat(DYNAMIC_RECONFIG_MEM, &sbuf)) { struct dr_connector *drc_list, *drc; drc_list = get_drc_info(OFDT_BASE); if (drc_list == NULL) { report_unknown_error(__FILE__, __LINE__); rc = -1; } else { /* For memory dlpar, we need a list of all * posiible memory nodes for the system, initalize * those here. */ for (drc = drc_list; drc; drc = drc->next) { if (strncmp(drc->name, "LMB", 3)) continue; lmb = lmb_list_add(drc->index, lmb_list); if (!lmb) { say(ERROR, "Failed to add LMB (%x)\n", drc->index); rc = -1; break; } lmb_list->lmbs_found++; } } say(INFO, "Maximum of %d LMBs\n", lmb_list->lmbs_found); rc = get_mem_node_lmbs(lmb_list); } else { /* A small hack to here to allow memory add to work in * certain kernels. Due to a bug in the kernel (see comment * in acquire_lmb()) we need to get lmb info from both places. * For a good kernel, the get_mem_node_lmbs routine will not * update the lmb_list. */ rc = get_dynamic_reconfig_lmbs(lmb_list); if (! rc) rc = get_mem_node_lmbs(lmb_list); } if (rc) { free_lmbs(lmb_list); lmb_list = NULL; } else if (sort == LMB_RANDOM_SORT) { shuffle_lmbs(lmb_list); } return lmb_list; }