1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51#include <linux/errno.h>
52#include <linux/kernel.h>
53#include <linux/fs.h>
54#include <linux/sched.h>
55#include <linux/types.h>
56#include <linux/string.h>
57#include <linux/fcntl.h>
58#include <linux/stat.h>
59#include <linux/tty.h>
60#include <linux/file.h>
61#include <linux/slab.h>
62#include <linux/smp_lock.h>
63#include <linux/init.h>
64
65#include <asm/uaccess.h>
66
67#define __DQUOT_VERSION__ "dquot_6.4.0"
68
69int nr_dquots, nr_free_dquots;
70
71static char *quotatypes[] = INITQFNAMES;
72
73static inline struct quota_mount_options *sb_dqopt(struct super_block *sb)
74{
75 return &sb->s_dquot;
76}
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114static LIST_HEAD(inuse_list);
115static LIST_HEAD(free_dquots);
116static struct list_head dquot_hash[NR_DQHASH];
117
118static struct dqstats dqstats;
119
120static void dqput(struct dquot *);
121static struct dquot *dqduplicate(struct dquot *);
122
123static inline char is_enabled(struct quota_mount_options *dqopt, short type)
124{
125 switch (type) {
126 case USRQUOTA:
127 return((dqopt->flags & DQUOT_USR_ENABLED) != 0);
128 case GRPQUOTA:
129 return((dqopt->flags & DQUOT_GRP_ENABLED) != 0);
130 }
131 return(0);
132}
133
134static inline char sb_has_quota_enabled(struct super_block *sb, short type)
135{
136 return is_enabled(sb_dqopt(sb), type);
137}
138
139static inline int const hashfn(kdev_t dev, unsigned int id, short type)
140{
141 return((HASHDEV(dev) ^ id) * (MAXQUOTAS - type)) % NR_DQHASH;
142}
143
144static inline void insert_dquot_hash(struct dquot *dquot)
145{
146 struct list_head *head = dquot_hash + hashfn(dquot->dq_dev, dquot->dq_id, dquot->dq_type);
147 list_add(&dquot->dq_hash, head);
148}
149
150static inline void remove_dquot_hash(struct dquot *dquot)
151{
152 list_del(&dquot->dq_hash);
153 INIT_LIST_HEAD(&dquot->dq_hash);
154}
155
156static inline struct dquot *find_dquot(unsigned int hashent, kdev_t dev, unsigned int id, short type)
157{
158 struct list_head *head;
159 struct dquot *dquot;
160
161 for (head = dquot_hash[hashent].next; head != dquot_hash+hashent; head = head->next) {
162 dquot = list_entry(head, struct dquot, dq_hash);
163 if (dquot->dq_dev == dev && dquot->dq_id == id && dquot->dq_type == type)
164 return dquot;
165 }
166 return NODQUOT;
167}
168
169
170static inline void put_dquot_head(struct dquot *dquot)
171{
172 list_add(&dquot->dq_free, &free_dquots);
173 nr_free_dquots++;
174}
175
176
177static inline void put_dquot_last(struct dquot *dquot)
178{
179 list_add(&dquot->dq_free, free_dquots.prev);
180 nr_free_dquots++;
181}
182
183
184static inline void move_dquot_head(struct dquot *dquot)
185{
186 list_del(&dquot->dq_free);
187 list_add(&dquot->dq_free, &free_dquots);
188}
189
190static inline void remove_free_dquot(struct dquot *dquot)
191{
192 if (list_empty(&dquot->dq_free))
193 return;
194 list_del(&dquot->dq_free);
195 INIT_LIST_HEAD(&dquot->dq_free);
196 nr_free_dquots--;
197}
198
199static inline void put_inuse(struct dquot *dquot)
200{
201
202
203 list_add(&dquot->dq_inuse, inuse_list.prev);
204 nr_dquots++;
205}
206
207static inline void remove_inuse(struct dquot *dquot)
208{
209 nr_dquots--;
210 list_del(&dquot->dq_inuse);
211}
212
213static void __wait_on_dquot(struct dquot *dquot)
214{
215 DECLARE_WAITQUEUE(wait, current);
216
217 add_wait_queue(&dquot->dq_wait_lock, &wait);
218repeat:
219 set_current_state(TASK_UNINTERRUPTIBLE);
220 if (dquot->dq_flags & DQ_LOCKED) {
221 schedule();
222 goto repeat;
223 }
224 remove_wait_queue(&dquot->dq_wait_lock, &wait);
225 current->state = TASK_RUNNING;
226}
227
228static inline void wait_on_dquot(struct dquot *dquot)
229{
230 if (dquot->dq_flags & DQ_LOCKED)
231 __wait_on_dquot(dquot);
232}
233
234static inline void lock_dquot(struct dquot *dquot)
235{
236 wait_on_dquot(dquot);
237 dquot->dq_flags |= DQ_LOCKED;
238}
239
240static inline void unlock_dquot(struct dquot *dquot)
241{
242 dquot->dq_flags &= ~DQ_LOCKED;
243 wake_up(&dquot->dq_wait_lock);
244}
245
246static void __wait_dquot_unused(struct dquot *dquot)
247{
248 DECLARE_WAITQUEUE(wait, current);
249
250 add_wait_queue(&dquot->dq_wait_free, &wait);
251repeat:
252 set_current_state(TASK_UNINTERRUPTIBLE);
253 if (dquot->dq_count) {
254 schedule();
255 goto repeat;
256 }
257 remove_wait_queue(&dquot->dq_wait_free, &wait);
258 current->state = TASK_RUNNING;
259}
260
261
262
263
264static void write_dquot(struct dquot *dquot)
265{
266 short type = dquot->dq_type;
267 struct file *filp;
268 mm_segment_t fs;
269 loff_t offset;
270 ssize_t ret;
271 struct semaphore *sem = &dquot->dq_sb->s_dquot.dqio_sem;
272 struct dqblk dqbuf;
273
274 down(sem);
275 filp = dquot->dq_sb->s_dquot.files[type];
276 offset = dqoff(dquot->dq_id);
277 fs = get_fs();
278 set_fs(KERNEL_DS);
279
280
281
282
283
284 memcpy(&dqbuf, &dquot->dq_dqb, sizeof(struct dqblk));
285 dquot->dq_flags &= ~DQ_MOD;
286 ret = 0;
287 if (filp)
288 ret = filp->f_op->write(filp, (char *)&dqbuf,
289 sizeof(struct dqblk), &offset);
290 if (ret != sizeof(struct dqblk))
291 printk(KERN_WARNING "VFS: dquota write failed on dev %s\n",
292 kdevname(dquot->dq_dev));
293
294 set_fs(fs);
295 up(sem);
296 dqstats.writes++;
297}
298
299static void read_dquot(struct dquot *dquot)
300{
301 short type = dquot->dq_type;
302 struct file *filp;
303 mm_segment_t fs;
304 loff_t offset;
305
306 filp = dquot->dq_sb->s_dquot.files[type];
307 if (filp == (struct file *)NULL)
308 return;
309
310 lock_dquot(dquot);
311 if (!dquot->dq_sb)
312 goto out_lock;
313
314 down(&dquot->dq_sb->s_dquot.dqio_sem);
315 offset = dqoff(dquot->dq_id);
316 fs = get_fs();
317 set_fs(KERNEL_DS);
318 filp->f_op->read(filp, (char *)&dquot->dq_dqb, sizeof(struct dqblk), &offset);
319 up(&dquot->dq_sb->s_dquot.dqio_sem);
320 set_fs(fs);
321
322 if (dquot->dq_bhardlimit == 0 && dquot->dq_bsoftlimit == 0 &&
323 dquot->dq_ihardlimit == 0 && dquot->dq_isoftlimit == 0)
324 dquot->dq_flags |= DQ_FAKE;
325 dqstats.reads++;
326out_lock:
327 unlock_dquot(dquot);
328}
329
330
331
332
333static void invalidate_dquots(struct super_block *sb, short type)
334{
335 struct dquot *dquot;
336 struct list_head *head;
337
338restart:
339 for (head = inuse_list.next; head != &inuse_list; head = head->next) {
340 dquot = list_entry(head, struct dquot, dq_inuse);
341 if (dquot->dq_sb != sb)
342 continue;
343 if (dquot->dq_type != type)
344 continue;
345 dquot->dq_flags |= DQ_INVAL;
346 if (dquot->dq_count)
347
348
349
350
351
352 __wait_dquot_unused(dquot);
353
354 remove_dquot_hash(dquot);
355 remove_free_dquot(dquot);
356 remove_inuse(dquot);
357 kmem_cache_free(dquot_cachep, dquot);
358 goto restart;
359 }
360}
361
362int sync_dquots(kdev_t dev, short type)
363{
364 struct list_head *head;
365 struct dquot *dquot;
366
367 lock_kernel();
368restart:
369 for (head = inuse_list.next; head != &inuse_list; head = head->next) {
370 dquot = list_entry(head, struct dquot, dq_inuse);
371 if (dev && dquot->dq_dev != dev)
372 continue;
373 if (type != -1 && dquot->dq_type != type)
374 continue;
375 if (!dquot->dq_sb)
376 continue;
377 if (!(dquot->dq_flags & (DQ_MOD | DQ_LOCKED)))
378 continue;
379
380 dquot->dq_count++;
381 if (dquot->dq_flags & DQ_LOCKED)
382 wait_on_dquot(dquot);
383 if (dquot->dq_flags & DQ_MOD)
384 write_dquot(dquot);
385 dqput(dquot);
386 goto restart;
387 }
388 dqstats.syncs++;
389 unlock_kernel();
390 return 0;
391}
392
393
394static void prune_dqcache(int count)
395{
396 struct list_head *head;
397 struct dquot *dquot;
398
399 head = free_dquots.prev;
400 while (head != &free_dquots && count) {
401 dquot = list_entry(head, struct dquot, dq_free);
402 remove_dquot_hash(dquot);
403 remove_free_dquot(dquot);
404 remove_inuse(dquot);
405 kmem_cache_free(dquot_cachep, dquot);
406 count--;
407 head = free_dquots.prev;
408 }
409}
410
411int shrink_dqcache_memory(int priority, unsigned int gfp_mask)
412{
413 lock_kernel();
414 prune_dqcache(nr_free_dquots / (priority + 1));
415 unlock_kernel();
416 return kmem_cache_shrink(dquot_cachep);
417}
418
419
420static void dqput(struct dquot *dquot)
421{
422 if (!dquot)
423 return;
424 if (!dquot->dq_count) {
425 printk("VFS: dqput: trying to free free dquot\n");
426 printk("VFS: device %s, dquot of %s %d\n",
427 kdevname(dquot->dq_dev), quotatypes[dquot->dq_type],
428 dquot->dq_id);
429 return;
430 }
431
432 dqstats.drops++;
433we_slept:
434 if (dquot->dq_count > 1) {
435
436 dquot->dq_count--;
437 return;
438 }
439 if (dquot->dq_flags & DQ_MOD) {
440 write_dquot(dquot);
441 goto we_slept;
442 }
443
444
445 if (!list_empty(&dquot->dq_free)) {
446 printk(KERN_ERR "dqput: dquot already on free list??\n");
447 dquot->dq_count--;
448 return;
449 }
450 dquot->dq_count--;
451
452 if (!(dquot->dq_flags & DQ_INVAL))
453 put_dquot_last(dquot);
454 wake_up(&dquot->dq_wait_free);
455}
456
457static struct dquot *get_empty_dquot(void)
458{
459 struct dquot *dquot;
460
461 dquot = kmem_cache_alloc(dquot_cachep, SLAB_KERNEL);
462 if(!dquot)
463 return NODQUOT;
464
465 memset((caddr_t)dquot, 0, sizeof(struct dquot));
466 init_waitqueue_head(&dquot->dq_wait_free);
467 init_waitqueue_head(&dquot->dq_wait_lock);
468 INIT_LIST_HEAD(&dquot->dq_free);
469 INIT_LIST_HEAD(&dquot->dq_inuse);
470 INIT_LIST_HEAD(&dquot->dq_hash);
471 dquot->dq_count = 1;
472
473 put_inuse(dquot);
474
475 return dquot;
476}
477
478static struct dquot *dqget(struct super_block *sb, unsigned int id, short type)
479{
480 unsigned int hashent = hashfn(sb->s_dev, id, type);
481 struct dquot *dquot, *empty = NODQUOT;
482 struct quota_mount_options *dqopt = sb_dqopt(sb);
483
484we_slept:
485 if (!is_enabled(dqopt, type)) {
486 if (empty)
487 dqput(empty);
488 return NODQUOT;
489 }
490
491 if ((dquot = find_dquot(hashent, sb->s_dev, id, type)) == NODQUOT) {
492 if (empty == NODQUOT) {
493 if ((empty = get_empty_dquot()) == NODQUOT)
494 schedule();
495 goto we_slept;
496 }
497 dquot = empty;
498 dquot->dq_id = id;
499 dquot->dq_type = type;
500 dquot->dq_dev = sb->s_dev;
501 dquot->dq_sb = sb;
502
503 insert_dquot_hash(dquot);
504 read_dquot(dquot);
505 } else {
506 if (!dquot->dq_count++)
507 remove_free_dquot(dquot);
508 dqstats.cache_hits++;
509 wait_on_dquot(dquot);
510 if (empty)
511 dqput(empty);
512 }
513
514 if (!dquot->dq_sb) {
515 printk(KERN_ERR "VFS: dqget(): Quota invalidated in dqget()!\n");
516 dqput(dquot);
517 return NODQUOT;
518 }
519 dquot->dq_referenced++;
520 dqstats.lookups++;
521
522 return dquot;
523}
524
525static struct dquot *dqduplicate(struct dquot *dquot)
526{
527 if (dquot == NODQUOT)
528 return NODQUOT;
529 dquot->dq_count++;
530 if (!dquot->dq_sb) {
531 printk(KERN_ERR "VFS: dqduplicate(): Invalidated quota to be duplicated!\n");
532 dquot->dq_count--;
533 return NODQUOT;
534 }
535 if (dquot->dq_flags & DQ_LOCKED)
536 printk(KERN_ERR "VFS: dqduplicate(): Locked quota to be duplicated!\n");
537 dquot->dq_referenced++;
538 dqstats.lookups++;
539 return dquot;
540}
541
542static int dqinit_needed(struct inode *inode, short type)
543{
544 int cnt;
545
546 if (IS_NOQUOTA(inode))
547 return 0;
548 if (type != -1)
549 return inode->i_dquot[type] == NODQUOT;
550 for (cnt = 0; cnt < MAXQUOTAS; cnt++)
551 if (inode->i_dquot[cnt] == NODQUOT)
552 return 1;
553 return 0;
554}
555
556static void add_dquot_ref(struct super_block *sb, short type)
557{
558 struct list_head *p;
559
560 if (!sb->dq_op)
561 return;
562
563restart:
564 file_list_lock();
565 for (p = sb->s_files.next; p != &sb->s_files; p = p->next) {
566 struct file *filp = list_entry(p, struct file, f_list);
567 struct inode *inode = filp->f_dentry->d_inode;
568 if (filp->f_mode & FMODE_WRITE && dqinit_needed(inode, type)) {
569 struct vfsmount *mnt = mntget(filp->f_vfsmnt);
570 struct dentry *dentry = dget(filp->f_dentry);
571 file_list_unlock();
572 sb->dq_op->initialize(inode, type);
573 dput(dentry);
574 mntput(mnt);
575
576 goto restart;
577 }
578 }
579 file_list_unlock();
580}
581
582
583static inline int dqput_blocks(struct dquot *dquot)
584{
585 if (dquot->dq_count == 1)
586 return 1;
587 return 0;
588}
589
590
591int remove_inode_dquot_ref(struct inode *inode, short type, struct list_head *tofree_head)
592{
593 struct dquot *dquot = inode->i_dquot[type];
594 int cnt;
595
596 inode->i_dquot[type] = NODQUOT;
597
598 for (cnt = 0; cnt < MAXQUOTAS; cnt++) {
599 if (inode->i_dquot[cnt] != NODQUOT)
600 goto put_it;
601 }
602 inode->i_flags &= ~S_QUOTA;
603put_it:
604 if (dquot != NODQUOT) {
605 if (dqput_blocks(dquot)) {
606 if (dquot->dq_count != 1)
607 printk(KERN_WARNING "VFS: Adding dquot with dq_count %d to dispose list.\n", dquot->dq_count);
608 list_add(&dquot->dq_free, tofree_head);
609 return 1;
610 }
611 else
612 dqput(dquot);
613 }
614 return 0;
615}
616
617
618void put_dquot_list(struct list_head *tofree_head)
619{
620 struct list_head *act_head;
621 struct dquot *dquot;
622
623 lock_kernel();
624 act_head = tofree_head->next;
625
626 while (act_head != tofree_head) {
627 dquot = list_entry(act_head, struct dquot, dq_free);
628 act_head = act_head->next;
629 list_del(&dquot->dq_free);
630 INIT_LIST_HEAD(&dquot->dq_free);
631 dqput(dquot);
632 }
633 unlock_kernel();
634}
635
636static inline void dquot_incr_inodes(struct dquot *dquot, unsigned long number)
637{
638 dquot->dq_curinodes += number;
639 dquot->dq_flags |= DQ_MOD;
640}
641
642static inline void dquot_incr_blocks(struct dquot *dquot, unsigned long number)
643{
644 dquot->dq_curblocks += number;
645 dquot->dq_flags |= DQ_MOD;
646}
647
648static inline void dquot_decr_inodes(struct dquot *dquot, unsigned long number)
649{
650 if (dquot->dq_curinodes > number)
651 dquot->dq_curinodes -= number;
652 else
653 dquot->dq_curinodes = 0;
654 if (dquot->dq_curinodes < dquot->dq_isoftlimit)
655 dquot->dq_itime = (time_t) 0;
656 dquot->dq_flags &= ~DQ_INODES;
657 dquot->dq_flags |= DQ_MOD;
658}
659
660static inline void dquot_decr_blocks(struct dquot *dquot, unsigned long number)
661{
662 if (dquot->dq_curblocks > number)
663 dquot->dq_curblocks -= number;
664 else
665 dquot->dq_curblocks = 0;
666 if (dquot->dq_curblocks < dquot->dq_bsoftlimit)
667 dquot->dq_btime = (time_t) 0;
668 dquot->dq_flags &= ~DQ_BLKS;
669 dquot->dq_flags |= DQ_MOD;
670}
671
672static inline int need_print_warning(struct dquot *dquot, int flag)
673{
674 switch (dquot->dq_type) {
675 case USRQUOTA:
676 return current->fsuid == dquot->dq_id && !(dquot->dq_flags & flag);
677 case GRPQUOTA:
678 return in_group_p(dquot->dq_id) && !(dquot->dq_flags & flag);
679 }
680 return 0;
681}
682
683
684#define NOWARN 0
685#define IHARDWARN 1
686#define ISOFTLONGWARN 2
687#define ISOFTWARN 3
688#define BHARDWARN 4
689#define BSOFTLONGWARN 5
690#define BSOFTWARN 6
691
692
693static void print_warning(struct dquot *dquot, const char warntype)
694{
695 char *msg = NULL;
696 int flag = (warntype == BHARDWARN || warntype == BSOFTLONGWARN) ? DQ_BLKS :
697 ((warntype == IHARDWARN || warntype == ISOFTLONGWARN) ? DQ_INODES : 0);
698
699 if (!need_print_warning(dquot, flag))
700 return;
701 dquot->dq_flags |= flag;
702 tty_write_message(current->tty, (char *)bdevname(dquot->dq_sb->s_dev));
703 if (warntype == ISOFTWARN || warntype == BSOFTWARN)
704 tty_write_message(current->tty, ": warning, ");
705 else
706 tty_write_message(current->tty, ": write failed, ");
707 tty_write_message(current->tty, quotatypes[dquot->dq_type]);
708 switch (warntype) {
709 case IHARDWARN:
710 msg = " file limit reached.\n";
711 break;
712 case ISOFTLONGWARN:
713 msg = " file quota exceeded too long.\n";
714 break;
715 case ISOFTWARN:
716 msg = " file quota exceeded.\n";
717 break;
718 case BHARDWARN:
719 msg = " block limit reached.\n";
720 break;
721 case BSOFTLONGWARN:
722 msg = " block quota exceeded too long.\n";
723 break;
724 case BSOFTWARN:
725 msg = " block quota exceeded.\n";
726 break;
727 }
728 tty_write_message(current->tty, msg);
729}
730
731static inline void flush_warnings(struct dquot **dquots, char *warntype)
732{
733 int i;
734
735 for (i = 0; i < MAXQUOTAS; i++)
736 if (dquots[i] != NODQUOT && warntype[i] != NOWARN)
737 print_warning(dquots[i], warntype[i]);
738}
739
740static inline char ignore_hardlimit(struct dquot *dquot)
741{
742 return capable(CAP_SYS_RESOURCE) && !dquot->dq_sb->s_dquot.rsquash[dquot->dq_type];
743}
744
745static int check_idq(struct dquot *dquot, ulong inodes, char *warntype)
746{
747 *warntype = NOWARN;
748 if (inodes <= 0 || dquot->dq_flags & DQ_FAKE)
749 return QUOTA_OK;
750
751 if (dquot->dq_ihardlimit &&
752 (dquot->dq_curinodes + inodes) > dquot->dq_ihardlimit &&
753 !ignore_hardlimit(dquot)) {
754 *warntype = IHARDWARN;
755 return NO_QUOTA;
756 }
757
758 if (dquot->dq_isoftlimit &&
759 (dquot->dq_curinodes + inodes) > dquot->dq_isoftlimit &&
760 dquot->dq_itime && CURRENT_TIME >= dquot->dq_itime &&
761 !ignore_hardlimit(dquot)) {
762 *warntype = ISOFTLONGWARN;
763 return NO_QUOTA;
764 }
765
766 if (dquot->dq_isoftlimit &&
767 (dquot->dq_curinodes + inodes) > dquot->dq_isoftlimit &&
768 dquot->dq_itime == 0) {
769 *warntype = ISOFTWARN;
770 dquot->dq_itime = CURRENT_TIME + dquot->dq_sb->s_dquot.inode_expire[dquot->dq_type];
771 }
772
773 return QUOTA_OK;
774}
775
776static int check_bdq(struct dquot *dquot, ulong blocks, char prealloc, char *warntype)
777{
778 *warntype = 0;
779 if (blocks <= 0 || dquot->dq_flags & DQ_FAKE)
780 return QUOTA_OK;
781
782 if (dquot->dq_bhardlimit &&
783 (dquot->dq_curblocks + blocks) > dquot->dq_bhardlimit &&
784 !ignore_hardlimit(dquot)) {
785 if (!prealloc)
786 *warntype = BHARDWARN;
787 return NO_QUOTA;
788 }
789
790 if (dquot->dq_bsoftlimit &&
791 (dquot->dq_curblocks + blocks) > dquot->dq_bsoftlimit &&
792 dquot->dq_btime && CURRENT_TIME >= dquot->dq_btime &&
793 !ignore_hardlimit(dquot)) {
794 if (!prealloc)
795 *warntype = BSOFTLONGWARN;
796 return NO_QUOTA;
797 }
798
799 if (dquot->dq_bsoftlimit &&
800 (dquot->dq_curblocks + blocks) > dquot->dq_bsoftlimit &&
801 dquot->dq_btime == 0) {
802 if (!prealloc) {
803 *warntype = BSOFTWARN;
804 dquot->dq_btime = CURRENT_TIME + dquot->dq_sb->s_dquot.block_expire[dquot->dq_type];
805 }
806 else
807
808
809
810
811 return NO_QUOTA;
812 }
813
814 return QUOTA_OK;
815}
816
817
818
819
820
821static int set_dqblk(struct super_block *sb, int id, short type, int flags, struct dqblk *dqblk)
822{
823 struct dquot *dquot;
824 int error = -EFAULT;
825 struct dqblk dq_dqblk;
826
827 if (copy_from_user(&dq_dqblk, dqblk, sizeof(struct dqblk)))
828 return error;
829
830 if (sb && (dquot = dqget(sb, id, type)) != NODQUOT) {
831
832 if (id > 0 && ((flags & SET_QUOTA) || (flags & SET_QLIMIT))) {
833 dquot->dq_bhardlimit = dq_dqblk.dqb_bhardlimit;
834 dquot->dq_bsoftlimit = dq_dqblk.dqb_bsoftlimit;
835 dquot->dq_ihardlimit = dq_dqblk.dqb_ihardlimit;
836 dquot->dq_isoftlimit = dq_dqblk.dqb_isoftlimit;
837 }
838
839 if ((flags & SET_QUOTA) || (flags & SET_USE)) {
840 if (dquot->dq_isoftlimit &&
841 dquot->dq_curinodes < dquot->dq_isoftlimit &&
842 dq_dqblk.dqb_curinodes >= dquot->dq_isoftlimit)
843 dquot->dq_itime = CURRENT_TIME + dquot->dq_sb->s_dquot.inode_expire[type];
844 dquot->dq_curinodes = dq_dqblk.dqb_curinodes;
845 if (dquot->dq_curinodes < dquot->dq_isoftlimit)
846 dquot->dq_flags &= ~DQ_INODES;
847 if (dquot->dq_bsoftlimit &&
848 dquot->dq_curblocks < dquot->dq_bsoftlimit &&
849 dq_dqblk.dqb_curblocks >= dquot->dq_bsoftlimit)
850 dquot->dq_btime = CURRENT_TIME + dquot->dq_sb->s_dquot.block_expire[type];
851 dquot->dq_curblocks = dq_dqblk.dqb_curblocks;
852 if (dquot->dq_curblocks < dquot->dq_bsoftlimit)
853 dquot->dq_flags &= ~DQ_BLKS;
854 }
855
856 if (id == 0) {
857 dquot->dq_sb->s_dquot.block_expire[type] = dquot->dq_btime = dq_dqblk.dqb_btime;
858 dquot->dq_sb->s_dquot.inode_expire[type] = dquot->dq_itime = dq_dqblk.dqb_itime;
859 }
860
861 if (dq_dqblk.dqb_bhardlimit == 0 && dq_dqblk.dqb_bsoftlimit == 0 &&
862 dq_dqblk.dqb_ihardlimit == 0 && dq_dqblk.dqb_isoftlimit == 0)
863 dquot->dq_flags |= DQ_FAKE;
864 else
865 dquot->dq_flags &= ~DQ_FAKE;
866
867 dquot->dq_flags |= DQ_MOD;
868 dqput(dquot);
869 }
870 return 0;
871}
872
873static int get_quota(struct super_block *sb, int id, short type, struct dqblk *dqblk)
874{
875 struct dquot *dquot;
876 struct dqblk data;
877 int error = -ESRCH;
878
879 if (!sb || !sb_has_quota_enabled(sb, type))
880 goto out;
881 dquot = dqget(sb, id, type);
882 if (dquot == NODQUOT)
883 goto out;
884
885 memcpy(&data, &dquot->dq_dqb, sizeof(struct dqblk));
886 dqput(dquot);
887 error = -EFAULT;
888 if (dqblk && !copy_to_user(dqblk, &data, sizeof(struct dqblk)))
889 error = 0;
890out:
891 return error;
892}
893
894static int get_stats(caddr_t addr)
895{
896 int error = -EFAULT;
897 struct dqstats stats;
898
899 dqstats.allocated_dquots = nr_dquots;
900 dqstats.free_dquots = nr_free_dquots;
901
902
903 memcpy(&stats, &dqstats, sizeof(struct dqstats));
904 if (!copy_to_user(addr, &stats, sizeof(struct dqstats)))
905 error = 0;
906 return error;
907}
908
909static int quota_root_squash(struct super_block *sb, short type, int *addr)
910{
911 int new_value, error;
912
913 if (!sb)
914 return(-ENODEV);
915
916 error = -EFAULT;
917 if (!copy_from_user(&new_value, addr, sizeof(int))) {
918 sb_dqopt(sb)->rsquash[type] = new_value;
919 error = 0;
920 }
921 return error;
922}
923
924#if 0
925
926
927
928
929static u_long isize_to_blocks(loff_t isize, size_t blksize_bits)
930{
931 u_long blocks;
932 u_long indirect;
933
934 if (!blksize_bits)
935 blksize_bits = BLOCK_SIZE_BITS;
936 blocks = (isize >> blksize_bits) + ((isize & ~((1 << blksize_bits)-1)) ? 1 : 0);
937 if (blocks > 10) {
938 indirect = ((blocks - 11) >> 8) + 1;
939 if (blocks > (10 + 256)) {
940 indirect += ((blocks - 267) >> 16) + 1;
941 if (blocks > (10 + 256 + (256 << 8)))
942 indirect++;
943 }
944 blocks += indirect;
945 }
946 return blocks;
947}
948#endif
949
950
951
952
953
954
955void dquot_initialize(struct inode *inode, short type)
956{
957 struct dquot *dquot[MAXQUOTAS];
958 unsigned int id = 0;
959 short cnt;
960
961 if (IS_NOQUOTA(inode))
962 return;
963
964 for (cnt = 0; cnt < MAXQUOTAS; cnt++) {
965 dquot[cnt] = NODQUOT;
966 if (type != -1 && cnt != type)
967 continue;
968 if (!sb_has_quota_enabled(inode->i_sb, cnt))
969 continue;
970 if (inode->i_dquot[cnt] == NODQUOT) {
971 switch (cnt) {
972 case USRQUOTA:
973 id = inode->i_uid;
974 break;
975 case GRPQUOTA:
976 id = inode->i_gid;
977 break;
978 }
979 dquot[cnt] = dqget(inode->i_sb, id, cnt);
980 }
981 }
982
983 for (cnt = 0; cnt < MAXQUOTAS; cnt++) {
984 if (dquot[cnt] == NODQUOT || !sb_has_quota_enabled(inode->i_sb, cnt) || inode->i_dquot[cnt] != NODQUOT)
985 continue;
986 inode->i_dquot[cnt] = dquot[cnt];
987 dquot[cnt] = NODQUOT;
988 inode->i_flags |= S_QUOTA;
989 }
990
991
992 for (cnt = 0; cnt < MAXQUOTAS; cnt++)
993 if (dquot[cnt] != NODQUOT)
994 dqput(dquot[cnt]);
995}
996
997
998
999
1000
1001
1002void dquot_drop(struct inode *inode)
1003{
1004 struct dquot *dquot;
1005 short cnt;
1006
1007 inode->i_flags &= ~S_QUOTA;
1008 for (cnt = 0; cnt < MAXQUOTAS; cnt++) {
1009 if (inode->i_dquot[cnt] == NODQUOT)
1010 continue;
1011 dquot = inode->i_dquot[cnt];
1012 inode->i_dquot[cnt] = NODQUOT;
1013 dqput(dquot);
1014 }
1015}
1016
1017
1018
1019
1020int dquot_alloc_block(struct inode *inode, unsigned long number, char warn)
1021{
1022 int cnt, ret = NO_QUOTA;
1023 struct dquot *dquot[MAXQUOTAS];
1024 char warntype[MAXQUOTAS];
1025
1026 for (cnt = 0; cnt < MAXQUOTAS; cnt++) {
1027 dquot[cnt] = NODQUOT;
1028 warntype[cnt] = NOWARN;
1029 }
1030
1031 for (cnt = 0; cnt < MAXQUOTAS; cnt++) {
1032 dquot[cnt] = dqduplicate(inode->i_dquot[cnt]);
1033 if (dquot[cnt] == NODQUOT)
1034 continue;
1035 if (check_bdq(dquot[cnt], number, warn, warntype+cnt) == NO_QUOTA)
1036 goto warn_put_all;
1037 }
1038 for (cnt = 0; cnt < MAXQUOTAS; cnt++) {
1039 if (dquot[cnt] == NODQUOT)
1040 continue;
1041 dquot_incr_blocks(dquot[cnt], number);
1042 }
1043 inode->i_blocks += number << (BLOCK_SIZE_BITS - 9);
1044
1045 ret = QUOTA_OK;
1046warn_put_all:
1047 flush_warnings(dquot, warntype);
1048 for (cnt = 0; cnt < MAXQUOTAS; cnt++)
1049 if (dquot[cnt] != NODQUOT)
1050 dqput(dquot[cnt]);
1051 return ret;
1052}
1053
1054
1055
1056
1057int dquot_alloc_inode(const struct inode *inode, unsigned long number)
1058{
1059 int cnt, ret = NO_QUOTA;
1060 struct dquot *dquot[MAXQUOTAS];
1061 char warntype[MAXQUOTAS];
1062
1063 for (cnt = 0; cnt < MAXQUOTAS; cnt++) {
1064 dquot[cnt] = NODQUOT;
1065 warntype[cnt] = NOWARN;
1066 }
1067
1068 for (cnt = 0; cnt < MAXQUOTAS; cnt++) {
1069 dquot[cnt] = dqduplicate(inode -> i_dquot[cnt]);
1070 if (dquot[cnt] == NODQUOT)
1071 continue;
1072 if (check_idq(dquot[cnt], number, warntype+cnt) == NO_QUOTA)
1073 goto warn_put_all;
1074 }
1075
1076 for (cnt = 0; cnt < MAXQUOTAS; cnt++) {
1077 if (dquot[cnt] == NODQUOT)
1078 continue;
1079 dquot_incr_inodes(dquot[cnt], number);
1080 }
1081
1082 ret = QUOTA_OK;
1083warn_put_all:
1084 flush_warnings(dquot, warntype);
1085 for (cnt = 0; cnt < MAXQUOTAS; cnt++)
1086 if (dquot[cnt] != NODQUOT)
1087 dqput(dquot[cnt]);
1088 return ret;
1089}
1090
1091
1092
1093
1094void dquot_free_block(struct inode *inode, unsigned long number)
1095{
1096 unsigned short cnt;
1097 struct dquot *dquot;
1098
1099
1100 for (cnt = 0; cnt < MAXQUOTAS; cnt++) {
1101 dquot = dqduplicate(inode->i_dquot[cnt]);
1102 if (dquot == NODQUOT)
1103 continue;
1104 dquot_decr_blocks(dquot, number);
1105 dqput(dquot);
1106 }
1107 inode->i_blocks -= number << (BLOCK_SIZE_BITS - 9);
1108
1109}
1110
1111
1112
1113
1114void dquot_free_inode(const struct inode *inode, unsigned long number)
1115{
1116 unsigned short cnt;
1117 struct dquot *dquot;
1118
1119
1120 for (cnt = 0; cnt < MAXQUOTAS; cnt++) {
1121 dquot = dqduplicate(inode->i_dquot[cnt]);
1122 if (dquot == NODQUOT)
1123 continue;
1124 dquot_decr_inodes(dquot, number);
1125 dqput(dquot);
1126 }
1127
1128}
1129
1130
1131
1132
1133
1134
1135int dquot_transfer(struct inode *inode, struct iattr *iattr)
1136{
1137 unsigned long blocks;
1138 struct dquot *transfer_from[MAXQUOTAS];
1139 struct dquot *transfer_to[MAXQUOTAS];
1140 int cnt, ret = NO_QUOTA, chuid = (iattr->ia_valid & ATTR_UID) && inode->i_uid != iattr->ia_uid,
1141 chgid = (iattr->ia_valid & ATTR_GID) && inode->i_gid != iattr->ia_gid;
1142 char warntype[MAXQUOTAS];
1143
1144
1145 for (cnt = 0; cnt < MAXQUOTAS; cnt++) {
1146 transfer_to[cnt] = transfer_from[cnt] = NODQUOT;
1147 warntype[cnt] = NOWARN;
1148 }
1149
1150 for (cnt = 0; cnt < MAXQUOTAS; cnt++) {
1151 if (!sb_has_quota_enabled(inode->i_sb, cnt))
1152 continue;
1153 switch (cnt) {
1154 case USRQUOTA:
1155 if (!chuid)
1156 continue;
1157 transfer_to[cnt] = dqget(inode->i_sb, iattr->ia_uid, cnt);
1158 break;
1159 case GRPQUOTA:
1160 if (!chgid)
1161 continue;
1162 transfer_to[cnt] = dqget(inode->i_sb, iattr->ia_gid, cnt);
1163 break;
1164 }
1165 }
1166
1167 blocks = (inode->i_blocks >> 1);
1168
1169 for (cnt = 0; cnt < MAXQUOTAS; cnt++) {
1170
1171 if (transfer_to[cnt] == NODQUOT || !sb_has_quota_enabled(inode->i_sb, cnt))
1172 continue;
1173 transfer_from[cnt] = dqduplicate(inode->i_dquot[cnt]);
1174 if (transfer_from[cnt] == NODQUOT)
1175 continue;
1176 if (check_idq(transfer_to[cnt], 1, warntype+cnt) == NO_QUOTA ||
1177 check_bdq(transfer_to[cnt], blocks, 0, warntype+cnt) == NO_QUOTA)
1178 goto warn_put_all;
1179 }
1180
1181
1182
1183
1184 for (cnt = 0; cnt < MAXQUOTAS; cnt++) {
1185
1186
1187
1188 if (transfer_from[cnt] == NODQUOT || transfer_to[cnt] == NODQUOT)
1189 continue;
1190
1191 dquot_decr_inodes(transfer_from[cnt], 1);
1192 dquot_decr_blocks(transfer_from[cnt], blocks);
1193
1194 dquot_incr_inodes(transfer_to[cnt], 1);
1195 dquot_incr_blocks(transfer_to[cnt], blocks);
1196
1197 if (inode->i_dquot[cnt] == NODQUOT)
1198 BUG();
1199 inode->i_dquot[cnt] = transfer_to[cnt];
1200
1201
1202
1203
1204 transfer_to[cnt] = transfer_from[cnt];
1205 }
1206
1207 ret = QUOTA_OK;
1208warn_put_all:
1209 flush_warnings(transfer_to, warntype);
1210 for (cnt = 0; cnt < MAXQUOTAS; cnt++) {
1211 if (transfer_to[cnt] != NODQUOT)
1212 dqput(transfer_to[cnt]);
1213 if (transfer_from[cnt] != NODQUOT)
1214 dqput(transfer_from[cnt]);
1215 }
1216 return ret;
1217}
1218
1219static int __init dquot_init(void)
1220{
1221 int i;
1222
1223 for (i = 0; i < NR_DQHASH; i++)
1224 INIT_LIST_HEAD(dquot_hash + i);
1225 printk(KERN_NOTICE "VFS: Diskquotas version %s initialized\n", __DQUOT_VERSION__);
1226 return 0;
1227}
1228__initcall(dquot_init);
1229
1230
1231
1232
1233struct dquot_operations dquot_operations = {
1234 dquot_initialize,
1235 dquot_drop,
1236 dquot_alloc_block,
1237 dquot_alloc_inode,
1238 dquot_free_block,
1239 dquot_free_inode,
1240 dquot_transfer
1241};
1242
1243static inline void set_enable_flags(struct quota_mount_options *dqopt, short type)
1244{
1245 switch (type) {
1246 case USRQUOTA:
1247 dqopt->flags |= DQUOT_USR_ENABLED;
1248 break;
1249 case GRPQUOTA:
1250 dqopt->flags |= DQUOT_GRP_ENABLED;
1251 break;
1252 }
1253}
1254
1255static inline void reset_enable_flags(struct quota_mount_options *dqopt, short type)
1256{
1257 switch (type) {
1258 case USRQUOTA:
1259 dqopt->flags &= ~DQUOT_USR_ENABLED;
1260 break;
1261 case GRPQUOTA:
1262 dqopt->flags &= ~DQUOT_GRP_ENABLED;
1263 break;
1264 }
1265}
1266
1267
1268extern void remove_dquot_ref(struct super_block *, short);
1269
1270
1271
1272
1273int quota_off(struct super_block *sb, short type)
1274{
1275 struct file *filp;
1276 short cnt;
1277 struct quota_mount_options *dqopt = sb_dqopt(sb);
1278
1279 lock_kernel();
1280 if (!sb)
1281 goto out;
1282
1283
1284 down(&dqopt->dqoff_sem);
1285 for (cnt = 0; cnt < MAXQUOTAS; cnt++) {
1286 if (type != -1 && cnt != type)
1287 continue;
1288 if (!is_enabled(dqopt, cnt))
1289 continue;
1290 reset_enable_flags(dqopt, cnt);
1291
1292
1293 remove_dquot_ref(sb, cnt);
1294 invalidate_dquots(sb, cnt);
1295
1296 filp = dqopt->files[cnt];
1297 dqopt->files[cnt] = (struct file *)NULL;
1298 dqopt->inode_expire[cnt] = 0;
1299 dqopt->block_expire[cnt] = 0;
1300 fput(filp);
1301 }
1302 up(&dqopt->dqoff_sem);
1303out:
1304 unlock_kernel();
1305 return 0;
1306}
1307
1308static inline int check_quotafile_size(loff_t size)
1309{
1310 ulong blocks = size >> BLOCK_SIZE_BITS;
1311 size_t off = size & (BLOCK_SIZE - 1);
1312
1313 return !(((blocks % sizeof(struct dqblk)) * BLOCK_SIZE + off % sizeof(struct dqblk)) % sizeof(struct dqblk));
1314}
1315
1316static int quota_on(struct super_block *sb, short type, char *path)
1317{
1318 struct file *f;
1319 struct inode *inode;
1320 struct dquot *dquot;
1321 struct quota_mount_options *dqopt = sb_dqopt(sb);
1322 char *tmp;
1323 int error;
1324
1325 if (is_enabled(dqopt, type))
1326 return -EBUSY;
1327
1328 down(&dqopt->dqoff_sem);
1329 tmp = getname(path);
1330 error = PTR_ERR(tmp);
1331 if (IS_ERR(tmp))
1332 goto out_lock;
1333
1334 f = filp_open(tmp, O_RDWR, 0600);
1335 putname(tmp);
1336
1337 error = PTR_ERR(f);
1338 if (IS_ERR(f))
1339 goto out_lock;
1340 error = -EIO;
1341 if (!f->f_op || !f->f_op->read || !f->f_op->write)
1342 goto out_f;
1343 inode = f->f_dentry->d_inode;
1344 error = -EACCES;
1345 if (!S_ISREG(inode->i_mode))
1346 goto out_f;
1347 error = -EINVAL;
1348 if (inode->i_size == 0 || !check_quotafile_size(inode->i_size))
1349 goto out_f;
1350
1351 dquot_drop(inode);
1352 inode->i_flags |= S_NOQUOTA;
1353
1354 dqopt->files[type] = f;
1355 sb->dq_op = &dquot_operations;
1356 set_enable_flags(dqopt, type);
1357
1358 dquot = dqget(sb, 0, type);
1359 dqopt->inode_expire[type] = (dquot != NODQUOT) ? dquot->dq_itime : MAX_IQ_TIME;
1360 dqopt->block_expire[type] = (dquot != NODQUOT) ? dquot->dq_btime : MAX_DQ_TIME;
1361 dqput(dquot);
1362
1363 add_dquot_ref(sb, type);
1364
1365 up(&dqopt->dqoff_sem);
1366 return 0;
1367
1368out_f:
1369 filp_close(f, NULL);
1370out_lock:
1371 up(&dqopt->dqoff_sem);
1372
1373 return error;
1374}
1375
1376
1377
1378
1379
1380
1381
1382asmlinkage long sys_quotactl(int cmd, const char *special, int id, caddr_t addr)
1383{
1384 int cmds = 0, type = 0, flags = 0;
1385 kdev_t dev;
1386 struct super_block *sb = NULL;
1387 int ret = -EINVAL;
1388
1389 lock_kernel();
1390 cmds = cmd >> SUBCMDSHIFT;
1391 type = cmd & SUBCMDMASK;
1392
1393 if ((u_int) type >= MAXQUOTAS)
1394 goto out;
1395 if (id & ~0xFFFF)
1396 goto out;
1397
1398 ret = -EPERM;
1399 switch (cmds) {
1400 case Q_SYNC:
1401 case Q_GETSTATS:
1402 break;
1403 case Q_GETQUOTA:
1404 if (((type == USRQUOTA && current->euid != id) ||
1405 (type == GRPQUOTA && !in_egroup_p(id))) &&
1406 !capable(CAP_SYS_ADMIN))
1407 goto out;
1408 break;
1409 default:
1410 if (!capable(CAP_SYS_ADMIN))
1411 goto out;
1412 }
1413
1414 ret = -EINVAL;
1415 dev = NODEV;
1416 if (special != NULL || (cmds != Q_SYNC && cmds != Q_GETSTATS)) {
1417 mode_t mode;
1418 struct nameidata nd;
1419
1420 ret = user_path_walk(special, &nd);
1421 if (ret)
1422 goto out;
1423
1424 dev = nd.dentry->d_inode->i_rdev;
1425 mode = nd.dentry->d_inode->i_mode;
1426 path_release(&nd);
1427
1428 ret = -ENOTBLK;
1429 if (!S_ISBLK(mode))
1430 goto out;
1431 ret = -ENODEV;
1432 sb = get_super(dev);
1433 if (!sb)
1434 goto out;
1435 }
1436
1437 ret = -EINVAL;
1438 switch (cmds) {
1439 case Q_QUOTAON:
1440 ret = quota_on(sb, type, (char *) addr);
1441 goto out;
1442 case Q_QUOTAOFF:
1443 ret = quota_off(sb, type);
1444 goto out;
1445 case Q_GETQUOTA:
1446 ret = get_quota(sb, id, type, (struct dqblk *) addr);
1447 goto out;
1448 case Q_SETQUOTA:
1449 flags |= SET_QUOTA;
1450 break;
1451 case Q_SETUSE:
1452 flags |= SET_USE;
1453 break;
1454 case Q_SETQLIM:
1455 flags |= SET_QLIMIT;
1456 break;
1457 case Q_SYNC:
1458 ret = sync_dquots(dev, type);
1459 goto out;
1460 case Q_GETSTATS:
1461 ret = get_stats(addr);
1462 goto out;
1463 case Q_RSQUASH:
1464 ret = quota_root_squash(sb, type, (int *) addr);
1465 goto out;
1466 default:
1467 goto out;
1468 }
1469
1470 ret = -NODEV;
1471 if (sb && sb_has_quota_enabled(sb, type))
1472 ret = set_dqblk(sb, id, type, flags, (struct dqblk *) addr);
1473out:
1474 if (sb)
1475 drop_super(sb);
1476 unlock_kernel();
1477 return ret;
1478}
1479