diff options
author | Cyrill Gorcunov <gorcunov@openvz.org> | 2012-12-17 19:03:13 -0500 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2012-12-17 20:15:22 -0500 |
commit | 834f82e2aa9a8ede94b17b656329f850c1471514 (patch) | |
tree | dbd2a721c3b6b4c7d3cd5826a9ceb867158a1941 /fs/proc | |
parent | 7b9a7ec565505699f503b4fcf61500dceb36e744 (diff) |
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>
Diffstat (limited to 'fs/proc')
-rw-r--r-- | fs/proc/task_mmu.c | 53 |
1 files changed, 53 insertions, 0 deletions
diff --git a/fs/proc/task_mmu.c b/fs/proc/task_mmu.c index 48775628abbf..448455b7fd91 100644 --- a/fs/proc/task_mmu.c +++ b/fs/proc/task_mmu.c | |||
@@ -526,6 +526,57 @@ static int smaps_pte_range(pmd_t *pmd, unsigned long addr, unsigned long end, | |||
526 | return 0; | 526 | return 0; |
527 | } | 527 | } |
528 | 528 | ||
529 | static void show_smap_vma_flags(struct seq_file *m, struct vm_area_struct *vma) | ||
530 | { | ||
531 | /* | ||
532 | * Don't forget to update Documentation/ on changes. | ||
533 | */ | ||
534 | static const char mnemonics[BITS_PER_LONG][2] = { | ||
535 | /* | ||
536 | * In case if we meet a flag we don't know about. | ||
537 | */ | ||
538 | [0 ... (BITS_PER_LONG-1)] = "??", | ||
539 | |||
540 | [ilog2(VM_READ)] = "rd", | ||
541 | [ilog2(VM_WRITE)] = "wr", | ||
542 | [ilog2(VM_EXEC)] = "ex", | ||
543 | [ilog2(VM_SHARED)] = "sh", | ||
544 | [ilog2(VM_MAYREAD)] = "mr", | ||
545 | [ilog2(VM_MAYWRITE)] = "mw", | ||
546 | [ilog2(VM_MAYEXEC)] = "me", | ||
547 | [ilog2(VM_MAYSHARE)] = "ms", | ||
548 | [ilog2(VM_GROWSDOWN)] = "gd", | ||
549 | [ilog2(VM_PFNMAP)] = "pf", | ||
550 | [ilog2(VM_DENYWRITE)] = "dw", | ||
551 | [ilog2(VM_LOCKED)] = "lo", | ||
552 | [ilog2(VM_IO)] = "io", | ||
553 | [ilog2(VM_SEQ_READ)] = "sr", | ||
554 | [ilog2(VM_RAND_READ)] = "rr", | ||
555 | [ilog2(VM_DONTCOPY)] = "dc", | ||
556 | [ilog2(VM_DONTEXPAND)] = "de", | ||
557 | [ilog2(VM_ACCOUNT)] = "ac", | ||
558 | [ilog2(VM_NORESERVE)] = "nr", | ||
559 | [ilog2(VM_HUGETLB)] = "ht", | ||
560 | [ilog2(VM_NONLINEAR)] = "nl", | ||
561 | [ilog2(VM_ARCH_1)] = "ar", | ||
562 | [ilog2(VM_DONTDUMP)] = "dd", | ||
563 | [ilog2(VM_MIXEDMAP)] = "mm", | ||
564 | [ilog2(VM_HUGEPAGE)] = "hg", | ||
565 | [ilog2(VM_NOHUGEPAGE)] = "nh", | ||
566 | [ilog2(VM_MERGEABLE)] = "mg", | ||
567 | }; | ||
568 | size_t i; | ||
569 | |||
570 | seq_puts(m, "VmFlags: "); | ||
571 | for (i = 0; i < BITS_PER_LONG; i++) { | ||
572 | if (vma->vm_flags & (1UL << i)) { | ||
573 | seq_printf(m, "%c%c ", | ||
574 | mnemonics[i][0], mnemonics[i][1]); | ||
575 | } | ||
576 | } | ||
577 | seq_putc(m, '\n'); | ||
578 | } | ||
579 | |||
529 | static int show_smap(struct seq_file *m, void *v, int is_pid) | 580 | static int show_smap(struct seq_file *m, void *v, int is_pid) |
530 | { | 581 | { |
531 | struct proc_maps_private *priv = m->private; | 582 | struct proc_maps_private *priv = m->private; |
@@ -581,6 +632,8 @@ static int show_smap(struct seq_file *m, void *v, int is_pid) | |||
581 | seq_printf(m, "Nonlinear: %8lu kB\n", | 632 | seq_printf(m, "Nonlinear: %8lu kB\n", |
582 | mss.nonlinear >> 10); | 633 | mss.nonlinear >> 10); |
583 | 634 | ||
635 | show_smap_vma_flags(m, vma); | ||
636 | |||
584 | if (m->count < m->size) /* vma is copied successfully */ | 637 | if (m->count < m->size) /* vma is copied successfully */ |
585 | m->version = (vma != get_gate_vma(task->mm)) | 638 | m->version = (vma != get_gate_vma(task->mm)) |
586 | ? vma->vm_start : 0; | 639 | ? vma->vm_start : 0; |