*
* Virtual Context Support
*
- * Copyright (C) 2003-2004 Herbert Pötzl
+ * Copyright (C) 2003-2005 Herbert Pötzl
*
* V0.01 basic structure
* V0.02 adaptation vs1.3.0
*
*/
-#include <linux/config.h>
#include <linux/errno.h>
#include <linux/proc_fs.h>
-#include <linux/vserver.h>
+#include <linux/sched.h>
+#include <linux/vs_base.h>
+#include <linux/vs_context.h>
+#include <linux/vs_network.h>
+#include <linux/vs_cvirt.h>
+#include <linux/vserver/switch.h>
#include <asm/uaccess.h>
#include <asm/unistd.h>
+#include "cvirt_proc.h"
+#include "limit_proc.h"
+#include "sched_proc.h"
+#include "vci_config.h"
static struct proc_dir_entry *proc_virtual;
PROC_NID_STATUS,
};
-#define PROC_VID_MASK 0x60
+#define PROC_VID_MASK 0x60
/* first the actual feeds */
return sprintf(buffer,
"VCIVersion:\t%04x:%04x\n"
"VCISyscall:\t%d\n"
+ "VCIKernel:\t%08x\n"
,VCI_VERSION >> 16
,VCI_VERSION & 0xFFFF
,__NR_vserver
+ ,vci_kernel_config()
);
}
struct vx_info *vxi;
int length;
- vxi = find_vx_info(vid);
+ vxi = lookup_vx_info(vid);
if (!vxi)
return 0;
length = sprintf(buffer,
struct vx_info *vxi;
int length;
- vxi = find_vx_info(vid);
+ vxi = lookup_vx_info(vid);
if (!vxi)
return 0;
length = sprintf(buffer,
- "RefC:\t%d\n"
+ "UseCnt:\t%d\n"
+ "Tasks:\t%d\n"
"Flags:\t%016llx\n"
"BCaps:\t%016llx\n"
"CCaps:\t%016llx\n"
- "Ticks:\t%d\n"
- ,atomic_read(&vxi->vx_refcount)
- ,vxi->vx_flags
- ,vxi->vx_bcaps
- ,vxi->vx_ccaps
+ "Ticks:\t%d\n"
+ ,atomic_read(&vxi->vx_usecnt)
+ ,atomic_read(&vxi->vx_tasks)
+ ,(unsigned long long)vxi->vx_flags
+ ,(unsigned long long)vxi->vx_bcaps
+ ,(unsigned long long)vxi->vx_ccaps
,atomic_read(&vxi->limit.ticks)
);
put_vx_info(vxi);
struct vx_info *vxi;
int length;
- vxi = find_vx_info(vid);
+ vxi = lookup_vx_info(vid);
if (!vxi)
return 0;
length = vx_info_proc_limit(&vxi->limit, buffer);
struct vx_info *vxi;
int length;
- vxi = find_vx_info(vid);
+ vxi = lookup_vx_info(vid);
if (!vxi)
return 0;
length = vx_info_proc_sched(&vxi->sched, buffer);
struct vx_info *vxi;
int length;
- vxi = find_vx_info(vid);
+ vxi = lookup_vx_info(vid);
if (!vxi)
return 0;
+ vx_update_load(vxi);
length = vx_info_proc_cvirt(&vxi->cvirt, buffer);
put_vx_info(vxi);
return length;
struct vx_info *vxi;
int length;
- vxi = find_vx_info(vid);
+ vxi = lookup_vx_info(vid);
if (!vxi)
return 0;
length = vx_info_proc_cacct(&vxi->cacct, buffer);
);
}
-#define atoquad(a) \
- (((a)>>0) & 0xff), (((a)>>8) & 0xff), \
- (((a)>>16) & 0xff), (((a)>>24) & 0xff)
int proc_nid_info (int vid, char *buffer)
{
struct nx_info *nxi;
int length, i;
- nxi = find_nx_info(vid);
+ nxi = lookup_nx_info(vid);
if (!nxi)
return 0;
length = sprintf(buffer,
);
for (i=0; i<nxi->nbipv4; i++) {
length += sprintf(buffer + length,
- "%d:\t%d.%d.%d.%d/%d.%d.%d.%d\n", i,
- atoquad(nxi->ipv4[i]),
- atoquad(nxi->mask[i]));
+ "%d:\t" NIPQUAD_FMT "/" NIPQUAD_FMT "\n", i,
+ NIPQUAD(nxi->ipv4[i]), NIPQUAD(nxi->mask[i]));
}
put_nx_info(nxi);
return length;
struct nx_info *nxi;
int length;
- nxi = find_nx_info(vid);
+ nxi = lookup_nx_info(vid);
if (!nxi)
return 0;
length = sprintf(buffer,
- "RefC:\t%d\n"
- ,atomic_read(&nxi->nx_refcount)
+ "UseCnt:\t%d\n"
+ "Tasks:\t%d\n"
+ ,atomic_read(&nxi->nx_usecnt)
+ ,atomic_read(&nxi->nx_tasks)
);
put_nx_info(nxi);
return length;
/* here the inode helpers */
+#define fake_ino(id,nr) (((nr) & 0xFFFF) | \
+ (((id) & 0xFFFF) << 16))
-#define fake_ino(id,ino) (((id)<<16)|(ino))
-
-#define inode_vid(i) ((i)->i_ino >> 16)
-#define inode_type(i) ((i)->i_ino & 0xFFFF)
+#define inode_vid(i) (((i)->i_ino >> 16) & 0xFFFF)
+#define inode_type(i) ((i)->i_ino & 0xFFFF)
#define MAX_MULBY10 ((~0U-9)/10)
inode->i_uid = 0;
inode->i_gid = 0;
- // inode->i_xid = xid;
out:
return inode;
}
static int proc_vid_revalidate(struct dentry * dentry, struct nameidata *nd)
{
struct inode * inode = dentry->d_inode;
- int vid, valid=0;
+ int vid, hashed=0;
vid = inode_vid(inode);
switch (inode_type(inode) & PROC_VID_MASK) {
case PROC_XID_INO:
- valid = vx_info_id_valid(vid);
+ hashed = xid_is_hashed(vid);
break;
case PROC_NID_INO:
- valid = nx_info_id_valid(vid);
+ hashed = nid_is_hashed(vid);
break;
- }
- if (valid)
+ }
+ if (hashed)
return 1;
d_drop(dentry);
return 0;
}
-/*
-static int proc_vid_delete_dentry(struct dentry * dentry)
-{
- return 1;
-}
-*/
-
#define PROC_BLOCK_SIZE (PAGE_SIZE - 1024)
-static ssize_t proc_vid_info_read(struct file * file, char * buf,
+static ssize_t proc_vid_info_read(struct file * file, char __user * buf,
size_t count, loff_t *ppos)
{
struct inode * inode = file->f_dentry->d_inode;
unsigned long page;
ssize_t length;
- ssize_t end;
int vid;
if (count > PROC_BLOCK_SIZE)
vid = inode_vid(inode);
length = PROC_I(inode)->op.proc_vid_read(vid, (char*)page);
- if (length < 0) {
- free_page(page);
- return length;
- }
- /* Static 4kB (or whatever) block capacity */
- if (*ppos >= length) {
- free_page(page);
- return 0;
- }
- if (count + *ppos > length)
- count = length - *ppos;
- end = count + *ppos;
- copy_to_user(buf, (char *) page + *ppos, count);
- *ppos = end;
+ if (length >= 0)
+ length = simple_read_from_buffer(buf, count, ppos,
+ (char *)page, length);
free_page(page);
- return count;
+ return length;
}
/* here comes the lower level (vid) */
static struct file_operations proc_vid_info_file_operations = {
- read: proc_vid_info_read,
+ .read = proc_vid_info_read,
};
static struct dentry_operations proc_vid_dentry_operations = {
- d_revalidate: proc_vid_revalidate,
-// d_delete: proc_vid_delete_dentry,
+ .d_revalidate = proc_vid_revalidate,
};
switch (inode_type(dir)) {
case PROC_XID_INO:
- p = vx_base_stuff;
+ p = vx_base_stuff;
break;
case PROC_NID_INO:
- p = vn_base_stuff;
+ p = vn_base_stuff;
break;
default:
goto out;
case PROC_NID_STATUS:
PROC_I(inode)->op.proc_vid_read = proc_nid_status;
break;
-
+
default:
printk("procfs: impossible type (%d)",p->type);
iput(inode);
return ERR_PTR(-EINVAL);
}
inode->i_mode = p->mode;
-// inode->i_op = &proc_vid_info_inode_operations;
inode->i_fop = &proc_vid_info_file_operations;
inode->i_nlink = 1;
inode->i_flags|=S_IMMUTABLE;
-
+
dentry->d_op = &proc_vid_dentry_operations;
d_add(dentry, inode);
error = 0;
int i, size;
struct inode *inode = filp->f_dentry->d_inode;
struct vid_entry *p;
-
+
i = filp->f_pos;
switch (i) {
- case 0:
- if (filldir(dirent, ".", 1, i,
- inode->i_ino, DT_DIR) < 0)
- return 0;
- i++;
- filp->f_pos++;
- /* fall through */
- case 1:
- if (filldir(dirent, "..", 2, i,
- PROC_ROOT_INO, DT_DIR) < 0)
+ case 0:
+ if (filldir(dirent, ".", 1, i,
+ inode->i_ino, DT_DIR) < 0)
+ return 0;
+ i++;
+ filp->f_pos++;
+ /* fall through */
+ case 1:
+ if (filldir(dirent, "..", 2, i,
+ PROC_ROOT_INO, DT_DIR) < 0)
+ return 0;
+ i++;
+ filp->f_pos++;
+ /* fall through */
+ default:
+ i -= 2;
+ switch (inode_type(inode)) {
+ case PROC_XID_INO:
+ size = sizeof(vx_base_stuff);
+ p = vx_base_stuff + i;
+ break;
+ case PROC_NID_INO:
+ size = sizeof(vn_base_stuff);
+ p = vn_base_stuff + i;
+ break;
+ default:
+ return 1;
+ }
+ if (i >= size/sizeof(struct vid_entry))
+ return 1;
+ while (p->name) {
+ if (filldir(dirent, p->name, p->len,
+ filp->f_pos, fake_ino(inode_vid(inode),
+ p->type), p->mode >> 12) < 0)
return 0;
- i++;
filp->f_pos++;
- /* fall through */
- default:
- i -= 2;
- switch (inode_type(inode)) {
- case PROC_XID_INO:
- size = sizeof(vx_base_stuff);
- p = vx_base_stuff + i;
- break;
- case PROC_NID_INO:
- size = sizeof(vn_base_stuff);
- p = vn_base_stuff + i;
- break;
- default:
- return 1;
- }
- if (i >= size/sizeof(struct vid_entry))
- return 1;
- while (p->name) {
- if (filldir(dirent, p->name, p->len,
- filp->f_pos, fake_ino(inode_vid(inode),
- p->type), p->mode >> 12) < 0)
- return 0;
- filp->f_pos++;
- p++;
- }
+ p++;
+ }
}
return 1;
}
/* now the upper level (virtual) */
static struct file_operations proc_vid_file_operations = {
- read: generic_read_dir,
- readdir: proc_vid_readdir,
+ .read = generic_read_dir,
+ .readdir = proc_vid_readdir,
};
static struct inode_operations proc_vid_inode_operations = {
- lookup: proc_vid_lookup,
+ .lookup = proc_vid_lookup,
};
inode->i_ino = fake_ino(1, PROC_XID_INO);
inode->i_mode = S_IFLNK|S_IRWXUGO;
inode->i_uid = inode->i_gid = 0;
- inode->i_size = 64;
-// inode->i_op = &proc_current_inode_operations;
d_add(dentry, inode);
return NULL;
}
inode->i_fop = &proc_vid_info_file_operations;
PROC_I(inode)->op.proc_vid_read = proc_virtual_info;
inode->i_mode = S_IFREG|S_IRUGO;
-// inode->i_size = 64;
-// inode->i_op = &proc_current_inode_operations;
d_add(dentry, inode);
return NULL;
}
xid = atovid(name, len);
if (xid < 0)
goto out;
- vxi = find_vx_info(xid);
+ vxi = lookup_vx_info(xid);
if (!vxi)
goto out;
if (!inode)
goto out_release;
- inode->i_mode = S_IFDIR|S_IRUGO;
+ inode->i_mode = S_IFDIR|S_IRUGO|S_IXUGO;
inode->i_op = &proc_vid_inode_operations;
inode->i_fop = &proc_vid_file_operations;
inode->i_nlink = 2;
dentry->d_op = &proc_vid_dentry_operations;
d_add(dentry, inode);
ret = 0;
-
+
out_release:
put_vx_info(vxi);
out:
inode->i_ino = fake_ino(1, PROC_NID_INO);
inode->i_mode = S_IFLNK|S_IRWXUGO;
inode->i_uid = inode->i_gid = 0;
- inode->i_size = 64;
-// inode->i_op = &proc_current_inode_operations;
d_add(dentry, inode);
return NULL;
}
inode->i_fop = &proc_vid_info_file_operations;
PROC_I(inode)->op.proc_vid_read = proc_vnet_info;
inode->i_mode = S_IFREG|S_IRUGO;
-// inode->i_size = 64;
-// inode->i_op = &proc_current_inode_operations;
d_add(dentry, inode);
return NULL;
}
nid = atovid(name, len);
if (nid < 0)
goto out;
- nxi = find_nx_info(nid);
+ nxi = lookup_nx_info(nid);
if (!nxi)
goto out;
if (!inode)
goto out_release;
- inode->i_mode = S_IFDIR|S_IRUGO;
+ inode->i_mode = S_IFDIR|S_IRUGO|S_IXUGO;
inode->i_op = &proc_vid_inode_operations;
inode->i_fop = &proc_vid_file_operations;
inode->i_nlink = 2;
dentry->d_op = &proc_vid_dentry_operations;
d_add(dentry, inode);
ret = 0;
-
+
out_release:
put_nx_info(nxi);
out:
#define PROC_NUMBUF 10
#define PROC_MAXVIDS 32
-
-static int get_xid_list(int index, unsigned int *xids)
-{
- struct vx_info *p;
- int nr_xids = 0;
-
- index--;
- spin_lock(&vxlist_lock);
- list_for_each_entry(p, &vx_infos, vx_list) {
- int xid = p->vx_id;
-
- if (--index >= 0)
- continue;
- xids[nr_xids] = xid;
- if (++nr_xids >= PROC_MAXVIDS)
- break;
- }
- spin_unlock(&vxlist_lock);
- return nr_xids;
-}
-
int proc_virtual_readdir(struct file * filp,
void * dirent, filldir_t filldir)
{
ino_t ino;
switch ((long)filp->f_pos) {
- case 0:
- ino = fake_ino(0, PROC_XID_INO);
- if (filldir(dirent, ".", 1,
- filp->f_pos, ino, DT_DIR) < 0)
- return 0;
- filp->f_pos++;
- /* fall through */
- case 1:
- ino = filp->f_dentry->d_parent->d_inode->i_ino;
- if (filldir(dirent, "..", 2,
- filp->f_pos, ino, DT_DIR) < 0)
- return 0;
- filp->f_pos++;
- /* fall through */
- case 2:
- ino = fake_ino(0, PROC_XID_INFO);
- if (filldir(dirent, "info", 4,
+ case 0:
+ ino = fake_ino(0, PROC_XID_INO);
+ if (filldir(dirent, ".", 1,
+ filp->f_pos, ino, DT_DIR) < 0)
+ return 0;
+ filp->f_pos++;
+ /* fall through */
+ case 1:
+ ino = filp->f_dentry->d_parent->d_inode->i_ino;
+ if (filldir(dirent, "..", 2,
+ filp->f_pos, ino, DT_DIR) < 0)
+ return 0;
+ filp->f_pos++;
+ /* fall through */
+ case 2:
+ ino = fake_ino(0, PROC_XID_INFO);
+ if (filldir(dirent, "info", 4,
+ filp->f_pos, ino, DT_LNK) < 0)
+ return 0;
+ filp->f_pos++;
+ /* fall through */
+ case 3:
+ if (vx_current_xid() > 1) {
+ ino = fake_ino(1, PROC_XID_INO);
+ if (filldir(dirent, "current", 7,
filp->f_pos, ino, DT_LNK) < 0)
return 0;
- filp->f_pos++;
- /* fall through */
- case 3:
- if (current->xid > 1) {
- ino = fake_ino(1, PROC_XID_INO);
- if (filldir(dirent, "current", 7,
- filp->f_pos, ino, DT_LNK) < 0)
- return 0;
- }
- filp->f_pos++;
+ }
+ filp->f_pos++;
}
- nr_xids = get_xid_list(nr, xid_array);
-
+ nr_xids = get_xid_list(nr, xid_array, PROC_MAXVIDS);
for (i = 0; i < nr_xids; i++) {
int xid = xid_array[i];
ino_t ino = fake_ino(xid, PROC_XID_INO);
- unsigned long j = PROC_NUMBUF;
+ unsigned int j = PROC_NUMBUF;
do buf[--j] = '0' + (xid % 10); while (xid/=10);
static struct file_operations proc_virtual_dir_operations = {
- read: generic_read_dir,
- readdir: proc_virtual_readdir,
+ .read = generic_read_dir,
+ .readdir = proc_virtual_readdir,
};
static struct inode_operations proc_virtual_dir_inode_operations = {
- lookup: proc_virtual_lookup,
+ .lookup = proc_virtual_lookup,
};
-
-static int get_nid_list(int index, unsigned int *nids)
-{
- struct nx_info *p;
- int nr_nids = 0;
-
- index--;
- spin_lock(&nxlist_lock);
- list_for_each_entry(p, &nx_infos, nx_list) {
- int nid = p->nx_id;
-
- if (--index >= 0)
- continue;
- nids[nr_nids] = nid;
- if (++nr_nids >= PROC_MAXVIDS)
- break;
- }
- spin_unlock(&nxlist_lock);
- return nr_nids;
-}
-
int proc_vnet_readdir(struct file * filp,
void * dirent, filldir_t filldir)
{
unsigned int nid_array[PROC_MAXVIDS];
char buf[PROC_NUMBUF];
- unsigned int nr = filp->f_pos-3;
+ unsigned int nr = filp->f_pos-2;
unsigned int nr_nids, i;
ino_t ino;
switch ((long)filp->f_pos) {
- case 0:
- ino = fake_ino(0, PROC_NID_INO);
- if (filldir(dirent, ".", 1,
- filp->f_pos, ino, DT_DIR) < 0)
- return 0;
- filp->f_pos++;
- /* fall through */
- case 1:
- ino = filp->f_dentry->d_parent->d_inode->i_ino;
- if (filldir(dirent, "..", 2,
- filp->f_pos, ino, DT_DIR) < 0)
- return 0;
- filp->f_pos++;
- /* fall through */
- case 2:
- ino = fake_ino(0, PROC_NID_INFO);
- if (filldir(dirent, "info", 4,
- filp->f_pos, ino, DT_LNK) < 0)
- return 0;
- filp->f_pos++;
- /* fall through */
- case 3:
- if (current->xid > 1) {
- ino = fake_ino(1, PROC_NID_INO);
- if (filldir(dirent, "current", 7,
- filp->f_pos, ino, DT_LNK) < 0)
- return 0;
- }
- filp->f_pos++;
+ case 0:
+ ino = fake_ino(0, PROC_NID_INO);
+ if (filldir(dirent, ".", 1,
+ filp->f_pos, ino, DT_DIR) < 0)
+ return 0;
+ filp->f_pos++;
+ /* fall through */
+ case 1:
+ ino = filp->f_dentry->d_parent->d_inode->i_ino;
+ if (filldir(dirent, "..", 2,
+ filp->f_pos, ino, DT_DIR) < 0)
+ return 0;
+ filp->f_pos++;
+ /* fall through */
+ case 2:
+ ino = fake_ino(0, PROC_NID_INFO);
+ if (filldir(dirent, "info", 4,
+ filp->f_pos, ino, DT_REG) < 0)
+ return 0;
+ filp->f_pos++;
+ /* fall through */
}
- nr_nids = get_nid_list(nr, nid_array);
-
+ nr_nids = get_nid_list(nr, nid_array, PROC_MAXVIDS);
for (i = 0; i < nr_nids; i++) {
int nid = nid_array[i];
ino_t ino = fake_ino(nid, PROC_NID_INO);
static struct file_operations proc_vnet_dir_operations = {
- read: generic_read_dir,
- readdir: proc_vnet_readdir,
+ .read = generic_read_dir,
+ .readdir = proc_vnet_readdir,
};
static struct inode_operations proc_vnet_dir_inode_operations = {
- lookup: proc_vnet_lookup,
+ .lookup = proc_vnet_lookup,
};
}
proc_virtual = ent;
- ent = proc_mkdir("vnet", 0);
+ ent = proc_mkdir("virtnet", 0);
if (ent) {
ent->proc_fops = &proc_vnet_dir_operations;
ent->proc_iops = &proc_vnet_dir_inode_operations;
/* per pid info */
-char *task_vx_info(struct task_struct *p, char *buffer)
-{
- return buffer + sprintf(buffer,
- "XID:\t%d\n"
- ,p->xid);
-}
-
int proc_pid_vx_info(struct task_struct *p, char *buffer)
{
+ struct vx_info *vxi;
char * orig = buffer;
- buffer = task_vx_info(p, buffer);
+ buffer += sprintf (buffer,"XID:\t%d\n", vx_task_xid(p));
+ if (vx_flags(VXF_INFO_HIDE, 0))
+ goto out;
+
+ vxi = task_get_vx_info(p);
+ if (!vxi)
+ goto out;
+
+ buffer += sprintf (buffer,"BCaps:\t%016llx\n"
+ ,(unsigned long long)vxi->vx_bcaps);
+ buffer += sprintf (buffer,"CCaps:\t%016llx\n"
+ ,(unsigned long long)vxi->vx_ccaps);
+ buffer += sprintf (buffer,"CFlags:\t%016llx\n"
+ ,(unsigned long long)vxi->vx_flags);
+ buffer += sprintf (buffer,"CIPid:\t%d\n"
+ ,vxi->vx_initpid);
+
+ put_vx_info(vxi);
+out:
return buffer - orig;
}
-char *task_nx_info(struct task_struct *p, char *buffer)
-{
- return buffer + sprintf(buffer,
- "NID:\t%d\n"
- ,p->nid);
-}
int proc_pid_nx_info(struct task_struct *p, char *buffer)
{
+ struct nx_info *nxi;
char * orig = buffer;
+ int i;
- buffer = task_nx_info(p, buffer);
+ buffer += sprintf (buffer,"NID:\t%d\n", nx_task_nid(p));
+ if (vx_flags(VXF_INFO_HIDE, 0))
+ goto out;
+ nxi = task_get_nx_info(p);
+ if (!nxi)
+ goto out;
+
+ for (i=0; i<nxi->nbipv4; i++){
+ buffer += sprintf (buffer,
+ "V4Root[%d]:\t%d.%d.%d.%d/%d.%d.%d.%d\n", i
+ ,NIPQUAD(nxi->ipv4[i])
+ ,NIPQUAD(nxi->mask[i]));
+ }
+ buffer += sprintf (buffer,
+ "V4Root[bcast]:\t%d.%d.%d.%d\n"
+ ,NIPQUAD(nxi->v4_bcast));
+
+ put_nx_info(nxi);
+out:
return buffer - orig;
}