]> git.proxmox.com Git - mirror_ubuntu-kernels.git/blame - block/ioprio.c
Merge tag 'rpmsg-v5.16' of git://git.kernel.org/pub/scm/linux/kernel/git/remoteproc...
[mirror_ubuntu-kernels.git] / block / ioprio.c
CommitLineData
3dcf60bc 1// SPDX-License-Identifier: GPL-2.0
22e2c507
JA
2/*
3 * fs/ioprio.c
4 *
0fe23479 5 * Copyright (C) 2004 Jens Axboe <axboe@kernel.dk>
22e2c507
JA
6 *
7 * Helper functions for setting/querying io priorities of processes. The
8 * system calls closely mimmick getpriority/setpriority, see the man page for
9 * those. The prio argument is a composite of prio class and prio data, where
10 * the data argument has meaning within that class. The standard scheduling
11 * classes have 8 distinct prio levels, with 0 being the highest prio and 7
12 * being the lowest.
13 *
14 * IOW, setting BE scheduling class with prio 2 is done ala:
15 *
16 * unsigned int prio = (IOPRIO_CLASS_BE << IOPRIO_CLASS_SHIFT) | 2;
17 *
18 * ioprio_set(PRIO_PROCESS, pid, prio);
19 *
898bd37a 20 * See also Documentation/block/ioprio.rst
22e2c507
JA
21 *
22 */
5a0e3ad6 23#include <linux/gfp.h>
22e2c507 24#include <linux/kernel.h>
afeacc8c 25#include <linux/export.h>
22e2c507 26#include <linux/ioprio.h>
5b825c3a 27#include <linux/cred.h>
22e2c507 28#include <linux/blkdev.h>
16f7e0fe 29#include <linux/capability.h>
8703e8a4 30#include <linux/sched/user.h>
f719ff9b 31#include <linux/sched/task.h>
9abdc4cd 32#include <linux/syscalls.h>
03e68060 33#include <linux/security.h>
b488893a 34#include <linux/pid_namespace.h>
22e2c507 35
b3881f74 36int set_task_ioprio(struct task_struct *task, int ioprio)
22e2c507 37{
03e68060 38 int err;
22e2c507 39 struct io_context *ioc;
c69e8d9c 40 const struct cred *cred = current_cred(), *tcred;
22e2c507 41
c69e8d9c
DH
42 rcu_read_lock();
43 tcred = __task_cred(task);
8e96e3b7
EB
44 if (!uid_eq(tcred->uid, cred->euid) &&
45 !uid_eq(tcred->uid, cred->uid) && !capable(CAP_SYS_NICE)) {
c69e8d9c 46 rcu_read_unlock();
22e2c507 47 return -EPERM;
c69e8d9c
DH
48 }
49 rcu_read_unlock();
22e2c507 50
03e68060
JM
51 err = security_task_setioprio(task, ioprio);
52 if (err)
53 return err;
54
6e736be7
TH
55 ioc = get_task_io_context(task, GFP_ATOMIC, NUMA_NO_NODE);
56 if (ioc) {
2b566fa5 57 ioc->ioprio = ioprio;
11a3122f 58 put_io_context(ioc);
fd0928df 59 }
22e2c507 60
fd0928df 61 return err;
22e2c507 62}
b3881f74 63EXPORT_SYMBOL_GPL(set_task_ioprio);
22e2c507 64
aa434577 65int ioprio_check_cap(int ioprio)
22e2c507
JA
66{
67 int class = IOPRIO_PRIO_CLASS(ioprio);
68 int data = IOPRIO_PRIO_DATA(ioprio);
22e2c507
JA
69
70 switch (class) {
71 case IOPRIO_CLASS_RT:
9d3a39a5 72 if (!capable(CAP_SYS_NICE) && !capable(CAP_SYS_ADMIN))
22e2c507 73 return -EPERM;
df561f66 74 fallthrough;
e29387eb 75 /* rt has prio field too */
22e2c507 76 case IOPRIO_CLASS_BE:
202bc942 77 if (data >= IOPRIO_NR_LEVELS || data < 0)
22e2c507 78 return -EINVAL;
22e2c507
JA
79 break;
80 case IOPRIO_CLASS_IDLE:
81 break;
8ec680e4
JA
82 case IOPRIO_CLASS_NONE:
83 if (data)
84 return -EINVAL;
85 break;
22e2c507
JA
86 default:
87 return -EINVAL;
88 }
89
aa434577
AM
90 return 0;
91}
92
93SYSCALL_DEFINE3(ioprio_set, int, which, int, who, int, ioprio)
94{
95 struct task_struct *p, *g;
96 struct user_struct *user;
97 struct pid *pgrp;
98 kuid_t uid;
99 int ret;
100
101 ret = ioprio_check_cap(ioprio);
102 if (ret)
103 return ret;
104
22e2c507 105 ret = -ESRCH;
d69b78ba 106 rcu_read_lock();
22e2c507
JA
107 switch (which) {
108 case IOPRIO_WHO_PROCESS:
109 if (!who)
110 p = current;
111 else
228ebcbe 112 p = find_task_by_vpid(who);
22e2c507
JA
113 if (p)
114 ret = set_task_ioprio(p, ioprio);
115 break;
116 case IOPRIO_WHO_PGRP:
117 if (!who)
41487c65
EB
118 pgrp = task_pgrp(current);
119 else
b488893a 120 pgrp = find_vpid(who);
40c7fd3f
PZ
121
122 read_lock(&tasklist_lock);
2d70b68d 123 do_each_pid_thread(pgrp, PIDTYPE_PGID, p) {
22e2c507 124 ret = set_task_ioprio(p, ioprio);
40c7fd3f
PZ
125 if (ret) {
126 read_unlock(&tasklist_lock);
127 goto out;
128 }
2d70b68d 129 } while_each_pid_thread(pgrp, PIDTYPE_PGID, p);
40c7fd3f
PZ
130 read_unlock(&tasklist_lock);
131
22e2c507
JA
132 break;
133 case IOPRIO_WHO_USER:
7b44ab97
EB
134 uid = make_kuid(current_user_ns(), who);
135 if (!uid_valid(uid))
136 break;
22e2c507 137 if (!who)
86a264ab 138 user = current_user();
22e2c507 139 else
7b44ab97 140 user = find_user(uid);
22e2c507
JA
141
142 if (!user)
143 break;
144
612dafab 145 for_each_process_thread(g, p) {
8639b461
BS
146 if (!uid_eq(task_uid(p), uid) ||
147 !task_pid_vnr(p))
22e2c507
JA
148 continue;
149 ret = set_task_ioprio(p, ioprio);
150 if (ret)
78bd4d48 151 goto free_uid;
612dafab 152 }
78bd4d48 153free_uid:
22e2c507
JA
154 if (who)
155 free_uid(user);
156 break;
157 default:
158 ret = -EINVAL;
159 }
160
40c7fd3f 161out:
d69b78ba 162 rcu_read_unlock();
22e2c507
JA
163 return ret;
164}
165
a1836a42
DQ
166static int get_task_ioprio(struct task_struct *p)
167{
168 int ret;
169
170 ret = security_task_getioprio(p);
171 if (ret)
172 goto out;
e70344c0 173 ret = IOPRIO_DEFAULT;
8ba86821 174 task_lock(p);
fd0928df
JA
175 if (p->io_context)
176 ret = p->io_context->ioprio;
8ba86821 177 task_unlock(p);
a1836a42
DQ
178out:
179 return ret;
180}
181
e014ff8d
ON
182int ioprio_best(unsigned short aprio, unsigned short bprio)
183{
ece9c72a 184 if (!ioprio_valid(aprio))
e70344c0 185 aprio = IOPRIO_DEFAULT;
ece9c72a 186 if (!ioprio_valid(bprio))
e70344c0 187 bprio = IOPRIO_DEFAULT;
e014ff8d 188
9a87182c 189 return min(aprio, bprio);
e014ff8d
ON
190}
191
938bb9f5 192SYSCALL_DEFINE2(ioprio_get, int, which, int, who)
22e2c507
JA
193{
194 struct task_struct *g, *p;
195 struct user_struct *user;
41487c65 196 struct pid *pgrp;
7b44ab97 197 kuid_t uid;
22e2c507 198 int ret = -ESRCH;
a1836a42 199 int tmpio;
22e2c507 200
d69b78ba 201 rcu_read_lock();
22e2c507
JA
202 switch (which) {
203 case IOPRIO_WHO_PROCESS:
204 if (!who)
205 p = current;
206 else
228ebcbe 207 p = find_task_by_vpid(who);
22e2c507 208 if (p)
a1836a42 209 ret = get_task_ioprio(p);
22e2c507
JA
210 break;
211 case IOPRIO_WHO_PGRP:
212 if (!who)
41487c65
EB
213 pgrp = task_pgrp(current);
214 else
b488893a 215 pgrp = find_vpid(who);
2d70b68d 216 do_each_pid_thread(pgrp, PIDTYPE_PGID, p) {
a1836a42
DQ
217 tmpio = get_task_ioprio(p);
218 if (tmpio < 0)
219 continue;
22e2c507 220 if (ret == -ESRCH)
a1836a42 221 ret = tmpio;
22e2c507 222 else
a1836a42 223 ret = ioprio_best(ret, tmpio);
2d70b68d 224 } while_each_pid_thread(pgrp, PIDTYPE_PGID, p);
22e2c507
JA
225 break;
226 case IOPRIO_WHO_USER:
7b44ab97 227 uid = make_kuid(current_user_ns(), who);
22e2c507 228 if (!who)
86a264ab 229 user = current_user();
22e2c507 230 else
7b44ab97 231 user = find_user(uid);
22e2c507
JA
232
233 if (!user)
234 break;
235
612dafab 236 for_each_process_thread(g, p) {
8639b461
BS
237 if (!uid_eq(task_uid(p), user->uid) ||
238 !task_pid_vnr(p))
22e2c507 239 continue;
a1836a42
DQ
240 tmpio = get_task_ioprio(p);
241 if (tmpio < 0)
242 continue;
22e2c507 243 if (ret == -ESRCH)
a1836a42 244 ret = tmpio;
22e2c507 245 else
a1836a42 246 ret = ioprio_best(ret, tmpio);
612dafab 247 }
22e2c507
JA
248
249 if (who)
250 free_uid(user);
251 break;
252 default:
253 ret = -EINVAL;
254 }
255
d69b78ba 256 rcu_read_unlock();
22e2c507
JA
257 return ret;
258}