Revert "CHROMIUM: Add /dev/low-mem device for low-memory notification."

This reverts commit 7a62ca9c46c556ebb857e754d97c456faa82dc9d.
diff --git a/drivers/char/mem.c b/drivers/char/mem.c
index d041226c..43dd089 100644
--- a/drivers/char/mem.c
+++ b/drivers/char/mem.c
@@ -31,7 +31,6 @@
 #include <linux/uio.h>
 #include <linux/uaccess.h>
 #include <linux/security.h>
-#include <linux/low-mem-notify.h>
 
 #ifdef CONFIG_IA64
 # include <linux/efi.h>
@@ -902,9 +901,6 @@
 #ifdef CONFIG_PRINTK
 	[11] = { "kmsg", 0644, &kmsg_fops, 0 },
 #endif
-#ifdef CONFIG_LOW_MEM_NOTIFY
-	[12] = { "chromeos-low-mem", 0666, &low_mem_notify_fops, 0 },
-#endif
 };
 
 static int memory_open(struct inode *inode, struct file *filp)
diff --git a/include/linux/low-mem-notify.h b/include/linux/low-mem-notify.h
deleted file mode 100644
index 63bed13..0000000
--- a/include/linux/low-mem-notify.h
+++ /dev/null
@@ -1,150 +0,0 @@
-#ifndef _LINUX_LOW_MEM_NOTIFY_H
-#define _LINUX_LOW_MEM_NOTIFY_H
-
-#include <linux/mm.h>
-#include <linux/ratelimit.h>
-#include <linux/stddef.h>
-#include <linux/swap.h>
-
-/* We support up to this many different thresholds. */
-#define LOW_MEM_THRESHOLD_MAX 5
-
-extern unsigned long low_mem_thresholds[];
-extern unsigned int low_mem_threshold_count;
-extern unsigned int low_mem_threshold_last;
-extern const struct file_operations low_mem_notify_fops;
-extern bool low_mem_margin_enabled;
-extern unsigned long low_mem_lowest_seen_anon_mem;
-extern unsigned int low_mem_ram_vs_swap_weight;
-extern struct ratelimit_state low_mem_logging_ratelimit;
-
-#ifdef CONFIG_SYSFS
-extern void low_mem_threshold_notify(void);
-#else
-static inline void low_mem_threshold_notify(void)
-{
-}
-#endif
-
-/*
- * Compute available memory used by files that can be reclaimed quickly.
- */
-static inline unsigned long get_available_file_mem(void)
-{
-	unsigned long file_mem =
-			global_node_page_state(NR_ACTIVE_FILE) +
-			global_node_page_state(NR_INACTIVE_FILE);
-	unsigned long dirty_mem = global_node_page_state(NR_FILE_DIRTY);
-	unsigned long min_file_mem = min_filelist_kbytes >> (PAGE_SHIFT - 10);
-	unsigned long clean_file_mem = file_mem - dirty_mem;
-	/* Conservatively estimate the amount of available_file_mem */
-	unsigned long available_file_mem = (clean_file_mem > min_file_mem) ?
-			(clean_file_mem - min_file_mem) : 0;
-	return available_file_mem;
-}
-
-/*
- * Available anonymous memory.
- */
-static inline unsigned long get_available_anon_mem(void)
-{
-	return global_node_page_state(NR_ACTIVE_ANON) +
-		global_node_page_state(NR_INACTIVE_ANON);
-}
-
-/*
- * Compute "available" memory, that is either free memory or memory that can be
- * reclaimed quickly, adjusted for the presence of swap.
- */
-static inline unsigned long get_available_mem_adj(void)
-{
-	/* free_mem is completely unallocated; clean file-backed memory
-	 * (file_mem - dirty_mem) is easy to reclaim, except for the last
-	 * min_filelist_kbytes. totalreserve_pages is the reserve of pages that
-	 * are not available to user space.
-	 */
-	unsigned long raw_free_mem = global_zone_page_state(NR_FREE_PAGES);
-	unsigned long free_mem = (raw_free_mem > totalreserve_pages) ?
-			raw_free_mem - totalreserve_pages : 0;
-	unsigned long available_mem = free_mem +
-			get_available_file_mem();
-	unsigned long swappable_pages = min_t(unsigned long,
-			get_nr_swap_pages(), get_available_anon_mem());
-	/*
-	 * The contribution of swap is reduced by a factor of
-	 * low_mem_ram_vs_swap_weight.
-	 */
-	return available_mem + swappable_pages / low_mem_ram_vs_swap_weight;
-}
-
-#ifdef CONFIG_LOW_MEM_NOTIFY
-void low_mem_notify(void);
-
-extern atomic_t in_low_mem_check;
-
-/*
- * Returns TRUE if we are in a low memory state.
- */
-static inline bool low_mem_check(void)
-{
-	static bool was_low_mem;	/* = false, as per style guide */
-	/* We declare a low-memory condition when a combination of RAM and swap
-	 * space is low.
-	 */
-	unsigned long available_mem = get_available_mem_adj();
-	/*
-	 * For backwards compatibility with the older margin interface, we will
-	 * trigger the /dev/chromeos-low_mem device when we are below the
-	 * lowest threshold
-	 */
-	bool is_low_mem = available_mem < low_mem_thresholds[0];
-	unsigned int threshold_lowest = UINT_MAX;
-	int i;
-
-	if (!low_mem_margin_enabled)
-		return false;
-
-	if (atomic_xchg(&in_low_mem_check, 1))
-		return was_low_mem;
-
-	if (unlikely(is_low_mem && !was_low_mem) &&
-	    __ratelimit(&low_mem_logging_ratelimit)) {
-		pr_info("entering low_mem (avail RAM = %lu kB, avail swap %lu kB, avail file %lu kB, anon mem: %lu kB)\n",
-			available_mem * PAGE_SIZE / 1024,
-			get_nr_swap_pages() * PAGE_SIZE / 1024,
-			get_available_file_mem() * PAGE_SIZE / 1024,
-			get_available_anon_mem() * PAGE_SIZE / 1024);
-	}
-	was_low_mem = is_low_mem;
-
-	if (is_low_mem)
-		low_mem_notify();
-
-	for (i = 0; i < low_mem_threshold_count; i++)
-		if (available_mem < low_mem_thresholds[i]) {
-			threshold_lowest = i;
-			break;
-		}
-
-	/* we crossed one or more thresholds */
-	if (unlikely(threshold_lowest < low_mem_threshold_last))
-		low_mem_threshold_notify();
-
-	low_mem_threshold_last = threshold_lowest;
-
-	atomic_set(&in_low_mem_check, 0);
-
-	return is_low_mem;
-}
-#else
-static inline void low_mem_notify(void)
-{
-}
-
-static inline bool low_mem_check(void)
-{
-	return false;
-}
-#endif
-
-#endif
diff --git a/mm/Kconfig b/mm/Kconfig
index 70fd8ce..7fbb7d1 100644
--- a/mm/Kconfig
+++ b/mm/Kconfig
@@ -753,17 +753,6 @@
 config ARCH_HAS_HUGEPD
 	bool
 
-config LOW_MEM_NOTIFY
-	bool "Create device that lets processes detect low-memory conditions"
-	default n
-	help
-	  A process can poll the /dev/low_mem device to be notified of
-	  low-memory conditions.  The process can then attempt to free memory
-	  before a OOM condition develops and the OOM killer takes over.  This
-	  is meant to be used in systems with no or very little swap space.  In
-	  the presence of large swap space, the system is likely to become
-	  unusable before the OOM killer is triggered.
-
 config MAPPING_DIRTY_HELPERS
         bool
 
diff --git a/mm/Makefile b/mm/Makefile
index ed6efd0..272e660 100644
--- a/mm/Makefile
+++ b/mm/Makefile
@@ -102,7 +102,6 @@
 obj-$(CONFIG_USERFAULTFD) += userfaultfd.o
 obj-$(CONFIG_IDLE_PAGE_TRACKING) += page_idle.o
 obj-$(CONFIG_FRAME_VECTOR) += frame_vector.o
-obj-$(CONFIG_LOW_MEM_NOTIFY) += low-mem-notify.o
 obj-$(CONFIG_DEBUG_PAGE_REF) += debug_page_ref.o
 obj-$(CONFIG_HARDENED_USERCOPY) += usercopy.o
 obj-$(CONFIG_PERCPU_STATS) += percpu-stats.o
diff --git a/mm/low-mem-notify.c b/mm/low-mem-notify.c
deleted file mode 100644
index 1a9e3f7..0000000
--- a/mm/low-mem-notify.c
+++ /dev/null
@@ -1,293 +0,0 @@
-/*
- * mm/low-mem-notify.c
- *
- * Sends low-memory notifications to processes via /dev/low-mem.
- *
- * Copyright (C) 2012 The Chromium OS Authors
- * This program is free software, released under the GPL.
- * Based on a proposal by Minchan Kim
- *
- * A process that polls /dev/low-mem is notified of a low-memory situation.
- * The intent is to allow the process to free some memory before the OOM killer
- * is invoked.
- *
- * A low-memory condition is estimated by subtracting anonymous memory
- * (i.e. process data segments), kernel memory, and a fixed amount of
- * file-backed memory from total memory.  This is just a heuristic, as in
- * general we don't know how much memory can be reclaimed before we try to
- * reclaim it, and that's too expensive or too late.
- *
- * This is tailored to Chromium OS, where a single program (the browser)
- * controls most of the memory, and (currently) no swap space is used.
- */
-
-
-#include <linux/low-mem-notify.h>
-#include <linux/module.h>
-#include <linux/sched.h>
-#include <linux/wait.h>
-#include <linux/poll.h>
-#include <linux/slab.h>
-#include <linux/mm.h>
-#include <linux/ctype.h>
-
-#define MB (1 << 20)
-
-static DECLARE_WAIT_QUEUE_HEAD(low_mem_wait);
-static atomic_t low_mem_state = ATOMIC_INIT(0);
-atomic_t in_low_mem_check = ATOMIC_INIT(0);
-
-/* This is a list of thresholds in pages and should be in ascending order. */
-unsigned long low_mem_thresholds[LOW_MEM_THRESHOLD_MAX] = {
-	50 * MB / PAGE_SIZE };
-unsigned int low_mem_threshold_count = 1;
-
-/* last observed threshold */
-unsigned int low_mem_threshold_last = UINT_MAX;
-bool low_mem_margin_enabled = true;
-unsigned int low_mem_ram_vs_swap_weight = 4;
-
-/* Limit logging low memory to once per second. */
-DEFINE_RATELIMIT_STATE(low_mem_logging_ratelimit, 1 * HZ, 1);
-
-unsigned long low_mem_lowest_seen_anon_mem;
-const unsigned long low_mem_anon_mem_delta = 10 * MB / PAGE_SIZE;
-static struct kernfs_node *low_mem_available_dirent;
-
-struct low_mem_notify_file_info {
-	unsigned long unused;
-};
-
-void low_mem_notify(void)
-{
-	atomic_set(&low_mem_state, true);
-	wake_up(&low_mem_wait);
-}
-
-static int low_mem_notify_open(struct inode *inode, struct file *file)
-{
-	struct low_mem_notify_file_info *info;
-	int err = 0;
-
-	info = kmalloc(sizeof(*info), GFP_KERNEL);
-	if (!info) {
-		err = -ENOMEM;
-		goto out;
-	}
-
-	file->private_data = info;
-out:
-	return err;
-}
-
-static int low_mem_notify_release(struct inode *inode, struct file *file)
-{
-	kfree(file->private_data);
-	return 0;
-}
-
-static __poll_t low_mem_notify_poll(struct file *file, poll_table *wait)
-{
-	unsigned int ret = 0;
-
-	/* Update state to reflect any recent freeing. */
-	atomic_set(&low_mem_state, low_mem_check());
-
-	poll_wait(file, &low_mem_wait, wait);
-
-	if (low_mem_margin_enabled && atomic_read(&low_mem_state) != 0)
-		ret = POLLIN;
-
-	return ret;
-}
-
-const struct file_operations low_mem_notify_fops = {
-	.open = low_mem_notify_open,
-	.release = low_mem_notify_release,
-	.poll = low_mem_notify_poll,
-};
-EXPORT_SYMBOL(low_mem_notify_fops);
-
-#ifdef CONFIG_SYSFS
-
-#define LOW_MEM_ATTR(_name)				      \
-	static struct kobj_attribute low_mem_##_name##_attr = \
-		__ATTR(_name, 0644, low_mem_##_name##_show,   \
-		       low_mem_##_name##_store)
-
-static ssize_t low_mem_margin_show(struct kobject *kobj,
-				  struct kobj_attribute *attr, char *buf)
-{
-	if (low_mem_margin_enabled && low_mem_threshold_count) {
-		int i;
-		ssize_t written = 0;
-
-		for (i = 0; i < low_mem_threshold_count; i++)
-			written += sprintf(buf + written, "%lu ",
-			    low_mem_thresholds[i] * PAGE_SIZE / MB);
-		written += sprintf(buf + written, "\n");
-		return written;
-	} else
-		return sprintf(buf, "off\n");
-}
-
-static ssize_t low_mem_margin_store(struct kobject *kobj,
-				    struct kobj_attribute *attr,
-				    const char *buf, size_t count)
-{
-	int i = 0, consumed = 0;
-	const char *start = buf;
-	char *endp;
-	unsigned long thresholds[LOW_MEM_THRESHOLD_MAX];
-
-	memset(thresholds, 0, sizeof(thresholds));
-	/*
-	 * Even though the API does not say anything about this, the string in
-	 * buf is zero-terminated (as long as count < PAGE_SIZE) because buf is
-	 * a newly allocated zero-filled page.  Most other sysfs handlers rely
-	 * on this too.
-	 */
-	if (strncmp("off", buf, 3) == 0) {
-		pr_info("low_mem: disabling notifier\n");
-		low_mem_margin_enabled = false;
-		return count;
-	}
-	if (strncmp("on", buf, 2) == 0) {
-		pr_info("low_mem: enabling notifier\n");
-		low_mem_margin_enabled = true;
-		return count;
-	}
-	/*
-	 * This takes a space separated list of thresholds in ascending order,
-	 * and a trailing newline is optional.
-	 */
-	while (consumed < count) {
-		if (i >= LOW_MEM_THRESHOLD_MAX) {
-			pr_warn("low-mem: too many thresholds");
-			return -EINVAL;
-		}
-		/* special case for trailing newline */
-		if (*start == '\n')
-			break;
-
-		thresholds[i] = simple_strtoul(start, &endp, 0);
-		if ((endp == start) && *endp != '\n')
-			return -EINVAL;
-
-		/* make sure each is larger than the last one */
-		if (i && thresholds[i] <= thresholds[i - 1]) {
-			pr_warn("low-mem: thresholds not in increasing order: %lu then %lu\n",
-				thresholds[i - 1], thresholds[i]);
-			return -EINVAL;
-		}
-
-		if (thresholds[i] * (MB / PAGE_SIZE) > totalram_pages()) {
-			pr_warn("low-mem: threshold too high\n");
-			return -EINVAL;
-		}
-
-		consumed += endp - start + 1;
-		start = endp + 1;
-		i++;
-	}
-
-	low_mem_threshold_count = i;
-	low_mem_margin_enabled = !!low_mem_threshold_count;
-
-	/* Convert to pages outside the allocator fast path. */
-	for (i = 0; i < low_mem_threshold_count; i++) {
-		low_mem_thresholds[i] =
-			thresholds[i] * (MB / PAGE_SIZE);
-		pr_info("low_mem: threshold[%d] %lu MB\n", i,
-			low_mem_thresholds[i] * PAGE_SIZE / MB);
-	}
-
-	return count;
-}
-LOW_MEM_ATTR(margin);
-
-static ssize_t low_mem_ram_vs_swap_weight_show(struct kobject *kobj,
-					       struct kobj_attribute *attr,
-					       char *buf)
-{
-	return sprintf(buf, "%u\n", low_mem_ram_vs_swap_weight);
-}
-
-static ssize_t low_mem_ram_vs_swap_weight_store(struct kobject *kobj,
-						struct kobj_attribute *attr,
-						const char *buf, size_t count)
-{
-	unsigned long weight;
-	int err;
-
-	err = kstrtoul(buf, 10, &weight);
-	if (err)
-		return -EINVAL;
-	/* The special value 0 represents infinity. */
-	low_mem_ram_vs_swap_weight = weight == 0 ?
-		-1U : (unsigned int) weight;
-	pr_info("low_mem: setting ram weight to %u\n",
-		low_mem_ram_vs_swap_weight);
-	return count;
-}
-LOW_MEM_ATTR(ram_vs_swap_weight);
-
-static ssize_t low_mem_available_show(struct kobject *kobj,
-				      struct kobj_attribute *attr,
-				      char *buf)
-{
-	unsigned long available_mem = get_available_mem_adj();
-
-	return sprintf(buf, "%lu\n",
-		       available_mem / (MB / PAGE_SIZE));
-}
-
-static ssize_t low_mem_available_store(struct kobject *kobj,
-				       struct kobj_attribute *attr,
-				       const char *buf, size_t count)
-{
-	return -EINVAL;
-}
-LOW_MEM_ATTR(available);
-
-static struct attribute *low_mem_attrs[] = {
-	&low_mem_margin_attr.attr,
-	&low_mem_ram_vs_swap_weight_attr.attr,
-	&low_mem_available_attr.attr,
-	NULL,
-};
-
-static struct attribute_group low_mem_attr_group = {
-	.attrs = low_mem_attrs,
-	.name = "chromeos-low_mem",
-};
-
-void low_mem_threshold_notify(void)
-{
-	if (low_mem_available_dirent)
-		sysfs_notify_dirent(low_mem_available_dirent);
-}
-
-static int __init low_mem_init(void)
-{
-	struct kernfs_node *low_mem_node;
-	int err = sysfs_create_group(mm_kobj, &low_mem_attr_group);
-	if (err)
-		pr_err("low_mem: register sysfs failed\n");
-
-	low_mem_node = sysfs_get_dirent(mm_kobj->sd, "chromeos-low_mem");
-	if (low_mem_node) {
-		low_mem_available_dirent =
-		    sysfs_get_dirent(low_mem_node, "available");
-		sysfs_put(low_mem_node);
-	}
-
-	if (!low_mem_available_dirent)
-		pr_warn("unable to find dirent for \"available\" attribute\n");
-
-	low_mem_lowest_seen_anon_mem = totalram_pages();
-	return err;
-}
-module_init(low_mem_init)
-
-#endif
diff --git a/mm/page_alloc.c b/mm/page_alloc.c
index 7e7d0bc5..3c4eb75 100644
--- a/mm/page_alloc.c
+++ b/mm/page_alloc.c
@@ -68,7 +68,6 @@
 #include <linux/lockdep.h>
 #include <linux/nmi.h>
 #include <linux/psi.h>
-#include <linux/low-mem-notify.h>
 
 #include <asm/sections.h>
 #include <asm/tlbflush.h>
@@ -4287,7 +4286,6 @@
 	 * several times in the row.
 	 */
 	if (*no_progress_loops > MAX_RECLAIM_RETRIES) {
-		low_mem_notify();
 		/* Before OOM, exhaust highatomic_reserve */
 		return unreserve_highatomic_pageblock(ac, true);
 	}
@@ -4723,8 +4721,6 @@
 
 	finalise_ac(gfp_mask, &ac);
 
-	low_mem_check();
-
 	/*
 	 * Forbid the first pass from falling back to types that fragment
 	 * memory until all local zones are considered.
diff --git a/tools/mm/low-mem-test.c b/tools/mm/low-mem-test.c
deleted file mode 100644
index e5cc839..0000000
--- a/tools/mm/low-mem-test.c
+++ /dev/null
@@ -1,178 +0,0 @@
-/* Copyright (c) 2012 The Chromium OS Authors. All rights reserved.
- * This program is free software, released under the GPL.
- * Based on code by Minchan Kim
- *
- * User program that tests low-memory notifications.
- *
- * Compile with -lpthread
- * for instance
- * i686-pc-linux-gnu-gcc low-mem-test.c -o low-mem-test -lpthread
- *
- * Run as: low-mem-test <allocation size> <allocation interval (microseconds)>
- *
- * This program runs in two threads.  One thread continuously allocates memory
- * in the given chunk size, waiting for the specified microsecond interval
- * between allocations.  The other runs in a loop that waits for a low-memory
- * notification, then frees some of the memory that the first thread has
- * allocated.
- */
-
-#include <poll.h>
-#include <sys/types.h>
-#include <sys/stat.h>
-#include <fcntl.h>
-#include <stdio.h>
-#include <pthread.h>
-#include <stdlib.h>
-#include <string.h>
-
-int memory_chunk_size = 10000000;
-int wait_time_us = 10000;
-int autotesting;
-
-pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
-
-struct node {
-	void *memory;
-	struct node *prev;
-	struct node *next;
-};
-
-struct node head, tail;
-
-void work(void)
-{
-	int i;
-
-	while (1) {
-		struct node *new = malloc(sizeof(struct node));
-		if (new == NULL) {
-			perror("allocating node");
-			exit(1);
-		}
-		new->memory = malloc(memory_chunk_size);
-		if (new->memory == NULL) {
-			perror("allocating chunk");
-			exit(1);
-		}
-
-		pthread_mutex_lock(&mutex);
-		new->next = &head;
-		new->prev = head.prev;
-		new->prev->next = new;
-		new->next->prev = new;
-		for (i = 0; i < memory_chunk_size / 4096; i++) {
-			/* touch page */
-			((unsigned char *) new->memory)[i * 4096] = 1;
-		}
-
-		pthread_mutex_unlock(&mutex);
-
-		if (!autotesting) {
-			printf("+");
-			fflush(stdout);
-		}
-
-		usleep(wait_time_us);
-	}
-}
-
-void free_memory(void)
-{
-	struct node *old;
-	pthread_mutex_lock(&mutex);
-	old = tail.next;
-	if (old == &head) {
-		fprintf(stderr, "no memory left to free\n");
-		exit(1);
-	}
-	old->prev->next = old->next;
-	old->next->prev = old->prev;
-	free(old->memory);
-	free(old);
-	pthread_mutex_unlock(&mutex);
-	if (!autotesting) {
-		printf("-");
-		fflush(stdout);
-	}
-}
-
-void *poll_thread(void *dummy)
-{
-	struct pollfd pfd;
-	int fd = open("/dev/chromeos-low-mem", O_RDONLY);
-	if (fd == -1) {
-		perror("/dev/chromeos-low-mem");
-		exit(1);
-	}
-
-	pfd.fd = fd;
-	pfd.events = POLLIN;
-
-	if (autotesting) {
-		/* Check that there is no memory shortage yet. */
-		poll(&pfd, 1, 0);
-		if (pfd.revents != 0) {
-			exit(0);
-		} else {
-			fprintf(stderr, "expected no events but "
-				"poll() returned 0x%x\n", pfd.revents);
-			exit(1);
-		}
-	}
-
-	while (1) {
-		poll(&pfd, 1, -1);
-		if (autotesting) {
-			/* Free several chunks and check that the notification
-			 * is gone. */
-			free_memory();
-			free_memory();
-			free_memory();
-			free_memory();
-			free_memory();
-			poll(&pfd, 1, 0);
-			if (pfd.revents == 0) {
-				exit(0);
-			} else {
-				fprintf(stderr, "expected no events but "
-					"poll() returned 0x%x\n", pfd.revents);
-				exit(1);
-			}
-		}
-		free_memory();
-	}
-}
-
-int main(int argc, char **argv)
-{
-	pthread_t threadid;
-
-	head.next = NULL;
-	head.prev = &tail;
-	tail.next = &head;
-	tail.prev = NULL;
-
-	if (argc != 3 && (argc != 2 || strcmp(argv[1], "autotesting"))) {
-		fprintf(stderr,
-			"usage: low-mem-test <alloc size in bytes> "
-			"<alloc interval in microseconds>\n"
-			"or:    low-mem-test autotesting\n");
-		exit(1);
-	}
-
-	if (argc == 2) {
-		autotesting = 1;
-	} else {
-		memory_chunk_size = atoi(argv[1]);
-		wait_time_us = atoi(argv[2]);
-	}
-
-	if (pthread_create(&threadid, NULL, poll_thread, NULL)) {
-		perror("pthread");
-		return 1;
-	}
-
-	work();
-	return 0;
-}