diff options
author | Eric W. Biederman <ebiederm@xmission.com> | 2006-10-02 05:18:49 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@g5.osdl.org> | 2006-10-02 10:57:24 -0400 |
commit | 61a28784028e6d55755e4d0f39bee8d9bf2ee8d9 (patch) | |
tree | ee114d76871f98da80ab14e9a86416da27a1787e /fs | |
parent | 444ceed8d186631fdded5e3f24dc20b93d0d3fda (diff) |
[PATCH] proc: Remove the hard coded inode numbers
The hard coded inode numbers in proc currently limit its maintainability,
its flexibility, and what can be done with the rest of system. /proc limits
pid-max to 32768 on 32 bit systems it limits fd-max to 32768 on all systems,
and placing the pid in the inode number really gets in the way of implementing
subdirectories of per process information.
Ever since people started adding to the middle of the file type enumeration we
haven't been maintaing the historical inode numbers, all we have really
succeeded in doing is keeping the pid in the proc inode number. The pid is
already available in the directory name so no information is lost removing it
from the inode number.
So if something in user space cares if we remove the inode number from the
/proc inode it is almost certainly broken.
Signed-off-by: Eric W. Biederman <ebiederm@xmission.com>
Signed-off-by: Andrew Morton <akpm@osdl.org>
Signed-off-by: Linus Torvalds <torvalds@osdl.org>
Diffstat (limited to 'fs')
-rw-r--r-- | fs/proc/base.c | 384 |
1 files changed, 174 insertions, 210 deletions
diff --git a/fs/proc/base.c b/fs/proc/base.c index e8084eb037e3..7bf28c3af70c 100644 --- a/fs/proc/base.c +++ b/fs/proc/base.c | |||
@@ -84,114 +84,11 @@ | |||
84 | * in /proc for a task before it execs a suid executable. | 84 | * in /proc for a task before it execs a suid executable. |
85 | */ | 85 | */ |
86 | 86 | ||
87 | /* | ||
88 | * For hysterical raisins we keep the same inumbers as in the old procfs. | ||
89 | * Feel free to change the macro below - just keep the range distinct from | ||
90 | * inumbers of the rest of procfs (currently those are in 0x0000--0xffff). | ||
91 | * As soon as we'll get a separate superblock we will be able to forget | ||
92 | * about magical ranges too. | ||
93 | */ | ||
94 | |||
95 | #define fake_ino(pid,ino) (((pid)<<16)|(ino)) | ||
96 | |||
97 | enum pid_directory_inos { | ||
98 | PROC_TGID_INO = 2, | ||
99 | PROC_TGID_TASK, | ||
100 | PROC_TGID_STATUS, | ||
101 | PROC_TGID_MEM, | ||
102 | #ifdef CONFIG_SECCOMP | ||
103 | PROC_TGID_SECCOMP, | ||
104 | #endif | ||
105 | PROC_TGID_CWD, | ||
106 | PROC_TGID_ROOT, | ||
107 | PROC_TGID_EXE, | ||
108 | PROC_TGID_FD, | ||
109 | PROC_TGID_ENVIRON, | ||
110 | PROC_TGID_AUXV, | ||
111 | PROC_TGID_CMDLINE, | ||
112 | PROC_TGID_STAT, | ||
113 | PROC_TGID_STATM, | ||
114 | PROC_TGID_MAPS, | ||
115 | PROC_TGID_NUMA_MAPS, | ||
116 | PROC_TGID_MOUNTS, | ||
117 | PROC_TGID_MOUNTSTATS, | ||
118 | PROC_TGID_WCHAN, | ||
119 | #ifdef CONFIG_MMU | ||
120 | PROC_TGID_SMAPS, | ||
121 | #endif | ||
122 | #ifdef CONFIG_SCHEDSTATS | ||
123 | PROC_TGID_SCHEDSTAT, | ||
124 | #endif | ||
125 | #ifdef CONFIG_CPUSETS | ||
126 | PROC_TGID_CPUSET, | ||
127 | #endif | ||
128 | #ifdef CONFIG_SECURITY | ||
129 | PROC_TGID_ATTR, | ||
130 | PROC_TGID_ATTR_CURRENT, | ||
131 | PROC_TGID_ATTR_PREV, | ||
132 | PROC_TGID_ATTR_EXEC, | ||
133 | PROC_TGID_ATTR_FSCREATE, | ||
134 | PROC_TGID_ATTR_KEYCREATE, | ||
135 | PROC_TGID_ATTR_SOCKCREATE, | ||
136 | #endif | ||
137 | #ifdef CONFIG_AUDITSYSCALL | ||
138 | PROC_TGID_LOGINUID, | ||
139 | #endif | ||
140 | PROC_TGID_OOM_SCORE, | ||
141 | PROC_TGID_OOM_ADJUST, | ||
142 | PROC_TID_INO, | ||
143 | PROC_TID_STATUS, | ||
144 | PROC_TID_MEM, | ||
145 | #ifdef CONFIG_SECCOMP | ||
146 | PROC_TID_SECCOMP, | ||
147 | #endif | ||
148 | PROC_TID_CWD, | ||
149 | PROC_TID_ROOT, | ||
150 | PROC_TID_EXE, | ||
151 | PROC_TID_FD, | ||
152 | PROC_TID_ENVIRON, | ||
153 | PROC_TID_AUXV, | ||
154 | PROC_TID_CMDLINE, | ||
155 | PROC_TID_STAT, | ||
156 | PROC_TID_STATM, | ||
157 | PROC_TID_MAPS, | ||
158 | PROC_TID_NUMA_MAPS, | ||
159 | PROC_TID_MOUNTS, | ||
160 | PROC_TID_MOUNTSTATS, | ||
161 | PROC_TID_WCHAN, | ||
162 | #ifdef CONFIG_MMU | ||
163 | PROC_TID_SMAPS, | ||
164 | #endif | ||
165 | #ifdef CONFIG_SCHEDSTATS | ||
166 | PROC_TID_SCHEDSTAT, | ||
167 | #endif | ||
168 | #ifdef CONFIG_CPUSETS | ||
169 | PROC_TID_CPUSET, | ||
170 | #endif | ||
171 | #ifdef CONFIG_SECURITY | ||
172 | PROC_TID_ATTR, | ||
173 | PROC_TID_ATTR_CURRENT, | ||
174 | PROC_TID_ATTR_PREV, | ||
175 | PROC_TID_ATTR_EXEC, | ||
176 | PROC_TID_ATTR_FSCREATE, | ||
177 | PROC_TID_ATTR_KEYCREATE, | ||
178 | PROC_TID_ATTR_SOCKCREATE, | ||
179 | #endif | ||
180 | #ifdef CONFIG_AUDITSYSCALL | ||
181 | PROC_TID_LOGINUID, | ||
182 | #endif | ||
183 | PROC_TID_OOM_SCORE, | ||
184 | PROC_TID_OOM_ADJUST, | ||
185 | |||
186 | /* Add new entries before this */ | ||
187 | PROC_TID_FD_DIR = 0x8000, /* 0x8000-0xffff */ | ||
188 | }; | ||
189 | 87 | ||
190 | /* Worst case buffer size needed for holding an integer. */ | 88 | /* Worst case buffer size needed for holding an integer. */ |
191 | #define PROC_NUMBUF 10 | 89 | #define PROC_NUMBUF 10 |
192 | 90 | ||
193 | struct pid_entry { | 91 | struct pid_entry { |
194 | int type; | ||
195 | int len; | 92 | int len; |
196 | char *name; | 93 | char *name; |
197 | mode_t mode; | 94 | mode_t mode; |
@@ -200,8 +97,7 @@ struct pid_entry { | |||
200 | union proc_op op; | 97 | union proc_op op; |
201 | }; | 98 | }; |
202 | 99 | ||
203 | #define NOD(TYPE, NAME, MODE, IOP, FOP, OP) { \ | 100 | #define NOD(NAME, MODE, IOP, FOP, OP) { \ |
204 | .type = (TYPE), \ | ||
205 | .len = sizeof(NAME) - 1, \ | 101 | .len = sizeof(NAME) - 1, \ |
206 | .name = (NAME), \ | 102 | .name = (NAME), \ |
207 | .mode = MODE, \ | 103 | .mode = MODE, \ |
@@ -210,19 +106,19 @@ struct pid_entry { | |||
210 | .op = OP, \ | 106 | .op = OP, \ |
211 | } | 107 | } |
212 | 108 | ||
213 | #define DIR(TYPE, NAME, MODE, OTYPE) \ | 109 | #define DIR(NAME, MODE, OTYPE) \ |
214 | NOD(TYPE, NAME, (S_IFDIR|(MODE)), \ | 110 | NOD(NAME, (S_IFDIR|(MODE)), \ |
215 | &proc_##OTYPE##_inode_operations, &proc_##OTYPE##_operations, \ | 111 | &proc_##OTYPE##_inode_operations, &proc_##OTYPE##_operations, \ |
216 | {} ) | 112 | {} ) |
217 | #define LNK(TYPE, NAME, OTYPE) \ | 113 | #define LNK(NAME, OTYPE) \ |
218 | NOD(TYPE, NAME, (S_IFLNK|S_IRWXUGO), \ | 114 | NOD(NAME, (S_IFLNK|S_IRWXUGO), \ |
219 | &proc_pid_link_inode_operations, NULL, \ | 115 | &proc_pid_link_inode_operations, NULL, \ |
220 | { .proc_get_link = &proc_##OTYPE##_link } ) | 116 | { .proc_get_link = &proc_##OTYPE##_link } ) |
221 | #define REG(TYPE, NAME, MODE, OTYPE) \ | 117 | #define REG(NAME, MODE, OTYPE) \ |
222 | NOD(TYPE, NAME, (S_IFREG|(MODE)), NULL, \ | 118 | NOD(NAME, (S_IFREG|(MODE)), NULL, \ |
223 | &proc_##OTYPE##_operations, {}) | 119 | &proc_##OTYPE##_operations, {}) |
224 | #define INF(TYPE, NAME, MODE, OTYPE) \ | 120 | #define INF(NAME, MODE, OTYPE) \ |
225 | NOD(TYPE, NAME, (S_IFREG|(MODE)), \ | 121 | NOD(NAME, (S_IFREG|(MODE)), \ |
226 | NULL, &proc_info_file_operations, \ | 122 | NULL, &proc_info_file_operations, \ |
227 | { .proc_read = &proc_##OTYPE } ) | 123 | { .proc_read = &proc_##OTYPE } ) |
228 | 124 | ||
@@ -1043,7 +939,7 @@ static int task_dumpable(struct task_struct *task) | |||
1043 | } | 939 | } |
1044 | 940 | ||
1045 | 941 | ||
1046 | static struct inode *proc_pid_make_inode(struct super_block * sb, struct task_struct *task, int ino) | 942 | static struct inode *proc_pid_make_inode(struct super_block * sb, struct task_struct *task) |
1047 | { | 943 | { |
1048 | struct inode * inode; | 944 | struct inode * inode; |
1049 | struct proc_inode *ei; | 945 | struct proc_inode *ei; |
@@ -1057,7 +953,6 @@ static struct inode *proc_pid_make_inode(struct super_block * sb, struct task_st | |||
1057 | /* Common stuff */ | 953 | /* Common stuff */ |
1058 | ei = PROC_I(inode); | 954 | ei = PROC_I(inode); |
1059 | inode->i_mtime = inode->i_atime = inode->i_ctime = CURRENT_TIME; | 955 | inode->i_mtime = inode->i_atime = inode->i_ctime = CURRENT_TIME; |
1060 | inode->i_ino = fake_ino(task->pid, ino); | ||
1061 | inode->i_op = &proc_def_inode_operations; | 956 | inode->i_op = &proc_def_inode_operations; |
1062 | 957 | ||
1063 | /* | 958 | /* |
@@ -1160,6 +1055,50 @@ static struct dentry_operations pid_dentry_operations = | |||
1160 | 1055 | ||
1161 | /* Lookups */ | 1056 | /* Lookups */ |
1162 | 1057 | ||
1058 | typedef struct dentry *instantiate_t(struct inode *, struct dentry *, struct task_struct *, void *); | ||
1059 | |||
1060 | static int proc_fill_cache(struct file *filp, void *dirent, filldir_t filldir, | ||
1061 | char *name, int len, | ||
1062 | instantiate_t instantiate, struct task_struct *task, void *ptr) | ||
1063 | { | ||
1064 | struct dentry *child, *dir = filp->f_dentry; | ||
1065 | struct inode *inode; | ||
1066 | struct qstr qname; | ||
1067 | ino_t ino = 0; | ||
1068 | unsigned type = DT_UNKNOWN; | ||
1069 | |||
1070 | qname.name = name; | ||
1071 | qname.len = len; | ||
1072 | qname.hash = full_name_hash(name, len); | ||
1073 | |||
1074 | child = d_lookup(dir, &qname); | ||
1075 | if (!child) { | ||
1076 | struct dentry *new; | ||
1077 | new = d_alloc(dir, &qname); | ||
1078 | if (new) { | ||
1079 | child = instantiate(dir->d_inode, new, task, ptr); | ||
1080 | if (child) | ||
1081 | dput(new); | ||
1082 | else | ||
1083 | child = new; | ||
1084 | } | ||
1085 | } | ||
1086 | if (!child || IS_ERR(child) || !child->d_inode) | ||
1087 | goto end_instantiate; | ||
1088 | inode = child->d_inode; | ||
1089 | if (inode) { | ||
1090 | ino = inode->i_ino; | ||
1091 | type = inode->i_mode >> 12; | ||
1092 | } | ||
1093 | dput(child); | ||
1094 | end_instantiate: | ||
1095 | if (!ino) | ||
1096 | ino = find_inode_number(dir, &qname); | ||
1097 | if (!ino) | ||
1098 | ino = 1; | ||
1099 | return filldir(dirent, name, len, filp->f_pos, ino, type); | ||
1100 | } | ||
1101 | |||
1163 | static unsigned name_to_int(struct dentry *dentry) | 1102 | static unsigned name_to_int(struct dentry *dentry) |
1164 | { | 1103 | { |
1165 | const char *name = dentry->d_name.name; | 1104 | const char *name = dentry->d_name.name; |
@@ -1264,7 +1203,7 @@ static struct dentry *proc_fd_instantiate(struct inode *dir, | |||
1264 | struct proc_inode *ei; | 1203 | struct proc_inode *ei; |
1265 | struct dentry *error = ERR_PTR(-ENOENT); | 1204 | struct dentry *error = ERR_PTR(-ENOENT); |
1266 | 1205 | ||
1267 | inode = proc_pid_make_inode(dir->i_sb, task, PROC_TID_FD_DIR+fd); | 1206 | inode = proc_pid_make_inode(dir->i_sb, task); |
1268 | if (!inode) | 1207 | if (!inode) |
1269 | goto out; | 1208 | goto out; |
1270 | ei = PROC_I(inode); | 1209 | ei = PROC_I(inode); |
@@ -1327,6 +1266,15 @@ out_no_task: | |||
1327 | return result; | 1266 | return result; |
1328 | } | 1267 | } |
1329 | 1268 | ||
1269 | static int proc_fd_fill_cache(struct file *filp, void *dirent, filldir_t filldir, | ||
1270 | struct task_struct *task, int fd) | ||
1271 | { | ||
1272 | char name[PROC_NUMBUF]; | ||
1273 | int len = snprintf(name, sizeof(name), "%d", fd); | ||
1274 | return proc_fill_cache(filp, dirent, filldir, name, len, | ||
1275 | proc_fd_instantiate, task, &fd); | ||
1276 | } | ||
1277 | |||
1330 | static int proc_readfd(struct file * filp, void * dirent, filldir_t filldir) | 1278 | static int proc_readfd(struct file * filp, void * dirent, filldir_t filldir) |
1331 | { | 1279 | { |
1332 | struct dentry *dentry = filp->f_dentry; | 1280 | struct dentry *dentry = filp->f_dentry; |
@@ -1334,7 +1282,6 @@ static int proc_readfd(struct file * filp, void * dirent, filldir_t filldir) | |||
1334 | struct task_struct *p = get_proc_task(inode); | 1282 | struct task_struct *p = get_proc_task(inode); |
1335 | unsigned int fd, tid, ino; | 1283 | unsigned int fd, tid, ino; |
1336 | int retval; | 1284 | int retval; |
1337 | char buf[PROC_NUMBUF]; | ||
1338 | struct files_struct * files; | 1285 | struct files_struct * files; |
1339 | struct fdtable *fdt; | 1286 | struct fdtable *fdt; |
1340 | 1287 | ||
@@ -1364,22 +1311,12 @@ static int proc_readfd(struct file * filp, void * dirent, filldir_t filldir) | |||
1364 | for (fd = filp->f_pos-2; | 1311 | for (fd = filp->f_pos-2; |
1365 | fd < fdt->max_fds; | 1312 | fd < fdt->max_fds; |
1366 | fd++, filp->f_pos++) { | 1313 | fd++, filp->f_pos++) { |
1367 | unsigned int i,j; | ||
1368 | 1314 | ||
1369 | if (!fcheck_files(files, fd)) | 1315 | if (!fcheck_files(files, fd)) |
1370 | continue; | 1316 | continue; |
1371 | rcu_read_unlock(); | 1317 | rcu_read_unlock(); |
1372 | 1318 | ||
1373 | j = PROC_NUMBUF; | 1319 | if (proc_fd_fill_cache(filp, dirent, filldir, p, fd) < 0) { |
1374 | i = fd; | ||
1375 | do { | ||
1376 | j--; | ||
1377 | buf[j] = '0' + (i % 10); | ||
1378 | i /= 10; | ||
1379 | } while (i); | ||
1380 | |||
1381 | ino = fake_ino(tid, PROC_TID_FD_DIR + fd); | ||
1382 | if (filldir(dirent, buf+j, PROC_NUMBUF-j, fd+2, ino, DT_LNK) < 0) { | ||
1383 | rcu_read_lock(); | 1320 | rcu_read_lock(); |
1384 | break; | 1321 | break; |
1385 | } | 1322 | } |
@@ -1415,7 +1352,7 @@ static struct dentry *proc_pident_instantiate(struct inode *dir, | |||
1415 | struct proc_inode *ei; | 1352 | struct proc_inode *ei; |
1416 | struct dentry *error = ERR_PTR(-EINVAL); | 1353 | struct dentry *error = ERR_PTR(-EINVAL); |
1417 | 1354 | ||
1418 | inode = proc_pid_make_inode(dir->i_sb, task, p->type); | 1355 | inode = proc_pid_make_inode(dir->i_sb, task); |
1419 | if (!inode) | 1356 | if (!inode) |
1420 | goto out; | 1357 | goto out; |
1421 | 1358 | ||
@@ -1473,6 +1410,13 @@ out_no_task: | |||
1473 | return error; | 1410 | return error; |
1474 | } | 1411 | } |
1475 | 1412 | ||
1413 | static int proc_pident_fill_cache(struct file *filp, void *dirent, filldir_t filldir, | ||
1414 | struct task_struct *task, struct pid_entry *p) | ||
1415 | { | ||
1416 | return proc_fill_cache(filp, dirent, filldir, p->name, p->len, | ||
1417 | proc_pident_instantiate, task, p); | ||
1418 | } | ||
1419 | |||
1476 | static int proc_pident_readdir(struct file *filp, | 1420 | static int proc_pident_readdir(struct file *filp, |
1477 | void *dirent, filldir_t filldir, | 1421 | void *dirent, filldir_t filldir, |
1478 | struct pid_entry *ents, unsigned int nents) | 1422 | struct pid_entry *ents, unsigned int nents) |
@@ -1488,11 +1432,10 @@ static int proc_pident_readdir(struct file *filp, | |||
1488 | 1432 | ||
1489 | ret = -ENOENT; | 1433 | ret = -ENOENT; |
1490 | if (!task) | 1434 | if (!task) |
1491 | goto out; | 1435 | goto out_no_task; |
1492 | 1436 | ||
1493 | ret = 0; | 1437 | ret = 0; |
1494 | pid = task->pid; | 1438 | pid = task->pid; |
1495 | put_task_struct(task); | ||
1496 | i = filp->f_pos; | 1439 | i = filp->f_pos; |
1497 | switch (i) { | 1440 | switch (i) { |
1498 | case 0: | 1441 | case 0: |
@@ -1517,8 +1460,7 @@ static int proc_pident_readdir(struct file *filp, | |||
1517 | } | 1460 | } |
1518 | p = ents + i; | 1461 | p = ents + i; |
1519 | while (p->name) { | 1462 | while (p->name) { |
1520 | if (filldir(dirent, p->name, p->len, filp->f_pos, | 1463 | if (proc_pident_fill_cache(filp, dirent, filldir, task, p) < 0) |
1521 | fake_ino(pid, p->type), p->mode >> 12) < 0) | ||
1522 | goto out; | 1464 | goto out; |
1523 | filp->f_pos++; | 1465 | filp->f_pos++; |
1524 | p++; | 1466 | p++; |
@@ -1527,6 +1469,8 @@ static int proc_pident_readdir(struct file *filp, | |||
1527 | 1469 | ||
1528 | ret = 1; | 1470 | ret = 1; |
1529 | out: | 1471 | out: |
1472 | put_task_struct(task); | ||
1473 | out_no_task: | ||
1530 | return ret; | 1474 | return ret; |
1531 | } | 1475 | } |
1532 | 1476 | ||
@@ -1606,21 +1550,21 @@ static struct file_operations proc_pid_attr_operations = { | |||
1606 | }; | 1550 | }; |
1607 | 1551 | ||
1608 | static struct pid_entry tgid_attr_stuff[] = { | 1552 | static struct pid_entry tgid_attr_stuff[] = { |
1609 | REG(PROC_TGID_ATTR_CURRENT, "current", S_IRUGO|S_IWUGO, pid_attr), | 1553 | REG("current", S_IRUGO|S_IWUGO, pid_attr), |
1610 | REG(PROC_TGID_ATTR_PREV, "prev", S_IRUGO, pid_attr), | 1554 | REG("prev", S_IRUGO, pid_attr), |
1611 | REG(PROC_TGID_ATTR_EXEC, "exec", S_IRUGO|S_IWUGO, pid_attr), | 1555 | REG("exec", S_IRUGO|S_IWUGO, pid_attr), |
1612 | REG(PROC_TGID_ATTR_FSCREATE, "fscreate", S_IRUGO|S_IWUGO, pid_attr), | 1556 | REG("fscreate", S_IRUGO|S_IWUGO, pid_attr), |
1613 | REG(PROC_TGID_ATTR_KEYCREATE, "keycreate", S_IRUGO|S_IWUGO, pid_attr), | 1557 | REG("keycreate", S_IRUGO|S_IWUGO, pid_attr), |
1614 | REG(PROC_TGID_ATTR_SOCKCREATE, "sockcreate", S_IRUGO|S_IWUGO, pid_attr), | 1558 | REG("sockcreate", S_IRUGO|S_IWUGO, pid_attr), |
1615 | {} | 1559 | {} |
1616 | }; | 1560 | }; |
1617 | static struct pid_entry tid_attr_stuff[] = { | 1561 | static struct pid_entry tid_attr_stuff[] = { |
1618 | REG(PROC_TID_ATTR_CURRENT, "current", S_IRUGO|S_IWUGO, pid_attr), | 1562 | REG("current", S_IRUGO|S_IWUGO, pid_attr), |
1619 | REG(PROC_TID_ATTR_PREV, "prev", S_IRUGO, pid_attr), | 1563 | REG("prev", S_IRUGO, pid_attr), |
1620 | REG(PROC_TID_ATTR_EXEC, "exec", S_IRUGO|S_IWUGO, pid_attr), | 1564 | REG("exec", S_IRUGO|S_IWUGO, pid_attr), |
1621 | REG(PROC_TID_ATTR_FSCREATE, "fscreate", S_IRUGO|S_IWUGO, pid_attr), | 1565 | REG("fscreate", S_IRUGO|S_IWUGO, pid_attr), |
1622 | REG(PROC_TID_ATTR_KEYCREATE, "keycreate", S_IRUGO|S_IWUGO, pid_attr), | 1566 | REG("keycreate", S_IRUGO|S_IWUGO, pid_attr), |
1623 | REG(PROC_TID_ATTR_SOCKCREATE, "sockcreate", S_IRUGO|S_IWUGO, pid_attr), | 1567 | REG("sockcreate", S_IRUGO|S_IWUGO, pid_attr), |
1624 | {} | 1568 | {} |
1625 | }; | 1569 | }; |
1626 | 1570 | ||
@@ -1704,7 +1648,7 @@ static struct inode_operations proc_self_inode_operations = { | |||
1704 | * describe something that is process related. | 1648 | * describe something that is process related. |
1705 | */ | 1649 | */ |
1706 | static struct pid_entry proc_base_stuff[] = { | 1650 | static struct pid_entry proc_base_stuff[] = { |
1707 | NOD(PROC_TGID_INO, "self", S_IFLNK|S_IRWXUGO, | 1651 | NOD("self", S_IFLNK|S_IRWXUGO, |
1708 | &proc_self_inode_operations, NULL, {}), | 1652 | &proc_self_inode_operations, NULL, {}), |
1709 | {} | 1653 | {} |
1710 | }; | 1654 | }; |
@@ -1749,7 +1693,6 @@ static struct dentry *proc_base_instantiate(struct inode *dir, | |||
1749 | /* Initialize the inode */ | 1693 | /* Initialize the inode */ |
1750 | ei = PROC_I(inode); | 1694 | ei = PROC_I(inode); |
1751 | inode->i_mtime = inode->i_atime = inode->i_ctime = CURRENT_TIME; | 1695 | inode->i_mtime = inode->i_atime = inode->i_ctime = CURRENT_TIME; |
1752 | inode->i_ino = fake_ino(0, p->type); | ||
1753 | 1696 | ||
1754 | /* | 1697 | /* |
1755 | * grab the reference to the task. | 1698 | * grab the reference to the task. |
@@ -1809,6 +1752,13 @@ out_no_task: | |||
1809 | return error; | 1752 | return error; |
1810 | } | 1753 | } |
1811 | 1754 | ||
1755 | static int proc_base_fill_cache(struct file *filp, void *dirent, filldir_t filldir, | ||
1756 | struct task_struct *task, struct pid_entry *p) | ||
1757 | { | ||
1758 | return proc_fill_cache(filp, dirent, filldir, p->name, p->len, | ||
1759 | proc_base_instantiate, task, p); | ||
1760 | } | ||
1761 | |||
1812 | /* | 1762 | /* |
1813 | * Thread groups | 1763 | * Thread groups |
1814 | */ | 1764 | */ |
@@ -1816,46 +1766,46 @@ static struct file_operations proc_task_operations; | |||
1816 | static struct inode_operations proc_task_inode_operations; | 1766 | static struct inode_operations proc_task_inode_operations; |
1817 | 1767 | ||
1818 | static struct pid_entry tgid_base_stuff[] = { | 1768 | static struct pid_entry tgid_base_stuff[] = { |
1819 | DIR(PROC_TGID_TASK, "task", S_IRUGO|S_IXUGO, task), | 1769 | DIR("task", S_IRUGO|S_IXUGO, task), |
1820 | DIR(PROC_TGID_FD, "fd", S_IRUSR|S_IXUSR, fd), | 1770 | DIR("fd", S_IRUSR|S_IXUSR, fd), |
1821 | INF(PROC_TGID_ENVIRON, "environ", S_IRUSR, pid_environ), | 1771 | INF("environ", S_IRUSR, pid_environ), |
1822 | INF(PROC_TGID_AUXV, "auxv", S_IRUSR, pid_auxv), | 1772 | INF("auxv", S_IRUSR, pid_auxv), |
1823 | INF(PROC_TGID_STATUS, "status", S_IRUGO, pid_status), | 1773 | INF("status", S_IRUGO, pid_status), |
1824 | INF(PROC_TGID_CMDLINE, "cmdline", S_IRUGO, pid_cmdline), | 1774 | INF("cmdline", S_IRUGO, pid_cmdline), |
1825 | INF(PROC_TGID_STAT, "stat", S_IRUGO, tgid_stat), | 1775 | INF("stat", S_IRUGO, tgid_stat), |
1826 | INF(PROC_TGID_STATM, "statm", S_IRUGO, pid_statm), | 1776 | INF("statm", S_IRUGO, pid_statm), |
1827 | REG(PROC_TGID_MAPS, "maps", S_IRUGO, maps), | 1777 | REG("maps", S_IRUGO, maps), |
1828 | #ifdef CONFIG_NUMA | 1778 | #ifdef CONFIG_NUMA |
1829 | REG(PROC_TGID_NUMA_MAPS, "numa_maps", S_IRUGO, numa_maps), | 1779 | REG("numa_maps", S_IRUGO, numa_maps), |
1830 | #endif | 1780 | #endif |
1831 | REG(PROC_TGID_MEM, "mem", S_IRUSR|S_IWUSR, mem), | 1781 | REG("mem", S_IRUSR|S_IWUSR, mem), |
1832 | #ifdef CONFIG_SECCOMP | 1782 | #ifdef CONFIG_SECCOMP |
1833 | REG(PROC_TGID_SECCOMP, "seccomp", S_IRUSR|S_IWUSR, seccomp), | 1783 | REG("seccomp", S_IRUSR|S_IWUSR, seccomp), |
1834 | #endif | 1784 | #endif |
1835 | LNK(PROC_TGID_CWD, "cwd", cwd), | 1785 | LNK("cwd", cwd), |
1836 | LNK(PROC_TGID_ROOT, "root", root), | 1786 | LNK("root", root), |
1837 | LNK(PROC_TGID_EXE, "exe", exe), | 1787 | LNK("exe", exe), |
1838 | REG(PROC_TGID_MOUNTS, "mounts", S_IRUGO, mounts), | 1788 | REG("mounts", S_IRUGO, mounts), |
1839 | REG(PROC_TGID_MOUNTSTATS, "mountstats", S_IRUSR, mountstats), | 1789 | REG("mountstats", S_IRUSR, mountstats), |
1840 | #ifdef CONFIG_MMU | 1790 | #ifdef CONFIG_MMU |
1841 | REG(PROC_TGID_SMAPS, "smaps", S_IRUGO, smaps), | 1791 | REG("smaps", S_IRUGO, smaps), |
1842 | #endif | 1792 | #endif |
1843 | #ifdef CONFIG_SECURITY | 1793 | #ifdef CONFIG_SECURITY |
1844 | DIR(PROC_TGID_ATTR, "attr", S_IRUGO|S_IXUGO, tgid_attr), | 1794 | DIR("attr", S_IRUGO|S_IXUGO, tgid_attr), |
1845 | #endif | 1795 | #endif |
1846 | #ifdef CONFIG_KALLSYMS | 1796 | #ifdef CONFIG_KALLSYMS |
1847 | INF(PROC_TGID_WCHAN, "wchan", S_IRUGO, pid_wchan), | 1797 | INF("wchan", S_IRUGO, pid_wchan), |
1848 | #endif | 1798 | #endif |
1849 | #ifdef CONFIG_SCHEDSTATS | 1799 | #ifdef CONFIG_SCHEDSTATS |
1850 | INF(PROC_TGID_SCHEDSTAT, "schedstat", S_IRUGO, pid_schedstat), | 1800 | INF("schedstat", S_IRUGO, pid_schedstat), |
1851 | #endif | 1801 | #endif |
1852 | #ifdef CONFIG_CPUSETS | 1802 | #ifdef CONFIG_CPUSETS |
1853 | REG(PROC_TGID_CPUSET, "cpuset", S_IRUGO, cpuset), | 1803 | REG("cpuset", S_IRUGO, cpuset), |
1854 | #endif | 1804 | #endif |
1855 | INF(PROC_TGID_OOM_SCORE, "oom_score", S_IRUGO, oom_score), | 1805 | INF("oom_score", S_IRUGO, oom_score), |
1856 | REG(PROC_TGID_OOM_ADJUST, "oom_adj", S_IRUGO|S_IWUSR, oom_adjust), | 1806 | REG("oom_adj", S_IRUGO|S_IWUSR, oom_adjust), |
1857 | #ifdef CONFIG_AUDITSYSCALL | 1807 | #ifdef CONFIG_AUDITSYSCALL |
1858 | REG(PROC_TGID_LOGINUID, "loginuid", S_IWUSR|S_IRUGO, loginuid), | 1808 | REG("loginuid", S_IWUSR|S_IRUGO, loginuid), |
1859 | #endif | 1809 | #endif |
1860 | {} | 1810 | {} |
1861 | }; | 1811 | }; |
@@ -1955,7 +1905,7 @@ struct dentry *proc_pid_instantiate(struct inode *dir, | |||
1955 | struct dentry *error = ERR_PTR(-ENOENT); | 1905 | struct dentry *error = ERR_PTR(-ENOENT); |
1956 | struct inode *inode; | 1906 | struct inode *inode; |
1957 | 1907 | ||
1958 | inode = proc_pid_make_inode(dir->i_sb, task, PROC_TGID_INO); | 1908 | inode = proc_pid_make_inode(dir->i_sb, task); |
1959 | if (!inode) | 1909 | if (!inode) |
1960 | goto out; | 1910 | goto out; |
1961 | 1911 | ||
@@ -2045,18 +1995,29 @@ retry: | |||
2045 | 1995 | ||
2046 | #define TGID_OFFSET (FIRST_PROCESS_ENTRY + (1 /* /proc/self */)) | 1996 | #define TGID_OFFSET (FIRST_PROCESS_ENTRY + (1 /* /proc/self */)) |
2047 | 1997 | ||
1998 | static int proc_pid_fill_cache(struct file *filp, void *dirent, filldir_t filldir, | ||
1999 | struct task_struct *task, int tgid) | ||
2000 | { | ||
2001 | char name[PROC_NUMBUF]; | ||
2002 | int len = snprintf(name, sizeof(name), "%d", tgid); | ||
2003 | return proc_fill_cache(filp, dirent, filldir, name, len, | ||
2004 | proc_pid_instantiate, task, NULL); | ||
2005 | } | ||
2006 | |||
2048 | /* for the /proc/ directory itself, after non-process stuff has been done */ | 2007 | /* for the /proc/ directory itself, after non-process stuff has been done */ |
2049 | int proc_pid_readdir(struct file * filp, void * dirent, filldir_t filldir) | 2008 | int proc_pid_readdir(struct file * filp, void * dirent, filldir_t filldir) |
2050 | { | 2009 | { |
2051 | char buf[PROC_NUMBUF]; | ||
2052 | unsigned int nr = filp->f_pos - FIRST_PROCESS_ENTRY; | 2010 | unsigned int nr = filp->f_pos - FIRST_PROCESS_ENTRY; |
2011 | struct task_struct *reaper = get_proc_task(filp->f_dentry->d_inode); | ||
2053 | struct task_struct *task; | 2012 | struct task_struct *task; |
2054 | int tgid; | 2013 | int tgid; |
2055 | 2014 | ||
2015 | if (!reaper) | ||
2016 | goto out_no_task; | ||
2017 | |||
2056 | for (; nr < (ARRAY_SIZE(proc_base_stuff) - 1); filp->f_pos++, nr++) { | 2018 | for (; nr < (ARRAY_SIZE(proc_base_stuff) - 1); filp->f_pos++, nr++) { |
2057 | struct pid_entry *p = &proc_base_stuff[nr]; | 2019 | struct pid_entry *p = &proc_base_stuff[nr]; |
2058 | if (filldir(dirent, p->name, p->len, filp->f_pos, | 2020 | if (proc_base_fill_cache(filp, dirent, filldir, reaper, p) < 0) |
2059 | fake_ino(0, p->type), p->mode >> 12) < 0) | ||
2060 | goto out; | 2021 | goto out; |
2061 | } | 2022 | } |
2062 | 2023 | ||
@@ -2064,19 +2025,17 @@ int proc_pid_readdir(struct file * filp, void * dirent, filldir_t filldir) | |||
2064 | for (task = next_tgid(tgid); | 2025 | for (task = next_tgid(tgid); |
2065 | task; | 2026 | task; |
2066 | put_task_struct(task), task = next_tgid(tgid + 1)) { | 2027 | put_task_struct(task), task = next_tgid(tgid + 1)) { |
2067 | int len; | ||
2068 | ino_t ino; | ||
2069 | tgid = task->pid; | 2028 | tgid = task->pid; |
2070 | filp->f_pos = tgid + TGID_OFFSET; | 2029 | filp->f_pos = tgid + TGID_OFFSET; |
2071 | len = snprintf(buf, sizeof(buf), "%d", tgid); | 2030 | if (proc_pid_fill_cache(filp, dirent, filldir, task, tgid) < 0) { |
2072 | ino = fake_ino(tgid, PROC_TGID_INO); | ||
2073 | if (filldir(dirent, buf, len, filp->f_pos, ino, DT_DIR) < 0) { | ||
2074 | put_task_struct(task); | 2031 | put_task_struct(task); |
2075 | goto out; | 2032 | goto out; |
2076 | } | 2033 | } |
2077 | } | 2034 | } |
2078 | filp->f_pos = PID_MAX_LIMIT + TGID_OFFSET; | 2035 | filp->f_pos = PID_MAX_LIMIT + TGID_OFFSET; |
2079 | out: | 2036 | out: |
2037 | put_task_struct(reaper); | ||
2038 | out_no_task: | ||
2080 | return 0; | 2039 | return 0; |
2081 | } | 2040 | } |
2082 | 2041 | ||
@@ -2084,44 +2043,44 @@ out: | |||
2084 | * Tasks | 2043 | * Tasks |
2085 | */ | 2044 | */ |
2086 | static struct pid_entry tid_base_stuff[] = { | 2045 | static struct pid_entry tid_base_stuff[] = { |
2087 | DIR(PROC_TID_FD, "fd", S_IRUSR|S_IXUSR, fd), | 2046 | DIR("fd", S_IRUSR|S_IXUSR, fd), |
2088 | INF(PROC_TID_ENVIRON, "environ", S_IRUSR, pid_environ), | 2047 | INF("environ", S_IRUSR, pid_environ), |
2089 | INF(PROC_TID_AUXV, "auxv", S_IRUSR, pid_auxv), | 2048 | INF("auxv", S_IRUSR, pid_auxv), |
2090 | INF(PROC_TID_STATUS, "status", S_IRUGO, pid_status), | 2049 | INF("status", S_IRUGO, pid_status), |
2091 | INF(PROC_TID_CMDLINE, "cmdline", S_IRUGO, pid_cmdline), | 2050 | INF("cmdline", S_IRUGO, pid_cmdline), |
2092 | INF(PROC_TID_STAT, "stat", S_IRUGO, tid_stat), | 2051 | INF("stat", S_IRUGO, tid_stat), |
2093 | INF(PROC_TID_STATM, "statm", S_IRUGO, pid_statm), | 2052 | INF("statm", S_IRUGO, pid_statm), |
2094 | REG(PROC_TID_MAPS, "maps", S_IRUGO, maps), | 2053 | REG("maps", S_IRUGO, maps), |
2095 | #ifdef CONFIG_NUMA | 2054 | #ifdef CONFIG_NUMA |
2096 | REG(PROC_TID_NUMA_MAPS, "numa_maps", S_IRUGO, numa_maps), | 2055 | REG("numa_maps", S_IRUGO, numa_maps), |
2097 | #endif | 2056 | #endif |
2098 | REG(PROC_TID_MEM, "mem", S_IRUSR|S_IWUSR, mem), | 2057 | REG("mem", S_IRUSR|S_IWUSR, mem), |
2099 | #ifdef CONFIG_SECCOMP | 2058 | #ifdef CONFIG_SECCOMP |
2100 | REG(PROC_TID_SECCOMP, "seccomp", S_IRUSR|S_IWUSR, seccomp), | 2059 | REG("seccomp", S_IRUSR|S_IWUSR, seccomp), |
2101 | #endif | 2060 | #endif |
2102 | LNK(PROC_TID_CWD, "cwd", cwd), | 2061 | LNK("cwd", cwd), |
2103 | LNK(PROC_TID_ROOT, "root", root), | 2062 | LNK("root", root), |
2104 | LNK(PROC_TID_EXE, "exe", exe), | 2063 | LNK("exe", exe), |
2105 | REG(PROC_TID_MOUNTS, "mounts", S_IRUGO, mounts), | 2064 | REG("mounts", S_IRUGO, mounts), |
2106 | #ifdef CONFIG_MMU | 2065 | #ifdef CONFIG_MMU |
2107 | REG(PROC_TID_SMAPS, "smaps", S_IRUGO, smaps), | 2066 | REG("smaps", S_IRUGO, smaps), |
2108 | #endif | 2067 | #endif |
2109 | #ifdef CONFIG_SECURITY | 2068 | #ifdef CONFIG_SECURITY |
2110 | DIR(PROC_TID_ATTR, "attr", S_IRUGO|S_IXUGO, tid_attr), | 2069 | DIR("attr", S_IRUGO|S_IXUGO, tid_attr), |
2111 | #endif | 2070 | #endif |
2112 | #ifdef CONFIG_KALLSYMS | 2071 | #ifdef CONFIG_KALLSYMS |
2113 | INF(PROC_TID_WCHAN, "wchan", S_IRUGO, pid_wchan), | 2072 | INF("wchan", S_IRUGO, pid_wchan), |
2114 | #endif | 2073 | #endif |
2115 | #ifdef CONFIG_SCHEDSTATS | 2074 | #ifdef CONFIG_SCHEDSTATS |
2116 | INF(PROC_TID_SCHEDSTAT, "schedstat", S_IRUGO, pid_schedstat), | 2075 | INF("schedstat", S_IRUGO, pid_schedstat), |
2117 | #endif | 2076 | #endif |
2118 | #ifdef CONFIG_CPUSETS | 2077 | #ifdef CONFIG_CPUSETS |
2119 | REG(PROC_TID_CPUSET, "cpuset", S_IRUGO, cpuset), | 2078 | REG("cpuset", S_IRUGO, cpuset), |
2120 | #endif | 2079 | #endif |
2121 | INF(PROC_TID_OOM_SCORE, "oom_score", S_IRUGO, oom_score), | 2080 | INF("oom_score", S_IRUGO, oom_score), |
2122 | REG(PROC_TID_OOM_ADJUST, "oom_adj", S_IRUGO|S_IWUSR, oom_adjust), | 2081 | REG("oom_adj", S_IRUGO|S_IWUSR, oom_adjust), |
2123 | #ifdef CONFIG_AUDITSYSCALL | 2082 | #ifdef CONFIG_AUDITSYSCALL |
2124 | REG(PROC_TID_LOGINUID, "loginuid", S_IWUSR|S_IRUGO, loginuid), | 2083 | REG("loginuid", S_IWUSR|S_IRUGO, loginuid), |
2125 | #endif | 2084 | #endif |
2126 | {} | 2085 | {} |
2127 | }; | 2086 | }; |
@@ -2153,7 +2112,7 @@ static struct dentry *proc_task_instantiate(struct inode *dir, | |||
2153 | { | 2112 | { |
2154 | struct dentry *error = ERR_PTR(-ENOENT); | 2113 | struct dentry *error = ERR_PTR(-ENOENT); |
2155 | struct inode *inode; | 2114 | struct inode *inode; |
2156 | inode = proc_pid_make_inode(dir->i_sb, task, PROC_TID_INO); | 2115 | inode = proc_pid_make_inode(dir->i_sb, task); |
2157 | 2116 | ||
2158 | if (!inode) | 2117 | if (!inode) |
2159 | goto out; | 2118 | goto out; |
@@ -2279,10 +2238,18 @@ static struct task_struct *next_tid(struct task_struct *start) | |||
2279 | return pos; | 2238 | return pos; |
2280 | } | 2239 | } |
2281 | 2240 | ||
2241 | static int proc_task_fill_cache(struct file *filp, void *dirent, filldir_t filldir, | ||
2242 | struct task_struct *task, int tid) | ||
2243 | { | ||
2244 | char name[PROC_NUMBUF]; | ||
2245 | int len = snprintf(name, sizeof(name), "%d", tid); | ||
2246 | return proc_fill_cache(filp, dirent, filldir, name, len, | ||
2247 | proc_task_instantiate, task, NULL); | ||
2248 | } | ||
2249 | |||
2282 | /* for the /proc/TGID/task/ directories */ | 2250 | /* for the /proc/TGID/task/ directories */ |
2283 | static int proc_task_readdir(struct file * filp, void * dirent, filldir_t filldir) | 2251 | static int proc_task_readdir(struct file * filp, void * dirent, filldir_t filldir) |
2284 | { | 2252 | { |
2285 | char buf[PROC_NUMBUF]; | ||
2286 | struct dentry *dentry = filp->f_dentry; | 2253 | struct dentry *dentry = filp->f_dentry; |
2287 | struct inode *inode = dentry->d_inode; | 2254 | struct inode *inode = dentry->d_inode; |
2288 | struct task_struct *leader = get_proc_task(inode); | 2255 | struct task_struct *leader = get_proc_task(inode); |
@@ -2319,11 +2286,8 @@ static int proc_task_readdir(struct file * filp, void * dirent, filldir_t filldi | |||
2319 | for (task = first_tid(leader, tid, pos - 2); | 2286 | for (task = first_tid(leader, tid, pos - 2); |
2320 | task; | 2287 | task; |
2321 | task = next_tid(task), pos++) { | 2288 | task = next_tid(task), pos++) { |
2322 | int len; | ||
2323 | tid = task->pid; | 2289 | tid = task->pid; |
2324 | len = snprintf(buf, sizeof(buf), "%d", tid); | 2290 | if (proc_task_fill_cache(filp, dirent, filldir, task, tid) < 0) { |
2325 | ino = fake_ino(tid, PROC_TID_INO); | ||
2326 | if (filldir(dirent, buf, len, pos, ino, DT_DIR < 0)) { | ||
2327 | /* returning this tgid failed, save it as the first | 2291 | /* returning this tgid failed, save it as the first |
2328 | * pid for the next readir call */ | 2292 | * pid for the next readir call */ |
2329 | filp->f_version = tid; | 2293 | filp->f_version = tid; |