--- linux-2.6.18.2/fs/dcache.c 2006-09-20 16:58:34 +0200 +++ linux-2.6.18.2-vs2.1.1/fs/dcache.c 2006-09-25 15:40:02 +0200 @@ -146,6 +147,7 @@ void dput(struct dentry *dentry) if (!dentry) return; + vx_dentry_dec(dentry); repeat: if (atomic_read(&dentry->d_count) == 1) might_sleep(); --- linux-2.6.18.2/fs/dcache.c 2006-09-20 16:58:34 +0200 +++ linux-2.6.18.2-vs2.1.1/fs/dcache.c 2006-09-25 15:40:02 +0200 @@ -159,6 +161,8 @@ repeat: return; } + vx_dentry_dec(dentry); + /* * AV: ->d_delete() is _NOT_ allowed to block now. */ --- linux-2.6.18.2/fs/dcache.c 2006-09-20 16:58:34 +0200 +++ linux-2.6.18.2-vs2.1.1/fs/dcache.c 2006-09-25 15:40:02 +0200 @@ -269,6 +273,7 @@ static inline struct dentry * __dget_loc if (!list_empty(&dentry->d_lru)) { dentry_stat.nr_unused--; list_del_init(&dentry->d_lru); + vx_dentry_inc(dentry); } return dentry; } --- linux-2.6.18.2/fs/dcache.c 2006-09-20 16:58:34 +0200 +++ linux-2.6.18.2-vs2.1.1/fs/dcache.c 2006-09-25 15:40:02 +0200 @@ -722,6 +727,9 @@ struct dentry *d_alloc(struct dentry * p struct dentry *dentry; char *dname; + if (!vx_dentry_avail(1)) + return NULL; + dentry = kmem_cache_alloc(dentry_cache, GFP_KERNEL); if (!dentry) return NULL; --- linux-2.6.18.2/fs/dcache.c 2006-09-20 16:58:34 +0200 +++ linux-2.6.18.2-vs2.1.1/fs/dcache.c 2006-09-25 15:40:02 +0200 @@ -770,6 +778,7 @@ struct dentry *d_alloc(struct dentry * p if (parent) list_add(&dentry->d_u.d_child, &parent->d_subdirs); dentry_stat.nr_dentry++; + vx_dentry_inc(dentry); spin_unlock(&dcache_lock); return dentry; --- linux-2.6.18.2/fs/dcache.c 2006-09-20 16:58:34 +0200 +++ linux-2.6.18.2-vs2.1.1/fs/dcache.c 2006-09-25 15:40:02 +0200 @@ -1101,6 +1110,7 @@ struct dentry * __d_lookup(struct dentry if (!d_unhashed(dentry)) { atomic_inc(&dentry->d_count); + vx_dentry_inc(dentry); found = dentry; } spin_unlock(&dentry->d_lock); --- linux-2.6.18.2/fs/fcntl.c 2006-06-18 04:54:34 +0200 +++ linux-2.6.18.2-vs2.1.1/fs/fcntl.c 2006-09-20 17:01:44 +0200 @@ -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.18.2/fs/fcntl.c 2006-06-18 04:54:34 +0200 +++ linux-2.6.18.2-vs2.1.1/fs/fcntl.c 2006-09-20 17:01:44 +0200 @@ -125,6 +128,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.18.2/fs/fcntl.c 2006-06-18 04:54:34 +0200 +++ linux-2.6.18.2-vs2.1.1/fs/fcntl.c 2006-09-20 17:01:44 +0200 @@ -177,6 +181,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.18.2/fs/file_table.c 2006-09-20 16:58:34 +0200 +++ linux-2.6.18.2-vs2.1.1/fs/file_table.c 2006-09-20 17:01:44 +0200 @@ -120,6 +122,8 @@ struct file *get_empty_filp(void) f->f_gid = tsk->fsgid; eventpoll_init_file(f); /* f->f_version: 0 */ + f->f_xid = vx_current_xid(); + vx_files_inc(f); return f; over: --- linux-2.6.18.2/fs/file_table.c 2006-09-20 16:58:34 +0200 +++ linux-2.6.18.2-vs2.1.1/fs/file_table.c 2006-09-20 17:01:44 +0200 @@ -174,6 +178,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.18.2/fs/file_table.c 2006-09-20 16:58:34 +0200 +++ linux-2.6.18.2-vs2.1.1/fs/file_table.c 2006-09-20 17:01:44 +0200 @@ -239,6 +245,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.18.2/fs/locks.c 2006-09-20 16:58:35 +0200 +++ linux-2.6.18.2-vs2.1.1/fs/locks.c 2006-09-25 15:40:02 +0200 @@ -147,6 +148,8 @@ static kmem_cache_t *filelock_cache __re /* 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.18.2/fs/locks.c 2006-09-20 16:58:35 +0200 +++ linux-2.6.18.2-vs2.1.1/fs/locks.c 2006-09-25 15:40:02 +0200 @@ -172,6 +175,7 @@ static void locks_free_lock(struct file_ BUG_ON(!list_empty(&fl->fl_block)); BUG_ON(!list_empty(&fl->fl_link)); + vx_locks_dec(fl); locks_release_private(fl); kmem_cache_free(filelock_cache, fl); } --- linux-2.6.18.2/fs/locks.c 2006-09-20 16:58:35 +0200 +++ linux-2.6.18.2-vs2.1.1/fs/locks.c 2006-09-25 15:40:02 +0200 @@ -286,6 +292,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.18.2/fs/locks.c 2006-09-20 16:58:35 +0200 +++ linux-2.6.18.2-vs2.1.1/fs/locks.c 2006-09-25 15:40:02 +0200 @@ -470,6 +482,11 @@ static int lease_alloc(struct file *filp if (fl == NULL) goto out; + 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) { locks_free_lock(fl); --- linux-2.6.18.2/fs/locks.c 2006-09-20 16:58:35 +0200 +++ linux-2.6.18.2-vs2.1.1/fs/locks.c 2006-09-25 15:40:02 +0200 @@ -790,6 +807,7 @@ find_conflict: if (request->fl_flags & FL_ACCESS) goto out; locks_copy_lock(new_fl, request); + vx_locks_inc(new_fl); locks_insert_lock(&inode->i_flock, new_fl); new_fl = NULL; error = 0; --- linux-2.6.18.2/fs/locks.c 2006-09-20 16:58:35 +0200 +++ linux-2.6.18.2-vs2.1.1/fs/locks.c 2006-09-25 15:40:02 +0200 @@ -801,7 +819,8 @@ out: return error; } -static int __posix_lock_file_conf(struct inode *inode, struct file_lock *request, struct file_lock *conflock) +static int __posix_lock_file_conf(struct inode *inode, struct file_lock *request, + struct file_lock *conflock, xid_t xid) { struct file_lock *fl; struct file_lock *new_fl = NULL; --- linux-2.6.18.2/fs/locks.c 2006-09-20 16:58:35 +0200 +++ linux-2.6.18.2-vs2.1.1/fs/locks.c 2006-09-25 15:40:02 +0200 @@ -821,7 +842,11 @@ static int __posix_lock_file_conf(struct (request->fl_type != F_UNLCK || request->fl_start != 0 || request->fl_end != OFFSET_MAX)) { 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(); --- linux-2.6.18.2/fs/locks.c 2006-09-20 16:58:35 +0200 +++ linux-2.6.18.2-vs2.1.1/fs/locks.c 2006-09-25 15:40:02 +0200 @@ -1018,7 +1043,8 @@ static int __posix_lock_file_conf(struct */ int posix_lock_file(struct file *filp, struct file_lock *fl) { - return __posix_lock_file_conf(filp->f_dentry->d_inode, fl, NULL); + return __posix_lock_file_conf(filp->f_dentry->d_inode, + fl, NULL, filp->f_xid); } EXPORT_SYMBOL(posix_lock_file); --- linux-2.6.18.2/fs/locks.c 2006-09-20 16:58:35 +0200 +++ linux-2.6.18.2-vs2.1.1/fs/locks.c 2006-09-25 15:40:02 +0200 @@ -1033,7 +1059,8 @@ EXPORT_SYMBOL(posix_lock_file); int posix_lock_file_conf(struct file *filp, struct file_lock *fl, struct file_lock *conflock) { - return __posix_lock_file_conf(filp->f_dentry->d_inode, fl, conflock); + return __posix_lock_file_conf(filp->f_dentry->d_inode, + fl, conflock, filp->f_xid); } EXPORT_SYMBOL(posix_lock_file_conf); --- linux-2.6.18.2/fs/locks.c 2006-09-20 16:58:35 +0200 +++ linux-2.6.18.2-vs2.1.1/fs/locks.c 2006-09-25 15:40:02 +0200 @@ -1123,7 +1150,7 @@ int locks_mandatory_area(int read_write, fl.fl_end = offset + count - 1; for (;;) { - error = __posix_lock_file_conf(inode, &fl, NULL); + error = __posix_lock_file_conf(inode, &fl, NULL, filp->f_xid); if (error != -EAGAIN) break; if (!(fl.fl_flags & FL_SLEEP)) --- linux-2.6.18.2/fs/locks.c 2006-09-20 16:58:35 +0200 +++ linux-2.6.18.2-vs2.1.1/fs/locks.c 2006-09-25 15:40:02 +0200 @@ -1685,6 +1712,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.18.2/fs/locks.c 2006-09-20 16:58:35 +0200 +++ linux-2.6.18.2-vs2.1.1/fs/locks.c 2006-09-25 15:40:02 +0200 @@ -1828,6 +1860,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.18.2/fs/open.c 2006-09-20 16:58:35 +0200 +++ linux-2.6.18.2-vs2.1.1/fs/open.c 2006-11-04 08:24:09 +0100 @@ -1015,6 +1037,7 @@ repeat: FD_SET(fd, fdt->open_fds); FD_CLR(fd, fdt->close_on_exec); files->next_fd = fd + 1; + vx_openfd_inc(fd); #if 1 /* Sanity check */ if (fdt->fd[fd] != NULL) { --- linux-2.6.18.2/fs/open.c 2006-09-20 16:58:35 +0200 +++ linux-2.6.18.2-vs2.1.1/fs/open.c 2006-11-04 08:24:09 +0100 @@ -1037,6 +1060,7 @@ static void __put_unused_fd(struct files __FD_CLR(fd, fdt->open_fds); if (fd < files->next_fd) files->next_fd = fd; + vx_openfd_dec(fd); } void fastcall put_unused_fd(unsigned int fd) --- linux-2.6.18.2/include/linux/vserver/limit.h 1970-01-01 01:00:00 +0100 +++ linux-2.6.18.2-vs2.1.1/include/linux/vserver/limit.h 2006-09-25 15:40:02 +0200 @@ -0,0 +1,66 @@ +#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 +#define VLIMIT_DENTRY 22 + +#ifdef __KERNEL__ + +#define VLIM_NOCHECK (1L << VLIMIT_DENTRY) + +/* 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.18.2/include/linux/vserver/limit_int.h 1970-01-01 01:00:00 +0100 +++ linux-2.6.18.2-vs2.1.1/include/linux/vserver/limit_int.h 2006-09-25 15:40:02 +0200 @@ -0,0 +1,83 @@ +#ifndef _VX_LIMIT_INT_H +#define _VX_LIMIT_INT_H + + +#ifdef __KERNEL__ + +#define VXD_RCRES_COND(r) VXD_CBIT(cres, (r)) +#define VXD_RLIMIT_COND(r) VXD_CBIT(limit, (r)) + +extern const char *vlimit_name[NUM_LIMITS]; + +static inline void __vx_acc_cres(struct vx_info *vxi, + int res, int dir, void *_data, char *_file, int _line) +{ + if (VXD_RCRES_COND(res)) + vxlprintk(1, "vx_acc_cres[%5d,%s,%2d]: %5ld%s (%p)", + (vxi ? vxi->vx_id : -1), vlimit_name[res], res, + (vxi ? (long)__rlim_get(&vxi->limit, res) : 0), + (dir > 0) ? "++" : "--", _data, _file, _line); + if (!vxi) + return; + + if (dir > 0) + __rlim_inc(&vxi->limit, res); + else + __rlim_dec(&vxi->limit, res); +} + +static inline void __vx_add_cres(struct vx_info *vxi, + int res, int amount, void *_data, char *_file, int _line) +{ + if (VXD_RCRES_COND(res)) + vxlprintk(1, "vx_add_cres[%5d,%s,%2d]: %5ld += %5d (%p)", + (vxi ? vxi->vx_id : -1), vlimit_name[res], res, + (vxi ? (long)__rlim_get(&vxi->limit, res) : 0), + amount, _data, _file, _line); + if (amount == 0) + return; + if (!vxi) + return; + __rlim_add(&vxi->limit, res, amount); +} + +static inline int __vx_cres_avail(struct vx_info *vxi, + int res, int num, char *_file, int _line) +{ + rlim_t value; + + if (VXD_RLIMIT_COND(res)) + vxlprintk(1, "vx_cres_avail[%5d,%s,%2d]: %5ld/%5ld > %5ld + %5d", + (vxi ? vxi->vx_id : -1), vlimit_name[res], res, + (vxi ? (long)__rlim_soft(&vxi->limit, res) : -1), + (vxi ? (long)__rlim_hard(&vxi->limit, res) : -1), + (vxi ? (long)__rlim_get(&vxi->limit, res) : 0), + num, _file, _line); + if (num == 0) + return 1; + if (!vxi) + return 1; + + value = __rlim_get(&vxi->limit, res); + + if (value > __rlim_rmax(&vxi->limit, res)) + __rlim_rmax(&vxi->limit, res) = value; + else if (value < __rlim_rmin(&vxi->limit, res)) + __rlim_rmin(&vxi->limit, res) = value; + + if (__rlim_soft(&vxi->limit, res) == RLIM_INFINITY) + return -1; + if (value + num <= __rlim_soft(&vxi->limit, res)) + return -1; + + if (__rlim_hard(&vxi->limit, res) == RLIM_INFINITY) + return 1; + if (value + num <= __rlim_hard(&vxi->limit, res)) + return 1; + + __rlim_hit(&vxi->limit, res); + return 0; +} + +#endif /* __KERNEL__ */ +#endif /* _VX_LIMIT_INT_H */ --- linux-2.6.18.2/ipc/mqueue.c 2006-09-20 16:58:44 +0200 +++ linux-2.6.18.2-vs2.1.1/ipc/mqueue.c 2006-09-20 17:01:45 +0200 @@ -152,7 +154,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.18.2/ipc/mqueue.c 2006-09-20 16:58:44 +0200 +++ linux-2.6.18.2-vs2.1.1/ipc/mqueue.c 2006-09-20 17:01:45 +0200 @@ -157,6 +160,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.18.2/ipc/mqueue.c 2006-09-20 16:58:44 +0200 +++ linux-2.6.18.2-vs2.1.1/ipc/mqueue.c 2006-09-20 17:01:45 +0200 @@ -163,6 +167,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.18.2/ipc/mqueue.c 2006-09-20 16:58:44 +0200 +++ linux-2.6.18.2-vs2.1.1/ipc/mqueue.c 2006-09-20 17:01:45 +0200 @@ -260,10 +265,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.18.2/ipc/sem.c 2006-09-20 16:58:44 +0200 +++ linux-2.6.18.2-vs2.1.1/ipc/sem.c 2006-09-25 15:40:02 +0200 @@ -198,6 +200,8 @@ static int newary (key_t key, int nsems, return -ENOSPC; } used_sems += nsems; + vx_semary_inc(sma); + vx_nsems_add(sma, nsems); sma->sem_id = sem_buildid(id, sma->sem_perm.seq); sma->sem_base = (struct sem *) &sma[1]; --- linux-2.6.18.2/ipc/sem.c 2006-09-20 16:58:44 +0200 +++ linux-2.6.18.2-vs2.1.1/ipc/sem.c 2006-09-25 15:40:02 +0200 @@ -476,6 +480,8 @@ static void freeary (struct sem_array *s sem_unlock(sma); used_sems -= sma->sem_nsems; + vx_nsems_sub(sma, sma->sem_nsems); + vx_semary_dec(sma); size = sizeof (*sma) + sma->sem_nsems * sizeof (struct sem); security_sem_free(sma); ipc_rcu_putref(sma); --- linux-2.6.18.2/ipc/shm.c 2006-09-20 16:58:44 +0200 +++ linux-2.6.18.2-vs2.1.1/ipc/shm.c 2006-09-25 15:40:02 +0200 @@ -116,7 +118,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.18.2/ipc/shm.c 2006-09-20 16:58:44 +0200 +++ linux-2.6.18.2-vs2.1.1/ipc/shm.c 2006-09-25 15:40:02 +0200 @@ -126,6 +133,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.18.2/ipc/shm.c 2006-09-20 16:58:44 +0200 +++ linux-2.6.18.2-vs2.1.1/ipc/shm.c 2006-09-25 15:40:02 +0200 @@ -202,6 +210,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.18.2/ipc/shm.c 2006-09-20 16:58:44 +0200 +++ linux-2.6.18.2-vs2.1.1/ipc/shm.c 2006-09-25 15:40:02 +0200 @@ -208,6 +218,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.18.2/ipc/shm.c 2006-09-20 16:58:44 +0200 +++ linux-2.6.18.2-vs2.1.1/ipc/shm.c 2006-09-25 15:40:02 +0200 @@ -258,6 +269,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.18.2/kernel/exit.c 2006-09-20 16:58:44 +0200 +++ linux-2.6.18.2-vs2.1.1/kernel/exit.c 2006-10-28 18:31:23 +0200 @@ -444,6 +447,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.18.2/kernel/fork.c 2006-09-20 16:58:44 +0200 +++ linux-2.6.18.2-vs2.1.1/kernel/fork.c 2006-09-25 15:40:02 +0200 @@ -691,6 +701,8 @@ static struct files_struct *dup_fd(struc 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.18.2/kernel/fork.c 2006-09-20 16:58:44 +0200 +++ linux-2.6.18.2-vs2.1.1/kernel/fork.c 2006-09-25 15:40:02 +0200 @@ -1247,6 +1279,18 @@ static struct task_struct *copy_process( total_forks++; spin_unlock(¤t->sighand->siglock); + + /* 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.18.2/kernel/vserver/limit.c 1970-01-01 01:00:00 +0100 +++ linux-2.6.18.2-vs2.1.1/kernel/vserver/limit.c 2006-09-25 15:40:02 +0200 @@ -0,0 +1,297 @@ +/* + * linux/kernel/vserver/limit.c + * + * Virtual Server: Context Limits + * + * Copyright (C) 2004-2006 Herbert Pötzl + * + * V0.01 broken out from vcontext V0.05 + * V0.02 changed vcmds to vxi arg + * + */ + +#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", + [VLIMIT_DENTRY] = "DENTRY", +}; + +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 RLIMIT_LOCKS: + case RLIMIT_MSGQUEUE: + + case VLIMIT_NSOCK: + case VLIMIT_OPENFD: + case VLIMIT_ANON: + case VLIMIT_SHMEM: + case VLIMIT_DENTRY: + 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); +} + +static int do_get_rlimit(struct vx_info *vxi, uint32_t id, + uint64_t *minimum, uint64_t *softlimit, uint64_t *maximum) +{ + if (!is_valid_rlimit(id)) + return -EINVAL; + + if (minimum) + *minimum = CRLIM_UNSET; + if (softlimit) + *softlimit = vc_get_soft(vxi, id); + if (maximum) + *maximum = vc_get_hard(vxi, id); + return 0; +} + +int vc_get_rlimit(struct vx_info *vxi, void __user *data) +{ + struct vcmd_ctx_rlimit_v0 vc_data; + int ret; + + if (copy_from_user (&vc_data, data, sizeof(vc_data))) + return -EFAULT; + + ret = do_get_rlimit(vxi, vc_data.id, + &vc_data.minimum, &vc_data.softlimit, &vc_data.maximum); + if (ret) + return ret; + + if (copy_to_user (data, &vc_data, sizeof(vc_data))) + return -EFAULT; + return 0; +} + +static int do_set_rlimit(struct vx_info *vxi, uint32_t id, + uint64_t minimum, uint64_t softlimit, uint64_t maximum) +{ + if (!is_valid_rlimit(id)) + return -EINVAL; + + if (maximum != CRLIM_KEEP) + __rlim_hard(&vxi->limit, id) = VX_RLIM(maximum); + if (softlimit != CRLIM_KEEP) + __rlim_soft(&vxi->limit, id) = VX_RLIM(softlimit); + + /* clamp soft limit */ + if (__rlim_soft(&vxi->limit, id) > __rlim_hard(&vxi->limit, id)) + __rlim_soft(&vxi->limit, id) = __rlim_hard(&vxi->limit, id); + + return 0; +} + +int vc_set_rlimit(struct vx_info *vxi, void __user *data) +{ + struct vcmd_ctx_rlimit_v0 vc_data; + + if (copy_from_user (&vc_data, data, sizeof(vc_data))) + return -EFAULT; + + return do_set_rlimit(vxi, vc_data.id, + vc_data.minimum, vc_data.softlimit, vc_data.maximum); +} + +#ifdef CONFIG_IA32_EMULATION + +int vc_set_rlimit_x32(struct vx_info *vxi, void __user *data) +{ + struct vcmd_ctx_rlimit_v0_x32 vc_data; + + if (copy_from_user (&vc_data, data, sizeof(vc_data))) + return -EFAULT; + + return do_set_rlimit(vxi, vc_data.id, + vc_data.minimum, vc_data.softlimit, vc_data.maximum); +} + +int vc_get_rlimit_x32(struct vx_info *vxi, void __user *data) +{ + struct vcmd_ctx_rlimit_v0_x32 vc_data; + int ret; + + if (copy_from_user (&vc_data, data, sizeof(vc_data))) + return -EFAULT; + + ret = do_get_rlimit(vxi, vc_data.id, + &vc_data.minimum, &vc_data.softlimit, &vc_data.maximum); + if (ret) + return ret; + + if (copy_to_user (data, &vc_data, sizeof(vc_data))) + return -EFAULT; + return 0; +} + +#endif /* CONFIG_IA32_EMULATION */ + + +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) | + (1 << VLIMIT_DENTRY) | + 0 + }; + + if (copy_to_user(data, &mask, sizeof(mask))) + return -EFAULT; + return 0; +} + + +static inline void vx_reset_minmax(struct _vx_limit *limit) +{ + rlim_t value; + int lim; + + for (lim=0; limlimit); + return 0; +} + + +int vc_rlimit_stat(struct vx_info *vxi, void __user *data) +{ + struct vcmd_rlimit_stat_v0 vc_data; + struct _vx_limit *limit = &vxi->limit; + int id; + + if (copy_from_user (&vc_data, data, sizeof(vc_data))) + return -EFAULT; + + id = vc_data.id; + if (!is_valid_rlimit(id)) + return -EINVAL; + + vc_data.hits = atomic_read(&__rlim_lhit(limit, id)); + vc_data.value = __rlim_get(limit, id); + vc_data.minimum = __rlim_rmin(limit, id); + vc_data.maximum = __rlim_rmax(limit, id); + + if (copy_to_user (data, &vc_data, sizeof(vc_data))) + return -EFAULT; + return 0; +} + + +void vx_vsi_meminfo(struct sysinfo *val) +{ + struct vx_info *vxi = current->vx_info; + unsigned long totalram, freeram; + rlim_t v; + + /* we blindly accept the max */ + v = __rlim_soft(&vxi->limit, RLIMIT_RSS); + totalram = (v != RLIM_INFINITY) ? v : val->totalram; + + /* total minus used equals free */ + v = __rlim_get(&vxi->limit, RLIMIT_RSS); + freeram = (v < totalram) ? totalram - v : 0; + + val->totalram = totalram; + val->freeram = freeram; + val->bufferram = 0; + val->totalhigh = 0; + val->freehigh = 0; + return; +} + +void vx_vsi_swapinfo(struct sysinfo *val) +{ + struct vx_info *vxi = current->vx_info; + unsigned long totalswap, freeswap; + rlim_t v, w; + + v = __rlim_soft(&vxi->limit, RLIMIT_RSS); + if (v == RLIM_INFINITY) { + val->freeswap = val->totalswap; + return; + } + + /* we blindly accept the max */ + w = __rlim_hard(&vxi->limit, RLIMIT_RSS); + totalswap = (w != RLIM_INFINITY) ? (w - v) : val->totalswap; + + /* currently 'used' swap */ + w = __rlim_get(&vxi->limit, RLIMIT_RSS); + w -= (w > v) ? v : w; + + /* total minus used equals free */ + freeswap = (w < totalswap) ? totalswap - w : 0; + + val->totalswap = totalswap; + val->freeswap = freeswap; + return; +} +