Merge tag 'v3.10.107' into update
[GitHub/mt8127/android_kernel_alcatel_ttab.git] / fs / proc / task_mmu.c
index 972cdc282b1a434d7b5e6332bc7783da8ca31c7c..3ced57ef25ebd1328fec217e937a86000dca1da1 100644 (file)
@@ -134,6 +134,56 @@ static void release_task_mempolicy(struct proc_maps_private *priv)
 }
 #endif
 
+static void seq_print_vma_name(struct seq_file *m, struct vm_area_struct *vma)
+{
+       const char __user *name = vma_get_anon_name(vma);
+       struct mm_struct *mm = vma->vm_mm;
+
+       unsigned long page_start_vaddr;
+       unsigned long page_offset;
+       unsigned long num_pages;
+       unsigned long max_len = NAME_MAX;
+       int i;
+
+       page_start_vaddr = (unsigned long)name & PAGE_MASK;
+       page_offset = (unsigned long)name - page_start_vaddr;
+       num_pages = DIV_ROUND_UP(page_offset + max_len, PAGE_SIZE);
+
+       seq_puts(m, "[anon:");
+
+       for (i = 0; i < num_pages; i++) {
+               int len;
+               int write_len;
+               const char *kaddr;
+               long pages_pinned;
+               struct page *page;
+
+               pages_pinned = get_user_pages(current, mm, page_start_vaddr,
+                               1, 0, 0, &page, NULL);
+               if (pages_pinned < 1) {
+                       seq_puts(m, "<fault>]");
+                       return;
+               }
+
+               kaddr = (const char *)kmap(page);
+               len = min(max_len, PAGE_SIZE - page_offset);
+               write_len = strnlen(kaddr + page_offset, len);
+               seq_write(m, kaddr + page_offset, write_len);
+               kunmap(page);
+               put_page(page);
+
+               /* if strnlen hit a null terminator then we're done */
+               if (write_len != len)
+                       break;
+
+               max_len -= len;
+               page_offset = 0;
+               page_start_vaddr += PAGE_SIZE;
+       }
+
+       seq_putc(m, ']');
+}
+
 static void vma_stop(struct proc_maps_private *priv, struct vm_area_struct *vma)
 {
        if (vma && vma != priv->tail_vma) {
@@ -331,6 +381,12 @@ show_map_vma(struct seq_file *m, struct vm_area_struct *vma, int is_pid)
                                pad_len_spaces(m, len);
                                seq_printf(m, "[stack:%d]", tid);
                        }
+                       goto done;
+               }
+
+               if (vma_get_anon_name(vma)) {
+                       pad_len_spaces(m, len);
+                       seq_print_vma_name(m, vma);
                }
        }
 
@@ -437,8 +493,18 @@ struct mem_size_stats {
        unsigned long swap;
        unsigned long nonlinear;
        u64 pss;
+        u64 pswap;
 };
 
+#ifdef CONFIG_SWAP 
+extern struct swap_info_struct *swap_info_get(swp_entry_t entry);
+extern void swap_info_unlock(struct swap_info_struct *si);
+#endif // CONFIG_SWAP 
+
+static inline unsigned char swap_count(unsigned char ent)
+{
+       return ent & ~SWAP_HAS_CACHE;   /* may include SWAP_HAS_CONT flag */
+}
 
 static void smaps_pte_entry(pte_t ptent, unsigned long addr,
                unsigned long ptent_size, struct mm_walk *walk)
@@ -454,9 +520,29 @@ static void smaps_pte_entry(pte_t ptent, unsigned long addr,
        } else if (is_swap_pte(ptent)) {
                swp_entry_t swpent = pte_to_swp_entry(ptent);
 
-               if (!non_swap_entry(swpent))
+               if (!non_swap_entry(swpent)) {
+#ifdef CONFIG_SWAP
+                       swp_entry_t entry;
+                       struct swap_info_struct *p;
+#endif // CONFIG_SWAP
+
                        mss->swap += ptent_size;
-               else if (is_migration_entry(swpent))
+
+#ifdef CONFIG_SWAP
+                       entry = pte_to_swp_entry(ptent);
+                       if (non_swap_entry(entry))
+                               return;
+                       p = swap_info_get(entry);
+                       if (p) {
+                               int swapcount = swap_count(p->swap_map[swp_offset(entry)]);
+                               if (swapcount == 0) {
+                                       swapcount = 1;
+                               }
+                               mss->pswap += (ptent_size << PSS_SHIFT) / swapcount;
+                               swap_info_unlock(p);
+                       }
+#endif // CONFIG_SWAP
+               } else if (is_migration_entry(swpent))
                        page = migration_entry_to_page(swpent);
        } else if (pte_file(ptent)) {
                if (pte_to_pgoff(ptent) != pgoff)
@@ -605,6 +691,7 @@ static int show_smap(struct seq_file *m, void *v, int is_pid)
                   "Anonymous:      %8lu kB\n"
                   "AnonHugePages:  %8lu kB\n"
                   "Swap:           %8lu kB\n"
+                  "PSwap:          %8lu kB\n"
                   "KernelPageSize: %8lu kB\n"
                   "MMUPageSize:    %8lu kB\n"
                   "Locked:         %8lu kB\n",
@@ -619,6 +706,7 @@ static int show_smap(struct seq_file *m, void *v, int is_pid)
                   mss.anonymous >> 10,
                   mss.anonymous_thp >> 10,
                   mss.swap >> 10,
+                  (unsigned long)(mss.pswap >> (10 + PSS_SHIFT)),
                   vma_kernel_pagesize(vma) >> 10,
                   vma_mmu_pagesize(vma) >> 10,
                   (vma->vm_flags & VM_LOCKED) ?
@@ -630,6 +718,12 @@ static int show_smap(struct seq_file *m, void *v, int is_pid)
 
        show_smap_vma_flags(m, vma);
 
+       if (vma_get_anon_name(vma)) {
+               seq_puts(m, "Name:           ");
+               seq_print_vma_name(m, vma);
+               seq_putc(m, '\n');
+       }
+
        if (m->count < m->size)  /* vma is copied successfully */
                m->version = (vma != get_gate_vma(task->mm))
                        ? vma->vm_start : 0;