--- linux-2.6.12.2/fs/fcntl.c 2005-06-22 02:38:36 +0200 +++ linux-2.6.12.2-vs2.0-rc6.1/fs/fcntl.c 2005-07-02 22:38:30 +0200 @@ -77,6 +78,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.12.2/fs/fcntl.c 2005-06-22 02:38:36 +0200 +++ linux-2.6.12.2-vs2.0-rc6.1/fs/fcntl.c 2005-07-02 22:38:30 +0200 @@ -109,6 +112,7 @@ static int dupfd(struct file *file, unsi FD_SET(fd, files->open_fds); FD_CLR(fd, files->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.12.2/fs/fcntl.c 2005-06-22 02:38:36 +0200 +++ linux-2.6.12.2-vs2.0-rc6.1/fs/fcntl.c 2005-07-02 22:38:30 +0200 @@ -159,6 +163,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.12.2/fs/file_table.c 2005-03-02 12:38:44 +0100 +++ linux-2.6.12.2-vs2.0-rc6.1/fs/file_table.c 2005-07-02 22:38:30 +0200 @@ -85,6 +87,8 @@ static int old_max; rwlock_init(&f->f_owner.lock); /* f->f_version: 0 */ INIT_LIST_HEAD(&f->f_list); + f->f_xid = vx_current_xid(); + vx_files_inc(f); f->f_maxcount = INT_MAX; return f; } --- linux-2.6.12.2/fs/file_table.c 2005-03-02 12:38:44 +0100 +++ linux-2.6.12.2-vs2.0-rc6.1/fs/file_table.c 2005-07-02 22:38:30 +0200 @@ -138,6 +142,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.12.2/fs/file_table.c 2005-03-02 12:38:44 +0100 +++ linux-2.6.12.2-vs2.0-rc6.1/fs/file_table.c 2005-07-02 22:38:30 +0200 @@ -193,6 +199,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.12.2/fs/locks.c 2005-06-22 02:38:37 +0200 +++ linux-2.6.12.2-vs2.0-rc6.1/fs/locks.c 2005-07-02 22:38:30 +0200 @@ -149,12 +150,16 @@ 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); } /* Free a lock which is not in use. */ static inline void locks_free_lock(struct file_lock *fl) { + vx_locks_dec(fl); + if (fl == NULL) { BUG(); return; --- linux-2.6.12.2/fs/locks.c 2005-06-22 02:38:37 +0200 +++ linux-2.6.12.2-vs2.0-rc6.1/fs/locks.c 2005-07-02 22:38:30 +0200 @@ -198,6 +203,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.12.2/fs/locks.c 2005-06-22 02:38:37 +0200 +++ linux-2.6.12.2-vs2.0-rc6.1/fs/locks.c 2005-07-02 22:38:30 +0200 @@ -235,6 +241,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.12.2/fs/locks.c 2005-06-22 02:38:37 +0200 +++ linux-2.6.12.2-vs2.0-rc6.1/fs/locks.c 2005-07-02 22:38:30 +0200 @@ -271,6 +279,10 @@ static int flock_make_lock(struct file * fl->fl_flags = FL_FLOCK; fl->fl_type = type; fl->fl_end = OFFSET_MAX; + + /* check against file xid maybe ? */ + fl->fl_xid = vx_current_xid(); + vx_locks_inc(fl); *lock = fl; return 0; --- linux-2.6.12.2/fs/locks.c 2005-06-22 02:38:37 +0200 +++ linux-2.6.12.2-vs2.0-rc6.1/fs/locks.c 2005-07-02 22:38:30 +0200 @@ -448,6 +460,8 @@ static int lease_alloc(struct file *filp if (fl == NULL) return -ENOMEM; + fl->fl_xid = vx_current_xid(); + vx_locks_inc(fl); error = lease_init(filp, type, fl); if (error) return error; --- linux-2.6.12.2/fs/locks.c 2005-06-22 02:38:37 +0200 +++ linux-2.6.12.2-vs2.0-rc6.1/fs/locks.c 2005-07-02 22:38:30 +0200 @@ -777,7 +791,11 @@ static int __posix_lock_file(struct inod * so we get them in advance to avoid races. */ new_fl = locks_alloc_lock(); + new_fl->fl_xid = vx_current_xid(); + vx_locks_inc(new_fl); new_fl2 = locks_alloc_lock(); + new_fl2->fl_xid = vx_current_xid(); + vx_locks_inc(new_fl2); lock_kernel(); if (request->fl_type != F_UNLCK) { --- linux-2.6.12.2/fs/locks.c 2005-06-22 02:38:37 +0200 +++ linux-2.6.12.2-vs2.0-rc6.1/fs/locks.c 2005-07-02 22:38:30 +0200 @@ -1597,6 +1615,9 @@ int fcntl_setlk(struct file *filp, unsig if (file_lock == NULL) return -ENOLCK; + file_lock->fl_xid = vx_current_xid(); + vx_locks_inc(file_lock); + /* * This might block, so we do it before checking the inode. */ --- linux-2.6.12.2/fs/locks.c 2005-06-22 02:38:37 +0200 +++ linux-2.6.12.2-vs2.0-rc6.1/fs/locks.c 2005-07-02 22:38:30 +0200 @@ -1728,6 +1749,9 @@ int fcntl_setlk64(struct file *filp, uns if (file_lock == NULL) return -ENOLCK; + file_lock->fl_xid = vx_current_xid(); + vx_locks_inc(file_lock); + /* * This might block, so we do it before checking the inode. */ --- linux-2.6.12.2/fs/open.c 2005-03-02 12:38:45 +0100 +++ linux-2.6.12.2-vs2.0-rc6.1/fs/open.c 2005-07-02 22:38:30 +0200 @@ -872,6 +878,7 @@ repeat: FD_SET(fd, files->open_fds); FD_CLR(fd, files->close_on_exec); files->next_fd = fd + 1; + vx_openfd_inc(fd); #if 1 /* Sanity check */ if (files->fd[fd] != NULL) { --- linux-2.6.12.2/fs/open.c 2005-03-02 12:38:45 +0100 +++ linux-2.6.12.2-vs2.0-rc6.1/fs/open.c 2005-07-02 22:38:30 +0200 @@ -893,6 +900,7 @@ static inline void __put_unused_fd(struc __FD_CLR(fd, files->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.12.2/include/linux/vserver/limit.h 1970-01-01 01:00:00 +0100 +++ linux-2.6.12.2-vs2.0-rc6.1/include/linux/vserver/limit.h 2005-07-02 22:38:30 +0200 @@ -0,0 +1,23 @@ +#ifndef _VX_LIMIT_H +#define _VX_LIMIT_H + +#ifdef __KERNEL__ + +struct sysinfo; + +void vx_vsi_meminfo(struct sysinfo *); +void vx_vsi_swapinfo(struct sysinfo *); + +#define VXD_RLIMIT(r,l) (VXD_CBIT(limit, (l)) && ((r) == (l))) + +#define NUM_LIMITS 24 + +#define VLIMIT_NSOCK 16 +#define VLIMIT_OPENFD 17 +#define VLIMIT_ANON 18 +#define VLIMIT_SHMEM 19 + +extern const char *vlimit_name[NUM_LIMITS]; + +#endif /* __KERNEL__ */ +#endif /* _VX_LIMIT_H */ --- linux-2.6.12.2/ipc/mqueue.c 2005-06-22 02:38:52 +0200 +++ linux-2.6.12.2-vs2.0-rc6.1/ipc/mqueue.c 2005-07-02 22:38:30 +0200 @@ -147,17 +149,20 @@ 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; } 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); 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.12.2/ipc/mqueue.c 2005-06-22 02:38:52 +0200 +++ linux-2.6.12.2-vs2.0-rc6.1/ipc/mqueue.c 2005-07-02 22:38:30 +0200 @@ -255,10 +260,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 = locate_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.12.2/ipc/shm.c 2005-06-22 02:38:52 +0200 +++ linux-2.6.12.2-vs2.0-rc6.1/ipc/shm.c 2005-07-02 22:38:30 +0200 @@ -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 = locate_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.12.2/ipc/shm.c 2005-06-22 02:38:52 +0200 +++ linux-2.6.12.2-vs2.0-rc6.1/ipc/shm.c 2005-07-02 22:38:30 +0200 @@ -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.12.2/ipc/shm.c 2005-06-22 02:38:52 +0200 +++ linux-2.6.12.2-vs2.0-rc6.1/ipc/shm.c 2005-07-02 22:38:30 +0200 @@ -190,12 +197,15 @@ 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) return -ENOMEM; shp->shm_perm.key = key; + shp->shm_perm.xid = vx_current_xid(); shp->shm_flags = (shmflg & S_IRWXUGO); shp->mlock_user = NULL; --- linux-2.6.12.2/ipc/shm.c 2005-06-22 02:38:52 +0200 +++ linux-2.6.12.2-vs2.0-rc6.1/ipc/shm.c 2005-07-02 22:38:30 +0200 @@ -237,6 +247,7 @@ static int newseg (key_t key, int shmflg else 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.12.2/kernel/exit.c 2005-06-22 02:38:52 +0200 +++ linux-2.6.12.2-vs2.0-rc6.1/kernel/exit.c 2005-07-02 22:38:30 +0200 @@ -44,6 +46,11 @@ static void exit_mm(struct task_struct * static void __unhash_process(struct task_struct *p) { nr_threads--; + /* tasklist_lock is held, is this sufficient? */ + if (p->vx_info) { + atomic_dec(&p->vx_info->cvirt.nr_threads); + vx_nproc_dec(p); + } detach_pid(p, PIDTYPE_PID); detach_pid(p, PIDTYPE_TGID); if (thread_group_leader(p)) { --- linux-2.6.12.2/kernel/exit.c 2005-06-22 02:38:52 +0200 +++ linux-2.6.12.2-vs2.0-rc6.1/kernel/exit.c 2005-07-02 22:38:30 +0200 @@ -100,6 +107,10 @@ repeat: spin_unlock(&p->proc_lock); proc_pid_flush(proc_dentry); release_thread(p); + if (p->vx_info) + release_vx_info(p->vx_info, p); + if (p->nx_info) + release_nx_info(p->nx_info, p); put_task_struct(p); p = leader; --- linux-2.6.12.2/kernel/exit.c 2005-06-22 02:38:52 +0200 +++ linux-2.6.12.2-vs2.0-rc6.1/kernel/exit.c 2005-07-02 22:38:30 +0200 @@ -376,6 +388,7 @@ static inline void close_files(struct fi struct file * file = xchg(&files->fd[i], NULL); if (file) filp_close(file, files); + vx_openfd_dec(i); } i++; set >>= 1; --- linux-2.6.12.2/kernel/fork.c 2005-06-22 02:38:52 +0200 +++ linux-2.6.12.2-vs2.0-rc6.1/kernel/fork.c 2005-07-02 22:38:30 +0200 @@ -650,6 +659,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.12.2/kernel/fork.c 2005-06-22 02:38:52 +0200 +++ linux-2.6.12.2-vs2.0-rc6.1/kernel/fork.c 2005-07-02 22:38:30 +0200 @@ -1101,6 +1132,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); retval = 0; --- linux-2.6.12.2/kernel/vserver/limit.c 1970-01-01 01:00:00 +0100 +++ linux-2.6.12.2-vs2.0-rc6.1/kernel/vserver/limit.c 2005-07-02 22:38:30 +0200 @@ -0,0 +1,178 @@ +/* + * 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 +#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_rlim(struct vx_info *vxi, int id) +{ + unsigned long limit; + + limit = vxi->limit.rlim[id]; + if (limit == RLIM_INFINITY) + return CRLIM_INFINITY; + return 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 = locate_vx_info(id); + if (!vxi) + return -ESRCH; + + vc_data.maximum = vc_get_rlim(vxi, vc_data.id); + vc_data.minimum = CRLIM_UNSET; + vc_data.softlimit = CRLIM_UNSET; + 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 = locate_vx_info(id); + if (!vxi) + return -ESRCH; + + if (vc_data.maximum != CRLIM_KEEP) + vxi->limit.rlim[vc_data.id] = vc_data.maximum; + 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 */ + 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; + unsigned long v; + + v = vxi->limit.rlim[RLIMIT_RSS]; + if (v != RLIM_INFINITY) + val->totalram = min(val->totalram, v); + v = atomic_read(&vxi->limit.rcur[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; + unsigned long v, w; + + v = vxi->limit.rlim[RLIMIT_RSS]; + w = vxi->limit.rlim[RLIMIT_AS]; + if (w != RLIM_INFINITY) + val->totalswap = min(val->totalswap, w - + ((v != RLIM_INFINITY) ? v : 0)); + w = atomic_read(&vxi->limit.rcur[RLIMIT_AS]); + val->freeswap = (w < val->totalswap) ? val->totalswap - w : 0; + return; +} + --- linux-2.6.12.2/include/linux/fs.h 2005-06-22 02:38:48 +0200 +++ linux-2.6.12.2-vs2.0-rc6.1/include/linux/fs.h 2005-07-09 03:54:30 +0200 @@ -666,6 +680,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 */