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