--- linux-2.6.16-rc1/fs/fcntl.c 2006-01-26 22:35:11 +0100 +++ linux-2.6.16-rc1-vs2.1.0.9.4/fs/fcntl.c 2006-01-21 18:28:14 +0100 @@ -85,6 +86,8 @@ repeat: error = -EMFILE; if (newfd >= current->signal->rlim[RLIMIT_NOFILE].rlim_cur) goto out; + if (!vx_files_avail(1)) + goto out; error = expand_files(files, newfd); if (error < 0) --- linux-2.6.16-rc1/fs/fcntl.c 2006-01-26 22:35:11 +0100 +++ linux-2.6.16-rc1-vs2.1.0.9.4/fs/fcntl.c 2006-01-21 18:28:14 +0100 @@ -126,6 +129,7 @@ static int dupfd(struct file *file, unsi FD_SET(fd, fdt->open_fds); FD_CLR(fd, fdt->close_on_exec); spin_unlock(&files->file_lock); + vx_openfd_inc(fd); fd_install(fd, file); } else { spin_unlock(&files->file_lock); --- linux-2.6.16-rc1/fs/fcntl.c 2006-01-26 22:35:11 +0100 +++ linux-2.6.16-rc1-vs2.1.0.9.4/fs/fcntl.c 2006-01-21 18:28:14 +0100 @@ -178,6 +182,9 @@ asmlinkage long sys_dup2(unsigned int ol if (tofree) filp_close(tofree, files); + else + vx_openfd_inc(newfd); /* fd was unused */ + err = newfd; out: return err; --- linux-2.6.16-rc1/fs/file_table.c 2006-01-26 22:35:11 +0100 +++ linux-2.6.16-rc1-vs2.1.0.9.4/fs/file_table.c 2006-01-21 18:28:14 +0100 @@ -97,6 +99,8 @@ struct file *get_empty_filp(void) rwlock_init(&f->f_owner.lock); /* f->f_version: 0 */ INIT_LIST_HEAD(&f->f_u.fu_list); + f->f_xid = vx_current_xid(); + vx_files_inc(f); return f; over: --- linux-2.6.16-rc1/fs/file_table.c 2006-01-26 22:35:11 +0100 +++ linux-2.6.16-rc1-vs2.1.0.9.4/fs/file_table.c 2006-01-21 18:28:14 +0100 @@ -151,6 +155,8 @@ void fastcall __fput(struct file *file) fops_put(file->f_op); if (file->f_mode & FMODE_WRITE) put_write_access(inode); + vx_files_dec(file); + file->f_xid = 0; file_kill(file); file->f_dentry = NULL; file->f_vfsmnt = NULL; --- linux-2.6.16-rc1/fs/file_table.c 2006-01-26 22:35:11 +0100 +++ linux-2.6.16-rc1-vs2.1.0.9.4/fs/file_table.c 2006-01-21 18:28:14 +0100 @@ -216,6 +222,8 @@ void put_filp(struct file *file) { if (atomic_dec_and_test(&file->f_count)) { security_file_free(file); + vx_files_dec(file); + file->f_xid = 0; file_kill(file); file_free(file); } --- linux-2.6.16-rc1/fs/locks.c 2006-01-26 22:35:12 +0100 +++ linux-2.6.16-rc1-vs2.1.0.9.4/fs/locks.c 2006-01-21 18:28:14 +0100 @@ -150,6 +151,8 @@ static kmem_cache_t *filelock_cache; /* Allocate an empty lock structure. */ static struct file_lock *locks_alloc_lock(void) { + if (!vx_locks_avail(1)) + return NULL; return kmem_cache_alloc(filelock_cache, SLAB_KERNEL); } --- linux-2.6.16-rc1/fs/locks.c 2006-01-26 22:35:12 +0100 +++ linux-2.6.16-rc1-vs2.1.0.9.4/fs/locks.c 2006-01-21 18:28:14 +0100 @@ -156,6 +159,8 @@ ***** /* Free a lock which is not in use. */ static void locks_free_lock(struct file_lock *fl) { + vx_locks_dec(fl); + if (fl == NULL) { BUG(); return; --- linux-2.6.16-rc1/fs/locks.c 2006-01-26 22:35:12 +0100 +++ linux-2.6.16-rc1-vs2.1.0.9.4/fs/locks.c 2006-01-21 18:28:14 +0100 @@ -199,6 +204,7 @@ void locks_init_lock(struct file_lock *f fl->fl_start = fl->fl_end = 0; fl->fl_ops = NULL; fl->fl_lmops = NULL; + fl->fl_xid = -1; } EXPORT_SYMBOL(locks_init_lock); --- linux-2.6.16-rc1/fs/locks.c 2006-01-26 22:35:12 +0100 +++ linux-2.6.16-rc1-vs2.1.0.9.4/fs/locks.c 2006-01-21 18:28:14 +0100 @@ -236,6 +242,8 @@ void locks_copy_lock(struct file_lock *n fl->fl_ops->fl_copy_lock(new, fl); if (fl->fl_lmops && fl->fl_lmops->fl_copy_lock) fl->fl_lmops->fl_copy_lock(new, fl); + + new->fl_xid = fl->fl_xid; } EXPORT_SYMBOL(locks_copy_lock); --- linux-2.6.16-rc1/fs/locks.c 2006-01-26 22:35:12 +0100 +++ linux-2.6.16-rc1-vs2.1.0.9.4/fs/locks.c 2006-01-21 18:28:14 +0100 @@ -272,6 +280,11 @@ static int flock_make_lock(struct file * fl->fl_flags = FL_FLOCK; fl->fl_type = type; fl->fl_end = OFFSET_MAX; + + vxd_assert(filp->f_xid == vx_current_xid(), + "f_xid(%d) == current(%d)", filp->f_xid, vx_current_xid()); + fl->fl_xid = filp->f_xid; + vx_locks_inc(fl); *lock = fl; return 0; --- linux-2.6.16-rc1/fs/locks.c 2006-01-26 22:35:12 +0100 +++ linux-2.6.16-rc1-vs2.1.0.9.4/fs/locks.c 2006-01-21 18:28:14 +0100 @@ -457,6 +470,11 @@ static int lease_alloc(struct file *filp if (fl == NULL) return -ENOMEM; + fl->fl_xid = vx_current_xid(); + if (filp) + vxd_assert(filp->f_xid == fl->fl_xid, + "f_xid(%d) == fl_xid(%d)", filp->f_xid, fl->fl_xid); + vx_locks_inc(fl); error = lease_init(filp, type, fl); if (error) return error; --- linux-2.6.16-rc1/fs/locks.c 2006-01-26 22:35:12 +0100 +++ linux-2.6.16-rc1-vs2.1.0.9.4/fs/locks.c 2006-01-21 18:28:14 +0100 @@ -771,7 +789,7 @@ out: EXPORT_SYMBOL(posix_lock_file); -static int __posix_lock_file(struct inode *inode, struct file_lock *request) +static int __posix_lock_file(struct inode *inode, struct file_lock *request, xid_t xid) { struct file_lock *fl; struct file_lock *new_fl, *new_fl2; --- linux-2.6.16-rc1/fs/locks.c 2006-01-26 22:35:12 +0100 +++ linux-2.6.16-rc1-vs2.1.0.9.4/fs/locks.c 2006-01-21 18:28:14 +0100 @@ -780,6 +798,8 @@ static int __posix_lock_file(struct inod struct file_lock **before; int error, added = 0; + vxd_assert(xid == vx_current_xid(), + "xid(%d) == current(%d)", xid, vx_current_xid()); /* * We may need two file_lock structures for this operation, * so we get them in advance to avoid races. --- linux-2.6.16-rc1/fs/locks.c 2006-01-26 22:35:12 +0100 +++ linux-2.6.16-rc1-vs2.1.0.9.4/fs/locks.c 2006-01-21 18:28:14 +0100 @@ -785,7 +805,11 @@ ***** * so we get them in advance to avoid races. */ new_fl = locks_alloc_lock(); + new_fl->fl_xid = xid; + vx_locks_inc(new_fl); new_fl2 = locks_alloc_lock(); + new_fl2->fl_xid = xid; + vx_locks_inc(new_fl2); lock_kernel(); if (request->fl_type != F_UNLCK) { --- linux-2.6.16-rc1/fs/locks.c 2006-01-26 22:35:12 +0100 +++ linux-2.6.16-rc1-vs2.1.0.9.4/fs/locks.c 2006-01-21 18:28:14 +0100 @@ -963,7 +987,7 @@ static int __posix_lock_file(struct inod */ int posix_lock_file(struct file *filp, struct file_lock *fl) { - return __posix_lock_file(filp->f_dentry->d_inode, fl); + return __posix_lock_file(filp->f_dentry->d_inode, fl, filp->f_xid); } /** --- linux-2.6.16-rc1/fs/locks.c 2006-01-26 22:35:12 +0100 +++ linux-2.6.16-rc1-vs2.1.0.9.4/fs/locks.c 2006-01-21 18:28:14 +0100 @@ -980,7 +1004,8 @@ int posix_lock_file_wait(struct file *fi int error; might_sleep (); for (;;) { - error = __posix_lock_file(filp->f_dentry->d_inode, fl); + error = __posix_lock_file(filp->f_dentry->d_inode, + fl, filp->f_xid); if ((error != -EAGAIN) || !(fl->fl_flags & FL_SLEEP)) break; error = wait_event_interruptible(fl->fl_wait, !fl->fl_next); --- linux-2.6.16-rc1/fs/locks.c 2006-01-26 22:35:12 +0100 +++ linux-2.6.16-rc1-vs2.1.0.9.4/fs/locks.c 2006-01-21 18:28:14 +0100 @@ -1052,7 +1077,7 @@ int locks_mandatory_area(int read_write, fl.fl_end = offset + count - 1; for (;;) { - error = __posix_lock_file(inode, &fl); + error = __posix_lock_file(inode, &fl, filp->f_xid); if (error != -EAGAIN) break; if (!(fl.fl_flags & FL_SLEEP)) --- linux-2.6.16-rc1/fs/locks.c 2006-01-26 22:35:12 +0100 +++ linux-2.6.16-rc1-vs2.1.0.9.4/fs/locks.c 2006-01-21 18:28:14 +0100 @@ -1613,6 +1638,11 @@ int fcntl_setlk(unsigned int fd, struct if (file_lock == NULL) return -ENOLCK; + vxd_assert(filp->f_xid == vx_current_xid(), + "f_xid(%d) == current(%d)", filp->f_xid, vx_current_xid()); + file_lock->fl_xid = filp->f_xid; + vx_locks_inc(file_lock); + /* * This might block, so we do it before checking the inode. */ --- linux-2.6.16-rc1/fs/locks.c 2006-01-26 22:35:12 +0100 +++ linux-2.6.16-rc1-vs2.1.0.9.4/fs/locks.c 2006-01-21 18:28:14 +0100 @@ -1665,7 +1695,8 @@ again: error = filp->f_op->lock(filp, cmd, file_lock); else { for (;;) { - error = __posix_lock_file(inode, file_lock); + error = __posix_lock_file(inode, file_lock, + filp->f_xid); if ((error != -EAGAIN) || (cmd == F_SETLK)) break; error = wait_event_interruptible(file_lock->fl_wait, --- linux-2.6.16-rc1/fs/locks.c 2006-01-26 22:35:12 +0100 +++ linux-2.6.16-rc1-vs2.1.0.9.4/fs/locks.c 2006-01-21 18:28:14 +0100 @@ -1756,6 +1787,11 @@ int fcntl_setlk64(unsigned int fd, struc if (file_lock == NULL) return -ENOLCK; + vxd_assert(filp->f_xid == vx_current_xid(), + "f_xid(%d) == current(%d)", filp->f_xid, vx_current_xid()); + file_lock->fl_xid = filp->f_xid; + vx_locks_inc(file_lock); + /* * This might block, so we do it before checking the inode. */ --- linux-2.6.16-rc1/fs/locks.c 2006-01-26 22:35:12 +0100 +++ linux-2.6.16-rc1-vs2.1.0.9.4/fs/locks.c 2006-01-21 18:28:14 +0100 @@ -1808,7 +1844,8 @@ again: error = filp->f_op->lock(filp, cmd, file_lock); else { for (;;) { - error = __posix_lock_file(inode, file_lock); + error = __posix_lock_file(inode, file_lock, + filp->f_xid); if ((error != -EAGAIN) || (cmd == F_SETLK64)) break; error = wait_event_interruptible(file_lock->fl_wait, --- linux-2.6.16-rc1/fs/open.c 2006-01-26 22:35:12 +0100 +++ linux-2.6.16-rc1-vs2.1.0.9.4/fs/open.c 2006-01-25 05:34:51 +0100 @@ -956,6 +963,7 @@ repeat: FD_SET(fd, fdt->open_fds); FD_CLR(fd, fdt->close_on_exec); fdt->next_fd = fd + 1; + vx_openfd_inc(fd); #if 1 /* Sanity check */ if (fdt->fd[fd] != NULL) { --- linux-2.6.16-rc1/fs/open.c 2006-01-26 22:35:12 +0100 +++ linux-2.6.16-rc1-vs2.1.0.9.4/fs/open.c 2006-01-25 05:34:51 +0100 @@ -978,6 +986,7 @@ static void __put_unused_fd(struct files __FD_CLR(fd, fdt->open_fds); if (fd < fdt->next_fd) fdt->next_fd = fd; + vx_openfd_dec(fd); } void fastcall put_unused_fd(unsigned int fd) --- linux-2.6.16-rc1/include/linux/fs.h 2006-01-26 22:35:19 +0100 +++ linux-2.6.16-rc1-vs2.1.0.9.4/include/linux/fs.h 2006-01-29 16:01:52 +0100 @@ -709,6 +729,7 @@ struct file_lock { unsigned char fl_type; loff_t fl_start; loff_t fl_end; + xid_t fl_xid; struct fasync_struct * fl_fasync; /* for lease break notifications */ unsigned long fl_break_time; /* for nonblocking lease breaks */ --- linux-2.6.16-rc1/include/linux/vserver/limit.h 1970-01-01 01:00:00 +0100 +++ linux-2.6.16-rc1-vs2.1.0.9.4/include/linux/vserver/limit.h 2006-01-28 08:54:48 +0100 @@ -0,0 +1,63 @@ +#ifndef _VX_LIMIT_H +#define _VX_LIMIT_H + + +#define VLIMIT_NSOCK 16 +#define VLIMIT_OPENFD 17 +#define VLIMIT_ANON 18 +#define VLIMIT_SHMEM 19 +#define VLIMIT_SEMARY 20 +#define VLIMIT_NSEMS 21 + +#ifdef __KERNEL__ + +/* keep in sync with CRLIM_INFINITY */ + +#define VLIM_INFINITY (~0ULL) + +#ifndef RLIM_INFINITY +#warning RLIM_INFINITY is undefined +#endif + +#define __rlim_val(l,r,v) ((l)->res[(r)].v) + +#define __rlim_soft(l,r) __rlim_val(l,r,soft) +#define __rlim_hard(l,r) __rlim_val(l,r,hard) + +#define __rlim_rcur(l,r) __rlim_val(l,r,rcur) +#define __rlim_rmin(l,r) __rlim_val(l,r,rmin) +#define __rlim_rmax(l,r) __rlim_val(l,r,rmax) + +#define __rlim_lhit(l,r) __rlim_val(l,r,lhit) +#define __rlim_hit(l,r) atomic_inc(&__rlim_lhit(l,r)) + +typedef atomic_long_t rlim_atomic_t; +typedef unsigned long rlim_t; + +#define __rlim_get(l,r) atomic_long_read(&__rlim_rcur(l,r)) +#define __rlim_set(l,r,v) atomic_long_set(&__rlim_rcur(l,r), v) +#define __rlim_inc(l,r) atomic_long_inc(&__rlim_rcur(l,r)) +#define __rlim_dec(l,r) atomic_long_dec(&__rlim_rcur(l,r)) +#define __rlim_add(l,r,v) atomic_long_add(v, &__rlim_rcur(l,r)) +#define __rlim_sub(l,r,v) atomic_long_sub(v, &__rlim_rcur(l,r)) + + +#if (RLIM_INFINITY == VLIM_INFINITY) +#define VX_VLIM(r) ((long long)(long)(r)) +#define VX_RLIM(v) ((rlim_t)(v)) +#else +#define VX_VLIM(r) (((r) == RLIM_INFINITY) \ + ? VLIM_INFINITY : (long long)(r)) +#define VX_RLIM(v) (((v) == VLIM_INFINITY) \ + ? RLIM_INFINITY : (rlim_t)(v)) +#endif + +struct sysinfo; + +void vx_vsi_meminfo(struct sysinfo *); +void vx_vsi_swapinfo(struct sysinfo *); + +#define NUM_LIMITS 24 + +#endif /* __KERNEL__ */ +#endif /* _VX_LIMIT_H */ --- linux-2.6.16-rc1/ipc/mqueue.c 2006-01-26 22:35:32 +0100 +++ linux-2.6.16-rc1-vs2.1.0.9.4/ipc/mqueue.c 2006-01-21 18:28:17 +0100 @@ -148,7 +150,8 @@ static struct inode *mqueue_get_inode(st spin_lock(&mq_lock); if (u->mq_bytes + mq_bytes < u->mq_bytes || u->mq_bytes + mq_bytes > - p->signal->rlim[RLIMIT_MSGQUEUE].rlim_cur) { + p->signal->rlim[RLIMIT_MSGQUEUE].rlim_cur || + !vx_ipcmsg_avail(p->vx_info, mq_bytes)) { spin_unlock(&mq_lock); goto out_inode; } --- linux-2.6.16-rc1/ipc/mqueue.c 2006-01-26 22:35:32 +0100 +++ linux-2.6.16-rc1-vs2.1.0.9.4/ipc/mqueue.c 2006-01-21 18:28:17 +0100 @@ -153,6 +156,7 @@ ***** goto out_inode; } u->mq_bytes += mq_bytes; + vx_ipcmsg_add(p->vx_info, u, mq_bytes); spin_unlock(&mq_lock); info->messages = kmalloc(mq_msg_tblsz, GFP_KERNEL); --- linux-2.6.16-rc1/ipc/mqueue.c 2006-01-26 22:35:32 +0100 +++ linux-2.6.16-rc1-vs2.1.0.9.4/ipc/mqueue.c 2006-01-21 18:28:17 +0100 @@ -159,6 +163,7 @@ ***** if (!info->messages) { spin_lock(&mq_lock); u->mq_bytes -= mq_bytes; + vx_ipcmsg_sub(p->vx_info, u, mq_bytes); spin_unlock(&mq_lock); goto out_inode; } --- linux-2.6.16-rc1/ipc/mqueue.c 2006-01-26 22:35:32 +0100 +++ linux-2.6.16-rc1-vs2.1.0.9.4/ipc/mqueue.c 2006-01-21 18:28:17 +0100 @@ -256,10 +261,14 @@ static void mqueue_delete_inode(struct i (info->attr.mq_maxmsg * info->attr.mq_msgsize)); user = info->user; if (user) { + struct vx_info *vxi = lookup_vx_info(user->xid); + spin_lock(&mq_lock); user->mq_bytes -= mq_bytes; + vx_ipcmsg_sub(vxi, user, mq_bytes); queues_count--; spin_unlock(&mq_lock); + put_vx_info(vxi); free_uid(user); } } --- linux-2.6.16-rc1/ipc/shm.c 2006-01-26 22:35:32 +0100 +++ linux-2.6.16-rc1-vs2.1.0.9.4/ipc/shm.c 2006-01-21 18:28:14 +0100 @@ -114,7 +115,12 @@ static void shm_open (struct vm_area_str */ static void shm_destroy (struct shmid_kernel *shp) { - shm_tot -= (shp->shm_segsz + PAGE_SIZE - 1) >> PAGE_SHIFT; + struct vx_info *vxi = lookup_vx_info(shp->shm_perm.xid); + int numpages = (shp->shm_segsz + PAGE_SIZE - 1) >> PAGE_SHIFT; + + vx_ipcshm_sub(vxi, shp, numpages); + shm_tot -= numpages; + shm_rmid (shp->id); shm_unlock(shp); if (!is_file_hugepages(shp->shm_file)) --- linux-2.6.16-rc1/ipc/shm.c 2006-01-26 22:35:32 +0100 +++ linux-2.6.16-rc1-vs2.1.0.9.4/ipc/shm.c 2006-01-21 18:28:14 +0100 @@ -124,6 +130,7 @@ static void shm_destroy (struct shmid_ke shp->mlock_user); fput (shp->shm_file); security_shm_free(shp); + put_vx_info(vxi); ipc_rcu_putref(shp); } --- linux-2.6.16-rc1/ipc/shm.c 2006-01-26 22:35:32 +0100 +++ linux-2.6.16-rc1-vs2.1.0.9.4/ipc/shm.c 2006-01-21 18:28:14 +0100 @@ -198,6 +205,8 @@ static int newseg (key_t key, int shmflg if (shm_tot + numpages >= shm_ctlall) return -ENOSPC; + if (!vx_ipcshm_avail(current->vx_info, numpages)) + return -ENOSPC; shp = ipc_rcu_alloc(sizeof(*shp)); if (!shp) --- linux-2.6.16-rc1/ipc/shm.c 2006-01-26 22:35:32 +0100 +++ linux-2.6.16-rc1-vs2.1.0.9.4/ipc/shm.c 2006-01-21 18:28:14 +0100 @@ -204,6 +213,7 @@ ***** return -ENOMEM; shp->shm_perm.key = key; + shp->shm_perm.xid = vx_current_xid(); shp->shm_perm.mode = (shmflg & S_IRWXUGO); shp->mlock_user = NULL; --- linux-2.6.16-rc1/ipc/shm.c 2006-01-26 22:35:32 +0100 +++ linux-2.6.16-rc1-vs2.1.0.9.4/ipc/shm.c 2006-01-21 18:28:14 +0100 @@ -254,6 +264,7 @@ static int newseg (key_t key, int shmflg file->f_op = &shm_file_operations; shm_tot += numpages; + vx_ipcshm_add(current->vx_info, key, numpages); shm_unlock(shp); return shp->id; --- linux-2.6.16-rc1/kernel/exit.c 2006-01-26 22:35:32 +0100 +++ linux-2.6.16-rc1-vs2.1.0.9.4/kernel/exit.c 2006-01-21 18:28:14 +0100 @@ -393,6 +396,7 @@ static void close_files(struct files_str struct file * file = xchg(&fdt->fd[i], NULL); if (file) filp_close(file, files); + vx_openfd_dec(i); } i++; set >>= 1; --- linux-2.6.16-rc1/kernel/fork.c 2006-01-26 22:35:32 +0100 +++ linux-2.6.16-rc1-vs2.1.0.9.4/kernel/fork.c 2006-01-21 18:28:17 +0100 @@ -675,6 +685,8 @@ static int copy_files(unsigned long clon struct file *f = *old_fds++; if (f) { get_file(f); + /* FIXME: sum it first for check and performance */ + vx_openfd_inc(open_files - i); } else { /* * The fd may be claimed in the fd bitmap but not yet --- linux-2.6.16-rc1/kernel/fork.c 2006-01-26 22:35:32 +0100 +++ linux-2.6.16-rc1-vs2.1.0.9.4/kernel/fork.c 2006-01-21 18:28:17 +0100 @@ -1149,6 +1181,18 @@ static task_t *copy_process(unsigned lon nr_threads++; total_forks++; + + /* p is copy of current */ + vxi = p->vx_info; + if (vxi) { + claim_vx_info(vxi, p); + atomic_inc(&vxi->cvirt.nr_threads); + atomic_inc(&vxi->cvirt.total_forks); + vx_nproc_inc(p); + } + nxi = p->nx_info; + if (nxi) + claim_nx_info(nxi, p); write_unlock_irq(&tasklist_lock); proc_fork_connector(p); return p; --- linux-2.6.16-rc1/kernel/vserver/limit.c 1970-01-01 01:00:00 +0100 +++ linux-2.6.16-rc1-vs2.1.0.9.4/kernel/vserver/limit.c 2006-01-28 08:34:13 +0100 @@ -0,0 +1,196 @@ +/* + * linux/kernel/vserver/limit.c + * + * Virtual Server: Context Limits + * + * Copyright (C) 2004-2005 Herbert Pötzl + * + * V0.01 broken out from vcontext V0.05 + * + */ + +#include +#include +#include +#include +#include +#include + +#include +#include + + +const char *vlimit_name[NUM_LIMITS] = { + [RLIMIT_CPU] = "CPU", + [RLIMIT_RSS] = "RSS", + [RLIMIT_NPROC] = "NPROC", + [RLIMIT_NOFILE] = "NOFILE", + [RLIMIT_MEMLOCK] = "VML", + [RLIMIT_AS] = "VM", + [RLIMIT_LOCKS] = "LOCKS", + [RLIMIT_SIGPENDING] = "SIGP", + [RLIMIT_MSGQUEUE] = "MSGQ", + + [VLIMIT_NSOCK] = "NSOCK", + [VLIMIT_OPENFD] = "OPENFD", + [VLIMIT_ANON] = "ANON", + [VLIMIT_SHMEM] = "SHMEM", +}; + +EXPORT_SYMBOL_GPL(vlimit_name); + + +static int is_valid_rlimit(int id) +{ + int valid = 0; + + switch (id) { + case RLIMIT_RSS: + case RLIMIT_NPROC: + case RLIMIT_NOFILE: + case RLIMIT_MEMLOCK: + case RLIMIT_AS: + + case VLIMIT_NSOCK: + case VLIMIT_OPENFD: + case VLIMIT_ANON: + case VLIMIT_SHMEM: + valid = 1; + break; + } + return valid; +} + +static inline uint64_t vc_get_soft(struct vx_info *vxi, int id) +{ + rlim_t limit = __rlim_soft(&vxi->limit, id); + return VX_VLIM(limit); +} + +static inline uint64_t vc_get_hard(struct vx_info *vxi, int id) +{ + rlim_t limit = __rlim_hard(&vxi->limit, id); + return VX_VLIM(limit); +} + +int vc_get_rlimit(uint32_t id, void __user *data) +{ + struct vx_info *vxi; + struct vcmd_ctx_rlimit_v0 vc_data; + + if (copy_from_user (&vc_data, data, sizeof(vc_data))) + return -EFAULT; + if (!is_valid_rlimit(vc_data.id)) + return -ENOTSUPP; + + vxi = lookup_vx_info(id); + if (!vxi) + return -ESRCH; + + vc_data.minimum = CRLIM_UNSET; + vc_data.softlimit = vc_get_soft(vxi, vc_data.id); + vc_data.maximum = vc_get_hard(vxi, vc_data.id); + put_vx_info(vxi); + + if (copy_to_user (data, &vc_data, sizeof(vc_data))) + return -EFAULT; + return 0; +} + +int vc_set_rlimit(uint32_t id, void __user *data) +{ + struct vx_info *vxi; + struct vcmd_ctx_rlimit_v0 vc_data; + + if (!capable(CAP_SYS_ADMIN) || !capable(CAP_SYS_RESOURCE)) + return -EPERM; + if (copy_from_user (&vc_data, data, sizeof(vc_data))) + return -EFAULT; + if (!is_valid_rlimit(vc_data.id)) + return -ENOTSUPP; + + vxi = lookup_vx_info(id); + if (!vxi) + return -ESRCH; + + if (vc_data.maximum != CRLIM_KEEP) + __rlim_hard(&vxi->limit, vc_data.id) = + VX_RLIM(vc_data.maximum); + if (vc_data.softlimit != CRLIM_KEEP) + __rlim_soft(&vxi->limit, vc_data.id) = + VX_RLIM(vc_data.softlimit); + put_vx_info(vxi); + + return 0; +} + +int vc_get_rlimit_mask(uint32_t id, void __user *data) +{ + static struct vcmd_ctx_rlimit_mask_v0 mask = { + /* minimum */ + 0 + , /* softlimit */ + (1 << RLIMIT_RSS) | + (1 << VLIMIT_ANON) | + 0 + , /* maximum */ + (1 << RLIMIT_RSS) | + (1 << RLIMIT_NPROC) | + (1 << RLIMIT_NOFILE) | + (1 << RLIMIT_MEMLOCK) | + (1 << RLIMIT_LOCKS) | + (1 << RLIMIT_AS) | + (1 << VLIMIT_ANON) | + 0 + }; + + if (!capable(CAP_SYS_ADMIN) || !capable(CAP_SYS_RESOURCE)) + return -EPERM; + if (copy_to_user(data, &mask, sizeof(mask))) + return -EFAULT; + return 0; +} + + +void vx_vsi_meminfo(struct sysinfo *val) +{ + struct vx_info *vxi = current->vx_info; + rlim_t v; + + v = __rlim_soft(&vxi->limit, RLIMIT_RSS); + if (v == RLIM_INFINITY) + return; + + val->totalram = min((unsigned long)v, + (unsigned long)val->totalram); + + v = __rlim_get(&vxi->limit, RLIMIT_RSS); + val->freeram = (v < val->totalram) ? val->totalram - v : 0; + + val->bufferram = 0; + val->totalhigh = 0; + val->freehigh = 0; + return; +} + +void vx_vsi_swapinfo(struct sysinfo *val) +{ + struct vx_info *vxi = current->vx_info; + rlim_t v, w; + + v = __rlim_soft(&vxi->limit, RLIMIT_RSS); + if (v == RLIM_INFINITY) + return; + + w = __rlim_hard(&vxi->limit, RLIMIT_RSS); + if (w == RLIM_INFINITY) + return; + + val->totalswap = min((unsigned long)(w - v), + (unsigned long)val->totalswap); + + w = __rlim_get(&vxi->limit, RLIMIT_RSS) - v; + val->freeswap = (w < val->totalswap) ? val->totalswap - w : 0; + return; +} +