aboutsummaryrefslogtreecommitdiffstats
path: root/fs/proc
diff options
context:
space:
mode:
Diffstat (limited to 'fs/proc')
-rw-r--r--fs/proc/task_mmu.c35
1 files changed, 34 insertions, 1 deletions
diff --git a/fs/proc/task_mmu.c b/fs/proc/task_mmu.c
index a18e065c1c3e..dbf61f6174f0 100644
--- a/fs/proc/task_mmu.c
+++ b/fs/proc/task_mmu.c
@@ -689,6 +689,23 @@ const struct file_operations proc_tid_smaps_operations = {
689 .release = seq_release_private, 689 .release = seq_release_private,
690}; 690};
691 691
692/*
693 * We do not want to have constant page-shift bits sitting in
694 * pagemap entries and are about to reuse them some time soon.
695 *
696 * Here's the "migration strategy":
697 * 1. when the system boots these bits remain what they are,
698 * but a warning about future change is printed in log;
699 * 2. once anyone clears soft-dirty bits via clear_refs file,
700 * these flag is set to denote, that user is aware of the
701 * new API and those page-shift bits change their meaning.
702 * The respective warning is printed in dmesg;
703 * 3. In a couple of releases we will remove all the mentions
704 * of page-shift in pagemap entries.
705 */
706
707static bool soft_dirty_cleared __read_mostly;
708
692enum clear_refs_types { 709enum clear_refs_types {
693 CLEAR_REFS_ALL = 1, 710 CLEAR_REFS_ALL = 1,
694 CLEAR_REFS_ANON, 711 CLEAR_REFS_ANON,
@@ -778,6 +795,13 @@ static ssize_t clear_refs_write(struct file *file, const char __user *buf,
778 type = (enum clear_refs_types)itype; 795 type = (enum clear_refs_types)itype;
779 if (type < CLEAR_REFS_ALL || type >= CLEAR_REFS_LAST) 796 if (type < CLEAR_REFS_ALL || type >= CLEAR_REFS_LAST)
780 return -EINVAL; 797 return -EINVAL;
798
799 if (type == CLEAR_REFS_SOFT_DIRTY) {
800 soft_dirty_cleared = true;
801 pr_warn_once("The pagemap bits 55-60 has changed their meaning! "
802 "See the linux/Documentation/vm/pagemap.txt for details.\n");
803 }
804
781 task = get_proc_task(file_inode(file)); 805 task = get_proc_task(file_inode(file));
782 if (!task) 806 if (!task)
783 return -ESRCH; 807 return -ESRCH;
@@ -1091,7 +1115,7 @@ static ssize_t pagemap_read(struct file *file, char __user *buf,
1091 if (!count) 1115 if (!count)
1092 goto out_task; 1116 goto out_task;
1093 1117
1094 pm.v2 = false; 1118 pm.v2 = soft_dirty_cleared;
1095 pm.len = PM_ENTRY_BYTES * (PAGEMAP_WALK_SIZE >> PAGE_SHIFT); 1119 pm.len = PM_ENTRY_BYTES * (PAGEMAP_WALK_SIZE >> PAGE_SHIFT);
1096 pm.buffer = kmalloc(pm.len, GFP_TEMPORARY); 1120 pm.buffer = kmalloc(pm.len, GFP_TEMPORARY);
1097 ret = -ENOMEM; 1121 ret = -ENOMEM;
@@ -1164,9 +1188,18 @@ out:
1164 return ret; 1188 return ret;
1165} 1189}
1166 1190
1191static int pagemap_open(struct inode *inode, struct file *file)
1192{
1193 pr_warn_once("Bits 55-60 of /proc/PID/pagemap entries are about "
1194 "to stop being page-shift some time soon. See the "
1195 "linux/Documentation/vm/pagemap.txt for details.\n");
1196 return 0;
1197}
1198
1167const struct file_operations proc_pagemap_operations = { 1199const struct file_operations proc_pagemap_operations = {
1168 .llseek = mem_lseek, /* borrow this */ 1200 .llseek = mem_lseek, /* borrow this */
1169 .read = pagemap_read, 1201 .read = pagemap_read,
1202 .open = pagemap_open,
1170}; 1203};
1171#endif /* CONFIG_PROC_PAGE_MONITOR */ 1204#endif /* CONFIG_PROC_PAGE_MONITOR */
1172 1205