Linux Audio

Check our new training course

Loading...
Note: File does not exist in v4.6.
  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/export.h>
 25#include <linux/ioprio.h>
 26#include <linux/blkdev.h>
 27#include <linux/capability.h>
 28#include <linux/syscalls.h>
 29#include <linux/security.h>
 30#include <linux/pid_namespace.h>
 31
 32int set_task_ioprio(struct task_struct *task, int ioprio)
 33{
 34	int err;
 35	struct io_context *ioc;
 36	const struct cred *cred = current_cred(), *tcred;
 37
 38	rcu_read_lock();
 39	tcred = __task_cred(task);
 40	if (!uid_eq(tcred->uid, cred->euid) &&
 41	    !uid_eq(tcred->uid, cred->uid) && !capable(CAP_SYS_NICE)) {
 42		rcu_read_unlock();
 43		return -EPERM;
 44	}
 45	rcu_read_unlock();
 46
 47	err = security_task_setioprio(task, ioprio);
 48	if (err)
 49		return err;
 50
 51	ioc = get_task_io_context(task, GFP_ATOMIC, NUMA_NO_NODE);
 52	if (ioc) {
 53		ioc->ioprio = ioprio;
 54		put_io_context(ioc);
 55	}
 56
 57	return err;
 58}
 59EXPORT_SYMBOL_GPL(set_task_ioprio);
 60
 61SYSCALL_DEFINE3(ioprio_set, int, which, int, who, int, ioprio)
 62{
 63	int class = IOPRIO_PRIO_CLASS(ioprio);
 64	int data = IOPRIO_PRIO_DATA(ioprio);
 65	struct task_struct *p, *g;
 66	struct user_struct *user;
 67	struct pid *pgrp;
 68	kuid_t uid;
 69	int ret;
 70
 71	switch (class) {
 72		case IOPRIO_CLASS_RT:
 73			if (!capable(CAP_SYS_ADMIN))
 74				return -EPERM;
 75			/* fall through, rt has prio field too */
 76		case IOPRIO_CLASS_BE:
 77			if (data >= IOPRIO_BE_NR || data < 0)
 78				return -EINVAL;
 79
 80			break;
 81		case IOPRIO_CLASS_IDLE:
 82			break;
 83		case IOPRIO_CLASS_NONE:
 84			if (data)
 85				return -EINVAL;
 86			break;
 87		default:
 88			return -EINVAL;
 89	}
 90
 91	ret = -ESRCH;
 92	rcu_read_lock();
 93	switch (which) {
 94		case IOPRIO_WHO_PROCESS:
 95			if (!who)
 96				p = current;
 97			else
 98				p = find_task_by_vpid(who);
 99			if (p)
100				ret = set_task_ioprio(p, ioprio);
101			break;
102		case IOPRIO_WHO_PGRP:
103			if (!who)
104				pgrp = task_pgrp(current);
105			else
106				pgrp = find_vpid(who);
107			do_each_pid_thread(pgrp, PIDTYPE_PGID, p) {
108				ret = set_task_ioprio(p, ioprio);
109				if (ret)
110					break;
111			} while_each_pid_thread(pgrp, PIDTYPE_PGID, p);
112			break;
113		case IOPRIO_WHO_USER:
114			uid = make_kuid(current_user_ns(), who);
115			if (!uid_valid(uid))
116				break;
117			if (!who)
118				user = current_user();
119			else
120				user = find_user(uid);
121
122			if (!user)
123				break;
124
125			do_each_thread(g, p) {
126				if (!uid_eq(task_uid(p), uid))
127					continue;
128				ret = set_task_ioprio(p, ioprio);
129				if (ret)
130					goto free_uid;
131			} while_each_thread(g, p);
132free_uid:
133			if (who)
134				free_uid(user);
135			break;
136		default:
137			ret = -EINVAL;
138	}
139
140	rcu_read_unlock();
141	return ret;
142}
143
144static int get_task_ioprio(struct task_struct *p)
145{
146	int ret;
147
148	ret = security_task_getioprio(p);
149	if (ret)
150		goto out;
151	ret = IOPRIO_PRIO_VALUE(IOPRIO_CLASS_NONE, IOPRIO_NORM);
152	if (p->io_context)
153		ret = p->io_context->ioprio;
154out:
155	return ret;
156}
157
158int ioprio_best(unsigned short aprio, unsigned short bprio)
159{
160	unsigned short aclass = IOPRIO_PRIO_CLASS(aprio);
161	unsigned short bclass = IOPRIO_PRIO_CLASS(bprio);
162
163	if (aclass == IOPRIO_CLASS_NONE)
164		aclass = IOPRIO_CLASS_BE;
165	if (bclass == IOPRIO_CLASS_NONE)
166		bclass = IOPRIO_CLASS_BE;
167
168	if (aclass == bclass)
169		return min(aprio, bprio);
170	if (aclass > bclass)
171		return bprio;
172	else
173		return aprio;
174}
175
176SYSCALL_DEFINE2(ioprio_get, int, which, int, who)
177{
178	struct task_struct *g, *p;
179	struct user_struct *user;
180	struct pid *pgrp;
181	kuid_t uid;
182	int ret = -ESRCH;
183	int tmpio;
184
185	rcu_read_lock();
186	switch (which) {
187		case IOPRIO_WHO_PROCESS:
188			if (!who)
189				p = current;
190			else
191				p = find_task_by_vpid(who);
192			if (p)
193				ret = get_task_ioprio(p);
194			break;
195		case IOPRIO_WHO_PGRP:
196			if (!who)
197				pgrp = task_pgrp(current);
198			else
199				pgrp = find_vpid(who);
200			do_each_pid_thread(pgrp, PIDTYPE_PGID, p) {
201				tmpio = get_task_ioprio(p);
202				if (tmpio < 0)
203					continue;
204				if (ret == -ESRCH)
205					ret = tmpio;
206				else
207					ret = ioprio_best(ret, tmpio);
208			} while_each_pid_thread(pgrp, PIDTYPE_PGID, p);
209			break;
210		case IOPRIO_WHO_USER:
211			uid = make_kuid(current_user_ns(), who);
212			if (!who)
213				user = current_user();
214			else
215				user = find_user(uid);
216
217			if (!user)
218				break;
219
220			do_each_thread(g, p) {
221				if (!uid_eq(task_uid(p), user->uid))
222					continue;
223				tmpio = get_task_ioprio(p);
224				if (tmpio < 0)
225					continue;
226				if (ret == -ESRCH)
227					ret = tmpio;
228				else
229					ret = ioprio_best(ret, tmpio);
230			} while_each_thread(g, p);
231
232			if (who)
233				free_uid(user);
234			break;
235		default:
236			ret = -EINVAL;
237	}
238
239	rcu_read_unlock();
240	return ret;
241}