18c2ecf20Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0-only
28c2ecf20Sopenharmony_ci/*
38c2ecf20Sopenharmony_ci * mm/interval_tree.c - interval tree for mapping->i_mmap
48c2ecf20Sopenharmony_ci *
58c2ecf20Sopenharmony_ci * Copyright (C) 2012, Michel Lespinasse <walken@google.com>
68c2ecf20Sopenharmony_ci */
78c2ecf20Sopenharmony_ci
88c2ecf20Sopenharmony_ci#include <linux/mm.h>
98c2ecf20Sopenharmony_ci#include <linux/fs.h>
108c2ecf20Sopenharmony_ci#include <linux/rmap.h>
118c2ecf20Sopenharmony_ci#include <linux/interval_tree_generic.h>
128c2ecf20Sopenharmony_ci
138c2ecf20Sopenharmony_cistatic inline unsigned long vma_start_pgoff(struct vm_area_struct *v)
148c2ecf20Sopenharmony_ci{
158c2ecf20Sopenharmony_ci	return v->vm_pgoff;
168c2ecf20Sopenharmony_ci}
178c2ecf20Sopenharmony_ci
188c2ecf20Sopenharmony_cistatic inline unsigned long vma_last_pgoff(struct vm_area_struct *v)
198c2ecf20Sopenharmony_ci{
208c2ecf20Sopenharmony_ci	return v->vm_pgoff + vma_pages(v) - 1;
218c2ecf20Sopenharmony_ci}
228c2ecf20Sopenharmony_ci
238c2ecf20Sopenharmony_ciINTERVAL_TREE_DEFINE(struct vm_area_struct, shared.rb,
248c2ecf20Sopenharmony_ci		     unsigned long, shared.rb_subtree_last,
258c2ecf20Sopenharmony_ci		     vma_start_pgoff, vma_last_pgoff,, vma_interval_tree)
268c2ecf20Sopenharmony_ci
278c2ecf20Sopenharmony_ci/* Insert node immediately after prev in the interval tree */
288c2ecf20Sopenharmony_civoid vma_interval_tree_insert_after(struct vm_area_struct *node,
298c2ecf20Sopenharmony_ci				    struct vm_area_struct *prev,
308c2ecf20Sopenharmony_ci				    struct rb_root_cached *root)
318c2ecf20Sopenharmony_ci{
328c2ecf20Sopenharmony_ci	struct rb_node **link;
338c2ecf20Sopenharmony_ci	struct vm_area_struct *parent;
348c2ecf20Sopenharmony_ci	unsigned long last = vma_last_pgoff(node);
358c2ecf20Sopenharmony_ci
368c2ecf20Sopenharmony_ci	VM_BUG_ON_VMA(vma_start_pgoff(node) != vma_start_pgoff(prev), node);
378c2ecf20Sopenharmony_ci
388c2ecf20Sopenharmony_ci	if (!prev->shared.rb.rb_right) {
398c2ecf20Sopenharmony_ci		parent = prev;
408c2ecf20Sopenharmony_ci		link = &prev->shared.rb.rb_right;
418c2ecf20Sopenharmony_ci	} else {
428c2ecf20Sopenharmony_ci		parent = rb_entry(prev->shared.rb.rb_right,
438c2ecf20Sopenharmony_ci				  struct vm_area_struct, shared.rb);
448c2ecf20Sopenharmony_ci		if (parent->shared.rb_subtree_last < last)
458c2ecf20Sopenharmony_ci			parent->shared.rb_subtree_last = last;
468c2ecf20Sopenharmony_ci		while (parent->shared.rb.rb_left) {
478c2ecf20Sopenharmony_ci			parent = rb_entry(parent->shared.rb.rb_left,
488c2ecf20Sopenharmony_ci				struct vm_area_struct, shared.rb);
498c2ecf20Sopenharmony_ci			if (parent->shared.rb_subtree_last < last)
508c2ecf20Sopenharmony_ci				parent->shared.rb_subtree_last = last;
518c2ecf20Sopenharmony_ci		}
528c2ecf20Sopenharmony_ci		link = &parent->shared.rb.rb_left;
538c2ecf20Sopenharmony_ci	}
548c2ecf20Sopenharmony_ci
558c2ecf20Sopenharmony_ci	node->shared.rb_subtree_last = last;
568c2ecf20Sopenharmony_ci	rb_link_node(&node->shared.rb, &parent->shared.rb, link);
578c2ecf20Sopenharmony_ci	rb_insert_augmented(&node->shared.rb, &root->rb_root,
588c2ecf20Sopenharmony_ci			    &vma_interval_tree_augment);
598c2ecf20Sopenharmony_ci}
608c2ecf20Sopenharmony_ci
618c2ecf20Sopenharmony_cistatic inline unsigned long avc_start_pgoff(struct anon_vma_chain *avc)
628c2ecf20Sopenharmony_ci{
638c2ecf20Sopenharmony_ci	return vma_start_pgoff(avc->vma);
648c2ecf20Sopenharmony_ci}
658c2ecf20Sopenharmony_ci
668c2ecf20Sopenharmony_cistatic inline unsigned long avc_last_pgoff(struct anon_vma_chain *avc)
678c2ecf20Sopenharmony_ci{
688c2ecf20Sopenharmony_ci	return vma_last_pgoff(avc->vma);
698c2ecf20Sopenharmony_ci}
708c2ecf20Sopenharmony_ci
718c2ecf20Sopenharmony_ciINTERVAL_TREE_DEFINE(struct anon_vma_chain, rb, unsigned long, rb_subtree_last,
728c2ecf20Sopenharmony_ci		     avc_start_pgoff, avc_last_pgoff,
738c2ecf20Sopenharmony_ci		     static inline, __anon_vma_interval_tree)
748c2ecf20Sopenharmony_ci
758c2ecf20Sopenharmony_civoid anon_vma_interval_tree_insert(struct anon_vma_chain *node,
768c2ecf20Sopenharmony_ci				   struct rb_root_cached *root)
778c2ecf20Sopenharmony_ci{
788c2ecf20Sopenharmony_ci#ifdef CONFIG_DEBUG_VM_RB
798c2ecf20Sopenharmony_ci	node->cached_vma_start = avc_start_pgoff(node);
808c2ecf20Sopenharmony_ci	node->cached_vma_last = avc_last_pgoff(node);
818c2ecf20Sopenharmony_ci#endif
828c2ecf20Sopenharmony_ci	__anon_vma_interval_tree_insert(node, root);
838c2ecf20Sopenharmony_ci}
848c2ecf20Sopenharmony_ci
858c2ecf20Sopenharmony_civoid anon_vma_interval_tree_remove(struct anon_vma_chain *node,
868c2ecf20Sopenharmony_ci				   struct rb_root_cached *root)
878c2ecf20Sopenharmony_ci{
888c2ecf20Sopenharmony_ci	__anon_vma_interval_tree_remove(node, root);
898c2ecf20Sopenharmony_ci}
908c2ecf20Sopenharmony_ci
918c2ecf20Sopenharmony_cistruct anon_vma_chain *
928c2ecf20Sopenharmony_cianon_vma_interval_tree_iter_first(struct rb_root_cached *root,
938c2ecf20Sopenharmony_ci				  unsigned long first, unsigned long last)
948c2ecf20Sopenharmony_ci{
958c2ecf20Sopenharmony_ci	return __anon_vma_interval_tree_iter_first(root, first, last);
968c2ecf20Sopenharmony_ci}
978c2ecf20Sopenharmony_ci
988c2ecf20Sopenharmony_cistruct anon_vma_chain *
998c2ecf20Sopenharmony_cianon_vma_interval_tree_iter_next(struct anon_vma_chain *node,
1008c2ecf20Sopenharmony_ci				 unsigned long first, unsigned long last)
1018c2ecf20Sopenharmony_ci{
1028c2ecf20Sopenharmony_ci	return __anon_vma_interval_tree_iter_next(node, first, last);
1038c2ecf20Sopenharmony_ci}
1048c2ecf20Sopenharmony_ci
1058c2ecf20Sopenharmony_ci#ifdef CONFIG_DEBUG_VM_RB
1068c2ecf20Sopenharmony_civoid anon_vma_interval_tree_verify(struct anon_vma_chain *node)
1078c2ecf20Sopenharmony_ci{
1088c2ecf20Sopenharmony_ci	WARN_ON_ONCE(node->cached_vma_start != avc_start_pgoff(node));
1098c2ecf20Sopenharmony_ci	WARN_ON_ONCE(node->cached_vma_last != avc_last_pgoff(node));
1108c2ecf20Sopenharmony_ci}
1118c2ecf20Sopenharmony_ci#endif
112