This commit was manufactured by cvs2svn to create tag
[linux-2.6.git] / kernel / fork.c
index 84252e0..f6cbd98 100644 (file)
 #include <linux/audit.h>
 #include <linux/profile.h>
 #include <linux/rmap.h>
+#include <linux/ckrm.h>
+#include <linux/ckrm_tsk.h>
+#include <linux/ckrm_mem_inline.h>
+#include <linux/vs_network.h>
+#include <linux/vs_limit.h>
+#include <linux/vs_memory.h>
 
 #include <asm/pgtable.h>
 #include <asm/pgalloc.h>
@@ -81,6 +87,8 @@ static kmem_cache_t *task_struct_cachep;
 void free_task(struct task_struct *tsk)
 {
        free_thread_info(tsk->thread_info);
+       clr_vx_info(&tsk->vx_info);
+       clr_nx_info(&tsk->nx_info);
        free_task_struct(tsk);
 }
 EXPORT_SYMBOL(free_task);
@@ -152,6 +160,8 @@ static struct task_struct *dup_task_struct(struct task_struct *orig)
        tsk->thread_info = ti;
        ti->task = tsk;
 
+       ckrm_cb_newtask(tsk);
+       ckrm_task_mm_init(tsk);
        /* One for us, one for whoever does the "release_task()" (usually parent) */
        atomic_set(&tsk->usage,2);
        return tsk;
@@ -299,9 +309,11 @@ static struct mm_struct * mm_init(struct mm_struct * mm)
        mm->ioctx_list = NULL;
        mm->default_kioctx = (struct kioctx)INIT_KIOCTX(mm->default_kioctx, *mm);
        mm->free_area_cache = TASK_UNMAPPED_BASE;
+       ckrm_mm_init(mm);
 
        if (likely(!mm_alloc_pgd(mm))) {
                mm->def_flags = 0;
+               set_vx_info(&mm->mm_vx_info, current->vx_info);
                return mm;
        }
        free_mm(mm);
@@ -319,6 +331,7 @@ struct mm_struct * mm_alloc(void)
        if (mm) {
                memset(mm, 0, sizeof(*mm));
                mm = mm_init(mm);
+               ckrm_mm_setclass(mm, ckrm_get_mem_class(current));
        }
        return mm;
 }
@@ -333,6 +346,8 @@ void fastcall __mmdrop(struct mm_struct *mm)
        BUG_ON(mm == &init_mm);
        mm_free_pgd(mm);
        destroy_context(mm);
+       ckrm_mm_clearclass(mm);
+       clr_vx_info(&mm->mm_vx_info);
        free_mm(mm);
 }
 
@@ -459,6 +474,7 @@ static int copy_mm(unsigned long clone_flags, struct task_struct * tsk)
 
        /* Copy the current MM stuff.. */
        memcpy(mm, oldmm, sizeof(*mm));
+       mm->mm_vx_info = NULL;
        if (!mm_init(mm))
                goto fail_nomem;
 
@@ -470,8 +486,10 @@ static int copy_mm(unsigned long clone_flags, struct task_struct * tsk)
                goto free_pt;
 
 good_mm:
+       ckrm_mm_setclass(mm, oldmm->memclass);
        tsk->mm = mm;
        tsk->active_mm = mm;
+       ckrm_init_mm_to_task(mm, tsk);
        return 0;
 
 free_pt:
@@ -791,6 +809,7 @@ static task_t *copy_process(unsigned long clone_flags,
 {
        int retval;
        struct task_struct *p = NULL;
+       struct vx_info *vxi;
 
        if ((clone_flags & (CLONE_NEWNS|CLONE_FS)) == (CLONE_NEWNS|CLONE_FS))
                return ERR_PTR(-EINVAL);
@@ -818,13 +837,51 @@ static task_t *copy_process(unsigned long clone_flags,
        p = dup_task_struct(current);
        if (!p)
                goto fork_out;
+       p->tux_info = NULL;
+
+       p->vx_info = NULL;
+       set_vx_info(&p->vx_info, current->vx_info);
+       p->nx_info = NULL;
+       set_nx_info(&p->nx_info, current->nx_info);
+
+       /* check vserver memory */
+       if (p->mm && !(clone_flags & CLONE_VM)) {
+               if (vx_vmpages_avail(p->mm, p->mm->total_vm))
+                       vx_pages_add(p->mm->mm_vx_info, RLIMIT_AS, p->mm->total_vm);
+               else
+                       goto bad_fork_free;
+       }
+       if (p->mm && vx_flags(VXF_FORK_RSS, 0)) {
+               if (!vx_rsspages_avail(p->mm, p->mm->rss))
+                       goto bad_fork_cleanup_vm;
+       }
+
+       p->vx_info = NULL;
+       set_vx_info(&p->vx_info, current->vx_info);
+       p->nx_info = NULL;
+       set_nx_info(&p->nx_info, current->nx_info);
+
+       /* check vserver memory */
+       if (p->mm && !(clone_flags & CLONE_VM)) {
+               if (vx_vmpages_avail(p->mm, p->mm->total_vm))
+                       vx_pages_add(p->mm->mm_vx_info, RLIMIT_AS, p->mm->total_vm);
+               else
+                       goto bad_fork_free;
+       }
+       if (p->mm && vx_flags(VXF_FORK_RSS, 0)) {
+               if (!vx_rsspages_avail(p->mm, p->mm->rss))
+                       goto bad_fork_cleanup_vm;
+       }
 
        retval = -EAGAIN;
+       if (!vx_nproc_avail(1))
+               goto bad_fork_cleanup_vm;
+
        if (atomic_read(&p->user->processes) >=
                        p->signal->rlim[RLIMIT_NPROC].rlim_cur) {
                if (!capable(CAP_SYS_ADMIN) && !capable(CAP_SYS_RESOURCE) &&
                                p->user != &root_user)
-                       goto bad_fork_free;
+                       goto bad_fork_cleanup_vm;
        }
 
        atomic_inc(&p->user->__count);
@@ -845,6 +902,7 @@ static task_t *copy_process(unsigned long clone_flags,
        if (p->binfmt && !try_module_get(p->binfmt->module))
                goto bad_fork_cleanup_put_domain;
 
+       init_delays(p);
        p->did_exec = 0;
        copy_flags(clone_flags, p);
        p->pid = pid;
@@ -1019,7 +1077,14 @@ static task_t *copy_process(unsigned long clone_flags,
                        __get_cpu_var(process_counts)++;
        }
 
+       p->ioprio = current->ioprio;
        nr_threads++;
+       /* p is copy of current */
+       vxi = p->vx_info;
+       if (vxi) {
+               atomic_inc(&vxi->cvirt.nr_threads);
+               vx_nproc_inc(p);
+       }
        write_unlock_irq(&tasklist_lock);
        retval = 0;
 
@@ -1062,6 +1127,9 @@ bad_fork_cleanup_count:
        put_group_info(p->group_info);
        atomic_dec(&p->user->processes);
        free_uid(p->user);
+bad_fork_cleanup_vm:
+       if (p->mm && !(clone_flags & CLONE_VM))
+               vx_pages_sub(p->mm->mm_vx_info, RLIMIT_AS, p->mm->total_vm);
 bad_fork_free:
        free_task(p);
        goto fork_out;
@@ -1127,6 +1195,12 @@ long do_fork(unsigned long clone_flags,
                        clone_flags |= CLONE_PTRACE;
        }
 
+#ifdef CONFIG_CKRM_TYPE_TASKCLASS
+       if (numtasks_get_ref(current->taskclass, 0) == 0) {
+               return -ENOMEM;
+       }
+#endif
+
        p = copy_process(clone_flags, stack_start, regs, stack_size, parent_tidptr, child_tidptr, pid);
        /*
         * Do this prior waking up the new thread - the thread pointer
@@ -1135,6 +1209,8 @@ long do_fork(unsigned long clone_flags,
        if (!IS_ERR(p)) {
                struct completion vfork;
 
+               ckrm_cb_fork(p);
+
                if (clone_flags & CLONE_VFORK) {
                        p->vfork_done = &vfork;
                        init_completion(&vfork);
@@ -1165,6 +1241,9 @@ long do_fork(unsigned long clone_flags,
                                ptrace_notify ((PTRACE_EVENT_VFORK_DONE << 8) | SIGTRAP);
                }
        } else {
+#ifdef CONFIG_CKRM_TYPE_TASKCLASS
+               numtasks_put_ref(current->taskclass);
+#endif
                free_pidmap(pid);
                pid = PTR_ERR(p);
        }