pagemap: prepare to reuse constant bits with page-shift
[deliverable/linux.git] / fs / proc / task_mmu.c
index a18e065c1c3e6c3b6ae9f4db8fb2d39c98eaa5b2..dbf61f6174f0f473d3d9a19311a09170f8dab9f3 100644 (file)
@@ -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 */
 
This page took 0.045734 seconds and 5 git commands to generate.