LCOV - code coverage report
Current view: top level - fs - ioprio.c (source / functions) Hit Total Coverage
Test: coverage.info Lines: 16 96 16.7 %
Date: 2014-02-18 Functions: 2 5 40.0 %
Branches: 7 113 6.2 %

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

Generated by: LCOV version 1.9