diff -urN linux-2.5.6/Documentation/filesystems/proc.txt linux/Documentation/filesystems/proc.txt --- linux-2.5.6/Documentation/filesystems/proc.txt Thu Mar 7 21:18:20 2002 +++ linux/Documentation/filesystems/proc.txt Sun Mar 10 13:34:22 2002 @@ -118,6 +118,7 @@ Table 1-1: Process specific entries in /proc .............................................................................. File Content + affinity Writable bitmask of allowed CPUs (2.5)(smp) cmdline Command line arguments cpu Current and last cpu in wich it was executed (2.4)(smp) cwd Link to the current working directory @@ -159,12 +160,17 @@ CapPrm: 0000000000000000 CapEff: 0000000000000000 - This shows you nearly the same information you would get if you viewed it with the ps command. In fact, ps uses the proc file system to obtain its information. The statm file contains more detailed information about the process memory usage. Its seven fields are explained in Table 1-2. +For writable entries, such as affinity: + + >echo 1 > /proc/PID/affinity + +To set the affinity of PID to 0x00000001 (=> only CPU0). + Table 1-2: Contents of the statm files .............................................................................. diff -urN linux-2.5.6/fs/proc/array.c linux/fs/proc/array.c --- linux-2.5.6/fs/proc/array.c Thu Mar 7 21:18:07 2002 +++ linux/fs/proc/array.c Sun Mar 10 13:34:22 2002 @@ -47,9 +47,11 @@ * Gerhard Wichert : added BIGMEM support * Siemens AG * - * 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. + * Al Viro & : moved most of the thing into base.c and + * Jeff Garzik proc_misc.c. The rest may eventually go into + * base.c too. + * + * Robert Love : added affinity (get/set task->cpus_allowed) */ #include @@ -695,4 +697,37 @@ return len; } -#endif + +int proc_pid_affinity_read(struct task_struct *task, char * buffer) +{ + return sprintf(buffer, "%08lx\n", task->cpus_allowed & cpu_online_map); +} + +int proc_pid_affinity_write(struct task_struct *task, char *buffer, + size_t bytes) +{ + int retval; + unsigned long new_mask; + char *end; + + new_mask = simple_strtoul(buffer, &end, 16); + new_mask &= cpu_online_map; + if (!new_mask) + return -EINVAL; + + read_lock(&tasklist_lock); + + if ((current->euid != task->euid) && (current->euid != task->uid) + && !capable(CAP_SYS_NICE)) { + retval = -EPERM; + goto out_unlock; + } + + retval = end - buffer; + set_cpus_allowed(task, new_mask); + +out_unlock: + read_unlock(&tasklist_lock); + return retval; +} +#endif /* CONFIG_SMP */ diff -urN linux-2.5.6/fs/proc/base.c linux/fs/proc/base.c --- linux-2.5.6/fs/proc/base.c Thu Mar 7 21:18:08 2002 +++ linux/fs/proc/base.c Sun Mar 10 13:34:22 2002 @@ -47,6 +47,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) { @@ -331,8 +333,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; + struct task_struct *task = proc_task(inode); + struct proc_inode *ei = PROC_I(inode); + ssize_t ret; + if (ei->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)) { + ret = -EFAULT; + goto out; + } + + ((char *) page)[count] = '\0'; + + ret = ei->op.proc_write(task, (char*) page, count); + if (ret < 0) + goto out; + + *ppos += ret; + +out: + 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) \ @@ -546,6 +584,7 @@ PROC_PID_STATM, PROC_PID_MAPS, PROC_PID_CPU, + PROC_PID_AFFINITY, PROC_PID_MOUNTS, PROC_PID_FD_DIR = 0x8000, /* 0x8000-0xffff */ }; @@ -560,6 +599,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), @@ -936,6 +976,11 @@ inode->i_fop = &proc_info_file_operations; ei->op.proc_read = proc_pid_cpu; break; + case PROC_PID_AFFINITY: + inode->i_fop = &proc_info_file_operations; + ei->op.proc_read = proc_pid_affinity_read; + ei->op.proc_write = proc_pid_affinity_write; + break; #endif case PROC_PID_MEM: inode->i_op = &proc_mem_inode_operations; diff -urN linux-2.5.6/include/linux/capability.h linux/include/linux/capability.h --- linux-2.5.6/include/linux/capability.h Thu Mar 7 21:18:19 2002 +++ linux/include/linux/capability.h Sun Mar 10 13:34:22 2002 @@ -242,6 +242,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.5.6/include/linux/proc_fs.h linux/include/linux/proc_fs.h --- linux-2.5.6/include/linux/proc_fs.h Thu Mar 7 21:18:03 2002 +++ linux/include/linux/proc_fs.h Sun Mar 10 13:34:22 2002 @@ -208,9 +208,10 @@ struct proc_inode { 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; struct proc_dir_entry *pde;