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 | |
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>
-rw-r--r-- | Documentation/filesystems/proc.txt | 40 | ||||
-rw-r--r-- | fs/proc/task_mmu.c | 53 |
2 files changed, 91 insertions, 2 deletions
diff --git a/Documentation/filesystems/proc.txt b/Documentation/filesystems/proc.txt index 3844d21d6ca3..74cb394e6888 100644 --- a/Documentation/filesystems/proc.txt +++ b/Documentation/filesystems/proc.txt | |||
@@ -142,7 +142,7 @@ Table 1-1: Process specific entries in /proc | |||
142 | pagemap Page table | 142 | pagemap Page table |
143 | stack Report full stack trace, enable via CONFIG_STACKTRACE | 143 | stack Report full stack trace, enable via CONFIG_STACKTRACE |
144 | smaps a extension based on maps, showing the memory consumption of | 144 | smaps a extension based on maps, showing the memory consumption of |
145 | each mapping | 145 | each mapping and flags associated with it |
146 | .............................................................................. | 146 | .............................................................................. |
147 | 147 | ||
148 | For example, to get the status information of a process, all you have to do is | 148 | For example, to get the status information of a process, all you have to do is |
@@ -415,8 +415,9 @@ Swap: 0 kB | |||
415 | KernelPageSize: 4 kB | 415 | KernelPageSize: 4 kB |
416 | MMUPageSize: 4 kB | 416 | MMUPageSize: 4 kB |
417 | Locked: 374 kB | 417 | Locked: 374 kB |
418 | VmFlags: rd ex mr mw me de | ||
418 | 419 | ||
419 | The first of these lines shows the same information as is displayed for the | 420 | the first of these lines shows the same information as is displayed for the |
420 | mapping in /proc/PID/maps. The remaining lines show the size of the mapping | 421 | mapping in /proc/PID/maps. The remaining lines show the size of the mapping |
421 | (size), the amount of the mapping that is currently resident in RAM (RSS), the | 422 | (size), the amount of the mapping that is currently resident in RAM (RSS), the |
422 | process' proportional share of this mapping (PSS), the number of clean and | 423 | process' proportional share of this mapping (PSS), the number of clean and |
@@ -430,6 +431,41 @@ and a page is modified, the file page is replaced by a private anonymous copy. | |||
430 | "Swap" shows how much would-be-anonymous memory is also used, but out on | 431 | "Swap" shows how much would-be-anonymous memory is also used, but out on |
431 | swap. | 432 | swap. |
432 | 433 | ||
434 | "VmFlags" field deserves a separate description. This member represents the kernel | ||
435 | flags associated with the particular virtual memory area in two letter encoded | ||
436 | manner. The codes are the following: | ||
437 | rd - readable | ||
438 | wr - writeable | ||
439 | ex - executable | ||
440 | sh - shared | ||
441 | mr - may read | ||
442 | mw - may write | ||
443 | me - may execute | ||
444 | ms - may share | ||
445 | gd - stack segment growns down | ||
446 | pf - pure PFN range | ||
447 | dw - disabled write to the mapped file | ||
448 | lo - pages are locked in memory | ||
449 | io - memory mapped I/O area | ||
450 | sr - sequential read advise provided | ||
451 | rr - random read advise provided | ||
452 | dc - do not copy area on fork | ||
453 | de - do not expand area on remapping | ||
454 | ac - area is accountable | ||
455 | nr - swap space is not reserved for the area | ||
456 | ht - area uses huge tlb pages | ||
457 | nl - non-linear mapping | ||
458 | ar - architecture specific flag | ||
459 | dd - do not include area into core dump | ||
460 | mm - mixed map area | ||
461 | hg - huge page advise flag | ||
462 | nh - no-huge page advise flag | ||
463 | mg - mergable advise flag | ||
464 | |||
465 | Note that there is no guarantee that every flag and associated mnemonic will | ||
466 | be present in all further kernel releases. Things get changed, the flags may | ||
467 | be vanished or the reverse -- new added. | ||
468 | |||
433 | This file is only present if the CONFIG_MMU kernel configuration option is | 469 | This file is only present if the CONFIG_MMU kernel configuration option is |
434 | enabled. | 470 | enabled. |
435 | 471 | ||
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; |