ioprio.c 5.0 KB

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