| .. | .. | 
|---|
| 11 | 11 | #include <linux/rwsem.h> | 
|---|
| 12 | 12 | #include <linux/memcontrol.h> | 
|---|
| 13 | 13 | #include <linux/highmem.h> | 
|---|
|  | 14 | +#ifndef __GENKSYMS__ | 
|---|
|  | 15 | +#define PROTECT_TRACE_INCLUDE_PATH | 
|---|
|  | 16 | +#include <trace/hooks/mm.h> | 
|---|
|  | 17 | +#endif | 
|---|
| 14 | 18 |  | 
|---|
| 15 | 19 | /* | 
|---|
| 16 | 20 | * The anon_vma heads a list of private "related" vmas, to scan if | 
|---|
| .. | .. | 
|---|
| 38 | 42 | */ | 
|---|
| 39 | 43 | atomic_t refcount; | 
|---|
| 40 | 44 |  | 
|---|
| 41 |  | -	/* | 
|---|
| 42 |  | -	 * Count of child anon_vmas and VMAs which points to this anon_vma. | 
|---|
| 43 |  | -	 * | 
|---|
| 44 |  | -	 * This counter is used for making decision about reusing anon_vma | 
|---|
| 45 |  | -	 * instead of forking new one. See comments in function anon_vma_clone. | 
|---|
| 46 |  | -	 */ | 
|---|
| 47 |  | -	unsigned degree; | 
|---|
|  | 45 | +	unsigned degree;		/* ANDROID: KABI preservation, DO NOT USE! */ | 
|---|
| 48 | 46 |  | 
|---|
| 49 | 47 | struct anon_vma *parent;	/* Parent of this anon_vma */ | 
|---|
| 50 | 48 |  | 
|---|
| .. | .. | 
|---|
| 59 | 57 |  | 
|---|
| 60 | 58 | /* Interval tree of private "related" vmas */ | 
|---|
| 61 | 59 | struct rb_root_cached rb_root; | 
|---|
|  | 60 | + | 
|---|
|  | 61 | +	/* | 
|---|
|  | 62 | +	 * ANDROID: KABI preservation, it's safe to put these at the end of this structure as it's | 
|---|
|  | 63 | +	 * only passed by a pointer everywhere, the size and internal structures are local to the | 
|---|
|  | 64 | +	 * core kernel. | 
|---|
|  | 65 | +	 */ | 
|---|
|  | 66 | +#ifndef __GENKSYMS__ | 
|---|
|  | 67 | +	/* | 
|---|
|  | 68 | +	 * Count of child anon_vmas. Equals to the count of all anon_vmas that | 
|---|
|  | 69 | +	 * have ->parent pointing to this one, including itself. | 
|---|
|  | 70 | +	 * | 
|---|
|  | 71 | +	 * This counter is used for making decision about reusing anon_vma | 
|---|
|  | 72 | +	 * instead of forking new one. See comments in function anon_vma_clone. | 
|---|
|  | 73 | +	 */ | 
|---|
|  | 74 | +	unsigned long num_children; | 
|---|
|  | 75 | +	/* Count of VMAs whose ->anon_vma pointer points to this object. */ | 
|---|
|  | 76 | +	unsigned long num_active_vmas; | 
|---|
|  | 77 | +#endif | 
|---|
|  | 78 | + | 
|---|
| 62 | 79 | }; | 
|---|
| 63 | 80 |  | 
|---|
| 64 | 81 | /* | 
|---|
| .. | .. | 
|---|
| 77 | 94 | struct anon_vma_chain { | 
|---|
| 78 | 95 | struct vm_area_struct *vma; | 
|---|
| 79 | 96 | struct anon_vma *anon_vma; | 
|---|
| 80 |  | -	struct list_head same_vma;   /* locked by mmap_sem & page_table_lock */ | 
|---|
|  | 97 | +	struct list_head same_vma;   /* locked by mmap_lock & page_table_lock */ | 
|---|
| 81 | 98 | struct rb_node rb;			/* locked by anon_vma->rwsem */ | 
|---|
| 82 | 99 | unsigned long rb_subtree_last; | 
|---|
| 83 | 100 | #ifdef CONFIG_DEBUG_VM_RB | 
|---|
| .. | .. | 
|---|
| 91 | 108 |  | 
|---|
| 92 | 109 | TTU_SPLIT_HUGE_PMD	= 0x4,	/* split huge PMD if any */ | 
|---|
| 93 | 110 | TTU_IGNORE_MLOCK	= 0x8,	/* ignore mlock */ | 
|---|
| 94 |  | -	TTU_IGNORE_ACCESS	= 0x10,	/* don't age */ | 
|---|
|  | 111 | +	TTU_SYNC		= 0x10,	/* avoid racy checks with PVMW_SYNC */ | 
|---|
| 95 | 112 | TTU_IGNORE_HWPOISON	= 0x20,	/* corrupted page is recoverable */ | 
|---|
| 96 | 113 | TTU_BATCH_FLUSH		= 0x40,	/* Batch TLB flushes where possible | 
|---|
| 97 | 114 | * and caller guarantees they will | 
|---|
| 98 | 115 | * do a final flush if necessary */ | 
|---|
| 99 | 116 | TTU_RMAP_LOCKED		= 0x80,	/* do not grab rmap lock: | 
|---|
| 100 | 117 | * caller holds it */ | 
|---|
| 101 |  | -	TTU_SPLIT_FREEZE	= 0x100, /* freeze pte under splitting thp */ | 
|---|
| 102 |  | -	TTU_SYNC		= 0x200, /* avoid racy checks with PVMW_SYNC */ | 
|---|
|  | 118 | +	TTU_SPLIT_FREEZE	= 0x100,		/* freeze pte under splitting thp */ | 
|---|
| 103 | 119 | }; | 
|---|
| 104 | 120 |  | 
|---|
| 105 | 121 | #ifdef CONFIG_MMU | 
|---|
| .. | .. | 
|---|
| 129 | 145 | static inline void anon_vma_lock_read(struct anon_vma *anon_vma) | 
|---|
| 130 | 146 | { | 
|---|
| 131 | 147 | down_read(&anon_vma->root->rwsem); | 
|---|
|  | 148 | +} | 
|---|
|  | 149 | + | 
|---|
|  | 150 | +static inline int anon_vma_trylock_read(struct anon_vma *anon_vma) | 
|---|
|  | 151 | +{ | 
|---|
|  | 152 | +	return down_read_trylock(&anon_vma->root->rwsem); | 
|---|
| 132 | 153 | } | 
|---|
| 133 | 154 |  | 
|---|
| 134 | 155 | static inline void anon_vma_unlock_read(struct anon_vma *anon_vma) | 
|---|
| .. | .. | 
|---|
| 175 | 196 | unsigned long, bool); | 
|---|
| 176 | 197 | void do_page_add_anon_rmap(struct page *, struct vm_area_struct *, | 
|---|
| 177 | 198 | unsigned long, int); | 
|---|
| 178 |  | -void page_add_new_anon_rmap(struct page *, struct vm_area_struct *, | 
|---|
| 179 |  | -		unsigned long, bool); | 
|---|
|  | 199 | +void __page_add_new_anon_rmap(struct page *page, struct vm_area_struct *vma, | 
|---|
|  | 200 | +			      unsigned long address, bool compound); | 
|---|
|  | 201 | +static inline void page_add_new_anon_rmap(struct page *page, | 
|---|
|  | 202 | +					  struct vm_area_struct *vma, | 
|---|
|  | 203 | +					  unsigned long address, bool compound) | 
|---|
|  | 204 | +{ | 
|---|
|  | 205 | +	VM_BUG_ON_VMA(address < vma->vm_start || address >= vma->vm_end, vma); | 
|---|
|  | 206 | +	__page_add_new_anon_rmap(page, vma, address, compound); | 
|---|
|  | 207 | +} | 
|---|
|  | 208 | + | 
|---|
| 180 | 209 | void page_add_file_rmap(struct page *, bool); | 
|---|
| 181 | 210 | void page_remove_rmap(struct page *, bool); | 
|---|
| 182 | 211 |  | 
|---|
| .. | .. | 
|---|
| 187 | 216 |  | 
|---|
| 188 | 217 | static inline void page_dup_rmap(struct page *page, bool compound) | 
|---|
| 189 | 218 | { | 
|---|
| 190 |  | -	atomic_inc(compound ? compound_mapcount_ptr(page) : &page->_mapcount); | 
|---|
|  | 219 | +	bool success = false; | 
|---|
|  | 220 | + | 
|---|
|  | 221 | +	if (!compound) | 
|---|
|  | 222 | +		trace_android_vh_update_page_mapcount(page, true, compound, NULL, &success); | 
|---|
|  | 223 | +	if (!success) | 
|---|
|  | 224 | +		atomic_inc(compound ? compound_mapcount_ptr(page) : &page->_mapcount); | 
|---|
| 191 | 225 | } | 
|---|
| 192 | 226 |  | 
|---|
| 193 | 227 | /* | 
|---|
| .. | .. | 
|---|
| 245 | 279 |  | 
|---|
| 246 | 280 | void remove_migration_ptes(struct page *old, struct page *new, bool locked); | 
|---|
| 247 | 281 |  | 
|---|
| 248 |  | -/* | 
|---|
| 249 |  | - * Called by memory-failure.c to kill processes. | 
|---|
| 250 |  | - */ | 
|---|
| 251 |  | -struct anon_vma *page_lock_anon_vma_read(struct page *page); | 
|---|
| 252 |  | -void page_unlock_anon_vma_read(struct anon_vma *anon_vma); | 
|---|
| 253 | 282 | int page_mapped_in_vma(struct page *page, struct vm_area_struct *vma); | 
|---|
| 254 | 283 |  | 
|---|
| 255 | 284 | /* | 
|---|
| 256 | 285 | * rmap_walk_control: To control rmap traversing for specific needs | 
|---|
| 257 | 286 | * | 
|---|
| 258 | 287 | * arg: passed to rmap_one() and invalid_vma() | 
|---|
|  | 288 | + * try_lock: bail out if the rmap lock is contended | 
|---|
|  | 289 | + * contended: indicate the rmap traversal bailed out due to lock contention | 
|---|
| 259 | 290 | * rmap_one: executed on each vma where page is mapped | 
|---|
| 260 | 291 | * done: for checking traversing termination condition | 
|---|
| 261 | 292 | * anon_lock: for getting anon_lock by optimized way rather than default | 
|---|
| .. | .. | 
|---|
| 263 | 294 | */ | 
|---|
| 264 | 295 | struct rmap_walk_control { | 
|---|
| 265 | 296 | void *arg; | 
|---|
|  | 297 | +	bool try_lock; | 
|---|
|  | 298 | +	bool contended; | 
|---|
| 266 | 299 | /* | 
|---|
| 267 | 300 | * Return false if page table scanning in rmap_walk should be stopped. | 
|---|
| 268 | 301 | * Otherwise, return true. | 
|---|
| .. | .. | 
|---|
| 270 | 303 | bool (*rmap_one)(struct page *page, struct vm_area_struct *vma, | 
|---|
| 271 | 304 | unsigned long addr, void *arg); | 
|---|
| 272 | 305 | int (*done)(struct page *page); | 
|---|
| 273 |  | -	struct anon_vma *(*anon_lock)(struct page *page); | 
|---|
|  | 306 | +	struct anon_vma *(*anon_lock)(struct page *page, | 
|---|
|  | 307 | +				      struct rmap_walk_control *rwc); | 
|---|
| 274 | 308 | bool (*invalid_vma)(struct vm_area_struct *vma, void *arg); | 
|---|
| 275 | 309 | }; | 
|---|
| 276 | 310 |  | 
|---|
| 277 | 311 | void rmap_walk(struct page *page, struct rmap_walk_control *rwc); | 
|---|
| 278 | 312 | void rmap_walk_locked(struct page *page, struct rmap_walk_control *rwc); | 
|---|
| 279 | 313 |  | 
|---|
|  | 314 | +/* | 
|---|
|  | 315 | + * Called by memory-failure.c to kill processes. | 
|---|
|  | 316 | + */ | 
|---|
|  | 317 | +struct anon_vma *page_lock_anon_vma_read(struct page *page, | 
|---|
|  | 318 | +					 struct rmap_walk_control *rwc); | 
|---|
|  | 319 | +void page_unlock_anon_vma_read(struct anon_vma *anon_vma); | 
|---|
|  | 320 | + | 
|---|
| 280 | 321 | #else	/* !CONFIG_MMU */ | 
|---|
| 281 | 322 |  | 
|---|
| 282 | 323 | #define anon_vma_init()		do {} while (0) | 
|---|