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