]> git.proxmox.com Git - mirror_ubuntu-artful-kernel.git/blame - block/ioprio.c
UBUNTU: Ubuntu-4.13.0-45.50
[mirror_ubuntu-artful-kernel.git] / block / ioprio.c
CommitLineData
22e2c507
JA
1/*
2 * fs/ioprio.c
3 *
0fe23479 4 * Copyright (C) 2004 Jens Axboe <axboe@kernel.dk>
22e2c507
JA
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 */
5a0e3ad6 22#include <linux/gfp.h>
22e2c507 23#include <linux/kernel.h>
afeacc8c 24#include <linux/export.h>
22e2c507 25#include <linux/ioprio.h>
5b825c3a 26#include <linux/cred.h>
22e2c507 27#include <linux/blkdev.h>
16f7e0fe 28#include <linux/capability.h>
8703e8a4 29#include <linux/sched/user.h>
f719ff9b 30#include <linux/sched/task.h>
9abdc4cd 31#include <linux/syscalls.h>
03e68060 32#include <linux/security.h>
b488893a 33#include <linux/pid_namespace.h>
22e2c507 34
b3881f74 35int set_task_ioprio(struct task_struct *task, int ioprio)
22e2c507 36{
03e68060 37 int err;
22e2c507 38 struct io_context *ioc;
c69e8d9c 39 const struct cred *cred = current_cred(), *tcred;
22e2c507 40
c69e8d9c
DH
41 rcu_read_lock();
42 tcred = __task_cred(task);
8e96e3b7
EB
43 if (!uid_eq(tcred->uid, cred->euid) &&
44 !uid_eq(tcred->uid, cred->uid) && !capable(CAP_SYS_NICE)) {
c69e8d9c 45 rcu_read_unlock();
22e2c507 46 return -EPERM;
c69e8d9c
DH
47 }
48 rcu_read_unlock();
22e2c507 49
03e68060
JM
50 err = security_task_setioprio(task, ioprio);
51 if (err)
52 return err;
53
6e736be7
TH
54 ioc = get_task_io_context(task, GFP_ATOMIC, NUMA_NO_NODE);
55 if (ioc) {
2b566fa5 56 ioc->ioprio = ioprio;
11a3122f 57 put_io_context(ioc);
fd0928df 58 }
22e2c507 59
fd0928df 60 return err;
22e2c507 61}
b3881f74 62EXPORT_SYMBOL_GPL(set_task_ioprio);
22e2c507 63
938bb9f5 64SYSCALL_DEFINE3(ioprio_set, int, which, int, who, int, ioprio)
22e2c507
JA
65{
66 int class = IOPRIO_PRIO_CLASS(ioprio);
67 int data = IOPRIO_PRIO_DATA(ioprio);
68 struct task_struct *p, *g;
69 struct user_struct *user;
41487c65 70 struct pid *pgrp;
7b44ab97 71 kuid_t uid;
22e2c507
JA
72 int ret;
73
74 switch (class) {
75 case IOPRIO_CLASS_RT:
76 if (!capable(CAP_SYS_ADMIN))
77 return -EPERM;
e29387eb
BVA
78 /* fall through */
79 /* rt has prio field too */
22e2c507
JA
80 case IOPRIO_CLASS_BE:
81 if (data >= IOPRIO_BE_NR || data < 0)
82 return -EINVAL;
83
84 break;
85 case IOPRIO_CLASS_IDLE:
86 break;
8ec680e4
JA
87 case IOPRIO_CLASS_NONE:
88 if (data)
89 return -EINVAL;
90 break;
22e2c507
JA
91 default:
92 return -EINVAL;
93 }
94
95 ret = -ESRCH;
d69b78ba 96 rcu_read_lock();
22e2c507
JA
97 switch (which) {
98 case IOPRIO_WHO_PROCESS:
99 if (!who)
100 p = current;
101 else
228ebcbe 102 p = find_task_by_vpid(who);
22e2c507
JA
103 if (p)
104 ret = set_task_ioprio(p, ioprio);
105 break;
106 case IOPRIO_WHO_PGRP:
107 if (!who)
41487c65
EB
108 pgrp = task_pgrp(current);
109 else
b488893a 110 pgrp = find_vpid(who);
2d70b68d 111 do_each_pid_thread(pgrp, PIDTYPE_PGID, p) {
22e2c507
JA
112 ret = set_task_ioprio(p, ioprio);
113 if (ret)
114 break;
2d70b68d 115 } while_each_pid_thread(pgrp, PIDTYPE_PGID, p);
22e2c507
JA
116 break;
117 case IOPRIO_WHO_USER:
7b44ab97
EB
118 uid = make_kuid(current_user_ns(), who);
119 if (!uid_valid(uid))
120 break;
22e2c507 121 if (!who)
86a264ab 122 user = current_user();
22e2c507 123 else
7b44ab97 124 user = find_user(uid);
22e2c507
JA
125
126 if (!user)
127 break;
128
612dafab 129 for_each_process_thread(g, p) {
8639b461
BS
130 if (!uid_eq(task_uid(p), uid) ||
131 !task_pid_vnr(p))
22e2c507
JA
132 continue;
133 ret = set_task_ioprio(p, ioprio);
134 if (ret)
78bd4d48 135 goto free_uid;
612dafab 136 }
78bd4d48 137free_uid:
22e2c507
JA
138 if (who)
139 free_uid(user);
140 break;
141 default:
142 ret = -EINVAL;
143 }
144
d69b78ba 145 rcu_read_unlock();
22e2c507
JA
146 return ret;
147}
148
a1836a42
DQ
149static int get_task_ioprio(struct task_struct *p)
150{
151 int ret;
152
153 ret = security_task_getioprio(p);
154 if (ret)
155 goto out;
fd0928df 156 ret = IOPRIO_PRIO_VALUE(IOPRIO_CLASS_NONE, IOPRIO_NORM);
8ba86821 157 task_lock(p);
fd0928df
JA
158 if (p->io_context)
159 ret = p->io_context->ioprio;
8ba86821 160 task_unlock(p);
a1836a42
DQ
161out:
162 return ret;
163}
164
e014ff8d
ON
165int ioprio_best(unsigned short aprio, unsigned short bprio)
166{
ece9c72a
JK
167 if (!ioprio_valid(aprio))
168 aprio = IOPRIO_PRIO_VALUE(IOPRIO_CLASS_BE, IOPRIO_NORM);
169 if (!ioprio_valid(bprio))
170 bprio = IOPRIO_PRIO_VALUE(IOPRIO_CLASS_BE, IOPRIO_NORM);
e014ff8d 171
9a87182c 172 return min(aprio, bprio);
e014ff8d
ON
173}
174
938bb9f5 175SYSCALL_DEFINE2(ioprio_get, int, which, int, who)
22e2c507
JA
176{
177 struct task_struct *g, *p;
178 struct user_struct *user;
41487c65 179 struct pid *pgrp;
7b44ab97 180 kuid_t uid;
22e2c507 181 int ret = -ESRCH;
a1836a42 182 int tmpio;
22e2c507 183
d69b78ba 184 rcu_read_lock();
22e2c507
JA
185 switch (which) {
186 case IOPRIO_WHO_PROCESS:
187 if (!who)
188 p = current;
189 else
228ebcbe 190 p = find_task_by_vpid(who);
22e2c507 191 if (p)
a1836a42 192 ret = get_task_ioprio(p);
22e2c507
JA
193 break;
194 case IOPRIO_WHO_PGRP:
195 if (!who)
41487c65
EB
196 pgrp = task_pgrp(current);
197 else
b488893a 198 pgrp = find_vpid(who);
2d70b68d 199 do_each_pid_thread(pgrp, PIDTYPE_PGID, p) {
a1836a42
DQ
200 tmpio = get_task_ioprio(p);
201 if (tmpio < 0)
202 continue;
22e2c507 203 if (ret == -ESRCH)
a1836a42 204 ret = tmpio;
22e2c507 205 else
a1836a42 206 ret = ioprio_best(ret, tmpio);
2d70b68d 207 } while_each_pid_thread(pgrp, PIDTYPE_PGID, p);
22e2c507
JA
208 break;
209 case IOPRIO_WHO_USER:
7b44ab97 210 uid = make_kuid(current_user_ns(), who);
22e2c507 211 if (!who)
86a264ab 212 user = current_user();
22e2c507 213 else
7b44ab97 214 user = find_user(uid);
22e2c507
JA
215
216 if (!user)
217 break;
218
612dafab 219 for_each_process_thread(g, p) {
8639b461
BS
220 if (!uid_eq(task_uid(p), user->uid) ||
221 !task_pid_vnr(p))
22e2c507 222 continue;
a1836a42
DQ
223 tmpio = get_task_ioprio(p);
224 if (tmpio < 0)
225 continue;
22e2c507 226 if (ret == -ESRCH)
a1836a42 227 ret = tmpio;
22e2c507 228 else
a1836a42 229 ret = ioprio_best(ret, tmpio);
612dafab 230 }
22e2c507
JA
231
232 if (who)
233 free_uid(user);
234 break;
235 default:
236 ret = -EINVAL;
237 }
238
d69b78ba 239 rcu_read_unlock();
22e2c507
JA
240 return ret;
241}