diff options
author | Chris Wilson <chris@chris-wilson.co.uk> | 2017-12-14 18:32:28 -0500 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2017-12-14 19:00:48 -0500 |
commit | 338f1d9d1b829fec494d053f62820a2ee625b1ec (patch) | |
tree | 9ac2dd5f45f7e251300f677ccf669efa9ef303cd | |
parent | c47d7f56e914900410f65835933f9fc4374d0a2b (diff) |
lib/rbtree,drm/mm: add rbtree_replace_node_cached()
Add a variant of rbtree_replace_node() that maintains the leftmost cache
of struct rbtree_root_cached when replacing nodes within the rbtree.
As drm_mm is the only rb_replace_node() being used on an interval tree,
the mistake looks fairly self-contained. Furthermore the only user of
drm_mm_replace_node() is its testsuite...
Testcase: igt/drm_mm/replace
Link: http://lkml.kernel.org/r/20171122100729.3742-1-chris@chris-wilson.co.uk
Link: https://patchwork.freedesktop.org/patch/msgid/20171109212435.9265-1-chris@chris-wilson.co.uk
Fixes: f808c13fd373 ("lib/interval_tree: fast overlap detection")
Signed-off-by: Chris Wilson <chris@chris-wilson.co.uk>
Reviewed-by: Joonas Lahtinen <joonas.lahtinen@linux.intel.com>
Acked-by: Davidlohr Bueso <dbueso@suse.de>
Cc: Jérôme Glisse <jglisse@redhat.com>
Cc: Joonas Lahtinen <joonas.lahtinen@linux.intel.com>
Cc: Daniel Vetter <daniel.vetter@ffwll.ch>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
-rw-r--r-- | drivers/gpu/drm/drm_mm.c | 8 | ||||
-rw-r--r-- | include/linux/rbtree.h | 2 | ||||
-rw-r--r-- | lib/rbtree.c | 10 |
3 files changed, 17 insertions, 3 deletions
diff --git a/drivers/gpu/drm/drm_mm.c b/drivers/gpu/drm/drm_mm.c index 61a1c8ea74bc..c3c79ee6119e 100644 --- a/drivers/gpu/drm/drm_mm.c +++ b/drivers/gpu/drm/drm_mm.c | |||
@@ -575,21 +575,23 @@ EXPORT_SYMBOL(drm_mm_remove_node); | |||
575 | */ | 575 | */ |
576 | void drm_mm_replace_node(struct drm_mm_node *old, struct drm_mm_node *new) | 576 | void drm_mm_replace_node(struct drm_mm_node *old, struct drm_mm_node *new) |
577 | { | 577 | { |
578 | struct drm_mm *mm = old->mm; | ||
579 | |||
578 | DRM_MM_BUG_ON(!old->allocated); | 580 | DRM_MM_BUG_ON(!old->allocated); |
579 | 581 | ||
580 | *new = *old; | 582 | *new = *old; |
581 | 583 | ||
582 | list_replace(&old->node_list, &new->node_list); | 584 | list_replace(&old->node_list, &new->node_list); |
583 | rb_replace_node(&old->rb, &new->rb, &old->mm->interval_tree.rb_root); | 585 | rb_replace_node_cached(&old->rb, &new->rb, &mm->interval_tree); |
584 | 586 | ||
585 | if (drm_mm_hole_follows(old)) { | 587 | if (drm_mm_hole_follows(old)) { |
586 | list_replace(&old->hole_stack, &new->hole_stack); | 588 | list_replace(&old->hole_stack, &new->hole_stack); |
587 | rb_replace_node(&old->rb_hole_size, | 589 | rb_replace_node(&old->rb_hole_size, |
588 | &new->rb_hole_size, | 590 | &new->rb_hole_size, |
589 | &old->mm->holes_size); | 591 | &mm->holes_size); |
590 | rb_replace_node(&old->rb_hole_addr, | 592 | rb_replace_node(&old->rb_hole_addr, |
591 | &new->rb_hole_addr, | 593 | &new->rb_hole_addr, |
592 | &old->mm->holes_addr); | 594 | &mm->holes_addr); |
593 | } | 595 | } |
594 | 596 | ||
595 | old->allocated = false; | 597 | old->allocated = false; |
diff --git a/include/linux/rbtree.h b/include/linux/rbtree.h index d574361943ea..fcbeed4053ef 100644 --- a/include/linux/rbtree.h +++ b/include/linux/rbtree.h | |||
@@ -99,6 +99,8 @@ extern void rb_replace_node(struct rb_node *victim, struct rb_node *new, | |||
99 | struct rb_root *root); | 99 | struct rb_root *root); |
100 | extern void rb_replace_node_rcu(struct rb_node *victim, struct rb_node *new, | 100 | extern void rb_replace_node_rcu(struct rb_node *victim, struct rb_node *new, |
101 | struct rb_root *root); | 101 | struct rb_root *root); |
102 | extern void rb_replace_node_cached(struct rb_node *victim, struct rb_node *new, | ||
103 | struct rb_root_cached *root); | ||
102 | 104 | ||
103 | static inline void rb_link_node(struct rb_node *node, struct rb_node *parent, | 105 | static inline void rb_link_node(struct rb_node *node, struct rb_node *parent, |
104 | struct rb_node **rb_link) | 106 | struct rb_node **rb_link) |
diff --git a/lib/rbtree.c b/lib/rbtree.c index ba4a9d165f1b..d3ff682fd4b8 100644 --- a/lib/rbtree.c +++ b/lib/rbtree.c | |||
@@ -603,6 +603,16 @@ void rb_replace_node(struct rb_node *victim, struct rb_node *new, | |||
603 | } | 603 | } |
604 | EXPORT_SYMBOL(rb_replace_node); | 604 | EXPORT_SYMBOL(rb_replace_node); |
605 | 605 | ||
606 | void rb_replace_node_cached(struct rb_node *victim, struct rb_node *new, | ||
607 | struct rb_root_cached *root) | ||
608 | { | ||
609 | rb_replace_node(victim, new, &root->rb_root); | ||
610 | |||
611 | if (root->rb_leftmost == victim) | ||
612 | root->rb_leftmost = new; | ||
613 | } | ||
614 | EXPORT_SYMBOL(rb_replace_node_cached); | ||
615 | |||
606 | void rb_replace_node_rcu(struct rb_node *victim, struct rb_node *new, | 616 | void rb_replace_node_rcu(struct rb_node *victim, struct rb_node *new, |
607 | struct rb_root *root) | 617 | struct rb_root *root) |
608 | { | 618 | { |