162306a36Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0-only
262306a36Sopenharmony_ci/*
362306a36Sopenharmony_ci * mm/interval_tree.c - interval tree for mapping->i_mmap
462306a36Sopenharmony_ci *
562306a36Sopenharmony_ci * Copyright (C) 2012, Michel Lespinasse <walken@google.com>
662306a36Sopenharmony_ci */
762306a36Sopenharmony_ci
862306a36Sopenharmony_ci#include <linux/mm.h>
962306a36Sopenharmony_ci#include <linux/fs.h>
1062306a36Sopenharmony_ci#include <linux/rmap.h>
1162306a36Sopenharmony_ci#include <linux/interval_tree_generic.h>
1262306a36Sopenharmony_ci
1362306a36Sopenharmony_cistatic inline unsigned long vma_start_pgoff(struct vm_area_struct *v)
1462306a36Sopenharmony_ci{
1562306a36Sopenharmony_ci	return v->vm_pgoff;
1662306a36Sopenharmony_ci}
1762306a36Sopenharmony_ci
1862306a36Sopenharmony_cistatic inline unsigned long vma_last_pgoff(struct vm_area_struct *v)
1962306a36Sopenharmony_ci{
2062306a36Sopenharmony_ci	return v->vm_pgoff + vma_pages(v) - 1;
2162306a36Sopenharmony_ci}
2262306a36Sopenharmony_ci
2362306a36Sopenharmony_ciINTERVAL_TREE_DEFINE(struct vm_area_struct, shared.rb,
2462306a36Sopenharmony_ci		     unsigned long, shared.rb_subtree_last,
2562306a36Sopenharmony_ci		     vma_start_pgoff, vma_last_pgoff, /* empty */, vma_interval_tree)
2662306a36Sopenharmony_ci
2762306a36Sopenharmony_ci/* Insert node immediately after prev in the interval tree */
2862306a36Sopenharmony_civoid vma_interval_tree_insert_after(struct vm_area_struct *node,
2962306a36Sopenharmony_ci				    struct vm_area_struct *prev,
3062306a36Sopenharmony_ci				    struct rb_root_cached *root)
3162306a36Sopenharmony_ci{
3262306a36Sopenharmony_ci	struct rb_node **link;
3362306a36Sopenharmony_ci	struct vm_area_struct *parent;
3462306a36Sopenharmony_ci	unsigned long last = vma_last_pgoff(node);
3562306a36Sopenharmony_ci
3662306a36Sopenharmony_ci	VM_BUG_ON_VMA(vma_start_pgoff(node) != vma_start_pgoff(prev), node);
3762306a36Sopenharmony_ci
3862306a36Sopenharmony_ci	if (!prev->shared.rb.rb_right) {
3962306a36Sopenharmony_ci		parent = prev;
4062306a36Sopenharmony_ci		link = &prev->shared.rb.rb_right;
4162306a36Sopenharmony_ci	} else {
4262306a36Sopenharmony_ci		parent = rb_entry(prev->shared.rb.rb_right,
4362306a36Sopenharmony_ci				  struct vm_area_struct, shared.rb);
4462306a36Sopenharmony_ci		if (parent->shared.rb_subtree_last < last)
4562306a36Sopenharmony_ci			parent->shared.rb_subtree_last = last;
4662306a36Sopenharmony_ci		while (parent->shared.rb.rb_left) {
4762306a36Sopenharmony_ci			parent = rb_entry(parent->shared.rb.rb_left,
4862306a36Sopenharmony_ci				struct vm_area_struct, shared.rb);
4962306a36Sopenharmony_ci			if (parent->shared.rb_subtree_last < last)
5062306a36Sopenharmony_ci				parent->shared.rb_subtree_last = last;
5162306a36Sopenharmony_ci		}
5262306a36Sopenharmony_ci		link = &parent->shared.rb.rb_left;
5362306a36Sopenharmony_ci	}
5462306a36Sopenharmony_ci
5562306a36Sopenharmony_ci	node->shared.rb_subtree_last = last;
5662306a36Sopenharmony_ci	rb_link_node(&node->shared.rb, &parent->shared.rb, link);
5762306a36Sopenharmony_ci	rb_insert_augmented(&node->shared.rb, &root->rb_root,
5862306a36Sopenharmony_ci			    &vma_interval_tree_augment);
5962306a36Sopenharmony_ci}
6062306a36Sopenharmony_ci
6162306a36Sopenharmony_cistatic inline unsigned long avc_start_pgoff(struct anon_vma_chain *avc)
6262306a36Sopenharmony_ci{
6362306a36Sopenharmony_ci	return vma_start_pgoff(avc->vma);
6462306a36Sopenharmony_ci}
6562306a36Sopenharmony_ci
6662306a36Sopenharmony_cistatic inline unsigned long avc_last_pgoff(struct anon_vma_chain *avc)
6762306a36Sopenharmony_ci{
6862306a36Sopenharmony_ci	return vma_last_pgoff(avc->vma);
6962306a36Sopenharmony_ci}
7062306a36Sopenharmony_ci
7162306a36Sopenharmony_ciINTERVAL_TREE_DEFINE(struct anon_vma_chain, rb, unsigned long, rb_subtree_last,
7262306a36Sopenharmony_ci		     avc_start_pgoff, avc_last_pgoff,
7362306a36Sopenharmony_ci		     static inline, __anon_vma_interval_tree)
7462306a36Sopenharmony_ci
7562306a36Sopenharmony_civoid anon_vma_interval_tree_insert(struct anon_vma_chain *node,
7662306a36Sopenharmony_ci				   struct rb_root_cached *root)
7762306a36Sopenharmony_ci{
7862306a36Sopenharmony_ci#ifdef CONFIG_DEBUG_VM_RB
7962306a36Sopenharmony_ci	node->cached_vma_start = avc_start_pgoff(node);
8062306a36Sopenharmony_ci	node->cached_vma_last = avc_last_pgoff(node);
8162306a36Sopenharmony_ci#endif
8262306a36Sopenharmony_ci	__anon_vma_interval_tree_insert(node, root);
8362306a36Sopenharmony_ci}
8462306a36Sopenharmony_ci
8562306a36Sopenharmony_civoid anon_vma_interval_tree_remove(struct anon_vma_chain *node,
8662306a36Sopenharmony_ci				   struct rb_root_cached *root)
8762306a36Sopenharmony_ci{
8862306a36Sopenharmony_ci	__anon_vma_interval_tree_remove(node, root);
8962306a36Sopenharmony_ci}
9062306a36Sopenharmony_ci
9162306a36Sopenharmony_cistruct anon_vma_chain *
9262306a36Sopenharmony_cianon_vma_interval_tree_iter_first(struct rb_root_cached *root,
9362306a36Sopenharmony_ci				  unsigned long first, unsigned long last)
9462306a36Sopenharmony_ci{
9562306a36Sopenharmony_ci	return __anon_vma_interval_tree_iter_first(root, first, last);
9662306a36Sopenharmony_ci}
9762306a36Sopenharmony_ci
9862306a36Sopenharmony_cistruct anon_vma_chain *
9962306a36Sopenharmony_cianon_vma_interval_tree_iter_next(struct anon_vma_chain *node,
10062306a36Sopenharmony_ci				 unsigned long first, unsigned long last)
10162306a36Sopenharmony_ci{
10262306a36Sopenharmony_ci	return __anon_vma_interval_tree_iter_next(node, first, last);
10362306a36Sopenharmony_ci}
10462306a36Sopenharmony_ci
10562306a36Sopenharmony_ci#ifdef CONFIG_DEBUG_VM_RB
10662306a36Sopenharmony_civoid anon_vma_interval_tree_verify(struct anon_vma_chain *node)
10762306a36Sopenharmony_ci{
10862306a36Sopenharmony_ci	WARN_ON_ONCE(node->cached_vma_start != avc_start_pgoff(node));
10962306a36Sopenharmony_ci	WARN_ON_ONCE(node->cached_vma_last != avc_last_pgoff(node));
11062306a36Sopenharmony_ci}
11162306a36Sopenharmony_ci#endif
112