This source file includes following definitions.
- proc_register
- proc_unregister
- make_inode_number
- proc_register_dynamic
- proc_self_followlink
- proc_self_readlink
- proc_root_init
- proc_match
- proc_lookup
- proc_root_lookup
- proc_readdir
- proc_root_readdir
1
2
3
4
5
6
7
8
9 #include <asm/segment.h>
10
11 #include <linux/errno.h>
12 #include <linux/sched.h>
13 #include <linux/proc_fs.h>
14 #include <linux/stat.h>
15 #include <linux/config.h>
16 #include <asm/bitops.h>
17
18
19
20
21 #define FIRST_PROCESS_ENTRY 256
22
23 static int proc_root_readdir(struct inode *, struct file *, void *, filldir_t);
24 static int proc_root_lookup(struct inode *,const char *,int,struct inode **);
25
26 static unsigned char proc_alloc_map[PROC_NDYNAMIC / 8] = {0};
27
28
29
30
31
32
33
34
35
36 static struct file_operations proc_dir_operations = {
37 NULL,
38 NULL,
39 NULL,
40 proc_readdir,
41 NULL,
42 NULL,
43 NULL,
44 NULL,
45 NULL,
46 NULL
47 };
48
49
50
51
52 struct inode_operations proc_dir_inode_operations = {
53 &proc_dir_operations,
54 NULL,
55 proc_lookup,
56 NULL,
57 NULL,
58 NULL,
59 NULL,
60 NULL,
61 NULL,
62 NULL,
63 NULL,
64 NULL,
65 NULL,
66 NULL,
67 NULL,
68 NULL,
69 NULL
70 };
71
72
73
74
75
76
77 static struct file_operations proc_root_operations = {
78 NULL,
79 NULL,
80 NULL,
81 proc_root_readdir,
82 NULL,
83 NULL,
84 NULL,
85 NULL,
86 NULL,
87 NULL
88 };
89
90
91
92
93 static struct inode_operations proc_root_inode_operations = {
94 &proc_root_operations,
95 NULL,
96 proc_root_lookup,
97 NULL,
98 NULL,
99 NULL,
100 NULL,
101 NULL,
102 NULL,
103 NULL,
104 NULL,
105 NULL,
106 NULL,
107 NULL,
108 NULL,
109 NULL,
110 NULL
111 };
112
113
114
115
116 struct proc_dir_entry proc_root = {
117 PROC_ROOT_INO, 5, "/proc",
118 S_IFDIR | S_IRUGO | S_IXUGO, 2, 0, 0,
119 0, &proc_root_inode_operations,
120 NULL, NULL,
121 NULL,
122 &proc_root, NULL
123 };
124
125 struct proc_dir_entry proc_net = {
126 PROC_NET, 3, "net",
127 S_IFDIR | S_IRUGO | S_IXUGO, 2, 0, 0,
128 0, &proc_dir_inode_operations,
129 NULL, NULL,
130 NULL,
131 NULL, NULL
132 };
133
134 struct proc_dir_entry proc_scsi = {
135 PROC_SCSI, 4, "scsi",
136 S_IFDIR | S_IRUGO | S_IXUGO, 2, 0, 0,
137 0, &proc_dir_inode_operations,
138 NULL, NULL,
139 NULL, &proc_root, NULL
140 };
141
142 struct proc_dir_entry proc_sys_root = {
143 PROC_SYS, 3, "sys",
144 S_IFDIR | S_IRUGO | S_IXUGO, 2, 0, 0,
145 0, &proc_dir_inode_operations,
146 NULL, NULL,
147 NULL,
148 NULL, NULL
149 };
150
151 int proc_register(struct proc_dir_entry * dir, struct proc_dir_entry * dp)
152 {
153 dp->next = dir->subdir;
154 dp->parent = dir;
155 dir->subdir = dp;
156 if (S_ISDIR(dp->mode))
157 dir->nlink++;
158 return 0;
159 }
160
161 int proc_unregister(struct proc_dir_entry * dir, int ino)
162 {
163 struct proc_dir_entry **p = &dir->subdir, *dp;
164
165 while ((dp = *p) != NULL) {
166 if (dp->low_ino == ino) {
167 *p = dp->next;
168 dp->next = NULL;
169 if (S_ISDIR(dp->mode))
170 dir->nlink--;
171 if (ino >= PROC_DYNAMIC_FIRST &&
172 ino < PROC_DYNAMIC_FIRST+PROC_NDYNAMIC)
173 clear_bit(ino-PROC_DYNAMIC_FIRST,
174 (void *) proc_alloc_map);
175 return 0;
176 }
177 p = &dp->next;
178 }
179 return -EINVAL;
180 }
181
182 static int make_inode_number(void)
183 {
184 int i = find_first_zero_bit((void *) proc_alloc_map, PROC_NDYNAMIC);
185 if (i<0 || i>=PROC_NDYNAMIC)
186 return -1;
187 set_bit(i, (void *) proc_alloc_map);
188 return PROC_DYNAMIC_FIRST + i;
189 }
190
191 int proc_register_dynamic(struct proc_dir_entry * dir,
192 struct proc_dir_entry * dp)
193 {
194 int i = make_inode_number();
195 if (i < 0)
196 return -EAGAIN;
197 dp->low_ino = i;
198 dp->next = dir->subdir;
199 dp->parent = dir;
200 dir->subdir = dp;
201 if (S_ISDIR(dp->mode))
202 dir->nlink++;
203 return 0;
204 }
205
206
207
208
209 static int proc_self_followlink(struct inode * dir, struct inode * inode,
210 int flag, int mode, struct inode ** res_inode)
211 {
212 iput(dir);
213 *res_inode = proc_get_inode(inode->i_sb, (current->pid << 16) + PROC_PID_INO, &proc_pid);
214 iput(inode);
215 if (!*res_inode)
216 return -ENOENT;
217 return 0;
218 }
219
220 static int proc_self_readlink(struct inode * inode, char * buffer, int buflen)
221 {
222 int len;
223 char tmp[30];
224
225 iput(inode);
226 len = 1 + sprintf(tmp, "%d", current->pid);
227 if (buflen < len)
228 len = buflen;
229 memcpy_tofs(buffer, tmp, len);
230 return len;
231 }
232
233 static struct inode_operations proc_self_inode_operations = {
234 NULL,
235 NULL,
236 NULL,
237 NULL,
238 NULL,
239 NULL,
240 NULL,
241 NULL,
242 NULL,
243 NULL,
244 proc_self_readlink,
245 proc_self_followlink,
246 NULL,
247 NULL,
248 NULL,
249 NULL,
250 NULL
251 };
252
253 void proc_root_init(void)
254 {
255 static int done = 0;
256
257 if (done)
258 return;
259 done = 1;
260 proc_base_init();
261 proc_register(&proc_root, &(struct proc_dir_entry) {
262 PROC_LOADAVG, 7, "loadavg",
263 S_IFREG | S_IRUGO, 1, 0, 0,
264 });
265 proc_register(&proc_root, &(struct proc_dir_entry) {
266 PROC_UPTIME, 6, "uptime",
267 S_IFREG | S_IRUGO, 1, 0, 0,
268 });
269 proc_register(&proc_root, &(struct proc_dir_entry) {
270 PROC_MEMINFO, 7, "meminfo",
271 S_IFREG | S_IRUGO, 1, 0, 0,
272 });
273 proc_register(&proc_root, &(struct proc_dir_entry) {
274 PROC_KMSG, 4, "kmsg",
275 S_IFREG | S_IRUSR, 1, 0, 0,
276 });
277 proc_register(&proc_root, &(struct proc_dir_entry) {
278 PROC_VERSION, 7, "version",
279 S_IFREG | S_IRUGO, 1, 0, 0,
280 });
281 #ifdef CONFIG_PCI
282 proc_register(&proc_root, &(struct proc_dir_entry) {
283 PROC_PCI, 3, "pci",
284 S_IFREG | S_IRUGO, 1, 0, 0,
285 });
286 #endif
287 proc_register(&proc_root, &(struct proc_dir_entry) {
288 PROC_CPUINFO, 7, "cpuinfo",
289 S_IFREG | S_IRUGO, 1, 0, 0,
290 });
291 proc_register(&proc_root, &(struct proc_dir_entry) {
292 PROC_SELF, 4, "self",
293 S_IFLNK | S_IRUGO | S_IWUGO | S_IXUGO, 1, 0, 0,
294 64, &proc_self_inode_operations,
295 });
296 proc_register(&proc_root, &proc_net);
297 proc_register(&proc_root, &proc_scsi);
298 proc_register(&proc_root, &proc_sys_root);
299
300 #ifdef CONFIG_DEBUG_MALLOC
301 proc_register(&proc_root, &(struct proc_dir_entry) {
302 PROC_MALLOC, 6, "malloc",
303 S_IFREG | S_IRUGO, 1, 0, 0,
304 });
305 #endif
306 proc_register(&proc_root, &(struct proc_dir_entry) {
307 PROC_KCORE, 5, "kcore",
308 S_IFREG | S_IRUSR, 1, 0, 0,
309 });
310
311 #ifdef CONFIG_MODULES
312 proc_register(&proc_root, &(struct proc_dir_entry) {
313 PROC_MODULES, 7, "modules",
314 S_IFREG | S_IRUGO, 1, 0, 0,
315 });
316 proc_register(&proc_root, &(struct proc_dir_entry) {
317 PROC_KSYMS, 5, "ksyms",
318 S_IFREG | S_IRUGO, 1, 0, 0,
319 });
320 #endif
321 proc_register(&proc_root, &(struct proc_dir_entry) {
322 PROC_STAT, 4, "stat",
323 S_IFREG | S_IRUGO, 1, 0, 0,
324 });
325 proc_register(&proc_root, &(struct proc_dir_entry) {
326 PROC_DEVICES, 7, "devices",
327 S_IFREG | S_IRUGO, 1, 0, 0,
328 });
329 proc_register(&proc_root, &(struct proc_dir_entry) {
330 PROC_INTERRUPTS, 10,"interrupts",
331 S_IFREG | S_IRUGO, 1, 0, 0,
332 });
333 #ifdef __SMP_PROF__
334 proc_register(&proc_root, &(struct proc_dir_entry) {
335 PROC_SMP_PROF, 3,"smp",
336 S_IFREG | S_IRUGO, 1, 0, 0,
337 });
338 #endif
339 proc_register(&proc_root, &(struct proc_dir_entry) {
340 PROC_FILESYSTEMS, 11,"filesystems",
341 S_IFREG | S_IRUGO, 1, 0, 0,
342 });
343 proc_register(&proc_root, &(struct proc_dir_entry) {
344 PROC_DMA, 3, "dma",
345 S_IFREG | S_IRUGO, 1, 0, 0,
346 });
347 proc_register(&proc_root, &(struct proc_dir_entry) {
348 PROC_IOPORTS, 7, "ioports",
349 S_IFREG | S_IRUGO, 1, 0, 0,
350 });
351 proc_register(&proc_root, &(struct proc_dir_entry) {
352 PROC_CMDLINE, 7, "cmdline",
353 S_IFREG | S_IRUGO, 1, 0, 0,
354 });
355 #ifdef CONFIG_RTC
356 proc_register(&proc_root, &(struct proc_dir_entry) {
357 PROC_RTC, 3, "rtc",
358 S_IFREG | S_IRUGO, 1, 0, 0,
359 });
360 #endif
361 proc_register(&proc_root, &(struct proc_dir_entry) {
362 PROC_LOCKS, 5, "locks",
363 S_IFREG | S_IRUGO, 1, 0, 0,
364 });
365
366 proc_register( &proc_root, &(struct proc_dir_entry)
367 { PROC_MTAB, 6, "mounts", S_IFREG | S_IRUGO, 1, 0, 0, } );
368
369 if (prof_shift) {
370 proc_register(&proc_root, &(struct proc_dir_entry) {
371 PROC_PROFILE, 7, "profile",
372 S_IFREG | S_IRUGO | S_IWUSR, 1, 0, 0,
373 });
374 }
375 }
376
377
378 int proc_match(int len,const char * name,struct proc_dir_entry * de)
379 {
380 if (!de || !de->low_ino)
381 return 0;
382
383 if (!len && (de->name[0]=='.') && (de->name[1]=='\0'))
384 return 1;
385 if (de->namelen != len)
386 return 0;
387 return !memcmp(name, de->name, len);
388 }
389
390 int proc_lookup(struct inode * dir,const char * name, int len,
391 struct inode ** result)
392 {
393 struct proc_dir_entry * de;
394 int ino;
395
396 *result = NULL;
397 if (!dir || !S_ISDIR(dir->i_mode)) {
398 iput(dir);
399 return -ENOTDIR;
400 }
401
402 de = (struct proc_dir_entry *) dir->u.generic_ip;
403 if (!de) {
404 iput(dir);
405 return -EINVAL;
406 }
407
408
409 *result = dir;
410 if (!len)
411 return 0;
412 if (name[0] == '.') {
413 if (len == 1)
414 return 0;
415 if (name[1] == '.' && len == 2) {
416 struct inode * inode;
417 inode = proc_get_inode(dir->i_sb, de->parent->low_ino, de->parent);
418 iput(dir);
419 if (!inode)
420 return -EINVAL;
421 *result = inode;
422 return 0;
423 }
424 }
425
426 *result = NULL;
427 for (de = de->subdir; de ; de = de->next) {
428 if (proc_match(len, name, de))
429 break;
430 }
431 if (!de) {
432 iput(dir);
433 return -ENOENT;
434 }
435
436 ino = de->low_ino | (dir->i_ino & ~(0xffff));
437
438 if (!(*result = proc_get_inode(dir->i_sb, ino, de))) {
439 iput(dir);
440 return -EINVAL;
441 }
442 iput(dir);
443 return 0;
444 }
445
446 static int proc_root_lookup(struct inode * dir,const char * name, int len,
447 struct inode ** result)
448 {
449 unsigned int pid, c;
450 int i, ino, retval;
451
452 dir->i_count++;
453 retval = proc_lookup(dir, name, len, result);
454 if (retval != -ENOENT) {
455 iput(dir);
456 return retval;
457 }
458
459 pid = 0;
460 while (len-- > 0) {
461 c = *name - '0';
462 name++;
463 if (c > 9) {
464 pid = 0;
465 break;
466 }
467 pid *= 10;
468 pid += c;
469 if (pid & 0xffff0000) {
470 pid = 0;
471 break;
472 }
473 }
474 for (i = 0 ; i < NR_TASKS ; i++)
475 if (task[i] && task[i]->pid == pid)
476 break;
477 if (!pid || i >= NR_TASKS) {
478 iput(dir);
479 return -ENOENT;
480 }
481 ino = (pid << 16) + PROC_PID_INO;
482 if (!(*result = proc_get_inode(dir->i_sb, ino, &proc_pid))) {
483 iput(dir);
484 return -EINVAL;
485 }
486 iput(dir);
487 return 0;
488 }
489
490
491
492
493
494
495
496
497
498
499 int proc_readdir(struct inode * inode, struct file * filp,
500 void * dirent, filldir_t filldir)
501 {
502 struct proc_dir_entry * de;
503 unsigned int ino;
504 int i;
505
506 if (!inode || !S_ISDIR(inode->i_mode))
507 return -ENOTDIR;
508 ino = inode->i_ino;
509 de = (struct proc_dir_entry *) inode->u.generic_ip;
510 if (!de)
511 return -EINVAL;
512 i = filp->f_pos;
513 switch (i) {
514 case 0:
515 if (filldir(dirent, ".", 1, i, ino) < 0)
516 return 0;
517 i++;
518 filp->f_pos++;
519
520 case 1:
521 if (filldir(dirent, "..", 2, i, de->parent->low_ino) < 0)
522 return 0;
523 i++;
524 filp->f_pos++;
525
526 default:
527 ino &= ~0xffff;
528 de = de->subdir;
529 i -= 2;
530 for (;;) {
531 if (!de)
532 return 1;
533 if (!i)
534 break;
535 de = de->next;
536 i--;
537 }
538
539 do {
540 if (filldir(dirent, de->name, de->namelen, filp->f_pos, ino | de->low_ino) < 0)
541 return 0;
542 filp->f_pos++;
543 de = de->next;
544 } while (de);
545 }
546 return 1;
547 }
548
549 #define NUMBUF 10
550
551 static int proc_root_readdir(struct inode * inode, struct file * filp,
552 void * dirent, filldir_t filldir)
553 {
554 char buf[NUMBUF];
555 unsigned int nr,pid;
556 unsigned long i,j;
557
558 nr = filp->f_pos;
559 if (nr < FIRST_PROCESS_ENTRY) {
560 int error = proc_readdir(inode, filp, dirent, filldir);
561 if (error <= 0)
562 return error;
563 filp->f_pos = nr = FIRST_PROCESS_ENTRY;
564 }
565
566 for (nr -= FIRST_PROCESS_ENTRY; nr < NR_TASKS; nr++, filp->f_pos++) {
567 struct task_struct * p = task[nr];
568
569 if (!p || !(pid = p->pid))
570 continue;
571
572 j = NUMBUF;
573 i = pid;
574 do {
575 j--;
576 buf[j] = '0' + (i % 10);
577 i /= 10;
578 } while (i);
579
580 if (filldir(dirent, buf+j, NUMBUF-j, filp->f_pos, (pid << 16) + PROC_PID_INO) < 0)
581 break;
582 }
583 return 0;
584 }