b16949bca2ab3dca5c9b8c8db9fad42370a64135
[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-2005  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  *
16  */
17
18 #include <linux/errno.h>
19 #include <linux/proc_fs.h>
20 #include <linux/sched.h>
21 #include <linux/vs_context.h>
22 #include <linux/vs_network.h>
23 #include <linux/vs_cvirt.h>
24
25 #include <linux/vserver/switch.h>
26
27 #include <asm/uaccess.h>
28 #include <asm/unistd.h>
29
30 #include "cvirt_proc.h"
31 #include "limit_proc.h"
32 #include "sched_proc.h"
33 #include "vci_config.h"
34
35 static struct proc_dir_entry *proc_virtual;
36
37 static struct proc_dir_entry *proc_vnet;
38
39
40 enum vid_directory_inos {
41         PROC_XID_INO = 32,
42         PROC_XID_INFO,
43         PROC_XID_STATUS,
44         PROC_XID_LIMIT,
45         PROC_XID_SCHED,
46         PROC_XID_CVIRT,
47         PROC_XID_CACCT,
48
49         PROC_NID_INO = 64,
50         PROC_NID_INFO,
51         PROC_NID_STATUS,
52 };
53
54 #define PROC_VID_MASK   0x60
55
56
57 /* first the actual feeds */
58
59
60 static int proc_virtual_info(int vid, char *buffer)
61 {
62         return sprintf(buffer,
63                 "VCIVersion:\t%04x:%04x\n"
64                 "VCISyscall:\t%d\n"
65                 "VCIKernel:\t%08x\n"
66                 ,VCI_VERSION >> 16
67                 ,VCI_VERSION & 0xFFFF
68                 ,__NR_vserver
69                 ,vci_kernel_config()
70                 );
71 }
72
73
74 int proc_xid_info (int vid, char *buffer)
75 {
76         struct vx_info *vxi;
77         int length;
78
79         vxi = lookup_vx_info(vid);
80         if (!vxi)
81                 return 0;
82         length = sprintf(buffer,
83                 "ID:\t%d\n"
84                 "Info:\t%p\n"
85                 "Init:\t%d\n"
86                 ,vxi->vx_id
87                 ,vxi
88                 ,vxi->vx_initpid
89                 );
90         put_vx_info(vxi);
91         return length;
92 }
93
94 int proc_xid_status (int vid, char *buffer)
95 {
96         struct vx_info *vxi;
97         int length;
98
99         vxi = lookup_vx_info(vid);
100         if (!vxi)
101                 return 0;
102         length = sprintf(buffer,
103                 "UseCnt:\t%d\n"
104                 "Tasks:\t%d\n"
105                 "Flags:\t%016llx\n"
106                 "BCaps:\t%016llx\n"
107                 "CCaps:\t%016llx\n"
108                 "Ticks:\t%d\n"
109                 ,atomic_read(&vxi->vx_usecnt)
110                 ,atomic_read(&vxi->vx_tasks)
111                 ,(unsigned long long)vxi->vx_flags
112                 ,(unsigned long long)vxi->vx_bcaps
113                 ,(unsigned long long)vxi->vx_ccaps
114                 ,atomic_read(&vxi->limit.ticks)
115                 );
116         put_vx_info(vxi);
117         return length;
118 }
119
120 int proc_xid_limit (int vid, char *buffer)
121 {
122         struct vx_info *vxi;
123         int length;
124
125         vxi = lookup_vx_info(vid);
126         if (!vxi)
127                 return 0;
128         length = vx_info_proc_limit(&vxi->limit, buffer);
129         put_vx_info(vxi);
130         return length;
131 }
132
133 int proc_xid_sched (int vid, char *buffer)
134 {
135         struct vx_info *vxi;
136         int length;
137
138         vxi = lookup_vx_info(vid);
139         if (!vxi)
140                 return 0;
141         length = vx_info_proc_sched(&vxi->sched, buffer);
142         put_vx_info(vxi);
143         return length;
144 }
145
146 int proc_xid_cvirt (int vid, char *buffer)
147 {
148         struct vx_info *vxi;
149         int length;
150
151         vxi = lookup_vx_info(vid);
152         if (!vxi)
153                 return 0;
154         vx_update_load(vxi);
155         length = vx_info_proc_cvirt(&vxi->cvirt, buffer);
156         put_vx_info(vxi);
157         return length;
158 }
159
160 int proc_xid_cacct (int vid, char *buffer)
161 {
162         struct vx_info *vxi;
163         int length;
164
165         vxi = lookup_vx_info(vid);
166         if (!vxi)
167                 return 0;
168         length = vx_info_proc_cacct(&vxi->cacct, buffer);
169         put_vx_info(vxi);
170         return length;
171 }
172
173
174 static int proc_vnet_info(int vid, char *buffer)
175 {
176         return sprintf(buffer,
177                 "VCIVersion:\t%04x:%04x\n"
178                 "VCISyscall:\t%d\n"
179                 ,VCI_VERSION >> 16
180                 ,VCI_VERSION & 0xFFFF
181                 ,__NR_vserver
182                 );
183 }
184
185
186 int proc_nid_info (int vid, char *buffer)
187 {
188         struct nx_info *nxi;
189         int length, i;
190
191         nxi = lookup_nx_info(vid);
192         if (!nxi)
193                 return 0;
194         length = sprintf(buffer,
195                 "ID:\t%d\n"
196                 "Info:\t%p\n"
197                 ,nxi->nx_id
198                 ,nxi
199                 );
200         for (i=0; i<nxi->nbipv4; i++) {
201                 length += sprintf(buffer + length,
202                         "%d:\t" NIPQUAD_FMT "/" NIPQUAD_FMT "\n", i,
203                         NIPQUAD(nxi->ipv4[i]), NIPQUAD(nxi->mask[i]));
204         }
205         put_nx_info(nxi);
206         return length;
207 }
208
209 int proc_nid_status (int vid, char *buffer)
210 {
211         struct nx_info *nxi;
212         int length;
213
214         nxi = lookup_nx_info(vid);
215         if (!nxi)
216                 return 0;
217         length = sprintf(buffer,
218                 "UseCnt:\t%d\n"
219                 "Tasks:\t%d\n"
220                 ,atomic_read(&nxi->nx_usecnt)
221                 ,atomic_read(&nxi->nx_tasks)
222                 );
223         put_nx_info(nxi);
224         return length;
225 }
226
227 /* here the inode helpers */
228
229
230 #define fake_ino(id,nr) (((nr) & 0xFFFF) | \
231                         (((id) & 0xFFFF) << 16))
232
233 #define inode_vid(i)    (((i)->i_ino >> 16) & 0xFFFF)
234 #define inode_type(i)   ((i)->i_ino & 0xFFFF)
235
236 #define MAX_MULBY10     ((~0U-9)/10)
237
238
239 static struct inode *proc_vid_make_inode(struct super_block * sb,
240         int vid, int ino)
241 {
242         struct inode *inode = new_inode(sb);
243
244         if (!inode)
245                 goto out;
246
247         inode->i_mtime = inode->i_atime =
248                 inode->i_ctime = CURRENT_TIME;
249         inode->i_ino = fake_ino(vid, ino);
250
251         inode->i_uid = 0;
252         inode->i_gid = 0;
253 out:
254         return inode;
255 }
256
257 static int proc_vid_revalidate(struct dentry * dentry, struct nameidata *nd)
258 {
259         struct inode * inode = dentry->d_inode;
260         int vid, hashed=0;
261
262         vid = inode_vid(inode);
263         switch (inode_type(inode) & PROC_VID_MASK) {
264                 case PROC_XID_INO:
265                         hashed = xid_is_hashed(vid);
266                         break;
267                 case PROC_NID_INO:
268                         hashed = nid_is_hashed(vid);
269                         break;
270         }
271         if (hashed)
272                 return 1;
273         d_drop(dentry);
274         return 0;
275 }
276
277
278 #define PROC_BLOCK_SIZE (PAGE_SIZE - 1024)
279
280 static ssize_t proc_vid_info_read(struct file * file, char __user * buf,
281                           size_t count, loff_t *ppos)
282 {
283         struct inode * inode = file->f_dentry->d_inode;
284         unsigned long page;
285         ssize_t length;
286         int vid;
287
288         if (count > PROC_BLOCK_SIZE)
289                 count = PROC_BLOCK_SIZE;
290         if (!(page = __get_free_page(GFP_KERNEL)))
291                 return -ENOMEM;
292
293         vid = inode_vid(inode);
294         length = PROC_I(inode)->op.proc_vid_read(vid, (char*)page);
295
296         if (length >= 0)
297                 length = simple_read_from_buffer(buf, count, ppos,
298                         (char *)page, length);
299         free_page(page);
300         return length;
301 }
302
303
304
305
306
307 /* here comes the lower level (vid) */
308
309 static struct file_operations proc_vid_info_file_operations = {
310         .read =         proc_vid_info_read,
311 };
312
313 static struct dentry_operations proc_vid_dentry_operations = {
314         .d_revalidate = proc_vid_revalidate,
315 };
316
317
318 struct vid_entry {
319         int type;
320         int len;
321         char *name;
322         mode_t mode;
323 };
324
325 #define E(type,name,mode) {(type),sizeof(name)-1,(name),(mode)}
326
327 static struct vid_entry vx_base_stuff[] = {
328         E(PROC_XID_INFO,        "info",         S_IFREG|S_IRUGO),
329         E(PROC_XID_STATUS,      "status",       S_IFREG|S_IRUGO),
330         E(PROC_XID_LIMIT,       "limit",        S_IFREG|S_IRUGO),
331         E(PROC_XID_SCHED,       "sched",        S_IFREG|S_IRUGO),
332         E(PROC_XID_CVIRT,       "cvirt",        S_IFREG|S_IRUGO),
333         E(PROC_XID_CACCT,       "cacct",        S_IFREG|S_IRUGO),
334         {0,0,NULL,0}
335 };
336
337 static struct vid_entry vn_base_stuff[] = {
338         E(PROC_NID_INFO,        "info",         S_IFREG|S_IRUGO),
339         E(PROC_NID_STATUS,      "status",       S_IFREG|S_IRUGO),
340         {0,0,NULL,0}
341 };
342
343
344
345 static struct dentry *proc_vid_lookup(struct inode *dir,
346         struct dentry *dentry, struct nameidata *nd)
347 {
348         struct inode *inode;
349         struct vid_entry *p;
350         int error;
351
352         error = -ENOENT;
353         inode = NULL;
354
355         switch (inode_type(dir)) {
356                 case PROC_XID_INO:
357                         p = vx_base_stuff;
358                         break;
359                 case PROC_NID_INO:
360                         p = vn_base_stuff;
361                         break;
362                 default:
363                         goto out;
364         }
365
366         for (; p->name; p++) {
367                 if (p->len != dentry->d_name.len)
368                         continue;
369                 if (!memcmp(dentry->d_name.name, p->name, p->len))
370                         break;
371         }
372         if (!p->name)
373                 goto out;
374
375         error = -EINVAL;
376         inode = proc_vid_make_inode(dir->i_sb, inode_vid(dir), p->type);
377         if (!inode)
378                 goto out;
379
380         switch(p->type) {
381                 case PROC_XID_INFO:
382                         PROC_I(inode)->op.proc_vid_read = proc_xid_info;
383                         break;
384                 case PROC_XID_STATUS:
385                         PROC_I(inode)->op.proc_vid_read = proc_xid_status;
386                         break;
387                 case PROC_XID_LIMIT:
388                         PROC_I(inode)->op.proc_vid_read = proc_xid_limit;
389                         break;
390                 case PROC_XID_SCHED:
391                         PROC_I(inode)->op.proc_vid_read = proc_xid_sched;
392                         break;
393                 case PROC_XID_CVIRT:
394                         PROC_I(inode)->op.proc_vid_read = proc_xid_cvirt;
395                         break;
396                 case PROC_XID_CACCT:
397                         PROC_I(inode)->op.proc_vid_read = proc_xid_cacct;
398                         break;
399
400                 case PROC_NID_INFO:
401                         PROC_I(inode)->op.proc_vid_read = proc_nid_info;
402                         break;
403                 case PROC_NID_STATUS:
404                         PROC_I(inode)->op.proc_vid_read = proc_nid_status;
405                         break;
406
407                 default:
408                         printk("procfs: impossible type (%d)",p->type);
409                         iput(inode);
410                         return ERR_PTR(-EINVAL);
411         }
412         inode->i_mode = p->mode;
413         inode->i_fop = &proc_vid_info_file_operations;
414         inode->i_nlink = 1;
415         inode->i_flags|=S_IMMUTABLE;
416
417         dentry->d_op = &proc_vid_dentry_operations;
418         d_add(dentry, inode);
419         error = 0;
420 out:
421         return ERR_PTR(error);
422 }
423
424
425 static int proc_vid_readdir(struct file * filp,
426         void * dirent, filldir_t filldir)
427 {
428         int i, size;
429         struct inode *inode = filp->f_dentry->d_inode;
430         struct vid_entry *p;
431
432         i = filp->f_pos;
433         switch (i) {
434         case 0:
435                 if (filldir(dirent, ".", 1, i,
436                         inode->i_ino, DT_DIR) < 0)
437                         return 0;
438                 i++;
439                 filp->f_pos++;
440                 /* fall through */
441         case 1:
442                 if (filldir(dirent, "..", 2, i,
443                         PROC_ROOT_INO, DT_DIR) < 0)
444                         return 0;
445                 i++;
446                 filp->f_pos++;
447                 /* fall through */
448         default:
449                 i -= 2;
450                 switch (inode_type(inode)) {
451                         case PROC_XID_INO:
452                                 size = sizeof(vx_base_stuff);
453                                 p = vx_base_stuff + i;
454                                 break;
455                         case PROC_NID_INO:
456                                 size = sizeof(vn_base_stuff);
457                                 p = vn_base_stuff + i;
458                                 break;
459                         default:
460                                 return 1;
461                 }
462                 if (i >= size/sizeof(struct vid_entry))
463                         return 1;
464                 while (p->name) {
465                         if (filldir(dirent, p->name, p->len,
466                                 filp->f_pos, fake_ino(inode_vid(inode),
467                                 p->type), p->mode >> 12) < 0)
468                                 return 0;
469                         filp->f_pos++;
470                         p++;
471                 }
472         }
473         return 1;
474 }
475
476
477
478
479 /* now the upper level (virtual) */
480
481 static struct file_operations proc_vid_file_operations = {
482         .read =         generic_read_dir,
483         .readdir =      proc_vid_readdir,
484 };
485
486 static struct inode_operations proc_vid_inode_operations = {
487         .lookup =       proc_vid_lookup,
488 };
489
490
491
492 static __inline__ int atovid(const char *str, int len)
493 {
494         int vid, c;
495
496         vid = 0;
497         while (len-- > 0) {
498                 c = *str - '0';
499                 str++;
500                 if (c > 9)
501                         return -1;
502                 if (vid >= MAX_MULBY10)
503                         return -1;
504                 vid *= 10;
505                 vid += c;
506                 if (!vid)
507                         return -1;
508         }
509         return vid;
510 }
511
512
513 struct dentry *proc_virtual_lookup(struct inode *dir,
514         struct dentry * dentry, struct nameidata *nd)
515 {
516         int xid, len, ret;
517         struct vx_info *vxi;
518         const char *name;
519         struct inode *inode;
520
521         name = dentry->d_name.name;
522         len = dentry->d_name.len;
523         ret = -ENOMEM;
524
525         if (len == 7 && !memcmp(name, "current", 7)) {
526                 inode = new_inode(dir->i_sb);
527                 if (!inode)
528                         goto out;
529                 inode->i_mtime = inode->i_atime =
530                         inode->i_ctime = CURRENT_TIME;
531                 inode->i_ino = fake_ino(1, PROC_XID_INO);
532                 inode->i_mode = S_IFLNK|S_IRWXUGO;
533                 inode->i_uid = inode->i_gid = 0;
534                 d_add(dentry, inode);
535                 return NULL;
536         }
537         if (len == 4 && !memcmp(name, "info", 4)) {
538                 inode = proc_vid_make_inode(dir->i_sb, 0, PROC_XID_INFO);
539                 if (!inode)
540                         goto out;
541                 inode->i_fop = &proc_vid_info_file_operations;
542                 PROC_I(inode)->op.proc_vid_read = proc_virtual_info;
543                 inode->i_mode = S_IFREG|S_IRUGO;
544                 d_add(dentry, inode);
545                 return NULL;
546         }
547
548         ret = -ENOENT;
549         xid = atovid(name, len);
550         if (xid < 0)
551                 goto out;
552         vxi = lookup_vx_info(xid);
553         if (!vxi)
554                 goto out;
555
556         inode = NULL;
557         if (vx_check(xid, VX_ADMIN|VX_WATCH|VX_IDENT))
558                 inode = proc_vid_make_inode(dir->i_sb,
559                         vxi->vx_id, PROC_XID_INO);
560         if (!inode)
561                 goto out_release;
562
563         inode->i_mode = S_IFDIR|S_IRUGO|S_IXUGO;
564         inode->i_op = &proc_vid_inode_operations;
565         inode->i_fop = &proc_vid_file_operations;
566         inode->i_nlink = 2;
567         inode->i_flags|=S_IMMUTABLE;
568
569         dentry->d_op = &proc_vid_dentry_operations;
570         d_add(dentry, inode);
571         ret = 0;
572
573 out_release:
574         put_vx_info(vxi);
575 out:
576         return ERR_PTR(ret);
577 }
578
579
580 struct dentry *proc_vnet_lookup(struct inode *dir,
581         struct dentry * dentry, struct nameidata *nd)
582 {
583         int nid, len, ret;
584         struct nx_info *nxi;
585         const char *name;
586         struct inode *inode;
587
588         name = dentry->d_name.name;
589         len = dentry->d_name.len;
590         ret = -ENOMEM;
591         if (len == 7 && !memcmp(name, "current", 7)) {
592                 inode = new_inode(dir->i_sb);
593                 if (!inode)
594                         goto out;
595                 inode->i_mtime = inode->i_atime =
596                         inode->i_ctime = CURRENT_TIME;
597                 inode->i_ino = fake_ino(1, PROC_NID_INO);
598                 inode->i_mode = S_IFLNK|S_IRWXUGO;
599                 inode->i_uid = inode->i_gid = 0;
600                 d_add(dentry, inode);
601                 return NULL;
602         }
603         if (len == 4 && !memcmp(name, "info", 4)) {
604                 inode = proc_vid_make_inode(dir->i_sb, 0, PROC_NID_INFO);
605                 if (!inode)
606                         goto out;
607                 inode->i_fop = &proc_vid_info_file_operations;
608                 PROC_I(inode)->op.proc_vid_read = proc_vnet_info;
609                 inode->i_mode = S_IFREG|S_IRUGO;
610                 d_add(dentry, inode);
611                 return NULL;
612         }
613
614         ret = -ENOENT;
615         nid = atovid(name, len);
616         if (nid < 0)
617                 goto out;
618         nxi = lookup_nx_info(nid);
619         if (!nxi)
620                 goto out;
621
622         inode = NULL;
623         if (1)
624                 inode = proc_vid_make_inode(dir->i_sb,
625                         nxi->nx_id, PROC_NID_INO);
626         if (!inode)
627                 goto out_release;
628
629         inode->i_mode = S_IFDIR|S_IRUGO|S_IXUGO;
630         inode->i_op = &proc_vid_inode_operations;
631         inode->i_fop = &proc_vid_file_operations;
632         inode->i_nlink = 2;
633         inode->i_flags|=S_IMMUTABLE;
634
635         dentry->d_op = &proc_vid_dentry_operations;
636         d_add(dentry, inode);
637         ret = 0;
638
639 out_release:
640         put_nx_info(nxi);
641 out:
642         return ERR_PTR(ret);
643 }
644
645
646
647
648 #define PROC_NUMBUF 10
649 #define PROC_MAXVIDS 32
650
651 int proc_virtual_readdir(struct file * filp,
652         void * dirent, filldir_t filldir)
653 {
654         unsigned int xid_array[PROC_MAXVIDS];
655         char buf[PROC_NUMBUF];
656         unsigned int nr = filp->f_pos-3;
657         unsigned int nr_xids, i;
658         ino_t ino;
659
660         switch ((long)filp->f_pos) {
661         case 0:
662                 ino = fake_ino(0, PROC_XID_INO);
663                 if (filldir(dirent, ".", 1,
664                         filp->f_pos, ino, DT_DIR) < 0)
665                         return 0;
666                 filp->f_pos++;
667                 /* fall through */
668         case 1:
669                 ino = filp->f_dentry->d_parent->d_inode->i_ino;
670                 if (filldir(dirent, "..", 2,
671                         filp->f_pos, ino, DT_DIR) < 0)
672                         return 0;
673                 filp->f_pos++;
674                 /* fall through */
675         case 2:
676                 ino = fake_ino(0, PROC_XID_INFO);
677                 if (filldir(dirent, "info", 4,
678                         filp->f_pos, ino, DT_LNK) < 0)
679                         return 0;
680                 filp->f_pos++;
681                 /* fall through */
682         case 3:
683                 if (vx_current_xid() > 1) {
684                         ino = fake_ino(1, PROC_XID_INO);
685                         if (filldir(dirent, "current", 7,
686                                 filp->f_pos, ino, DT_LNK) < 0)
687                                 return 0;
688                 }
689                 filp->f_pos++;
690         }
691
692         nr_xids = get_xid_list(nr, xid_array, PROC_MAXVIDS);
693         for (i = 0; i < nr_xids; i++) {
694                 int xid = xid_array[i];
695                 ino_t ino = fake_ino(xid, PROC_XID_INO);
696                 unsigned int j = PROC_NUMBUF;
697
698                 do buf[--j] = '0' + (xid % 10); while (xid/=10);
699
700                 if (filldir(dirent, buf+j, PROC_NUMBUF-j,
701                         filp->f_pos, ino, DT_DIR) < 0)
702                         break;
703                 filp->f_pos++;
704         }
705         return 0;
706 }
707
708
709 static struct file_operations proc_virtual_dir_operations = {
710         .read =         generic_read_dir,
711         .readdir =      proc_virtual_readdir,
712 };
713
714 static struct inode_operations proc_virtual_dir_inode_operations = {
715         .lookup =       proc_virtual_lookup,
716 };
717
718
719 int proc_vnet_readdir(struct file * filp,
720         void * dirent, filldir_t filldir)
721 {
722         unsigned int nid_array[PROC_MAXVIDS];
723         char buf[PROC_NUMBUF];
724         unsigned int nr = filp->f_pos-2;
725         unsigned int nr_nids, i;
726         ino_t ino;
727
728         switch ((long)filp->f_pos) {
729         case 0:
730                 ino = fake_ino(0, PROC_NID_INO);
731                 if (filldir(dirent, ".", 1,
732                         filp->f_pos, ino, DT_DIR) < 0)
733                         return 0;
734                 filp->f_pos++;
735                 /* fall through */
736         case 1:
737                 ino = filp->f_dentry->d_parent->d_inode->i_ino;
738                 if (filldir(dirent, "..", 2,
739                         filp->f_pos, ino, DT_DIR) < 0)
740                         return 0;
741                 filp->f_pos++;
742                 /* fall through */
743         case 2:
744                 ino = fake_ino(0, PROC_NID_INFO);
745                 if (filldir(dirent, "info", 4,
746                         filp->f_pos, ino, DT_REG) < 0)
747                         return 0;
748                 filp->f_pos++;
749                 /* fall through */
750         }
751
752         nr_nids = get_nid_list(nr, nid_array, PROC_MAXVIDS);
753         for (i = 0; i < nr_nids; i++) {
754                 int nid = nid_array[i];
755                 ino_t ino = fake_ino(nid, PROC_NID_INO);
756                 unsigned long j = PROC_NUMBUF;
757
758                 do buf[--j] = '0' + (nid % 10); while (nid/=10);
759
760                 if (filldir(dirent, buf+j, PROC_NUMBUF-j,
761                         filp->f_pos, ino, DT_DIR) < 0)
762                         break;
763                 filp->f_pos++;
764         }
765         return 0;
766 }
767
768
769 static struct file_operations proc_vnet_dir_operations = {
770         .read =         generic_read_dir,
771         .readdir =      proc_vnet_readdir,
772 };
773
774 static struct inode_operations proc_vnet_dir_inode_operations = {
775         .lookup =       proc_vnet_lookup,
776 };
777
778
779
780 void proc_vx_init(void)
781 {
782         struct proc_dir_entry *ent;
783
784         ent = proc_mkdir("virtual", 0);
785         if (ent) {
786                 ent->proc_fops = &proc_virtual_dir_operations;
787                 ent->proc_iops = &proc_virtual_dir_inode_operations;
788         }
789         proc_virtual = ent;
790
791         ent = proc_mkdir("virtnet", 0);
792         if (ent) {
793                 ent->proc_fops = &proc_vnet_dir_operations;
794                 ent->proc_iops = &proc_vnet_dir_inode_operations;
795         }
796         proc_vnet = ent;
797 }
798
799
800
801
802 /* per pid info */
803
804
805 int proc_pid_vx_info(struct task_struct *p, char *buffer)
806 {
807         struct vx_info *vxi;
808         char * orig = buffer;
809
810         buffer += sprintf (buffer,"XID:\t%d\n", vx_task_xid(p));
811         if (vx_flags(VXF_INFO_HIDE, 0))
812                 goto out;
813
814         vxi = task_get_vx_info(p);
815         if (!vxi)
816                 goto out;
817
818         buffer += sprintf (buffer,"BCaps:\t%016llx\n"
819                 ,(unsigned long long)vxi->vx_bcaps);
820         buffer += sprintf (buffer,"CCaps:\t%016llx\n"
821                 ,(unsigned long long)vxi->vx_ccaps);
822         buffer += sprintf (buffer,"CFlags:\t%016llx\n"
823                 ,(unsigned long long)vxi->vx_flags);
824         buffer += sprintf (buffer,"CIPid:\t%d\n"
825                 ,vxi->vx_initpid);
826
827         put_vx_info(vxi);
828 out:
829         return buffer - orig;
830 }
831
832
833 int proc_pid_nx_info(struct task_struct *p, char *buffer)
834 {
835         struct nx_info *nxi;
836         char * orig = buffer;
837         int i;
838
839         buffer += sprintf (buffer,"NID:\t%d\n", nx_task_nid(p));
840         if (vx_flags(VXF_INFO_HIDE, 0))
841                 goto out;
842         nxi = task_get_nx_info(p);
843         if (!nxi)
844                 goto out;
845
846         for (i=0; i<nxi->nbipv4; i++){
847                 buffer += sprintf (buffer,
848                         "V4Root[%d]:\t%d.%d.%d.%d/%d.%d.%d.%d\n", i
849                         ,NIPQUAD(nxi->ipv4[i])
850                         ,NIPQUAD(nxi->mask[i]));
851         }
852         buffer += sprintf (buffer,
853                 "V4Root[bcast]:\t%d.%d.%d.%d\n"
854                 ,NIPQUAD(nxi->v4_bcast));
855
856         put_nx_info(nxi);
857 out:
858         return buffer - orig;
859 }
860