aboutsummaryrefslogtreecommitdiffstats
path: root/fs
diff options
context:
space:
mode:
Diffstat (limited to 'fs')
-rw-r--r--fs/Kconfig43
-rw-r--r--fs/aio.c4
-rw-r--r--fs/binfmt_flat.c2
-rw-r--r--fs/devpts/Makefile1
-rw-r--r--fs/devpts/inode.c21
-rw-r--r--fs/devpts/xattr_security.c47
-rw-r--r--fs/proc/base.c96
-rw-r--r--fs/proc/task_mmu.c357
-rw-r--r--fs/xattr.c80
9 files changed, 465 insertions, 186 deletions
diff --git a/fs/Kconfig b/fs/Kconfig
index e54be7058359..ed78d24ee426 100644
--- a/fs/Kconfig
+++ b/fs/Kconfig
@@ -783,28 +783,6 @@ config SYSFS
783 783
784 Designers of embedded systems may wish to say N here to conserve space. 784 Designers of embedded systems may wish to say N here to conserve space.
785 785
786config DEVPTS_FS_XATTR
787 bool "/dev/pts Extended Attributes"
788 depends on UNIX98_PTYS
789 help
790 Extended attributes are name:value pairs associated with inodes by
791 the kernel or by users (see the attr(5) manual page, or visit
792 <http://acl.bestbits.at/> for details).
793
794 If unsure, say N.
795
796config DEVPTS_FS_SECURITY
797 bool "/dev/pts Security Labels"
798 depends on DEVPTS_FS_XATTR
799 help
800 Security labels support alternative access control models
801 implemented by security modules like SELinux. This option
802 enables an extended attribute handler for file security
803 labels in the /dev/pts filesystem.
804
805 If you are not using a security module that requires using
806 extended attributes for file security labels, say N.
807
808config TMPFS 786config TMPFS
809 bool "Virtual memory file system support (former shm fs)" 787 bool "Virtual memory file system support (former shm fs)"
810 help 788 help
@@ -817,27 +795,6 @@ config TMPFS
817 795
818 See <file:Documentation/filesystems/tmpfs.txt> for details. 796 See <file:Documentation/filesystems/tmpfs.txt> for details.
819 797
820config TMPFS_XATTR
821 bool "tmpfs Extended Attributes"
822 depends on TMPFS
823 help
824 Extended attributes are name:value pairs associated with inodes by
825 the kernel or by users (see the attr(5) manual page, or visit
826 <http://acl.bestbits.at/> for details).
827
828 If unsure, say N.
829
830config TMPFS_SECURITY
831 bool "tmpfs Security Labels"
832 depends on TMPFS_XATTR
833 help
834 Security labels support alternative access control models
835 implemented by security modules like SELinux. This option
836 enables an extended attribute handler for file security
837 labels in the tmpfs filesystem.
838 If you are not using a security module that requires using
839 extended attributes for file security labels, say N.
840
841config HUGETLBFS 798config HUGETLBFS
842 bool "HugeTLB file system support" 799 bool "HugeTLB file system support"
843 depends X86 || IA64 || PPC64 || SPARC64 || SUPERH || X86_64 || BROKEN 800 depends X86 || IA64 || PPC64 || SPARC64 || SUPERH || X86_64 || BROKEN
diff --git a/fs/aio.c b/fs/aio.c
index 06d7d4390fe7..4f641abac3c0 100644
--- a/fs/aio.c
+++ b/fs/aio.c
@@ -567,6 +567,10 @@ static void use_mm(struct mm_struct *mm)
567 atomic_inc(&mm->mm_count); 567 atomic_inc(&mm->mm_count);
568 tsk->mm = mm; 568 tsk->mm = mm;
569 tsk->active_mm = mm; 569 tsk->active_mm = mm;
570 /*
571 * Note that on UML this *requires* PF_BORROWED_MM to be set, otherwise
572 * it won't work. Update it accordingly if you change it here
573 */
570 activate_mm(active_mm, mm); 574 activate_mm(active_mm, mm);
571 task_unlock(tsk); 575 task_unlock(tsk);
572 576
diff --git a/fs/binfmt_flat.c b/fs/binfmt_flat.c
index c8998dc66882..7974efa107bc 100644
--- a/fs/binfmt_flat.c
+++ b/fs/binfmt_flat.c
@@ -520,7 +520,7 @@ static int load_flat_file(struct linux_binprm * bprm,
520 DBG_FLT("BINFMT_FLAT: ROM mapping of file (we hope)\n"); 520 DBG_FLT("BINFMT_FLAT: ROM mapping of file (we hope)\n");
521 521
522 down_write(&current->mm->mmap_sem); 522 down_write(&current->mm->mmap_sem);
523 textpos = do_mmap(bprm->file, 0, text_len, PROT_READ|PROT_EXEC, MAP_SHARED, 0); 523 textpos = do_mmap(bprm->file, 0, text_len, PROT_READ|PROT_EXEC, MAP_PRIVATE, 0);
524 up_write(&current->mm->mmap_sem); 524 up_write(&current->mm->mmap_sem);
525 if (!textpos || textpos >= (unsigned long) -4096) { 525 if (!textpos || textpos >= (unsigned long) -4096) {
526 if (!textpos) 526 if (!textpos)
diff --git a/fs/devpts/Makefile b/fs/devpts/Makefile
index 5800df2e50c8..236696efcbac 100644
--- a/fs/devpts/Makefile
+++ b/fs/devpts/Makefile
@@ -5,4 +5,3 @@
5obj-$(CONFIG_UNIX98_PTYS) += devpts.o 5obj-$(CONFIG_UNIX98_PTYS) += devpts.o
6 6
7devpts-$(CONFIG_UNIX98_PTYS) := inode.o 7devpts-$(CONFIG_UNIX98_PTYS) := inode.o
8devpts-$(CONFIG_DEVPTS_FS_SECURITY) += xattr_security.o
diff --git a/fs/devpts/inode.c b/fs/devpts/inode.c
index 1571c8d6c232..f2be44d4491f 100644
--- a/fs/devpts/inode.c
+++ b/fs/devpts/inode.c
@@ -18,28 +18,9 @@
18#include <linux/mount.h> 18#include <linux/mount.h>
19#include <linux/tty.h> 19#include <linux/tty.h>
20#include <linux/devpts_fs.h> 20#include <linux/devpts_fs.h>
21#include <linux/xattr.h>
22 21
23#define DEVPTS_SUPER_MAGIC 0x1cd1 22#define DEVPTS_SUPER_MAGIC 0x1cd1
24 23
25extern struct xattr_handler devpts_xattr_security_handler;
26
27static struct xattr_handler *devpts_xattr_handlers[] = {
28#ifdef CONFIG_DEVPTS_FS_SECURITY
29 &devpts_xattr_security_handler,
30#endif
31 NULL
32};
33
34static struct inode_operations devpts_file_inode_operations = {
35#ifdef CONFIG_DEVPTS_FS_XATTR
36 .setxattr = generic_setxattr,
37 .getxattr = generic_getxattr,
38 .listxattr = generic_listxattr,
39 .removexattr = generic_removexattr,
40#endif
41};
42
43static struct vfsmount *devpts_mnt; 24static struct vfsmount *devpts_mnt;
44static struct dentry *devpts_root; 25static struct dentry *devpts_root;
45 26
@@ -102,7 +83,6 @@ devpts_fill_super(struct super_block *s, void *data, int silent)
102 s->s_blocksize_bits = 10; 83 s->s_blocksize_bits = 10;
103 s->s_magic = DEVPTS_SUPER_MAGIC; 84 s->s_magic = DEVPTS_SUPER_MAGIC;
104 s->s_op = &devpts_sops; 85 s->s_op = &devpts_sops;
105 s->s_xattr = devpts_xattr_handlers;
106 s->s_time_gran = 1; 86 s->s_time_gran = 1;
107 87
108 inode = new_inode(s); 88 inode = new_inode(s);
@@ -175,7 +155,6 @@ int devpts_pty_new(struct tty_struct *tty)
175 inode->i_gid = config.setgid ? config.gid : current->fsgid; 155 inode->i_gid = config.setgid ? config.gid : current->fsgid;
176 inode->i_mtime = inode->i_atime = inode->i_ctime = CURRENT_TIME; 156 inode->i_mtime = inode->i_atime = inode->i_ctime = CURRENT_TIME;
177 init_special_inode(inode, S_IFCHR|config.mode, device); 157 init_special_inode(inode, S_IFCHR|config.mode, device);
178 inode->i_op = &devpts_file_inode_operations;
179 inode->u.generic_ip = tty; 158 inode->u.generic_ip = tty;
180 159
181 dentry = get_node(number); 160 dentry = get_node(number);
diff --git a/fs/devpts/xattr_security.c b/fs/devpts/xattr_security.c
deleted file mode 100644
index 864cb5c79baa..000000000000
--- a/fs/devpts/xattr_security.c
+++ /dev/null
@@ -1,47 +0,0 @@
1/*
2 * Security xattr support for devpts.
3 *
4 * Author: Stephen Smalley <sds@epoch.ncsc.mil>
5 * Copyright (c) 2004 Red Hat, Inc., James Morris <jmorris@redhat.com>
6 *
7 * This program is free software; you can redistribute it and/or modify it
8 * under the terms of the GNU General Public License as published by the Free
9 * Software Foundation; either version 2 of the License, or (at your option)
10 * any later version.
11 */
12#include <linux/string.h>
13#include <linux/fs.h>
14#include <linux/security.h>
15#include <linux/xattr.h>
16
17static size_t
18devpts_xattr_security_list(struct inode *inode, char *list, size_t list_len,
19 const char *name, size_t name_len)
20{
21 return security_inode_listsecurity(inode, list, list_len);
22}
23
24static int
25devpts_xattr_security_get(struct inode *inode, const char *name,
26 void *buffer, size_t size)
27{
28 if (strcmp(name, "") == 0)
29 return -EINVAL;
30 return security_inode_getsecurity(inode, name, buffer, size);
31}
32
33static int
34devpts_xattr_security_set(struct inode *inode, const char *name,
35 const void *value, size_t size, int flags)
36{
37 if (strcmp(name, "") == 0)
38 return -EINVAL;
39 return security_inode_setsecurity(inode, name, value, size, flags);
40}
41
42struct xattr_handler devpts_xattr_security_handler = {
43 .prefix = XATTR_SECURITY_PREFIX,
44 .list = devpts_xattr_security_list,
45 .get = devpts_xattr_security_get,
46 .set = devpts_xattr_security_set,
47};
diff --git a/fs/proc/base.c b/fs/proc/base.c
index 491f2d9f89ac..520978e49e92 100644
--- a/fs/proc/base.c
+++ b/fs/proc/base.c
@@ -11,6 +11,40 @@
11 * go into icache. We cache the reference to task_struct upon lookup too. 11 * go into icache. We cache the reference to task_struct upon lookup too.
12 * Eventually it should become a filesystem in its own. We don't use the 12 * Eventually it should become a filesystem in its own. We don't use the
13 * rest of procfs anymore. 13 * rest of procfs anymore.
14 *
15 *
16 * Changelog:
17 * 17-Jan-2005
18 * Allan Bezerra
19 * Bruna Moreira <bruna.moreira@indt.org.br>
20 * Edjard Mota <edjard.mota@indt.org.br>
21 * Ilias Biris <ilias.biris@indt.org.br>
22 * Mauricio Lin <mauricio.lin@indt.org.br>
23 *
24 * Embedded Linux Lab - 10LE Instituto Nokia de Tecnologia - INdT
25 *
26 * A new process specific entry (smaps) included in /proc. It shows the
27 * size of rss for each memory area. The maps entry lacks information
28 * about physical memory size (rss) for each mapped file, i.e.,
29 * rss information for executables and library files.
30 * This additional information is useful for any tools that need to know
31 * about physical memory consumption for a process specific library.
32 *
33 * Changelog:
34 * 21-Feb-2005
35 * Embedded Linux Lab - 10LE Instituto Nokia de Tecnologia - INdT
36 * Pud inclusion in the page table walking.
37 *
38 * ChangeLog:
39 * 10-Mar-2005
40 * 10LE Instituto Nokia de Tecnologia - INdT:
41 * A better way to walks through the page table as suggested by Hugh Dickins.
42 *
43 * Simo Piiroinen <simo.piiroinen@nokia.com>:
44 * Smaps information related to shared, private, clean and dirty pages.
45 *
46 * Paul Mundt <paul.mundt@nokia.com>:
47 * Overall revision about smaps.
14 */ 48 */
15 49
16#include <asm/uaccess.h> 50#include <asm/uaccess.h>
@@ -65,8 +99,10 @@ enum pid_directory_inos {
65 PROC_TGID_STAT, 99 PROC_TGID_STAT,
66 PROC_TGID_STATM, 100 PROC_TGID_STATM,
67 PROC_TGID_MAPS, 101 PROC_TGID_MAPS,
102 PROC_TGID_NUMA_MAPS,
68 PROC_TGID_MOUNTS, 103 PROC_TGID_MOUNTS,
69 PROC_TGID_WCHAN, 104 PROC_TGID_WCHAN,
105 PROC_TGID_SMAPS,
70#ifdef CONFIG_SCHEDSTATS 106#ifdef CONFIG_SCHEDSTATS
71 PROC_TGID_SCHEDSTAT, 107 PROC_TGID_SCHEDSTAT,
72#endif 108#endif
@@ -102,8 +138,10 @@ enum pid_directory_inos {
102 PROC_TID_STAT, 138 PROC_TID_STAT,
103 PROC_TID_STATM, 139 PROC_TID_STATM,
104 PROC_TID_MAPS, 140 PROC_TID_MAPS,
141 PROC_TID_NUMA_MAPS,
105 PROC_TID_MOUNTS, 142 PROC_TID_MOUNTS,
106 PROC_TID_WCHAN, 143 PROC_TID_WCHAN,
144 PROC_TID_SMAPS,
107#ifdef CONFIG_SCHEDSTATS 145#ifdef CONFIG_SCHEDSTATS
108 PROC_TID_SCHEDSTAT, 146 PROC_TID_SCHEDSTAT,
109#endif 147#endif
@@ -144,6 +182,9 @@ static struct pid_entry tgid_base_stuff[] = {
144 E(PROC_TGID_STAT, "stat", S_IFREG|S_IRUGO), 182 E(PROC_TGID_STAT, "stat", S_IFREG|S_IRUGO),
145 E(PROC_TGID_STATM, "statm", S_IFREG|S_IRUGO), 183 E(PROC_TGID_STATM, "statm", S_IFREG|S_IRUGO),
146 E(PROC_TGID_MAPS, "maps", S_IFREG|S_IRUGO), 184 E(PROC_TGID_MAPS, "maps", S_IFREG|S_IRUGO),
185#ifdef CONFIG_NUMA
186 E(PROC_TGID_NUMA_MAPS, "numa_maps", S_IFREG|S_IRUGO),
187#endif
147 E(PROC_TGID_MEM, "mem", S_IFREG|S_IRUSR|S_IWUSR), 188 E(PROC_TGID_MEM, "mem", S_IFREG|S_IRUSR|S_IWUSR),
148#ifdef CONFIG_SECCOMP 189#ifdef CONFIG_SECCOMP
149 E(PROC_TGID_SECCOMP, "seccomp", S_IFREG|S_IRUSR|S_IWUSR), 190 E(PROC_TGID_SECCOMP, "seccomp", S_IFREG|S_IRUSR|S_IWUSR),
@@ -152,6 +193,7 @@ static struct pid_entry tgid_base_stuff[] = {
152 E(PROC_TGID_ROOT, "root", S_IFLNK|S_IRWXUGO), 193 E(PROC_TGID_ROOT, "root", S_IFLNK|S_IRWXUGO),
153 E(PROC_TGID_EXE, "exe", S_IFLNK|S_IRWXUGO), 194 E(PROC_TGID_EXE, "exe", S_IFLNK|S_IRWXUGO),
154 E(PROC_TGID_MOUNTS, "mounts", S_IFREG|S_IRUGO), 195 E(PROC_TGID_MOUNTS, "mounts", S_IFREG|S_IRUGO),
196 E(PROC_TGID_SMAPS, "smaps", S_IFREG|S_IRUGO),
155#ifdef CONFIG_SECURITY 197#ifdef CONFIG_SECURITY
156 E(PROC_TGID_ATTR, "attr", S_IFDIR|S_IRUGO|S_IXUGO), 198 E(PROC_TGID_ATTR, "attr", S_IFDIR|S_IRUGO|S_IXUGO),
157#endif 199#endif
@@ -180,6 +222,9 @@ static struct pid_entry tid_base_stuff[] = {
180 E(PROC_TID_STAT, "stat", S_IFREG|S_IRUGO), 222 E(PROC_TID_STAT, "stat", S_IFREG|S_IRUGO),
181 E(PROC_TID_STATM, "statm", S_IFREG|S_IRUGO), 223 E(PROC_TID_STATM, "statm", S_IFREG|S_IRUGO),
182 E(PROC_TID_MAPS, "maps", S_IFREG|S_IRUGO), 224 E(PROC_TID_MAPS, "maps", S_IFREG|S_IRUGO),
225#ifdef CONFIG_NUMA
226 E(PROC_TID_NUMA_MAPS, "numa_maps", S_IFREG|S_IRUGO),
227#endif
183 E(PROC_TID_MEM, "mem", S_IFREG|S_IRUSR|S_IWUSR), 228 E(PROC_TID_MEM, "mem", S_IFREG|S_IRUSR|S_IWUSR),
184#ifdef CONFIG_SECCOMP 229#ifdef CONFIG_SECCOMP
185 E(PROC_TID_SECCOMP, "seccomp", S_IFREG|S_IRUSR|S_IWUSR), 230 E(PROC_TID_SECCOMP, "seccomp", S_IFREG|S_IRUSR|S_IWUSR),
@@ -188,6 +233,7 @@ static struct pid_entry tid_base_stuff[] = {
188 E(PROC_TID_ROOT, "root", S_IFLNK|S_IRWXUGO), 233 E(PROC_TID_ROOT, "root", S_IFLNK|S_IRWXUGO),
189 E(PROC_TID_EXE, "exe", S_IFLNK|S_IRWXUGO), 234 E(PROC_TID_EXE, "exe", S_IFLNK|S_IRWXUGO),
190 E(PROC_TID_MOUNTS, "mounts", S_IFREG|S_IRUGO), 235 E(PROC_TID_MOUNTS, "mounts", S_IFREG|S_IRUGO),
236 E(PROC_TID_SMAPS, "smaps", S_IFREG|S_IRUGO),
191#ifdef CONFIG_SECURITY 237#ifdef CONFIG_SECURITY
192 E(PROC_TID_ATTR, "attr", S_IFDIR|S_IRUGO|S_IXUGO), 238 E(PROC_TID_ATTR, "attr", S_IFDIR|S_IRUGO|S_IXUGO),
193#endif 239#endif
@@ -515,6 +561,46 @@ static struct file_operations proc_maps_operations = {
515 .release = seq_release, 561 .release = seq_release,
516}; 562};
517 563
564#ifdef CONFIG_NUMA
565extern struct seq_operations proc_pid_numa_maps_op;
566static int numa_maps_open(struct inode *inode, struct file *file)
567{
568 struct task_struct *task = proc_task(inode);
569 int ret = seq_open(file, &proc_pid_numa_maps_op);
570 if (!ret) {
571 struct seq_file *m = file->private_data;
572 m->private = task;
573 }
574 return ret;
575}
576
577static struct file_operations proc_numa_maps_operations = {
578 .open = numa_maps_open,
579 .read = seq_read,
580 .llseek = seq_lseek,
581 .release = seq_release,
582};
583#endif
584
585extern struct seq_operations proc_pid_smaps_op;
586static int smaps_open(struct inode *inode, struct file *file)
587{
588 struct task_struct *task = proc_task(inode);
589 int ret = seq_open(file, &proc_pid_smaps_op);
590 if (!ret) {
591 struct seq_file *m = file->private_data;
592 m->private = task;
593 }
594 return ret;
595}
596
597static struct file_operations proc_smaps_operations = {
598 .open = smaps_open,
599 .read = seq_read,
600 .llseek = seq_lseek,
601 .release = seq_release,
602};
603
518extern struct seq_operations mounts_op; 604extern struct seq_operations mounts_op;
519static int mounts_open(struct inode *inode, struct file *file) 605static int mounts_open(struct inode *inode, struct file *file)
520{ 606{
@@ -1524,6 +1610,12 @@ static struct dentry *proc_pident_lookup(struct inode *dir,
1524 case PROC_TGID_MAPS: 1610 case PROC_TGID_MAPS:
1525 inode->i_fop = &proc_maps_operations; 1611 inode->i_fop = &proc_maps_operations;
1526 break; 1612 break;
1613#ifdef CONFIG_NUMA
1614 case PROC_TID_NUMA_MAPS:
1615 case PROC_TGID_NUMA_MAPS:
1616 inode->i_fop = &proc_numa_maps_operations;
1617 break;
1618#endif
1527 case PROC_TID_MEM: 1619 case PROC_TID_MEM:
1528 case PROC_TGID_MEM: 1620 case PROC_TGID_MEM:
1529 inode->i_op = &proc_mem_inode_operations; 1621 inode->i_op = &proc_mem_inode_operations;
@@ -1539,6 +1631,10 @@ static struct dentry *proc_pident_lookup(struct inode *dir,
1539 case PROC_TGID_MOUNTS: 1631 case PROC_TGID_MOUNTS:
1540 inode->i_fop = &proc_mounts_operations; 1632 inode->i_fop = &proc_mounts_operations;
1541 break; 1633 break;
1634 case PROC_TID_SMAPS:
1635 case PROC_TGID_SMAPS:
1636 inode->i_fop = &proc_smaps_operations;
1637 break;
1542#ifdef CONFIG_SECURITY 1638#ifdef CONFIG_SECURITY
1543 case PROC_TID_ATTR: 1639 case PROC_TID_ATTR:
1544 inode->i_nlink = 2; 1640 inode->i_nlink = 2;
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
9char *task_mem(struct mm_struct *mm, char *buffer) 14char *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
90static int show_map(struct seq_file *m, void *v) 95struct 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
104static 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
179static int show_map(struct seq_file *m, void *v)
180{
181 return show_map_internal(m, v, 0);
182}
183
184static 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
220static 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
236static 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
252static 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
268static 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
149static void *m_start(struct seq_file *m, loff_t *pos) 285static 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
195out: 331out:
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
206static void m_stop(struct seq_file *m, void *v) 342static 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)
217static void *m_next(struct seq_file *m, void *v, loff_t *pos) 353static 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
230struct seq_operations proc_pid_maps_op = { 366struct 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
373struct 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
382struct 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 */
393static 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
430static 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
502struct 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
diff --git a/fs/xattr.c b/fs/xattr.c
index 6acd5c63da91..dc8bc7624f26 100644
--- a/fs/xattr.c
+++ b/fs/xattr.c
@@ -51,20 +51,29 @@ setxattr(struct dentry *d, char __user *name, void __user *value,
51 } 51 }
52 } 52 }
53 53
54 down(&d->d_inode->i_sem);
55 error = security_inode_setxattr(d, kname, kvalue, size, flags);
56 if (error)
57 goto out;
54 error = -EOPNOTSUPP; 58 error = -EOPNOTSUPP;
55 if (d->d_inode->i_op && d->d_inode->i_op->setxattr) { 59 if (d->d_inode->i_op && d->d_inode->i_op->setxattr) {
56 down(&d->d_inode->i_sem); 60 error = d->d_inode->i_op->setxattr(d, kname, kvalue,
57 error = security_inode_setxattr(d, kname, kvalue, size, flags); 61 size, flags);
58 if (error)
59 goto out;
60 error = d->d_inode->i_op->setxattr(d, kname, kvalue, size, flags);
61 if (!error) { 62 if (!error) {
62 fsnotify_xattr(d); 63 fsnotify_xattr(d);
63 security_inode_post_setxattr(d, kname, kvalue, size, flags); 64 security_inode_post_setxattr(d, kname, kvalue,
65 size, flags);
64 } 66 }
65out: 67 } else if (!strncmp(kname, XATTR_SECURITY_PREFIX,
66 up(&d->d_inode->i_sem); 68 sizeof XATTR_SECURITY_PREFIX - 1)) {
69 const char *suffix = kname + sizeof XATTR_SECURITY_PREFIX - 1;
70 error = security_inode_setsecurity(d->d_inode, suffix, kvalue,
71 size, flags);
72 if (!error)
73 fsnotify_xattr(d);
67 } 74 }
75out:
76 up(&d->d_inode->i_sem);
68 if (kvalue) 77 if (kvalue)
69 kfree(kvalue); 78 kfree(kvalue);
70 return error; 79 return error;
@@ -139,20 +148,25 @@ getxattr(struct dentry *d, char __user *name, void __user *value, size_t size)
139 return -ENOMEM; 148 return -ENOMEM;
140 } 149 }
141 150
151 error = security_inode_getxattr(d, kname);
152 if (error)
153 goto out;
142 error = -EOPNOTSUPP; 154 error = -EOPNOTSUPP;
143 if (d->d_inode->i_op && d->d_inode->i_op->getxattr) { 155 if (d->d_inode->i_op && d->d_inode->i_op->getxattr)
144 error = security_inode_getxattr(d, kname);
145 if (error)
146 goto out;
147 error = d->d_inode->i_op->getxattr(d, kname, kvalue, size); 156 error = d->d_inode->i_op->getxattr(d, kname, kvalue, size);
148 if (error > 0) { 157 else if (!strncmp(kname, XATTR_SECURITY_PREFIX,
149 if (size && copy_to_user(value, kvalue, error)) 158 sizeof XATTR_SECURITY_PREFIX - 1)) {
150 error = -EFAULT; 159 const char *suffix = kname + sizeof XATTR_SECURITY_PREFIX - 1;
151 } else if (error == -ERANGE && size >= XATTR_SIZE_MAX) { 160 error = security_inode_getsecurity(d->d_inode, suffix, kvalue,
152 /* The file system tried to returned a value bigger 161 size);
153 than XATTR_SIZE_MAX bytes. Not possible. */ 162 }
154 error = -E2BIG; 163 if (error > 0) {
155 } 164 if (size && copy_to_user(value, kvalue, error))
165 error = -EFAULT;
166 } else if (error == -ERANGE && size >= XATTR_SIZE_MAX) {
167 /* The file system tried to returned a value bigger
168 than XATTR_SIZE_MAX bytes. Not possible. */
169 error = -E2BIG;
156 } 170 }
157out: 171out:
158 if (kvalue) 172 if (kvalue)
@@ -221,20 +235,24 @@ listxattr(struct dentry *d, char __user *list, size_t size)
221 return -ENOMEM; 235 return -ENOMEM;
222 } 236 }
223 237
238 error = security_inode_listxattr(d);
239 if (error)
240 goto out;
224 error = -EOPNOTSUPP; 241 error = -EOPNOTSUPP;
225 if (d->d_inode->i_op && d->d_inode->i_op->listxattr) { 242 if (d->d_inode->i_op && d->d_inode->i_op->listxattr) {
226 error = security_inode_listxattr(d);
227 if (error)
228 goto out;
229 error = d->d_inode->i_op->listxattr(d, klist, size); 243 error = d->d_inode->i_op->listxattr(d, klist, size);
230 if (error > 0) { 244 } else {
231 if (size && copy_to_user(list, klist, error)) 245 error = security_inode_listsecurity(d->d_inode, klist, size);
232 error = -EFAULT; 246 if (size && error >= size)
233 } else if (error == -ERANGE && size >= XATTR_LIST_MAX) { 247 error = -ERANGE;
234 /* The file system tried to returned a list bigger 248 }
235 than XATTR_LIST_MAX bytes. Not possible. */ 249 if (error > 0) {
236 error = -E2BIG; 250 if (size && copy_to_user(list, klist, error))
237 } 251 error = -EFAULT;
252 } else if (error == -ERANGE && size >= XATTR_LIST_MAX) {
253 /* The file system tried to returned a list bigger
254 than XATTR_LIST_MAX bytes. Not possible. */
255 error = -E2BIG;
238 } 256 }
239out: 257out:
240 if (klist) 258 if (klist)