This source file includes following definitions.
- hashfn
- hash
- has_quota_enabled
- insert_dquot_free
- remove_dquot_free
- insert_dquot_hash
- remove_dquot_hash
- put_last_free
- grow_dquots
- __wait_on_dquot
- wait_on_dquot
- lock_dquot
- unlock_dquot
- clear_dquot
- write_dquot
- read_dquot
- sync_dquots
- invalidate_dquots
- dquot_incr_inodes
- dquot_incr_blocks
- dquot_decr_inodes
- dquot_decr_blocks
- need_print_warning
- check_idq
- check_bdq
- dqput
- get_empty_dquot
- dqget
- set_dqblk
- get_quota
- get_stats
- dquot_initialize
- dquot_drop
- isize_to_blocks
- dquot_alloc_block
- dquot_alloc_inode
- dquot_free_block
- dquot_free_inode
- dquot_transfer
- dquot_init
- quota_off
- quota_on
- sys_quotactl
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24 #include <linux/errno.h>
25 #include <linux/kernel.h>
26 #include <linux/sched.h>
27 #include <linux/types.h>
28 #include <linux/string.h>
29 #include <linux/fcntl.h>
30 #include <linux/stat.h>
31 #include <linux/tty.h>
32 #include <linux/malloc.h>
33 #include <linux/mount.h>
34
35 #include <asm/segment.h>
36 #include <sys/sysmacros.h>
37
38 #define __DQUOT_VERSION__ "dquot_5.6.0"
39
40 static char quotamessage[MAX_QUOTA_MESSAGE];
41 static char *quotatypes[] = INITQFNAMES;
42
43 static int nr_dquots = 0, nr_free_dquots = 0;
44 static struct dquot *hash_table[NR_DQHASH];
45 static struct dquot *first_dquot;
46 static struct dqstats dqstats;
47
48 static struct wait_queue *dquot_wait = (struct wait_queue *)NULL;
49
50 extern void add_dquot_ref(kdev_t dev, short type);
51 extern void reset_dquot_ptrs(kdev_t dev, short type);
52
53 #ifndef min
54 #define min(a,b) ((a) < (b)) ? (a) : (b)
55 #endif
56
57
58
59
60 static inline int const hashfn(kdev_t dev, unsigned int id, short type)
61 {
62 return((HASHDEV(dev) ^ id) * (MAXQUOTAS - type)) % NR_DQHASH;
63 }
64
65 static inline struct dquot **const hash(kdev_t dev, unsigned int id, short type)
66 {
67 return(hash_table + hashfn(dev, id, type));
68 }
69
70 static inline int has_quota_enabled(kdev_t dev, short type)
71 {
72 struct vfsmount *vfsmnt;
73
74 return((vfsmnt = lookup_vfsmnt(dev)) != (struct vfsmount *)NULL &&
75 (vfsmnt->mnt_quotas[type] != (struct file *)NULL));
76 }
77
78 static void insert_dquot_free(struct dquot *dquot)
79 {
80 dquot->dq_next = first_dquot;
81 dquot->dq_prev = first_dquot->dq_prev;
82 dquot->dq_next->dq_prev = dquot;
83 dquot->dq_prev->dq_next = dquot;
84 first_dquot = dquot;
85 }
86
87 static void remove_dquot_free(struct dquot *dquot)
88 {
89 if (first_dquot == dquot)
90 first_dquot = first_dquot->dq_next;
91 if (dquot->dq_next)
92 dquot->dq_next->dq_prev = dquot->dq_prev;
93 if (dquot->dq_prev)
94 dquot->dq_prev->dq_next = dquot->dq_next;
95 dquot->dq_next = dquot->dq_prev = NODQUOT;
96 }
97
98 static void insert_dquot_hash(struct dquot *dquot)
99 {
100 struct dquot **hash_ent;
101
102 hash_ent = hash(dquot->dq_dev, dquot->dq_id, dquot->dq_type);
103 dquot->dq_hash_next = *hash_ent;
104 dquot->dq_hash_prev = NODQUOT;
105 if (dquot->dq_hash_next)
106 dquot->dq_hash_next->dq_hash_prev = dquot;
107 *hash_ent = dquot;
108 }
109
110 static void remove_dquot_hash(struct dquot *dquot)
111 {
112 struct dquot **hash_ent;
113
114 hash_ent = hash(dquot->dq_dev, dquot->dq_id, dquot->dq_type);
115 if (*hash_ent == dquot)
116 *hash_ent = dquot->dq_hash_next;
117 if (dquot->dq_hash_next)
118 dquot->dq_hash_next->dq_hash_prev = dquot->dq_hash_prev;
119 if (dquot->dq_hash_prev)
120 dquot->dq_hash_prev->dq_hash_next = dquot->dq_hash_next;
121 dquot->dq_hash_prev = dquot->dq_hash_next = NODQUOT;
122 }
123
124 static void put_last_free(struct dquot *dquot)
125 {
126 remove_dquot_free(dquot);
127 dquot->dq_prev = first_dquot->dq_prev;
128 dquot->dq_prev->dq_next = dquot;
129 dquot->dq_next = first_dquot;
130 dquot->dq_next->dq_prev = dquot;
131 }
132
133 static void grow_dquots(void)
134 {
135 struct dquot *dquot;
136 int cnt;
137
138 if (!(dquot = (struct dquot*) get_free_page(GFP_KERNEL)))
139 return;
140 dqstats.pages_allocated++;
141 cnt = PAGE_SIZE / sizeof(struct dquot);
142 nr_dquots += cnt;
143 nr_free_dquots += cnt;
144 if (!first_dquot) {
145 dquot->dq_next = dquot->dq_prev = first_dquot = dquot++;
146 cnt--;
147 }
148 for (; cnt; cnt--)
149 insert_dquot_free(dquot++);
150 }
151
152
153
154
155 static void __wait_on_dquot(struct dquot *dquot)
156 {
157 struct wait_queue wait = {current, NULL};
158
159 add_wait_queue(&dquot->dq_wait, &wait);
160 repeat:
161 current->state = TASK_UNINTERRUPTIBLE;
162 if (dquot->dq_flags & DQ_LOCKED) {
163 dquot->dq_flags |= DQ_WANT;
164 schedule();
165 goto repeat;
166 }
167 remove_wait_queue(&dquot->dq_wait, &wait);
168 current->state = TASK_RUNNING;
169 }
170
171 static inline void wait_on_dquot(struct dquot *dquot)
172 {
173 if (dquot->dq_flags & DQ_LOCKED)
174 __wait_on_dquot(dquot);
175 }
176
177 static inline void lock_dquot(struct dquot *dquot)
178 {
179 wait_on_dquot(dquot);
180 dquot->dq_flags |= DQ_LOCKED;
181 }
182
183 static inline void unlock_dquot(struct dquot *dquot)
184 {
185 dquot->dq_flags &= ~DQ_LOCKED;
186 if (dquot->dq_flags & DQ_WANT) {
187 dquot->dq_flags &= ~DQ_WANT;
188 wake_up(&dquot->dq_wait);
189 }
190 }
191
192
193
194
195
196
197
198 static void clear_dquot(struct dquot * dquot)
199 {
200 struct wait_queue *wait;
201
202 wait_on_dquot(dquot);
203 remove_dquot_hash(dquot);
204 remove_dquot_free(dquot);
205 wait = ((volatile struct dquot *) dquot)->dq_wait;
206 if (dquot->dq_count)
207 nr_free_dquots++;
208 memset(dquot, 0, sizeof(*dquot));
209 ((volatile struct dquot *) dquot)->dq_wait = wait;
210 insert_dquot_free(dquot);
211 }
212
213 static void write_dquot(struct dquot *dquot)
214 {
215 short type = dquot->dq_type;
216 struct file *filp = dquot->dq_mnt->mnt_quotas[type];
217 unsigned short fs;
218
219 if (!(dquot->dq_flags & DQ_MOD) || (filp == (struct file *)NULL))
220 return;
221 lock_dquot(dquot);
222 down(&dquot->dq_mnt->mnt_sem);
223 if (filp->f_op->lseek) {
224 if (filp->f_op->lseek(filp->f_inode, filp,
225 dqoff(dquot->dq_id), 0) != dqoff(dquot->dq_id)) {
226 up(&dquot->dq_mnt->mnt_sem);
227 unlock_dquot(dquot);
228 return;
229 }
230 } else
231 filp->f_pos = dqoff(dquot->dq_id);
232 fs = get_fs();
233 set_fs(KERNEL_DS);
234 if (filp->f_op->write(filp->f_inode, filp,
235 (char *)&dquot->dq_dqb, sizeof(struct dqblk)) == sizeof(struct dqblk))
236 dquot->dq_flags &= ~DQ_MOD;
237 up(&dquot->dq_mnt->mnt_sem);
238 set_fs(fs);
239 unlock_dquot(dquot);
240 dqstats.writes++;
241 }
242
243 static void read_dquot(struct dquot *dquot)
244 {
245 short type = dquot->dq_type;
246 struct file *filp = dquot->dq_mnt->mnt_quotas[type];
247 unsigned short fs;
248
249 if (filp == (struct file *)NULL)
250 return;
251 lock_dquot(dquot);
252 down(&dquot->dq_mnt->mnt_sem);
253 if (filp->f_op->lseek) {
254 if (filp->f_op->lseek(filp->f_inode, filp,
255 dqoff(dquot->dq_id), 0) != dqoff(dquot->dq_id)) {
256 up(&dquot->dq_mnt->mnt_sem);
257 unlock_dquot(dquot);
258 return;
259 }
260 } else
261 filp->f_pos = dqoff(dquot->dq_id);
262 fs = get_fs();
263 set_fs(KERNEL_DS);
264 filp->f_op->read(filp->f_inode, filp, (char *)&dquot->dq_dqb, sizeof(struct dqblk));
265 up(&dquot->dq_mnt->mnt_sem);
266 set_fs(fs);
267 if (dquot->dq_bhardlimit == 0 && dquot->dq_bsoftlimit == 0 &&
268 dquot->dq_ihardlimit == 0 && dquot->dq_isoftlimit == 0)
269 dquot->dq_flags |= DQ_FAKE;
270 unlock_dquot(dquot);
271 dqstats.reads++;
272 }
273
274 int sync_dquots(kdev_t dev, short type)
275 {
276 struct dquot *dquot = first_dquot;
277 int i;
278
279 dqstats.syncs++;
280 for (i = 0; i < nr_dquots * 2; i++, dquot = dquot->dq_next) {
281 if (dev == NODEV || dquot->dq_count == 0 || dquot->dq_dev != dev)
282 continue;
283 if (type != -1 && dquot->dq_type != type)
284 continue;
285 wait_on_dquot(dquot);
286 if (dquot->dq_flags & DQ_MOD)
287 write_dquot(dquot);
288 }
289 return(0);
290 }
291
292
293
294
295 void invalidate_dquots(kdev_t dev, short type)
296 {
297 struct dquot *dquot, *next;
298 int cnt;
299
300 next = first_dquot;
301 for (cnt = nr_dquots ; cnt > 0 ; cnt--) {
302 dquot = next;
303 next = dquot->dq_next;
304 if (dquot->dq_dev != dev || dquot->dq_type != type)
305 continue;
306 if (dquot->dq_flags & DQ_LOCKED) {
307 printk("VFS: dquot busy on removed device %s\n", kdevname(dev));
308 continue;
309 }
310 if (dquot->dq_flags & DQ_MOD)
311 write_dquot(dquot);
312 dqstats.drops++;
313 clear_dquot(dquot);
314 }
315 }
316
317 static inline void dquot_incr_inodes(struct dquot *dquot, unsigned long number)
318 {
319 lock_dquot(dquot);
320 dquot->dq_curinodes += number;
321 dquot->dq_flags |= DQ_MOD;
322 unlock_dquot(dquot);
323 }
324
325 static inline void dquot_incr_blocks(struct dquot *dquot, unsigned long number)
326 {
327 lock_dquot(dquot);
328 dquot->dq_curblocks += number;
329 dquot->dq_flags |= DQ_MOD;
330 unlock_dquot(dquot);
331 }
332
333 static inline void dquot_decr_inodes(struct dquot *dquot, unsigned long number)
334 {
335 lock_dquot(dquot);
336 if (dquot->dq_curinodes > number)
337 dquot->dq_curinodes -= number;
338 else
339 dquot->dq_curinodes = 0;
340 if (dquot->dq_curinodes < dquot->dq_isoftlimit)
341 dquot->dq_itime = (time_t) 0;
342 dquot->dq_flags &= ~DQ_INODES;
343 dquot->dq_flags |= DQ_MOD;
344 unlock_dquot(dquot);
345 }
346
347 static inline void dquot_decr_blocks(struct dquot *dquot, unsigned long number)
348 {
349 lock_dquot(dquot);
350 if (dquot->dq_curblocks > number)
351 dquot->dq_curblocks -= number;
352 else
353 dquot->dq_curblocks = 0;
354 if (dquot->dq_curblocks < dquot->dq_bsoftlimit)
355 dquot->dq_btime = (time_t) 0;
356 dquot->dq_flags &= ~DQ_BLKS;
357 dquot->dq_flags |= DQ_MOD;
358 unlock_dquot(dquot);
359 }
360
361 static inline int need_print_warning(short type, struct dquot *dquot)
362 {
363 switch (type) {
364 case USRQUOTA:
365 return(current->fsuid == dquot->dq_id);
366 case GRPQUOTA:
367 return(current->fsgid == dquot->dq_id);
368 }
369 return(0);
370 }
371
372 static int check_idq(struct dquot *dquot, short type, u_long short inodes)
373 {
374 if (inodes <= 0 || dquot->dq_flags & DQ_FAKE)
375 return(QUOTA_OK);
376 if (dquot->dq_ihardlimit &&
377 (dquot->dq_curinodes + inodes) > dquot->dq_ihardlimit && !fsuser()) {
378 if ((dquot->dq_flags & DQ_INODES) == 0 &&
379 need_print_warning(type, dquot)) {
380 sprintf(quotamessage, "%s: write failed, %s file limit reached\r\n",
381 dquot->dq_mnt->mnt_dirname, quotatypes[type]);
382 tty_write_message(current->tty, quotamessage);
383 dquot->dq_flags |= DQ_INODES;
384 }
385 return(NO_QUOTA);
386 }
387 if (dquot->dq_isoftlimit &&
388 (dquot->dq_curinodes + inodes) > dquot->dq_isoftlimit &&
389 dquot->dq_itime && CURRENT_TIME >= dquot->dq_itime && !fsuser()) {
390 if (need_print_warning(type, dquot)) {
391 sprintf(quotamessage, "%s: warning, %s file quota exceeded to long.\r\n",
392 dquot->dq_mnt->mnt_dirname, quotatypes[type]);
393 tty_write_message(current->tty, quotamessage);
394 }
395 return(NO_QUOTA);
396 }
397 if (dquot->dq_isoftlimit &&
398 (dquot->dq_curinodes + inodes) > dquot->dq_isoftlimit &&
399 dquot->dq_itime == 0 && !fsuser()) {
400 if (need_print_warning(type, dquot)) {
401 sprintf(quotamessage, "%s: warning, %s file quota exceeded\r\n",
402 dquot->dq_mnt->mnt_dirname, quotatypes[type]);
403 tty_write_message(current->tty, quotamessage);
404 }
405 dquot->dq_itime = CURRENT_TIME + dquot->dq_mnt->mnt_iexp[type];
406 }
407 return(QUOTA_OK);
408 }
409
410 static int check_bdq(struct dquot *dquot, short type, u_long blocks)
411 {
412 if (blocks <= 0 || dquot->dq_flags & DQ_FAKE)
413 return(QUOTA_OK);
414 if (dquot->dq_bhardlimit &&
415 (dquot->dq_curblocks + blocks) > dquot->dq_bhardlimit && !fsuser()) {
416 if ((dquot->dq_flags & DQ_BLKS) == 0 &&
417 need_print_warning(type, dquot)) {
418 sprintf(quotamessage, "%s: write failed, %s disk limit reached.\r\n",
419 dquot->dq_mnt->mnt_dirname, quotatypes[type]);
420 tty_write_message(current->tty, quotamessage);
421 dquot->dq_flags |= DQ_BLKS;
422 }
423 return(NO_QUOTA);
424 }
425 if (dquot->dq_bsoftlimit &&
426 (dquot->dq_curblocks + blocks) > dquot->dq_bsoftlimit &&
427 dquot->dq_btime && CURRENT_TIME >= dquot->dq_btime && !fsuser()) {
428 if (need_print_warning(type, dquot)) {
429 sprintf(quotamessage, "%s: write failed, %s disk quota exceeded to long.\r\n",
430 dquot->dq_mnt->mnt_dirname, quotatypes[type]);
431 tty_write_message(current->tty, quotamessage);
432 }
433 return(NO_QUOTA);
434 }
435 if (dquot->dq_bsoftlimit &&
436 (dquot->dq_curblocks + blocks) > dquot->dq_bsoftlimit &&
437 dquot->dq_btime == 0 && !fsuser()) {
438 if (need_print_warning(type, dquot)) {
439 sprintf(quotamessage, "%s: warning, %s disk quota exceeded\r\n",
440 dquot->dq_mnt->mnt_dirname, quotatypes[type]);
441 tty_write_message(current->tty, quotamessage);
442 }
443 dquot->dq_btime = CURRENT_TIME + dquot->dq_mnt->mnt_bexp[type];
444 }
445 return(QUOTA_OK);
446 }
447
448 static void dqput(struct dquot *dquot)
449 {
450 if (!dquot)
451 return;
452
453
454
455
456
457 if (dquot->dq_mnt != (struct vfsmount *)NULL) {
458 dqstats.drops++;
459 wait_on_dquot(dquot);
460 if (!dquot->dq_count) {
461 printk("VFS: dqput: trying to free free dquot\n");
462 printk("VFS: device %s, dquot of %s %d\n", kdevname(dquot->dq_dev),
463 quotatypes[dquot->dq_type], dquot->dq_id);
464 return;
465 }
466 repeat:
467 if (dquot->dq_count > 1) {
468 dquot->dq_count--;
469 return;
470 }
471 wake_up(&dquot_wait);
472 if (dquot->dq_flags & DQ_MOD) {
473 write_dquot(dquot);
474 wait_on_dquot(dquot);
475 goto repeat;
476 }
477 }
478 if (dquot->dq_count) {
479 dquot->dq_count--;
480 nr_free_dquots++;
481 }
482 return;
483 }
484
485 static struct dquot *get_empty_dquot(void)
486 {
487 struct dquot *dquot, *best;
488 int cnt;
489
490 if (nr_dquots < NR_DQUOTS && nr_free_dquots < (nr_dquots >> 2))
491 grow_dquots();
492
493 repeat:
494 dquot = first_dquot;
495 best = NODQUOT;
496 for (cnt = 0; cnt < nr_dquots; dquot = dquot->dq_next, cnt++) {
497 if (!dquot->dq_count) {
498 if (!best)
499 best = dquot;
500 if (!(dquot->dq_flags & DQ_MOD) && !(dquot->dq_flags & DQ_LOCKED)) {
501 best = dquot;
502 break;
503 }
504 }
505 }
506 if (!best || best->dq_flags & DQ_MOD || best->dq_flags & DQ_LOCKED)
507 if (nr_dquots < NR_DQUOTS) {
508 grow_dquots();
509 goto repeat;
510 }
511 dquot = best;
512 if (!dquot) {
513 printk("VFS: No free dquots - contact mvw@mcs.ow.org\n");
514 sleep_on(&dquot_wait);
515 goto repeat;
516 }
517 if (dquot->dq_flags & DQ_LOCKED) {
518 wait_on_dquot(dquot);
519 goto repeat;
520 }
521 if (dquot->dq_flags & DQ_MOD) {
522 write_dquot(dquot);
523 goto repeat;
524 }
525 if (dquot->dq_count)
526 goto repeat;
527 clear_dquot(dquot);
528 dquot->dq_count = 1;
529 nr_free_dquots--;
530 if (nr_free_dquots < 0) {
531 printk ("VFS: get_empty_dquot: bad free dquot count.\n");
532 nr_free_dquots = 0;
533 }
534 return(dquot);
535 }
536
537 static struct dquot *dqget(kdev_t dev, unsigned int id, short type)
538 {
539 struct dquot *dquot, *empty;
540 struct vfsmount *vfsmnt;
541
542 if ((vfsmnt = lookup_vfsmnt(dev)) == (struct vfsmount *)NULL ||
543 (vfsmnt->mnt_quotas[type] == (struct file *)0))
544 return(NODQUOT);
545 dqstats.lookups++;
546 empty = get_empty_dquot();
547 repeat:
548 dquot = *(hash(dev, id, type));
549 while (dquot) {
550 if (dquot->dq_dev != dev || dquot->dq_id != id) {
551 dquot = dquot->dq_hash_next;
552 continue;
553 }
554 wait_on_dquot(dquot);
555 if (dquot->dq_dev != dev || dquot->dq_id != id)
556 goto repeat;
557 if (!dquot->dq_count)
558 nr_free_dquots--;
559 dquot->dq_count++;
560 if (empty)
561 dqput(empty);
562 dqstats.cache_hits++;
563 return(dquot);
564 }
565 if (!empty)
566 return(NODQUOT);
567 dquot = empty;
568 dquot->dq_id = id;
569 dquot->dq_type = type;
570 dquot->dq_dev = dev;
571 dquot->dq_mnt = vfsmnt;
572 put_last_free(dquot);
573 insert_dquot_hash(dquot);
574 read_dquot(dquot);
575 return(dquot);
576 }
577
578
579
580
581
582 static int set_dqblk(kdev_t dev, int id, short type, int flags, struct dqblk *dqblk)
583 {
584 struct dquot *dquot;
585 struct dqblk dq_dqblk;
586 int error;
587
588 if (dqblk == (struct dqblk *)NULL)
589 return(-EFAULT);
590
591 if (flags & QUOTA_SYSCALL) {
592 if ((error = verify_area(VERIFY_READ, dqblk, sizeof(struct dqblk))) != 0)
593 return(error);
594 memcpy_fromfs(&dq_dqblk, dqblk, sizeof(struct dqblk));
595 } else {
596 memcpy(&dq_dqblk, dqblk, sizeof(struct dqblk));
597 }
598 if ((dquot = dqget(dev, id, type)) != NODQUOT) {
599 lock_dquot(dquot);
600 if (id > 0 && ((flags & SET_QUOTA) || (flags & SET_QLIMIT))) {
601 dquot->dq_bhardlimit = dq_dqblk.dqb_bhardlimit;
602 dquot->dq_bsoftlimit = dq_dqblk.dqb_bsoftlimit;
603 dquot->dq_ihardlimit = dq_dqblk.dqb_ihardlimit;
604 dquot->dq_isoftlimit = dq_dqblk.dqb_isoftlimit;
605 }
606 if ((flags & SET_QUOTA) || (flags & SET_USE)) {
607 if (dquot->dq_isoftlimit &&
608 dquot->dq_curinodes < dquot->dq_isoftlimit &&
609 dq_dqblk.dqb_curinodes >= dquot->dq_isoftlimit)
610 dquot->dq_itime = CURRENT_TIME + dquot->dq_mnt->mnt_iexp[type];
611 dquot->dq_curinodes = dq_dqblk.dqb_curinodes;
612 if (dquot->dq_curinodes < dquot->dq_isoftlimit)
613 dquot->dq_flags &= ~DQ_INODES;
614 if (dquot->dq_bsoftlimit &&
615 dquot->dq_curblocks < dquot->dq_bsoftlimit &&
616 dq_dqblk.dqb_curblocks >= dquot->dq_bsoftlimit)
617 dquot->dq_btime = CURRENT_TIME + dquot->dq_mnt->mnt_bexp[type];
618 dquot->dq_curblocks = dq_dqblk.dqb_curblocks;
619 if (dquot->dq_curblocks < dquot->dq_bsoftlimit)
620 dquot->dq_flags &= ~DQ_BLKS;
621 }
622 if (id == 0) {
623
624
625
626 dquot->dq_mnt->mnt_bexp[type] = dquot->dq_btime = dq_dqblk.dqb_btime;
627 dquot->dq_mnt->mnt_iexp[type] = dquot->dq_itime = dq_dqblk.dqb_itime;
628 }
629 if (dq_dqblk.dqb_bhardlimit == 0 && dq_dqblk.dqb_bsoftlimit == 0 &&
630 dq_dqblk.dqb_ihardlimit == 0 && dq_dqblk.dqb_isoftlimit == 0)
631 dquot->dq_flags |= DQ_FAKE;
632 else
633 dquot->dq_flags &= ~DQ_FAKE;
634 dquot->dq_flags |= DQ_MOD;
635 unlock_dquot(dquot);
636 dqput(dquot);
637 }
638 return(0);
639 }
640
641 static int get_quota(kdev_t dev, int id, short type, struct dqblk *dqblk)
642 {
643 struct dquot *dquot;
644 int error;
645
646 if (has_quota_enabled(dev, type)) {
647 if (dqblk == (struct dqblk *)NULL)
648 return(-EFAULT);
649
650 if ((error = verify_area(VERIFY_WRITE, dqblk, sizeof(struct dqblk))) != 0)
651 return(error);
652
653 if ((dquot = dqget(dev, id, type)) != NODQUOT) {
654 memcpy_tofs(dqblk, (char *)&dquot->dq_dqb, sizeof(struct dqblk));
655 dqput(dquot);
656 return(0);
657 }
658 }
659 return(-ESRCH);
660 }
661
662 static int get_stats(caddr_t addr)
663 {
664 int error;
665
666 if ((error = verify_area(VERIFY_WRITE, addr, sizeof(struct dqstats))) != 0)
667 return(error);
668
669 dqstats.allocated_dquots = nr_dquots;
670 dqstats.free_dquots = nr_free_dquots;
671 memcpy_tofs(addr, (caddr_t)&dqstats, sizeof(struct dqstats));
672 return(0);
673 }
674
675
676
677
678 void dquot_initialize(struct inode *inode, short type)
679 {
680 unsigned int id = 0;
681 short cnt;
682
683 if (S_ISREG(inode->i_mode) || S_ISDIR(inode->i_mode) || S_ISLNK(inode->i_mode)) {
684 for (cnt = 0; cnt < MAXQUOTAS; cnt++) {
685 if (type != -1 && cnt != type)
686 continue;
687 if (!has_quota_enabled(inode->i_dev, cnt))
688 continue;
689 if (inode->i_dquot[cnt] == NODQUOT) {
690 switch (cnt) {
691 case USRQUOTA:
692 id = inode->i_uid;
693 break;
694 case GRPQUOTA:
695 id = inode->i_gid;
696 break;
697 }
698 inode->i_dquot[cnt] = dqget(inode->i_dev, id, cnt);
699 inode->i_flags |= S_WRITE;
700 }
701 }
702 }
703 }
704
705 void dquot_drop(struct inode *inode)
706 {
707 short cnt;
708
709 for (cnt = 0; cnt < MAXQUOTAS; cnt++) {
710 if (inode->i_dquot[cnt] == NODQUOT)
711 continue;
712 dqput(inode->i_dquot[cnt]);
713 inode->i_dquot[cnt] = NODQUOT;
714 }
715 inode->i_flags &= ~S_WRITE;
716 }
717
718
719
720
721
722 static u_long isize_to_blocks(size_t isize, size_t blksize)
723 {
724 u_long blocks;
725 u_long indirect;
726
727 if (!blksize)
728 blksize = BLOCK_SIZE;
729 blocks = (isize / blksize) + ((isize % blksize) ? 1 : 0);
730 if (blocks > 10) {
731 indirect = ((blocks - 11) >> 8) + 1;
732 if (blocks > (10 + 256)) {
733 indirect += ((blocks - 267) >> 16) + 1;
734 if (blocks > (10 + 256 + (256 << 8)))
735 indirect++;
736 }
737 blocks += indirect;
738 }
739 return(blocks);
740 }
741
742
743
744
745 int dquot_alloc_block(const struct inode *inode, unsigned long number)
746 {
747 unsigned short cnt;
748
749 for (cnt = 0; cnt < MAXQUOTAS; cnt++) {
750 if (inode->i_dquot[cnt] == NODQUOT)
751 continue;
752 if (check_bdq(inode->i_dquot[cnt], cnt, number))
753 return(NO_QUOTA);
754 }
755 for (cnt = 0; cnt < MAXQUOTAS; cnt++) {
756 if (inode->i_dquot[cnt] == NODQUOT)
757 continue;
758 dquot_incr_blocks(inode->i_dquot[cnt], number);
759 }
760 return(QUOTA_OK);
761 }
762
763 int dquot_alloc_inode(const struct inode *inode, unsigned long number)
764 {
765 unsigned short cnt;
766
767 for (cnt = 0; cnt < MAXQUOTAS; cnt++) {
768 if (inode->i_dquot[cnt] == NODQUOT)
769 continue;
770 if (check_idq(inode->i_dquot[cnt], cnt, number))
771 return(NO_QUOTA);
772 }
773 for (cnt = 0; cnt < MAXQUOTAS; cnt++) {
774 if (inode->i_dquot[cnt] == NODQUOT)
775 continue;
776 dquot_incr_inodes(inode->i_dquot[cnt], number);
777 }
778 return(QUOTA_OK);
779 }
780
781 void dquot_free_block(const struct inode *inode, unsigned long number)
782 {
783 unsigned short cnt;
784
785 for (cnt = 0; cnt < MAXQUOTAS; cnt++) {
786 if (inode->i_dquot[cnt] == NODQUOT)
787 continue;
788 dquot_decr_blocks(inode->i_dquot[cnt], number);
789 }
790 }
791
792 void dquot_free_inode(const struct inode *inode, unsigned long number)
793 {
794 unsigned short cnt;
795
796 for (cnt = 0; cnt < MAXQUOTAS; cnt++) {
797 if (inode->i_dquot[cnt] == NODQUOT)
798 continue;
799 dquot_decr_inodes(inode->i_dquot[cnt], number);
800 }
801 }
802
803
804
805
806 int dquot_transfer(struct inode *inode, struct iattr *iattr, char direction)
807 {
808 unsigned long blocks;
809 struct dquot *transfer_from[MAXQUOTAS];
810 struct dquot *transfer_to[MAXQUOTAS];
811 short cnt, disc;
812
813
814
815
816 if (inode->i_blksize == 0)
817 blocks = isize_to_blocks(inode->i_size, BLOCK_SIZE);
818 else
819 blocks = (inode->i_blocks / 2);
820
821
822
823
824
825 for (cnt = 0; cnt < MAXQUOTAS; cnt++) {
826 transfer_from[cnt] = NODQUOT;
827 transfer_to[cnt] = NODQUOT;
828
829 if (!has_quota_enabled(inode->i_dev, cnt))
830 continue;
831
832 switch (cnt) {
833 case USRQUOTA:
834 if (inode->i_uid == iattr->ia_uid)
835 continue;
836 transfer_from[cnt] = dqget(inode->i_dev, (direction) ? iattr->ia_uid : inode->i_uid, cnt);
837 transfer_to[cnt] = dqget(inode->i_dev, (direction) ? inode->i_uid : iattr->ia_uid, cnt);
838 break;
839 case GRPQUOTA:
840 if (inode->i_gid == iattr->ia_gid)
841 continue;
842 transfer_from[cnt] = dqget(inode->i_dev, (direction) ? iattr->ia_gid : inode->i_gid, cnt);
843 transfer_to[cnt] = dqget(inode->i_dev, (direction) ? inode->i_gid : iattr->ia_gid, cnt);
844 break;
845 }
846
847 if (check_idq(transfer_to[cnt], cnt, 1) == NO_QUOTA ||
848 check_bdq(transfer_to[cnt], cnt, blocks) == NO_QUOTA) {
849 for (disc = 0; disc <= cnt; disc++) {
850 dqput(transfer_from[disc]);
851 dqput(transfer_to[disc]);
852 }
853 return(NO_QUOTA);
854 }
855 }
856
857
858
859
860
861 for (cnt = 0; cnt < MAXQUOTAS; cnt++) {
862
863
864
865 if (transfer_from[cnt] == NODQUOT && transfer_to[cnt] == NODQUOT)
866 continue;
867
868 if (transfer_from[cnt] != NODQUOT) {
869 dquot_decr_inodes(transfer_from[cnt], 1);
870 dquot_decr_blocks(transfer_from[cnt], blocks);
871 }
872 if (transfer_to[cnt] != NODQUOT) {
873 dquot_incr_inodes(transfer_to[cnt], 1);
874 dquot_incr_blocks(transfer_to[cnt], blocks);
875 }
876 if (inode->i_dquot[cnt] != NODQUOT) {
877 dqput(transfer_from[cnt]);
878 dqput(inode->i_dquot[cnt]);
879 inode->i_dquot[cnt] = transfer_to[cnt];
880 } else {
881 dqput(transfer_from[cnt]);
882 dqput(transfer_to[cnt]);
883 }
884 }
885 return(QUOTA_OK);
886 }
887
888 void dquot_init(void)
889 {
890 printk("VFS: Diskquotas version %s initialized\r\n", __DQUOT_VERSION__);
891 memset(hash_table, 0, sizeof(hash_table));
892 memset((caddr_t)&dqstats, 0, sizeof(dqstats));
893 first_dquot = NODQUOT;
894 }
895
896
897
898
899 struct dquot_operations dquot_operations = {
900 dquot_initialize,
901 dquot_drop,
902 dquot_alloc_block,
903 dquot_alloc_inode,
904 dquot_free_block,
905 dquot_free_inode,
906 dquot_transfer
907 };
908
909
910
911
912 int quota_off(kdev_t dev, short type)
913 {
914 struct vfsmount *vfsmnt;
915 short cnt;
916
917 for (cnt = 0; cnt < MAXQUOTAS; cnt++) {
918 if (type != -1 && cnt != type)
919 continue;
920 if ((vfsmnt = lookup_vfsmnt(dev)) == (struct vfsmount *)NULL ||
921 vfsmnt->mnt_quotas[cnt] == (struct file *)NULL)
922 continue;
923 vfsmnt->mnt_sb->dq_op = (struct dquot_operations *)NULL;
924 reset_dquot_ptrs(dev, cnt);
925 invalidate_dquots(dev, cnt);
926 close_fp(vfsmnt->mnt_quotas[cnt]);
927 vfsmnt->mnt_quotas[cnt] = (struct file *)NULL;
928 vfsmnt->mnt_iexp[cnt] = vfsmnt->mnt_bexp[cnt] = (time_t)NULL;
929 }
930 return(0);
931 }
932
933 int quota_on(kdev_t dev, short type, char *path)
934 {
935 struct file *filp = (struct file *)NULL;
936 struct vfsmount *vfsmnt;
937 struct inode *inode;
938 struct dquot *dquot;
939 char *tmp;
940 int error;
941
942 if ((vfsmnt = lookup_vfsmnt(dev)) == (struct vfsmount *)NULL)
943 return(-ENODEV);
944 if (vfsmnt->mnt_quotas[type] != (struct file *)NULL)
945 return(-EBUSY);
946 if ((error = getname(path, &tmp)) != 0)
947 return(error);
948 error = open_namei(tmp, O_RDWR, 0600, &inode, 0);
949 putname(tmp);
950 if (error)
951 return(error);
952 if (!S_ISREG(inode->i_mode)) {
953 iput(inode);
954 return(-EACCES);
955 }
956 if ((filp = get_empty_filp()) != (struct file *)NULL) {
957 filp->f_mode = (O_RDWR + 1) & O_ACCMODE;
958 filp->f_flags = O_RDWR;
959 filp->f_inode = inode;
960 filp->f_pos = 0;
961 filp->f_reada = 0;
962 filp->f_op = inode->i_op->default_file_ops;
963 if (filp->f_op->read || filp->f_op->write) {
964 if ((error = get_write_access(inode)) == 0) {
965 if (filp->f_op && filp->f_op->open)
966 error = filp->f_op->open(inode, filp);
967 if (error == 0) {
968 vfsmnt->mnt_quotas[type] = filp;
969 dquot = dqget(dev, 0, type);
970 vfsmnt->mnt_iexp[type] = (dquot) ? dquot->dq_itime : MAX_IQ_TIME;
971 vfsmnt->mnt_bexp[type] = (dquot) ? dquot->dq_btime : MAX_DQ_TIME;
972 dqput(dquot);
973 vfsmnt->mnt_sb->dq_op = &dquot_operations;
974 add_dquot_ref(dev, type);
975 return(0);
976 }
977 put_write_access(inode);
978 }
979 } else
980 error = -EIO;
981 filp->f_count--;
982 } else
983 error = -EMFILE;
984 iput(inode);
985 return(error);
986 }
987
988
989
990
991
992
993
994 asmlinkage int sys_quotactl(int cmd, const char *special, int id, caddr_t addr)
995 {
996 int cmds = 0, type = 0, flags = 0;
997 struct inode *ino;
998 kdev_t dev;
999
1000 cmds = cmd >> SUBCMDSHIFT;
1001 type = cmd & SUBCMDMASK;
1002
1003 if ((u_int) type >= MAXQUOTAS)
1004 return(-EINVAL);
1005 switch (cmds) {
1006 case Q_SYNC:
1007 case Q_GETSTATS:
1008 break;
1009 case Q_GETQUOTA:
1010 if (((type == USRQUOTA && current->uid != id) ||
1011 (type == GRPQUOTA && current->gid != id)) && !fsuser())
1012 return(-EPERM);
1013 break;
1014 default:
1015 if (!fsuser())
1016 return(-EPERM);
1017 }
1018
1019 if (special == (char *)NULL && (cmds == Q_SYNC || cmds == Q_GETSTATS))
1020 dev = 0;
1021 else {
1022 if (namei(special, &ino))
1023 return(-EINVAL);
1024 dev = ino->i_rdev;
1025 if (!S_ISBLK(ino->i_mode)) {
1026 iput(ino);
1027 return(-ENOTBLK);
1028 }
1029 iput(ino);
1030 }
1031
1032 switch (cmds) {
1033 case Q_QUOTAON:
1034 return(quota_on(dev, type, (char *) addr));
1035 case Q_QUOTAOFF:
1036 return(quota_off(dev, type));
1037 case Q_GETQUOTA:
1038 return(get_quota(dev, id, type, (struct dqblk *) addr));
1039 case Q_SETQUOTA:
1040 flags |= SET_QUOTA;
1041 break;
1042 case Q_SETUSE:
1043 flags |= SET_USE;
1044 break;
1045 case Q_SETQLIM:
1046 flags |= SET_QLIMIT;
1047 break;
1048 case Q_SYNC:
1049 return(sync_dquots(dev, type));
1050 case Q_GETSTATS:
1051 return(get_stats(addr));
1052 default:
1053 return(-EINVAL);
1054 }
1055
1056 flags |= QUOTA_SYSCALL;
1057 if (has_quota_enabled(dev, type))
1058 return(set_dqblk(dev, id, type, flags, (struct dqblk *) addr));
1059 return(-ESRCH);
1060 }