Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

at v3.0-rc2 250 lines 5.1 kB view raw
1/* 2 * fs/ioprio.c 3 * 4 * Copyright (C) 2004 Jens Axboe <axboe@kernel.dk> 5 * 6 * Helper functions for setting/querying io priorities of processes. The 7 * system calls closely mimmick getpriority/setpriority, see the man page for 8 * those. The prio argument is a composite of prio class and prio data, where 9 * the data argument has meaning within that class. The standard scheduling 10 * classes have 8 distinct prio levels, with 0 being the highest prio and 7 11 * being the lowest. 12 * 13 * IOW, setting BE scheduling class with prio 2 is done ala: 14 * 15 * unsigned int prio = (IOPRIO_CLASS_BE << IOPRIO_CLASS_SHIFT) | 2; 16 * 17 * ioprio_set(PRIO_PROCESS, pid, prio); 18 * 19 * See also Documentation/block/ioprio.txt 20 * 21 */ 22#include <linux/gfp.h> 23#include <linux/kernel.h> 24#include <linux/ioprio.h> 25#include <linux/blkdev.h> 26#include <linux/capability.h> 27#include <linux/syscalls.h> 28#include <linux/security.h> 29#include <linux/pid_namespace.h> 30 31int set_task_ioprio(struct task_struct *task, int ioprio) 32{ 33 int err; 34 struct io_context *ioc; 35 const struct cred *cred = current_cred(), *tcred; 36 37 rcu_read_lock(); 38 tcred = __task_cred(task); 39 if (tcred->uid != cred->euid && 40 tcred->uid != cred->uid && !capable(CAP_SYS_NICE)) { 41 rcu_read_unlock(); 42 return -EPERM; 43 } 44 rcu_read_unlock(); 45 46 err = security_task_setioprio(task, ioprio); 47 if (err) 48 return err; 49 50 task_lock(task); 51 do { 52 ioc = task->io_context; 53 /* see wmb() in current_io_context() */ 54 smp_read_barrier_depends(); 55 if (ioc) 56 break; 57 58 ioc = alloc_io_context(GFP_ATOMIC, -1); 59 if (!ioc) { 60 err = -ENOMEM; 61 break; 62 } 63 task->io_context = ioc; 64 } while (1); 65 66 if (!err) { 67 ioc->ioprio = ioprio; 68 ioc->ioprio_changed = 1; 69 } 70 71 task_unlock(task); 72 return err; 73} 74EXPORT_SYMBOL_GPL(set_task_ioprio); 75 76SYSCALL_DEFINE3(ioprio_set, int, which, int, who, int, ioprio) 77{ 78 int class = IOPRIO_PRIO_CLASS(ioprio); 79 int data = IOPRIO_PRIO_DATA(ioprio); 80 struct task_struct *p, *g; 81 struct user_struct *user; 82 struct pid *pgrp; 83 int ret; 84 85 switch (class) { 86 case IOPRIO_CLASS_RT: 87 if (!capable(CAP_SYS_ADMIN)) 88 return -EPERM; 89 /* fall through, rt has prio field too */ 90 case IOPRIO_CLASS_BE: 91 if (data >= IOPRIO_BE_NR || data < 0) 92 return -EINVAL; 93 94 break; 95 case IOPRIO_CLASS_IDLE: 96 break; 97 case IOPRIO_CLASS_NONE: 98 if (data) 99 return -EINVAL; 100 break; 101 default: 102 return -EINVAL; 103 } 104 105 ret = -ESRCH; 106 rcu_read_lock(); 107 switch (which) { 108 case IOPRIO_WHO_PROCESS: 109 if (!who) 110 p = current; 111 else 112 p = find_task_by_vpid(who); 113 if (p) 114 ret = set_task_ioprio(p, ioprio); 115 break; 116 case IOPRIO_WHO_PGRP: 117 if (!who) 118 pgrp = task_pgrp(current); 119 else 120 pgrp = find_vpid(who); 121 do_each_pid_thread(pgrp, PIDTYPE_PGID, p) { 122 ret = set_task_ioprio(p, ioprio); 123 if (ret) 124 break; 125 } while_each_pid_thread(pgrp, PIDTYPE_PGID, p); 126 break; 127 case IOPRIO_WHO_USER: 128 if (!who) 129 user = current_user(); 130 else 131 user = find_user(who); 132 133 if (!user) 134 break; 135 136 do_each_thread(g, p) { 137 if (__task_cred(p)->uid != who) 138 continue; 139 ret = set_task_ioprio(p, ioprio); 140 if (ret) 141 goto free_uid; 142 } while_each_thread(g, p); 143free_uid: 144 if (who) 145 free_uid(user); 146 break; 147 default: 148 ret = -EINVAL; 149 } 150 151 rcu_read_unlock(); 152 return ret; 153} 154 155static int get_task_ioprio(struct task_struct *p) 156{ 157 int ret; 158 159 ret = security_task_getioprio(p); 160 if (ret) 161 goto out; 162 ret = IOPRIO_PRIO_VALUE(IOPRIO_CLASS_NONE, IOPRIO_NORM); 163 if (p->io_context) 164 ret = p->io_context->ioprio; 165out: 166 return ret; 167} 168 169int ioprio_best(unsigned short aprio, unsigned short bprio) 170{ 171 unsigned short aclass = IOPRIO_PRIO_CLASS(aprio); 172 unsigned short bclass = IOPRIO_PRIO_CLASS(bprio); 173 174 if (aclass == IOPRIO_CLASS_NONE) 175 aclass = IOPRIO_CLASS_BE; 176 if (bclass == IOPRIO_CLASS_NONE) 177 bclass = IOPRIO_CLASS_BE; 178 179 if (aclass == bclass) 180 return min(aprio, bprio); 181 if (aclass > bclass) 182 return bprio; 183 else 184 return aprio; 185} 186 187SYSCALL_DEFINE2(ioprio_get, int, which, int, who) 188{ 189 struct task_struct *g, *p; 190 struct user_struct *user; 191 struct pid *pgrp; 192 int ret = -ESRCH; 193 int tmpio; 194 195 rcu_read_lock(); 196 switch (which) { 197 case IOPRIO_WHO_PROCESS: 198 if (!who) 199 p = current; 200 else 201 p = find_task_by_vpid(who); 202 if (p) 203 ret = get_task_ioprio(p); 204 break; 205 case IOPRIO_WHO_PGRP: 206 if (!who) 207 pgrp = task_pgrp(current); 208 else 209 pgrp = find_vpid(who); 210 do_each_pid_thread(pgrp, PIDTYPE_PGID, p) { 211 tmpio = get_task_ioprio(p); 212 if (tmpio < 0) 213 continue; 214 if (ret == -ESRCH) 215 ret = tmpio; 216 else 217 ret = ioprio_best(ret, tmpio); 218 } while_each_pid_thread(pgrp, PIDTYPE_PGID, p); 219 break; 220 case IOPRIO_WHO_USER: 221 if (!who) 222 user = current_user(); 223 else 224 user = find_user(who); 225 226 if (!user) 227 break; 228 229 do_each_thread(g, p) { 230 if (__task_cred(p)->uid != user->uid) 231 continue; 232 tmpio = get_task_ioprio(p); 233 if (tmpio < 0) 234 continue; 235 if (ret == -ESRCH) 236 ret = tmpio; 237 else 238 ret = ioprio_best(ret, tmpio); 239 } while_each_thread(g, p); 240 241 if (who) 242 free_uid(user); 243 break; 244 default: 245 ret = -EINVAL; 246 } 247 248 rcu_read_unlock(); 249 return ret; 250}