diff -urN linux-2.4.16/fs/proc/array.c linux/fs/proc/array.c
--- linux-2.4.16/fs/proc/array.c	Mon Nov 26 15:56:17 2001
+++ linux/fs/proc/array.c	Mon Nov 26 21:37:02 2001
@@ -50,6 +50,8 @@
  * Al Viro & Jeff Garzik :  moved most of the thing into base.c and
  *			 :  proc_misc.c. The rest may eventually go into
  *			 :  base.c too.
+ *
+ * Robert Love	     :	added affinity (set processes's CPU affinity)
  */
 
 #include <linux/config.h>
@@ -693,4 +695,64 @@
 
 	return len;
 }
-#endif
+
+int proc_pid_affinity_read(struct task_struct *task, char * buffer)
+{
+	int len;
+
+	/*
+	 * AND the mask against the current CPU configuration to return
+	 * only valid bits
+	 */
+	len = sprintf(buffer, "%08lx\n", task->cpus_allowed & cpu_online_map);
+	return len;
+}
+
+int proc_pid_affinity_write(struct task_struct *task, char * buffer,
+		size_t bytes)
+{
+	unsigned long new_mask;
+	int reschedule = 0;
+	char * endp;
+
+	if ((current->euid != task->euid) && (current->euid != task->uid)
+			&& !capable(CAP_SYS_NICE))
+		return -EPERM;
+
+	new_mask = simple_strtoul(buffer, &endp, 16);
+
+	new_mask &= cpu_online_map;
+	if (!new_mask)
+		return -EINVAL;
+
+	read_lock_irq(&tasklist_lock);
+	spin_lock(&runqueue_lock);
+
+	task->cpus_allowed = new_mask;
+
+	/*
+	 * if running on a different CPU, cause a reschedule
+	 * to move the process to an allowed CPU
+	 */
+	if (!(task->cpus_runnable & task->cpus_allowed)) {
+		if (task == current)
+			reschedule = 1;
+		else {
+			task->need_resched = 1;
+			smp_send_reschedule(task->processor);
+		}
+	}
+
+	spin_unlock(&runqueue_lock);
+	read_unlock_irq(&tasklist_lock);
+
+	/*
+	 * if the task is on this CPU, wait to reschedule
+	 * it until we drop the locks
+	 */
+	if (reschedule)
+		schedule();
+
+	return endp - buffer;
+}
+#endif /* CONFIG_SMP */
diff -urN linux-2.4.16/fs/proc/base.c linux/fs/proc/base.c
--- linux-2.4.16/fs/proc/base.c	Mon Nov 26 15:56:17 2001
+++ linux/fs/proc/base.c	Mon Nov 26 21:39:28 2001
@@ -39,6 +39,8 @@
 int proc_pid_status(struct task_struct*,char*);
 int proc_pid_statm(struct task_struct*,char*);
 int proc_pid_cpu(struct task_struct*,char*);
+int proc_pid_affinity_read(struct task_struct*,char*);
+int proc_pid_affinity_write(struct task_struct*,char*,size_t);
 
 static int proc_fd_link(struct inode *inode, struct dentry **dentry, struct vfsmount **mnt)
 {
@@ -282,8 +284,44 @@
 	return count;
 }
 
+static ssize_t proc_info_write(struct file * file, const char * buf,
+			size_t count, loff_t *ppos)
+{
+	struct inode * inode = file->f_dentry->d_inode;
+	unsigned long page;
+	ssize_t ret;
+	struct task_struct *task = inode->u.proc_i.task;
+
+	if (inode->u.proc_i.op.proc_write == NULL)
+		return -EINVAL;
+
+	if (count > PAGE_SIZE - 1)
+		return -EINVAL;
+
+	if (!(page = __get_free_page(GFP_KERNEL)))
+		return -ENOMEM;
+
+	if (copy_from_user((char *)page, buf, count)) {
+		free_page(page);
+		return -EFAULT;
+	}
+
+	((char *) page)[count] = '\0';
+	ret = inode->u.proc_i.op.proc_write(task, (char*) page, count);
+	if (ret < 0) {
+		free_page(page);
+		return -EFAULT;
+	}
+
+	*ppos += ret;
+
+	free_page(page);
+	return ret;
+}
+
 static struct file_operations proc_info_file_operations = {
 	read:		proc_info_read,
+	write:		proc_info_write,
 };
 
 #define MAY_PTRACE(p) \
@@ -497,6 +535,7 @@
 	PROC_PID_STATM,
 	PROC_PID_MAPS,
 	PROC_PID_CPU,
+	PROC_PID_AFFINITY,
 	PROC_PID_FD_DIR = 0x8000,	/* 0x8000-0xffff */
 };
 
@@ -510,6 +549,7 @@
   E(PROC_PID_STATM,	"statm",	S_IFREG|S_IRUGO),
 #ifdef CONFIG_SMP
   E(PROC_PID_CPU,	"cpu",		S_IFREG|S_IRUGO),
+  E(PROC_PID_AFFINITY,	"affinity",	S_IFREG|S_IRUGO|S_IWUSR),
 #endif
   E(PROC_PID_MAPS,	"maps",		S_IFREG|S_IRUGO),
   E(PROC_PID_MEM,	"mem",		S_IFREG|S_IRUSR|S_IWUSR),
@@ -870,6 +910,11 @@
 			inode->i_fop = &proc_info_file_operations;
 			inode->u.proc_i.op.proc_read = proc_pid_cpu;
 			break;
+		case PROC_PID_AFFINITY:
+			inode->i_fop = &proc_info_file_operations;
+			inode->u.proc_i.op.proc_read = proc_pid_affinity_read;
+			inode->u.proc_i.op.proc_write = proc_pid_affinity_write;
+ 			break;
 #endif
 		case PROC_PID_MEM:
 			inode->i_op = &proc_mem_inode_operations;
diff -urN linux-2.4.16/include/linux/capability.h linux/include/linux/capability.h
--- linux-2.4.16/include/linux/capability.h	Mon Nov 26 15:56:21 2001
+++ linux/include/linux/capability.h	Mon Nov 26 19:36:51 2001
@@ -243,6 +243,7 @@
 /* Allow use of FIFO and round-robin (realtime) scheduling on own
    processes and setting the scheduling algorithm used by another
    process. */
+/* Allow setting CPU affinity */
 
 #define CAP_SYS_NICE         23
 
diff -urN linux-2.4.16/include/linux/proc_fs_i.h linux/include/linux/proc_fs_i.h
--- linux-2.4.16/include/linux/proc_fs_i.h	Mon Nov 26 15:56:21 2001
+++ linux/include/linux/proc_fs_i.h	Mon Nov 26 21:41:24 2001
@@ -1,9 +1,11 @@
 struct proc_inode_info {
 	struct task_struct *task;
 	int type;
-	union {
+	struct {
 		int (*proc_get_link)(struct inode *, struct dentry **, struct vfsmount **);
 		int (*proc_read)(struct task_struct *task, char *page);
+		int (*proc_write)(struct task_struct *task, char *page,
+				  size_t bytes);
 	} op;
 	struct file *file;
 };