@@ -496,6 +496,10 @@ struct ttm_bo_alloc_state {
496496 struct dmem_cgroup_pool_state * limit_pool ;
497497 /** @in_evict: Whether we are currently evicting buffers */
498498 bool in_evict ;
499+ /** @may_try_low: If only unprotected BOs, i.e. BOs whose cgroup
500+ * is exceeding its dmem low/min protection, should be considered for eviction
501+ */
502+ bool may_try_low ;
499503};
500504
501505/**
@@ -545,6 +549,42 @@ static int ttm_bo_alloc_at_place(struct ttm_buffer_object *bo,
545549 }
546550 }
547551
552+ /*
553+ * cgroup protection plays a special role in eviction.
554+ * Conceptually, protection of memory via the dmem cgroup controller
555+ * entitles the protected cgroup to use a certain amount of memory.
556+ * There are two types of protection - the 'low' limit is a
557+ * "best-effort" protection, whereas the 'min' limit provides a hard
558+ * guarantee that memory within the cgroup's allowance will not be
559+ * evicted under any circumstance.
560+ *
561+ * To faithfully model this concept in TTM, we also need to take cgroup
562+ * protection into account when allocating. When allocation in one
563+ * place fails, TTM will default to trying other places first before
564+ * evicting.
565+ * If the allocation is covered by dmem cgroup protection, however,
566+ * this prevents the allocation from using the memory it is "entitled"
567+ * to. To make sure unprotected allocations cannot push new protected
568+ * allocations out of places they are "entitled" to use, we should
569+ * evict buffers not covered by any cgroup protection, if this
570+ * allocation is covered by cgroup protection.
571+ *
572+ * Buffers covered by 'min' protection are a special case - the 'min'
573+ * limit is a stronger guarantee than 'low', and thus buffers protected
574+ * by 'low' but not 'min' should also be considered for eviction.
575+ * Buffers protected by 'min' will never be considered for eviction
576+ * anyway, so the regular eviction path should be triggered here.
577+ * Buffers protected by 'low' but not 'min' will take a special
578+ * eviction path that only evicts buffers covered by neither 'low' or
579+ * 'min' protections.
580+ */
581+ if (!alloc_state -> in_evict ) {
582+ may_evict |= dmem_cgroup_below_min (NULL , alloc_state -> charge_pool );
583+ alloc_state -> may_try_low = may_evict ;
584+
585+ may_evict |= dmem_cgroup_below_low (NULL , alloc_state -> charge_pool );
586+ }
587+
548588 ret = ttm_resource_alloc (bo , place , res , alloc_state -> charge_pool );
549589 if (ret ) {
550590 if (ret == - ENOSPC && may_evict )
@@ -657,8 +697,12 @@ static int ttm_bo_evict_alloc(struct ttm_device *bdev,
657697 evict_walk .walk .arg .trylock_only = true;
658698 lret = ttm_lru_walk_for_evict (& evict_walk .walk , bdev , man , 1 );
659699
660- /* One more attempt if we hit low limit? */
661- if (!lret && evict_walk .hit_low ) {
700+ /* If we failed to find enough BOs to evict, but we skipped over
701+ * some BOs because they were covered by dmem low protection, retry
702+ * evicting these protected BOs too, except if we're told not to
703+ * consider protected BOs at all.
704+ */
705+ if (!lret && evict_walk .hit_low && state -> may_try_low ) {
662706 evict_walk .try_low = true;
663707 lret = ttm_lru_walk_for_evict (& evict_walk .walk , bdev , man , 1 );
664708 }
@@ -679,7 +723,8 @@ static int ttm_bo_evict_alloc(struct ttm_device *bdev,
679723 } while (!lret && evict_walk .evicted );
680724
681725 /* We hit the low limit? Try once more */
682- if (!lret && evict_walk .hit_low && !evict_walk .try_low ) {
726+ if (!lret && evict_walk .hit_low && !evict_walk .try_low &&
727+ state -> may_try_low ) {
683728 evict_walk .try_low = true;
684729 goto retry ;
685730 }
0 commit comments