From: Simon Derr <simon.derr@bull.net>

This fixes a possible race between two threads of a single process in
cpuset_tasks_read().

It is mostly the same issue as the one that was in sysfs.

Signed-Off-By: Simon Derr <simon.derr@bull.net>
Signed-off-by: Andrew Morton <akpm@osdl.org>
---

 25-akpm/kernel/cpuset.c |   13 ++++++++++---
 1 files changed, 10 insertions(+), 3 deletions(-)

diff -puN kernel/cpuset.c~cpusets-fix-possible-race-in-cpuset_tasks_read kernel/cpuset.c
--- 25/kernel/cpuset.c~cpusets-fix-possible-race-in-cpuset_tasks_read	2004-09-11 17:26:05.822749504 -0700
+++ 25-akpm/kernel/cpuset.c	2004-09-11 17:26:05.826748896 -0700
@@ -1083,20 +1083,27 @@ err0:
 static ssize_t cpuset_tasks_read(struct file *file, char __user *buf,
 						size_t nbytes, loff_t *ppos)
 {
-	struct ctr_struct *ctr = (struct ctr_struct *)file->private_data;
+	struct ctr_struct *ctr;
 
+	down(&cpuset_sem);
+	ctr = (struct ctr_struct *)file->private_data;
 	/* allocate buffer and fill it on first call to read() */
 	if (!ctr) {
 		ctr = cpuset_tasks_mkctr(file);
-		if (!ctr)
+		if (!ctr) {
+			up(&cpuset_sem);
 			return -ENOMEM;
+		}
 	}
 
 	if (*ppos + nbytes > ctr->bufsz)
 		nbytes = ctr->bufsz - *ppos;
-	if (copy_to_user(buf, ctr->buf + *ppos, nbytes))
+	if (copy_to_user(buf, ctr->buf + *ppos, nbytes)) {
+		up(&cpuset_sem);
 		return -EFAULT;
+	}
 	*ppos += nbytes;
+	up(&cpuset_sem);
 	return nbytes;
 }
 
_