diff options
Diffstat (limited to 'fs/proc/task_mmu.c')
| -rw-r--r-- | fs/proc/task_mmu.c | 357 |
1 files changed, 315 insertions, 42 deletions
diff --git a/fs/proc/task_mmu.c b/fs/proc/task_mmu.c index 28b4a0253a92..c7ef3e48e35b 100644 --- a/fs/proc/task_mmu.c +++ b/fs/proc/task_mmu.c | |||
| @@ -2,8 +2,13 @@ | |||
| 2 | #include <linux/hugetlb.h> | 2 | #include <linux/hugetlb.h> |
| 3 | #include <linux/mount.h> | 3 | #include <linux/mount.h> |
| 4 | #include <linux/seq_file.h> | 4 | #include <linux/seq_file.h> |
| 5 | #include <linux/highmem.h> | ||
| 6 | #include <linux/pagemap.h> | ||
| 7 | #include <linux/mempolicy.h> | ||
| 8 | |||
| 5 | #include <asm/elf.h> | 9 | #include <asm/elf.h> |
| 6 | #include <asm/uaccess.h> | 10 | #include <asm/uaccess.h> |
| 11 | #include <asm/tlbflush.h> | ||
| 7 | #include "internal.h" | 12 | #include "internal.h" |
| 8 | 13 | ||
| 9 | char *task_mem(struct mm_struct *mm, char *buffer) | 14 | char *task_mem(struct mm_struct *mm, char *buffer) |
| @@ -87,49 +92,58 @@ static void pad_len_spaces(struct seq_file *m, int len) | |||
| 87 | seq_printf(m, "%*c", len, ' '); | 92 | seq_printf(m, "%*c", len, ' '); |
| 88 | } | 93 | } |
| 89 | 94 | ||
| 90 | static int show_map(struct seq_file *m, void *v) | 95 | struct mem_size_stats |
| 96 | { | ||
| 97 | unsigned long resident; | ||
| 98 | unsigned long shared_clean; | ||
| 99 | unsigned long shared_dirty; | ||
| 100 | unsigned long private_clean; | ||
| 101 | unsigned long private_dirty; | ||
| 102 | }; | ||
| 103 | |||
| 104 | static int show_map_internal(struct seq_file *m, void *v, struct mem_size_stats *mss) | ||
| 91 | { | 105 | { |
| 92 | struct task_struct *task = m->private; | 106 | struct task_struct *task = m->private; |
| 93 | struct vm_area_struct *map = v; | 107 | struct vm_area_struct *vma = v; |
| 94 | struct mm_struct *mm = map->vm_mm; | 108 | struct mm_struct *mm = vma->vm_mm; |
| 95 | struct file *file = map->vm_file; | 109 | struct file *file = vma->vm_file; |
| 96 | int flags = map->vm_flags; | 110 | int flags = vma->vm_flags; |
| 97 | unsigned long ino = 0; | 111 | unsigned long ino = 0; |
| 98 | dev_t dev = 0; | 112 | dev_t dev = 0; |
| 99 | int len; | 113 | int len; |
| 100 | 114 | ||
| 101 | if (file) { | 115 | if (file) { |
| 102 | struct inode *inode = map->vm_file->f_dentry->d_inode; | 116 | struct inode *inode = vma->vm_file->f_dentry->d_inode; |
| 103 | dev = inode->i_sb->s_dev; | 117 | dev = inode->i_sb->s_dev; |
| 104 | ino = inode->i_ino; | 118 | ino = inode->i_ino; |
| 105 | } | 119 | } |
| 106 | 120 | ||
| 107 | seq_printf(m, "%08lx-%08lx %c%c%c%c %08lx %02x:%02x %lu %n", | 121 | seq_printf(m, "%08lx-%08lx %c%c%c%c %08lx %02x:%02x %lu %n", |
| 108 | map->vm_start, | 122 | vma->vm_start, |
| 109 | map->vm_end, | 123 | vma->vm_end, |
| 110 | flags & VM_READ ? 'r' : '-', | 124 | flags & VM_READ ? 'r' : '-', |
| 111 | flags & VM_WRITE ? 'w' : '-', | 125 | flags & VM_WRITE ? 'w' : '-', |
| 112 | flags & VM_EXEC ? 'x' : '-', | 126 | flags & VM_EXEC ? 'x' : '-', |
| 113 | flags & VM_MAYSHARE ? 's' : 'p', | 127 | flags & VM_MAYSHARE ? 's' : 'p', |
| 114 | map->vm_pgoff << PAGE_SHIFT, | 128 | vma->vm_pgoff << PAGE_SHIFT, |
| 115 | MAJOR(dev), MINOR(dev), ino, &len); | 129 | MAJOR(dev), MINOR(dev), ino, &len); |
| 116 | 130 | ||
| 117 | /* | 131 | /* |
| 118 | * Print the dentry name for named mappings, and a | 132 | * Print the dentry name for named mappings, and a |
| 119 | * special [heap] marker for the heap: | 133 | * special [heap] marker for the heap: |
| 120 | */ | 134 | */ |
| 121 | if (map->vm_file) { | 135 | if (file) { |
| 122 | pad_len_spaces(m, len); | 136 | pad_len_spaces(m, len); |
| 123 | seq_path(m, file->f_vfsmnt, file->f_dentry, ""); | 137 | seq_path(m, file->f_vfsmnt, file->f_dentry, "\n"); |
| 124 | } else { | 138 | } else { |
| 125 | if (mm) { | 139 | if (mm) { |
| 126 | if (map->vm_start <= mm->start_brk && | 140 | if (vma->vm_start <= mm->start_brk && |
| 127 | map->vm_end >= mm->brk) { | 141 | vma->vm_end >= mm->brk) { |
| 128 | pad_len_spaces(m, len); | 142 | pad_len_spaces(m, len); |
| 129 | seq_puts(m, "[heap]"); | 143 | seq_puts(m, "[heap]"); |
| 130 | } else { | 144 | } else { |
| 131 | if (map->vm_start <= mm->start_stack && | 145 | if (vma->vm_start <= mm->start_stack && |
| 132 | map->vm_end >= mm->start_stack) { | 146 | vma->vm_end >= mm->start_stack) { |
| 133 | 147 | ||
| 134 | pad_len_spaces(m, len); | 148 | pad_len_spaces(m, len); |
| 135 | seq_puts(m, "[stack]"); | 149 | seq_puts(m, "[stack]"); |
| @@ -141,24 +155,146 @@ static int show_map(struct seq_file *m, void *v) | |||
| 141 | } | 155 | } |
| 142 | } | 156 | } |
| 143 | seq_putc(m, '\n'); | 157 | seq_putc(m, '\n'); |
| 144 | if (m->count < m->size) /* map is copied successfully */ | 158 | |
| 145 | m->version = (map != get_gate_vma(task))? map->vm_start: 0; | 159 | if (mss) |
| 160 | seq_printf(m, | ||
| 161 | "Size: %8lu kB\n" | ||
| 162 | "Rss: %8lu kB\n" | ||
| 163 | "Shared_Clean: %8lu kB\n" | ||
| 164 | "Shared_Dirty: %8lu kB\n" | ||
| 165 | "Private_Clean: %8lu kB\n" | ||
| 166 | "Private_Dirty: %8lu kB\n", | ||
| 167 | (vma->vm_end - vma->vm_start) >> 10, | ||
| 168 | mss->resident >> 10, | ||
| 169 | mss->shared_clean >> 10, | ||
| 170 | mss->shared_dirty >> 10, | ||
| 171 | mss->private_clean >> 10, | ||
| 172 | mss->private_dirty >> 10); | ||
| 173 | |||
| 174 | if (m->count < m->size) /* vma is copied successfully */ | ||
| 175 | m->version = (vma != get_gate_vma(task))? vma->vm_start: 0; | ||
| 146 | return 0; | 176 | return 0; |
| 147 | } | 177 | } |
| 148 | 178 | ||
| 179 | static int show_map(struct seq_file *m, void *v) | ||
| 180 | { | ||
| 181 | return show_map_internal(m, v, 0); | ||
| 182 | } | ||
| 183 | |||
| 184 | static void smaps_pte_range(struct vm_area_struct *vma, pmd_t *pmd, | ||
| 185 | unsigned long addr, unsigned long end, | ||
| 186 | struct mem_size_stats *mss) | ||
| 187 | { | ||
| 188 | pte_t *pte, ptent; | ||
| 189 | unsigned long pfn; | ||
| 190 | struct page *page; | ||
| 191 | |||
| 192 | pte = pte_offset_map(pmd, addr); | ||
| 193 | do { | ||
| 194 | ptent = *pte; | ||
| 195 | if (pte_none(ptent) || !pte_present(ptent)) | ||
| 196 | continue; | ||
| 197 | |||
| 198 | mss->resident += PAGE_SIZE; | ||
| 199 | pfn = pte_pfn(ptent); | ||
| 200 | if (!pfn_valid(pfn)) | ||
| 201 | continue; | ||
| 202 | |||
| 203 | page = pfn_to_page(pfn); | ||
| 204 | if (page_count(page) >= 2) { | ||
| 205 | if (pte_dirty(ptent)) | ||
| 206 | mss->shared_dirty += PAGE_SIZE; | ||
| 207 | else | ||
| 208 | mss->shared_clean += PAGE_SIZE; | ||
| 209 | } else { | ||
| 210 | if (pte_dirty(ptent)) | ||
| 211 | mss->private_dirty += PAGE_SIZE; | ||
| 212 | else | ||
| 213 | mss->private_clean += PAGE_SIZE; | ||
| 214 | } | ||
| 215 | } while (pte++, addr += PAGE_SIZE, addr != end); | ||
| 216 | pte_unmap(pte - 1); | ||
| 217 | cond_resched_lock(&vma->vm_mm->page_table_lock); | ||
| 218 | } | ||
| 219 | |||
| 220 | static inline void smaps_pmd_range(struct vm_area_struct *vma, pud_t *pud, | ||
| 221 | unsigned long addr, unsigned long end, | ||
| 222 | struct mem_size_stats *mss) | ||
| 223 | { | ||
| 224 | pmd_t *pmd; | ||
| 225 | unsigned long next; | ||
| 226 | |||
| 227 | pmd = pmd_offset(pud, addr); | ||
| 228 | do { | ||
| 229 | next = pmd_addr_end(addr, end); | ||
| 230 | if (pmd_none_or_clear_bad(pmd)) | ||
| 231 | continue; | ||
| 232 | smaps_pte_range(vma, pmd, addr, next, mss); | ||
| 233 | } while (pmd++, addr = next, addr != end); | ||
| 234 | } | ||
| 235 | |||
| 236 | static inline void smaps_pud_range(struct vm_area_struct *vma, pgd_t *pgd, | ||
| 237 | unsigned long addr, unsigned long end, | ||
| 238 | struct mem_size_stats *mss) | ||
| 239 | { | ||
| 240 | pud_t *pud; | ||
| 241 | unsigned long next; | ||
| 242 | |||
| 243 | pud = pud_offset(pgd, addr); | ||
| 244 | do { | ||
| 245 | next = pud_addr_end(addr, end); | ||
| 246 | if (pud_none_or_clear_bad(pud)) | ||
| 247 | continue; | ||
| 248 | smaps_pmd_range(vma, pud, addr, next, mss); | ||
| 249 | } while (pud++, addr = next, addr != end); | ||
| 250 | } | ||
| 251 | |||
| 252 | static inline void smaps_pgd_range(struct vm_area_struct *vma, | ||
| 253 | unsigned long addr, unsigned long end, | ||
| 254 | struct mem_size_stats *mss) | ||
| 255 | { | ||
| 256 | pgd_t *pgd; | ||
| 257 | unsigned long next; | ||
| 258 | |||
| 259 | pgd = pgd_offset(vma->vm_mm, addr); | ||
| 260 | do { | ||
| 261 | next = pgd_addr_end(addr, end); | ||
| 262 | if (pgd_none_or_clear_bad(pgd)) | ||
| 263 | continue; | ||
| 264 | smaps_pud_range(vma, pgd, addr, next, mss); | ||
| 265 | } while (pgd++, addr = next, addr != end); | ||
| 266 | } | ||
| 267 | |||
| 268 | static int show_smap(struct seq_file *m, void *v) | ||
| 269 | { | ||
| 270 | struct vm_area_struct *vma = v; | ||
| 271 | struct mm_struct *mm = vma->vm_mm; | ||
| 272 | struct mem_size_stats mss; | ||
| 273 | |||
| 274 | memset(&mss, 0, sizeof mss); | ||
| 275 | |||
| 276 | if (mm) { | ||
| 277 | spin_lock(&mm->page_table_lock); | ||
| 278 | smaps_pgd_range(vma, vma->vm_start, vma->vm_end, &mss); | ||
| 279 | spin_unlock(&mm->page_table_lock); | ||
| 280 | } | ||
| 281 | |||
| 282 | return show_map_internal(m, v, &mss); | ||
| 283 | } | ||
| 284 | |||
| 149 | static void *m_start(struct seq_file *m, loff_t *pos) | 285 | static void *m_start(struct seq_file *m, loff_t *pos) |
| 150 | { | 286 | { |
| 151 | struct task_struct *task = m->private; | 287 | struct task_struct *task = m->private; |
| 152 | unsigned long last_addr = m->version; | 288 | unsigned long last_addr = m->version; |
| 153 | struct mm_struct *mm; | 289 | struct mm_struct *mm; |
| 154 | struct vm_area_struct *map, *tail_map; | 290 | struct vm_area_struct *vma, *tail_vma; |
| 155 | loff_t l = *pos; | 291 | loff_t l = *pos; |
| 156 | 292 | ||
| 157 | /* | 293 | /* |
| 158 | * We remember last_addr rather than next_addr to hit with | 294 | * We remember last_addr rather than next_addr to hit with |
| 159 | * mmap_cache most of the time. We have zero last_addr at | 295 | * mmap_cache most of the time. We have zero last_addr at |
| 160 | * the begining and also after lseek. We will have -1 last_addr | 296 | * the beginning and also after lseek. We will have -1 last_addr |
| 161 | * after the end of the maps. | 297 | * after the end of the vmas. |
| 162 | */ | 298 | */ |
| 163 | 299 | ||
| 164 | if (last_addr == -1UL) | 300 | if (last_addr == -1UL) |
| @@ -168,47 +304,47 @@ static void *m_start(struct seq_file *m, loff_t *pos) | |||
| 168 | if (!mm) | 304 | if (!mm) |
| 169 | return NULL; | 305 | return NULL; |
| 170 | 306 | ||
| 171 | tail_map = get_gate_vma(task); | 307 | tail_vma = get_gate_vma(task); |
| 172 | down_read(&mm->mmap_sem); | 308 | down_read(&mm->mmap_sem); |
| 173 | 309 | ||
| 174 | /* Start with last addr hint */ | 310 | /* Start with last addr hint */ |
| 175 | if (last_addr && (map = find_vma(mm, last_addr))) { | 311 | if (last_addr && (vma = find_vma(mm, last_addr))) { |
| 176 | map = map->vm_next; | 312 | vma = vma->vm_next; |
| 177 | goto out; | 313 | goto out; |
| 178 | } | 314 | } |
| 179 | 315 | ||
| 180 | /* | 316 | /* |
| 181 | * Check the map index is within the range and do | 317 | * Check the vma index is within the range and do |
| 182 | * sequential scan until m_index. | 318 | * sequential scan until m_index. |
| 183 | */ | 319 | */ |
| 184 | map = NULL; | 320 | vma = NULL; |
| 185 | if ((unsigned long)l < mm->map_count) { | 321 | if ((unsigned long)l < mm->map_count) { |
| 186 | map = mm->mmap; | 322 | vma = mm->mmap; |
| 187 | while (l-- && map) | 323 | while (l-- && vma) |
| 188 | map = map->vm_next; | 324 | vma = vma->vm_next; |
| 189 | goto out; | 325 | goto out; |
| 190 | } | 326 | } |
| 191 | 327 | ||
| 192 | if (l != mm->map_count) | 328 | if (l != mm->map_count) |
| 193 | tail_map = NULL; /* After gate map */ | 329 | tail_vma = NULL; /* After gate vma */ |
| 194 | 330 | ||
| 195 | out: | 331 | out: |
| 196 | if (map) | 332 | if (vma) |
| 197 | return map; | 333 | return vma; |
| 198 | 334 | ||
| 199 | /* End of maps has reached */ | 335 | /* End of vmas has been reached */ |
| 200 | m->version = (tail_map != NULL)? 0: -1UL; | 336 | m->version = (tail_vma != NULL)? 0: -1UL; |
| 201 | up_read(&mm->mmap_sem); | 337 | up_read(&mm->mmap_sem); |
| 202 | mmput(mm); | 338 | mmput(mm); |
| 203 | return tail_map; | 339 | return tail_vma; |
| 204 | } | 340 | } |
| 205 | 341 | ||
| 206 | static void m_stop(struct seq_file *m, void *v) | 342 | static void m_stop(struct seq_file *m, void *v) |
| 207 | { | 343 | { |
| 208 | struct task_struct *task = m->private; | 344 | struct task_struct *task = m->private; |
| 209 | struct vm_area_struct *map = v; | 345 | struct vm_area_struct *vma = v; |
| 210 | if (map && map != get_gate_vma(task)) { | 346 | if (vma && vma != get_gate_vma(task)) { |
| 211 | struct mm_struct *mm = map->vm_mm; | 347 | struct mm_struct *mm = vma->vm_mm; |
| 212 | up_read(&mm->mmap_sem); | 348 | up_read(&mm->mmap_sem); |
| 213 | mmput(mm); | 349 | mmput(mm); |
| 214 | } | 350 | } |
| @@ -217,14 +353,14 @@ static void m_stop(struct seq_file *m, void *v) | |||
| 217 | static void *m_next(struct seq_file *m, void *v, loff_t *pos) | 353 | static void *m_next(struct seq_file *m, void *v, loff_t *pos) |
| 218 | { | 354 | { |
| 219 | struct task_struct *task = m->private; | 355 | struct task_struct *task = m->private; |
| 220 | struct vm_area_struct *map = v; | 356 | struct vm_area_struct *vma = v; |
| 221 | struct vm_area_struct *tail_map = get_gate_vma(task); | 357 | struct vm_area_struct *tail_vma = get_gate_vma(task); |
| 222 | 358 | ||
| 223 | (*pos)++; | 359 | (*pos)++; |
| 224 | if (map && (map != tail_map) && map->vm_next) | 360 | if (vma && (vma != tail_vma) && vma->vm_next) |
| 225 | return map->vm_next; | 361 | return vma->vm_next; |
| 226 | m_stop(m, v); | 362 | m_stop(m, v); |
| 227 | return (map != tail_map)? tail_map: NULL; | 363 | return (vma != tail_vma)? tail_vma: NULL; |
| 228 | } | 364 | } |
| 229 | 365 | ||
| 230 | struct seq_operations proc_pid_maps_op = { | 366 | struct seq_operations proc_pid_maps_op = { |
| @@ -233,3 +369,140 @@ struct seq_operations proc_pid_maps_op = { | |||
| 233 | .stop = m_stop, | 369 | .stop = m_stop, |
| 234 | .show = show_map | 370 | .show = show_map |
| 235 | }; | 371 | }; |
| 372 | |||
| 373 | struct seq_operations proc_pid_smaps_op = { | ||
| 374 | .start = m_start, | ||
| 375 | .next = m_next, | ||
| 376 | .stop = m_stop, | ||
| 377 | .show = show_smap | ||
| 378 | }; | ||
| 379 | |||
| 380 | #ifdef CONFIG_NUMA | ||
| 381 | |||
| 382 | struct numa_maps { | ||
| 383 | unsigned long pages; | ||
| 384 | unsigned long anon; | ||
| 385 | unsigned long mapped; | ||
| 386 | unsigned long mapcount_max; | ||
| 387 | unsigned long node[MAX_NUMNODES]; | ||
| 388 | }; | ||
| 389 | |||
| 390 | /* | ||
| 391 | * Calculate numa node maps for a vma | ||
| 392 | */ | ||
| 393 | static struct numa_maps *get_numa_maps(const struct vm_area_struct *vma) | ||
| 394 | { | ||
| 395 | struct page *page; | ||
| 396 | unsigned long vaddr; | ||
| 397 | struct mm_struct *mm = vma->vm_mm; | ||
| 398 | int i; | ||
| 399 | struct numa_maps *md = kmalloc(sizeof(struct numa_maps), GFP_KERNEL); | ||
| 400 | |||
| 401 | if (!md) | ||
| 402 | return NULL; | ||
| 403 | md->pages = 0; | ||
| 404 | md->anon = 0; | ||
| 405 | md->mapped = 0; | ||
| 406 | md->mapcount_max = 0; | ||
| 407 | for_each_node(i) | ||
| 408 | md->node[i] =0; | ||
| 409 | |||
| 410 | spin_lock(&mm->page_table_lock); | ||
| 411 | for (vaddr = vma->vm_start; vaddr < vma->vm_end; vaddr += PAGE_SIZE) { | ||
| 412 | page = follow_page(mm, vaddr, 0); | ||
| 413 | if (page) { | ||
| 414 | int count = page_mapcount(page); | ||
| 415 | |||
| 416 | if (count) | ||
| 417 | md->mapped++; | ||
| 418 | if (count > md->mapcount_max) | ||
| 419 | md->mapcount_max = count; | ||
| 420 | md->pages++; | ||
| 421 | if (PageAnon(page)) | ||
| 422 | md->anon++; | ||
| 423 | md->node[page_to_nid(page)]++; | ||
| 424 | } | ||
| 425 | } | ||
| 426 | spin_unlock(&mm->page_table_lock); | ||
| 427 | return md; | ||
| 428 | } | ||
| 429 | |||
| 430 | static int show_numa_map(struct seq_file *m, void *v) | ||
| 431 | { | ||
| 432 | struct task_struct *task = m->private; | ||
| 433 | struct vm_area_struct *vma = v; | ||
| 434 | struct mempolicy *pol; | ||
| 435 | struct numa_maps *md; | ||
| 436 | struct zone **z; | ||
| 437 | int n; | ||
| 438 | int first; | ||
| 439 | |||
| 440 | if (!vma->vm_mm) | ||
| 441 | return 0; | ||
| 442 | |||
| 443 | md = get_numa_maps(vma); | ||
| 444 | if (!md) | ||
| 445 | return 0; | ||
| 446 | |||
| 447 | seq_printf(m, "%08lx", vma->vm_start); | ||
| 448 | pol = get_vma_policy(task, vma, vma->vm_start); | ||
| 449 | /* Print policy */ | ||
| 450 | switch (pol->policy) { | ||
| 451 | case MPOL_PREFERRED: | ||
| 452 | seq_printf(m, " prefer=%d", pol->v.preferred_node); | ||
| 453 | break; | ||
| 454 | case MPOL_BIND: | ||
| 455 | seq_printf(m, " bind={"); | ||
| 456 | first = 1; | ||
| 457 | for (z = pol->v.zonelist->zones; *z; z++) { | ||
| 458 | |||
| 459 | if (!first) | ||
| 460 | seq_putc(m, ','); | ||
| 461 | else | ||
| 462 | first = 0; | ||
| 463 | seq_printf(m, "%d/%s", (*z)->zone_pgdat->node_id, | ||
| 464 | (*z)->name); | ||
| 465 | } | ||
| 466 | seq_putc(m, '}'); | ||
| 467 | break; | ||
| 468 | case MPOL_INTERLEAVE: | ||
| 469 | seq_printf(m, " interleave={"); | ||
| 470 | first = 1; | ||
| 471 | for_each_node(n) { | ||
| 472 | if (test_bit(n, pol->v.nodes)) { | ||
| 473 | if (!first) | ||
| 474 | seq_putc(m,','); | ||
| 475 | else | ||
| 476 | first = 0; | ||
| 477 | seq_printf(m, "%d",n); | ||
| 478 | } | ||
| 479 | } | ||
| 480 | seq_putc(m, '}'); | ||
| 481 | break; | ||
| 482 | default: | ||
| 483 | seq_printf(m," default"); | ||
| 484 | break; | ||
| 485 | } | ||
| 486 | seq_printf(m, " MaxRef=%lu Pages=%lu Mapped=%lu", | ||
| 487 | md->mapcount_max, md->pages, md->mapped); | ||
| 488 | if (md->anon) | ||
| 489 | seq_printf(m," Anon=%lu",md->anon); | ||
| 490 | |||
| 491 | for_each_online_node(n) { | ||
| 492 | if (md->node[n]) | ||
| 493 | seq_printf(m, " N%d=%lu", n, md->node[n]); | ||
| 494 | } | ||
| 495 | seq_putc(m, '\n'); | ||
| 496 | kfree(md); | ||
| 497 | if (m->count < m->size) /* vma is copied successfully */ | ||
| 498 | m->version = (vma != get_gate_vma(task)) ? vma->vm_start : 0; | ||
| 499 | return 0; | ||
| 500 | } | ||
| 501 | |||
| 502 | struct seq_operations proc_pid_numa_maps_op = { | ||
| 503 | .start = m_start, | ||
| 504 | .next = m_next, | ||
| 505 | .stop = m_stop, | ||
| 506 | .show = show_numa_map | ||
| 507 | }; | ||
| 508 | #endif | ||
