procfs: add VmFlags field in smaps output
During c/r sessions we've found that there is no way at the moment to fetch some VMA associated flags, such as mlock() and madvise(). This leads us to a problem -- we don't know if we should call for mlock() and/or madvise() after restore on the vma area we're bringing back to life. This patch intorduces a new field into "smaps" output called VmFlags, where all set flags associated with the particular VMA is shown as two letter mnemonics. [ Strictly speaking for c/r we only need mlock/madvise bits but it has been said that providing just a few flags looks somehow inconsistent. So all flags are here now. ] This feature is made available on CONFIG_CHECKPOINT_RESTORE=n kernels, as other applications may start to use these fields. The data is encoded in a somewhat awkward two letters mnemonic form, to encourage userspace to be prepared for fields being added or removed in the future. [a.p.zijlstra@chello.nl: props to use for_each_set_bit] [sfr@canb.auug.org.au: props to use array instead of struct] [akpm@linux-foundation.org: overall redesign and simplification] [akpm@linux-foundation.org: remove unneeded braces per sfr, avoid using bloaty for_each_set_bit()] Signed-off-by: Cyrill Gorcunov <gorcunov@openvz.org> Cc: Pavel Emelyanov <xemul@parallels.com> Cc: Peter Zijlstra <a.p.zijlstra@chello.nl> Cc: Stephen Rothwell <sfr@canb.auug.org.au> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
This commit is contained in:

committed by
Linus Torvalds

parent
7b9a7ec565
commit
834f82e2aa
@@ -526,6 +526,57 @@ static int smaps_pte_range(pmd_t *pmd, unsigned long addr, unsigned long end,
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void show_smap_vma_flags(struct seq_file *m, struct vm_area_struct *vma)
|
||||
{
|
||||
/*
|
||||
* Don't forget to update Documentation/ on changes.
|
||||
*/
|
||||
static const char mnemonics[BITS_PER_LONG][2] = {
|
||||
/*
|
||||
* In case if we meet a flag we don't know about.
|
||||
*/
|
||||
[0 ... (BITS_PER_LONG-1)] = "??",
|
||||
|
||||
[ilog2(VM_READ)] = "rd",
|
||||
[ilog2(VM_WRITE)] = "wr",
|
||||
[ilog2(VM_EXEC)] = "ex",
|
||||
[ilog2(VM_SHARED)] = "sh",
|
||||
[ilog2(VM_MAYREAD)] = "mr",
|
||||
[ilog2(VM_MAYWRITE)] = "mw",
|
||||
[ilog2(VM_MAYEXEC)] = "me",
|
||||
[ilog2(VM_MAYSHARE)] = "ms",
|
||||
[ilog2(VM_GROWSDOWN)] = "gd",
|
||||
[ilog2(VM_PFNMAP)] = "pf",
|
||||
[ilog2(VM_DENYWRITE)] = "dw",
|
||||
[ilog2(VM_LOCKED)] = "lo",
|
||||
[ilog2(VM_IO)] = "io",
|
||||
[ilog2(VM_SEQ_READ)] = "sr",
|
||||
[ilog2(VM_RAND_READ)] = "rr",
|
||||
[ilog2(VM_DONTCOPY)] = "dc",
|
||||
[ilog2(VM_DONTEXPAND)] = "de",
|
||||
[ilog2(VM_ACCOUNT)] = "ac",
|
||||
[ilog2(VM_NORESERVE)] = "nr",
|
||||
[ilog2(VM_HUGETLB)] = "ht",
|
||||
[ilog2(VM_NONLINEAR)] = "nl",
|
||||
[ilog2(VM_ARCH_1)] = "ar",
|
||||
[ilog2(VM_DONTDUMP)] = "dd",
|
||||
[ilog2(VM_MIXEDMAP)] = "mm",
|
||||
[ilog2(VM_HUGEPAGE)] = "hg",
|
||||
[ilog2(VM_NOHUGEPAGE)] = "nh",
|
||||
[ilog2(VM_MERGEABLE)] = "mg",
|
||||
};
|
||||
size_t i;
|
||||
|
||||
seq_puts(m, "VmFlags: ");
|
||||
for (i = 0; i < BITS_PER_LONG; i++) {
|
||||
if (vma->vm_flags & (1UL << i)) {
|
||||
seq_printf(m, "%c%c ",
|
||||
mnemonics[i][0], mnemonics[i][1]);
|
||||
}
|
||||
}
|
||||
seq_putc(m, '\n');
|
||||
}
|
||||
|
||||
static int show_smap(struct seq_file *m, void *v, int is_pid)
|
||||
{
|
||||
struct proc_maps_private *priv = m->private;
|
||||
@@ -581,6 +632,8 @@ static int show_smap(struct seq_file *m, void *v, int is_pid)
|
||||
seq_printf(m, "Nonlinear: %8lu kB\n",
|
||||
mss.nonlinear >> 10);
|
||||
|
||||
show_smap_vma_flags(m, vma);
|
||||
|
||||
if (m->count < m->size) /* vma is copied successfully */
|
||||
m->version = (vma != get_gate_vma(task->mm))
|
||||
? vma->vm_start : 0;
|
||||
|
Reference in New Issue
Block a user