|
@@ -689,6 +689,23 @@ const struct file_operations proc_tid_smaps_operations = {
|
|
|
.release = seq_release_private,
|
|
|
};
|
|
|
|
|
|
+/*
|
|
|
+ * We do not want to have constant page-shift bits sitting in
|
|
|
+ * pagemap entries and are about to reuse them some time soon.
|
|
|
+ *
|
|
|
+ * Here's the "migration strategy":
|
|
|
+ * 1. when the system boots these bits remain what they are,
|
|
|
+ * but a warning about future change is printed in log;
|
|
|
+ * 2. once anyone clears soft-dirty bits via clear_refs file,
|
|
|
+ * these flag is set to denote, that user is aware of the
|
|
|
+ * new API and those page-shift bits change their meaning.
|
|
|
+ * The respective warning is printed in dmesg;
|
|
|
+ * 3. In a couple of releases we will remove all the mentions
|
|
|
+ * of page-shift in pagemap entries.
|
|
|
+ */
|
|
|
+
|
|
|
+static bool soft_dirty_cleared __read_mostly;
|
|
|
+
|
|
|
enum clear_refs_types {
|
|
|
CLEAR_REFS_ALL = 1,
|
|
|
CLEAR_REFS_ANON,
|
|
@@ -778,6 +795,13 @@ static ssize_t clear_refs_write(struct file *file, const char __user *buf,
|
|
|
type = (enum clear_refs_types)itype;
|
|
|
if (type < CLEAR_REFS_ALL || type >= CLEAR_REFS_LAST)
|
|
|
return -EINVAL;
|
|
|
+
|
|
|
+ if (type == CLEAR_REFS_SOFT_DIRTY) {
|
|
|
+ soft_dirty_cleared = true;
|
|
|
+ pr_warn_once("The pagemap bits 55-60 has changed their meaning! "
|
|
|
+ "See the linux/Documentation/vm/pagemap.txt for details.\n");
|
|
|
+ }
|
|
|
+
|
|
|
task = get_proc_task(file_inode(file));
|
|
|
if (!task)
|
|
|
return -ESRCH;
|
|
@@ -1091,7 +1115,7 @@ static ssize_t pagemap_read(struct file *file, char __user *buf,
|
|
|
if (!count)
|
|
|
goto out_task;
|
|
|
|
|
|
- pm.v2 = false;
|
|
|
+ pm.v2 = soft_dirty_cleared;
|
|
|
pm.len = PM_ENTRY_BYTES * (PAGEMAP_WALK_SIZE >> PAGE_SHIFT);
|
|
|
pm.buffer = kmalloc(pm.len, GFP_TEMPORARY);
|
|
|
ret = -ENOMEM;
|
|
@@ -1164,9 +1188,18 @@ out:
|
|
|
return ret;
|
|
|
}
|
|
|
|
|
|
+static int pagemap_open(struct inode *inode, struct file *file)
|
|
|
+{
|
|
|
+ pr_warn_once("Bits 55-60 of /proc/PID/pagemap entries are about "
|
|
|
+ "to stop being page-shift some time soon. See the "
|
|
|
+ "linux/Documentation/vm/pagemap.txt for details.\n");
|
|
|
+ return 0;
|
|
|
+}
|
|
|
+
|
|
|
const struct file_operations proc_pagemap_operations = {
|
|
|
.llseek = mem_lseek, /* borrow this */
|
|
|
.read = pagemap_read,
|
|
|
+ .open = pagemap_open,
|
|
|
};
|
|
|
#endif /* CONFIG_PROC_PAGE_MONITOR */
|
|
|
|