Pull release into acpica branch
[pandora-kernel.git] / fs / ioprio.c
1 /*
2  * fs/ioprio.c
3  *
4  * Copyright (C) 2004 Jens Axboe <axboe@suse.de>
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/kernel.h>
23 #include <linux/ioprio.h>
24 #include <linux/blkdev.h>
25 #include <linux/syscalls.h>
26
27 static int set_task_ioprio(struct task_struct *task, int ioprio)
28 {
29         struct io_context *ioc;
30
31         if (task->uid != current->euid &&
32             task->uid != current->uid && !capable(CAP_SYS_NICE))
33                 return -EPERM;
34
35         task_lock(task);
36
37         task->ioprio = ioprio;
38
39         ioc = task->io_context;
40         if (ioc && ioc->set_ioprio)
41                 ioc->set_ioprio(ioc, ioprio);
42
43         task_unlock(task);
44         return 0;
45 }
46
47 asmlinkage long sys_ioprio_set(int which, int who, int ioprio)
48 {
49         int class = IOPRIO_PRIO_CLASS(ioprio);
50         int data = IOPRIO_PRIO_DATA(ioprio);
51         struct task_struct *p, *g;
52         struct user_struct *user;
53         int ret;
54
55         switch (class) {
56                 case IOPRIO_CLASS_RT:
57                         if (!capable(CAP_SYS_ADMIN))
58                                 return -EPERM;
59                         /* fall through, rt has prio field too */
60                 case IOPRIO_CLASS_BE:
61                         if (data >= IOPRIO_BE_NR || data < 0)
62                                 return -EINVAL;
63
64                         break;
65                 case IOPRIO_CLASS_IDLE:
66                         if (!capable(CAP_SYS_ADMIN))
67                                 return -EPERM;
68                         break;
69                 default:
70                         return -EINVAL;
71         }
72
73         ret = -ESRCH;
74         read_lock_irq(&tasklist_lock);
75         switch (which) {
76                 case IOPRIO_WHO_PROCESS:
77                         if (!who)
78                                 p = current;
79                         else
80                                 p = find_task_by_pid(who);
81                         if (p)
82                                 ret = set_task_ioprio(p, ioprio);
83                         break;
84                 case IOPRIO_WHO_PGRP:
85                         if (!who)
86                                 who = process_group(current);
87                         do_each_task_pid(who, PIDTYPE_PGID, p) {
88                                 ret = set_task_ioprio(p, ioprio);
89                                 if (ret)
90                                         break;
91                         } while_each_task_pid(who, PIDTYPE_PGID, p);
92                         break;
93                 case IOPRIO_WHO_USER:
94                         if (!who)
95                                 user = current->user;
96                         else
97                                 user = find_user(who);
98
99                         if (!user)
100                                 break;
101
102                         do_each_thread(g, p) {
103                                 if (p->uid != who)
104                                         continue;
105                                 ret = set_task_ioprio(p, ioprio);
106                                 if (ret)
107                                         break;
108                         } while_each_thread(g, p);
109
110                         if (who)
111                                 free_uid(user);
112                         break;
113                 default:
114                         ret = -EINVAL;
115         }
116
117         read_unlock_irq(&tasklist_lock);
118         return ret;
119 }
120
121 asmlinkage long sys_ioprio_get(int which, int who)
122 {
123         struct task_struct *g, *p;
124         struct user_struct *user;
125         int ret = -ESRCH;
126
127         read_lock_irq(&tasklist_lock);
128         switch (which) {
129                 case IOPRIO_WHO_PROCESS:
130                         if (!who)
131                                 p = current;
132                         else
133                                 p = find_task_by_pid(who);
134                         if (p)
135                                 ret = p->ioprio;
136                         break;
137                 case IOPRIO_WHO_PGRP:
138                         if (!who)
139                                 who = process_group(current);
140                         do_each_task_pid(who, PIDTYPE_PGID, p) {
141                                 if (ret == -ESRCH)
142                                         ret = p->ioprio;
143                                 else
144                                         ret = ioprio_best(ret, p->ioprio);
145                         } while_each_task_pid(who, PIDTYPE_PGID, p);
146                         break;
147                 case IOPRIO_WHO_USER:
148                         if (!who)
149                                 user = current->user;
150                         else
151                                 user = find_user(who);
152
153                         if (!user)
154                                 break;
155
156                         do_each_thread(g, p) {
157                                 if (p->uid != user->uid)
158                                         continue;
159                                 if (ret == -ESRCH)
160                                         ret = p->ioprio;
161                                 else
162                                         ret = ioprio_best(ret, p->ioprio);
163                         } while_each_thread(g, p);
164
165                         if (who)
166                                 free_uid(user);
167                         break;
168                 default:
169                         ret = -EINVAL;
170         }
171
172         read_unlock_irq(&tasklist_lock);
173         return ret;
174 }
175