* See also Documentation/block/ioprio.txt
*
*/
+#include <linux/gfp.h>
#include <linux/kernel.h>
+#include <linux/export.h>
#include <linux/ioprio.h>
#include <linux/blkdev.h>
#include <linux/capability.h>
#include <linux/security.h>
#include <linux/pid_namespace.h>
-static int set_task_ioprio(struct task_struct *task, int ioprio)
+int set_task_ioprio(struct task_struct *task, int ioprio)
{
int err;
struct io_context *ioc;
+ const struct cred *cred = current_cred(), *tcred;
- if (task->uid != current->euid &&
- task->uid != current->uid && !capable(CAP_SYS_NICE))
+ rcu_read_lock();
+ tcred = __task_cred(task);
+ if (tcred->uid != cred->euid &&
+ tcred->uid != cred->uid && !capable(CAP_SYS_NICE)) {
+ rcu_read_unlock();
return -EPERM;
+ }
+ rcu_read_unlock();
err = security_task_setioprio(task, ioprio);
if (err)
return err;
- task_lock(task);
- do {
- ioc = task->io_context;
- /* see wmb() in current_io_context() */
- smp_read_barrier_depends();
- if (ioc)
- break;
-
- ioc = alloc_io_context(GFP_ATOMIC, -1);
- if (!ioc) {
- err = -ENOMEM;
- break;
- }
- task->io_context = ioc;
- } while (1);
-
- if (!err) {
- ioc->ioprio = ioprio;
- ioc->ioprio_changed = 1;
+ ioc = get_task_io_context(task, GFP_ATOMIC, NUMA_NO_NODE);
+ if (ioc) {
+ ioc_ioprio_changed(ioc, ioprio);
+ put_io_context(ioc);
}
- task_unlock(task);
return err;
}
+EXPORT_SYMBOL_GPL(set_task_ioprio);
SYSCALL_DEFINE3(ioprio_set, int, which, int, who, int, ioprio)
{
}
ret = -ESRCH;
- /*
- * We want IOPRIO_WHO_PGRP/IOPRIO_WHO_USER to be "atomic",
- * so we can't use rcu_read_lock(). See re-copy of ->ioprio
- * in copy_process().
- */
- read_lock(&tasklist_lock);
+ rcu_read_lock();
switch (which) {
case IOPRIO_WHO_PROCESS:
if (!who)
break;
case IOPRIO_WHO_USER:
if (!who)
- user = current->user;
+ user = current_user();
else
user = find_user(who);
break;
do_each_thread(g, p) {
- if (p->uid != who)
+ if (__task_cred(p)->uid != who)
continue;
ret = set_task_ioprio(p, ioprio);
if (ret)
ret = -EINVAL;
}
- read_unlock(&tasklist_lock);
+ rcu_read_unlock();
return ret;
}
int ret = -ESRCH;
int tmpio;
- read_lock(&tasklist_lock);
+ rcu_read_lock();
switch (which) {
case IOPRIO_WHO_PROCESS:
if (!who)
break;
case IOPRIO_WHO_USER:
if (!who)
- user = current->user;
+ user = current_user();
else
user = find_user(who);
break;
do_each_thread(g, p) {
- if (p->uid != user->uid)
+ if (__task_cred(p)->uid != user->uid)
continue;
tmpio = get_task_ioprio(p);
if (tmpio < 0)
ret = -EINVAL;
}
- read_unlock(&tasklist_lock);
+ rcu_read_unlock();
return ret;
}