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