Skip to content

Commit 8b9b0d3

Browse files
sjp38torvalds
authored andcommitted
mm/damon/core: allow non-exclusive DAMON start/stop
Patch series "Introduce DAMON sysfs interface", v3. Introduction ============ DAMON's debugfs-based user interface (DAMON_DBGFS) served very well, so far. However, it unnecessarily depends on debugfs, while DAMON is not aimed to be used for only debugging. Also, the interface receives multiple values via one file. For example, schemes file receives 18 values. As a result, it is inefficient, hard to be used, and difficult to be extended. Especially, keeping backward compatibility of user space tools is getting only challenging. It would be better to implement another reliable and flexible interface and deprecate DAMON_DBGFS in long term. For the reason, this patchset introduces a sysfs-based new user interface of DAMON. The idea of the new interface is, using directory hierarchies and having one dedicated file for each value. For a short example, users can do the virtual address monitoring via the interface as below: # cd /sys/kernel/mm/damon/admin/ # echo 1 > kdamonds/nr_kdamonds # echo 1 > kdamonds/0/contexts/nr_contexts # echo vaddr > kdamonds/0/contexts/0/operations # echo 1 > kdamonds/0/contexts/0/targets/nr_targets # echo $(pidof <workload>) > kdamonds/0/contexts/0/targets/0/pid_target # echo on > kdamonds/0/state A brief representation of the files hierarchy of DAMON sysfs interface is as below. Childs are represented with indentation, directories are having '/' suffix, and files in each directory are separated by comma. /sys/kernel/mm/damon/admin │ kdamonds/nr_kdamonds │ │ 0/state,pid │ │ │ contexts/nr_contexts │ │ │ │ 0/operations │ │ │ │ │ monitoring_attrs/ │ │ │ │ │ │ intervals/sample_us,aggr_us,update_us │ │ │ │ │ │ nr_regions/min,max │ │ │ │ │ targets/nr_targets │ │ │ │ │ │ 0/pid_target │ │ │ │ │ │ │ regions/nr_regions │ │ │ │ │ │ │ │ 0/start,end │ │ │ │ │ │ │ │ ... │ │ │ │ │ │ ... │ │ │ │ │ schemes/nr_schemes │ │ │ │ │ │ 0/action │ │ │ │ │ │ │ access_pattern/ │ │ │ │ │ │ │ │ sz/min,max │ │ │ │ │ │ │ │ nr_accesses/min,max │ │ │ │ │ │ │ │ age/min,max │ │ │ │ │ │ │ quotas/ms,bytes,reset_interval_ms │ │ │ │ │ │ │ │ weights/sz_permil,nr_accesses_permil,age_permil │ │ │ │ │ │ │ watermarks/metric,interval_us,high,mid,low │ │ │ │ │ │ │ stats/nr_tried,sz_tried,nr_applied,sz_applied,qt_exceeds │ │ │ │ │ │ ... │ │ │ │ ... │ │ ... Detailed usage of the files will be described in the final Documentation patch of this patchset. Main Difference Between DAMON_DBGFS and DAMON_SYSFS --------------------------------------------------- At the moment, DAMON_DBGFS and DAMON_SYSFS provides same features. One important difference between them is their exclusiveness. DAMON_DBGFS works in an exclusive manner, so that no DAMON worker thread (kdamond) in the system can run concurrently and interfere somehow. For the reason, DAMON_DBGFS asks users to construct all monitoring contexts and start them at once. It's not a big problem but makes the operation a little bit complex and unflexible. For more flexible usage, DAMON_SYSFS moves the responsibility of preventing any possible interference to the admins and work in a non-exclusive manner. That is, users can configure and start contexts one by one. Note that DAMON respects both exclusive groups and non-exclusive groups of contexts, in a manner similar to that of reader-writer locks. That is, if any exclusive monitoring contexts (e.g., contexts that started via DAMON_DBGFS) are running, DAMON_SYSFS does not start new contexts, and vice versa. Future Plan of DAMON_DBGFS Deprecation ====================================== Once this patchset is merged, DAMON_DBGFS development will be frozen. That is, we will maintain it to work as is now so that no users will be break. But, it will not be extended to provide any new feature of DAMON. The support will be continued only until next LTS release. After that, we will drop DAMON_DBGFS. User-space Tooling Compatibility -------------------------------- As DAMON_SYSFS provides all features of DAMON_DBGFS, all user space tooling can move to DAMON_SYSFS. As we will continue supporting DAMON_DBGFS until next LTS kernel release, user space tools would have enough time to move to DAMON_SYSFS. The official user space tool, damo[1], is already supporting both DAMON_SYSFS and DAMON_DBGFS. Both correctness tests[2] and performance tests[3] of DAMON using DAMON_SYSFS also passed. [1] https://github.com/awslabs/damo [2] https://github.com/awslabs/damon-tests/tree/master/corr [3] https://github.com/awslabs/damon-tests/tree/master/perf Sequence of Patches =================== First two patches (patches 1-2) make core changes for DAMON_SYSFS. The first one (patch 1) allows non-exclusive DAMON contexts so that DAMON_SYSFS can work in non-exclusive mode, while the second one (patch 2) adds size of DAMON enum types so that DAMON API users can safely iterate the enums. Third patch (patch 3) implements basic sysfs stub for virtual address spaces monitoring. Note that this implements only sysfs files and DAMON is not linked. Fourth patch (patch 4) links the DAMON_SYSFS to DAMON so that users can control DAMON using the sysfs files. Following six patches (patches 5-10) implements other DAMON features that DAMON_DBGFS supports one by one (physical address space monitoring, DAMON-based operation schemes, schemes quotas, schemes prioritization weights, schemes watermarks, and schemes stats). Following patch (patch 11) adds a simple selftest for DAMON_SYSFS, and the final one (patch 12) documents DAMON_SYSFS. This patch (of 13): To avoid interference between DAMON contexts monitoring overlapping memory regions, damon_start() works in an exclusive manner. That is, damon_start() does nothing bug fails if any context that started by another instance of the function is still running. This makes its usage a little bit restrictive. However, admins could aware each DAMON usage and address such interferences on their own in some cases. This commit hence implements non-exclusive mode of the function and allows the callers to select the mode. Note that the exclusive groups and non-exclusive groups of contexts will respect each other in a manner similar to that of reader-writer locks. Therefore, this commit will not cause any behavioral change to the exclusive groups. Link: https://lkml.kernel.org/r/[email protected] Link: https://lkml.kernel.org/r/[email protected] Signed-off-by: SeongJae Park <[email protected]> Cc: Jonathan Corbet <[email protected]> Cc: Shuah Khan <[email protected]> Cc: David Rientjes <[email protected]> Cc: Xin Hao <[email protected]> Cc: Greg Kroah-Hartman <[email protected]> Signed-off-by: Andrew Morton <[email protected]> Signed-off-by: Linus Torvalds <[email protected]>
1 parent 4c1f287 commit 8b9b0d3

File tree

4 files changed

+18
-11
lines changed

4 files changed

+18
-11
lines changed

include/linux/damon.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -508,7 +508,7 @@ int damon_nr_running_ctxs(void);
508508
int damon_register_ops(struct damon_operations *ops);
509509
int damon_select_ops(struct damon_ctx *ctx, enum damon_ops_id id);
510510

511-
int damon_start(struct damon_ctx **ctxs, int nr_ctxs);
511+
int damon_start(struct damon_ctx **ctxs, int nr_ctxs, bool exclusive);
512512
int damon_stop(struct damon_ctx **ctxs, int nr_ctxs);
513513

514514
#endif /* CONFIG_DAMON */

mm/damon/core.c

Lines changed: 15 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@
2424

2525
static DEFINE_MUTEX(damon_lock);
2626
static int nr_running_ctxs;
27+
static bool running_exclusive_ctxs;
2728

2829
static DEFINE_MUTEX(damon_ops_lock);
2930
static struct damon_operations damon_registered_ops[NR_DAMON_OPS];
@@ -434,22 +435,25 @@ static int __damon_start(struct damon_ctx *ctx)
434435
* damon_start() - Starts the monitorings for a given group of contexts.
435436
* @ctxs: an array of the pointers for contexts to start monitoring
436437
* @nr_ctxs: size of @ctxs
438+
* @exclusive: exclusiveness of this contexts group
437439
*
438440
* This function starts a group of monitoring threads for a group of monitoring
439441
* contexts. One thread per each context is created and run in parallel. The
440-
* caller should handle synchronization between the threads by itself. If a
441-
* group of threads that created by other 'damon_start()' call is currently
442-
* running, this function does nothing but returns -EBUSY.
442+
* caller should handle synchronization between the threads by itself. If
443+
* @exclusive is true and a group of threads that created by other
444+
* 'damon_start()' call is currently running, this function does nothing but
445+
* returns -EBUSY.
443446
*
444447
* Return: 0 on success, negative error code otherwise.
445448
*/
446-
int damon_start(struct damon_ctx **ctxs, int nr_ctxs)
449+
int damon_start(struct damon_ctx **ctxs, int nr_ctxs, bool exclusive)
447450
{
448451
int i;
449452
int err = 0;
450453

451454
mutex_lock(&damon_lock);
452-
if (nr_running_ctxs) {
455+
if ((exclusive && nr_running_ctxs) ||
456+
(!exclusive && running_exclusive_ctxs)) {
453457
mutex_unlock(&damon_lock);
454458
return -EBUSY;
455459
}
@@ -460,13 +464,15 @@ int damon_start(struct damon_ctx **ctxs, int nr_ctxs)
460464
break;
461465
nr_running_ctxs++;
462466
}
467+
if (exclusive && nr_running_ctxs)
468+
running_exclusive_ctxs = true;
463469
mutex_unlock(&damon_lock);
464470

465471
return err;
466472
}
467473

468474
/*
469-
* __damon_stop() - Stops monitoring of given context.
475+
* __damon_stop() - Stops monitoring of a given context.
470476
* @ctx: monitoring context
471477
*
472478
* Return: 0 on success, negative error code otherwise.
@@ -504,9 +510,8 @@ int damon_stop(struct damon_ctx **ctxs, int nr_ctxs)
504510
/* nr_running_ctxs is decremented in kdamond_fn */
505511
err = __damon_stop(ctxs[i]);
506512
if (err)
507-
return err;
513+
break;
508514
}
509-
510515
return err;
511516
}
512517

@@ -1102,6 +1107,8 @@ static int kdamond_fn(void *data)
11021107

11031108
mutex_lock(&damon_lock);
11041109
nr_running_ctxs--;
1110+
if (!nr_running_ctxs && running_exclusive_ctxs)
1111+
running_exclusive_ctxs = false;
11051112
mutex_unlock(&damon_lock);
11061113

11071114
return 0;

mm/damon/dbgfs.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -967,7 +967,7 @@ static ssize_t dbgfs_monitor_on_write(struct file *file,
967967
return -EINVAL;
968968
}
969969
}
970-
ret = damon_start(dbgfs_ctxs, dbgfs_nr_ctxs);
970+
ret = damon_start(dbgfs_ctxs, dbgfs_nr_ctxs, true);
971971
} else if (!strncmp(kbuf, "off", count)) {
972972
ret = damon_stop(dbgfs_ctxs, dbgfs_nr_ctxs);
973973
} else {

mm/damon/reclaim.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -330,7 +330,7 @@ static int damon_reclaim_turn(bool on)
330330
if (err)
331331
goto free_scheme_out;
332332

333-
err = damon_start(&ctx, 1);
333+
err = damon_start(&ctx, 1, true);
334334
if (!err) {
335335
kdamond_pid = ctx->kdamond->pid;
336336
return 0;

0 commit comments

Comments
 (0)