0001
0002
0003
0004
0005
0006
0007
0008 #define pr_fmt(fmt) "damon: " fmt
0009
0010 #include <linux/damon.h>
0011 #include <linux/delay.h>
0012 #include <linux/kthread.h>
0013 #include <linux/mm.h>
0014 #include <linux/slab.h>
0015 #include <linux/string.h>
0016
0017 #define CREATE_TRACE_POINTS
0018 #include <trace/events/damon.h>
0019
0020 #ifdef CONFIG_DAMON_KUNIT_TEST
0021 #undef DAMON_MIN_REGION
0022 #define DAMON_MIN_REGION 1
0023 #endif
0024
0025 static DEFINE_MUTEX(damon_lock);
0026 static int nr_running_ctxs;
0027 static bool running_exclusive_ctxs;
0028
0029 static DEFINE_MUTEX(damon_ops_lock);
0030 static struct damon_operations damon_registered_ops[NR_DAMON_OPS];
0031
0032
0033 static bool __damon_is_registered_ops(enum damon_ops_id id)
0034 {
0035 struct damon_operations empty_ops = {};
0036
0037 if (!memcmp(&empty_ops, &damon_registered_ops[id], sizeof(empty_ops)))
0038 return false;
0039 return true;
0040 }
0041
0042
0043
0044
0045
0046
0047
0048 bool damon_is_registered_ops(enum damon_ops_id id)
0049 {
0050 bool registered;
0051
0052 if (id >= NR_DAMON_OPS)
0053 return false;
0054 mutex_lock(&damon_ops_lock);
0055 registered = __damon_is_registered_ops(id);
0056 mutex_unlock(&damon_ops_lock);
0057 return registered;
0058 }
0059
0060
0061
0062
0063
0064
0065
0066
0067
0068
0069 int damon_register_ops(struct damon_operations *ops)
0070 {
0071 int err = 0;
0072
0073 if (ops->id >= NR_DAMON_OPS)
0074 return -EINVAL;
0075 mutex_lock(&damon_ops_lock);
0076
0077 if (__damon_is_registered_ops(ops->id)) {
0078 err = -EINVAL;
0079 goto out;
0080 }
0081 damon_registered_ops[ops->id] = *ops;
0082 out:
0083 mutex_unlock(&damon_ops_lock);
0084 return err;
0085 }
0086
0087
0088
0089
0090
0091
0092
0093
0094
0095
0096
0097 int damon_select_ops(struct damon_ctx *ctx, enum damon_ops_id id)
0098 {
0099 int err = 0;
0100
0101 if (id >= NR_DAMON_OPS)
0102 return -EINVAL;
0103
0104 mutex_lock(&damon_ops_lock);
0105 if (!__damon_is_registered_ops(id))
0106 err = -EINVAL;
0107 else
0108 ctx->ops = damon_registered_ops[id];
0109 mutex_unlock(&damon_ops_lock);
0110 return err;
0111 }
0112
0113
0114
0115
0116
0117
0118 struct damon_region *damon_new_region(unsigned long start, unsigned long end)
0119 {
0120 struct damon_region *region;
0121
0122 region = kmalloc(sizeof(*region), GFP_KERNEL);
0123 if (!region)
0124 return NULL;
0125
0126 region->ar.start = start;
0127 region->ar.end = end;
0128 region->nr_accesses = 0;
0129 INIT_LIST_HEAD(®ion->list);
0130
0131 region->age = 0;
0132 region->last_nr_accesses = 0;
0133
0134 return region;
0135 }
0136
0137 void damon_add_region(struct damon_region *r, struct damon_target *t)
0138 {
0139 list_add_tail(&r->list, &t->regions_list);
0140 t->nr_regions++;
0141 }
0142
0143 static void damon_del_region(struct damon_region *r, struct damon_target *t)
0144 {
0145 list_del(&r->list);
0146 t->nr_regions--;
0147 }
0148
0149 static void damon_free_region(struct damon_region *r)
0150 {
0151 kfree(r);
0152 }
0153
0154 void damon_destroy_region(struct damon_region *r, struct damon_target *t)
0155 {
0156 damon_del_region(r, t);
0157 damon_free_region(r);
0158 }
0159
0160
0161
0162
0163
0164
0165 static bool damon_intersect(struct damon_region *r,
0166 struct damon_addr_range *re)
0167 {
0168 return !(r->ar.end <= re->start || re->end <= r->ar.start);
0169 }
0170
0171
0172
0173
0174
0175
0176
0177
0178
0179
0180
0181
0182 int damon_set_regions(struct damon_target *t, struct damon_addr_range *ranges,
0183 unsigned int nr_ranges)
0184 {
0185 struct damon_region *r, *next;
0186 unsigned int i;
0187
0188
0189 damon_for_each_region_safe(r, next, t) {
0190 for (i = 0; i < nr_ranges; i++) {
0191 if (damon_intersect(r, &ranges[i]))
0192 break;
0193 }
0194 if (i == nr_ranges)
0195 damon_destroy_region(r, t);
0196 }
0197
0198
0199 for (i = 0; i < nr_ranges; i++) {
0200 struct damon_region *first = NULL, *last, *newr;
0201 struct damon_addr_range *range;
0202
0203 range = &ranges[i];
0204
0205 damon_for_each_region(r, t) {
0206 if (damon_intersect(r, range)) {
0207 if (!first)
0208 first = r;
0209 last = r;
0210 }
0211 if (r->ar.start >= range->end)
0212 break;
0213 }
0214 if (!first) {
0215
0216 newr = damon_new_region(
0217 ALIGN_DOWN(range->start,
0218 DAMON_MIN_REGION),
0219 ALIGN(range->end, DAMON_MIN_REGION));
0220 if (!newr)
0221 return -ENOMEM;
0222 damon_insert_region(newr, damon_prev_region(r), r, t);
0223 } else {
0224
0225 first->ar.start = ALIGN_DOWN(range->start,
0226 DAMON_MIN_REGION);
0227 last->ar.end = ALIGN(range->end, DAMON_MIN_REGION);
0228 }
0229 }
0230 return 0;
0231 }
0232
0233 struct damos *damon_new_scheme(
0234 unsigned long min_sz_region, unsigned long max_sz_region,
0235 unsigned int min_nr_accesses, unsigned int max_nr_accesses,
0236 unsigned int min_age_region, unsigned int max_age_region,
0237 enum damos_action action, struct damos_quota *quota,
0238 struct damos_watermarks *wmarks)
0239 {
0240 struct damos *scheme;
0241
0242 scheme = kmalloc(sizeof(*scheme), GFP_KERNEL);
0243 if (!scheme)
0244 return NULL;
0245 scheme->min_sz_region = min_sz_region;
0246 scheme->max_sz_region = max_sz_region;
0247 scheme->min_nr_accesses = min_nr_accesses;
0248 scheme->max_nr_accesses = max_nr_accesses;
0249 scheme->min_age_region = min_age_region;
0250 scheme->max_age_region = max_age_region;
0251 scheme->action = action;
0252 scheme->stat = (struct damos_stat){};
0253 INIT_LIST_HEAD(&scheme->list);
0254
0255 scheme->quota.ms = quota->ms;
0256 scheme->quota.sz = quota->sz;
0257 scheme->quota.reset_interval = quota->reset_interval;
0258 scheme->quota.weight_sz = quota->weight_sz;
0259 scheme->quota.weight_nr_accesses = quota->weight_nr_accesses;
0260 scheme->quota.weight_age = quota->weight_age;
0261 scheme->quota.total_charged_sz = 0;
0262 scheme->quota.total_charged_ns = 0;
0263 scheme->quota.esz = 0;
0264 scheme->quota.charged_sz = 0;
0265 scheme->quota.charged_from = 0;
0266 scheme->quota.charge_target_from = NULL;
0267 scheme->quota.charge_addr_from = 0;
0268
0269 scheme->wmarks.metric = wmarks->metric;
0270 scheme->wmarks.interval = wmarks->interval;
0271 scheme->wmarks.high = wmarks->high;
0272 scheme->wmarks.mid = wmarks->mid;
0273 scheme->wmarks.low = wmarks->low;
0274 scheme->wmarks.activated = true;
0275
0276 return scheme;
0277 }
0278
0279 void damon_add_scheme(struct damon_ctx *ctx, struct damos *s)
0280 {
0281 list_add_tail(&s->list, &ctx->schemes);
0282 }
0283
0284 static void damon_del_scheme(struct damos *s)
0285 {
0286 list_del(&s->list);
0287 }
0288
0289 static void damon_free_scheme(struct damos *s)
0290 {
0291 kfree(s);
0292 }
0293
0294 void damon_destroy_scheme(struct damos *s)
0295 {
0296 damon_del_scheme(s);
0297 damon_free_scheme(s);
0298 }
0299
0300
0301
0302
0303
0304
0305 struct damon_target *damon_new_target(void)
0306 {
0307 struct damon_target *t;
0308
0309 t = kmalloc(sizeof(*t), GFP_KERNEL);
0310 if (!t)
0311 return NULL;
0312
0313 t->pid = NULL;
0314 t->nr_regions = 0;
0315 INIT_LIST_HEAD(&t->regions_list);
0316
0317 return t;
0318 }
0319
0320 void damon_add_target(struct damon_ctx *ctx, struct damon_target *t)
0321 {
0322 list_add_tail(&t->list, &ctx->adaptive_targets);
0323 }
0324
0325 bool damon_targets_empty(struct damon_ctx *ctx)
0326 {
0327 return list_empty(&ctx->adaptive_targets);
0328 }
0329
0330 static void damon_del_target(struct damon_target *t)
0331 {
0332 list_del(&t->list);
0333 }
0334
0335 void damon_free_target(struct damon_target *t)
0336 {
0337 struct damon_region *r, *next;
0338
0339 damon_for_each_region_safe(r, next, t)
0340 damon_free_region(r);
0341 kfree(t);
0342 }
0343
0344 void damon_destroy_target(struct damon_target *t)
0345 {
0346 damon_del_target(t);
0347 damon_free_target(t);
0348 }
0349
0350 unsigned int damon_nr_regions(struct damon_target *t)
0351 {
0352 return t->nr_regions;
0353 }
0354
0355 struct damon_ctx *damon_new_ctx(void)
0356 {
0357 struct damon_ctx *ctx;
0358
0359 ctx = kzalloc(sizeof(*ctx), GFP_KERNEL);
0360 if (!ctx)
0361 return NULL;
0362
0363 ctx->sample_interval = 5 * 1000;
0364 ctx->aggr_interval = 100 * 1000;
0365 ctx->ops_update_interval = 60 * 1000 * 1000;
0366
0367 ktime_get_coarse_ts64(&ctx->last_aggregation);
0368 ctx->last_ops_update = ctx->last_aggregation;
0369
0370 mutex_init(&ctx->kdamond_lock);
0371
0372 ctx->min_nr_regions = 10;
0373 ctx->max_nr_regions = 1000;
0374
0375 INIT_LIST_HEAD(&ctx->adaptive_targets);
0376 INIT_LIST_HEAD(&ctx->schemes);
0377
0378 return ctx;
0379 }
0380
0381 static void damon_destroy_targets(struct damon_ctx *ctx)
0382 {
0383 struct damon_target *t, *next_t;
0384
0385 if (ctx->ops.cleanup) {
0386 ctx->ops.cleanup(ctx);
0387 return;
0388 }
0389
0390 damon_for_each_target_safe(t, next_t, ctx)
0391 damon_destroy_target(t);
0392 }
0393
0394 void damon_destroy_ctx(struct damon_ctx *ctx)
0395 {
0396 struct damos *s, *next_s;
0397
0398 damon_destroy_targets(ctx);
0399
0400 damon_for_each_scheme_safe(s, next_s, ctx)
0401 damon_destroy_scheme(s);
0402
0403 kfree(ctx);
0404 }
0405
0406
0407
0408
0409
0410
0411
0412
0413
0414
0415
0416
0417
0418
0419
0420 int damon_set_attrs(struct damon_ctx *ctx, unsigned long sample_int,
0421 unsigned long aggr_int, unsigned long ops_upd_int,
0422 unsigned long min_nr_reg, unsigned long max_nr_reg)
0423 {
0424 if (min_nr_reg < 3)
0425 return -EINVAL;
0426 if (min_nr_reg > max_nr_reg)
0427 return -EINVAL;
0428
0429 ctx->sample_interval = sample_int;
0430 ctx->aggr_interval = aggr_int;
0431 ctx->ops_update_interval = ops_upd_int;
0432 ctx->min_nr_regions = min_nr_reg;
0433 ctx->max_nr_regions = max_nr_reg;
0434
0435 return 0;
0436 }
0437
0438
0439
0440
0441
0442
0443
0444
0445
0446
0447
0448
0449 int damon_set_schemes(struct damon_ctx *ctx, struct damos **schemes,
0450 ssize_t nr_schemes)
0451 {
0452 struct damos *s, *next;
0453 ssize_t i;
0454
0455 damon_for_each_scheme_safe(s, next, ctx)
0456 damon_destroy_scheme(s);
0457 for (i = 0; i < nr_schemes; i++)
0458 damon_add_scheme(ctx, schemes[i]);
0459 return 0;
0460 }
0461
0462
0463
0464
0465 int damon_nr_running_ctxs(void)
0466 {
0467 int nr_ctxs;
0468
0469 mutex_lock(&damon_lock);
0470 nr_ctxs = nr_running_ctxs;
0471 mutex_unlock(&damon_lock);
0472
0473 return nr_ctxs;
0474 }
0475
0476
0477 static unsigned long damon_region_sz_limit(struct damon_ctx *ctx)
0478 {
0479 struct damon_target *t;
0480 struct damon_region *r;
0481 unsigned long sz = 0;
0482
0483 damon_for_each_target(t, ctx) {
0484 damon_for_each_region(r, t)
0485 sz += r->ar.end - r->ar.start;
0486 }
0487
0488 if (ctx->min_nr_regions)
0489 sz /= ctx->min_nr_regions;
0490 if (sz < DAMON_MIN_REGION)
0491 sz = DAMON_MIN_REGION;
0492
0493 return sz;
0494 }
0495
0496 static int kdamond_fn(void *data);
0497
0498
0499
0500
0501
0502
0503
0504
0505
0506 static int __damon_start(struct damon_ctx *ctx)
0507 {
0508 int err = -EBUSY;
0509
0510 mutex_lock(&ctx->kdamond_lock);
0511 if (!ctx->kdamond) {
0512 err = 0;
0513 ctx->kdamond = kthread_run(kdamond_fn, ctx, "kdamond.%d",
0514 nr_running_ctxs);
0515 if (IS_ERR(ctx->kdamond)) {
0516 err = PTR_ERR(ctx->kdamond);
0517 ctx->kdamond = NULL;
0518 }
0519 }
0520 mutex_unlock(&ctx->kdamond_lock);
0521
0522 return err;
0523 }
0524
0525
0526
0527
0528
0529
0530
0531
0532
0533
0534
0535
0536
0537
0538
0539
0540 int damon_start(struct damon_ctx **ctxs, int nr_ctxs, bool exclusive)
0541 {
0542 int i;
0543 int err = 0;
0544
0545 mutex_lock(&damon_lock);
0546 if ((exclusive && nr_running_ctxs) ||
0547 (!exclusive && running_exclusive_ctxs)) {
0548 mutex_unlock(&damon_lock);
0549 return -EBUSY;
0550 }
0551
0552 for (i = 0; i < nr_ctxs; i++) {
0553 err = __damon_start(ctxs[i]);
0554 if (err)
0555 break;
0556 nr_running_ctxs++;
0557 }
0558 if (exclusive && nr_running_ctxs)
0559 running_exclusive_ctxs = true;
0560 mutex_unlock(&damon_lock);
0561
0562 return err;
0563 }
0564
0565
0566
0567
0568
0569
0570
0571 static int __damon_stop(struct damon_ctx *ctx)
0572 {
0573 struct task_struct *tsk;
0574
0575 mutex_lock(&ctx->kdamond_lock);
0576 tsk = ctx->kdamond;
0577 if (tsk) {
0578 get_task_struct(tsk);
0579 mutex_unlock(&ctx->kdamond_lock);
0580 kthread_stop(tsk);
0581 put_task_struct(tsk);
0582 return 0;
0583 }
0584 mutex_unlock(&ctx->kdamond_lock);
0585
0586 return -EPERM;
0587 }
0588
0589
0590
0591
0592
0593
0594
0595
0596 int damon_stop(struct damon_ctx **ctxs, int nr_ctxs)
0597 {
0598 int i, err = 0;
0599
0600 for (i = 0; i < nr_ctxs; i++) {
0601
0602 err = __damon_stop(ctxs[i]);
0603 if (err)
0604 break;
0605 }
0606 return err;
0607 }
0608
0609
0610
0611
0612
0613
0614
0615
0616
0617
0618
0619 static bool damon_check_reset_time_interval(struct timespec64 *baseline,
0620 unsigned long interval)
0621 {
0622 struct timespec64 now;
0623
0624 ktime_get_coarse_ts64(&now);
0625 if ((timespec64_to_ns(&now) - timespec64_to_ns(baseline)) <
0626 interval * 1000)
0627 return false;
0628 *baseline = now;
0629 return true;
0630 }
0631
0632
0633
0634
0635 static bool kdamond_aggregate_interval_passed(struct damon_ctx *ctx)
0636 {
0637 return damon_check_reset_time_interval(&ctx->last_aggregation,
0638 ctx->aggr_interval);
0639 }
0640
0641
0642
0643
0644 static void kdamond_reset_aggregated(struct damon_ctx *c)
0645 {
0646 struct damon_target *t;
0647 unsigned int ti = 0;
0648
0649 damon_for_each_target(t, c) {
0650 struct damon_region *r;
0651
0652 damon_for_each_region(r, t) {
0653 trace_damon_aggregated(t, ti, r, damon_nr_regions(t));
0654 r->last_nr_accesses = r->nr_accesses;
0655 r->nr_accesses = 0;
0656 }
0657 ti++;
0658 }
0659 }
0660
0661 static void damon_split_region_at(struct damon_ctx *ctx,
0662 struct damon_target *t, struct damon_region *r,
0663 unsigned long sz_r);
0664
0665 static bool __damos_valid_target(struct damon_region *r, struct damos *s)
0666 {
0667 unsigned long sz;
0668
0669 sz = r->ar.end - r->ar.start;
0670 return s->min_sz_region <= sz && sz <= s->max_sz_region &&
0671 s->min_nr_accesses <= r->nr_accesses &&
0672 r->nr_accesses <= s->max_nr_accesses &&
0673 s->min_age_region <= r->age && r->age <= s->max_age_region;
0674 }
0675
0676 static bool damos_valid_target(struct damon_ctx *c, struct damon_target *t,
0677 struct damon_region *r, struct damos *s)
0678 {
0679 bool ret = __damos_valid_target(r, s);
0680
0681 if (!ret || !s->quota.esz || !c->ops.get_scheme_score)
0682 return ret;
0683
0684 return c->ops.get_scheme_score(c, t, r, s) >= s->quota.min_score;
0685 }
0686
0687 static void damon_do_apply_schemes(struct damon_ctx *c,
0688 struct damon_target *t,
0689 struct damon_region *r)
0690 {
0691 struct damos *s;
0692
0693 damon_for_each_scheme(s, c) {
0694 struct damos_quota *quota = &s->quota;
0695 unsigned long sz = r->ar.end - r->ar.start;
0696 struct timespec64 begin, end;
0697 unsigned long sz_applied = 0;
0698
0699 if (!s->wmarks.activated)
0700 continue;
0701
0702
0703 if (quota->esz && quota->charged_sz >= quota->esz)
0704 continue;
0705
0706
0707 if (quota->charge_target_from) {
0708 if (t != quota->charge_target_from)
0709 continue;
0710 if (r == damon_last_region(t)) {
0711 quota->charge_target_from = NULL;
0712 quota->charge_addr_from = 0;
0713 continue;
0714 }
0715 if (quota->charge_addr_from &&
0716 r->ar.end <= quota->charge_addr_from)
0717 continue;
0718
0719 if (quota->charge_addr_from && r->ar.start <
0720 quota->charge_addr_from) {
0721 sz = ALIGN_DOWN(quota->charge_addr_from -
0722 r->ar.start, DAMON_MIN_REGION);
0723 if (!sz) {
0724 if (r->ar.end - r->ar.start <=
0725 DAMON_MIN_REGION)
0726 continue;
0727 sz = DAMON_MIN_REGION;
0728 }
0729 damon_split_region_at(c, t, r, sz);
0730 r = damon_next_region(r);
0731 sz = r->ar.end - r->ar.start;
0732 }
0733 quota->charge_target_from = NULL;
0734 quota->charge_addr_from = 0;
0735 }
0736
0737 if (!damos_valid_target(c, t, r, s))
0738 continue;
0739
0740
0741 if (c->ops.apply_scheme) {
0742 if (quota->esz &&
0743 quota->charged_sz + sz > quota->esz) {
0744 sz = ALIGN_DOWN(quota->esz - quota->charged_sz,
0745 DAMON_MIN_REGION);
0746 if (!sz)
0747 goto update_stat;
0748 damon_split_region_at(c, t, r, sz);
0749 }
0750 ktime_get_coarse_ts64(&begin);
0751 sz_applied = c->ops.apply_scheme(c, t, r, s);
0752 ktime_get_coarse_ts64(&end);
0753 quota->total_charged_ns += timespec64_to_ns(&end) -
0754 timespec64_to_ns(&begin);
0755 quota->charged_sz += sz;
0756 if (quota->esz && quota->charged_sz >= quota->esz) {
0757 quota->charge_target_from = t;
0758 quota->charge_addr_from = r->ar.end + 1;
0759 }
0760 }
0761 if (s->action != DAMOS_STAT)
0762 r->age = 0;
0763
0764 update_stat:
0765 s->stat.nr_tried++;
0766 s->stat.sz_tried += sz;
0767 if (sz_applied)
0768 s->stat.nr_applied++;
0769 s->stat.sz_applied += sz_applied;
0770 }
0771 }
0772
0773
0774 static void damos_set_effective_quota(struct damos_quota *quota)
0775 {
0776 unsigned long throughput;
0777 unsigned long esz;
0778
0779 if (!quota->ms) {
0780 quota->esz = quota->sz;
0781 return;
0782 }
0783
0784 if (quota->total_charged_ns)
0785 throughput = quota->total_charged_sz * 1000000 /
0786 quota->total_charged_ns;
0787 else
0788 throughput = PAGE_SIZE * 1024;
0789 esz = throughput * quota->ms;
0790
0791 if (quota->sz && quota->sz < esz)
0792 esz = quota->sz;
0793 quota->esz = esz;
0794 }
0795
0796 static void kdamond_apply_schemes(struct damon_ctx *c)
0797 {
0798 struct damon_target *t;
0799 struct damon_region *r, *next_r;
0800 struct damos *s;
0801
0802 damon_for_each_scheme(s, c) {
0803 struct damos_quota *quota = &s->quota;
0804 unsigned long cumulated_sz;
0805 unsigned int score, max_score = 0;
0806
0807 if (!s->wmarks.activated)
0808 continue;
0809
0810 if (!quota->ms && !quota->sz)
0811 continue;
0812
0813
0814 if (time_after_eq(jiffies, quota->charged_from +
0815 msecs_to_jiffies(
0816 quota->reset_interval))) {
0817 if (quota->esz && quota->charged_sz >= quota->esz)
0818 s->stat.qt_exceeds++;
0819 quota->total_charged_sz += quota->charged_sz;
0820 quota->charged_from = jiffies;
0821 quota->charged_sz = 0;
0822 damos_set_effective_quota(quota);
0823 }
0824
0825 if (!c->ops.get_scheme_score)
0826 continue;
0827
0828
0829 memset(quota->histogram, 0, sizeof(quota->histogram));
0830 damon_for_each_target(t, c) {
0831 damon_for_each_region(r, t) {
0832 if (!__damos_valid_target(r, s))
0833 continue;
0834 score = c->ops.get_scheme_score(
0835 c, t, r, s);
0836 quota->histogram[score] +=
0837 r->ar.end - r->ar.start;
0838 if (score > max_score)
0839 max_score = score;
0840 }
0841 }
0842
0843
0844 for (cumulated_sz = 0, score = max_score; ; score--) {
0845 cumulated_sz += quota->histogram[score];
0846 if (cumulated_sz >= quota->esz || !score)
0847 break;
0848 }
0849 quota->min_score = score;
0850 }
0851
0852 damon_for_each_target(t, c) {
0853 damon_for_each_region_safe(r, next_r, t)
0854 damon_do_apply_schemes(c, t, r);
0855 }
0856 }
0857
0858 static inline unsigned long sz_damon_region(struct damon_region *r)
0859 {
0860 return r->ar.end - r->ar.start;
0861 }
0862
0863
0864
0865
0866 static void damon_merge_two_regions(struct damon_target *t,
0867 struct damon_region *l, struct damon_region *r)
0868 {
0869 unsigned long sz_l = sz_damon_region(l), sz_r = sz_damon_region(r);
0870
0871 l->nr_accesses = (l->nr_accesses * sz_l + r->nr_accesses * sz_r) /
0872 (sz_l + sz_r);
0873 l->age = (l->age * sz_l + r->age * sz_r) / (sz_l + sz_r);
0874 l->ar.end = r->ar.end;
0875 damon_destroy_region(r, t);
0876 }
0877
0878
0879
0880
0881
0882
0883
0884
0885 static void damon_merge_regions_of(struct damon_target *t, unsigned int thres,
0886 unsigned long sz_limit)
0887 {
0888 struct damon_region *r, *prev = NULL, *next;
0889
0890 damon_for_each_region_safe(r, next, t) {
0891 if (abs(r->nr_accesses - r->last_nr_accesses) > thres)
0892 r->age = 0;
0893 else
0894 r->age++;
0895
0896 if (prev && prev->ar.end == r->ar.start &&
0897 abs(prev->nr_accesses - r->nr_accesses) <= thres &&
0898 sz_damon_region(prev) + sz_damon_region(r) <= sz_limit)
0899 damon_merge_two_regions(t, prev, r);
0900 else
0901 prev = r;
0902 }
0903 }
0904
0905
0906
0907
0908
0909
0910
0911
0912
0913
0914
0915
0916 static void kdamond_merge_regions(struct damon_ctx *c, unsigned int threshold,
0917 unsigned long sz_limit)
0918 {
0919 struct damon_target *t;
0920
0921 damon_for_each_target(t, c)
0922 damon_merge_regions_of(t, threshold, sz_limit);
0923 }
0924
0925
0926
0927
0928
0929
0930
0931 static void damon_split_region_at(struct damon_ctx *ctx,
0932 struct damon_target *t, struct damon_region *r,
0933 unsigned long sz_r)
0934 {
0935 struct damon_region *new;
0936
0937 new = damon_new_region(r->ar.start + sz_r, r->ar.end);
0938 if (!new)
0939 return;
0940
0941 r->ar.end = new->ar.start;
0942
0943 new->age = r->age;
0944 new->last_nr_accesses = r->last_nr_accesses;
0945
0946 damon_insert_region(new, r, damon_next_region(r), t);
0947 }
0948
0949
0950 static void damon_split_regions_of(struct damon_ctx *ctx,
0951 struct damon_target *t, int nr_subs)
0952 {
0953 struct damon_region *r, *next;
0954 unsigned long sz_region, sz_sub = 0;
0955 int i;
0956
0957 damon_for_each_region_safe(r, next, t) {
0958 sz_region = r->ar.end - r->ar.start;
0959
0960 for (i = 0; i < nr_subs - 1 &&
0961 sz_region > 2 * DAMON_MIN_REGION; i++) {
0962
0963
0964
0965
0966 sz_sub = ALIGN_DOWN(damon_rand(1, 10) *
0967 sz_region / 10, DAMON_MIN_REGION);
0968
0969 if (sz_sub == 0 || sz_sub >= sz_region)
0970 continue;
0971
0972 damon_split_region_at(ctx, t, r, sz_sub);
0973 sz_region = sz_sub;
0974 }
0975 }
0976 }
0977
0978
0979
0980
0981
0982
0983
0984
0985
0986
0987
0988 static void kdamond_split_regions(struct damon_ctx *ctx)
0989 {
0990 struct damon_target *t;
0991 unsigned int nr_regions = 0;
0992 static unsigned int last_nr_regions;
0993 int nr_subregions = 2;
0994
0995 damon_for_each_target(t, ctx)
0996 nr_regions += damon_nr_regions(t);
0997
0998 if (nr_regions > ctx->max_nr_regions / 2)
0999 return;
1000
1001
1002 if (last_nr_regions == nr_regions &&
1003 nr_regions < ctx->max_nr_regions / 3)
1004 nr_subregions = 3;
1005
1006 damon_for_each_target(t, ctx)
1007 damon_split_regions_of(ctx, t, nr_subregions);
1008
1009 last_nr_regions = nr_regions;
1010 }
1011
1012
1013
1014
1015
1016
1017
1018 static bool kdamond_need_update_operations(struct damon_ctx *ctx)
1019 {
1020 return damon_check_reset_time_interval(&ctx->last_ops_update,
1021 ctx->ops_update_interval);
1022 }
1023
1024
1025
1026
1027
1028
1029
1030
1031
1032 static bool kdamond_need_stop(struct damon_ctx *ctx)
1033 {
1034 struct damon_target *t;
1035
1036 if (kthread_should_stop())
1037 return true;
1038
1039 if (!ctx->ops.target_valid)
1040 return false;
1041
1042 damon_for_each_target(t, ctx) {
1043 if (ctx->ops.target_valid(t))
1044 return false;
1045 }
1046
1047 return true;
1048 }
1049
1050 static unsigned long damos_wmark_metric_value(enum damos_wmark_metric metric)
1051 {
1052 struct sysinfo i;
1053
1054 switch (metric) {
1055 case DAMOS_WMARK_FREE_MEM_RATE:
1056 si_meminfo(&i);
1057 return i.freeram * 1000 / i.totalram;
1058 default:
1059 break;
1060 }
1061 return -EINVAL;
1062 }
1063
1064
1065
1066
1067
1068 static unsigned long damos_wmark_wait_us(struct damos *scheme)
1069 {
1070 unsigned long metric;
1071
1072 if (scheme->wmarks.metric == DAMOS_WMARK_NONE)
1073 return 0;
1074
1075 metric = damos_wmark_metric_value(scheme->wmarks.metric);
1076
1077 if (metric > scheme->wmarks.high || scheme->wmarks.low > metric) {
1078 if (scheme->wmarks.activated)
1079 pr_debug("deactivate a scheme (%d) for %s wmark\n",
1080 scheme->action,
1081 metric > scheme->wmarks.high ?
1082 "high" : "low");
1083 scheme->wmarks.activated = false;
1084 return scheme->wmarks.interval;
1085 }
1086
1087
1088 if ((scheme->wmarks.high >= metric && metric >= scheme->wmarks.mid) &&
1089 !scheme->wmarks.activated)
1090 return scheme->wmarks.interval;
1091
1092 if (!scheme->wmarks.activated)
1093 pr_debug("activate a scheme (%d)\n", scheme->action);
1094 scheme->wmarks.activated = true;
1095 return 0;
1096 }
1097
1098 static void kdamond_usleep(unsigned long usecs)
1099 {
1100
1101 if (usecs > 20 * USEC_PER_MSEC)
1102 schedule_timeout_idle(usecs_to_jiffies(usecs));
1103 else
1104 usleep_idle_range(usecs, usecs + 1);
1105 }
1106
1107
1108 static int kdamond_wait_activation(struct damon_ctx *ctx)
1109 {
1110 struct damos *s;
1111 unsigned long wait_time;
1112 unsigned long min_wait_time = 0;
1113 bool init_wait_time = false;
1114
1115 while (!kdamond_need_stop(ctx)) {
1116 damon_for_each_scheme(s, ctx) {
1117 wait_time = damos_wmark_wait_us(s);
1118 if (!init_wait_time || wait_time < min_wait_time) {
1119 init_wait_time = true;
1120 min_wait_time = wait_time;
1121 }
1122 }
1123 if (!min_wait_time)
1124 return 0;
1125
1126 kdamond_usleep(min_wait_time);
1127
1128 if (ctx->callback.after_wmarks_check &&
1129 ctx->callback.after_wmarks_check(ctx))
1130 break;
1131 }
1132 return -EBUSY;
1133 }
1134
1135
1136
1137
1138 static int kdamond_fn(void *data)
1139 {
1140 struct damon_ctx *ctx = data;
1141 struct damon_target *t;
1142 struct damon_region *r, *next;
1143 unsigned int max_nr_accesses = 0;
1144 unsigned long sz_limit = 0;
1145 bool done = false;
1146
1147 pr_debug("kdamond (%d) starts\n", current->pid);
1148
1149 if (ctx->ops.init)
1150 ctx->ops.init(ctx);
1151 if (ctx->callback.before_start && ctx->callback.before_start(ctx))
1152 done = true;
1153
1154 sz_limit = damon_region_sz_limit(ctx);
1155
1156 while (!kdamond_need_stop(ctx) && !done) {
1157 if (kdamond_wait_activation(ctx)) {
1158 done = true;
1159 continue;
1160 }
1161
1162 if (ctx->ops.prepare_access_checks)
1163 ctx->ops.prepare_access_checks(ctx);
1164 if (ctx->callback.after_sampling &&
1165 ctx->callback.after_sampling(ctx)) {
1166 done = true;
1167 continue;
1168 }
1169
1170 kdamond_usleep(ctx->sample_interval);
1171
1172 if (ctx->ops.check_accesses)
1173 max_nr_accesses = ctx->ops.check_accesses(ctx);
1174
1175 if (kdamond_aggregate_interval_passed(ctx)) {
1176 kdamond_merge_regions(ctx,
1177 max_nr_accesses / 10,
1178 sz_limit);
1179 if (ctx->callback.after_aggregation &&
1180 ctx->callback.after_aggregation(ctx)) {
1181 done = true;
1182 continue;
1183 }
1184 kdamond_apply_schemes(ctx);
1185 kdamond_reset_aggregated(ctx);
1186 kdamond_split_regions(ctx);
1187 if (ctx->ops.reset_aggregated)
1188 ctx->ops.reset_aggregated(ctx);
1189 }
1190
1191 if (kdamond_need_update_operations(ctx)) {
1192 if (ctx->ops.update)
1193 ctx->ops.update(ctx);
1194 sz_limit = damon_region_sz_limit(ctx);
1195 }
1196 }
1197 damon_for_each_target(t, ctx) {
1198 damon_for_each_region_safe(r, next, t)
1199 damon_destroy_region(r, t);
1200 }
1201
1202 if (ctx->callback.before_terminate)
1203 ctx->callback.before_terminate(ctx);
1204 if (ctx->ops.cleanup)
1205 ctx->ops.cleanup(ctx);
1206
1207 pr_debug("kdamond (%d) finishes\n", current->pid);
1208 mutex_lock(&ctx->kdamond_lock);
1209 ctx->kdamond = NULL;
1210 mutex_unlock(&ctx->kdamond_lock);
1211
1212 mutex_lock(&damon_lock);
1213 nr_running_ctxs--;
1214 if (!nr_running_ctxs && running_exclusive_ctxs)
1215 running_exclusive_ctxs = false;
1216 mutex_unlock(&damon_lock);
1217
1218 return 0;
1219 }
1220
1221 #include "core-test.h"