IPv6 support for 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-2007  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  *  V0.08  remove inode type
16  *
17  */
18
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 #include <linux/vserver/global.h>
28
29 #include <asm/uaccess.h>
30 #include <asm/unistd.h>
31
32 #include "cvirt_proc.h"
33 #include "cacct_proc.h"
34 #include "limit_proc.h"
35 #include "sched_proc.h"
36 #include "vci_config.h"
37
38 static struct proc_dir_entry *proc_virtual;
39
40 static struct proc_dir_entry *proc_virtnet;
41
42
43 /* first the actual feeds */
44
45
46 static int proc_vci(char *buffer)
47 {
48         return sprintf(buffer,
49                 "VCIVersion:\t%04x:%04x\n"
50                 "VCISyscall:\t%d\n"
51                 "VCIKernel:\t%08x\n"
52                 ,VCI_VERSION >> 16
53                 ,VCI_VERSION & 0xFFFF
54                 ,__NR_vserver
55                 ,vci_kernel_config()
56                 );
57 }
58
59 static int proc_virtual_info(char *buffer)
60 {
61         return proc_vci(buffer);
62 }
63
64 static int proc_virtual_status(char *buffer)
65 {
66         return sprintf(buffer,
67                 "#CTotal:\t%d\n"
68                 "#CActive:\t%d\n"
69                 "#NSProxy:\t%d\t%d %d %d %d\n"
70                 ,atomic_read(&vx_global_ctotal)
71                 ,atomic_read(&vx_global_cactive)
72                 ,atomic_read(&vs_global_nsproxy)
73                 ,atomic_read(&vs_global_fs)
74                 ,atomic_read(&vs_global_mnt_ns)
75                 ,atomic_read(&vs_global_uts_ns)
76                 ,atomic_read(&vs_global_ipc_ns)
77                 );
78 }
79
80
81 int proc_vxi_info (struct vx_info *vxi, char *buffer)
82 {
83         int length;
84
85         length = sprintf(buffer,
86                 "ID:\t%d\n"
87                 "Info:\t%p\n"
88                 "Init:\t%d\n"
89                 ,vxi->vx_id
90                 ,vxi
91                 ,vxi->vx_initpid
92                 );
93         return length;
94 }
95
96 int proc_vxi_status (struct vx_info *vxi, char *buffer)
97 {
98         int length;
99
100         length = sprintf(buffer,
101                 "UseCnt:\t%d\n"
102                 "Tasks:\t%d\n"
103                 "Flags:\t%016llx\n"
104                 "BCaps:\t%016llx\n"
105                 "CCaps:\t%016llx\n"
106                 "Spaces:\t%08lx\n"
107                 ,atomic_read(&vxi->vx_usecnt)
108                 ,atomic_read(&vxi->vx_tasks)
109                 ,(unsigned long long)vxi->vx_flags
110                 ,(unsigned long long)vxi->vx_bcaps
111                 ,(unsigned long long)vxi->vx_ccaps
112                 ,vxi->vx_nsmask
113                 );
114         return length;
115 }
116
117 int proc_vxi_limit (struct vx_info *vxi, char *buffer)
118 {
119         return vx_info_proc_limit(&vxi->limit, buffer);
120 }
121
122 int proc_vxi_sched (struct vx_info *vxi, char *buffer)
123 {
124         int cpu, length;
125
126         length = vx_info_proc_sched(&vxi->sched, buffer);
127         for_each_online_cpu(cpu) {
128                 length += vx_info_proc_sched_pc(
129                         &vx_per_cpu(vxi, sched_pc, cpu),
130                         buffer + length, cpu);
131         }
132         return length;
133 }
134
135 int proc_vxi_nsproxy (struct vx_info *vxi, char *buffer)
136 {
137         return vx_info_proc_nsproxy(vxi->vx_nsproxy, buffer);
138 }
139
140 int proc_vxi_cvirt (struct vx_info *vxi, char *buffer)
141 {
142         int cpu, length;
143
144         vx_update_load(vxi);
145         length = vx_info_proc_cvirt(&vxi->cvirt, buffer);
146         for_each_online_cpu(cpu) {
147                 length += vx_info_proc_cvirt_pc(
148                         &vx_per_cpu(vxi, cvirt_pc, cpu),
149                         buffer + length, cpu);
150         }
151         return length;
152 }
153
154 int proc_vxi_cacct (struct vx_info *vxi, char *buffer)
155 {
156         return vx_info_proc_cacct(&vxi->cacct, buffer);
157 }
158
159
160 static int proc_virtnet_info(char *buffer)
161 {
162         return proc_vci(buffer);
163 }
164
165 static int proc_virtnet_status(char *buffer)
166 {
167         return sprintf(buffer,
168                 "#CTotal:\t%d\n"
169                 "#CActive:\t%d\n"
170                 ,atomic_read(&nx_global_ctotal)
171                 ,atomic_read(&nx_global_cactive)
172                 );
173 }
174
175 int proc_nxi_info (struct nx_info *nxi, char *buffer)
176 {
177         int length, i;
178
179         length = sprintf(buffer,
180                 "ID:\t%d\n"
181                 "Info:\t%p\n"
182                 ,nxi->nx_id
183                 ,nxi
184                 );
185         for (i=0; i<nxi->nbipv4; i++) {
186                 length += sprintf(buffer + length,
187                         "%d:\t" NIPQUAD_FMT "/" NIPQUAD_FMT "\n", i,
188                         NIPQUAD(nxi->ipv4[i]), NIPQUAD(nxi->mask[i]));
189         }
190 #if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)
191         for (i=0; i<nxi->nbipv6;i++) {
192                 length += sprintf(buffer + length,
193                         "%d:\t" NIP6_FMT "/%d\n", i,
194                         NIP6(nxi->ipv6[i]), nxi->prefix6[i]);
195         }
196 #endif /* CONFIG_IPV6 || CONFIG_IPV6_MODULE */
197         return length;
198 }
199
200 int proc_nxi_status (struct nx_info *nxi, char *buffer)
201 {
202         int length;
203
204         length = sprintf(buffer,
205                 "UseCnt:\t%d\n"
206                 "Tasks:\t%d\n"
207                 "Flags:\t%016llx\n"
208                 "NCaps:\t%016llx\n"
209                 ,atomic_read(&nxi->nx_usecnt)
210                 ,atomic_read(&nxi->nx_tasks)
211                 ,(unsigned long long)nxi->nx_flags
212                 ,(unsigned long long)nxi->nx_ncaps
213                 );
214         return length;
215 }
216
217
218
219 /* here the inode helpers */
220
221 struct vs_entry {
222         int len;
223         char *name;
224         mode_t mode;
225         struct inode_operations *iop;
226         struct file_operations *fop;
227         union proc_op op;
228 };
229
230 static struct inode *vs_proc_make_inode(struct super_block *sb, struct vs_entry *p)
231 {
232         struct inode *inode = new_inode(sb);
233
234         if (!inode)
235                 goto out;
236
237         inode->i_mode = p->mode;
238         if (p->iop)
239                 inode->i_op = p->iop;
240         if (p->fop)
241                 inode->i_fop = p->fop;
242
243         inode->i_nlink = (p->mode & S_IFDIR) ? 2 : 1;
244         inode->i_flags |= S_IMMUTABLE;
245
246         inode->i_mtime = inode->i_atime = inode->i_ctime = CURRENT_TIME;
247
248         inode->i_uid = 0;
249         inode->i_gid = 0;
250         inode->i_tag = 0;
251 out:
252         return inode;
253 }
254
255 static struct dentry *vs_proc_instantiate(struct inode *dir,
256         struct dentry *dentry, int id, void *ptr)
257 {
258         struct vs_entry *p = ptr;
259         struct inode *inode = vs_proc_make_inode(dir->i_sb, p);
260         struct dentry *error = ERR_PTR(-EINVAL);
261
262         if (!inode)
263                 goto out;
264
265         PROC_I(inode)->op = p->op;
266         PROC_I(inode)->fd = id;
267         d_add(dentry, inode);
268         error = NULL;
269 out:
270         return error;
271 }
272
273 /* Lookups */
274
275 typedef struct dentry *instantiate_t(struct inode *, struct dentry *, int, void *);
276
277 /*
278  * Fill a directory entry.
279  *
280  * If possible create the dcache entry and derive our inode number and
281  * file type from dcache entry.
282  *
283  * Since all of the proc inode numbers are dynamically generated, the inode
284  * numbers do not exist until the inode is cache.  This means creating the
285  * the dcache entry in readdir is necessary to keep the inode numbers
286  * reported by readdir in sync with the inode numbers reported
287  * by stat.
288  */
289 static int proc_fill_cache(struct file *filp, void *dirent, filldir_t filldir,
290         char *name, int len, instantiate_t instantiate, int id, void *ptr)
291 {
292         struct dentry *child, *dir = filp->f_dentry;
293         struct inode *inode;
294         struct qstr qname;
295         ino_t ino = 0;
296         unsigned type = DT_UNKNOWN;
297
298         qname.name = name;
299         qname.len  = len;
300         qname.hash = full_name_hash(name, len);
301
302         child = d_lookup(dir, &qname);
303         if (!child) {
304                 struct dentry *new;
305                 new = d_alloc(dir, &qname);
306                 if (new) {
307                         child = instantiate(dir->d_inode, new, id, ptr);
308                         if (child)
309                                 dput(new);
310                         else
311                                 child = new;
312                 }
313         }
314         if (!child || IS_ERR(child) || !child->d_inode)
315                 goto end_instantiate;
316         inode = child->d_inode;
317         if (inode) {
318                 ino = inode->i_ino;
319                 type = inode->i_mode >> 12;
320         }
321         dput(child);
322 end_instantiate:
323         if (!ino)
324                 ino = find_inode_number(dir, &qname);
325         if (!ino)
326                 ino = 1;
327         return filldir(dirent, name, len, filp->f_pos, ino, type);
328 }
329
330
331
332 /* get and revalidate vx_info/xid */
333
334 static inline
335 struct vx_info *get_proc_vx_info(struct inode *inode)
336 {
337         return lookup_vx_info(PROC_I(inode)->fd);
338 }
339
340 static int proc_xid_revalidate(struct dentry * dentry, struct nameidata *nd)
341 {
342         struct inode *inode = dentry->d_inode;
343         xid_t xid = PROC_I(inode)->fd;
344
345         if (!xid || xid_is_hashed(xid))
346                 return 1;
347         d_drop(dentry);
348         return 0;
349 }
350
351
352 /* get and revalidate nx_info/nid */
353
354 static int proc_nid_revalidate(struct dentry * dentry, struct nameidata *nd)
355 {
356         struct inode *inode = dentry->d_inode;
357         nid_t nid = PROC_I(inode)->fd;
358
359         if (!nid || nid_is_hashed(nid))
360                 return 1;
361         d_drop(dentry);
362         return 0;
363 }
364
365
366
367 #define PROC_BLOCK_SIZE (PAGE_SIZE - 1024)
368
369 static ssize_t proc_vs_info_read(struct file * file, char __user * buf,
370                           size_t count, loff_t *ppos)
371 {
372         struct inode *inode = file->f_dentry->d_inode;
373         unsigned long page;
374         ssize_t length = 0;
375
376         if (count > PROC_BLOCK_SIZE)
377                 count = PROC_BLOCK_SIZE;
378
379         /* fade that out as soon as stable */
380         WARN_ON(PROC_I(inode)->fd);
381
382         if (!(page = __get_free_page(GFP_KERNEL)))
383                 return -ENOMEM;
384
385         BUG_ON(!PROC_I(inode)->op.proc_vs_read);
386         length = PROC_I(inode)->op.proc_vs_read((char*)page);
387
388         if (length >= 0)
389                 length = simple_read_from_buffer(buf, count, ppos,
390                         (char *)page, length);
391
392         free_page(page);
393         return length;
394 }
395
396 static ssize_t proc_vx_info_read(struct file * file, char __user * buf,
397                           size_t count, loff_t *ppos)
398 {
399         struct inode *inode = file->f_dentry->d_inode;
400         struct vx_info *vxi = NULL;
401         xid_t xid = PROC_I(inode)->fd;
402         unsigned long page;
403         ssize_t length = 0;
404
405         if (count > PROC_BLOCK_SIZE)
406                 count = PROC_BLOCK_SIZE;
407
408         /* fade that out as soon as stable */
409         WARN_ON(!xid);
410         vxi = lookup_vx_info(xid);
411         if (!vxi)
412                 goto out;
413
414         length = -ENOMEM;
415         if (!(page = __get_free_page(GFP_KERNEL)))
416                 goto out_put;
417
418         BUG_ON(!PROC_I(inode)->op.proc_vxi_read);
419         length = PROC_I(inode)->op.proc_vxi_read(vxi, (char*)page);
420
421         if (length >= 0)
422                 length = simple_read_from_buffer(buf, count, ppos,
423                         (char *)page, length);
424
425         free_page(page);
426 out_put:
427         put_vx_info(vxi);
428 out:
429         return length;
430 }
431
432 static ssize_t proc_nx_info_read(struct file * file, char __user * buf,
433                           size_t count, loff_t *ppos)
434 {
435         struct inode *inode = file->f_dentry->d_inode;
436         struct nx_info *nxi = NULL;
437         nid_t nid = PROC_I(inode)->fd;
438         unsigned long page;
439         ssize_t length = 0;
440
441         if (count > PROC_BLOCK_SIZE)
442                 count = PROC_BLOCK_SIZE;
443
444         /* fade that out as soon as stable */
445         WARN_ON(!nid);
446         nxi = lookup_nx_info(nid);
447         if (!nxi)
448                 goto out;
449
450         length = -ENOMEM;
451         if (!(page = __get_free_page(GFP_KERNEL)))
452                 goto out_put;
453
454         BUG_ON(!PROC_I(inode)->op.proc_nxi_read);
455         length = PROC_I(inode)->op.proc_nxi_read(nxi, (char*)page);
456
457         if (length >= 0)
458                 length = simple_read_from_buffer(buf, count, ppos,
459                         (char *)page, length);
460
461         free_page(page);
462 out_put:
463         put_nx_info(nxi);
464 out:
465         return length;
466 }
467
468
469
470 /* here comes the lower level */
471
472
473 #define NOD(NAME, MODE, IOP, FOP, OP) { \
474         .len  = sizeof(NAME) - 1,       \
475         .name = (NAME),                 \
476         .mode = MODE,                   \
477         .iop  = IOP,                    \
478         .fop  = FOP,                    \
479         .op   = OP,                     \
480 }
481
482
483 #define DIR(NAME, MODE, OTYPE)                          \
484         NOD(NAME, (S_IFDIR|(MODE)),                     \
485                 &proc_##OTYPE##_inode_operations,       \
486                 &proc_##OTYPE##_file_operations, { } )
487
488 #define INF(NAME, MODE, OTYPE)                          \
489         NOD(NAME, (S_IFREG|(MODE)), NULL,               \
490                 &proc_vs_info_file_operations,          \
491                 { .proc_vs_read = &proc_##OTYPE } )
492
493 #define VINF(NAME, MODE, OTYPE)                         \
494         NOD(NAME, (S_IFREG|(MODE)), NULL,               \
495                 &proc_vx_info_file_operations,          \
496                 { .proc_vxi_read = &proc_##OTYPE } )
497
498 #define NINF(NAME, MODE, OTYPE)                         \
499         NOD(NAME, (S_IFREG|(MODE)), NULL,               \
500                 &proc_nx_info_file_operations,          \
501                 { .proc_nxi_read = &proc_##OTYPE } )
502
503
504 static struct file_operations proc_vs_info_file_operations = {
505         .read =         proc_vs_info_read,
506 };
507
508 static struct file_operations proc_vx_info_file_operations = {
509         .read =         proc_vx_info_read,
510 };
511
512 static struct dentry_operations proc_xid_dentry_operations = {
513         .d_revalidate = proc_xid_revalidate,
514 };
515
516 static struct vs_entry vx_base_stuff[] = {
517         VINF("info",    S_IRUGO, vxi_info),
518         VINF("status",  S_IRUGO, vxi_status),
519         VINF("limit",   S_IRUGO, vxi_limit),
520         VINF("sched",   S_IRUGO, vxi_sched),
521         VINF("nsproxy", S_IRUGO, vxi_nsproxy),
522         VINF("cvirt",   S_IRUGO, vxi_cvirt),
523         VINF("cacct",   S_IRUGO, vxi_cacct),
524         {}
525 };
526
527
528
529
530 static struct dentry *proc_xid_instantiate(struct inode *dir,
531         struct dentry *dentry, int id, void *ptr)
532 {
533         dentry->d_op = &proc_xid_dentry_operations;
534         return vs_proc_instantiate(dir, dentry, id, ptr);
535 }
536
537 static struct dentry *proc_xid_lookup(struct inode *dir,
538         struct dentry *dentry, struct nameidata *nd)
539 {
540         struct vs_entry *p = vx_base_stuff;
541         struct dentry *error = ERR_PTR(-ENOENT);
542
543         for (; p->name; p++) {
544                 if (p->len != dentry->d_name.len)
545                         continue;
546                 if (!memcmp(dentry->d_name.name, p->name, p->len))
547                         break;
548         }
549         if (!p->name)
550                 goto out;
551
552         error = proc_xid_instantiate(dir, dentry, PROC_I(dir)->fd, p);
553 out:
554         return error;
555 }
556
557 static int proc_xid_readdir(struct file * filp,
558         void * dirent, filldir_t filldir)
559 {
560         struct dentry *dentry = filp->f_dentry;
561         struct inode *inode = dentry->d_inode;
562         struct vs_entry *p = vx_base_stuff;
563         int size = sizeof(vx_base_stuff)/sizeof(struct vs_entry);
564         int pos, index;
565         u64 ino;
566
567         pos = filp->f_pos;
568         switch (pos) {
569         case 0:
570                 ino = inode->i_ino;
571                 if (filldir(dirent, ".", 1, pos, ino, DT_DIR) < 0)
572                         goto out;
573                 pos++;
574                 /* fall through */
575         case 1:
576                 ino = parent_ino(dentry);
577                 if (filldir(dirent, "..", 2, pos, ino, DT_DIR) < 0)
578                         goto out;
579                 pos++;
580                 /* fall through */
581         default:
582                 index = pos - 2;
583                 if (index >= size)
584                         goto out;
585                 for (p += index; p->name; p++) {
586                         if (proc_fill_cache(filp, dirent, filldir, p->name, p->len,
587                                 vs_proc_instantiate, PROC_I(inode)->fd, p))
588                                 goto out;
589                         pos++;
590                 }
591         }
592 out:
593         filp->f_pos = pos;
594         return 1;
595 }
596
597
598
599 static struct file_operations proc_nx_info_file_operations = {
600         .read =         proc_nx_info_read,
601 };
602
603 static struct dentry_operations proc_nid_dentry_operations = {
604         .d_revalidate = proc_nid_revalidate,
605 };
606
607 static struct vs_entry nx_base_stuff[] = {
608         NINF("info",    S_IRUGO, nxi_info),
609         NINF("status",  S_IRUGO, nxi_status),
610         {}
611 };
612
613
614 static struct dentry *proc_nid_instantiate(struct inode *dir,
615         struct dentry *dentry, int id, void *ptr)
616 {
617         dentry->d_op = &proc_nid_dentry_operations;
618         return vs_proc_instantiate(dir, dentry, id, ptr);
619 }
620
621 static struct dentry *proc_nid_lookup(struct inode *dir,
622         struct dentry *dentry, struct nameidata *nd)
623 {
624         struct vs_entry *p = nx_base_stuff;
625         struct dentry *error = ERR_PTR(-ENOENT);
626
627         for (; p->name; p++) {
628                 if (p->len != dentry->d_name.len)
629                         continue;
630                 if (!memcmp(dentry->d_name.name, p->name, p->len))
631                         break;
632         }
633         if (!p->name)
634                 goto out;
635
636         error = proc_nid_instantiate(dir, dentry, PROC_I(dir)->fd, p);
637 out:
638         return error;
639 }
640
641 static int proc_nid_readdir(struct file * filp,
642         void * dirent, filldir_t filldir)
643 {
644         struct dentry *dentry = filp->f_dentry;
645         struct inode *inode = dentry->d_inode;
646         struct vs_entry *p = nx_base_stuff;
647         int size = sizeof(nx_base_stuff)/sizeof(struct vs_entry);
648         int pos, index;
649         u64 ino;
650
651         pos = filp->f_pos;
652         switch (pos) {
653         case 0:
654                 ino = inode->i_ino;
655                 if (filldir(dirent, ".", 1, pos, ino, DT_DIR) < 0)
656                         goto out;
657                 pos++;
658                 /* fall through */
659         case 1:
660                 ino = parent_ino(dentry);
661                 if (filldir(dirent, "..", 2, pos, ino, DT_DIR) < 0)
662                         goto out;
663                 pos++;
664                 /* fall through */
665         default:
666                 index = pos - 2;
667                 if (index >= size)
668                         goto out;
669                 for (p += index; p->name; p++) {
670                         if (proc_fill_cache(filp, dirent, filldir, p->name, p->len,
671                                 vs_proc_instantiate, PROC_I(inode)->fd, p))
672                                 goto out;
673                         pos++;
674                 }
675         }
676 out:
677         filp->f_pos = pos;
678         return 1;
679 }
680
681
682 #define MAX_MULBY10     ((~0U-9)/10)
683
684 static inline int atovid(const char *str, int len)
685 {
686         int vid, c;
687
688         vid = 0;
689         while (len-- > 0) {
690                 c = *str - '0';
691                 str++;
692                 if (c > 9)
693                         return -1;
694                 if (vid >= MAX_MULBY10)
695                         return -1;
696                 vid *= 10;
697                 vid += c;
698                 if (!vid)
699                         return -1;
700         }
701         return vid;
702 }
703
704 /* now the upper level (virtual) */
705
706
707 static struct file_operations proc_xid_file_operations = {
708         .read =         generic_read_dir,
709         .readdir =      proc_xid_readdir,
710 };
711
712 static struct inode_operations proc_xid_inode_operations = {
713         .lookup =       proc_xid_lookup,
714 };
715
716 static struct vs_entry vx_virtual_stuff[] = {
717         INF("info",     S_IRUGO, virtual_info),
718         INF("status",   S_IRUGO, virtual_status),
719         DIR(NULL,       S_IRUGO|S_IXUGO, xid),
720 };
721
722
723 static struct dentry *proc_virtual_lookup(struct inode *dir,
724         struct dentry *dentry, struct nameidata *nd)
725 {
726         struct vs_entry *p = vx_virtual_stuff;
727         struct dentry *error = ERR_PTR(-ENOENT);
728         int id = 0;
729
730         for (; p->name; p++) {
731                 if (p->len != dentry->d_name.len)
732                         continue;
733                 if (!memcmp(dentry->d_name.name, p->name, p->len))
734                         break;
735         }
736         if (p->name)
737                 goto instantiate;
738
739         id = atovid(dentry->d_name.name, dentry->d_name.len);
740         if ((id < 0) || !xid_is_hashed(id))
741                 goto out;
742
743 instantiate:
744         error = proc_xid_instantiate(dir, dentry, id, p);
745 out:
746         return error;
747 }
748
749 static struct file_operations proc_nid_file_operations = {
750         .read =         generic_read_dir,
751         .readdir =      proc_nid_readdir,
752 };
753
754 static struct inode_operations proc_nid_inode_operations = {
755         .lookup =       proc_nid_lookup,
756 };
757
758 static struct vs_entry nx_virtnet_stuff[] = {
759         INF("info",     S_IRUGO, virtnet_info),
760         INF("status",   S_IRUGO, virtnet_status),
761         DIR(NULL,       S_IRUGO|S_IXUGO, nid),
762 };
763
764
765 static struct dentry *proc_virtnet_lookup(struct inode *dir,
766         struct dentry *dentry, struct nameidata *nd)
767 {
768         struct vs_entry *p = nx_virtnet_stuff;
769         struct dentry *error = ERR_PTR(-ENOENT);
770         int id = 0;
771
772         for (; p->name; p++) {
773                 if (p->len != dentry->d_name.len)
774                         continue;
775                 if (!memcmp(dentry->d_name.name, p->name, p->len))
776                         break;
777         }
778         if (p->name)
779                 goto instantiate;
780
781         id = atovid(dentry->d_name.name, dentry->d_name.len);
782         if ((id < 0) || !nid_is_hashed(id))
783                 goto out;
784
785 instantiate:
786         error = proc_nid_instantiate(dir, dentry, id, p);
787 out:
788         return error;
789 }
790
791
792
793 #define PROC_NUMBUF 10
794 #define PROC_MAXVIDS 32
795
796 int proc_virtual_readdir(struct file * filp,
797         void * dirent, filldir_t filldir)
798 {
799         struct dentry *dentry = filp->f_dentry;
800         struct inode *inode = dentry->d_inode;
801         struct vs_entry *p = vx_virtual_stuff;
802         int size = sizeof(vx_virtual_stuff)/sizeof(struct vs_entry);
803         int pos, index;
804         unsigned int xid_array[PROC_MAXVIDS];
805         char buf[PROC_NUMBUF];
806         unsigned int nr_xids, i;
807         u64 ino;
808
809         pos = filp->f_pos;
810         switch (pos) {
811         case 0:
812                 ino = inode->i_ino;
813                 if (filldir(dirent, ".", 1, pos, ino, DT_DIR) < 0)
814                         goto out;
815                 pos++;
816                 /* fall through */
817         case 1:
818                 ino = parent_ino(dentry);
819                 if (filldir(dirent, "..", 2, pos, ino, DT_DIR) < 0)
820                         goto out;
821                 pos++;
822                 /* fall through */
823         default:
824                 index = pos - 2;
825                 if (index >= size)
826                         goto entries;
827                 for (p += index; p->name; p++) {
828                         if (proc_fill_cache(filp, dirent, filldir, p->name, p->len,
829                                 vs_proc_instantiate, 0, p))
830                                 goto out;
831                         pos++;
832                 }
833         entries:
834                 index = pos - size;
835                 p = &vx_virtual_stuff[size-1];
836                 nr_xids = get_xid_list(index, xid_array, PROC_MAXVIDS);
837                 for (i = 0; i < nr_xids; i++) {
838                         int n, xid = xid_array[i];
839                         unsigned int j = PROC_NUMBUF;
840
841                         n = xid;
842                         do buf[--j] = '0' + (n % 10); while (n /= 10);
843
844                         if (proc_fill_cache(filp, dirent, filldir, buf+j, PROC_NUMBUF-j,
845                                 vs_proc_instantiate, xid, p))
846                                 goto out;
847                         pos++;
848                 }
849         }
850 out:
851         filp->f_pos = pos;
852         return 0;
853 }
854
855 static int proc_virtual_getattr(struct vfsmount *mnt,
856         struct dentry *dentry, struct kstat *stat)
857 {
858         struct inode *inode = dentry->d_inode;
859
860         generic_fillattr(inode, stat);
861         stat->nlink = 2 + atomic_read(&vx_global_cactive);
862         return 0;
863 }
864
865 static struct file_operations proc_virtual_dir_operations = {
866         .read =         generic_read_dir,
867         .readdir =      proc_virtual_readdir,
868 };
869
870 static struct inode_operations proc_virtual_dir_inode_operations = {
871         .getattr =      proc_virtual_getattr,
872         .lookup =       proc_virtual_lookup,
873 };
874
875
876
877
878
879 int proc_virtnet_readdir(struct file * filp,
880         void * dirent, filldir_t filldir)
881 {
882         struct dentry *dentry = filp->f_dentry;
883         struct inode *inode = dentry->d_inode;
884         struct vs_entry *p = nx_virtnet_stuff;
885         int size = sizeof(nx_virtnet_stuff)/sizeof(struct vs_entry);
886         int pos, index;
887         unsigned int nid_array[PROC_MAXVIDS];
888         char buf[PROC_NUMBUF];
889         unsigned int nr_nids, i;
890         u64 ino;
891
892         pos = filp->f_pos;
893         switch (pos) {
894         case 0:
895                 ino = inode->i_ino;
896                 if (filldir(dirent, ".", 1, pos, ino, DT_DIR) < 0)
897                         goto out;
898                 pos++;
899                 /* fall through */
900         case 1:
901                 ino = parent_ino(dentry);
902                 if (filldir(dirent, "..", 2, pos, ino, DT_DIR) < 0)
903                         goto out;
904                 pos++;
905                 /* fall through */
906         default:
907                 index = pos - 2;
908                 if (index >= size)
909                         goto entries;
910                 for (p += index; p->name; p++) {
911                         if (proc_fill_cache(filp, dirent, filldir, p->name, p->len,
912                                 vs_proc_instantiate, 0, p))
913                                 goto out;
914                         pos++;
915                 }
916         entries:
917                 index = pos - size;
918                 p = &nx_virtnet_stuff[size-1];
919                 nr_nids = get_nid_list(index, nid_array, PROC_MAXVIDS);
920                 for (i = 0; i < nr_nids; i++) {
921                         int n, nid = nid_array[i];
922                         unsigned int j = PROC_NUMBUF;
923
924                         n = nid;
925                         do buf[--j] = '0' + (n % 10); while (n /= 10);
926
927                         if (proc_fill_cache(filp, dirent, filldir, buf+j, PROC_NUMBUF-j,
928                                 vs_proc_instantiate, nid, p))
929                                 goto out;
930                         pos++;
931                 }
932         }
933 out:
934         filp->f_pos = pos;
935         return 0;
936 }
937
938 static int proc_virtnet_getattr(struct vfsmount *mnt,
939         struct dentry *dentry, struct kstat *stat)
940 {
941         struct inode *inode = dentry->d_inode;
942
943         generic_fillattr(inode, stat);
944         stat->nlink = 2 + atomic_read(&nx_global_cactive);
945         return 0;
946 }
947
948 static struct file_operations proc_virtnet_dir_operations = {
949         .read =         generic_read_dir,
950         .readdir =      proc_virtnet_readdir,
951 };
952
953 static struct inode_operations proc_virtnet_dir_inode_operations = {
954         .getattr =      proc_virtnet_getattr,
955         .lookup =       proc_virtnet_lookup,
956 };
957
958
959
960 void proc_vx_init(void)
961 {
962         struct proc_dir_entry *ent;
963
964         ent = proc_mkdir("virtual", 0);
965         if (ent) {
966                 ent->proc_fops = &proc_virtual_dir_operations;
967                 ent->proc_iops = &proc_virtual_dir_inode_operations;
968         }
969         proc_virtual = ent;
970
971         ent = proc_mkdir("virtnet", 0);
972         if (ent) {
973                 ent->proc_fops = &proc_virtnet_dir_operations;
974                 ent->proc_iops = &proc_virtnet_dir_inode_operations;
975         }
976         proc_virtnet = ent;
977 }
978
979
980
981
982 /* per pid info */
983
984
985 int proc_pid_vx_info(struct task_struct *p, char *buffer)
986 {
987         struct vx_info *vxi;
988         char * orig = buffer;
989
990         buffer += sprintf (buffer,"XID:\t%d\n", vx_task_xid(p));
991
992         vxi = task_get_vx_info(p);
993         if (!vxi)
994                 goto out;
995
996         buffer += sprintf (buffer,"BCaps:\t%016llx\n"
997                 ,(unsigned long long)vxi->vx_bcaps);
998         buffer += sprintf (buffer,"CCaps:\t%016llx\n"
999                 ,(unsigned long long)vxi->vx_ccaps);
1000         buffer += sprintf (buffer,"CFlags:\t%016llx\n"
1001                 ,(unsigned long long)vxi->vx_flags);
1002         buffer += sprintf (buffer,"CIPid:\t%d\n"
1003                 ,vxi->vx_initpid);
1004
1005         put_vx_info(vxi);
1006 out:
1007         return buffer - orig;
1008 }
1009
1010
1011 int proc_pid_nx_info(struct task_struct *p, char *buffer)
1012 {
1013         struct nx_info *nxi;
1014         char * orig = buffer;
1015         int i;
1016
1017         buffer += sprintf (buffer,"NID:\t%d\n", nx_task_nid(p));
1018
1019         nxi = task_get_nx_info(p);
1020         if (!nxi)
1021                 goto out;
1022
1023         buffer += sprintf (buffer,"NCaps:\t%016llx\n"
1024                 ,(unsigned long long)nxi->nx_ncaps);
1025         buffer += sprintf (buffer,"NFlags:\t%016llx\n"
1026                 ,(unsigned long long)nxi->nx_flags);
1027
1028         for (i=0; i<nxi->nbipv4; i++){
1029                 buffer += sprintf (buffer,
1030                         "V4Root[%d]:\t%d.%d.%d.%d/%d.%d.%d.%d\n", i
1031                         ,NIPQUAD(nxi->ipv4[i])
1032                         ,NIPQUAD(nxi->mask[i]));
1033         }
1034         buffer += sprintf (buffer,
1035                 "V4Root[bcast]:\t%d.%d.%d.%d\n"
1036                 ,NIPQUAD(nxi->v4_bcast));
1037
1038         put_nx_info(nxi);
1039 out:
1040         return buffer - orig;
1041 }
1042