root/block/ioprio.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. set_task_ioprio
  2. ioprio_check_cap
  3. SYSCALL_DEFINE3
  4. get_task_ioprio
  5. ioprio_best
  6. SYSCALL_DEFINE2

   1 // SPDX-License-Identifier: GPL-2.0
   2 /*
   3  * fs/ioprio.c
   4  *
   5  * Copyright (C) 2004 Jens Axboe <axboe@kernel.dk>
   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  *
  20  * See also Documentation/block/ioprio.rst
  21  *
  22  */
  23 #include <linux/gfp.h>
  24 #include <linux/kernel.h>
  25 #include <linux/export.h>
  26 #include <linux/ioprio.h>
  27 #include <linux/cred.h>
  28 #include <linux/blkdev.h>
  29 #include <linux/capability.h>
  30 #include <linux/sched/user.h>
  31 #include <linux/sched/task.h>
  32 #include <linux/syscalls.h>
  33 #include <linux/security.h>
  34 #include <linux/pid_namespace.h>
  35 
  36 int set_task_ioprio(struct task_struct *task, int ioprio)
  37 {
  38         int err;
  39         struct io_context *ioc;
  40         const struct cred *cred = current_cred(), *tcred;
  41 
  42         rcu_read_lock();
  43         tcred = __task_cred(task);
  44         if (!uid_eq(tcred->uid, cred->euid) &&
  45             !uid_eq(tcred->uid, cred->uid) && !capable(CAP_SYS_NICE)) {
  46                 rcu_read_unlock();
  47                 return -EPERM;
  48         }
  49         rcu_read_unlock();
  50 
  51         err = security_task_setioprio(task, ioprio);
  52         if (err)
  53                 return err;
  54 
  55         ioc = get_task_io_context(task, GFP_ATOMIC, NUMA_NO_NODE);
  56         if (ioc) {
  57                 ioc->ioprio = ioprio;
  58                 put_io_context(ioc);
  59         }
  60 
  61         return err;
  62 }
  63 EXPORT_SYMBOL_GPL(set_task_ioprio);
  64 
  65 int ioprio_check_cap(int ioprio)
  66 {
  67         int class = IOPRIO_PRIO_CLASS(ioprio);
  68         int data = IOPRIO_PRIO_DATA(ioprio);
  69 
  70         switch (class) {
  71                 case IOPRIO_CLASS_RT:
  72                         if (!capable(CAP_SYS_ADMIN))
  73                                 return -EPERM;
  74                         /* fall through */
  75                         /* 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         return 0;
  92 }
  93 
  94 SYSCALL_DEFINE3(ioprio_set, int, which, int, who, int, ioprio)
  95 {
  96         struct task_struct *p, *g;
  97         struct user_struct *user;
  98         struct pid *pgrp;
  99         kuid_t uid;
 100         int ret;
 101 
 102         ret = ioprio_check_cap(ioprio);
 103         if (ret)
 104                 return ret;
 105 
 106         ret = -ESRCH;
 107         rcu_read_lock();
 108         switch (which) {
 109                 case IOPRIO_WHO_PROCESS:
 110                         if (!who)
 111                                 p = current;
 112                         else
 113                                 p = find_task_by_vpid(who);
 114                         if (p)
 115                                 ret = set_task_ioprio(p, ioprio);
 116                         break;
 117                 case IOPRIO_WHO_PGRP:
 118                         if (!who)
 119                                 pgrp = task_pgrp(current);
 120                         else
 121                                 pgrp = find_vpid(who);
 122                         do_each_pid_thread(pgrp, PIDTYPE_PGID, p) {
 123                                 ret = set_task_ioprio(p, ioprio);
 124                                 if (ret)
 125                                         break;
 126                         } while_each_pid_thread(pgrp, PIDTYPE_PGID, p);
 127                         break;
 128                 case IOPRIO_WHO_USER:
 129                         uid = make_kuid(current_user_ns(), who);
 130                         if (!uid_valid(uid))
 131                                 break;
 132                         if (!who)
 133                                 user = current_user();
 134                         else
 135                                 user = find_user(uid);
 136 
 137                         if (!user)
 138                                 break;
 139 
 140                         for_each_process_thread(g, p) {
 141                                 if (!uid_eq(task_uid(p), uid) ||
 142                                     !task_pid_vnr(p))
 143                                         continue;
 144                                 ret = set_task_ioprio(p, ioprio);
 145                                 if (ret)
 146                                         goto free_uid;
 147                         }
 148 free_uid:
 149                         if (who)
 150                                 free_uid(user);
 151                         break;
 152                 default:
 153                         ret = -EINVAL;
 154         }
 155 
 156         rcu_read_unlock();
 157         return ret;
 158 }
 159 
 160 static int get_task_ioprio(struct task_struct *p)
 161 {
 162         int ret;
 163 
 164         ret = security_task_getioprio(p);
 165         if (ret)
 166                 goto out;
 167         ret = IOPRIO_PRIO_VALUE(IOPRIO_CLASS_NONE, IOPRIO_NORM);
 168         task_lock(p);
 169         if (p->io_context)
 170                 ret = p->io_context->ioprio;
 171         task_unlock(p);
 172 out:
 173         return ret;
 174 }
 175 
 176 int ioprio_best(unsigned short aprio, unsigned short bprio)
 177 {
 178         if (!ioprio_valid(aprio))
 179                 aprio = IOPRIO_PRIO_VALUE(IOPRIO_CLASS_BE, IOPRIO_NORM);
 180         if (!ioprio_valid(bprio))
 181                 bprio = IOPRIO_PRIO_VALUE(IOPRIO_CLASS_BE, IOPRIO_NORM);
 182 
 183         return min(aprio, bprio);
 184 }
 185 
 186 SYSCALL_DEFINE2(ioprio_get, int, which, int, who)
 187 {
 188         struct task_struct *g, *p;
 189         struct user_struct *user;
 190         struct pid *pgrp;
 191         kuid_t uid;
 192         int ret = -ESRCH;
 193         int tmpio;
 194 
 195         rcu_read_lock();
 196         switch (which) {
 197                 case IOPRIO_WHO_PROCESS:
 198                         if (!who)
 199                                 p = current;
 200                         else
 201                                 p = find_task_by_vpid(who);
 202                         if (p)
 203                                 ret = get_task_ioprio(p);
 204                         break;
 205                 case IOPRIO_WHO_PGRP:
 206                         if (!who)
 207                                 pgrp = task_pgrp(current);
 208                         else
 209                                 pgrp = find_vpid(who);
 210                         do_each_pid_thread(pgrp, PIDTYPE_PGID, p) {
 211                                 tmpio = get_task_ioprio(p);
 212                                 if (tmpio < 0)
 213                                         continue;
 214                                 if (ret == -ESRCH)
 215                                         ret = tmpio;
 216                                 else
 217                                         ret = ioprio_best(ret, tmpio);
 218                         } while_each_pid_thread(pgrp, PIDTYPE_PGID, p);
 219                         break;
 220                 case IOPRIO_WHO_USER:
 221                         uid = make_kuid(current_user_ns(), who);
 222                         if (!who)
 223                                 user = current_user();
 224                         else
 225                                 user = find_user(uid);
 226 
 227                         if (!user)
 228                                 break;
 229 
 230                         for_each_process_thread(g, p) {
 231                                 if (!uid_eq(task_uid(p), user->uid) ||
 232                                     !task_pid_vnr(p))
 233                                         continue;
 234                                 tmpio = get_task_ioprio(p);
 235                                 if (tmpio < 0)
 236                                         continue;
 237                                 if (ret == -ESRCH)
 238                                         ret = tmpio;
 239                                 else
 240                                         ret = ioprio_best(ret, tmpio);
 241                         }
 242 
 243                         if (who)
 244                                 free_uid(user);
 245                         break;
 246                 default:
 247                         ret = -EINVAL;
 248         }
 249 
 250         rcu_read_unlock();
 251         return ret;
 252 }

/* [<][>][^][v][top][bottom][index][help] */