in drivers/mconsole_kern.c [289:380]
static int mem_config(char *str, char **error_out)
{
unsigned long long diff;
int err = -EINVAL, i, add;
char *ret;
if (str[0] != '=') {
*error_out = "Expected '=' after 'mem'";
goto out;
}
str++;
if (str[0] == '-')
add = 0;
else if (str[0] == '+') {
add = 1;
}
else {
*error_out = "Expected increment to start with '-' or '+'";
goto out;
}
str++;
diff = memparse(str, &ret);
if (*ret != '\0') {
*error_out = "Failed to parse memory increment";
goto out;
}
diff /= PAGE_SIZE;
mutex_lock(&plug_mem_mutex);
for (i = 0; i < diff; i++) {
struct unplugged_pages *unplugged;
void *addr;
if (add) {
if (list_empty(&unplugged_pages))
break;
unplugged = list_entry(unplugged_pages.next,
struct unplugged_pages, list);
if (unplug_index > 0)
addr = unplugged->pages[--unplug_index];
else {
list_del(&unplugged->list);
addr = unplugged;
unplug_index = UNPLUGGED_PER_PAGE;
}
free_page((unsigned long) addr);
unplugged_pages_count--;
}
else {
struct page *page;
page = alloc_page(GFP_ATOMIC);
if (page == NULL)
break;
unplugged = page_address(page);
if (unplug_index == UNPLUGGED_PER_PAGE) {
list_add(&unplugged->list, &unplugged_pages);
unplug_index = 0;
}
else {
struct list_head *entry = unplugged_pages.next;
addr = unplugged;
unplugged = list_entry(entry,
struct unplugged_pages,
list);
err = os_drop_memory(addr, PAGE_SIZE);
if (err) {
printk(KERN_ERR "Failed to release "
"memory - errno = %d\n", err);
*error_out = "Failed to release memory";
goto out_unlock;
}
unplugged->pages[unplug_index++] = addr;
}
unplugged_pages_count++;
}
}
err = 0;
out_unlock:
mutex_unlock(&plug_mem_mutex);
out:
return err;
}