Use struct path in fs_struct
[sfrench/cifs-2.6.git] / kernel / fork.c
index 314f5101d2b0e5f864f22fce25c4255c7305f789..dd249c37b3a392af26a79142d0238447fee04df2 100644 (file)
@@ -40,6 +40,7 @@
 #include <linux/ptrace.h>
 #include <linux/mount.h>
 #include <linux/audit.h>
+#include <linux/memcontrol.h>
 #include <linux/profile.h>
 #include <linux/rmap.h>
 #include <linux/acct.h>
@@ -325,7 +326,7 @@ static inline int mm_alloc_pgd(struct mm_struct * mm)
 
 static inline void mm_free_pgd(struct mm_struct * mm)
 {
-       pgd_free(mm->pgd);
+       pgd_free(mm, mm->pgd);
 }
 #else
 #define dup_mmap(mm, oldmm)    (0)
@@ -340,7 +341,7 @@ __cacheline_aligned_in_smp DEFINE_SPINLOCK(mmlist_lock);
 
 #include <linux/init_task.h>
 
-static struct mm_struct * mm_init(struct mm_struct * mm)
+static struct mm_struct * mm_init(struct mm_struct * mm, struct task_struct *p)
 {
        atomic_set(&mm->mm_users, 1);
        atomic_set(&mm->mm_count, 1);
@@ -357,11 +358,14 @@ static struct mm_struct * mm_init(struct mm_struct * mm)
        mm->ioctx_list = NULL;
        mm->free_area_cache = TASK_UNMAPPED_BASE;
        mm->cached_hole_size = ~0UL;
+       mm_init_cgroup(mm, p);
 
        if (likely(!mm_alloc_pgd(mm))) {
                mm->def_flags = 0;
                return mm;
        }
+
+       mm_free_cgroup(mm);
        free_mm(mm);
        return NULL;
 }
@@ -376,7 +380,7 @@ struct mm_struct * mm_alloc(void)
        mm = allocate_mm();
        if (mm) {
                memset(mm, 0, sizeof(*mm));
-               mm = mm_init(mm);
+               mm = mm_init(mm, current);
        }
        return mm;
 }
@@ -386,13 +390,15 @@ struct mm_struct * mm_alloc(void)
  * is dropped: either by a lazy thread or by
  * mmput. Free the page directory and the mm.
  */
-void fastcall __mmdrop(struct mm_struct *mm)
+void __mmdrop(struct mm_struct *mm)
 {
        BUG_ON(mm == &init_mm);
        mm_free_pgd(mm);
+       mm_free_cgroup(mm);
        destroy_context(mm);
        free_mm(mm);
 }
+EXPORT_SYMBOL_GPL(__mmdrop);
 
 /*
  * Decrement the use count and release all resources for an mm.
@@ -510,7 +516,7 @@ static struct mm_struct *dup_mm(struct task_struct *tsk)
        mm->token_priority = 0;
        mm->last_interval = 0;
 
-       if (!mm_init(mm))
+       if (!mm_init(mm, tsk))
                goto fail_nomem;
 
        if (init_new_context(tsk, mm))
@@ -594,16 +600,16 @@ static struct fs_struct *__copy_fs_struct(struct fs_struct *old)
                rwlock_init(&fs->lock);
                fs->umask = old->umask;
                read_lock(&old->lock);
-               fs->rootmnt = mntget(old->rootmnt);
-               fs->root = dget(old->root);
-               fs->pwdmnt = mntget(old->pwdmnt);
-               fs->pwd = dget(old->pwd);
-               if (old->altroot) {
-                       fs->altrootmnt = mntget(old->altrootmnt);
-                       fs->altroot = dget(old->altroot);
+               fs->root = old->root;
+               path_get(&old->root);
+               fs->pwd = old->pwd;
+               path_get(&old->pwd);
+               if (old->altroot.dentry) {
+                       fs->altroot = old->altroot;
+                       path_get(&old->altroot);
                } else {
-                       fs->altrootmnt = NULL;
-                       fs->altroot = NULL;
+                       fs->altroot.mnt = NULL;
+                       fs->altroot.dentry = NULL;
                }
                read_unlock(&old->lock);
        }
@@ -903,7 +909,6 @@ static int copy_signal(unsigned long clone_flags, struct task_struct *tsk)
        hrtimer_init(&sig->real_timer, CLOCK_MONOTONIC, HRTIMER_MODE_REL);
        sig->it_real_incr.tv64 = 0;
        sig->real_timer.function = it_real_fn;
-       sig->tsk = tsk;
 
        sig->it_virt_expires = cputime_zero;
        sig->it_virt_incr = cputime_zero;
@@ -1117,6 +1122,7 @@ static struct task_struct *copy_process(unsigned long clone_flags,
 #ifdef CONFIG_SECURITY
        p->security = NULL;
 #endif
+       p->cap_bset = current->cap_bset;
        p->io_context = NULL;
        p->audit_context = NULL;
        cgroup_fork(p);
@@ -1331,6 +1337,7 @@ static struct task_struct *copy_process(unsigned long clone_flags,
                        if (clone_flags & CLONE_NEWPID)
                                p->nsproxy->pid_ns->child_reaper = p;
 
+                       p->signal->leader_pid = pid;
                        p->signal->tty = current->signal->tty;
                        set_task_pgrp(p, task_pgrp_nr(current));
                        set_task_session(p, task_session_nr(current));
@@ -1397,7 +1404,7 @@ fork_out:
        return ERR_PTR(retval);
 }
 
-noinline struct pt_regs * __devinit __attribute__((weak)) idle_regs(struct pt_regs *regs)
+noinline struct pt_regs * __cpuinit __attribute__((weak)) idle_regs(struct pt_regs *regs)
 {
        memset(regs, 0, sizeof(struct pt_regs));
        return regs;
@@ -1449,6 +1456,23 @@ long do_fork(unsigned long clone_flags,
        int trace = 0;
        long nr;
 
+       /*
+        * We hope to recycle these flags after 2.6.26
+        */
+       if (unlikely(clone_flags & CLONE_STOPPED)) {
+               static int __read_mostly count = 100;
+
+               if (count > 0 && printk_ratelimit()) {
+                       char comm[TASK_COMM_LEN];
+
+                       count--;
+                       printk(KERN_INFO "fork(): process `%s' used deprecated "
+                                       "clone flags 0x%lx\n",
+                               get_task_comm(comm, current),
+                               clone_flags & CLONE_STOPPED);
+               }
+       }
+
        if (unlikely(current->ptrace)) {
                trace = fork_traceflag (clone_flags);
                if (trace)
@@ -1464,13 +1488,7 @@ long do_fork(unsigned long clone_flags,
        if (!IS_ERR(p)) {
                struct completion vfork;
 
-               /*
-                * this is enough to call pid_nr_ns here, but this if
-                * improves optimisation of regular fork()
-                */
-               nr = (clone_flags & CLONE_NEWPID) ?
-                       task_pid_nr_ns(p, current->nsproxy->pid_ns) :
-                               task_pid_vnr(p);
+               nr = task_pid_vnr(p);
 
                if (clone_flags & CLONE_PARENT_SETTID)
                        put_user(nr, parent_tidptr);
@@ -1491,7 +1509,7 @@ long do_fork(unsigned long clone_flags,
                if (!(clone_flags & CLONE_STOPPED))
                        wake_up_new_task(p, clone_flags);
                else
-                       p->state = TASK_STOPPED;
+                       __set_task_state(p, TASK_STOPPED);
 
                if (unlikely (trace)) {
                        current->ptrace_message = nr;