X-Git-Url: http://git.onelab.eu/?a=blobdiff_plain;f=kernel%2Fvserver%2Fcvirt.c;h=48053039d2b9eb6fe47600a4440c0997ad386caa;hb=43bc926fffd92024b46cafaf7350d669ba9ca884;hp=2b5c81e35b13c9ff6365a84762a3d2ef46aa4c52;hpb=b76fcd5f0c655b6e3e9bf534594357025421c66a;p=linux-2.6.git diff --git a/kernel/vserver/cvirt.c b/kernel/vserver/cvirt.c index 2b5c81e35..48053039d 100644 --- a/kernel/vserver/cvirt.c +++ b/kernel/vserver/cvirt.c @@ -3,17 +3,20 @@ * * Virtual Server: Context Virtualization * - * Copyright (C) 2004 Herbert Pötzl + * Copyright (C) 2004-2005 Herbert Pötzl * * V0.01 broken out from limit.c + * V0.02 added utsname stuff * */ -#include -#include -#include +#include +#include +#include +#include +#include #include -#include +#include #include #include @@ -24,8 +27,8 @@ void vx_vsi_uptime(struct timespec *uptime, struct timespec *idle) struct vx_info *vxi = current->vx_info; set_normalized_timespec(uptime, - uptime->tv_sec - vxi->cvirt.bias_tp.tv_sec, - uptime->tv_nsec - vxi->cvirt.bias_tp.tv_nsec); + uptime->tv_sec - vxi->cvirt.bias_uptime.tv_sec, + uptime->tv_nsec - vxi->cvirt.bias_uptime.tv_nsec); if (!idle) return; set_normalized_timespec(idle, @@ -34,8 +37,223 @@ void vx_vsi_uptime(struct timespec *uptime, struct timespec *idle) return; } -uint64_t vx_idle_jiffies() +uint64_t vx_idle_jiffies(void) { return init_task.utime + init_task.stime; } + + +static inline uint32_t __update_loadavg(uint32_t load, + int wsize, int delta, int n) +{ + unsigned long long calc, prev; + + /* just set it to n */ + if (unlikely(delta >= wsize)) + return (n << FSHIFT); + + calc = delta * n; + calc <<= FSHIFT; + prev = (wsize - delta); + prev *= load; + calc += prev; + do_div(calc, wsize); + return calc; +} + + +void vx_update_load(struct vx_info *vxi) +{ + uint32_t now, last, delta; + unsigned int nr_running, nr_uninterruptible; + unsigned int total; + + spin_lock(&vxi->cvirt.load_lock); + + now = jiffies; + last = vxi->cvirt.load_last; + delta = now - last; + + if (delta < 5*HZ) + goto out; + + nr_running = atomic_read(&vxi->cvirt.nr_running); + nr_uninterruptible = atomic_read(&vxi->cvirt.nr_uninterruptible); + total = nr_running + nr_uninterruptible; + + vxi->cvirt.load[0] = __update_loadavg(vxi->cvirt.load[0], + 60*HZ, delta, total); + vxi->cvirt.load[1] = __update_loadavg(vxi->cvirt.load[1], + 5*60*HZ, delta, total); + vxi->cvirt.load[2] = __update_loadavg(vxi->cvirt.load[2], + 15*60*HZ, delta, total); + + vxi->cvirt.load_last = now; +out: + atomic_inc(&vxi->cvirt.load_updates); + spin_unlock(&vxi->cvirt.load_lock); +} + + +int vx_uts_virt_handler(struct ctl_table *ctl, int write, xid_t xid, + void **datap, size_t *lenp) +{ + switch (ctl->ctl_name) { + case KERN_OSTYPE: + *datap = vx_new_uts(sysname); + break; + case KERN_OSRELEASE: + *datap = vx_new_uts(release); + break; + case KERN_VERSION: + *datap = vx_new_uts(version); + break; + case KERN_NODENAME: + *datap = vx_new_uts(nodename); + break; + case KERN_DOMAINNAME: + *datap = vx_new_uts(domainname); + break; + } + + return 0; +} + + + +/* + * Commands to do_syslog: + * + * 0 -- Close the log. Currently a NOP. + * 1 -- Open the log. Currently a NOP. + * 2 -- Read from the log. + * 3 -- Read all messages remaining in the ring buffer. + * 4 -- Read and clear all messages remaining in the ring buffer + * 5 -- Clear ring buffer. + * 6 -- Disable printk's to console + * 7 -- Enable printk's to console + * 8 -- Set level of messages printed to console + * 9 -- Return number of unread characters in the log buffer + * 10 -- Return size of the log buffer + */ +int vx_do_syslog(int type, char __user *buf, int len) +{ + int error = 0; + int do_clear = 0; + struct vx_info *vxi = current->vx_info; + struct _vx_syslog *log; + + if (!vxi) + return -EINVAL; + log = &vxi->cvirt.syslog; + + switch (type) { + case 0: /* Close log */ + case 1: /* Open log */ + break; + case 2: /* Read from log */ + error = wait_event_interruptible(log->log_wait, + (log->log_start - log->log_end)); + if (error) + break; + spin_lock_irq(&log->logbuf_lock); + spin_unlock_irq(&log->logbuf_lock); + break; + case 4: /* Read/clear last kernel messages */ + do_clear = 1; + /* fall through */ + case 3: /* Read last kernel messages */ + return 0; + + case 5: /* Clear ring buffer */ + return 0; + + case 6: /* Disable logging to console */ + case 7: /* Enable logging to console */ + case 8: /* Set level of messages printed to console */ + break; + + case 9: /* Number of chars in the log buffer */ + return 0; + case 10: /* Size of the log buffer */ + return 0; + default: + error = -EINVAL; + break; + } + return error; +} + + +/* virtual host info names */ + +static char * vx_vhi_name(struct vx_info *vxi, int id) +{ + switch (id) { + case VHIN_CONTEXT: + return vxi->vx_name; + case VHIN_SYSNAME: + return vxi->cvirt.utsname.sysname; + case VHIN_NODENAME: + return vxi->cvirt.utsname.nodename; + case VHIN_RELEASE: + return vxi->cvirt.utsname.release; + case VHIN_VERSION: + return vxi->cvirt.utsname.version; + case VHIN_MACHINE: + return vxi->cvirt.utsname.machine; + case VHIN_DOMAINNAME: + return vxi->cvirt.utsname.domainname; + default: + return NULL; + } + return NULL; +} + +int vc_set_vhi_name(uint32_t id, void __user *data) +{ + struct vx_info *vxi; + struct vcmd_vhi_name_v0 vc_data; + char *name; + + if (!capable(CAP_SYS_ADMIN)) + return -EPERM; + if (copy_from_user (&vc_data, data, sizeof(vc_data))) + return -EFAULT; + + vxi = lookup_vx_info(id); + if (!vxi) + return -ESRCH; + + name = vx_vhi_name(vxi, vc_data.field); + if (name) + memcpy(name, vc_data.name, 65); + put_vx_info(vxi); + return (name ? 0 : -EFAULT); +} + +int vc_get_vhi_name(uint32_t id, void __user *data) +{ + struct vx_info *vxi; + struct vcmd_vhi_name_v0 vc_data; + char *name; + + if (copy_from_user (&vc_data, data, sizeof(vc_data))) + return -EFAULT; + + vxi = lookup_vx_info(id); + if (!vxi) + return -ESRCH; + + name = vx_vhi_name(vxi, vc_data.field); + if (!name) + goto out_put; + + memcpy(vc_data.name, name, 65); + if (copy_to_user (data, &vc_data, sizeof(vc_data))) + return -EFAULT; +out_put: + put_vx_info(vxi); + return (name ? 0 : -EFAULT); +}