blob: b7a1c907acf191e6a17b1725da07580d18e53ac2 [file] [log] [blame]
#ifndef __LINUX_VMPRESSURE_H
#define __LINUX_VMPRESSURE_H
#include <linux/mutex.h>
#include <linux/list.h>
#include <linux/workqueue.h>
#include <linux/gfp.h>
#include <linux/types.h>
#include <linux/cgroup.h>
enum vmpressure_levels {
VMPRESSURE_LOW = 0,
VMPRESSURE_MEDIUM,
VMPRESSURE_CRITICAL,
VMPRESSURE_NUM_LEVELS,
};
struct vmpressure {
/*
* The window size is the number of scanned pages before
* we try to analyze scanned/reclaimed ratio. Using small window
* sizes can cause lot of false positives, but too big window size will
* delay the notifications.
*
* In order to reduce the amount of false positives for low and medium
* levels, those levels aren't reported until we've seen multiple
* windows at those respective pressure levels. This makes sure
* sure that we don't delay notifications when encountering critical
* levels of memory pressure, but also don't spam userspace in case
* nothing serious is going on. The number of windows seen at each
* pressure level is kept in nr_windows below.
*
* For the root mem cgroup, the window size is computed based on the
* total amount of pages available in the system. For non-root cgroups,
* we compute the window size based on the hard memory limit, or if
* that is not set, we fall back to the default window size.
*/
unsigned long window_size;
/* The number of windows we've seen each pressure level occur for */
unsigned int nr_windows[VMPRESSURE_NUM_LEVELS];
unsigned long scanned;
unsigned long reclaimed;
/* The lock is used to keep the members above in sync. */
struct mutex sr_lock;
/* The list of vmpressure_event structs. */
struct list_head events;
/* Have to grab the lock on events traversal or modifications. */
struct mutex events_lock;
struct work_struct work;
};
struct mem_cgroup;
#ifdef CONFIG_MEMCG
extern void vmpressure(gfp_t gfp, struct mem_cgroup *memcg,
unsigned long scanned, unsigned long reclaimed);
extern void vmpressure_prio(gfp_t gfp, struct mem_cgroup *memcg, int prio);
extern void vmpressure_init(struct vmpressure *vmpr, bool is_root);
extern struct vmpressure *memcg_to_vmpressure(struct mem_cgroup *memcg);
extern struct cgroup_subsys_state *vmpressure_to_css(struct vmpressure *vmpr);
extern struct vmpressure *css_to_vmpressure(struct cgroup_subsys_state *css);
extern void vmpressure_update_mem_limit(struct mem_cgroup *memcg,
unsigned long new_limit);
extern int vmpressure_register_event(struct cgroup *cg, struct cftype *cft,
struct eventfd_ctx *eventfd,
const char *args);
extern void vmpressure_unregister_event(struct cgroup *cg, struct cftype *cft,
struct eventfd_ctx *eventfd);
#else
static inline void vmpressure(gfp_t gfp, struct mem_cgroup *memcg,
unsigned long scanned, unsigned long reclaimed) {}
static inline void vmpressure_prio(gfp_t gfp, struct mem_cgroup *memcg,
int prio) {}
#endif /* CONFIG_MEMCG */
#endif /* __LINUX_VMPRESSURE_H */