upgrade to linux 2.6.10-1.12_FC2
[linux-2.6.git] / fs / quota.c
1 /*
2  * Quota code necessary even when VFS quota support is not compiled
3  * into the kernel.  The interesting stuff is over in dquot.c, here
4  * we have symbols for initial quotactl(2) handling, the sysctl(2)
5  * variables, etc - things needed even when quota support disabled.
6  */
7
8 #include <linux/fs.h>
9 #include <linux/namei.h>
10 #include <linux/slab.h>
11 #include <asm/current.h>
12 #include <asm/uaccess.h>
13 #include <linux/kernel.h>
14 #include <linux/smp_lock.h>
15 #include <linux/security.h>
16 #include <linux/syscalls.h>
17
18 /* Check validity of quotactl */
19 static int check_quotactl_valid(struct super_block *sb, int type, int cmd, qid_t id)
20 {
21         if (type >= MAXQUOTAS)
22                 return -EINVAL;
23         if (!sb && cmd != Q_SYNC)
24                 return -ENODEV;
25         /* Is operation supported? */
26         if (sb && !sb->s_qcop)
27                 return -ENOSYS;
28
29         switch (cmd) {
30                 case Q_GETFMT:
31                         break;
32                 case Q_QUOTAON:
33                         if (!sb->s_qcop->quota_on)
34                                 return -ENOSYS;
35                         break;
36                 case Q_QUOTAOFF:
37                         if (!sb->s_qcop->quota_off)
38                                 return -ENOSYS;
39                         break;
40                 case Q_SETINFO:
41                         if (!sb->s_qcop->set_info)
42                                 return -ENOSYS;
43                         break;
44                 case Q_GETINFO:
45                         if (!sb->s_qcop->get_info)
46                                 return -ENOSYS;
47                         break;
48                 case Q_SETQUOTA:
49                         if (!sb->s_qcop->set_dqblk)
50                                 return -ENOSYS;
51                         break;
52                 case Q_GETQUOTA:
53                         if (!sb->s_qcop->get_dqblk)
54                                 return -ENOSYS;
55                         break;
56                 case Q_SYNC:
57                         if (sb && !sb->s_qcop->quota_sync)
58                                 return -ENOSYS;
59                         break;
60                 case Q_XQUOTAON:
61                 case Q_XQUOTAOFF:
62                 case Q_XQUOTARM:
63                         if (!sb->s_qcop->set_xstate)
64                                 return -ENOSYS;
65                         break;
66                 case Q_XGETQSTAT:
67                         if (!sb->s_qcop->get_xstate)
68                                 return -ENOSYS;
69                         break;
70                 case Q_XSETQLIM:
71                         if (!sb->s_qcop->set_xquota)
72                                 return -ENOSYS;
73                         break;
74                 case Q_XGETQUOTA:
75                         if (!sb->s_qcop->get_xquota)
76                                 return -ENOSYS;
77                         break;
78                 default:
79                         return -EINVAL;
80         }
81
82         /* Is quota turned on for commands which need it? */
83         switch (cmd) {
84                 case Q_GETFMT:
85                 case Q_GETINFO:
86                 case Q_QUOTAOFF:
87                 case Q_SETINFO:
88                 case Q_SETQUOTA:
89                 case Q_GETQUOTA:
90                         /* This is just informative test so we are satisfied without a lock */
91                         if (!sb_has_quota_enabled(sb, type))
92                                 return -ESRCH;
93         }
94         /* Check privileges */
95         if (cmd == Q_GETQUOTA || cmd == Q_XGETQUOTA) {
96                 if (((type == USRQUOTA && current->euid != id) ||
97                      (type == GRPQUOTA && !in_egroup_p(id))) &&
98                     !capable(CAP_SYS_ADMIN))
99                         return -EPERM;
100         }
101         else if (cmd != Q_GETFMT && cmd != Q_SYNC && cmd != Q_GETINFO && cmd != Q_XGETQSTAT)
102                 if (!capable(CAP_SYS_ADMIN))
103                         return -EPERM;
104
105         return security_quotactl (cmd, type, id, sb);
106 }
107
108 static struct super_block *get_super_to_sync(int type)
109 {
110         struct list_head *head;
111         int cnt, dirty;
112
113 restart:
114         spin_lock(&sb_lock);
115         list_for_each(head, &super_blocks) {
116                 struct super_block *sb = list_entry(head, struct super_block, s_list);
117
118                 /* This test just improves performance so it needn't be reliable... */
119                 for (cnt = 0, dirty = 0; cnt < MAXQUOTAS; cnt++)
120                         if ((type == cnt || type == -1) && sb_has_quota_enabled(sb, cnt)
121                             && info_any_dirty(&sb_dqopt(sb)->info[cnt]))
122                                 dirty = 1;
123                 if (!dirty)
124                         continue;
125                 sb->s_count++;
126                 spin_unlock(&sb_lock);
127                 down_read(&sb->s_umount);
128                 if (!sb->s_root) {
129                         drop_super(sb);
130                         goto restart;
131                 }
132                 return sb;
133         }
134         spin_unlock(&sb_lock);
135         return NULL;
136 }
137
138 void sync_dquots(struct super_block *sb, int type)
139 {
140         if (sb) {
141                 if (sb->s_qcop->quota_sync)
142                         sb->s_qcop->quota_sync(sb, type);
143         }
144         else {
145                 while ((sb = get_super_to_sync(type)) != 0) {
146                         if (sb->s_qcop->quota_sync)
147                                 sb->s_qcop->quota_sync(sb, type);
148                         drop_super(sb);
149                 }
150         }
151 }
152
153 /* Copy parameters and call proper function */
154 static int do_quotactl(struct super_block *sb, int type, int cmd, qid_t id, void __user *addr)
155 {
156         int ret;
157
158         switch (cmd) {
159                 case Q_QUOTAON: {
160                         char *pathname;
161
162                         if (IS_ERR(pathname = getname(addr)))
163                                 return PTR_ERR(pathname);
164                         ret = sb->s_qcop->quota_on(sb, type, id, pathname);
165                         putname(pathname);
166                         return ret;
167                 }
168                 case Q_QUOTAOFF:
169                         return sb->s_qcop->quota_off(sb, type);
170
171                 case Q_GETFMT: {
172                         __u32 fmt;
173
174                         down_read(&sb_dqopt(sb)->dqptr_sem);
175                         if (!sb_has_quota_enabled(sb, type)) {
176                                 up_read(&sb_dqopt(sb)->dqptr_sem);
177                                 return -ESRCH;
178                         }
179                         fmt = sb_dqopt(sb)->info[type].dqi_format->qf_fmt_id;
180                         up_read(&sb_dqopt(sb)->dqptr_sem);
181                         if (copy_to_user(addr, &fmt, sizeof(fmt)))
182                                 return -EFAULT;
183                         return 0;
184                 }
185                 case Q_GETINFO: {
186                         struct if_dqinfo info;
187
188                         if ((ret = sb->s_qcop->get_info(sb, type, &info)))
189                                 return ret;
190                         if (copy_to_user(addr, &info, sizeof(info)))
191                                 return -EFAULT;
192                         return 0;
193                 }
194                 case Q_SETINFO: {
195                         struct if_dqinfo info;
196
197                         if (copy_from_user(&info, addr, sizeof(info)))
198                                 return -EFAULT;
199                         return sb->s_qcop->set_info(sb, type, &info);
200                 }
201                 case Q_GETQUOTA: {
202                         struct if_dqblk idq;
203
204                         if ((ret = sb->s_qcop->get_dqblk(sb, type, id, &idq)))
205                                 return ret;
206                         if (copy_to_user(addr, &idq, sizeof(idq)))
207                                 return -EFAULT;
208                         return 0;
209                 }
210                 case Q_SETQUOTA: {
211                         struct if_dqblk idq;
212
213                         if (copy_from_user(&idq, addr, sizeof(idq)))
214                                 return -EFAULT;
215                         return sb->s_qcop->set_dqblk(sb, type, id, &idq);
216                 }
217                 case Q_SYNC:
218                         sync_dquots(sb, type);
219                         return 0;
220
221                 case Q_XQUOTAON:
222                 case Q_XQUOTAOFF:
223                 case Q_XQUOTARM: {
224                         __u32 flags;
225
226                         if (copy_from_user(&flags, addr, sizeof(flags)))
227                                 return -EFAULT;
228                         return sb->s_qcop->set_xstate(sb, flags, cmd);
229                 }
230                 case Q_XGETQSTAT: {
231                         struct fs_quota_stat fqs;
232                 
233                         if ((ret = sb->s_qcop->get_xstate(sb, &fqs)))
234                                 return ret;
235                         if (copy_to_user(addr, &fqs, sizeof(fqs)))
236                                 return -EFAULT;
237                         return 0;
238                 }
239                 case Q_XSETQLIM: {
240                         struct fs_disk_quota fdq;
241
242                         if (copy_from_user(&fdq, addr, sizeof(fdq)))
243                                 return -EFAULT;
244                        return sb->s_qcop->set_xquota(sb, type, id, &fdq);
245                 }
246                 case Q_XGETQUOTA: {
247                         struct fs_disk_quota fdq;
248
249                         if ((ret = sb->s_qcop->get_xquota(sb, type, id, &fdq)))
250                                 return ret;
251                         if (copy_to_user(addr, &fdq, sizeof(fdq)))
252                                 return -EFAULT;
253                         return 0;
254                 }
255                 /* We never reach here unless validity check is broken */
256                 default:
257                         BUG();
258         }
259         return 0;
260 }
261
262 /*
263  * This is the system call interface. This communicates with
264  * the user-level programs. Currently this only supports diskquota
265  * calls. Maybe we need to add the process quotas etc. in the future,
266  * but we probably should use rlimits for that.
267  */
268 asmlinkage long sys_quotactl(unsigned int cmd, const char __user *special, qid_t id, void __user *addr)
269 {
270         uint cmds, type;
271         struct super_block *sb = NULL;
272         struct block_device *bdev;
273         char *tmp;
274         int ret;
275
276         cmds = cmd >> SUBCMDSHIFT;
277         type = cmd & SUBCMDMASK;
278
279         if (cmds != Q_SYNC || special) {
280                 tmp = getname(special);
281                 if (IS_ERR(tmp))
282                         return PTR_ERR(tmp);
283                 bdev = lookup_bdev(tmp);
284                 putname(tmp);
285                 if (IS_ERR(bdev))
286                         return PTR_ERR(bdev);
287                 sb = get_super(bdev);
288                 bdput(bdev);
289                 if (!sb)
290                         return -ENODEV;
291         }
292
293         ret = check_quotactl_valid(sb, type, cmds, id);
294         if (ret >= 0)
295                 ret = do_quotactl(sb, type, cmds, id, addr);
296         if (sb)
297                 drop_super(sb);
298
299         return ret;
300 }