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