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