diff options
Diffstat (limited to 'fs/proc')
-rw-r--r-- | fs/proc/task_mmu.c | 35 |
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 | |||
707 | static bool soft_dirty_cleared __read_mostly; | ||
708 | |||
692 | enum clear_refs_types { | 709 | enum 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 | ||
1191 | static 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 | |||
1167 | const struct file_operations proc_pagemap_operations = { | 1199 | const 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 | ||