2 * Implementation of the diskquota system for the LINUX operating
3 * system. QUOTA is implemented using the BSD system call interface as
4 * the means of communication with the user level. Currently only the
5 * ext2 filesystem has support for disk quotas. Other filesystems may
6 * be added in the future. This file contains the generic routines
7 * called by the different filesystems on allocation of an inode or
8 * block. These routines take care of the administration needed to
9 * have a consistent diskquota tracking system. The ideas of both
10 * user and group quotas are based on the Melbourne quota system as
11 * used on BSD derived systems. The internal implementation is
12 * based on one of the several variants of the LINUX inode-subsystem
13 * with added complexity of the diskquota system.
15 * Version: $Id: dquot.c,v 6.3 1996/11/17 18:35:34 mvw Exp mvw $
17 * Author: Marco van Wieringen <mvw@planets.elm.net>
19 * Fixes: Dmitry Gorodchanin <pgmdsg@ibi.com>, 11 Feb 96
21 * Revised list management to avoid races
22 * -- Bill Hawes, <whawes@star.net>, 9/98
24 * Fixed races in dquot_transfer(), dqget() and dquot_alloc_...().
25 * As the consequence the locking was moved from dquot_decr_...(),
26 * dquot_incr_...() to calling functions.
27 * invalidate_dquots() now writes modified dquots.
28 * Serialized quota_off() and quota_on() for mount point.
29 * Fixed a few bugs in grow_dquots().
30 * Fixed deadlock in write_dquot() - we no longer account quotas on
32 * remove_dquot_ref() moved to inode.c - it now traverses through inodes
33 * add_dquot_ref() restarts after blocking
34 * Added check for bogus uid and fixed check for group in quotactl.
35 * Jan Kara, <jack@suse.cz>, sponsored by SuSE CR, 10-11/99
37 * Used struct list_head instead of own list struct
38 * Invalidation of referenced dquots is no longer possible
39 * Improved free_dquots list management
40 * Quota and i_blocks are now updated in one place to avoid races
41 * Warnings are now delayed so we won't block in critical section
42 * Write updated not to require dquot lock
43 * Jan Kara, <jack@suse.cz>, 9/2000
45 * Added dynamic quota structure allocation
46 * Jan Kara <jack@suse.cz> 12/2000
48 * Rewritten quota interface. Implemented new quota format and
49 * formats registering.
50 * Jan Kara, <jack@suse.cz>, 2001,2002
52 * (C) Copyright 1994 - 1997 Marco van Wieringen
55 #include <linux/errno.h>
56 #include <linux/kernel.h>
59 #include <linux/time.h>
60 #include <linux/types.h>
61 #include <linux/string.h>
62 #include <linux/fcntl.h>
63 #include <linux/stat.h>
64 #include <linux/tty.h>
65 #include <linux/file.h>
66 #include <linux/slab.h>
67 #include <linux/sysctl.h>
68 #include <linux/smp_lock.h>
69 #include <linux/init.h>
70 #include <linux/module.h>
71 #include <linux/proc_fs.h>
73 #include <asm/uaccess.h>
75 static char *quotatypes
[] = INITQFNAMES
;
76 static struct quota_format_type
*quota_formats
; /* List of registered formats */
78 int register_quota_format(struct quota_format_type
*fmt
)
81 fmt
->qf_next
= quota_formats
;
87 void unregister_quota_format(struct quota_format_type
*fmt
)
89 struct quota_format_type
**actqf
;
92 for (actqf
= "a_formats
; *actqf
&& *actqf
!= fmt
; actqf
= &(*actqf
)->qf_next
);
94 *actqf
= (*actqf
)->qf_next
;
98 static struct quota_format_type
*find_quota_format(int id
)
100 struct quota_format_type
*actqf
;
103 for (actqf
= quota_formats
; actqf
&& actqf
->qf_fmt_id
!= id
; actqf
= actqf
->qf_next
);
104 if (actqf
&& !try_inc_mod_count(actqf
->qf_owner
))
110 static void put_quota_format(struct quota_format_type
*fmt
)
113 __MOD_DEC_USE_COUNT(fmt
->qf_owner
);
117 * Dquot List Management:
118 * The quota code uses three lists for dquot management: the inuse_list,
119 * free_dquots, and dquot_hash[] array. A single dquot structure may be
120 * on all three lists, depending on its current state.
122 * All dquots are placed to the end of inuse_list when first created, and this
123 * list is used for the sync and invalidate operations, which must look
126 * Unused dquots (dq_count == 0) are added to the free_dquots list when freed,
127 * and this list is searched whenever we need an available dquot. Dquots are
128 * removed from the list as soon as they are used again, and
129 * dqstats.free_dquots gives the number of dquots on the list. When
130 * dquot is invalidated it's completely released from memory.
132 * Dquots with a specific identity (device, type and id) are placed on
133 * one of the dquot_hash[] hash chains. The provides an efficient search
134 * mechanism to locate a specific dquot.
138 * Note that any operation which operates on dquot data (ie. dq_dqb) mustn't
139 * block while it's updating/reading it. Otherwise races would occur.
141 * Locked dquots might not be referenced in inodes - operations like
142 * add_dquot_space() does dqduplicate() and would complain. Currently
143 * dquot it locked only once in its existence - when it's being read
144 * to memory on first dqget() and at that time it can't be referenced
145 * from inode. Write operations on dquots don't hold dquot lock as they
146 * copy data to internal buffers before writing anyway and copying as well
147 * as any data update should be atomic. Also nobody can change used
148 * entries in dquot structure as this is done only when quota is destroyed
149 * and invalidate_dquots() waits for dquot to have dq_count == 0.
152 static LIST_HEAD(inuse_list
);
153 static LIST_HEAD(free_dquots
);
154 static struct list_head dquot_hash
[NR_DQHASH
];
156 struct dqstats dqstats
;
158 static void dqput(struct dquot
*);
159 static struct dquot
*dqduplicate(struct dquot
*);
161 static inline void get_dquot_ref(struct dquot
*dquot
)
166 static inline void put_dquot_ref(struct dquot
*dquot
)
171 static inline void get_dquot_dup_ref(struct dquot
*dquot
)
176 static inline void put_dquot_dup_ref(struct dquot
*dquot
)
181 static inline int const hashfn(struct super_block
*sb
, unsigned int id
, int type
)
183 return((((unsigned long)sb
>>L1_CACHE_SHIFT
) ^ id
) * (MAXQUOTAS
- type
)) % NR_DQHASH
;
186 static inline void insert_dquot_hash(struct dquot
*dquot
)
188 struct list_head
*head
= dquot_hash
+ hashfn(dquot
->dq_sb
, dquot
->dq_id
, dquot
->dq_type
);
189 list_add(&dquot
->dq_hash
, head
);
192 static inline void remove_dquot_hash(struct dquot
*dquot
)
194 list_del_init(&dquot
->dq_hash
);
197 static inline struct dquot
*find_dquot(unsigned int hashent
, struct super_block
*sb
, unsigned int id
, int type
)
199 struct list_head
*head
;
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
)
210 /* Add a dquot to the head of the free list */
211 static inline void put_dquot_head(struct dquot
*dquot
)
213 list_add(&dquot
->dq_free
, &free_dquots
);
214 dqstats
.free_dquots
++;
217 /* Add a dquot to the tail of the free list */
218 static inline void put_dquot_last(struct dquot
*dquot
)
220 list_add(&dquot
->dq_free
, free_dquots
.prev
);
221 dqstats
.free_dquots
++;
224 /* Move dquot to the head of free list (it must be already on it) */
225 static inline void move_dquot_head(struct dquot
*dquot
)
227 list_del(&dquot
->dq_free
);
228 list_add(&dquot
->dq_free
, &free_dquots
);
231 static inline void remove_free_dquot(struct dquot
*dquot
)
233 if (list_empty(&dquot
->dq_free
))
235 list_del_init(&dquot
->dq_free
);
236 dqstats
.free_dquots
--;
239 static inline void put_inuse(struct dquot
*dquot
)
241 /* We add to the back of inuse list so we don't have to restart
242 * when traversing this list and we block */
243 list_add(&dquot
->dq_inuse
, inuse_list
.prev
);
244 dqstats
.allocated_dquots
++;
247 static inline void remove_inuse(struct dquot
*dquot
)
249 dqstats
.allocated_dquots
--;
250 list_del(&dquot
->dq_inuse
);
253 static void __wait_on_dquot(struct dquot
*dquot
)
255 DECLARE_WAITQUEUE(wait
, current
);
257 add_wait_queue(&dquot
->dq_wait_lock
, &wait
);
259 set_current_state(TASK_UNINTERRUPTIBLE
);
260 if (dquot
->dq_flags
& DQ_LOCKED
) {
264 remove_wait_queue(&dquot
->dq_wait_lock
, &wait
);
265 current
->state
= TASK_RUNNING
;
268 static inline void wait_on_dquot(struct dquot
*dquot
)
270 if (dquot
->dq_flags
& DQ_LOCKED
)
271 __wait_on_dquot(dquot
);
274 static inline void lock_dquot(struct dquot
*dquot
)
276 wait_on_dquot(dquot
);
277 dquot
->dq_flags
|= DQ_LOCKED
;
280 static inline void unlock_dquot(struct dquot
*dquot
)
282 dquot
->dq_flags
&= ~DQ_LOCKED
;
283 wake_up(&dquot
->dq_wait_lock
);
286 /* Wait for dquot to be unused */
287 static void __wait_dquot_unused(struct dquot
*dquot
)
289 DECLARE_WAITQUEUE(wait
, current
);
291 add_wait_queue(&dquot
->dq_wait_free
, &wait
);
293 set_current_state(TASK_UNINTERRUPTIBLE
);
294 if (dquot
->dq_count
) {
298 remove_wait_queue(&dquot
->dq_wait_free
, &wait
);
299 current
->state
= TASK_RUNNING
;
302 /* Wait for all duplicated dquot references to be dropped */
303 static void __wait_dup_drop(struct dquot
*dquot
)
305 DECLARE_WAITQUEUE(wait
, current
);
307 add_wait_queue(&dquot
->dq_wait_free
, &wait
);
309 set_current_state(TASK_UNINTERRUPTIBLE
);
310 if (dquot
->dq_dup_ref
) {
314 remove_wait_queue(&dquot
->dq_wait_free
, &wait
);
315 current
->state
= TASK_RUNNING
;
318 static int read_dqblk(struct dquot
*dquot
)
321 struct quota_info
*dqopt
= sb_dqopt(dquot
->dq_sb
);
324 down(&dqopt
->dqio_sem
);
325 ret
= dqopt
->ops
[dquot
->dq_type
]->read_dqblk(dquot
);
326 up(&dqopt
->dqio_sem
);
331 static int commit_dqblk(struct dquot
*dquot
)
334 struct quota_info
*dqopt
= sb_dqopt(dquot
->dq_sb
);
336 down(&dqopt
->dqio_sem
);
337 ret
= dqopt
->ops
[dquot
->dq_type
]->commit_dqblk(dquot
);
338 up(&dqopt
->dqio_sem
);
342 /* Invalidate all dquots on the list, wait for all users. Note that this function is called
343 * after quota is disabled so no new quota might be created. As we only insert to the end of
344 * inuse list, we don't have to restart searching... */
345 static void invalidate_dquots(struct super_block
*sb
, int type
)
348 struct list_head
*head
;
351 list_for_each(head
, &inuse_list
) {
352 dquot
= list_entry(head
, struct dquot
, dq_inuse
);
353 if (dquot
->dq_sb
!= sb
)
355 if (dquot
->dq_type
!= type
)
357 dquot
->dq_flags
|= DQ_INVAL
;
360 * Wait for any users of quota. As we have already cleared the flags in
361 * superblock and cleared all pointers from inodes we are assured
362 * that there will be no new users of this quota.
364 __wait_dquot_unused(dquot
);
365 /* Quota now have no users and it has been written on last dqput() */
366 remove_dquot_hash(dquot
);
367 remove_free_dquot(dquot
);
369 kmem_cache_free(dquot_cachep
, dquot
);
374 static int vfs_quota_sync(struct super_block
*sb
, int type
)
376 struct list_head
*head
;
378 struct quota_info
*dqopt
= sb_dqopt(sb
);
382 list_for_each(head
, &inuse_list
) {
383 dquot
= list_entry(head
, struct dquot
, dq_inuse
);
384 if (sb
&& dquot
->dq_sb
!= sb
)
386 if (type
!= -1 && dquot
->dq_type
!= type
)
388 if (!dquot
->dq_sb
) /* Invalidated? */
390 if (!dquot_dirty(dquot
) && !(dquot
->dq_flags
& DQ_LOCKED
))
392 /* Get reference to quota so it won't be invalidated. get_dquot_ref()
393 * is enough since if dquot is locked/modified it can't be
394 * on the free list */
395 get_dquot_ref(dquot
);
396 if (dquot
->dq_flags
& DQ_LOCKED
)
397 wait_on_dquot(dquot
);
398 if (dquot_dirty(dquot
))
403 for (cnt
= 0; cnt
< MAXQUOTAS
; cnt
++)
404 if ((cnt
== type
|| type
== -1) && sb_has_quota_enabled(sb
, cnt
))
405 dqopt
->info
[cnt
].dqi_flags
&= ~DQF_ANY_DQUOT_DIRTY
;
406 for (cnt
= 0; cnt
< MAXQUOTAS
; cnt
++)
407 if ((cnt
== type
|| type
== -1) && sb_has_quota_enabled(sb
, cnt
) && info_dirty(&dqopt
->info
[cnt
]))
408 dqopt
->ops
[cnt
]->write_file_info(sb
, cnt
);
414 static struct super_block
*get_super_to_sync(int type
)
416 struct list_head
*head
;
421 list_for_each(head
, &super_blocks
) {
422 struct super_block
*sb
= list_entry(head
, struct super_block
, s_list
);
424 for (cnt
= 0, dirty
= 0; cnt
< MAXQUOTAS
; cnt
++)
425 if ((type
== cnt
|| type
== -1) && sb_has_quota_enabled(sb
, cnt
)
426 && sb_dqopt(sb
)->info
[cnt
].dqi_flags
& DQF_ANY_DQUOT_DIRTY
)
431 spin_unlock(&sb_lock
);
432 down_read(&sb
->s_umount
);
439 spin_unlock(&sb_lock
);
443 void sync_dquots(struct super_block
*sb
, int type
)
447 if (sb
->s_qcop
->quota_sync
)
448 sb
->s_qcop
->quota_sync(sb
, type
);
452 while ((sb
= get_super_to_sync(type
))) {
454 if (sb
->s_qcop
->quota_sync
)
455 sb
->s_qcop
->quota_sync(sb
, type
);
462 /* Free unused dquots from cache */
463 static void prune_dqcache(int count
)
465 struct list_head
*head
;
468 head
= free_dquots
.prev
;
469 while (head
!= &free_dquots
&& count
) {
470 dquot
= list_entry(head
, struct dquot
, dq_free
);
471 remove_dquot_hash(dquot
);
472 remove_free_dquot(dquot
);
474 kmem_cache_free(dquot_cachep
, dquot
);
476 head
= free_dquots
.prev
;
481 * This is called from kswapd when we think we need some
485 static int shrink_dqcache_memory(int nr
, unsigned int gfp_mask
)
492 return dqstats
.allocated_dquots
;
496 * Put reference to dquot
497 * NOTE: If you change this function please check whether dqput_blocks() works right...
499 static void dqput(struct dquot
*dquot
)
503 #ifdef __DQUOT_PARANOIA
504 if (!dquot
->dq_count
) {
505 printk("VFS: dqput: trying to free free dquot\n");
506 printk("VFS: device %s, dquot of %s %d\n",
508 quotatypes
[dquot
->dq_type
],
516 if (dquot
->dq_dup_ref
&& dquot
->dq_count
- dquot
->dq_dup_ref
<= 1) { /* Last unduplicated reference? */
517 __wait_dup_drop(dquot
);
520 if (dquot
->dq_count
> 1) {
521 /* We have more than one user... We can simply decrement use count */
522 put_dquot_ref(dquot
);
525 if (dquot_dirty(dquot
)) {
531 if (!list_empty(&dquot
->dq_free
)) {
532 printk(KERN_ERR
"dqput: dquot already on free list??\n");
533 put_dquot_ref(dquot
);
536 put_dquot_ref(dquot
);
537 /* If dquot is going to be invalidated invalidate_dquots() is going to free it so */
538 if (!(dquot
->dq_flags
& DQ_INVAL
))
539 put_dquot_last(dquot
); /* Place at end of LRU free queue */
540 wake_up(&dquot
->dq_wait_free
);
543 static struct dquot
*get_empty_dquot(struct super_block
*sb
, int type
)
547 dquot
= kmem_cache_alloc(dquot_cachep
, SLAB_KERNEL
);
551 memset((caddr_t
)dquot
, 0, sizeof(struct dquot
));
552 init_waitqueue_head(&dquot
->dq_wait_free
);
553 init_waitqueue_head(&dquot
->dq_wait_lock
);
554 INIT_LIST_HEAD(&dquot
->dq_free
);
555 INIT_LIST_HEAD(&dquot
->dq_inuse
);
556 INIT_LIST_HEAD(&dquot
->dq_hash
);
558 dquot
->dq_type
= type
;
560 /* all dquots go on the inuse_list */
566 static struct dquot
*dqget(struct super_block
*sb
, unsigned int id
, int type
)
568 unsigned int hashent
= hashfn(sb
, id
, type
);
569 struct dquot
*dquot
, *empty
= NODQUOT
;
570 struct quota_info
*dqopt
= sb_dqopt(sb
);
573 if (!is_enabled(dqopt
, type
)) {
579 if ((dquot
= find_dquot(hashent
, sb
, id
, type
)) == NODQUOT
) {
580 if (empty
== NODQUOT
) {
581 if ((empty
= get_empty_dquot(sb
, type
)) == NODQUOT
)
582 schedule(); /* Try to wait for a moment... */
587 /* hash it first so it can be found */
588 insert_dquot_hash(dquot
);
591 if (!dquot
->dq_count
)
592 remove_free_dquot(dquot
);
593 get_dquot_ref(dquot
);
594 dqstats
.cache_hits
++;
595 wait_on_dquot(dquot
);
600 if (!dquot
->dq_sb
) { /* Has somebody invalidated entry under us? */
601 printk(KERN_ERR
"VFS: dqget(): Quota invalidated in dqget()!\n");
605 ++dquot
->dq_referenced
;
611 /* Duplicate reference to dquot got from inode */
612 static struct dquot
*dqduplicate(struct dquot
*dquot
)
614 if (dquot
== NODQUOT
)
616 get_dquot_ref(dquot
);
618 printk(KERN_ERR
"VFS: dqduplicate(): Invalidated quota to be duplicated!\n");
619 put_dquot_ref(dquot
);
622 if (dquot
->dq_flags
& DQ_LOCKED
)
623 printk(KERN_ERR
"VFS: dqduplicate(): Locked quota to be duplicated!\n");
624 get_dquot_dup_ref(dquot
);
625 dquot
->dq_referenced
++;
631 /* Put duplicated reference */
632 static void dqputduplicate(struct dquot
*dquot
)
634 if (!dquot
->dq_dup_ref
) {
635 printk(KERN_ERR
"VFS: dqputduplicate(): Duplicated dquot put without duplicate reference.\n");
638 put_dquot_dup_ref(dquot
);
639 if (!dquot
->dq_dup_ref
)
640 wake_up(&dquot
->dq_wait_free
);
641 put_dquot_ref(dquot
);
645 static int dqinit_needed(struct inode
*inode
, int type
)
649 if (IS_NOQUOTA(inode
))
652 return inode
->i_dquot
[type
] == NODQUOT
;
653 for (cnt
= 0; cnt
< MAXQUOTAS
; cnt
++)
654 if (inode
->i_dquot
[cnt
] == NODQUOT
)
659 static void add_dquot_ref(struct super_block
*sb
, int type
)
665 list_for_each(p
, &sb
->s_files
) {
666 struct file
*filp
= list_entry(p
, struct file
, f_list
);
667 struct inode
*inode
= filp
->f_dentry
->d_inode
;
668 if (filp
->f_mode
& FMODE_WRITE
&& dqinit_needed(inode
, type
)) {
669 struct vfsmount
*mnt
= mntget(filp
->f_vfsmnt
);
670 struct dentry
*dentry
= dget(filp
->f_dentry
);
672 sb
->dq_op
->initialize(inode
, type
);
675 /* As we may have blocked we had better restart... */
682 /* Return 0 if dqput() won't block (note that 1 doesn't necessarily mean blocking) */
683 static inline int dqput_blocks(struct dquot
*dquot
)
685 if (dquot
->dq_dup_ref
&& dquot
->dq_count
- dquot
->dq_dup_ref
<= 1)
687 if (dquot
->dq_count
<= 1 && dquot
->dq_flags
& DQ_MOD
)
692 /* Remove references to dquots from inode - add dquot to list for freeing if needed */
693 int remove_inode_dquot_ref(struct inode
*inode
, int type
, struct list_head
*tofree_head
)
695 struct dquot
*dquot
= inode
->i_dquot
[type
];
698 inode
->i_dquot
[type
] = NODQUOT
;
699 /* any other quota in use? */
700 for (cnt
= 0; cnt
< MAXQUOTAS
; cnt
++) {
701 if (inode
->i_dquot
[cnt
] != NODQUOT
)
704 inode
->i_flags
&= ~S_QUOTA
;
706 if (dquot
!= NODQUOT
) {
707 if (dqput_blocks(dquot
)) {
708 if (dquot
->dq_count
!= 1)
709 printk(KERN_WARNING
"VFS: Adding dquot with dq_count %d to dispose list.\n", dquot
->dq_count
);
710 list_add(&dquot
->dq_free
, tofree_head
); /* As dquot must have currently users it can't be on the free list... */
714 dqput(dquot
); /* We have guaranteed we won't block */
719 /* Free list of dquots - called from inode.c */
720 void put_dquot_list(struct list_head
*tofree_head
)
722 struct list_head
*act_head
;
726 act_head
= tofree_head
->next
;
727 /* So now we have dquots on the list... Just free them */
728 while (act_head
!= tofree_head
) {
729 dquot
= list_entry(act_head
, struct dquot
, dq_free
);
730 act_head
= act_head
->next
;
731 list_del_init(&dquot
->dq_free
); /* Remove dquot from the list so we won't have problems... */
737 static inline void dquot_incr_inodes(struct dquot
*dquot
, unsigned long number
)
739 dquot
->dq_dqb
.dqb_curinodes
+= number
;
740 mark_dquot_dirty(dquot
);
743 static inline void dquot_incr_space(struct dquot
*dquot
, qsize_t number
)
745 dquot
->dq_dqb
.dqb_curspace
+= number
;
746 mark_dquot_dirty(dquot
);
749 static inline void dquot_decr_inodes(struct dquot
*dquot
, unsigned long number
)
751 if (dquot
->dq_dqb
.dqb_curinodes
> number
)
752 dquot
->dq_dqb
.dqb_curinodes
-= number
;
754 dquot
->dq_dqb
.dqb_curinodes
= 0;
755 if (dquot
->dq_dqb
.dqb_curinodes
< dquot
->dq_dqb
.dqb_isoftlimit
)
756 dquot
->dq_dqb
.dqb_itime
= (time_t) 0;
757 dquot
->dq_flags
&= ~DQ_INODES
;
758 mark_dquot_dirty(dquot
);
761 static inline void dquot_decr_space(struct dquot
*dquot
, qsize_t number
)
763 if (dquot
->dq_dqb
.dqb_curspace
> number
)
764 dquot
->dq_dqb
.dqb_curspace
-= number
;
766 dquot
->dq_dqb
.dqb_curspace
= 0;
767 if (toqb(dquot
->dq_dqb
.dqb_curspace
) < dquot
->dq_dqb
.dqb_bsoftlimit
)
768 dquot
->dq_dqb
.dqb_btime
= (time_t) 0;
769 dquot
->dq_flags
&= ~DQ_BLKS
;
770 mark_dquot_dirty(dquot
);
773 static inline int need_print_warning(struct dquot
*dquot
, int flag
)
775 switch (dquot
->dq_type
) {
777 return current
->fsuid
== dquot
->dq_id
&& !(dquot
->dq_flags
& flag
);
779 return in_group_p(dquot
->dq_id
) && !(dquot
->dq_flags
& flag
);
784 /* Values of warnings */
787 #define ISOFTLONGWARN 2
790 #define BSOFTLONGWARN 5
793 /* Print warning to user which exceeded quota */
794 static void print_warning(struct dquot
*dquot
, const char warntype
)
797 int flag
= (warntype
== BHARDWARN
|| warntype
== BSOFTLONGWARN
) ? DQ_BLKS
:
798 ((warntype
== IHARDWARN
|| warntype
== ISOFTLONGWARN
) ? DQ_INODES
: 0);
800 if (!need_print_warning(dquot
, flag
))
802 dquot
->dq_flags
|= flag
;
803 tty_write_message(current
->tty
, dquot
->dq_sb
->s_id
);
804 if (warntype
== ISOFTWARN
|| warntype
== BSOFTWARN
)
805 tty_write_message(current
->tty
, ": warning, ");
807 tty_write_message(current
->tty
, ": write failed, ");
808 tty_write_message(current
->tty
, quotatypes
[dquot
->dq_type
]);
811 msg
= " file limit reached.\n";
814 msg
= " file quota exceeded too long.\n";
817 msg
= " file quota exceeded.\n";
820 msg
= " block limit reached.\n";
823 msg
= " block quota exceeded too long.\n";
826 msg
= " block quota exceeded.\n";
829 tty_write_message(current
->tty
, msg
);
832 static inline void flush_warnings(struct dquot
**dquots
, char *warntype
)
836 for (i
= 0; i
< MAXQUOTAS
; i
++)
837 if (dquots
[i
] != NODQUOT
&& warntype
[i
] != NOWARN
)
838 print_warning(dquots
[i
], warntype
[i
]);
841 static inline char ignore_hardlimit(struct dquot
*dquot
)
843 struct mem_dqinfo
*info
= &sb_dqopt(dquot
->dq_sb
)->info
[dquot
->dq_type
];
845 return capable(CAP_SYS_RESOURCE
) &&
846 (info
->dqi_format
->qf_fmt_id
!= QFMT_VFS_OLD
|| !(info
->dqi_flags
& V1_DQF_RSQUASH
));
849 static int check_idq(struct dquot
*dquot
, ulong inodes
, char *warntype
)
852 if (inodes
<= 0 || dquot
->dq_flags
& DQ_FAKE
)
855 if (dquot
->dq_dqb
.dqb_ihardlimit
&&
856 (dquot
->dq_dqb
.dqb_curinodes
+ inodes
) > dquot
->dq_dqb
.dqb_ihardlimit
&&
857 !ignore_hardlimit(dquot
)) {
858 *warntype
= IHARDWARN
;
862 if (dquot
->dq_dqb
.dqb_isoftlimit
&&
863 (dquot
->dq_dqb
.dqb_curinodes
+ inodes
) > dquot
->dq_dqb
.dqb_isoftlimit
&&
864 dquot
->dq_dqb
.dqb_itime
&& CURRENT_TIME
>= dquot
->dq_dqb
.dqb_itime
&&
865 !ignore_hardlimit(dquot
)) {
866 *warntype
= ISOFTLONGWARN
;
870 if (dquot
->dq_dqb
.dqb_isoftlimit
&&
871 (dquot
->dq_dqb
.dqb_curinodes
+ inodes
) > dquot
->dq_dqb
.dqb_isoftlimit
&&
872 dquot
->dq_dqb
.dqb_itime
== 0) {
873 *warntype
= ISOFTWARN
;
874 dquot
->dq_dqb
.dqb_itime
= CURRENT_TIME
+ sb_dqopt(dquot
->dq_sb
)->info
[dquot
->dq_type
].dqi_igrace
;
880 static int check_bdq(struct dquot
*dquot
, qsize_t space
, int prealloc
, char *warntype
)
883 if (space
<= 0 || dquot
->dq_flags
& DQ_FAKE
)
886 if (dquot
->dq_dqb
.dqb_bhardlimit
&&
887 toqb(dquot
->dq_dqb
.dqb_curspace
+ space
) > dquot
->dq_dqb
.dqb_bhardlimit
&&
888 !ignore_hardlimit(dquot
)) {
890 *warntype
= BHARDWARN
;
894 if (dquot
->dq_dqb
.dqb_bsoftlimit
&&
895 toqb(dquot
->dq_dqb
.dqb_curspace
+ space
) > dquot
->dq_dqb
.dqb_bsoftlimit
&&
896 dquot
->dq_dqb
.dqb_btime
&& CURRENT_TIME
>= dquot
->dq_dqb
.dqb_btime
&&
897 !ignore_hardlimit(dquot
)) {
899 *warntype
= BSOFTLONGWARN
;
903 if (dquot
->dq_dqb
.dqb_bsoftlimit
&&
904 toqb(dquot
->dq_dqb
.dqb_curspace
+ space
) > dquot
->dq_dqb
.dqb_bsoftlimit
&&
905 dquot
->dq_dqb
.dqb_btime
== 0) {
907 *warntype
= BSOFTWARN
;
908 dquot
->dq_dqb
.dqb_btime
= CURRENT_TIME
+ sb_dqopt(dquot
->dq_sb
)->info
[dquot
->dq_type
].dqi_bgrace
;
912 * We don't allow preallocation to exceed softlimit so exceeding will
922 * Externally referenced functions through dquot_operations in inode.
924 * Note: this is a blocking operation.
926 void dquot_initialize(struct inode
*inode
, int type
)
928 struct dquot
*dquot
[MAXQUOTAS
];
932 if (IS_NOQUOTA(inode
))
934 /* Build list of quotas to initialize... We can block here */
935 for (cnt
= 0; cnt
< MAXQUOTAS
; cnt
++) {
936 dquot
[cnt
] = NODQUOT
;
937 if (type
!= -1 && cnt
!= type
)
939 if (!sb_has_quota_enabled(inode
->i_sb
, cnt
))
941 if (inode
->i_dquot
[cnt
] == NODQUOT
) {
950 dquot
[cnt
] = dqget(inode
->i_sb
, id
, cnt
);
953 /* NOBLOCK START: Here we shouldn't block */
954 for (cnt
= 0; cnt
< MAXQUOTAS
; cnt
++) {
955 if (dquot
[cnt
] == NODQUOT
|| !sb_has_quota_enabled(inode
->i_sb
, cnt
) || inode
->i_dquot
[cnt
] != NODQUOT
)
957 inode
->i_dquot
[cnt
] = dquot
[cnt
];
958 dquot
[cnt
] = NODQUOT
;
959 inode
->i_flags
|= S_QUOTA
;
962 /* Put quotas which we didn't use */
963 for (cnt
= 0; cnt
< MAXQUOTAS
; cnt
++)
964 if (dquot
[cnt
] != NODQUOT
)
969 * Release all quota for the specified inode.
971 * Note: this is a blocking operation.
973 void dquot_drop(struct inode
*inode
)
978 inode
->i_flags
&= ~S_QUOTA
;
979 for (cnt
= 0; cnt
< MAXQUOTAS
; cnt
++) {
980 if (inode
->i_dquot
[cnt
] == NODQUOT
)
982 dquot
= inode
->i_dquot
[cnt
];
983 inode
->i_dquot
[cnt
] = NODQUOT
;
989 * This operation can block, but only after everything is updated
991 int dquot_alloc_space(struct inode
*inode
, qsize_t number
, int warn
)
993 int cnt
, ret
= NO_QUOTA
;
994 struct dquot
*dquot
[MAXQUOTAS
];
995 char warntype
[MAXQUOTAS
];
998 for (cnt
= 0; cnt
< MAXQUOTAS
; cnt
++) {
999 dquot
[cnt
] = NODQUOT
;
1000 warntype
[cnt
] = NOWARN
;
1003 for (cnt
= 0; cnt
< MAXQUOTAS
; cnt
++) {
1004 dquot
[cnt
] = dqduplicate(inode
->i_dquot
[cnt
]);
1005 if (dquot
[cnt
] == NODQUOT
)
1007 if (check_bdq(dquot
[cnt
], number
, warn
, warntype
+cnt
) == NO_QUOTA
)
1010 for (cnt
= 0; cnt
< MAXQUOTAS
; cnt
++) {
1011 if (dquot
[cnt
] == NODQUOT
)
1013 dquot_incr_space(dquot
[cnt
], number
);
1015 inode_add_bytes(inode
, number
);
1019 flush_warnings(dquot
, warntype
);
1020 for (cnt
= 0; cnt
< MAXQUOTAS
; cnt
++)
1021 if (dquot
[cnt
] != NODQUOT
)
1022 dqputduplicate(dquot
[cnt
]);
1028 * This operation can block, but only after everything is updated
1030 int dquot_alloc_inode(const struct inode
*inode
, unsigned long number
)
1032 int cnt
, ret
= NO_QUOTA
;
1033 struct dquot
*dquot
[MAXQUOTAS
];
1034 char warntype
[MAXQUOTAS
];
1036 for (cnt
= 0; cnt
< MAXQUOTAS
; cnt
++) {
1037 dquot
[cnt
] = NODQUOT
;
1038 warntype
[cnt
] = NOWARN
;
1042 for (cnt
= 0; cnt
< MAXQUOTAS
; cnt
++) {
1043 dquot
[cnt
] = dqduplicate(inode
-> i_dquot
[cnt
]);
1044 if (dquot
[cnt
] == NODQUOT
)
1046 if (check_idq(dquot
[cnt
], number
, warntype
+cnt
) == NO_QUOTA
)
1050 for (cnt
= 0; cnt
< MAXQUOTAS
; cnt
++) {
1051 if (dquot
[cnt
] == NODQUOT
)
1053 dquot_incr_inodes(dquot
[cnt
], number
);
1058 flush_warnings(dquot
, warntype
);
1059 for (cnt
= 0; cnt
< MAXQUOTAS
; cnt
++)
1060 if (dquot
[cnt
] != NODQUOT
)
1061 dqputduplicate(dquot
[cnt
]);
1067 * This is a non-blocking operation.
1069 void dquot_free_space(struct inode
*inode
, qsize_t number
)
1072 struct dquot
*dquot
;
1076 for (cnt
= 0; cnt
< MAXQUOTAS
; cnt
++) {
1077 dquot
= dqduplicate(inode
->i_dquot
[cnt
]);
1078 if (dquot
== NODQUOT
)
1080 dquot_decr_space(dquot
, number
);
1081 dqputduplicate(dquot
);
1083 inode_sub_bytes(inode
, number
);
1089 * This is a non-blocking operation.
1091 void dquot_free_inode(const struct inode
*inode
, unsigned long number
)
1094 struct dquot
*dquot
;
1098 for (cnt
= 0; cnt
< MAXQUOTAS
; cnt
++) {
1099 dquot
= dqduplicate(inode
->i_dquot
[cnt
]);
1100 if (dquot
== NODQUOT
)
1102 dquot_decr_inodes(dquot
, number
);
1103 dqputduplicate(dquot
);
1110 * Transfer the number of inode and blocks from one diskquota to an other.
1112 * This operation can block, but only after everything is updated
1114 int dquot_transfer(struct inode
*inode
, struct iattr
*iattr
)
1117 struct dquot
*transfer_from
[MAXQUOTAS
];
1118 struct dquot
*transfer_to
[MAXQUOTAS
];
1119 int cnt
, ret
= NO_QUOTA
, chuid
= (iattr
->ia_valid
& ATTR_UID
) && inode
->i_uid
!= iattr
->ia_uid
,
1120 chgid
= (iattr
->ia_valid
& ATTR_GID
) && inode
->i_gid
!= iattr
->ia_gid
;
1121 char warntype
[MAXQUOTAS
];
1123 /* Clear the arrays */
1124 for (cnt
= 0; cnt
< MAXQUOTAS
; cnt
++) {
1125 transfer_to
[cnt
] = transfer_from
[cnt
] = NODQUOT
;
1126 warntype
[cnt
] = NOWARN
;
1128 /* First build the transfer_to list - here we can block on reading of dquots... */
1129 for (cnt
= 0; cnt
< MAXQUOTAS
; cnt
++) {
1130 if (!sb_has_quota_enabled(inode
->i_sb
, cnt
))
1136 transfer_to
[cnt
] = dqget(inode
->i_sb
, iattr
->ia_uid
, cnt
);
1141 transfer_to
[cnt
] = dqget(inode
->i_sb
, iattr
->ia_gid
, cnt
);
1145 /* NOBLOCK START: From now on we shouldn't block */
1146 space
= inode_get_bytes(inode
);
1147 /* Build the transfer_from list and check the limits */
1148 for (cnt
= 0; cnt
< MAXQUOTAS
; cnt
++) {
1149 /* The second test can fail when quotaoff is in progress... */
1150 if (transfer_to
[cnt
] == NODQUOT
|| !sb_has_quota_enabled(inode
->i_sb
, cnt
))
1152 transfer_from
[cnt
] = dqduplicate(inode
->i_dquot
[cnt
]);
1153 if (transfer_from
[cnt
] == NODQUOT
) /* Can happen on quotafiles (quota isn't initialized on them)... */
1155 if (check_idq(transfer_to
[cnt
], 1, warntype
+cnt
) == NO_QUOTA
||
1156 check_bdq(transfer_to
[cnt
], space
, 0, warntype
+cnt
) == NO_QUOTA
)
1161 * Finally perform the needed transfer from transfer_from to transfer_to
1163 for (cnt
= 0; cnt
< MAXQUOTAS
; cnt
++) {
1165 * Skip changes for same uid or gid or for non-existing quota-type.
1167 if (transfer_from
[cnt
] == NODQUOT
|| transfer_to
[cnt
] == NODQUOT
)
1170 dquot_decr_inodes(transfer_from
[cnt
], 1);
1171 dquot_decr_space(transfer_from
[cnt
], space
);
1173 dquot_incr_inodes(transfer_to
[cnt
], 1);
1174 dquot_incr_space(transfer_to
[cnt
], space
);
1176 if (inode
->i_dquot
[cnt
] == NODQUOT
)
1178 inode
->i_dquot
[cnt
] = transfer_to
[cnt
];
1180 * We've got to release transfer_from[] twice - once for dquot_transfer() and
1181 * once for inode. We don't want to release transfer_to[] as it's now placed in inode
1183 transfer_to
[cnt
] = transfer_from
[cnt
];
1185 /* NOBLOCK END. From now on we can block as we wish */
1188 flush_warnings(transfer_to
, warntype
);
1189 for (cnt
= 0; cnt
< MAXQUOTAS
; cnt
++) {
1190 /* First we must put duplicate - otherwise we might deadlock */
1191 if (transfer_to
[cnt
] != NODQUOT
)
1192 dqputduplicate(transfer_to
[cnt
]);
1193 if (transfer_from
[cnt
] != NODQUOT
)
1194 dqput(transfer_from
[cnt
]);
1200 * Definitions of diskquota operations.
1202 struct dquot_operations dquot_operations
= {
1203 .initialize
= dquot_initialize
, /* mandatory */
1204 .drop
= dquot_drop
, /* mandatory */
1205 .alloc_space
= dquot_alloc_space
,
1206 .alloc_inode
= dquot_alloc_inode
,
1207 .free_space
= dquot_free_space
,
1208 .free_inode
= dquot_free_inode
,
1209 .transfer
= dquot_transfer
1212 static inline void set_enable_flags(struct quota_info
*dqopt
, int type
)
1216 dqopt
->flags
|= DQUOT_USR_ENABLED
;
1219 dqopt
->flags
|= DQUOT_GRP_ENABLED
;
1224 static inline void reset_enable_flags(struct quota_info
*dqopt
, int type
)
1228 dqopt
->flags
&= ~DQUOT_USR_ENABLED
;
1231 dqopt
->flags
&= ~DQUOT_GRP_ENABLED
;
1236 /* Function in inode.c - remove pointers to dquots in icache */
1237 extern void remove_dquot_ref(struct super_block
*, int);
1240 * Turn quota off on a device. type == -1 ==> quotaoff for all types (umount)
1242 int vfs_quota_off(struct super_block
*sb
, int type
)
1245 struct quota_info
*dqopt
= sb_dqopt(sb
);
1251 /* We need to serialize quota_off() for device */
1252 down(&dqopt
->dqoff_sem
);
1253 for (cnt
= 0; cnt
< MAXQUOTAS
; cnt
++) {
1254 if (type
!= -1 && cnt
!= type
)
1256 if (!is_enabled(dqopt
, cnt
))
1258 reset_enable_flags(dqopt
, cnt
);
1260 /* Note: these are blocking operations */
1261 remove_dquot_ref(sb
, cnt
);
1262 invalidate_dquots(sb
, cnt
);
1263 if (info_dirty(&dqopt
->info
[cnt
]))
1264 dqopt
->ops
[cnt
]->write_file_info(sb
, cnt
);
1265 if (dqopt
->ops
[cnt
]->free_file_info
)
1266 dqopt
->ops
[cnt
]->free_file_info(sb
, cnt
);
1267 put_quota_format(dqopt
->info
[cnt
].dqi_format
);
1269 fput(dqopt
->files
[cnt
]);
1270 dqopt
->files
[cnt
] = (struct file
*)NULL
;
1271 dqopt
->info
[cnt
].dqi_flags
= 0;
1272 dqopt
->info
[cnt
].dqi_igrace
= 0;
1273 dqopt
->info
[cnt
].dqi_bgrace
= 0;
1274 dqopt
->ops
[cnt
] = NULL
;
1276 up(&dqopt
->dqoff_sem
);
1282 int vfs_quota_on(struct super_block
*sb
, int type
, int format_id
, char *path
)
1284 struct file
*f
= NULL
;
1285 struct inode
*inode
;
1286 struct quota_info
*dqopt
= sb_dqopt(sb
);
1287 struct quota_format_type
*fmt
= find_quota_format(format_id
);
1292 if (is_enabled(dqopt
, type
)) {
1297 down(&dqopt
->dqoff_sem
);
1299 f
= filp_open(path
, O_RDWR
, 0600);
1304 dqopt
->files
[type
] = f
;
1306 if (!f
->f_op
|| !f
->f_op
->read
|| !f
->f_op
->write
)
1308 error
= security_ops
->quota_on(f
);
1311 inode
= f
->f_dentry
->d_inode
;
1313 if (!S_ISREG(inode
->i_mode
))
1316 if (!fmt
->qf_ops
->check_quota_file(sb
, type
))
1318 /* We don't want quota on quota files */
1320 inode
->i_flags
|= S_NOQUOTA
;
1322 dqopt
->ops
[type
] = fmt
->qf_ops
;
1323 dqopt
->info
[type
].dqi_format
= fmt
;
1324 if ((error
= dqopt
->ops
[type
]->read_file_info(sb
, type
)) < 0)
1326 set_enable_flags(dqopt
, type
);
1328 add_dquot_ref(sb
, type
);
1330 up(&dqopt
->dqoff_sem
);
1335 filp_close(f
, NULL
);
1336 dqopt
->files
[type
] = NULL
;
1338 up(&dqopt
->dqoff_sem
);
1340 put_quota_format(fmt
);
1345 /* Generic routine for getting common part of quota structure */
1346 static void do_get_dqblk(struct dquot
*dquot
, struct if_dqblk
*di
)
1348 struct mem_dqblk
*dm
= &dquot
->dq_dqb
;
1350 di
->dqb_bhardlimit
= dm
->dqb_bhardlimit
;
1351 di
->dqb_bsoftlimit
= dm
->dqb_bsoftlimit
;
1352 di
->dqb_curspace
= dm
->dqb_curspace
;
1353 di
->dqb_ihardlimit
= dm
->dqb_ihardlimit
;
1354 di
->dqb_isoftlimit
= dm
->dqb_isoftlimit
;
1355 di
->dqb_curinodes
= dm
->dqb_curinodes
;
1356 di
->dqb_btime
= dm
->dqb_btime
;
1357 di
->dqb_itime
= dm
->dqb_itime
;
1358 di
->dqb_valid
= QIF_ALL
;
1361 int vfs_get_dqblk(struct super_block
*sb
, int type
, qid_t id
, struct if_dqblk
*di
)
1363 struct dquot
*dquot
= dqget(sb
, id
, type
);
1367 do_get_dqblk(dquot
, di
);
1372 /* Generic routine for setting common part of quota structure */
1373 static void do_set_dqblk(struct dquot
*dquot
, struct if_dqblk
*di
)
1375 struct mem_dqblk
*dm
= &dquot
->dq_dqb
;
1376 int check_blim
= 0, check_ilim
= 0;
1378 if (di
->dqb_valid
& QIF_SPACE
) {
1379 dm
->dqb_curspace
= di
->dqb_curspace
;
1382 if (di
->dqb_valid
& QIF_BLIMITS
) {
1383 dm
->dqb_bsoftlimit
= di
->dqb_bsoftlimit
;
1384 dm
->dqb_bhardlimit
= di
->dqb_bhardlimit
;
1387 if (di
->dqb_valid
& QIF_INODES
) {
1388 dm
->dqb_curinodes
= di
->dqb_curinodes
;
1391 if (di
->dqb_valid
& QIF_ILIMITS
) {
1392 dm
->dqb_isoftlimit
= di
->dqb_isoftlimit
;
1393 dm
->dqb_ihardlimit
= di
->dqb_ihardlimit
;
1396 if (di
->dqb_valid
& QIF_BTIME
)
1397 dm
->dqb_btime
= di
->dqb_btime
;
1398 if (di
->dqb_valid
& QIF_ITIME
)
1399 dm
->dqb_itime
= di
->dqb_itime
;
1402 if (!dm
->dqb_bsoftlimit
|| toqb(dm
->dqb_curspace
) < dm
->dqb_bsoftlimit
) {
1404 dquot
->dq_flags
&= ~DQ_BLKS
;
1406 else if (!(di
->dqb_valid
& QIF_BTIME
)) /* Set grace only if user hasn't provided his own... */
1407 dm
->dqb_btime
= CURRENT_TIME
+ sb_dqopt(dquot
->dq_sb
)->info
[dquot
->dq_type
].dqi_bgrace
;
1410 if (!dm
->dqb_isoftlimit
|| dm
->dqb_curinodes
< dm
->dqb_isoftlimit
) {
1412 dquot
->dq_flags
&= ~DQ_INODES
;
1414 else if (!(di
->dqb_valid
& QIF_ITIME
)) /* Set grace only if user hasn't provided his own... */
1415 dm
->dqb_itime
= CURRENT_TIME
+ sb_dqopt(dquot
->dq_sb
)->info
[dquot
->dq_type
].dqi_igrace
;
1417 if (dm
->dqb_bhardlimit
|| dm
->dqb_bsoftlimit
|| dm
->dqb_ihardlimit
|| dm
->dqb_isoftlimit
)
1418 dquot
->dq_flags
&= ~DQ_FAKE
;
1420 dquot
->dq_flags
|= DQ_FAKE
;
1421 dquot
->dq_flags
|= DQ_MOD
;
1424 int vfs_set_dqblk(struct super_block
*sb
, int type
, qid_t id
, struct if_dqblk
*di
)
1426 struct dquot
*dquot
= dqget(sb
, id
, type
);
1430 do_set_dqblk(dquot
, di
);
1435 /* Generic routine for getting common part of quota file information */
1436 int vfs_get_dqinfo(struct super_block
*sb
, int type
, struct if_dqinfo
*ii
)
1438 struct mem_dqinfo
*mi
= sb_dqopt(sb
)->info
+ type
;
1440 ii
->dqi_bgrace
= mi
->dqi_bgrace
;
1441 ii
->dqi_igrace
= mi
->dqi_igrace
;
1442 ii
->dqi_flags
= mi
->dqi_flags
& DQF_MASK
;
1443 ii
->dqi_valid
= IIF_ALL
;
1447 /* Generic routine for setting common part of quota file information */
1448 int vfs_set_dqinfo(struct super_block
*sb
, int type
, struct if_dqinfo
*ii
)
1450 struct mem_dqinfo
*mi
= sb_dqopt(sb
)->info
+ type
;
1452 if (ii
->dqi_valid
& IIF_BGRACE
)
1453 mi
->dqi_bgrace
= ii
->dqi_bgrace
;
1454 if (ii
->dqi_valid
& IIF_IGRACE
)
1455 mi
->dqi_igrace
= ii
->dqi_igrace
;
1456 if (ii
->dqi_valid
& IIF_FLAGS
)
1457 mi
->dqi_flags
= (mi
->dqi_flags
& ~DQF_MASK
) | (ii
->dqi_flags
& DQF_MASK
);
1458 mark_info_dirty(mi
);
1462 struct quotactl_ops vfs_quotactl_ops
= {
1463 .quota_on
= vfs_quota_on
,
1464 .quota_off
= vfs_quota_off
,
1465 .quota_sync
= vfs_quota_sync
,
1466 .get_info
= vfs_get_dqinfo
,
1467 .set_info
= vfs_set_dqinfo
,
1468 .get_dqblk
= vfs_get_dqblk
,
1469 .set_dqblk
= vfs_set_dqblk
1472 static ctl_table fs_dqstats_table
[] = {
1473 {FS_DQ_LOOKUPS
, "lookups", &dqstats
.lookups
, sizeof(int), 0444, NULL
, &proc_dointvec
},
1474 {FS_DQ_DROPS
, "drops", &dqstats
.drops
, sizeof(int), 0444, NULL
, &proc_dointvec
},
1475 {FS_DQ_READS
, "reads", &dqstats
.reads
, sizeof(int), 0444, NULL
, &proc_dointvec
},
1476 {FS_DQ_WRITES
, "writes", &dqstats
.writes
, sizeof(int), 0444, NULL
, &proc_dointvec
},
1477 {FS_DQ_CACHE_HITS
, "cache_hits", &dqstats
.cache_hits
, sizeof(int), 0444, NULL
, &proc_dointvec
},
1478 {FS_DQ_ALLOCATED
, "allocated_dquots", &dqstats
.allocated_dquots
, sizeof(int), 0444, NULL
, &proc_dointvec
},
1479 {FS_DQ_FREE
, "free_dquots", &dqstats
.free_dquots
, sizeof(int), 0444, NULL
, &proc_dointvec
},
1480 {FS_DQ_SYNCS
, "syncs", &dqstats
.syncs
, sizeof(int), 0444, NULL
, &proc_dointvec
},
1484 static ctl_table fs_table
[] = {
1485 {FS_DQSTATS
, "quota", NULL
, 0, 0555, fs_dqstats_table
},
1489 static ctl_table sys_table
[] = {
1490 {CTL_FS
, "fs", NULL
, 0, 0555, fs_table
},
1494 /* SLAB cache for dquot structures */
1495 kmem_cache_t
*dquot_cachep
;
1497 static int __init
dquot_init(void)
1501 register_sysctl_table(sys_table
, 0);
1502 for (i
= 0; i
< NR_DQHASH
; i
++)
1503 INIT_LIST_HEAD(dquot_hash
+ i
);
1504 printk(KERN_NOTICE
"VFS: Disk quotas v%s\n", __DQUOT_VERSION__
);
1506 dquot_cachep
= kmem_cache_create("dquot",
1507 sizeof(struct dquot
), sizeof(unsigned long) * 4,
1508 SLAB_HWCACHE_ALIGN
, NULL
, NULL
);
1510 panic("Cannot create dquot SLAB cache");
1512 set_shrinker(DEFAULT_SEEKS
, shrink_dqcache_memory
);
1516 module_init(dquot_init
);
1518 EXPORT_SYMBOL(register_quota_format
);
1519 EXPORT_SYMBOL(unregister_quota_format
);
1520 EXPORT_SYMBOL(dqstats
);