+
+
+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;
+ unsigned long flags;
+
+ spin_lock_irqsave(&vxi->cvirt.load_lock, flags);
+
+ 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_irqrestore(&vxi->cvirt.load_lock, flags);
+}
+
+
+/*
+ * 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)
+{
+ struct nsproxy *nsproxy;
+ struct uts_namespace *uts;
+
+
+ if (id == VHIN_CONTEXT)
+ return vxi->vx_name;
+
+ nsproxy = vxi->vx_nsproxy;
+ if (!nsproxy)
+ return NULL;
+
+ uts = nsproxy->uts_ns;
+ if (!uts)
+ return NULL;
+
+ switch (id) {
+ case VHIN_SYSNAME:
+ return uts->name.sysname;
+ case VHIN_NODENAME:
+ return uts->name.nodename;
+ case VHIN_RELEASE:
+ return uts->name.release;
+ case VHIN_VERSION:
+ return uts->name.version;
+ case VHIN_MACHINE:
+ return uts->name.machine;
+ case VHIN_DOMAINNAME:
+ return uts->name.domainname;
+ default:
+ return NULL;
+ }
+ return NULL;
+}
+
+int vc_set_vhi_name(struct vx_info *vxi, void __user *data)
+{
+ struct vcmd_vhi_name_v0 vc_data;
+ char *name;
+
+ if (copy_from_user (&vc_data, data, sizeof(vc_data)))
+ return -EFAULT;
+
+ name = vx_vhi_name(vxi, vc_data.field);
+ if (!name)
+ return -EINVAL;
+
+ memcpy(name, vc_data.name, 65);
+ return 0;
+}
+
+int vc_get_vhi_name(struct vx_info *vxi, void __user *data)
+{
+ struct vcmd_vhi_name_v0 vc_data;
+ char *name;
+
+ if (copy_from_user (&vc_data, data, sizeof(vc_data)))
+ return -EFAULT;
+
+ name = vx_vhi_name(vxi, vc_data.field);
+ if (!name)
+ return -EINVAL;
+
+ memcpy(vc_data.name, name, 65);
+ if (copy_to_user (data, &vc_data, sizeof(vc_data)))
+ return -EFAULT;
+ return 0;
+}
+
+
+int vc_virt_stat(struct vx_info *vxi, void __user *data)
+{
+ struct vcmd_virt_stat_v0 vc_data;
+ struct _vx_cvirt *cvirt = &vxi->cvirt;
+ struct timespec uptime;
+
+ do_posix_clock_monotonic_gettime(&uptime);
+ set_normalized_timespec(&uptime,
+ uptime.tv_sec - cvirt->bias_uptime.tv_sec,
+ uptime.tv_nsec - cvirt->bias_uptime.tv_nsec);
+
+ vc_data.offset = timeval_to_ns(&cvirt->bias_tv);
+ vc_data.uptime = timespec_to_ns(&uptime);
+ vc_data.nr_threads = atomic_read(&cvirt->nr_threads);
+ vc_data.nr_running = atomic_read(&cvirt->nr_running);
+ vc_data.nr_uninterruptible = atomic_read(&cvirt->nr_uninterruptible);
+ vc_data.nr_onhold = atomic_read(&cvirt->nr_onhold);
+ vc_data.nr_forks = atomic_read(&cvirt->total_forks);
+ vc_data.load[0] = cvirt->load[0];
+ vc_data.load[1] = cvirt->load[1];
+ vc_data.load[2] = cvirt->load[2];
+
+ if (copy_to_user (data, &vc_data, sizeof(vc_data)))
+ return -EFAULT;
+ return 0;
+}
+
+
+#ifdef CONFIG_VSERVER_VTIME
+
+/* virtualized time base */
+
+void vx_gettimeofday(struct timeval *tv)
+{
+ do_gettimeofday(tv);
+ if (!vx_flags(VXF_VIRT_TIME, 0))
+ return;
+
+ tv->tv_sec += current->vx_info->cvirt.bias_tv.tv_sec;
+ tv->tv_usec += current->vx_info->cvirt.bias_tv.tv_usec;
+
+ if (tv->tv_usec >= USEC_PER_SEC) {
+ tv->tv_sec++;
+ tv->tv_usec -= USEC_PER_SEC;
+ } else if (tv->tv_usec < 0) {
+ tv->tv_sec--;
+ tv->tv_usec += USEC_PER_SEC;
+ }
+}
+
+int vx_settimeofday(struct timespec *ts)
+{
+ struct timeval tv;
+
+ if (!vx_flags(VXF_VIRT_TIME, 0))
+ return do_settimeofday(ts);
+
+ do_gettimeofday(&tv);
+ current->vx_info->cvirt.bias_tv.tv_sec =
+ ts->tv_sec - tv.tv_sec;
+ current->vx_info->cvirt.bias_tv.tv_usec =
+ (ts->tv_nsec/NSEC_PER_USEC) - tv.tv_usec;
+ return 0;
+}
+
+#endif
+