fedora core 6 1.2949 + vserver 2.2.0
[linux-2.6.git] / kernel / vserver / proc.c
1 /*
2  *  linux/kernel/vserver/proc.c
3  *
4  *  Virtual Context Support
5  *
6  *  Copyright (C) 2003-2007  Herbert Pƶtzl
7  *
8  *  V0.01  basic structure
9  *  V0.02  adaptation vs1.3.0
10  *  V0.03  proc permissions
11  *  V0.04  locking/generic
12  *  V0.05  next generation procfs
13  *  V0.06  inode validation
14  *  V0.07  generic rewrite vid
15  *  V0.08  remove inode type
16  *
17  */
18
19 #include <linux/errno.h>
20 #include <linux/proc_fs.h>
21 #include <linux/sched.h>
22 #include <linux/vs_context.h>
23 #include <linux/vs_network.h>
24 #include <linux/vs_cvirt.h>
25
26 #include <linux/vserver/switch.h>
27 #include <linux/vserver/global.h>
28
29 #include <asm/uaccess.h>
30 #include <asm/unistd.h>
31
32 #include "cvirt_proc.h"
33 #include "cacct_proc.h"
34 #include "limit_proc.h"
35 #include "sched_proc.h"
36 #include "vci_config.h"
37
38 static struct proc_dir_entry *proc_virtual;
39
40 static struct proc_dir_entry *proc_virtnet;
41
42
43 /* first the actual feeds */
44
45
46 static int proc_vci(char *buffer)
47 {
48         return sprintf(buffer,
49                 "VCIVersion:\t%04x:%04x\n"
50                 "VCISyscall:\t%d\n"
51                 "VCIKernel:\t%08x\n"
52                 ,VCI_VERSION >> 16
53                 ,VCI_VERSION & 0xFFFF
54                 ,__NR_vserver
55                 ,vci_kernel_config()
56                 );
57 }
58
59 static int proc_virtual_info(char *buffer)
60 {
61         return proc_vci(buffer);
62 }
63
64 static int proc_virtual_status(char *buffer)
65 {
66         return sprintf(buffer,
67                 "#CTotal:\t%d\n"
68                 "#CActive:\t%d\n"
69                 "#NSProxy:\t%d\t%d %d %d %d\n"
70                 ,atomic_read(&vx_global_ctotal)
71                 ,atomic_read(&vx_global_cactive)
72                 ,atomic_read(&vs_global_nsproxy)
73                 ,atomic_read(&vs_global_fs)
74                 ,atomic_read(&vs_global_mnt_ns)
75                 ,atomic_read(&vs_global_uts_ns)
76                 ,atomic_read(&vs_global_ipc_ns)
77                 );
78 }
79
80
81 int proc_vxi_info (struct vx_info *vxi, char *buffer)
82 {
83         int length;
84
85         length = sprintf(buffer,
86                 "ID:\t%d\n"
87                 "Info:\t%p\n"
88                 "Init:\t%d\n"
89                 ,vxi->vx_id
90                 ,vxi
91                 ,vxi->vx_initpid
92                 );
93         return length;
94 }
95
96 int proc_vxi_status (struct vx_info *vxi, char *buffer)
97 {
98         int length;
99
100         length = sprintf(buffer,
101                 "UseCnt:\t%d\n"
102                 "Tasks:\t%d\n"
103                 "Flags:\t%016llx\n"
104                 "BCaps:\t%016llx\n"
105                 "CCaps:\t%016llx\n"
106                 "Spaces:\t%08lx\n"
107                 ,atomic_read(&vxi->vx_usecnt)
108                 ,atomic_read(&vxi->vx_tasks)
109                 ,(unsigned long long)vxi->vx_flags
110                 ,(unsigned long long)vxi->vx_bcaps
111                 ,(unsigned long long)vxi->vx_ccaps
112                 ,vxi->vx_nsmask
113                 );
114         return length;
115 }
116
117 int proc_vxi_limit (struct vx_info *vxi, char *buffer)
118 {
119         return vx_info_proc_limit(&vxi->limit, buffer);
120 }
121
122 int proc_vxi_sched (struct vx_info *vxi, char *buffer)
123 {
124         int cpu, length;
125
126         length = vx_info_proc_sched(&vxi->sched, buffer);
127         for_each_online_cpu(cpu) {
128                 length += vx_info_proc_sched_pc(
129                         &vx_per_cpu(vxi, sched_pc, cpu),
130                         buffer + length, cpu);
131         }
132         return length;
133 }
134
135 int proc_vxi_nsproxy (struct vx_info *vxi, char *buffer)
136 {
137         return vx_info_proc_nsproxy(vxi->vx_nsproxy, buffer);
138 }
139
140 int proc_vxi_cvirt (struct vx_info *vxi, char *buffer)
141 {
142         int cpu, length;
143
144         vx_update_load(vxi);
145         length = vx_info_proc_cvirt(&vxi->cvirt, buffer);
146         for_each_online_cpu(cpu) {
147                 length += vx_info_proc_cvirt_pc(
148                         &vx_per_cpu(vxi, cvirt_pc, cpu),
149                         buffer + length, cpu);
150         }
151         return length;
152 }
153
154 int proc_vxi_cacct (struct vx_info *vxi, char *buffer)
155 {
156         return vx_info_proc_cacct(&vxi->cacct, buffer);
157 }
158
159
160 static int proc_virtnet_info(char *buffer)
161 {
162         return proc_vci(buffer);
163 }
164
165 static int proc_virtnet_status(char *buffer)
166 {
167         return sprintf(buffer,
168                 "#CTotal:\t%d\n"
169                 "#CActive:\t%d\n"
170                 ,atomic_read(&nx_global_ctotal)
171                 ,atomic_read(&nx_global_cactive)
172                 );
173 }
174
175 int proc_nxi_info (struct nx_info *nxi, char *buffer)
176 {
177         int length, i;
178
179         length = sprintf(buffer,
180                 "ID:\t%d\n"
181                 "Info:\t%p\n"
182                 ,nxi->nx_id
183                 ,nxi
184                 );
185         for (i=0; i<nxi->nbipv4; i++) {
186                 length += sprintf(buffer + length,
187                         "%d:\t" NIPQUAD_FMT "/" NIPQUAD_FMT "\n", i,
188                         NIPQUAD(nxi->ipv4[i]), NIPQUAD(nxi->mask[i]));
189         }
190         return length;
191 }
192
193 int proc_nxi_status (struct nx_info *nxi, char *buffer)
194 {
195         int length;
196
197         length = sprintf(buffer,
198                 "UseCnt:\t%d\n"
199                 "Tasks:\t%d\n"
200                 "Flags:\t%016llx\n"
201                 "NCaps:\t%016llx\n"
202                 ,atomic_read(&nxi->nx_usecnt)
203                 ,atomic_read(&nxi->nx_tasks)
204                 ,(unsigned long long)nxi->nx_flags
205                 ,(unsigned long long)nxi->nx_ncaps
206                 );
207         return length;
208 }
209
210
211
212 /* here the inode helpers */
213
214 struct vs_entry {
215         int len;
216         char *name;
217         mode_t mode;
218         struct inode_operations *iop;
219         struct file_operations *fop;
220         union proc_op op;
221 };
222
223 static struct inode *vs_proc_make_inode(struct super_block *sb, struct vs_entry *p)
224 {
225         struct inode *inode = new_inode(sb);
226
227         if (!inode)
228                 goto out;
229
230         inode->i_mode = p->mode;
231         if (p->iop)
232                 inode->i_op = p->iop;
233         if (p->fop)
234                 inode->i_fop = p->fop;
235
236         inode->i_nlink = (p->mode & S_IFDIR) ? 2 : 1;
237         inode->i_flags |= S_IMMUTABLE;
238
239         inode->i_mtime = inode->i_atime = inode->i_ctime = CURRENT_TIME;
240
241         inode->i_uid = 0;
242         inode->i_gid = 0;
243         inode->i_tag = 0;
244 out:
245         return inode;
246 }
247
248 static struct dentry *vs_proc_instantiate(struct inode *dir,
249         struct dentry *dentry, int id, void *ptr)
250 {
251         struct vs_entry *p = ptr;
252         struct inode *inode = vs_proc_make_inode(dir->i_sb, p);
253         struct dentry *error = ERR_PTR(-EINVAL);
254
255         if (!inode)
256                 goto out;
257
258         PROC_I(inode)->op = p->op;
259         PROC_I(inode)->fd = id;
260         d_add(dentry, inode);
261         error = NULL;
262 out:
263         return error;
264 }
265
266 /* Lookups */
267
268 typedef struct dentry *instantiate_t(struct inode *, struct dentry *, int, void *);
269
270 /*
271  * Fill a directory entry.
272  *
273  * If possible create the dcache entry and derive our inode number and
274  * file type from dcache entry.
275  *
276  * Since all of the proc inode numbers are dynamically generated, the inode
277  * numbers do not exist until the inode is cache.  This means creating the
278  * the dcache entry in readdir is necessary to keep the inode numbers
279  * reported by readdir in sync with the inode numbers reported
280  * by stat.
281  */
282 static int proc_fill_cache(struct file *filp, void *dirent, filldir_t filldir,
283         char *name, int len, instantiate_t instantiate, int id, void *ptr)
284 {
285         struct dentry *child, *dir = filp->f_dentry;
286         struct inode *inode;
287         struct qstr qname;
288         ino_t ino = 0;
289         unsigned type = DT_UNKNOWN;
290
291         qname.name = name;
292         qname.len  = len;
293         qname.hash = full_name_hash(name, len);
294
295         child = d_lookup(dir, &qname);
296         if (!child) {
297                 struct dentry *new;
298                 new = d_alloc(dir, &qname);
299                 if (new) {
300                         child = instantiate(dir->d_inode, new, id, ptr);
301                         if (child)
302                                 dput(new);
303                         else
304                                 child = new;
305                 }
306         }
307         if (!child || IS_ERR(child) || !child->d_inode)
308                 goto end_instantiate;
309         inode = child->d_inode;
310         if (inode) {
311                 ino = inode->i_ino;
312                 type = inode->i_mode >> 12;
313         }
314         dput(child);
315 end_instantiate:
316         if (!ino)
317                 ino = find_inode_number(dir, &qname);
318         if (!ino)
319                 ino = 1;
320         return filldir(dirent, name, len, filp->f_pos, ino, type);
321 }
322
323
324
325 /* get and revalidate vx_info/xid */
326
327 static inline
328 struct vx_info *get_proc_vx_info(struct inode *inode)
329 {
330         return lookup_vx_info(PROC_I(inode)->fd);
331 }
332
333 static int proc_xid_revalidate(struct dentry * dentry, struct nameidata *nd)
334 {
335         struct inode *inode = dentry->d_inode;
336         xid_t xid = PROC_I(inode)->fd;
337
338         if (!xid || xid_is_hashed(xid))
339                 return 1;
340         d_drop(dentry);
341         return 0;
342 }
343
344
345 /* get and revalidate nx_info/nid */
346
347 static int proc_nid_revalidate(struct dentry * dentry, struct nameidata *nd)
348 {
349         struct inode *inode = dentry->d_inode;
350         nid_t nid = PROC_I(inode)->fd;
351
352         if (!nid || nid_is_hashed(nid))
353                 return 1;
354         d_drop(dentry);
355         return 0;
356 }
357
358
359
360 #define PROC_BLOCK_SIZE (PAGE_SIZE - 1024)
361
362 static ssize_t proc_vs_info_read(struct file * file, char __user * buf,
363                           size_t count, loff_t *ppos)
364 {
365         struct inode *inode = file->f_dentry->d_inode;
366         unsigned long page;
367         ssize_t length = 0;
368
369         if (count > PROC_BLOCK_SIZE)
370                 count = PROC_BLOCK_SIZE;
371
372         /* fade that out as soon as stable */
373         WARN_ON(PROC_I(inode)->fd);
374
375         if (!(page = __get_free_page(GFP_KERNEL)))
376                 return -ENOMEM;
377
378         BUG_ON(!PROC_I(inode)->op.proc_vs_read);
379         length = PROC_I(inode)->op.proc_vs_read((char*)page);
380
381         if (length >= 0)
382                 length = simple_read_from_buffer(buf, count, ppos,
383                         (char *)page, length);
384
385         free_page(page);
386         return length;
387 }
388
389 static ssize_t proc_vx_info_read(struct file * file, char __user * buf,
390                           size_t count, loff_t *ppos)
391 {
392         struct inode *inode = file->f_dentry->d_inode;
393         struct vx_info *vxi = NULL;
394         xid_t xid = PROC_I(inode)->fd;
395         unsigned long page;
396         ssize_t length = 0;
397
398         if (count > PROC_BLOCK_SIZE)
399                 count = PROC_BLOCK_SIZE;
400
401         /* fade that out as soon as stable */
402         WARN_ON(!xid);
403         vxi = lookup_vx_info(xid);
404         if (!vxi)
405                 goto out;
406
407         length = -ENOMEM;
408         if (!(page = __get_free_page(GFP_KERNEL)))
409                 goto out_put;
410
411         BUG_ON(!PROC_I(inode)->op.proc_vxi_read);
412         length = PROC_I(inode)->op.proc_vxi_read(vxi, (char*)page);
413
414         if (length >= 0)
415                 length = simple_read_from_buffer(buf, count, ppos,
416                         (char *)page, length);
417
418         free_page(page);
419 out_put:
420         put_vx_info(vxi);
421 out:
422         return length;
423 }
424
425 static ssize_t proc_nx_info_read(struct file * file, char __user * buf,
426                           size_t count, loff_t *ppos)
427 {
428         struct inode *inode = file->f_dentry->d_inode;
429         struct nx_info *nxi = NULL;
430         nid_t nid = PROC_I(inode)->fd;
431         unsigned long page;
432         ssize_t length = 0;
433
434         if (count > PROC_BLOCK_SIZE)
435                 count = PROC_BLOCK_SIZE;
436
437         /* fade that out as soon as stable */
438         WARN_ON(!nid);
439         nxi = lookup_nx_info(nid);
440         if (!nxi)
441                 goto out;
442
443         length = -ENOMEM;
444         if (!(page = __get_free_page(GFP_KERNEL)))
445                 goto out_put;
446
447         BUG_ON(!PROC_I(inode)->op.proc_nxi_read);
448         length = PROC_I(inode)->op.proc_nxi_read(nxi, (char*)page);
449
450         if (length >= 0)
451                 length = simple_read_from_buffer(buf, count, ppos,
452                         (char *)page, length);
453
454         free_page(page);
455 out_put:
456         put_nx_info(nxi);
457 out:
458         return length;
459 }
460
461
462
463 /* here comes the lower level */
464
465
466 #define NOD(NAME, MODE, IOP, FOP, OP) { \
467         .len  = sizeof(NAME) - 1,       \
468         .name = (NAME),                 \
469         .mode = MODE,                   \
470         .iop  = IOP,                    \
471         .fop  = FOP,                    \
472         .op   = OP,                     \
473 }
474
475
476 #define DIR(NAME, MODE, OTYPE)                          \
477         NOD(NAME, (S_IFDIR|(MODE)),                     \
478                 &proc_##OTYPE##_inode_operations,       \
479                 &proc_##OTYPE##_file_operations, { } )
480
481 #define INF(NAME, MODE, OTYPE)                          \
482         NOD(NAME, (S_IFREG|(MODE)), NULL,               \
483                 &proc_vs_info_file_operations,          \
484                 { .proc_vs_read = &proc_##OTYPE } )
485
486 #define VINF(NAME, MODE, OTYPE)                         \
487         NOD(NAME, (S_IFREG|(MODE)), NULL,               \
488                 &proc_vx_info_file_operations,          \
489                 { .proc_vxi_read = &proc_##OTYPE } )
490
491 #define NINF(NAME, MODE, OTYPE)                         \
492         NOD(NAME, (S_IFREG|(MODE)), NULL,               \
493                 &proc_nx_info_file_operations,          \
494                 { .proc_nxi_read = &proc_##OTYPE } )
495
496
497 static struct file_operations proc_vs_info_file_operations = {
498         .read =         proc_vs_info_read,
499 };
500
501 static struct file_operations proc_vx_info_file_operations = {
502         .read =         proc_vx_info_read,
503 };
504
505 static struct dentry_operations proc_xid_dentry_operations = {
506         .d_revalidate = proc_xid_revalidate,
507 };
508
509 static struct vs_entry vx_base_stuff[] = {
510         VINF("info",    S_IRUGO, vxi_info),
511         VINF("status",  S_IRUGO, vxi_status),
512         VINF("limit",   S_IRUGO, vxi_limit),
513         VINF("sched",   S_IRUGO, vxi_sched),
514         VINF("nsproxy", S_IRUGO, vxi_nsproxy),
515         VINF("cvirt",   S_IRUGO, vxi_cvirt),
516         VINF("cacct",   S_IRUGO, vxi_cacct),
517         {}
518 };
519
520
521
522
523 static struct dentry *proc_xid_instantiate(struct inode *dir,
524         struct dentry *dentry, int id, void *ptr)
525 {
526         dentry->d_op = &proc_xid_dentry_operations;
527         return vs_proc_instantiate(dir, dentry, id, ptr);
528 }
529
530 static struct dentry *proc_xid_lookup(struct inode *dir,
531         struct dentry *dentry, struct nameidata *nd)
532 {
533         struct vs_entry *p = vx_base_stuff;
534         struct dentry *error = ERR_PTR(-ENOENT);
535
536         for (; p->name; p++) {
537                 if (p->len != dentry->d_name.len)
538                         continue;
539                 if (!memcmp(dentry->d_name.name, p->name, p->len))
540                         break;
541         }
542         if (!p->name)
543                 goto out;
544
545         error = proc_xid_instantiate(dir, dentry, PROC_I(dir)->fd, p);
546 out:
547         return error;
548 }
549
550 static int proc_xid_readdir(struct file * filp,
551         void * dirent, filldir_t filldir)
552 {
553         struct dentry *dentry = filp->f_dentry;
554         struct inode *inode = dentry->d_inode;
555         struct vs_entry *p = vx_base_stuff;
556         int size = sizeof(vx_base_stuff)/sizeof(struct vs_entry);
557         int pos, index;
558         u64 ino;
559
560         pos = filp->f_pos;
561         switch (pos) {
562         case 0:
563                 ino = inode->i_ino;
564                 if (filldir(dirent, ".", 1, pos, ino, DT_DIR) < 0)
565                         goto out;
566                 pos++;
567                 /* fall through */
568         case 1:
569                 ino = parent_ino(dentry);
570                 if (filldir(dirent, "..", 2, pos, ino, DT_DIR) < 0)
571                         goto out;
572                 pos++;
573                 /* fall through */
574         default:
575                 index = pos - 2;
576                 if (index >= size)
577                         goto out;
578                 for (p += index; p->name; p++) {
579                         if (proc_fill_cache(filp, dirent, filldir, p->name, p->len,
580                                 vs_proc_instantiate, PROC_I(inode)->fd, p))
581                                 goto out;
582                         pos++;
583                 }
584         }
585 out:
586         filp->f_pos = pos;
587         return 1;
588 }
589
590
591
592 static struct file_operations proc_nx_info_file_operations = {
593         .read =         proc_nx_info_read,
594 };
595
596 static struct dentry_operations proc_nid_dentry_operations = {
597         .d_revalidate = proc_nid_revalidate,
598 };
599
600 static struct vs_entry nx_base_stuff[] = {
601         NINF("info",    S_IRUGO, nxi_info),
602         NINF("status",  S_IRUGO, nxi_status),
603         {}
604 };
605
606
607 static struct dentry *proc_nid_instantiate(struct inode *dir,
608         struct dentry *dentry, int id, void *ptr)
609 {
610         dentry->d_op = &proc_nid_dentry_operations;
611         return vs_proc_instantiate(dir, dentry, id, ptr);
612 }
613
614 static struct dentry *proc_nid_lookup(struct inode *dir,
615         struct dentry *dentry, struct nameidata *nd)
616 {
617         struct vs_entry *p = nx_base_stuff;
618         struct dentry *error = ERR_PTR(-ENOENT);
619
620         for (; p->name; p++) {
621                 if (p->len != dentry->d_name.len)
622                         continue;
623                 if (!memcmp(dentry->d_name.name, p->name, p->len))
624                         break;
625         }
626         if (!p->name)
627                 goto out;
628
629         error = proc_nid_instantiate(dir, dentry, PROC_I(dir)->fd, p);
630 out:
631         return error;
632 }
633
634 static int proc_nid_readdir(struct file * filp,
635         void * dirent, filldir_t filldir)
636 {
637         struct dentry *dentry = filp->f_dentry;
638         struct inode *inode = dentry->d_inode;
639         struct vs_entry *p = nx_base_stuff;
640         int size = sizeof(nx_base_stuff)/sizeof(struct vs_entry);
641         int pos, index;
642         u64 ino;
643
644         pos = filp->f_pos;
645         switch (pos) {
646         case 0:
647                 ino = inode->i_ino;
648                 if (filldir(dirent, ".", 1, pos, ino, DT_DIR) < 0)
649                         goto out;
650                 pos++;
651                 /* fall through */
652         case 1:
653                 ino = parent_ino(dentry);
654                 if (filldir(dirent, "..", 2, pos, ino, DT_DIR) < 0)
655                         goto out;
656                 pos++;
657                 /* fall through */
658         default:
659                 index = pos - 2;
660                 if (index >= size)
661                         goto out;
662                 for (p += index; p->name; p++) {
663                         if (proc_fill_cache(filp, dirent, filldir, p->name, p->len,
664                                 vs_proc_instantiate, PROC_I(inode)->fd, p))
665                                 goto out;
666                         pos++;
667                 }
668         }
669 out:
670         filp->f_pos = pos;
671         return 1;
672 }
673
674
675 #define MAX_MULBY10     ((~0U-9)/10)
676
677 static inline int atovid(const char *str, int len)
678 {
679         int vid, c;
680
681         vid = 0;
682         while (len-- > 0) {
683                 c = *str - '0';
684                 str++;
685                 if (c > 9)
686                         return -1;
687                 if (vid >= MAX_MULBY10)
688                         return -1;
689                 vid *= 10;
690                 vid += c;
691                 if (!vid)
692                         return -1;
693         }
694         return vid;
695 }
696
697 /* now the upper level (virtual) */
698
699
700 static struct file_operations proc_xid_file_operations = {
701         .read =         generic_read_dir,
702         .readdir =      proc_xid_readdir,
703 };
704
705 static struct inode_operations proc_xid_inode_operations = {
706         .lookup =       proc_xid_lookup,
707 };
708
709 static struct vs_entry vx_virtual_stuff[] = {
710         INF("info",     S_IRUGO, virtual_info),
711         INF("status",   S_IRUGO, virtual_status),
712         DIR(NULL,       S_IRUGO|S_IXUGO, xid),
713 };
714
715
716 static struct dentry *proc_virtual_lookup(struct inode *dir,
717         struct dentry *dentry, struct nameidata *nd)
718 {
719         struct vs_entry *p = vx_virtual_stuff;
720         struct dentry *error = ERR_PTR(-ENOENT);
721         int id = 0;
722
723         for (; p->name; p++) {
724                 if (p->len != dentry->d_name.len)
725                         continue;
726                 if (!memcmp(dentry->d_name.name, p->name, p->len))
727                         break;
728         }
729         if (p->name)
730                 goto instantiate;
731
732         id = atovid(dentry->d_name.name, dentry->d_name.len);
733         if ((id < 0) || !xid_is_hashed(id))
734                 goto out;
735
736 instantiate:
737         error = proc_xid_instantiate(dir, dentry, id, p);
738 out:
739         return error;
740 }
741
742 static struct file_operations proc_nid_file_operations = {
743         .read =         generic_read_dir,
744         .readdir =      proc_nid_readdir,
745 };
746
747 static struct inode_operations proc_nid_inode_operations = {
748         .lookup =       proc_nid_lookup,
749 };
750
751 static struct vs_entry nx_virtnet_stuff[] = {
752         INF("info",     S_IRUGO, virtnet_info),
753         INF("status",   S_IRUGO, virtnet_status),
754         DIR(NULL,       S_IRUGO|S_IXUGO, nid),
755 };
756
757
758 static struct dentry *proc_virtnet_lookup(struct inode *dir,
759         struct dentry *dentry, struct nameidata *nd)
760 {
761         struct vs_entry *p = nx_virtnet_stuff;
762         struct dentry *error = ERR_PTR(-ENOENT);
763         int id = 0;
764
765         for (; p->name; p++) {
766                 if (p->len != dentry->d_name.len)
767                         continue;
768                 if (!memcmp(dentry->d_name.name, p->name, p->len))
769                         break;
770         }
771         if (p->name)
772                 goto instantiate;
773
774         id = atovid(dentry->d_name.name, dentry->d_name.len);
775         if ((id < 0) || !nid_is_hashed(id))
776                 goto out;
777
778 instantiate:
779         error = proc_nid_instantiate(dir, dentry, id, p);
780 out:
781         return error;
782 }
783
784
785
786 #define PROC_NUMBUF 10
787 #define PROC_MAXVIDS 32
788
789 int proc_virtual_readdir(struct file * filp,
790         void * dirent, filldir_t filldir)
791 {
792         struct dentry *dentry = filp->f_dentry;
793         struct inode *inode = dentry->d_inode;
794         struct vs_entry *p = vx_virtual_stuff;
795         int size = sizeof(vx_virtual_stuff)/sizeof(struct vs_entry);
796         int pos, index;
797         unsigned int xid_array[PROC_MAXVIDS];
798         char buf[PROC_NUMBUF];
799         unsigned int nr_xids, i;
800         u64 ino;
801
802         pos = filp->f_pos;
803         switch (pos) {
804         case 0:
805                 ino = inode->i_ino;
806                 if (filldir(dirent, ".", 1, pos, ino, DT_DIR) < 0)
807                         goto out;
808                 pos++;
809                 /* fall through */
810         case 1:
811                 ino = parent_ino(dentry);
812                 if (filldir(dirent, "..", 2, pos, ino, DT_DIR) < 0)
813                         goto out;
814                 pos++;
815                 /* fall through */
816         default:
817                 index = pos - 2;
818                 if (index >= size)
819                         goto entries;
820                 for (p += index; p->name; p++) {
821                         if (proc_fill_cache(filp, dirent, filldir, p->name, p->len,
822                                 vs_proc_instantiate, 0, p))
823                                 goto out;
824                         pos++;
825                 }
826         entries:
827                 index = pos - size;
828                 p = &vx_virtual_stuff[size-1];
829                 nr_xids = get_xid_list(index, xid_array, PROC_MAXVIDS);
830                 for (i = 0; i < nr_xids; i++) {
831                         int n, xid = xid_array[i];
832                         unsigned int j = PROC_NUMBUF;
833
834                         n = xid;
835                         do buf[--j] = '0' + (n % 10); while (n /= 10);
836
837                         if (proc_fill_cache(filp, dirent, filldir, buf+j, PROC_NUMBUF-j,
838                                 vs_proc_instantiate, xid, p))
839                                 goto out;
840                         pos++;
841                 }
842         }
843 out:
844         filp->f_pos = pos;
845         return 0;
846 }
847
848 static int proc_virtual_getattr(struct vfsmount *mnt,
849         struct dentry *dentry, struct kstat *stat)
850 {
851         struct inode *inode = dentry->d_inode;
852
853         generic_fillattr(inode, stat);
854         stat->nlink = 2 + atomic_read(&vx_global_cactive);
855         return 0;
856 }
857
858 static struct file_operations proc_virtual_dir_operations = {
859         .read =         generic_read_dir,
860         .readdir =      proc_virtual_readdir,
861 };
862
863 static struct inode_operations proc_virtual_dir_inode_operations = {
864         .getattr =      proc_virtual_getattr,
865         .lookup =       proc_virtual_lookup,
866 };
867
868
869
870
871
872 int proc_virtnet_readdir(struct file * filp,
873         void * dirent, filldir_t filldir)
874 {
875         struct dentry *dentry = filp->f_dentry;
876         struct inode *inode = dentry->d_inode;
877         struct vs_entry *p = nx_virtnet_stuff;
878         int size = sizeof(nx_virtnet_stuff)/sizeof(struct vs_entry);
879         int pos, index;
880         unsigned int nid_array[PROC_MAXVIDS];
881         char buf[PROC_NUMBUF];
882         unsigned int nr_nids, i;
883         u64 ino;
884
885         pos = filp->f_pos;
886         switch (pos) {
887         case 0:
888                 ino = inode->i_ino;
889                 if (filldir(dirent, ".", 1, pos, ino, DT_DIR) < 0)
890                         goto out;
891                 pos++;
892                 /* fall through */
893         case 1:
894                 ino = parent_ino(dentry);
895                 if (filldir(dirent, "..", 2, pos, ino, DT_DIR) < 0)
896                         goto out;
897                 pos++;
898                 /* fall through */
899         default:
900                 index = pos - 2;
901                 if (index >= size)
902                         goto entries;
903                 for (p += index; p->name; p++) {
904                         if (proc_fill_cache(filp, dirent, filldir, p->name, p->len,
905                                 vs_proc_instantiate, 0, p))
906                                 goto out;
907                         pos++;
908                 }
909         entries:
910                 index = pos - size;
911                 p = &nx_virtnet_stuff[size-1];
912                 nr_nids = get_nid_list(index, nid_array, PROC_MAXVIDS);
913                 for (i = 0; i < nr_nids; i++) {
914                         int n, nid = nid_array[i];
915                         unsigned int j = PROC_NUMBUF;
916
917                         n = nid;
918                         do buf[--j] = '0' + (n % 10); while (n /= 10);
919
920                         if (proc_fill_cache(filp, dirent, filldir, buf+j, PROC_NUMBUF-j,
921                                 vs_proc_instantiate, nid, p))
922                                 goto out;
923                         pos++;
924                 }
925         }
926 out:
927         filp->f_pos = pos;
928         return 0;
929 }
930
931 static int proc_virtnet_getattr(struct vfsmount *mnt,
932         struct dentry *dentry, struct kstat *stat)
933 {
934         struct inode *inode = dentry->d_inode;
935
936         generic_fillattr(inode, stat);
937         stat->nlink = 2 + atomic_read(&nx_global_cactive);
938         return 0;
939 }
940
941 static struct file_operations proc_virtnet_dir_operations = {
942         .read =         generic_read_dir,
943         .readdir =      proc_virtnet_readdir,
944 };
945
946 static struct inode_operations proc_virtnet_dir_inode_operations = {
947         .getattr =      proc_virtnet_getattr,
948         .lookup =       proc_virtnet_lookup,
949 };
950
951
952
953 void proc_vx_init(void)
954 {
955         struct proc_dir_entry *ent;
956
957         ent = proc_mkdir("virtual", 0);
958         if (ent) {
959                 ent->proc_fops = &proc_virtual_dir_operations;
960                 ent->proc_iops = &proc_virtual_dir_inode_operations;
961         }
962         proc_virtual = ent;
963
964         ent = proc_mkdir("virtnet", 0);
965         if (ent) {
966                 ent->proc_fops = &proc_virtnet_dir_operations;
967                 ent->proc_iops = &proc_virtnet_dir_inode_operations;
968         }
969         proc_virtnet = ent;
970 }
971
972
973
974
975 /* per pid info */
976
977
978 int proc_pid_vx_info(struct task_struct *p, char *buffer)
979 {
980         struct vx_info *vxi;
981         char * orig = buffer;
982
983         buffer += sprintf (buffer,"XID:\t%d\n", vx_task_xid(p));
984
985         vxi = task_get_vx_info(p);
986         if (!vxi)
987                 goto out;
988
989         buffer += sprintf (buffer,"BCaps:\t%016llx\n"
990                 ,(unsigned long long)vxi->vx_bcaps);
991         buffer += sprintf (buffer,"CCaps:\t%016llx\n"
992                 ,(unsigned long long)vxi->vx_ccaps);
993         buffer += sprintf (buffer,"CFlags:\t%016llx\n"
994                 ,(unsigned long long)vxi->vx_flags);
995         buffer += sprintf (buffer,"CIPid:\t%d\n"
996                 ,vxi->vx_initpid);
997
998         put_vx_info(vxi);
999 out:
1000         return buffer - orig;
1001 }
1002
1003
1004 int proc_pid_nx_info(struct task_struct *p, char *buffer)
1005 {
1006         struct nx_info *nxi;
1007         char * orig = buffer;
1008         int i;
1009
1010         buffer += sprintf (buffer,"NID:\t%d\n", nx_task_nid(p));
1011
1012         nxi = task_get_nx_info(p);
1013         if (!nxi)
1014                 goto out;
1015
1016         buffer += sprintf (buffer,"NCaps:\t%016llx\n"
1017                 ,(unsigned long long)nxi->nx_ncaps);
1018         buffer += sprintf (buffer,"NFlags:\t%016llx\n"
1019                 ,(unsigned long long)nxi->nx_flags);
1020
1021         for (i=0; i<nxi->nbipv4; i++){
1022                 buffer += sprintf (buffer,
1023                         "V4Root[%d]:\t%d.%d.%d.%d/%d.%d.%d.%d\n", i
1024                         ,NIPQUAD(nxi->ipv4[i])
1025                         ,NIPQUAD(nxi->mask[i]));
1026         }
1027         buffer += sprintf (buffer,
1028                 "V4Root[bcast]:\t%d.%d.%d.%d\n"
1029                 ,NIPQUAD(nxi->v4_bcast));
1030
1031         put_nx_info(nxi);
1032 out:
1033         return buffer - orig;
1034 }
1035