aboutsummaryrefslogtreecommitdiffstats
path: root/fs/proc/base.c
diff options
context:
space:
mode:
Diffstat (limited to 'fs/proc/base.c')
-rw-r--r--fs/proc/base.c200
1 files changed, 137 insertions, 63 deletions
diff --git a/fs/proc/base.c b/fs/proc/base.c
index ace151fa4878..23db452ab428 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>
@@ -28,6 +62,7 @@
28#include <linux/namespace.h> 62#include <linux/namespace.h>
29#include <linux/mm.h> 63#include <linux/mm.h>
30#include <linux/smp_lock.h> 64#include <linux/smp_lock.h>
65#include <linux/rcupdate.h>
31#include <linux/kallsyms.h> 66#include <linux/kallsyms.h>
32#include <linux/mount.h> 67#include <linux/mount.h>
33#include <linux/security.h> 68#include <linux/security.h>
@@ -65,8 +100,10 @@ enum pid_directory_inos {
65 PROC_TGID_STAT, 100 PROC_TGID_STAT,
66 PROC_TGID_STATM, 101 PROC_TGID_STATM,
67 PROC_TGID_MAPS, 102 PROC_TGID_MAPS,
103 PROC_TGID_NUMA_MAPS,
68 PROC_TGID_MOUNTS, 104 PROC_TGID_MOUNTS,
69 PROC_TGID_WCHAN, 105 PROC_TGID_WCHAN,
106 PROC_TGID_SMAPS,
70#ifdef CONFIG_SCHEDSTATS 107#ifdef CONFIG_SCHEDSTATS
71 PROC_TGID_SCHEDSTAT, 108 PROC_TGID_SCHEDSTAT,
72#endif 109#endif
@@ -83,7 +120,6 @@ enum pid_directory_inos {
83#ifdef CONFIG_AUDITSYSCALL 120#ifdef CONFIG_AUDITSYSCALL
84 PROC_TGID_LOGINUID, 121 PROC_TGID_LOGINUID,
85#endif 122#endif
86 PROC_TGID_FD_DIR,
87 PROC_TGID_OOM_SCORE, 123 PROC_TGID_OOM_SCORE,
88 PROC_TGID_OOM_ADJUST, 124 PROC_TGID_OOM_ADJUST,
89 PROC_TID_INO, 125 PROC_TID_INO,
@@ -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
@@ -120,9 +158,11 @@ enum pid_directory_inos {
120#ifdef CONFIG_AUDITSYSCALL 158#ifdef CONFIG_AUDITSYSCALL
121 PROC_TID_LOGINUID, 159 PROC_TID_LOGINUID,
122#endif 160#endif
123 PROC_TID_FD_DIR = 0x8000, /* 0x8000-0xffff */
124 PROC_TID_OOM_SCORE, 161 PROC_TID_OOM_SCORE,
125 PROC_TID_OOM_ADJUST, 162 PROC_TID_OOM_ADJUST,
163
164 /* Add new entries before this */
165 PROC_TID_FD_DIR = 0x8000, /* 0x8000-0xffff */
126}; 166};
127 167
128struct pid_entry { 168struct pid_entry {
@@ -144,6 +184,9 @@ static struct pid_entry tgid_base_stuff[] = {
144 E(PROC_TGID_STAT, "stat", S_IFREG|S_IRUGO), 184 E(PROC_TGID_STAT, "stat", S_IFREG|S_IRUGO),
145 E(PROC_TGID_STATM, "statm", S_IFREG|S_IRUGO), 185 E(PROC_TGID_STATM, "statm", S_IFREG|S_IRUGO),
146 E(PROC_TGID_MAPS, "maps", S_IFREG|S_IRUGO), 186 E(PROC_TGID_MAPS, "maps", S_IFREG|S_IRUGO),
187#ifdef CONFIG_NUMA
188 E(PROC_TGID_NUMA_MAPS, "numa_maps", S_IFREG|S_IRUGO),
189#endif
147 E(PROC_TGID_MEM, "mem", S_IFREG|S_IRUSR|S_IWUSR), 190 E(PROC_TGID_MEM, "mem", S_IFREG|S_IRUSR|S_IWUSR),
148#ifdef CONFIG_SECCOMP 191#ifdef CONFIG_SECCOMP
149 E(PROC_TGID_SECCOMP, "seccomp", S_IFREG|S_IRUSR|S_IWUSR), 192 E(PROC_TGID_SECCOMP, "seccomp", S_IFREG|S_IRUSR|S_IWUSR),
@@ -152,6 +195,7 @@ static struct pid_entry tgid_base_stuff[] = {
152 E(PROC_TGID_ROOT, "root", S_IFLNK|S_IRWXUGO), 195 E(PROC_TGID_ROOT, "root", S_IFLNK|S_IRWXUGO),
153 E(PROC_TGID_EXE, "exe", S_IFLNK|S_IRWXUGO), 196 E(PROC_TGID_EXE, "exe", S_IFLNK|S_IRWXUGO),
154 E(PROC_TGID_MOUNTS, "mounts", S_IFREG|S_IRUGO), 197 E(PROC_TGID_MOUNTS, "mounts", S_IFREG|S_IRUGO),
198 E(PROC_TGID_SMAPS, "smaps", S_IFREG|S_IRUGO),
155#ifdef CONFIG_SECURITY 199#ifdef CONFIG_SECURITY
156 E(PROC_TGID_ATTR, "attr", S_IFDIR|S_IRUGO|S_IXUGO), 200 E(PROC_TGID_ATTR, "attr", S_IFDIR|S_IRUGO|S_IXUGO),
157#endif 201#endif
@@ -180,6 +224,9 @@ static struct pid_entry tid_base_stuff[] = {
180 E(PROC_TID_STAT, "stat", S_IFREG|S_IRUGO), 224 E(PROC_TID_STAT, "stat", S_IFREG|S_IRUGO),
181 E(PROC_TID_STATM, "statm", S_IFREG|S_IRUGO), 225 E(PROC_TID_STATM, "statm", S_IFREG|S_IRUGO),
182 E(PROC_TID_MAPS, "maps", S_IFREG|S_IRUGO), 226 E(PROC_TID_MAPS, "maps", S_IFREG|S_IRUGO),
227#ifdef CONFIG_NUMA
228 E(PROC_TID_NUMA_MAPS, "numa_maps", S_IFREG|S_IRUGO),
229#endif
183 E(PROC_TID_MEM, "mem", S_IFREG|S_IRUSR|S_IWUSR), 230 E(PROC_TID_MEM, "mem", S_IFREG|S_IRUSR|S_IWUSR),
184#ifdef CONFIG_SECCOMP 231#ifdef CONFIG_SECCOMP
185 E(PROC_TID_SECCOMP, "seccomp", S_IFREG|S_IRUSR|S_IWUSR), 232 E(PROC_TID_SECCOMP, "seccomp", S_IFREG|S_IRUSR|S_IWUSR),
@@ -188,6 +235,7 @@ static struct pid_entry tid_base_stuff[] = {
188 E(PROC_TID_ROOT, "root", S_IFLNK|S_IRWXUGO), 235 E(PROC_TID_ROOT, "root", S_IFLNK|S_IRWXUGO),
189 E(PROC_TID_EXE, "exe", S_IFLNK|S_IRWXUGO), 236 E(PROC_TID_EXE, "exe", S_IFLNK|S_IRWXUGO),
190 E(PROC_TID_MOUNTS, "mounts", S_IFREG|S_IRUGO), 237 E(PROC_TID_MOUNTS, "mounts", S_IFREG|S_IRUGO),
238 E(PROC_TID_SMAPS, "smaps", S_IFREG|S_IRUGO),
191#ifdef CONFIG_SECURITY 239#ifdef CONFIG_SECURITY
192 E(PROC_TID_ATTR, "attr", S_IFDIR|S_IRUGO|S_IXUGO), 240 E(PROC_TID_ATTR, "attr", S_IFDIR|S_IRUGO|S_IXUGO),
193#endif 241#endif
@@ -236,30 +284,36 @@ static int proc_fd_link(struct inode *inode, struct dentry **dentry, struct vfsm
236 284
237 files = get_files_struct(task); 285 files = get_files_struct(task);
238 if (files) { 286 if (files) {
239 spin_lock(&files->file_lock); 287 rcu_read_lock();
240 file = fcheck_files(files, fd); 288 file = fcheck_files(files, fd);
241 if (file) { 289 if (file) {
242 *mnt = mntget(file->f_vfsmnt); 290 *mnt = mntget(file->f_vfsmnt);
243 *dentry = dget(file->f_dentry); 291 *dentry = dget(file->f_dentry);
244 spin_unlock(&files->file_lock); 292 rcu_read_unlock();
245 put_files_struct(files); 293 put_files_struct(files);
246 return 0; 294 return 0;
247 } 295 }
248 spin_unlock(&files->file_lock); 296 rcu_read_unlock();
249 put_files_struct(files); 297 put_files_struct(files);
250 } 298 }
251 return -ENOENT; 299 return -ENOENT;
252} 300}
253 301
254static int proc_cwd_link(struct inode *inode, struct dentry **dentry, struct vfsmount **mnt) 302static struct fs_struct *get_fs_struct(struct task_struct *task)
255{ 303{
256 struct fs_struct *fs; 304 struct fs_struct *fs;
257 int result = -ENOENT; 305 task_lock(task);
258 task_lock(proc_task(inode)); 306 fs = task->fs;
259 fs = proc_task(inode)->fs;
260 if(fs) 307 if(fs)
261 atomic_inc(&fs->count); 308 atomic_inc(&fs->count);
262 task_unlock(proc_task(inode)); 309 task_unlock(task);
310 return fs;
311}
312
313static int proc_cwd_link(struct inode *inode, struct dentry **dentry, struct vfsmount **mnt)
314{
315 struct fs_struct *fs = get_fs_struct(proc_task(inode));
316 int result = -ENOENT;
263 if (fs) { 317 if (fs) {
264 read_lock(&fs->lock); 318 read_lock(&fs->lock);
265 *mnt = mntget(fs->pwdmnt); 319 *mnt = mntget(fs->pwdmnt);
@@ -273,13 +327,8 @@ static int proc_cwd_link(struct inode *inode, struct dentry **dentry, struct vfs
273 327
274static int proc_root_link(struct inode *inode, struct dentry **dentry, struct vfsmount **mnt) 328static int proc_root_link(struct inode *inode, struct dentry **dentry, struct vfsmount **mnt)
275{ 329{
276 struct fs_struct *fs; 330 struct fs_struct *fs = get_fs_struct(proc_task(inode));
277 int result = -ENOENT; 331 int result = -ENOENT;
278 task_lock(proc_task(inode));
279 fs = proc_task(inode)->fs;
280 if(fs)
281 atomic_inc(&fs->count);
282 task_unlock(proc_task(inode));
283 if (fs) { 332 if (fs) {
284 read_lock(&fs->lock); 333 read_lock(&fs->lock);
285 *mnt = mntget(fs->rootmnt); 334 *mnt = mntget(fs->rootmnt);
@@ -298,33 +347,6 @@ static int proc_root_link(struct inode *inode, struct dentry **dentry, struct vf
298 (task->state == TASK_STOPPED || task->state == TASK_TRACED) && \ 347 (task->state == TASK_STOPPED || task->state == TASK_TRACED) && \
299 security_ptrace(current,task) == 0)) 348 security_ptrace(current,task) == 0))
300 349
301static int may_ptrace_attach(struct task_struct *task)
302{
303 int retval = 0;
304
305 task_lock(task);
306
307 if (!task->mm)
308 goto out;
309 if (((current->uid != task->euid) ||
310 (current->uid != task->suid) ||
311 (current->uid != task->uid) ||
312 (current->gid != task->egid) ||
313 (current->gid != task->sgid) ||
314 (current->gid != task->gid)) && !capable(CAP_SYS_PTRACE))
315 goto out;
316 rmb();
317 if (task->mm->dumpable != 1 && !capable(CAP_SYS_PTRACE))
318 goto out;
319 if (security_ptrace(current, task))
320 goto out;
321
322 retval = 1;
323out:
324 task_unlock(task);
325 return retval;
326}
327
328static int proc_pid_environ(struct task_struct *task, char * buffer) 350static int proc_pid_environ(struct task_struct *task, char * buffer)
329{ 351{
330 int res = 0; 352 int res = 0;
@@ -334,7 +356,7 @@ static int proc_pid_environ(struct task_struct *task, char * buffer)
334 if (len > PAGE_SIZE) 356 if (len > PAGE_SIZE)
335 len = PAGE_SIZE; 357 len = PAGE_SIZE;
336 res = access_process_vm(task, mm->env_start, buffer, len, 0); 358 res = access_process_vm(task, mm->env_start, buffer, len, 0);
337 if (!may_ptrace_attach(task)) 359 if (!ptrace_may_attach(task))
338 res = -ESRCH; 360 res = -ESRCH;
339 mmput(mm); 361 mmput(mm);
340 } 362 }
@@ -515,6 +537,46 @@ static struct file_operations proc_maps_operations = {
515 .release = seq_release, 537 .release = seq_release,
516}; 538};
517 539
540#ifdef CONFIG_NUMA
541extern struct seq_operations proc_pid_numa_maps_op;
542static int numa_maps_open(struct inode *inode, struct file *file)
543{
544 struct task_struct *task = proc_task(inode);
545 int ret = seq_open(file, &proc_pid_numa_maps_op);
546 if (!ret) {
547 struct seq_file *m = file->private_data;
548 m->private = task;
549 }
550 return ret;
551}
552
553static struct file_operations proc_numa_maps_operations = {
554 .open = numa_maps_open,
555 .read = seq_read,
556 .llseek = seq_lseek,
557 .release = seq_release,
558};
559#endif
560
561extern struct seq_operations proc_pid_smaps_op;
562static int smaps_open(struct inode *inode, struct file *file)
563{
564 struct task_struct *task = proc_task(inode);
565 int ret = seq_open(file, &proc_pid_smaps_op);
566 if (!ret) {
567 struct seq_file *m = file->private_data;
568 m->private = task;
569 }
570 return ret;
571}
572
573static struct file_operations proc_smaps_operations = {
574 .open = smaps_open,
575 .read = seq_read,
576 .llseek = seq_lseek,
577 .release = seq_release,
578};
579
518extern struct seq_operations mounts_op; 580extern struct seq_operations mounts_op;
519static int mounts_open(struct inode *inode, struct file *file) 581static int mounts_open(struct inode *inode, struct file *file)
520{ 582{
@@ -597,7 +659,7 @@ static ssize_t mem_read(struct file * file, char __user * buf,
597 int ret = -ESRCH; 659 int ret = -ESRCH;
598 struct mm_struct *mm; 660 struct mm_struct *mm;
599 661
600 if (!MAY_PTRACE(task) || !may_ptrace_attach(task)) 662 if (!MAY_PTRACE(task) || !ptrace_may_attach(task))
601 goto out; 663 goto out;
602 664
603 ret = -ENOMEM; 665 ret = -ENOMEM;
@@ -623,7 +685,7 @@ static ssize_t mem_read(struct file * file, char __user * buf,
623 685
624 this_len = (count > PAGE_SIZE) ? PAGE_SIZE : count; 686 this_len = (count > PAGE_SIZE) ? PAGE_SIZE : count;
625 retval = access_process_vm(task, src, page, this_len, 0); 687 retval = access_process_vm(task, src, page, this_len, 0);
626 if (!retval || !MAY_PTRACE(task) || !may_ptrace_attach(task)) { 688 if (!retval || !MAY_PTRACE(task) || !ptrace_may_attach(task)) {
627 if (!ret) 689 if (!ret)
628 ret = -EIO; 690 ret = -EIO;
629 break; 691 break;
@@ -661,7 +723,7 @@ static ssize_t mem_write(struct file * file, const char * buf,
661 struct task_struct *task = proc_task(file->f_dentry->d_inode); 723 struct task_struct *task = proc_task(file->f_dentry->d_inode);
662 unsigned long dst = *ppos; 724 unsigned long dst = *ppos;
663 725
664 if (!MAY_PTRACE(task) || !may_ptrace_attach(task)) 726 if (!MAY_PTRACE(task) || !ptrace_may_attach(task))
665 return -ESRCH; 727 return -ESRCH;
666 728
667 page = (char *)__get_free_page(GFP_USER); 729 page = (char *)__get_free_page(GFP_USER);
@@ -890,7 +952,7 @@ static struct file_operations proc_seccomp_operations = {
890}; 952};
891#endif /* CONFIG_SECCOMP */ 953#endif /* CONFIG_SECCOMP */
892 954
893static int proc_pid_follow_link(struct dentry *dentry, struct nameidata *nd) 955static void *proc_pid_follow_link(struct dentry *dentry, struct nameidata *nd)
894{ 956{
895 struct inode *inode = dentry->d_inode; 957 struct inode *inode = dentry->d_inode;
896 int error = -EACCES; 958 int error = -EACCES;
@@ -907,7 +969,7 @@ static int proc_pid_follow_link(struct dentry *dentry, struct nameidata *nd)
907 error = PROC_I(inode)->op.proc_get_link(inode, &nd->dentry, &nd->mnt); 969 error = PROC_I(inode)->op.proc_get_link(inode, &nd->dentry, &nd->mnt);
908 nd->last_type = LAST_BIND; 970 nd->last_type = LAST_BIND;
909out: 971out:
910 return error; 972 return ERR_PTR(error);
911} 973}
912 974
913static int do_proc_readlink(struct dentry *dentry, struct vfsmount *mnt, 975static int do_proc_readlink(struct dentry *dentry, struct vfsmount *mnt,
@@ -978,6 +1040,7 @@ static int proc_readfd(struct file * filp, void * dirent, filldir_t filldir)
978 int retval; 1040 int retval;
979 char buf[NUMBUF]; 1041 char buf[NUMBUF];
980 struct files_struct * files; 1042 struct files_struct * files;
1043 struct fdtable *fdt;
981 1044
982 retval = -ENOENT; 1045 retval = -ENOENT;
983 if (!pid_alive(p)) 1046 if (!pid_alive(p))
@@ -1000,15 +1063,16 @@ static int proc_readfd(struct file * filp, void * dirent, filldir_t filldir)
1000 files = get_files_struct(p); 1063 files = get_files_struct(p);
1001 if (!files) 1064 if (!files)
1002 goto out; 1065 goto out;
1003 spin_lock(&files->file_lock); 1066 rcu_read_lock();
1067 fdt = files_fdtable(files);
1004 for (fd = filp->f_pos-2; 1068 for (fd = filp->f_pos-2;
1005 fd < files->max_fds; 1069 fd < fdt->max_fds;
1006 fd++, filp->f_pos++) { 1070 fd++, filp->f_pos++) {
1007 unsigned int i,j; 1071 unsigned int i,j;
1008 1072
1009 if (!fcheck_files(files, fd)) 1073 if (!fcheck_files(files, fd))
1010 continue; 1074 continue;
1011 spin_unlock(&files->file_lock); 1075 rcu_read_unlock();
1012 1076
1013 j = NUMBUF; 1077 j = NUMBUF;
1014 i = fd; 1078 i = fd;
@@ -1020,12 +1084,12 @@ static int proc_readfd(struct file * filp, void * dirent, filldir_t filldir)
1020 1084
1021 ino = fake_ino(tid, PROC_TID_FD_DIR + fd); 1085 ino = fake_ino(tid, PROC_TID_FD_DIR + fd);
1022 if (filldir(dirent, buf+j, NUMBUF-j, fd+2, ino, DT_LNK) < 0) { 1086 if (filldir(dirent, buf+j, NUMBUF-j, fd+2, ino, DT_LNK) < 0) {
1023 spin_lock(&files->file_lock); 1087 rcu_read_lock();
1024 break; 1088 break;
1025 } 1089 }
1026 spin_lock(&files->file_lock); 1090 rcu_read_lock();
1027 } 1091 }
1028 spin_unlock(&files->file_lock); 1092 rcu_read_unlock();
1029 put_files_struct(files); 1093 put_files_struct(files);
1030 } 1094 }
1031out: 1095out:
@@ -1200,9 +1264,9 @@ static int tid_fd_revalidate(struct dentry *dentry, struct nameidata *nd)
1200 1264
1201 files = get_files_struct(task); 1265 files = get_files_struct(task);
1202 if (files) { 1266 if (files) {
1203 spin_lock(&files->file_lock); 1267 rcu_read_lock();
1204 if (fcheck_files(files, fd)) { 1268 if (fcheck_files(files, fd)) {
1205 spin_unlock(&files->file_lock); 1269 rcu_read_unlock();
1206 put_files_struct(files); 1270 put_files_struct(files);
1207 if (task_dumpable(task)) { 1271 if (task_dumpable(task)) {
1208 inode->i_uid = task->euid; 1272 inode->i_uid = task->euid;
@@ -1214,7 +1278,7 @@ static int tid_fd_revalidate(struct dentry *dentry, struct nameidata *nd)
1214 security_task_to_inode(task, inode); 1278 security_task_to_inode(task, inode);
1215 return 1; 1279 return 1;
1216 } 1280 }
1217 spin_unlock(&files->file_lock); 1281 rcu_read_unlock();
1218 put_files_struct(files); 1282 put_files_struct(files);
1219 } 1283 }
1220 d_drop(dentry); 1284 d_drop(dentry);
@@ -1306,7 +1370,7 @@ static struct dentry *proc_lookupfd(struct inode * dir, struct dentry * dentry,
1306 if (!files) 1370 if (!files)
1307 goto out_unlock; 1371 goto out_unlock;
1308 inode->i_mode = S_IFLNK; 1372 inode->i_mode = S_IFLNK;
1309 spin_lock(&files->file_lock); 1373 rcu_read_lock();
1310 file = fcheck_files(files, fd); 1374 file = fcheck_files(files, fd);
1311 if (!file) 1375 if (!file)
1312 goto out_unlock2; 1376 goto out_unlock2;
@@ -1314,7 +1378,7 @@ static struct dentry *proc_lookupfd(struct inode * dir, struct dentry * dentry,
1314 inode->i_mode |= S_IRUSR | S_IXUSR; 1378 inode->i_mode |= S_IRUSR | S_IXUSR;
1315 if (file->f_mode & 2) 1379 if (file->f_mode & 2)
1316 inode->i_mode |= S_IWUSR | S_IXUSR; 1380 inode->i_mode |= S_IWUSR | S_IXUSR;
1317 spin_unlock(&files->file_lock); 1381 rcu_read_unlock();
1318 put_files_struct(files); 1382 put_files_struct(files);
1319 inode->i_op = &proc_pid_link_inode_operations; 1383 inode->i_op = &proc_pid_link_inode_operations;
1320 inode->i_size = 64; 1384 inode->i_size = 64;
@@ -1324,7 +1388,7 @@ static struct dentry *proc_lookupfd(struct inode * dir, struct dentry * dentry,
1324 return NULL; 1388 return NULL;
1325 1389
1326out_unlock2: 1390out_unlock2:
1327 spin_unlock(&files->file_lock); 1391 rcu_read_unlock();
1328 put_files_struct(files); 1392 put_files_struct(files);
1329out_unlock: 1393out_unlock:
1330 iput(inode); 1394 iput(inode);
@@ -1524,6 +1588,12 @@ static struct dentry *proc_pident_lookup(struct inode *dir,
1524 case PROC_TGID_MAPS: 1588 case PROC_TGID_MAPS:
1525 inode->i_fop = &proc_maps_operations; 1589 inode->i_fop = &proc_maps_operations;
1526 break; 1590 break;
1591#ifdef CONFIG_NUMA
1592 case PROC_TID_NUMA_MAPS:
1593 case PROC_TGID_NUMA_MAPS:
1594 inode->i_fop = &proc_numa_maps_operations;
1595 break;
1596#endif
1527 case PROC_TID_MEM: 1597 case PROC_TID_MEM:
1528 case PROC_TGID_MEM: 1598 case PROC_TGID_MEM:
1529 inode->i_op = &proc_mem_inode_operations; 1599 inode->i_op = &proc_mem_inode_operations;
@@ -1539,6 +1609,10 @@ static struct dentry *proc_pident_lookup(struct inode *dir,
1539 case PROC_TGID_MOUNTS: 1609 case PROC_TGID_MOUNTS:
1540 inode->i_fop = &proc_mounts_operations; 1610 inode->i_fop = &proc_mounts_operations;
1541 break; 1611 break;
1612 case PROC_TID_SMAPS:
1613 case PROC_TGID_SMAPS:
1614 inode->i_fop = &proc_smaps_operations;
1615 break;
1542#ifdef CONFIG_SECURITY 1616#ifdef CONFIG_SECURITY
1543 case PROC_TID_ATTR: 1617 case PROC_TID_ATTR:
1544 inode->i_nlink = 2; 1618 inode->i_nlink = 2;
@@ -1692,11 +1766,11 @@ static int proc_self_readlink(struct dentry *dentry, char __user *buffer,
1692 return vfs_readlink(dentry,buffer,buflen,tmp); 1766 return vfs_readlink(dentry,buffer,buflen,tmp);
1693} 1767}
1694 1768
1695static int proc_self_follow_link(struct dentry *dentry, struct nameidata *nd) 1769static void *proc_self_follow_link(struct dentry *dentry, struct nameidata *nd)
1696{ 1770{
1697 char tmp[30]; 1771 char tmp[30];
1698 sprintf(tmp, "%d", current->tgid); 1772 sprintf(tmp, "%d", current->tgid);
1699 return vfs_follow_link(nd,tmp); 1773 return ERR_PTR(vfs_follow_link(nd,tmp));
1700} 1774}
1701 1775
1702static struct inode_operations proc_self_inode_operations = { 1776static struct inode_operations proc_self_inode_operations = {