@@ -312,6 +312,7 @@ void kdamond_init_phys_regions(struct damon_ctx *ctx);
void kdamond_update_phys_regions(struct damon_ctx *ctx);
void kdamond_prepare_phys_access_checks(struct damon_ctx *ctx);
unsigned int kdamond_check_phys_accesses(struct damon_ctx *ctx);
+bool kdamond_phys_target_valid(struct damon_target *t);
void damon_set_paddr_primitives(struct damon_ctx *ctx);
#endif /* CONFIG_DAMON_PRIMITIVES */
@@ -8,6 +8,8 @@
#ifdef CONFIG_PAGE_IDLE_FLAG
+extern struct mutex page_idle_lock;
+
#ifdef CONFIG_64BIT
static inline bool page_is_young(struct page *page)
{
@@ -26,7 +26,7 @@ config DAMON_KUNIT_TEST
config DAMON_PRIMITIVES
bool "DAMON primitives for virtual/physical address spaces monitoring"
- depends on DAMON && MMU && !IDLE_PAGE_TRACKING
+ depends on DAMON && MMU
select PAGE_EXTENSION if !64BIT
select PAGE_IDLE_FLAG
help
@@ -12,6 +12,7 @@
#include <linux/file.h>
#include <linux/mm.h>
#include <linux/module.h>
+#include <linux/page_idle.h>
#include <linux/slab.h>
#define MIN_RECORD_BUFFER_LEN 1024
@@ -28,6 +29,7 @@ struct debugfs_recorder {
/* Monitoring contexts for debugfs interface users. */
static struct damon_ctx **debugfs_ctxs;
static int debugfs_nr_ctxs = 1;
+static int debugfs_nr_terminated_ctxs;
static DEFINE_MUTEX(damon_dbgfs_lock);
@@ -106,9 +108,20 @@ static void debugfs_init_vm_regions(struct damon_ctx *ctx)
kdamond_init_vm_regions(ctx);
}
+static void debugfs_unlock_page_idle_lock(void)
+{
+ mutex_lock(&damon_dbgfs_lock);
+ if (++debugfs_nr_terminated_ctxs == debugfs_nr_ctxs) {
+ debugfs_nr_terminated_ctxs = 0;
+ mutex_unlock(&page_idle_lock);
+ }
+ mutex_unlock(&damon_dbgfs_lock);
+}
+
static void debugfs_vm_cleanup(struct damon_ctx *ctx)
{
debugfs_flush_rbuffer(ctx->private);
+ debugfs_unlock_page_idle_lock();
kdamond_vm_cleanup(ctx);
}
@@ -120,6 +133,8 @@ static void debugfs_init_phys_regions(struct damon_ctx *ctx)
static void debugfs_phys_cleanup(struct damon_ctx *ctx)
{
debugfs_flush_rbuffer(ctx->private);
+ debugfs_unlock_page_idle_lock();
+
}
/*
@@ -197,6 +212,21 @@ static char *user_input_str(const char __user *buf, size_t count, loff_t *ppos)
return kbuf;
}
+static int debugfs_start_ctx_ptrs(struct damon_ctx **ctxs, int nr_ctxs)
+{
+ int rc;
+
+ if (!mutex_trylock(&page_idle_lock))
+ return -EBUSY;
+
+ rc = damon_start_ctx_ptrs(ctxs, nr_ctxs);
+ if (rc)
+ mutex_unlock(&page_idle_lock);
+
+ return rc;
+}
+
+
static ssize_t debugfs_monitor_on_write(struct file *file,
const char __user *buf, size_t count, loff_t *ppos)
{
@@ -212,7 +242,7 @@ static ssize_t debugfs_monitor_on_write(struct file *file,
if (sscanf(kbuf, "%s", kbuf) != 1)
return -EINVAL;
if (!strncmp(kbuf, "on", count))
- err = damon_start_ctx_ptrs(debugfs_ctxs, debugfs_nr_ctxs);
+ err = debugfs_start_ctx_ptrs(debugfs_ctxs, debugfs_nr_ctxs);
else if (!strncmp(kbuf, "off", count))
err = damon_stop_ctx_ptrs(debugfs_ctxs, debugfs_nr_ctxs);
else
@@ -30,6 +30,10 @@
#include "damon.h"
+#ifndef CONFIG_IDLE_PAGE_TRACKING
+DEFINE_MUTEX(page_idle_lock);
+#endif
+
/* Minimal region size. Every damon_region is aligned by this. */
#ifndef CONFIG_DAMON_KUNIT_TEST
#define MIN_REGION PAGE_SIZE
@@ -776,6 +780,9 @@ bool kdamond_vm_target_valid(struct damon_target *t)
{
struct task_struct *task;
+ if (!mutex_is_locked(&page_idle_lock))
+ return false;
+
task = damon_get_task_struct(t);
if (task) {
put_task_struct(task);
@@ -795,6 +802,13 @@ void kdamond_vm_cleanup(struct damon_ctx *ctx)
}
}
+bool kdamond_phys_target_valid(struct damon_target *t)
+{
+ if (!mutex_is_locked(&page_idle_lock))
+ return false;
+ return true;
+}
+
#ifndef CONFIG_ADVISE_SYSCALLS
static int damos_madvise(struct damon_target *target, struct damon_region *r,
int behavior)
@@ -874,7 +888,7 @@ void damon_set_paddr_primitives(struct damon_ctx *ctx)
ctx->update_target_regions = kdamond_update_phys_regions;
ctx->prepare_access_checks = kdamond_prepare_phys_access_checks;
ctx->check_accesses = kdamond_check_phys_accesses;
- ctx->target_valid = NULL;
+ ctx->target_valid = kdamond_phys_target_valid;
ctx->cleanup = NULL;
ctx->apply_scheme = NULL;
}
@@ -16,7 +16,7 @@
#define BITMAP_CHUNK_SIZE sizeof(u64)
#define BITMAP_CHUNK_BITS (BITMAP_CHUNK_SIZE * BITS_PER_BYTE)
-static DEFINE_MUTEX(page_idle_lock);
+DEFINE_MUTEX(page_idle_lock);
/*
* Idle page tracking only considers user memory pages, for other types of