]> git.neil.brown.name Git - history.git/commitdiff
[PATCH] consolidate task->mm code + fix
authorJohn Levon <levon@movementarian.org>
Wed, 24 Jul 2002 03:48:18 +0000 (20:48 -0700)
committerLinus Torvalds <torvalds@home.transmeta.com>
Wed, 24 Jul 2002 03:48:18 +0000 (20:48 -0700)
The patch below consolidates some duplicate code, reduces some
indentation, and adds a freeing of a page in mem_read() that could be left
unfreed, as far as I can see.

fs/proc/array.c
fs/proc/base.c
include/linux/sched.h
kernel/ptrace.c

index e0b09b3ced45bd73b786fa7a9f162fa174dc5bdc..8001f3faed1bf1b6f5100ec419009d16b29fc701 100644 (file)
@@ -277,15 +277,11 @@ static inline char *task_cap(struct task_struct *p, char *buffer)
 int proc_pid_status(struct task_struct *task, char * buffer)
 {
        char * orig = buffer;
-       struct mm_struct *mm;
+       struct mm_struct *mm = get_task_mm(task);
 
        buffer = task_name(task, buffer);
        buffer = task_state(task, buffer);
-       task_lock(task);
-       mm = task->mm;
-       if(mm)
-               atomic_inc(&mm->mm_users);
-       task_unlock(task);
        if (mm) {
                buffer = task_mem(mm, buffer);
                mmput(mm);
@@ -481,14 +477,9 @@ static void statm_pgd_range(pgd_t * pgd, unsigned long address, unsigned long en
 
 int proc_pid_statm(struct task_struct *task, char * buffer)
 {
-       struct mm_struct *mm;
        int size=0, resident=0, share=0, trs=0, lrs=0, drs=0, dt=0;
+       struct mm_struct *mm = get_task_mm(task);
 
-       task_lock(task);
-       mm = task->mm;
-       if(mm)
-               atomic_inc(&mm->mm_users);
-       task_unlock(task);
        if (mm) {
                struct vm_area_struct * vma;
                down_read(&mm->mmap_sem);
@@ -626,11 +617,8 @@ ssize_t proc_pid_read_maps (struct task_struct *task, struct file * file, char *
        if (!tmp)
                goto out_free1;
 
-       task_lock(task);
-       mm = task->mm;
-       if (mm)
-               atomic_inc(&mm->mm_users);
-       task_unlock(task);
+       mm = get_task_mm(task);
        retval = 0;
        if (!mm)
                goto out_free2;
index c8a80b066a72948ee5524fd7ed9263959754993d..adecdb54916239f3c6d3a39ddb0b38977bc5e99d 100644 (file)
@@ -131,16 +131,11 @@ static int proc_fd_link(struct inode *inode, struct dentry **dentry, struct vfsm
 
 static int proc_exe_link(struct inode *inode, struct dentry **dentry, struct vfsmount **mnt)
 {
-       struct mm_struct * mm;
        struct vm_area_struct * vma;
        int result = -ENOENT;
        struct task_struct *task = proc_task(inode);
+       struct mm_struct * mm = get_task_mm(task);
 
-       task_lock(task);
-       mm = task->mm;
-       if (mm)
-               atomic_inc(&mm->mm_users);
-       task_unlock(task);
        if (!mm)
                goto out;
        down_read(&mm->mmap_sem);
@@ -203,13 +198,8 @@ static int proc_root_link(struct inode *inode, struct dentry **dentry, struct vf
 
 static int proc_pid_environ(struct task_struct *task, char * buffer)
 {
-       struct mm_struct *mm;
        int res = 0;
-       task_lock(task);
-       mm = task->mm;
-       if (mm)
-               atomic_inc(&mm->mm_users);
-       task_unlock(task);
+       struct mm_struct *mm = get_task_mm(task);
        if (mm) {
                int len = mm->env_end - mm->env_start;
                if (len > PAGE_SIZE)
@@ -222,38 +212,36 @@ static int proc_pid_environ(struct task_struct *task, char * buffer)
 
 static int proc_pid_cmdline(struct task_struct *task, char * buffer)
 {
-       struct mm_struct *mm;
        int res = 0;
-       task_lock(task);
-       mm = task->mm;
-       if (mm)
-               atomic_inc(&mm->mm_users);
-       task_unlock(task);
-       if (mm) {
-               int len = mm->arg_end - mm->arg_start;
-               if (len > PAGE_SIZE)
-                       len = PAGE_SIZE;
-               res = access_process_vm(task, mm->arg_start, buffer, len, 0);
-               // If the nul at the end of args has been overwritten, then
-               // assume application is using setproctitle(3).
-               if ( res > 0 && buffer[res-1] != '\0' )
-               {
-                       len = strnlen( buffer, res );
-                       if ( len < res )
-                       {
-                           res = len;
-                       }
-                       else
-                       {
-                               len = mm->env_end - mm->env_start;
-                               if (len > PAGE_SIZE - res)
-                                       len = PAGE_SIZE - res;
-                               res += access_process_vm(task, mm->env_start, buffer+res, len, 0);
-                               res = strnlen( buffer, res );
-                       }
+       int len;
+       struct mm_struct *mm = get_task_mm(task);
+       if (!mm)
+               goto out;
+
+       len = mm->arg_end - mm->arg_start;
+       if (len > PAGE_SIZE)
+               len = PAGE_SIZE;
+       res = access_process_vm(task, mm->arg_start, buffer, len, 0);
+
+       // If the nul at the end of args has been overwritten, then
+       // assume application is using setproctitle(3).
+       if (res > 0 && buffer[res-1] != '\0') {
+               len = strnlen(buffer, res);
+               if (len < res) {
+                   res = len;
+               } else {
+                       len = mm->env_end - mm->env_start;
+                       if (len > PAGE_SIZE - res)
+                               len = PAGE_SIZE - res;
+                       res += access_process_vm(task, mm->env_start, buffer+res, len, 0);
+                       res = strnlen(buffer, res);
                }
-               mmput(mm);
        }
+       mmput(mm);
+
+out:
        return res;
 }
 
@@ -421,54 +409,59 @@ static ssize_t mem_read(struct file * file, char * buf,
        struct task_struct *task = proc_task(file->f_dentry->d_inode);
        char *page;
        unsigned long src = *ppos;
-       int copied = 0;
+       int ret = -ESRCH;
        struct mm_struct *mm;
 
-
        if (!MAY_PTRACE(task))
-               return -ESRCH;
+               goto out;
 
+       ret = -ENOMEM;
        page = (char *)__get_free_page(GFP_USER);
        if (!page)
-               return -ENOMEM;
+               goto out;
 
-       task_lock(task);
-       mm = task->mm;
-       if (mm)
-               atomic_inc(&mm->mm_users);
-       task_unlock(task);
+       ret = 0;
+       mm = get_task_mm(task);
        if (!mm)
-               return 0;
+               goto out_free;
 
-       if (file->private_data != (void*)((long)current->self_exec_id) ) {
-               mmput(mm);
-               return -EIO;
-       }
-               
+       ret = -EIO;
+       if (file->private_data != (void*)((long)current->self_exec_id))
+               goto out_put;
 
+       ret = 0;
        while (count > 0) {
                int this_len, retval;
 
                this_len = (count > PAGE_SIZE) ? PAGE_SIZE : count;
                retval = access_process_vm(task, src, page, this_len, 0);
                if (!retval) {
-                       if (!copied)
-                               copied = -EIO;
+                       if (!ret)
+                               ret = -EIO;
                        break;
                }
+
                if (copy_to_user(buf, page, retval)) {
-                       copied = -EFAULT;
+                       ret = -EFAULT;
                        break;
                }
-               copied += retval;
+               ret += retval;
                src += retval;
                buf += retval;
                count -= retval;
        }
        *ppos = src;
+
+out_put:
        mmput(mm);
+out_free:
        free_page((unsigned long) page);
-       return copied;
+out:
+       return ret;
 }
 
 #define mem_write NULL
index 1d288587e44d950d628af6bd50909da333d8ca66..004d2a129ca44aea4f4fbee3610871764901df28 100644 (file)
@@ -810,6 +810,27 @@ static inline char * d_path(struct dentry *dentry, struct vfsmount *vfsmnt,
        return res;
 }
 
+/**
+ * get_task_mm - acquire a reference to the task's mm
+ *
+ * Returns %NULL if the task has no mm. User must release
+ * the mm via mmput() after use.
+ */
+static inline struct mm_struct * get_task_mm(struct task_struct * task)
+{
+       struct mm_struct * mm;
+       task_lock(task);
+       mm = task->mm;
+       if (mm)
+               atomic_inc(&mm->mm_users);
+       task_unlock(task);
+
+       return mm;
+}
 /* set thread flags in other task's structures
  * - see asm/thread_info.h for TIF_xxxx flags available
  */
index 1a64a0c03b95c0c6a7eb44b847b0af2ac0569ae6..f6d76247cde30155724ec756cec7bfef4a9856c8 100644 (file)
@@ -124,12 +124,7 @@ int access_process_vm(struct task_struct *tsk, unsigned long addr, void *buf, in
        struct page *page;
        void *old_buf = buf;
 
-       /* Worry about races with exit() */
-       task_lock(tsk);
-       mm = tsk->mm;
-       if (mm)
-               atomic_inc(&mm->mm_users);
-       task_unlock(tsk);
+       mm = get_task_mm(tsk);
        if (!mm)
                return 0;