Merge to Fedora kernel-2.6.18-1.2255_FC5-vs2.0.2.2-rc9 patched with stable patch...
[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                 "Flags:\t%016llx\n"
221                 ,atomic_read(&nxi->nx_usecnt)
222                 ,atomic_read(&nxi->nx_tasks)
223                 ,(unsigned long long)nxi->nx_flags
224                 );
225         put_nx_info(nxi);
226         return length;
227 }
228
229 /* here the inode helpers */
230
231
232 #define fake_ino(id,nr) (((nr) & 0xFFFF) | \
233                         (((id) & 0xFFFF) << 16))
234
235 #define inode_vid(i)    (((i)->i_ino >> 16) & 0xFFFF)
236 #define inode_type(i)   ((i)->i_ino & 0xFFFF)
237
238 #define MAX_MULBY10     ((~0U-9)/10)
239
240
241 static struct inode *proc_vid_make_inode(struct super_block * sb,
242         int vid, int ino)
243 {
244         struct inode *inode = new_inode(sb);
245
246         if (!inode)
247                 goto out;
248
249         inode->i_mtime = inode->i_atime =
250                 inode->i_ctime = CURRENT_TIME;
251         inode->i_ino = fake_ino(vid, ino);
252
253         inode->i_uid = 0;
254         inode->i_gid = 0;
255 out:
256         return inode;
257 }
258
259 static int proc_vid_revalidate(struct dentry * dentry, struct nameidata *nd)
260 {
261         struct inode * inode = dentry->d_inode;
262         int vid, hashed=0;
263
264         vid = inode_vid(inode);
265         switch (inode_type(inode) & PROC_VID_MASK) {
266                 case PROC_XID_INO:
267                         hashed = xid_is_hashed(vid);
268                         break;
269                 case PROC_NID_INO:
270                         hashed = nid_is_hashed(vid);
271                         break;
272         }
273         if (hashed)
274                 return 1;
275         d_drop(dentry);
276         return 0;
277 }
278
279
280 #define PROC_BLOCK_SIZE (PAGE_SIZE - 1024)
281
282 static ssize_t proc_vid_info_read(struct file * file, char __user * buf,
283                           size_t count, loff_t *ppos)
284 {
285         struct inode * inode = file->f_dentry->d_inode;
286         unsigned long page;
287         ssize_t length;
288         int vid;
289
290         if (count > PROC_BLOCK_SIZE)
291                 count = PROC_BLOCK_SIZE;
292         if (!(page = __get_free_page(GFP_KERNEL)))
293                 return -ENOMEM;
294
295         vid = inode_vid(inode);
296         length = PROC_I(inode)->op.proc_vid_read(vid, (char*)page);
297
298         if (length >= 0)
299                 length = simple_read_from_buffer(buf, count, ppos,
300                         (char *)page, length);
301         free_page(page);
302         return length;
303 }
304
305
306
307
308
309 /* here comes the lower level (vid) */
310
311 static struct file_operations proc_vid_info_file_operations = {
312         .read =         proc_vid_info_read,
313 };
314
315 static struct dentry_operations proc_vid_dentry_operations = {
316         .d_revalidate = proc_vid_revalidate,
317 };
318
319
320 struct vid_entry {
321         int type;
322         int len;
323         char *name;
324         mode_t mode;
325 };
326
327 #define E(type,name,mode) {(type),sizeof(name)-1,(name),(mode)}
328
329 static struct vid_entry vx_base_stuff[] = {
330         E(PROC_XID_INFO,        "info",         S_IFREG|S_IRUGO),
331         E(PROC_XID_STATUS,      "status",       S_IFREG|S_IRUGO),
332         E(PROC_XID_LIMIT,       "limit",        S_IFREG|S_IRUGO),
333         E(PROC_XID_SCHED,       "sched",        S_IFREG|S_IRUGO),
334         E(PROC_XID_CVIRT,       "cvirt",        S_IFREG|S_IRUGO),
335         E(PROC_XID_CACCT,       "cacct",        S_IFREG|S_IRUGO),
336         {0,0,NULL,0}
337 };
338
339 static struct vid_entry vn_base_stuff[] = {
340         E(PROC_NID_INFO,        "info",         S_IFREG|S_IRUGO),
341         E(PROC_NID_STATUS,      "status",       S_IFREG|S_IRUGO),
342         {0,0,NULL,0}
343 };
344
345
346
347 static struct dentry *proc_vid_lookup(struct inode *dir,
348         struct dentry *dentry, struct nameidata *nd)
349 {
350         struct inode *inode;
351         struct vid_entry *p;
352         int error;
353
354         error = -ENOENT;
355         inode = NULL;
356
357         switch (inode_type(dir)) {
358                 case PROC_XID_INO:
359                         p = vx_base_stuff;
360                         break;
361                 case PROC_NID_INO:
362                         p = vn_base_stuff;
363                         break;
364                 default:
365                         goto out;
366         }
367
368         for (; p->name; p++) {
369                 if (p->len != dentry->d_name.len)
370                         continue;
371                 if (!memcmp(dentry->d_name.name, p->name, p->len))
372                         break;
373         }
374         if (!p->name)
375                 goto out;
376
377         error = -EINVAL;
378         inode = proc_vid_make_inode(dir->i_sb, inode_vid(dir), p->type);
379         if (!inode)
380                 goto out;
381
382         switch(p->type) {
383                 case PROC_XID_INFO:
384                         PROC_I(inode)->op.proc_vid_read = proc_xid_info;
385                         break;
386                 case PROC_XID_STATUS:
387                         PROC_I(inode)->op.proc_vid_read = proc_xid_status;
388                         break;
389                 case PROC_XID_LIMIT:
390                         PROC_I(inode)->op.proc_vid_read = proc_xid_limit;
391                         break;
392                 case PROC_XID_SCHED:
393                         PROC_I(inode)->op.proc_vid_read = proc_xid_sched;
394                         break;
395                 case PROC_XID_CVIRT:
396                         PROC_I(inode)->op.proc_vid_read = proc_xid_cvirt;
397                         break;
398                 case PROC_XID_CACCT:
399                         PROC_I(inode)->op.proc_vid_read = proc_xid_cacct;
400                         break;
401
402                 case PROC_NID_INFO:
403                         PROC_I(inode)->op.proc_vid_read = proc_nid_info;
404                         break;
405                 case PROC_NID_STATUS:
406                         PROC_I(inode)->op.proc_vid_read = proc_nid_status;
407                         break;
408
409                 default:
410                         printk("procfs: impossible type (%d)",p->type);
411                         iput(inode);
412                         return ERR_PTR(-EINVAL);
413         }
414         inode->i_mode = p->mode;
415         inode->i_fop = &proc_vid_info_file_operations;
416         inode->i_nlink = 1;
417         inode->i_flags|=S_IMMUTABLE;
418
419         dentry->d_op = &proc_vid_dentry_operations;
420         d_add(dentry, inode);
421         error = 0;
422 out:
423         return ERR_PTR(error);
424 }
425
426
427 static int proc_vid_readdir(struct file * filp,
428         void * dirent, filldir_t filldir)
429 {
430         int i, size;
431         struct inode *inode = filp->f_dentry->d_inode;
432         struct vid_entry *p;
433
434         i = filp->f_pos;
435         switch (i) {
436         case 0:
437                 if (filldir(dirent, ".", 1, i,
438                         inode->i_ino, DT_DIR) < 0)
439                         return 0;
440                 i++;
441                 filp->f_pos++;
442                 /* fall through */
443         case 1:
444                 if (filldir(dirent, "..", 2, i,
445                         PROC_ROOT_INO, DT_DIR) < 0)
446                         return 0;
447                 i++;
448                 filp->f_pos++;
449                 /* fall through */
450         default:
451                 i -= 2;
452                 switch (inode_type(inode)) {
453                         case PROC_XID_INO:
454                                 size = sizeof(vx_base_stuff);
455                                 p = vx_base_stuff + i;
456                                 break;
457                         case PROC_NID_INO:
458                                 size = sizeof(vn_base_stuff);
459                                 p = vn_base_stuff + i;
460                                 break;
461                         default:
462                                 return 1;
463                 }
464                 if (i >= size/sizeof(struct vid_entry))
465                         return 1;
466                 while (p->name) {
467                         if (filldir(dirent, p->name, p->len,
468                                 filp->f_pos, fake_ino(inode_vid(inode),
469                                 p->type), p->mode >> 12) < 0)
470                                 return 0;
471                         filp->f_pos++;
472                         p++;
473                 }
474         }
475         return 1;
476 }
477
478
479
480
481 /* now the upper level (virtual) */
482
483 static struct file_operations proc_vid_file_operations = {
484         .read =         generic_read_dir,
485         .readdir =      proc_vid_readdir,
486 };
487
488 static struct inode_operations proc_vid_inode_operations = {
489         .lookup =       proc_vid_lookup,
490 };
491
492
493
494 static __inline__ int atovid(const char *str, int len)
495 {
496         int vid, c;
497
498         vid = 0;
499         while (len-- > 0) {
500                 c = *str - '0';
501                 str++;
502                 if (c > 9)
503                         return -1;
504                 if (vid >= MAX_MULBY10)
505                         return -1;
506                 vid *= 10;
507                 vid += c;
508                 if (!vid)
509                         return -1;
510         }
511         return vid;
512 }
513
514
515 struct dentry *proc_virtual_lookup(struct inode *dir,
516         struct dentry * dentry, struct nameidata *nd)
517 {
518         int xid, len, ret;
519         struct vx_info *vxi;
520         const char *name;
521         struct inode *inode;
522
523         name = dentry->d_name.name;
524         len = dentry->d_name.len;
525         ret = -ENOMEM;
526
527         if (len == 7 && !memcmp(name, "current", 7)) {
528                 inode = new_inode(dir->i_sb);
529                 if (!inode)
530                         goto out;
531                 inode->i_mtime = inode->i_atime =
532                         inode->i_ctime = CURRENT_TIME;
533                 inode->i_ino = fake_ino(1, PROC_XID_INO);
534                 inode->i_mode = S_IFLNK|S_IRWXUGO;
535                 inode->i_uid = inode->i_gid = 0;
536                 d_add(dentry, inode);
537                 return NULL;
538         }
539         if (len == 4 && !memcmp(name, "info", 4)) {
540                 inode = proc_vid_make_inode(dir->i_sb, 0, PROC_XID_INFO);
541                 if (!inode)
542                         goto out;
543                 inode->i_fop = &proc_vid_info_file_operations;
544                 PROC_I(inode)->op.proc_vid_read = proc_virtual_info;
545                 inode->i_mode = S_IFREG|S_IRUGO;
546                 d_add(dentry, inode);
547                 return NULL;
548         }
549
550         ret = -ENOENT;
551         xid = atovid(name, len);
552         if (xid < 0)
553                 goto out;
554         vxi = lookup_vx_info(xid);
555         if (!vxi)
556                 goto out;
557
558         inode = NULL;
559         if (vx_check(xid, VX_ADMIN|VX_WATCH|VX_IDENT))
560                 inode = proc_vid_make_inode(dir->i_sb,
561                         vxi->vx_id, PROC_XID_INO);
562         if (!inode)
563                 goto out_release;
564
565         inode->i_mode = S_IFDIR|S_IRUGO|S_IXUGO;
566         inode->i_op = &proc_vid_inode_operations;
567         inode->i_fop = &proc_vid_file_operations;
568         inode->i_nlink = 2;
569         inode->i_flags|=S_IMMUTABLE;
570
571         dentry->d_op = &proc_vid_dentry_operations;
572         d_add(dentry, inode);
573         ret = 0;
574
575 out_release:
576         put_vx_info(vxi);
577 out:
578         return ERR_PTR(ret);
579 }
580
581
582 struct dentry *proc_vnet_lookup(struct inode *dir,
583         struct dentry * dentry, struct nameidata *nd)
584 {
585         int nid, len, ret;
586         struct nx_info *nxi;
587         const char *name;
588         struct inode *inode;
589
590         name = dentry->d_name.name;
591         len = dentry->d_name.len;
592         ret = -ENOMEM;
593         if (len == 7 && !memcmp(name, "current", 7)) {
594                 inode = new_inode(dir->i_sb);
595                 if (!inode)
596                         goto out;
597                 inode->i_mtime = inode->i_atime =
598                         inode->i_ctime = CURRENT_TIME;
599                 inode->i_ino = fake_ino(1, PROC_NID_INO);
600                 inode->i_mode = S_IFLNK|S_IRWXUGO;
601                 inode->i_uid = inode->i_gid = 0;
602                 d_add(dentry, inode);
603                 return NULL;
604         }
605         if (len == 4 && !memcmp(name, "info", 4)) {
606                 inode = proc_vid_make_inode(dir->i_sb, 0, PROC_NID_INFO);
607                 if (!inode)
608                         goto out;
609                 inode->i_fop = &proc_vid_info_file_operations;
610                 PROC_I(inode)->op.proc_vid_read = proc_vnet_info;
611                 inode->i_mode = S_IFREG|S_IRUGO;
612                 d_add(dentry, inode);
613                 return NULL;
614         }
615
616         ret = -ENOENT;
617         nid = atovid(name, len);
618         if (nid < 0)
619                 goto out;
620         nxi = lookup_nx_info(nid);
621         if (!nxi)
622                 goto out;
623
624         inode = NULL;
625         if (1)
626                 inode = proc_vid_make_inode(dir->i_sb,
627                         nxi->nx_id, PROC_NID_INO);
628         if (!inode)
629                 goto out_release;
630
631         inode->i_mode = S_IFDIR|S_IRUGO|S_IXUGO;
632         inode->i_op = &proc_vid_inode_operations;
633         inode->i_fop = &proc_vid_file_operations;
634         inode->i_nlink = 2;
635         inode->i_flags|=S_IMMUTABLE;
636
637         dentry->d_op = &proc_vid_dentry_operations;
638         d_add(dentry, inode);
639         ret = 0;
640
641 out_release:
642         put_nx_info(nxi);
643 out:
644         return ERR_PTR(ret);
645 }
646
647
648
649
650 #define PROC_NUMBUF 10
651 #define PROC_MAXVIDS 32
652
653 int proc_virtual_readdir(struct file * filp,
654         void * dirent, filldir_t filldir)
655 {
656         unsigned int xid_array[PROC_MAXVIDS];
657         char buf[PROC_NUMBUF];
658         unsigned int nr = filp->f_pos-3;
659         unsigned int nr_xids, i;
660         ino_t ino;
661
662         switch ((long)filp->f_pos) {
663         case 0:
664                 ino = fake_ino(0, PROC_XID_INO);
665                 if (filldir(dirent, ".", 1,
666                         filp->f_pos, ino, DT_DIR) < 0)
667                         return 0;
668                 filp->f_pos++;
669                 /* fall through */
670         case 1:
671                 ino = filp->f_dentry->d_parent->d_inode->i_ino;
672                 if (filldir(dirent, "..", 2,
673                         filp->f_pos, ino, DT_DIR) < 0)
674                         return 0;
675                 filp->f_pos++;
676                 /* fall through */
677         case 2:
678                 ino = fake_ino(0, PROC_XID_INFO);
679                 if (filldir(dirent, "info", 4,
680                         filp->f_pos, ino, DT_LNK) < 0)
681                         return 0;
682                 filp->f_pos++;
683                 /* fall through */
684         case 3:
685                 if (vx_current_xid() > 1) {
686                         ino = fake_ino(1, PROC_XID_INO);
687                         if (filldir(dirent, "current", 7,
688                                 filp->f_pos, ino, DT_LNK) < 0)
689                                 return 0;
690                 }
691                 filp->f_pos++;
692         }
693
694         nr_xids = get_xid_list(nr, xid_array, PROC_MAXVIDS);
695         for (i = 0; i < nr_xids; i++) {
696                 int xid = xid_array[i];
697                 ino_t ino = fake_ino(xid, PROC_XID_INO);
698                 unsigned int j = PROC_NUMBUF;
699
700                 do buf[--j] = '0' + (xid % 10); while (xid/=10);
701
702                 if (filldir(dirent, buf+j, PROC_NUMBUF-j,
703                         filp->f_pos, ino, DT_DIR) < 0)
704                         break;
705                 filp->f_pos++;
706         }
707         return 0;
708 }
709
710
711 static struct file_operations proc_virtual_dir_operations = {
712         .read =         generic_read_dir,
713         .readdir =      proc_virtual_readdir,
714 };
715
716 static struct inode_operations proc_virtual_dir_inode_operations = {
717         .lookup =       proc_virtual_lookup,
718 };
719
720
721 int proc_vnet_readdir(struct file * filp,
722         void * dirent, filldir_t filldir)
723 {
724         unsigned int nid_array[PROC_MAXVIDS];
725         char buf[PROC_NUMBUF];
726         unsigned int nr = filp->f_pos-2;
727         unsigned int nr_nids, i;
728         ino_t ino;
729
730         switch ((long)filp->f_pos) {
731         case 0:
732                 ino = fake_ino(0, PROC_NID_INO);
733                 if (filldir(dirent, ".", 1,
734                         filp->f_pos, ino, DT_DIR) < 0)
735                         return 0;
736                 filp->f_pos++;
737                 /* fall through */
738         case 1:
739                 ino = filp->f_dentry->d_parent->d_inode->i_ino;
740                 if (filldir(dirent, "..", 2,
741                         filp->f_pos, ino, DT_DIR) < 0)
742                         return 0;
743                 filp->f_pos++;
744                 /* fall through */
745         case 2:
746                 ino = fake_ino(0, PROC_NID_INFO);
747                 if (filldir(dirent, "info", 4,
748                         filp->f_pos, ino, DT_REG) < 0)
749                         return 0;
750                 filp->f_pos++;
751                 /* fall through */
752         }
753
754         nr_nids = get_nid_list(nr, nid_array, PROC_MAXVIDS);
755         for (i = 0; i < nr_nids; i++) {
756                 int nid = nid_array[i];
757                 ino_t ino = fake_ino(nid, PROC_NID_INO);
758                 unsigned long j = PROC_NUMBUF;
759
760                 do buf[--j] = '0' + (nid % 10); while (nid/=10);
761
762                 if (filldir(dirent, buf+j, PROC_NUMBUF-j,
763                         filp->f_pos, ino, DT_DIR) < 0)
764                         break;
765                 filp->f_pos++;
766         }
767         return 0;
768 }
769
770
771 static struct file_operations proc_vnet_dir_operations = {
772         .read =         generic_read_dir,
773         .readdir =      proc_vnet_readdir,
774 };
775
776 static struct inode_operations proc_vnet_dir_inode_operations = {
777         .lookup =       proc_vnet_lookup,
778 };
779
780
781
782 void proc_vx_init(void)
783 {
784         struct proc_dir_entry *ent;
785
786         ent = proc_mkdir("virtual", 0);
787         if (ent) {
788                 ent->proc_fops = &proc_virtual_dir_operations;
789                 ent->proc_iops = &proc_virtual_dir_inode_operations;
790         }
791         proc_virtual = ent;
792
793         ent = proc_mkdir("virtnet", 0);
794         if (ent) {
795                 ent->proc_fops = &proc_vnet_dir_operations;
796                 ent->proc_iops = &proc_vnet_dir_inode_operations;
797         }
798         proc_vnet = ent;
799 }
800
801
802
803
804 /* per pid info */
805
806
807 int proc_pid_vx_info(struct task_struct *p, char *buffer)
808 {
809         struct vx_info *vxi;
810         char * orig = buffer;
811
812         buffer += sprintf (buffer,"XID:\t%d\n", vx_task_xid(p));
813         if (vx_flags(VXF_INFO_HIDE, 0))
814                 goto out;
815
816         vxi = task_get_vx_info(p);
817         if (!vxi)
818                 goto out;
819
820         buffer += sprintf (buffer,"BCaps:\t%016llx\n"
821                 ,(unsigned long long)vxi->vx_bcaps);
822         buffer += sprintf (buffer,"CCaps:\t%016llx\n"
823                 ,(unsigned long long)vxi->vx_ccaps);
824         buffer += sprintf (buffer,"CFlags:\t%016llx\n"
825                 ,(unsigned long long)vxi->vx_flags);
826         buffer += sprintf (buffer,"CIPid:\t%d\n"
827                 ,vxi->vx_initpid);
828
829         put_vx_info(vxi);
830 out:
831         return buffer - orig;
832 }
833
834
835 int proc_pid_nx_info(struct task_struct *p, char *buffer)
836 {
837         struct nx_info *nxi;
838         char * orig = buffer;
839         int i;
840
841         buffer += sprintf (buffer,"NID:\t%d\n", nx_task_nid(p));
842         if (vx_flags(VXF_INFO_HIDE, 0))
843                 goto out;
844         nxi = task_get_nx_info(p);
845         if (!nxi)
846                 goto out;
847
848         for (i=0; i<nxi->nbipv4; i++){
849                 buffer += sprintf (buffer,
850                         "V4Root[%d]:\t%d.%d.%d.%d/%d.%d.%d.%d\n", i
851                         ,NIPQUAD(nxi->ipv4[i])
852                         ,NIPQUAD(nxi->mask[i]));
853         }
854         buffer += sprintf (buffer,
855                 "V4Root[bcast]:\t%d.%d.%d.%d\n"
856                 ,NIPQUAD(nxi->v4_bcast));
857
858         put_nx_info(nxi);
859 out:
860         return buffer - orig;
861 }
862