The Design and Implementation of the FreeBSD Operating System, Second Edition
Now available: The Design and Implementation of the FreeBSD Operating System (Second Edition)


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]

FreeBSD/Linux Kernel Cross Reference
sys/fs/ioprio.c

Version: -  FREEBSD  -  FREEBSD-13-STABLE  -  FREEBSD-13-0  -  FREEBSD-12-STABLE  -  FREEBSD-12-0  -  FREEBSD-11-STABLE  -  FREEBSD-11-0  -  FREEBSD-10-STABLE  -  FREEBSD-10-0  -  FREEBSD-9-STABLE  -  FREEBSD-9-0  -  FREEBSD-8-STABLE  -  FREEBSD-8-0  -  FREEBSD-7-STABLE  -  FREEBSD-7-0  -  FREEBSD-6-STABLE  -  FREEBSD-6-0  -  FREEBSD-5-STABLE  -  FREEBSD-5-0  -  FREEBSD-4-STABLE  -  FREEBSD-3-STABLE  -  FREEBSD22  -  l41  -  OPENBSD  -  linux-2.6  -  MK84  -  PLAN9  -  xnu-8792 
SearchContext: -  none  -  3  -  10 

    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 
   32 int 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 }
   59 EXPORT_SYMBOL_GPL(set_task_ioprio);
   60 
   61 SYSCALL_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);
  132 free_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 
  144 static 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;
  154 out:
  155         return ret;
  156 }
  157 
  158 int 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 
  176 SYSCALL_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 }

Cache object: b1b2e01c3c8dfb50daab036618c387db


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]


This page is part of the FreeBSD/Linux Linux Kernel Cross-Reference, and was automatically generated using a modified version of the LXR engine.