@@ -107,8 +107,12 @@ struct damos *damon_new_scheme(
107107 scheme -> stat_sz = 0 ;
108108 INIT_LIST_HEAD (& scheme -> list );
109109
110+ scheme -> quota .ms = quota -> ms ;
110111 scheme -> quota .sz = quota -> sz ;
111112 scheme -> quota .reset_interval = quota -> reset_interval ;
113+ scheme -> quota .total_charged_sz = 0 ;
114+ scheme -> quota .total_charged_ns = 0 ;
115+ scheme -> quota .esz = 0 ;
112116 scheme -> quota .charged_sz = 0 ;
113117 scheme -> quota .charged_from = 0 ;
114118 scheme -> quota .charge_target_from = NULL ;
@@ -550,9 +554,10 @@ static void damon_do_apply_schemes(struct damon_ctx *c,
550554 damon_for_each_scheme (s , c ) {
551555 struct damos_quota * quota = & s -> quota ;
552556 unsigned long sz = r -> ar .end - r -> ar .start ;
557+ struct timespec64 begin , end ;
553558
554559 /* Check the quota */
555- if (quota -> sz && quota -> charged_sz >= quota -> sz )
560+ if (quota -> esz && quota -> charged_sz >= quota -> esz )
556561 continue ;
557562
558563 /* Skip previously charged regions */
@@ -597,16 +602,21 @@ static void damon_do_apply_schemes(struct damon_ctx *c,
597602
598603 /* Apply the scheme */
599604 if (c -> primitive .apply_scheme ) {
600- if (quota -> sz && quota -> charged_sz + sz > quota -> sz ) {
601- sz = ALIGN_DOWN (quota -> sz - quota -> charged_sz ,
605+ if (quota -> esz &&
606+ quota -> charged_sz + sz > quota -> esz ) {
607+ sz = ALIGN_DOWN (quota -> esz - quota -> charged_sz ,
602608 DAMON_MIN_REGION );
603609 if (!sz )
604610 goto update_stat ;
605611 damon_split_region_at (c , t , r , sz );
606612 }
613+ ktime_get_coarse_ts64 (& begin );
607614 c -> primitive .apply_scheme (c , t , r , s );
615+ ktime_get_coarse_ts64 (& end );
616+ quota -> total_charged_ns += timespec64_to_ns (& end ) -
617+ timespec64_to_ns (& begin );
608618 quota -> charged_sz += sz ;
609- if (quota -> sz && quota -> charged_sz >= quota -> sz ) {
619+ if (quota -> esz && quota -> charged_sz >= quota -> esz ) {
610620 quota -> charge_target_from = t ;
611621 quota -> charge_addr_from = r -> ar .end + 1 ;
612622 }
@@ -620,6 +630,29 @@ static void damon_do_apply_schemes(struct damon_ctx *c,
620630 }
621631}
622632
633+ /* Shouldn't be called if quota->ms and quota->sz are zero */
634+ static void damos_set_effective_quota (struct damos_quota * quota )
635+ {
636+ unsigned long throughput ;
637+ unsigned long esz ;
638+
639+ if (!quota -> ms ) {
640+ quota -> esz = quota -> sz ;
641+ return ;
642+ }
643+
644+ if (quota -> total_charged_ns )
645+ throughput = quota -> total_charged_sz * 1000000 /
646+ quota -> total_charged_ns ;
647+ else
648+ throughput = PAGE_SIZE * 1024 ;
649+ esz = throughput * quota -> ms ;
650+
651+ if (quota -> sz && quota -> sz < esz )
652+ esz = quota -> sz ;
653+ quota -> esz = esz ;
654+ }
655+
623656static void kdamond_apply_schemes (struct damon_ctx * c )
624657{
625658 struct damon_target * t ;
@@ -629,15 +662,17 @@ static void kdamond_apply_schemes(struct damon_ctx *c)
629662 damon_for_each_scheme (s , c ) {
630663 struct damos_quota * quota = & s -> quota ;
631664
632- if (!quota -> sz )
665+ if (!quota -> ms && ! quota -> sz )
633666 continue ;
634667
635668 /* New charge window starts */
636669 if (time_after_eq (jiffies , quota -> charged_from +
637670 msecs_to_jiffies (
638671 quota -> reset_interval ))) {
672+ quota -> total_charged_sz += quota -> charged_sz ;
639673 quota -> charged_from = jiffies ;
640674 quota -> charged_sz = 0 ;
675+ damos_set_effective_quota (quota );
641676 }
642677 }
643678
0 commit comments