| .. | .. |
|---|
| 91 | 91 | anon_vma = kmem_cache_alloc(anon_vma_cachep, GFP_KERNEL); |
|---|
| 92 | 92 | if (anon_vma) { |
|---|
| 93 | 93 | atomic_set(&anon_vma->refcount, 1); |
|---|
| 94 | | - anon_vma->degree = 1; /* Reference for first vma */ |
|---|
| 94 | + anon_vma->num_children = 0; |
|---|
| 95 | + anon_vma->num_active_vmas = 0; |
|---|
| 95 | 96 | anon_vma->parent = anon_vma; |
|---|
| 96 | 97 | /* |
|---|
| 97 | 98 | * Initialise the anon_vma root to point to itself. If called |
|---|
| .. | .. |
|---|
| 199 | 200 | anon_vma = anon_vma_alloc(); |
|---|
| 200 | 201 | if (unlikely(!anon_vma)) |
|---|
| 201 | 202 | goto out_enomem_free_avc; |
|---|
| 203 | + anon_vma->num_children++; /* self-parent link for new root */ |
|---|
| 202 | 204 | allocated = anon_vma; |
|---|
| 203 | 205 | } |
|---|
| 204 | 206 | |
|---|
| .. | .. |
|---|
| 208 | 210 | if (likely(!vma->anon_vma)) { |
|---|
| 209 | 211 | vma->anon_vma = anon_vma; |
|---|
| 210 | 212 | anon_vma_chain_link(vma, avc, anon_vma); |
|---|
| 211 | | - /* vma reference or self-parent link for new root */ |
|---|
| 212 | | - anon_vma->degree++; |
|---|
| 213 | + anon_vma->num_active_vmas++; |
|---|
| 213 | 214 | allocated = NULL; |
|---|
| 214 | 215 | avc = NULL; |
|---|
| 215 | 216 | } |
|---|
| .. | .. |
|---|
| 294 | 295 | anon_vma_chain_link(dst, avc, anon_vma); |
|---|
| 295 | 296 | |
|---|
| 296 | 297 | /* |
|---|
| 297 | | - * Reuse existing anon_vma if its degree lower than two, |
|---|
| 298 | | - * that means it has no vma and only one anon_vma child. |
|---|
| 298 | + * Reuse existing anon_vma if it has no vma and only one |
|---|
| 299 | + * anon_vma child. |
|---|
| 299 | 300 | * |
|---|
| 300 | | - * Do not chose parent anon_vma, otherwise first child |
|---|
| 301 | | - * will always reuse it. Root anon_vma is never reused: |
|---|
| 301 | + * Root anon_vma is never reused: |
|---|
| 302 | 302 | * it has self-parent reference and at least one child. |
|---|
| 303 | 303 | */ |
|---|
| 304 | 304 | if (!dst->anon_vma && src->anon_vma && |
|---|
| 305 | | - anon_vma != src->anon_vma && anon_vma->degree < 2) |
|---|
| 305 | + anon_vma->num_children < 2 && |
|---|
| 306 | + anon_vma->num_active_vmas == 0) |
|---|
| 306 | 307 | dst->anon_vma = anon_vma; |
|---|
| 307 | 308 | } |
|---|
| 308 | 309 | if (dst->anon_vma) |
|---|
| 309 | | - dst->anon_vma->degree++; |
|---|
| 310 | + dst->anon_vma->num_active_vmas++; |
|---|
| 310 | 311 | unlock_anon_vma_root(root); |
|---|
| 311 | 312 | return 0; |
|---|
| 312 | 313 | |
|---|
| .. | .. |
|---|
| 356 | 357 | anon_vma = anon_vma_alloc(); |
|---|
| 357 | 358 | if (!anon_vma) |
|---|
| 358 | 359 | goto out_error; |
|---|
| 360 | + anon_vma->num_active_vmas++; |
|---|
| 359 | 361 | avc = anon_vma_chain_alloc(GFP_KERNEL); |
|---|
| 360 | 362 | if (!avc) |
|---|
| 361 | 363 | goto out_error_free_anon_vma; |
|---|
| .. | .. |
|---|
| 376 | 378 | vma->anon_vma = anon_vma; |
|---|
| 377 | 379 | anon_vma_lock_write(anon_vma); |
|---|
| 378 | 380 | anon_vma_chain_link(vma, avc, anon_vma); |
|---|
| 379 | | - anon_vma->parent->degree++; |
|---|
| 381 | + anon_vma->parent->num_children++; |
|---|
| 380 | 382 | anon_vma_unlock_write(anon_vma); |
|---|
| 381 | 383 | |
|---|
| 382 | 384 | return 0; |
|---|
| .. | .. |
|---|
| 408 | 410 | * to free them outside the lock. |
|---|
| 409 | 411 | */ |
|---|
| 410 | 412 | if (RB_EMPTY_ROOT(&anon_vma->rb_root.rb_root)) { |
|---|
| 411 | | - anon_vma->parent->degree--; |
|---|
| 413 | + anon_vma->parent->num_children--; |
|---|
| 412 | 414 | continue; |
|---|
| 413 | 415 | } |
|---|
| 414 | 416 | |
|---|
| .. | .. |
|---|
| 416 | 418 | anon_vma_chain_free(avc); |
|---|
| 417 | 419 | } |
|---|
| 418 | 420 | if (vma->anon_vma) |
|---|
| 419 | | - vma->anon_vma->degree--; |
|---|
| 421 | + vma->anon_vma->num_active_vmas--; |
|---|
| 422 | + |
|---|
| 420 | 423 | unlock_anon_vma_root(root); |
|---|
| 421 | 424 | |
|---|
| 422 | 425 | /* |
|---|
| .. | .. |
|---|
| 427 | 430 | list_for_each_entry_safe(avc, next, &vma->anon_vma_chain, same_vma) { |
|---|
| 428 | 431 | struct anon_vma *anon_vma = avc->anon_vma; |
|---|
| 429 | 432 | |
|---|
| 430 | | - VM_WARN_ON(anon_vma->degree); |
|---|
| 433 | + VM_WARN_ON(anon_vma->num_children); |
|---|
| 434 | + VM_WARN_ON(anon_vma->num_active_vmas); |
|---|
| 431 | 435 | put_anon_vma(anon_vma); |
|---|
| 432 | 436 | |
|---|
| 433 | 437 | list_del(&avc->same_vma); |
|---|
| .. | .. |
|---|
| 911 | 915 | |
|---|
| 912 | 916 | return rwc.contended ? -1 : pra.referenced; |
|---|
| 913 | 917 | } |
|---|
| 918 | +EXPORT_SYMBOL_GPL(page_referenced); |
|---|
| 914 | 919 | |
|---|
| 915 | 920 | static bool page_mkclean_one(struct page *page, struct vm_area_struct *vma, |
|---|
| 916 | 921 | unsigned long address, void *arg) |
|---|