2 Index: linux-2.6.5-7.276/include/linux/ext3_jbd.h
3 ===================================================================
4 --- linux-2.6.5-7.276.orig/include/linux/ext3_jbd.h 2006-09-15 17:44:48.000000000 +0800
5 +++ linux-2.6.5-7.276/include/linux/ext3_jbd.h 2006-10-26 16:47:10.000000000 +0800
8 #define EXT3_INDEX_EXTRA_TRANS_BLOCKS 8
11 +/* Amount of blocks needed for quota update - we know that the structure was
12 + * allocated so we need to update only inode+data */
13 +#define EXT3_QUOTA_TRANS_BLOCKS 2
14 +/* Amount of blocks needed for quota insert/delete - we do some block writes
15 + * but inode, sb and group updates are done only once */
16 +#define EXT3_QUOTA_INIT_BLOCKS (DQUOT_MAX_WRITES*\
17 + (EXT3_SINGLEDATA_TRANS_BLOCKS-3)+3)
19 +#define EXT3_QUOTA_TRANS_BLOCKS 0
20 +#define EXT3_QUOTA_INIT_BLOCKS 0
24 ext3_mark_iloc_dirty(handle_t *handle,
27 void ext3_journal_abort_handle(const char *caller, const char *err_fn,
28 struct buffer_head *bh, handle_t *handle, int err);
30 +int ext3_journal_dirty_data(handle_t *handle, struct buffer_head *bh);
33 __ext3_journal_get_undo_access(const char *where, handle_t *handle,
34 struct buffer_head *bh, int *credits)
35 Index: linux-2.6.5-7.276/include/linux/fs.h
36 ===================================================================
37 --- linux-2.6.5-7.276.orig/include/linux/fs.h 2006-10-26 16:47:09.000000000 +0800
38 +++ linux-2.6.5-7.276/include/linux/fs.h 2006-10-26 16:47:10.000000000 +0800
40 void (*umount_begin) (struct super_block *);
42 int (*show_options)(struct seq_file *, struct vfsmount *);
44 + ssize_t (*quota_read)(struct super_block *, int, char *, size_t, loff_t);
45 + ssize_t (*quota_write)(struct super_block *, int, const char *, size_t, loff_t);
48 /* Inode state bits. Protected by inode_lock. */
49 Index: linux-2.6.5-7.276/include/linux/quota.h
50 ===================================================================
51 --- linux-2.6.5-7.276.orig/include/linux/quota.h 2006-09-15 17:44:47.000000000 +0800
52 +++ linux-2.6.5-7.276/include/linux/quota.h 2006-10-26 16:47:10.000000000 +0800
54 #include <linux/dqblk_v1.h>
55 #include <linux/dqblk_v2.h>
57 +/* Maximal numbers of writes for quota operation (insert/delete/update)
58 + * (over all formats) - info block, 4 pointer blocks, data block */
59 +#define DQUOT_MAX_WRITES 6
62 * Data for one user/group kept in memory
70 #define DQF_MASK 0xffff /* Mask for format specific flags */
71 #define DQF_INFO_DIRTY_B 16
72 #define DQF_ANY_DQUOT_DIRTY_B 17
73 #define DQF_INFO_DIRTY (1 << DQF_INFO_DIRTY_B) /* Is info dirty? */
74 #define DQF_ANY_DQUOT_DIRTY (1 << DQF_ANY_DQUOT_DIRTY_B) /* Is any dquot dirty? */
76 -extern inline void mark_info_dirty(struct mem_dqinfo *info)
78 - set_bit(DQF_INFO_DIRTY_B, &info->dqi_flags);
81 +extern void mark_info_dirty(struct super_block *sb, int type);
82 #define info_dirty(info) test_bit(DQF_INFO_DIRTY_B, &(info)->dqi_flags)
83 #define info_any_dquot_dirty(info) test_bit(DQF_ANY_DQUOT_DIRTY_B, &(info)->dqi_flags)
84 #define info_any_dirty(info) (info_dirty(info) || info_any_dquot_dirty(info))
86 #define sb_dqopt(sb) (&(sb)->s_dquot)
87 +#define sb_dqinfo(sb, type) (sb_dqopt(sb)->info+(type))
95 +#define DQ_READ_B 4 /* dquot was read into memory */
96 +#define DQ_ACTIVE_B 5 /* dquot is active (dquot_release not called) */
97 +#define DQ_WAITFREE_B 6 /* dquot being waited (by invalidate_dquots) */
99 #define DQ_MOD (1 << DQ_MOD_B) /* dquot modified since read */
100 #define DQ_BLKS (1 << DQ_BLKS_B) /* uid/gid has been warned about blk limit */
101 @@ -239,18 +245,22 @@
102 int (*free_file_info)(struct super_block *sb, int type); /* Called on quotaoff() */
103 int (*read_dqblk)(struct dquot *dquot); /* Read structure for one user */
104 int (*commit_dqblk)(struct dquot *dquot); /* Write (or delete) structure for one user */
105 + int (*release_dqblk)(struct dquot *dquot); /* Called when last reference to dquot is being dropped */
108 /* Operations working with dquots */
109 struct dquot_operations {
110 - void (*initialize) (struct inode *, int);
111 - void (*drop) (struct inode *);
112 + int (*initialize) (struct inode *, int);
113 + int (*drop) (struct inode *);
114 int (*alloc_space) (struct inode *, qsize_t, int);
115 int (*alloc_inode) (const struct inode *, unsigned long);
116 - void (*free_space) (struct inode *, qsize_t);
117 - void (*free_inode) (const struct inode *, unsigned long);
118 + int (*free_space) (struct inode *, qsize_t);
119 + int (*free_inode) (const struct inode *, unsigned long);
120 int (*transfer) (struct inode *, struct iattr *);
121 int (*write_dquot) (struct dquot *);
122 + int (*acquire_dquot) (struct dquot *); /* Quota is going to be created on disk */
123 + int (*release_dquot) (struct dquot *); /* Quota is going to be deleted from disk */
124 + int (*write_info) (struct super_block *, int); /* Write of quota "superblock" */
127 /* Operations handling requests from userspace */
129 struct semaphore dqio_sem; /* lock device while I/O in progress */
130 struct semaphore dqonoff_sem; /* Serialize quotaon & quotaoff */
131 struct rw_semaphore dqptr_sem; /* serialize ops using quota_info struct, pointers from inode to dquots */
132 - struct file *files[MAXQUOTAS]; /* fp's to quotafiles */
133 + struct inode *files[MAXQUOTAS]; /* inodes of quotafiles */
134 + struct vfsmount *mnt[MAXQUOTAS]; /* mountpoint entries of filesystems with quota files */
135 struct mem_dqinfo info[MAXQUOTAS]; /* Information for each quota type */
136 struct quota_format_ops *ops[MAXQUOTAS]; /* Operations for each type */
138 Index: linux-2.6.5-7.276/include/linux/quotaops.h
139 ===================================================================
140 --- linux-2.6.5-7.276.orig/include/linux/quotaops.h 2006-09-30 11:24:23.000000000 +0800
141 +++ linux-2.6.5-7.276/include/linux/quotaops.h 2006-10-30 10:39:46.000000000 +0800
144 extern void sync_dquots(struct super_block *sb, int type);
146 -extern void dquot_initialize(struct inode *inode, int type);
147 -extern void dquot_drop(struct inode *inode);
148 +extern int dquot_initialize(struct inode *inode, int type);
149 +extern int dquot_drop(struct inode *inode);
151 extern int dquot_alloc_space(struct inode *inode, qsize_t number, int prealloc);
152 extern int dquot_alloc_inode(const struct inode *inode, unsigned long number);
154 -extern void dquot_free_space(struct inode *inode, qsize_t number);
155 -extern void dquot_free_inode(const struct inode *inode, unsigned long number);
156 +extern int dquot_free_space(struct inode *inode, qsize_t number);
157 +extern int dquot_free_inode(const struct inode *inode, unsigned long number);
159 extern int dquot_transfer(struct inode *inode, struct iattr *iattr);
161 +extern int dquot_commit(struct dquot *dquot);
162 +extern int dquot_commit_info(struct super_block *sb, int type);
163 +extern int dquot_acquire(struct dquot *dquot);
164 +extern int dquot_release(struct dquot *dquot);
167 * Operations supported for diskquotas.
173 - if (sb->s_qcop && sb->s_qcop->quota_off)
174 + if (sb_any_quota_enabled(sb) && sb->s_qcop && sb->s_qcop->quota_off)
175 ret = sb->s_qcop->quota_off(sb, -1);
178 Index: linux-2.6.5-7.276/include/linux/security.h
179 ===================================================================
180 --- linux-2.6.5-7.276.orig/include/linux/security.h 2006-09-15 17:44:47.000000000 +0800
181 +++ linux-2.6.5-7.276/include/linux/security.h 2006-10-26 16:47:10.000000000 +0800
182 @@ -1020,7 +1020,7 @@
183 int (*sysctl) (ctl_table * table, int op);
184 int (*capable) (struct task_struct * tsk, int cap);
185 int (*quotactl) (int cmds, int type, int id, struct super_block * sb);
186 - int (*quota_on) (struct file * f);
187 + int (*quota_on) (struct dentry * dentry);
188 int (*syslog) (int type);
189 int (*vm_enough_memory) (long pages);
191 @@ -1292,9 +1292,9 @@
195 -static inline int security_quota_on (struct file * file)
196 +static inline int security_quota_on (struct dentry * dentry)
198 - return COND_SECURITY(quota_on (file),
199 + return COND_SECURITY(quota_on (dentry),
203 Index: linux-2.6.5-7.276/security/dummy.c
204 ===================================================================
205 --- linux-2.6.5-7.276.orig/security/dummy.c 2006-09-15 17:44:47.000000000 +0800
206 +++ linux-2.6.5-7.276/security/dummy.c 2006-10-26 16:47:10.000000000 +0800
211 -static int dummy_quota_on (struct file *f)
212 +static int dummy_quota_on (struct dentry *dentry)
216 Index: linux-2.6.5-7.276/security/selinux/hooks.c
217 ===================================================================
218 --- linux-2.6.5-7.276.orig/security/selinux/hooks.c 2006-09-15 17:44:47.000000000 +0800
219 +++ linux-2.6.5-7.276/security/selinux/hooks.c 2006-10-26 16:47:10.000000000 +0800
220 @@ -1454,9 +1454,9 @@
224 -static int selinux_quota_on(struct file *f)
225 +static int selinux_quota_on(struct dentry *dentry)
227 - return file_has_perm(current, f, FILE__QUOTAON);
228 + return dentry_has_perm(current, NULL, dentry, FILE__QUOTAON);
231 static int selinux_syslog(int type)
232 Index: linux-2.6.5-7.276/fs/dquot.c
233 ===================================================================
234 --- linux-2.6.5-7.276.orig/fs/dquot.c 2006-09-15 17:44:47.000000000 +0800
235 +++ linux-2.6.5-7.276/fs/dquot.c 2006-10-26 16:47:10.000000000 +0800
238 * Jan Kara, <jack@suse.cz>, 10/2002
240 + * Fix lock inversion problems
241 + * Jan Kara, <jack@suse.cz>, 2003,2004
243 * (C) Copyright 1994 - 1997 Marco van Wieringen
247 #include <linux/proc_fs.h>
248 #include <linux/security.h>
249 #include <linux/kmod.h>
250 -#include <linux/pagemap.h>
251 +#include <linux/namei.h>
252 +#include <linux/buffer_head.h>
254 #include <asm/uaccess.h>
257 * dqget(). Write operations on dquots don't hold dq_lock as they copy data
258 * under dq_data_lock spinlock to internal buffers before writing.
260 - * Lock ordering (including journal_lock) is following:
261 + * Lock ordering (including journal_lock) is the following:
262 * dqonoff_sem > journal_lock > dqptr_sem > dquot->dq_lock > dqio_sem
264 spinlock_t dq_list_lock = SPIN_LOCK_UNLOCKED;
266 * on all three lists, depending on its current state.
268 * All dquots are placed to the end of inuse_list when first created, and this
269 - * list is used for the sync and invalidate operations, which must look
271 + * list is used for invalidate operation, which must look at every dquot.
273 * Unused dquots (dq_count == 0) are added to the free_dquots list when freed,
274 * and this list is searched whenever we need an available dquot. Dquots are
275 @@ -264,30 +267,105 @@
279 -static int read_dqblk(struct dquot *dquot)
280 +void mark_info_dirty(struct super_block *sb, int type)
283 + set_bit(DQF_INFO_DIRTY_B, &sb_dqopt(sb)->info[type].dqi_flags);
285 +EXPORT_SYMBOL(mark_info_dirty);
288 + * Read dquot from disk and alloc space for it
291 +int dquot_acquire(struct dquot *dquot)
293 + int ret = 0, ret2 = 0;
294 struct quota_info *dqopt = sb_dqopt(dquot->dq_sb);
296 down(&dquot->dq_lock);
297 down(&dqopt->dqio_sem);
298 - ret = dqopt->ops[dquot->dq_type]->read_dqblk(dquot);
299 + if (!test_bit(DQ_READ_B, &dquot->dq_flags))
300 + ret = dqopt->ops[dquot->dq_type]->read_dqblk(dquot);
303 + set_bit(DQ_READ_B, &dquot->dq_flags);
304 + /* Instantiate dquot if needed */
305 + if (!test_bit(DQ_ACTIVE_B, &dquot->dq_flags) && !dquot->dq_off) {
306 + ret = dqopt->ops[dquot->dq_type]->commit_dqblk(dquot);
307 + /* Write the info if needed */
308 + if (info_dirty(&dqopt->info[dquot->dq_type]))
309 + ret2 = dqopt->ops[dquot->dq_type]->write_file_info(dquot->dq_sb, dquot->dq_type);
317 + set_bit(DQ_ACTIVE_B, &dquot->dq_flags);
319 up(&dqopt->dqio_sem);
324 -static int commit_dqblk(struct dquot *dquot)
326 + * Write dquot to disk
328 +int dquot_commit(struct dquot *dquot)
331 + int ret = 0, ret2 = 0;
332 struct quota_info *dqopt = sb_dqopt(dquot->dq_sb);
334 down(&dqopt->dqio_sem);
335 - ret = dqopt->ops[dquot->dq_type]->commit_dqblk(dquot);
336 + spin_lock(&dq_list_lock);
337 + if (!test_and_clear_bit(DQ_MOD_B, &dquot->dq_flags)) {
338 + spin_unlock(&dq_list_lock);
341 + spin_unlock(&dq_list_lock);
342 + /* Inactive dquot can be only if there was error during read/init
343 + * => we have better not writing it */
344 + if (test_bit(DQ_ACTIVE_B, &dquot->dq_flags)) {
345 + ret = dqopt->ops[dquot->dq_type]->commit_dqblk(dquot);
346 + if (info_dirty(&dqopt->info[dquot->dq_type]))
347 + ret2 = dqopt->ops[dquot->dq_type]->write_file_info(dquot->dq_sb, dquot->dq_type);
352 up(&dqopt->dqio_sem);
359 +int dquot_release(struct dquot *dquot)
361 + int ret = 0, ret2 = 0;
362 + struct quota_info *dqopt = sb_dqopt(dquot->dq_sb);
364 + down(&dquot->dq_lock);
365 + /* Check whether we are not racing with some other dqget() */
366 + if (atomic_read(&dquot->dq_count) > 1)
368 + down(&dqopt->dqio_sem);
369 + if (dqopt->ops[dquot->dq_type]->release_dqblk) {
370 + ret = dqopt->ops[dquot->dq_type]->release_dqblk(dquot);
371 + /* Write the info */
372 + if (info_dirty(&dqopt->info[dquot->dq_type]))
373 + ret2 = dqopt->ops[dquot->dq_type]->write_file_info(dquot->dq_sb, dquot->dq_type);
377 + clear_bit(DQ_ACTIVE_B, &dquot->dq_flags);
378 + up(&dqopt->dqio_sem);
380 + up(&dquot->dq_lock);
384 /* Invalidate all dquots on the list. Note that this function is called after
385 * quota is disabled so no new quota might be created. Because we hold
386 * dqonoff_sem and pointers were already removed from inodes we actually know
389 if (!dquot_dirty(dquot))
391 + /* Dirty and inactive can be only bad dquot... */
392 + if (!test_bit(DQ_ACTIVE_B, &dquot->dq_flags)) {
393 + test_and_clear_bit(DQ_MOD_B, &dquot->dq_flags);
396 atomic_inc(&dquot->dq_count);
398 spin_unlock(&dq_list_lock);
400 spin_unlock(&dq_list_lock);
402 for (cnt = 0; cnt < MAXQUOTAS; cnt++)
403 - if ((cnt == type || type == -1) && sb_has_quota_enabled(sb, cnt) && info_dirty(&dqopt->info[cnt])) {
404 - down(&dqopt->dqio_sem);
405 - dqopt->ops[cnt]->write_file_info(sb, cnt);
406 - up(&dqopt->dqio_sem);
408 + if ((cnt == type || type == -1) && sb_has_quota_enabled(sb, cnt)
409 + && info_dirty(&dqopt->info[cnt]))
410 + sb->dq_op->write_info(sb, cnt);
411 spin_lock(&dq_list_lock);
413 spin_unlock(&dq_list_lock);
414 @@ -432,11 +513,19 @@
415 spin_unlock(&dq_list_lock);
418 - if (dquot_dirty(dquot)) {
419 + if (test_bit(DQ_ACTIVE_B, &dquot->dq_flags) && dquot_dirty(dquot)) {
420 spin_unlock(&dq_list_lock);
421 dquot->dq_sb->dq_op->write_dquot(dquot);
424 + /* Clear flag in case dquot was inactive (something bad happened) */
425 + test_and_clear_bit(DQ_MOD_B, &dquot->dq_flags);
426 + if (test_bit(DQ_ACTIVE_B, &dquot->dq_flags)) {
427 + spin_unlock(&dq_list_lock);
428 + dquot->dq_sb->dq_op->release_dquot(dquot);
432 atomic_dec(&dquot->dq_count);
433 #ifdef __DQUOT_PARANOIA
436 insert_dquot_hash(dquot);
438 spin_unlock(&dq_list_lock);
441 if (!atomic_read(&dquot->dq_count))
442 remove_free_dquot(dquot);
443 @@ -503,10 +591,15 @@
444 dqstats.cache_hits++;
446 spin_unlock(&dq_list_lock);
447 - wait_on_dquot(dquot);
449 kmem_cache_free(dquot_cachep, empty);
451 + wait_on_dquot(dquot);
452 + /* Read the dquot and instantiate it (everything done only if needed) */
453 + if (!test_bit(DQ_ACTIVE_B, &dquot->dq_flags) && sb->dq_op->acquire_dquot(dquot) < 0) {
458 #ifdef __DQUOT_PARANOIA
459 if (!dquot->dq_sb) /* Has somebody invalidated entry under us? */
460 @@ -819,19 +912,19 @@
462 * Note: this is a blocking operation.
464 -void dquot_initialize(struct inode *inode, int type)
465 +int dquot_initialize(struct inode *inode, int type)
470 /* Solve deadlock when we recurse when holding dqptr_sem... */
471 if (IS_NOQUOTA(inode))
474 down_write(&sb_dqopt(inode->i_sb)->dqptr_sem);
475 /* Having dqptr_sem we know NOQUOTA flags can't be altered... */
476 if (IS_NOQUOTA(inode)) {
477 up_write(&sb_dqopt(inode->i_sb)->dqptr_sem);
481 /* Build list of quotas to initialize... */
482 for (cnt = 0; cnt < MAXQUOTAS; cnt++) {
483 @@ -852,13 +945,14 @@
486 up_write(&sb_dqopt(inode->i_sb)->dqptr_sem);
491 * Release all quotas referenced by inode
492 * Needs dqonoff_sem to guard dqput()
494 -void dquot_drop(struct inode *inode)
495 +int dquot_drop(struct inode *inode)
502 up_write(&sb_dqopt(inode->i_sb)->dqptr_sem);
507 @@ -958,14 +1053,14 @@
509 * This is a non-blocking operation.
511 -void dquot_free_space(struct inode *inode, qsize_t number)
512 +int dquot_free_space(struct inode *inode, qsize_t number)
516 /* Solve deadlock when we recurse when holding dqptr_sem... */
517 if (IS_NOQUOTA(inode)) {
518 inode_add_bytes(inode, number);
522 down_read(&sb_dqopt(inode->i_sb)->dqptr_sem);
523 spin_lock(&dq_data_lock);
524 @@ -981,23 +1076,24 @@
525 inode_sub_bytes(inode, number);
526 spin_unlock(&dq_data_lock);
527 up_read(&sb_dqopt(inode->i_sb)->dqptr_sem);
532 * This is a non-blocking operation.
534 -void dquot_free_inode(const struct inode *inode, unsigned long number)
535 +int dquot_free_inode(const struct inode *inode, unsigned long number)
539 /* Solve deadlock when we recurse when holding dqptr_sem... */
540 if (IS_NOQUOTA(inode))
543 down_read(&sb_dqopt(inode->i_sb)->dqptr_sem);
544 /* Now recheck reliably when holding dqptr_sem */
545 if (IS_NOQUOTA(inode)) {
546 up_read(&sb_dqopt(inode->i_sb)->dqptr_sem);
550 spin_lock(&dq_data_lock);
551 for (cnt = 0; cnt < MAXQUOTAS; cnt++) {
552 @@ -1007,6 +1103,7 @@
554 spin_unlock(&dq_data_lock);
555 up_read(&sb_dqopt(inode->i_sb)->dqptr_sem);
560 @@ -1104,6 +1201,20 @@
564 + * Write info of quota file to disk
566 +int dquot_commit_info(struct super_block *sb, int type)
569 + struct quota_info *dqopt = sb_dqopt(sb);
571 + down(&dqopt->dqio_sem);
572 + ret = dqopt->ops[type]->write_file_info(sb, type);
573 + up(&dqopt->dqio_sem);
578 * Definitions of diskquota operations.
580 struct dquot_operations dquot_operations = {
581 @@ -1114,7 +1225,10 @@
582 .free_space = dquot_free_space,
583 .free_inode = dquot_free_inode,
584 .transfer = dquot_transfer,
585 - .write_dquot = commit_dqblk
586 + .write_dquot = dquot_commit,
587 + .acquire_dquot = dquot_acquire,
588 + .release_dquot = dquot_release,
589 + .write_info = dquot_commit_info
592 /* Function used by filesystems for initializing the dquot_operations structure */
593 @@ -1154,13 +1268,14 @@
596 struct quota_info *dqopt = sb_dqopt(sb);
600 + struct inode *toputinode[MAXQUOTAS];
601 + struct vfsmount *toputmnt[MAXQUOTAS];
603 /* We need to serialize quota_off() for device */
604 down(&dqopt->dqonoff_sem);
605 for (cnt = 0; cnt < MAXQUOTAS; cnt++) {
606 + toputinode[cnt] = NULL;
607 + toputmnt[cnt] = NULL;
608 if (type != -1 && cnt != type)
610 if (!sb_has_quota_enabled(sb, cnt))
611 @@ -1172,94 +1287,115 @@
612 invalidate_dquots(sb, cnt);
614 * Now all dquots should be invalidated, all writes done so we should be only
615 - * users of the info. No locks needed.
616 + * users of the info.
618 - if (info_dirty(&dqopt->info[cnt])) {
619 - down(&dqopt->dqio_sem);
620 - dqopt->ops[cnt]->write_file_info(sb, cnt);
621 - up(&dqopt->dqio_sem);
623 + if (info_dirty(&dqopt->info[cnt]))
624 + sb->dq_op->write_info(sb, cnt);
625 if (dqopt->ops[cnt]->free_file_info)
626 dqopt->ops[cnt]->free_file_info(sb, cnt);
627 put_quota_format(dqopt->info[cnt].dqi_format);
629 - fput(dqopt->files[cnt]);
630 - dqopt->files[cnt] = (struct file *)NULL;
631 + toputinode[cnt] = dqopt->files[cnt];
632 + toputmnt[cnt] = dqopt->mnt[cnt];
633 + dqopt->files[cnt] = NULL;
634 + dqopt->mnt[cnt] = NULL;
635 dqopt->info[cnt].dqi_flags = 0;
636 dqopt->info[cnt].dqi_igrace = 0;
637 dqopt->info[cnt].dqi_bgrace = 0;
638 dqopt->ops[cnt] = NULL;
640 up(&dqopt->dqonoff_sem);
642 + /* Sync the superblock so that buffers with quota data are written to
643 + * disk (and so userspace sees correct data afterwards).
644 + * The reference to vfsmnt we are still holding protects us from
645 + * umount (we don't have it only when quotas are turned on/off for
646 + * journal replay but in that case we are guarded by the fs anyway). */
647 + if (sb->s_op->sync_fs)
648 + sb->s_op->sync_fs(sb, 1);
649 + sync_blockdev(sb->s_bdev);
650 + /* Now the quota files are just ordinary files and we can set the
651 + * inode flags back. Moreover we discard the pagecache so that
652 + * userspace sees the writes we did bypassing the pagecache. We
653 + * must also discard the blockdev buffers so that we see the
654 + * changes done by userspace on the next quotaon() */
655 + for (cnt = 0; cnt < MAXQUOTAS; cnt++)
656 + if (toputinode[cnt]) {
657 + down(&dqopt->dqonoff_sem);
658 + /* If quota was reenabled in the meantime, we have
660 + if (!sb_has_quota_enabled(sb, cnt)) {
661 + down(&toputinode[cnt]->i_sem);
662 + toputinode[cnt]->i_flags &= ~(S_IMMUTABLE |
663 + S_NOATIME | S_NOQUOTA);
664 + truncate_inode_pages(&toputinode[cnt]->i_data, 0);
665 + up(&toputinode[cnt]->i_sem);
666 + mark_inode_dirty(toputinode[cnt]);
667 + iput(toputinode[cnt]);
669 + up(&dqopt->dqonoff_sem);
670 + /* We don't hold the reference when we turned on quotas
671 + * just for the journal replay... */
673 + mntput(toputmnt[cnt]);
675 + invalidate_bdev(sb->s_bdev, 0);
679 -int vfs_quota_on(struct super_block *sb, int type, int format_id, char *path)
681 + * Turn quotas on on a device
684 +/* Helper function when we already have the inode */
685 +static int vfs_quota_on_inode(struct inode *inode, int type, int format_id)
688 - struct inode *inode;
689 - struct quota_info *dqopt = sb_dqopt(sb);
690 struct quota_format_type *fmt = find_quota_format(format_id);
692 - struct dquot *to_drop[MAXQUOTAS];
693 - unsigned int oldflags;
694 + struct super_block *sb = inode->i_sb;
695 + struct quota_info *dqopt = sb_dqopt(sb);
701 - f = filp_open(path, O_RDWR, 0600);
703 - error = PTR_ERR(f);
704 + if (!S_ISREG(inode->i_mode)) {
708 + if (IS_RDONLY(inode)) {
712 + if (!sb->s_op->quota_write || !sb->s_op->quota_read) {
717 - if (!f->f_op || !f->f_op->read || !f->f_op->write)
719 - error = security_quota_on(f);
722 - inode = f->f_dentry->d_inode;
724 - if (!S_ISREG(inode->i_mode))
727 + /* As we bypass the pagecache we must now flush the inode so that
728 + * we see all the changes from userspace... */
729 + write_inode_now(inode, 1);
730 + /* And now flush the block cache so that kernel sees the changes */
731 + invalidate_bdev(sb->s_bdev, 0);
732 + down(&inode->i_sem);
733 down(&dqopt->dqonoff_sem);
734 if (sb_has_quota_enabled(sb, type)) {
738 - oldflags = inode->i_flags;
739 - dqopt->files[type] = f;
741 - if (!fmt->qf_ops->check_quota_file(sb, type))
742 - goto out_file_init;
743 /* We don't want quota and atime on quota files (deadlocks possible)
744 - * We also need to set GFP mask differently because we cannot recurse
745 - * into filesystem when allocating page for quota inode */
746 + * Also nobody should write to the file - we use special IO operations
747 + * which ignore the immutable bit. */
748 down_write(&dqopt->dqptr_sem);
749 - inode->i_flags |= S_NOQUOTA | S_NOATIME;
752 - * We write to quota files deep within filesystem code. We don't want
753 - * the VFS to reenter filesystem code when it tries to allocate a
754 - * pagecache page for the quota file write. So clear __GFP_FS in
755 - * the quota file's allocation flags.
757 - mapping_set_gfp_mask(inode->i_mapping,
758 - mapping_gfp_mask(inode->i_mapping) & ~__GFP_FS);
760 - for (cnt = 0; cnt < MAXQUOTAS; cnt++) {
761 - to_drop[cnt] = inode->i_dquot[cnt];
762 - inode->i_dquot[cnt] = NODQUOT;
764 - inode->i_flags &= ~S_QUOTA;
765 + oldflags = inode->i_flags & (S_NOATIME | S_IMMUTABLE | S_NOQUOTA);
766 + inode->i_flags |= S_NOQUOTA | S_NOATIME | S_IMMUTABLE;
767 up_write(&dqopt->dqptr_sem);
768 - /* We must put dquots outside of dqptr_sem because we may need to
769 - * start transaction for write */
770 - for (cnt = 0; cnt < MAXQUOTAS; cnt++) {
772 - dqput(to_drop[cnt]);
776 + dqopt->files[type] = igrab(inode);
777 + if (!dqopt->files[type])
780 + if (!fmt->qf_ops->check_quota_file(sb, type))
781 + goto out_file_init;
783 dqopt->ops[type] = fmt->qf_ops;
784 dqopt->info[type].dqi_format = fmt;
785 @@ -1269,6 +1405,7 @@
788 up(&dqopt->dqio_sem);
790 set_enable_flags(dqopt, type);
792 add_dquot_ref(sb, type);
793 @@ -1277,18 +1414,51 @@
797 - inode->i_flags = oldflags;
798 dqopt->files[type] = NULL;
801 up(&dqopt->dqonoff_sem);
803 - filp_close(f, NULL);
804 + if (oldflags != -1) {
805 + down_write(&dqopt->dqptr_sem);
806 + /* Set the flags back (in the case of accidental quotaon()
807 + * on a wrong file we don't want to mess up the flags) */
808 + inode->i_flags &= ~(S_NOATIME | S_NOQUOTA | S_IMMUTABLE);
809 + inode->i_flags |= oldflags;
810 + up_write(&dqopt->dqptr_sem);
814 put_quota_format(fmt);
819 +/* Actual function called from quotactl() */
820 +int vfs_quota_on(struct super_block *sb, int type, int format_id, char *path)
822 + struct nameidata nd;
825 + error = path_lookup(path, LOOKUP_FOLLOW, &nd);
828 + error = security_quota_on(nd.dentry);
831 + /* Quota file not on the same filesystem? */
832 + if (nd.mnt->mnt_sb != sb)
835 + error = vfs_quota_on_inode(nd.dentry->d_inode, type, format_id);
837 + sb_dqopt(sb)->mnt[type] = mntget(nd.mnt);
845 /* Generic routine for getting common part of quota structure */
846 static void do_get_dqblk(struct dquot *dquot, struct if_dqblk *di)
848 @@ -1430,8 +1600,10 @@
849 mi->dqi_igrace = ii->dqi_igrace;
850 if (ii->dqi_valid & IIF_FLAGS)
851 mi->dqi_flags = (mi->dqi_flags & ~DQF_MASK) | (ii->dqi_flags & DQF_MASK);
852 - mark_info_dirty(mi);
853 spin_unlock(&dq_data_lock);
854 + mark_info_dirty(sb, type);
855 + /* Force write to disk */
856 + sb->dq_op->write_info(sb, type);
857 up(&sb_dqopt(sb)->dqonoff_sem);
860 @@ -1564,3 +1736,15 @@
861 EXPORT_SYMBOL(dq_list_lock);
862 EXPORT_SYMBOL(dq_data_lock);
863 EXPORT_SYMBOL(init_dquot_operations);
864 +EXPORT_SYMBOL(dquot_commit);
865 +EXPORT_SYMBOL(dquot_commit_info);
866 +EXPORT_SYMBOL(dquot_acquire);
867 +EXPORT_SYMBOL(dquot_release);
868 +EXPORT_SYMBOL(dquot_initialize);
869 +EXPORT_SYMBOL(dquot_drop);
870 +EXPORT_SYMBOL(dquot_alloc_space);
871 +EXPORT_SYMBOL(dquot_alloc_inode);
872 +EXPORT_SYMBOL(dquot_free_space);
873 +EXPORT_SYMBOL(dquot_free_inode);
874 +EXPORT_SYMBOL(dquot_transfer);
876 Index: linux-2.6.5-7.276/fs/quota_v2.c
877 ===================================================================
878 --- linux-2.6.5-7.276.orig/fs/quota_v2.c 2006-09-15 17:44:47.000000000 +0800
879 +++ linux-2.6.5-7.276/fs/quota_v2.c 2006-10-26 16:47:10.000000000 +0800
881 #include <linux/slab.h>
883 #include <asm/byteorder.h>
884 -#include <asm/uaccess.h>
886 MODULE_AUTHOR("Jan Kara");
887 MODULE_DESCRIPTION("Quota format v2 support");
889 static int v2_check_quota_file(struct super_block *sb, int type)
891 struct v2_disk_dqheader dqhead;
892 - struct file *f = sb_dqopt(sb)->files[type];
896 static const uint quota_magics[] = V2_INITQMAGICS;
897 static const uint quota_versions[] = V2_INITQVERSIONS;
901 - size = f->f_op->read(f, (char *)&dqhead, sizeof(struct v2_disk_dqheader), &offset);
903 - if (size != sizeof(struct v2_disk_dqheader))
904 + size = sb->s_op->quota_read(sb, type, (char *)&dqhead, sizeof(struct v2_disk_dqheader), 0);
905 + if (size != sizeof(struct v2_disk_dqheader)) {
906 + printk("failed read\n");
909 if (le32_to_cpu(dqhead.dqh_magic) != quota_magics[type] ||
910 le32_to_cpu(dqhead.dqh_version) != quota_versions[type])
913 /* Read information header from quota file */
914 static int v2_read_file_info(struct super_block *sb, int type)
917 struct v2_disk_dqinfo dinfo;
918 struct mem_dqinfo *info = sb_dqopt(sb)->info+type;
919 - struct file *f = sb_dqopt(sb)->files[type];
921 - loff_t offset = V2_DQINFOOFF;
925 - size = f->f_op->read(f, (char *)&dinfo, sizeof(struct v2_disk_dqinfo), &offset);
927 + size = sb->s_op->quota_read(sb, type, (char *)&dinfo,
928 + sizeof(struct v2_disk_dqinfo), V2_DQINFOOFF);
929 if (size != sizeof(struct v2_disk_dqinfo)) {
930 printk(KERN_WARNING "Can't read info structure on device %s.\n",
931 - f->f_vfsmnt->mnt_sb->s_id);
935 info->dqi_bgrace = le32_to_cpu(dinfo.dqi_bgrace);
937 /* Write information header to quota file */
938 static int v2_write_file_info(struct super_block *sb, int type)
941 struct v2_disk_dqinfo dinfo;
942 struct mem_dqinfo *info = sb_dqopt(sb)->info+type;
943 - struct file *f = sb_dqopt(sb)->files[type];
945 - loff_t offset = V2_DQINFOOFF;
947 info->dqi_flags &= ~DQF_INFO_DIRTY;
948 dinfo.dqi_bgrace = cpu_to_le32(info->dqi_bgrace);
950 dinfo.dqi_blocks = cpu_to_le32(info->u.v2_i.dqi_blocks);
951 dinfo.dqi_free_blk = cpu_to_le32(info->u.v2_i.dqi_free_blk);
952 dinfo.dqi_free_entry = cpu_to_le32(info->u.v2_i.dqi_free_entry);
955 - size = f->f_op->write(f, (char *)&dinfo, sizeof(struct v2_disk_dqinfo), &offset);
958 + size = sb->s_op->quota_write(sb, type, (char *)&dinfo,
959 + sizeof(struct v2_disk_dqinfo), V2_DQINFOOFF);
961 if (size != sizeof(struct v2_disk_dqinfo)) {
962 printk(KERN_WARNING "Can't write info structure on device %s.\n",
963 - f->f_vfsmnt->mnt_sb->s_id);
968 @@ -144,38 +131,24 @@
972 -static ssize_t read_blk(struct file *filp, uint blk, dqbuf_t buf)
973 +static inline ssize_t read_blk(struct super_block *sb, int type, uint blk, dqbuf_t buf)
977 - loff_t offset = blk<<V2_DQBLKSIZE_BITS;
979 memset(buf, 0, V2_DQBLKSIZE);
982 - ret = filp->f_op->read(filp, (char *)buf, V2_DQBLKSIZE, &offset);
985 + return sb->s_op->quota_read(sb, type, (char *)buf,
986 + V2_DQBLKSIZE, blk << V2_DQBLKSIZE_BITS);
989 -static ssize_t write_blk(struct file *filp, uint blk, dqbuf_t buf)
990 +static inline ssize_t write_blk(struct super_block *sb, int type, uint blk, dqbuf_t buf)
994 - loff_t offset = blk<<V2_DQBLKSIZE_BITS;
998 - ret = filp->f_op->write(filp, (char *)buf, V2_DQBLKSIZE, &offset);
1002 + return sb->s_op->quota_write(sb, type, (char *)buf,
1003 + V2_DQBLKSIZE, blk << V2_DQBLKSIZE_BITS);
1006 /* Remove empty block from list and return it */
1007 -static int get_free_dqblk(struct file *filp, struct mem_dqinfo *info)
1008 +static int get_free_dqblk(struct super_block *sb, int type)
1010 dqbuf_t buf = getdqbuf();
1011 + struct mem_dqinfo *info = sb_dqinfo(sb, type);
1012 struct v2_disk_dqdbheader *dh = (struct v2_disk_dqdbheader *)buf;
1015 @@ -183,17 +156,18 @@
1017 if (info->u.v2_i.dqi_free_blk) {
1018 blk = info->u.v2_i.dqi_free_blk;
1019 - if ((ret = read_blk(filp, blk, buf)) < 0)
1020 + if ((ret = read_blk(sb, type, blk, buf)) < 0)
1022 info->u.v2_i.dqi_free_blk = le32_to_cpu(dh->dqdh_next_free);
1025 memset(buf, 0, V2_DQBLKSIZE);
1026 - if ((ret = write_blk(filp, info->u.v2_i.dqi_blocks, buf)) < 0) /* Assure block allocation... */
1027 + /* Assure block allocation... */
1028 + if ((ret = write_blk(sb, type, info->u.v2_i.dqi_blocks, buf)) < 0)
1030 blk = info->u.v2_i.dqi_blocks++;
1032 - mark_info_dirty(info);
1033 + mark_info_dirty(sb, type);
1040 /* Insert empty block to the list */
1041 -static int put_free_dqblk(struct file *filp, struct mem_dqinfo *info, dqbuf_t buf, uint blk)
1042 +static int put_free_dqblk(struct super_block *sb, int type, dqbuf_t buf, uint blk)
1044 + struct mem_dqinfo *info = sb_dqinfo(sb, type);
1045 struct v2_disk_dqdbheader *dh = (struct v2_disk_dqdbheader *)buf;
1048 @@ -210,16 +185,18 @@
1049 dh->dqdh_prev_free = cpu_to_le32(0);
1050 dh->dqdh_entries = cpu_to_le16(0);
1051 info->u.v2_i.dqi_free_blk = blk;
1052 - mark_info_dirty(info);
1053 - if ((err = write_blk(filp, blk, buf)) < 0) /* Some strange block. We had better leave it... */
1054 + mark_info_dirty(sb, type);
1055 + /* Some strange block. We had better leave it... */
1056 + if ((err = write_blk(sb, type, blk, buf)) < 0)
1061 /* Remove given block from the list of blocks with free entries */
1062 -static int remove_free_dqentry(struct file *filp, struct mem_dqinfo *info, dqbuf_t buf, uint blk)
1063 +static int remove_free_dqentry(struct super_block *sb, int type, dqbuf_t buf, uint blk)
1065 dqbuf_t tmpbuf = getdqbuf();
1066 + struct mem_dqinfo *info = sb_dqinfo(sb, type);
1067 struct v2_disk_dqdbheader *dh = (struct v2_disk_dqdbheader *)buf;
1068 uint nextblk = le32_to_cpu(dh->dqdh_next_free), prevblk = le32_to_cpu(dh->dqdh_prev_free);
1070 @@ -227,26 +204,27 @@
1074 - if ((err = read_blk(filp, nextblk, tmpbuf)) < 0)
1075 + if ((err = read_blk(sb, type, nextblk, tmpbuf)) < 0)
1077 ((struct v2_disk_dqdbheader *)tmpbuf)->dqdh_prev_free = dh->dqdh_prev_free;
1078 - if ((err = write_blk(filp, nextblk, tmpbuf)) < 0)
1079 + if ((err = write_blk(sb, type, nextblk, tmpbuf)) < 0)
1083 - if ((err = read_blk(filp, prevblk, tmpbuf)) < 0)
1084 + if ((err = read_blk(sb, type, prevblk, tmpbuf)) < 0)
1086 ((struct v2_disk_dqdbheader *)tmpbuf)->dqdh_next_free = dh->dqdh_next_free;
1087 - if ((err = write_blk(filp, prevblk, tmpbuf)) < 0)
1088 + if ((err = write_blk(sb, type, prevblk, tmpbuf)) < 0)
1092 info->u.v2_i.dqi_free_entry = nextblk;
1093 - mark_info_dirty(info);
1094 + mark_info_dirty(sb, type);
1097 dh->dqdh_next_free = dh->dqdh_prev_free = cpu_to_le32(0);
1098 - if (write_blk(filp, blk, buf) < 0) /* No matter whether write succeeds block is out of list */
1099 + /* No matter whether write succeeds block is out of list */
1100 + if (write_blk(sb, type, blk, buf) < 0)
1101 printk(KERN_ERR "VFS: Can't write block (%u) with free entries.\n", blk);
1104 @@ -255,9 +233,10 @@
1107 /* Insert given block to the beginning of list with free entries */
1108 -static int insert_free_dqentry(struct file *filp, struct mem_dqinfo *info, dqbuf_t buf, uint blk)
1109 +static int insert_free_dqentry(struct super_block *sb, int type, dqbuf_t buf, uint blk)
1111 dqbuf_t tmpbuf = getdqbuf();
1112 + struct mem_dqinfo *info = sb_dqinfo(sb, type);
1113 struct v2_disk_dqdbheader *dh = (struct v2_disk_dqdbheader *)buf;
1116 @@ -265,18 +244,18 @@
1118 dh->dqdh_next_free = cpu_to_le32(info->u.v2_i.dqi_free_entry);
1119 dh->dqdh_prev_free = cpu_to_le32(0);
1120 - if ((err = write_blk(filp, blk, buf)) < 0)
1121 + if ((err = write_blk(sb, type, blk, buf)) < 0)
1123 if (info->u.v2_i.dqi_free_entry) {
1124 - if ((err = read_blk(filp, info->u.v2_i.dqi_free_entry, tmpbuf)) < 0)
1125 + if ((err = read_blk(sb, type, info->u.v2_i.dqi_free_entry, tmpbuf)) < 0)
1127 ((struct v2_disk_dqdbheader *)tmpbuf)->dqdh_prev_free = cpu_to_le32(blk);
1128 - if ((err = write_blk(filp, info->u.v2_i.dqi_free_entry, tmpbuf)) < 0)
1129 + if ((err = write_blk(sb, type, info->u.v2_i.dqi_free_entry, tmpbuf)) < 0)
1133 info->u.v2_i.dqi_free_entry = blk;
1134 - mark_info_dirty(info);
1135 + mark_info_dirty(sb, type);
1140 /* Find space for dquot */
1141 static uint find_free_dqentry(struct dquot *dquot, int *err)
1143 - struct file *filp = sb_dqopt(dquot->dq_sb)->files[dquot->dq_type];
1144 - struct mem_dqinfo *info = sb_dqopt(dquot->dq_sb)->info+dquot->dq_type;
1145 + struct super_block *sb = dquot->dq_sb;
1146 + struct mem_dqinfo *info = sb_dqopt(sb)->info+dquot->dq_type;
1148 struct v2_disk_dqdbheader *dh;
1149 struct v2_disk_dqblk *ddquot;
1150 @@ -303,22 +282,23 @@
1151 ddquot = GETENTRIES(buf);
1152 if (info->u.v2_i.dqi_free_entry) {
1153 blk = info->u.v2_i.dqi_free_entry;
1154 - if ((*err = read_blk(filp, blk, buf)) < 0)
1155 + if ((*err = read_blk(sb, dquot->dq_type, blk, buf)) < 0)
1159 - blk = get_free_dqblk(filp, info);
1160 + blk = get_free_dqblk(sb, dquot->dq_type);
1166 memset(buf, 0, V2_DQBLKSIZE);
1167 - info->u.v2_i.dqi_free_entry = blk; /* This is enough as block is already zeroed and entry list is empty... */
1168 - mark_info_dirty(info);
1169 + /* This is enough as block is already zeroed and entry list is empty... */
1170 + info->u.v2_i.dqi_free_entry = blk;
1171 + mark_info_dirty(sb, dquot->dq_type);
1173 if (le16_to_cpu(dh->dqdh_entries)+1 >= V2_DQSTRINBLK) /* Block will be full? */
1174 - if ((*err = remove_free_dqentry(filp, info, buf, blk)) < 0) {
1175 + if ((*err = remove_free_dqentry(sb, dquot->dq_type, buf, blk)) < 0) {
1176 printk(KERN_ERR "VFS: find_free_dqentry(): Can't remove block (%u) from entry free list.\n", blk);
1183 - if ((*err = write_blk(filp, blk, buf)) < 0) {
1184 + if ((*err = write_blk(sb, dquot->dq_type, blk, buf)) < 0) {
1185 printk(KERN_ERR "VFS: find_free_dqentry(): Can't write quota data block %u.\n", blk);
1189 /* Insert reference to structure into the trie */
1190 static int do_insert_tree(struct dquot *dquot, uint *treeblk, int depth)
1192 - struct file *filp = sb_dqopt(dquot->dq_sb)->files[dquot->dq_type];
1193 - struct mem_dqinfo *info = sb_dqopt(dquot->dq_sb)->info + dquot->dq_type;
1194 + struct super_block *sb = dquot->dq_sb;
1196 int ret = 0, newson = 0, newact = 0;
1199 if (!(buf = getdqbuf()))
1202 - ret = get_free_dqblk(filp, info);
1203 + ret = get_free_dqblk(sb, dquot->dq_type);
1211 - if ((ret = read_blk(filp, *treeblk, buf)) < 0) {
1212 + if ((ret = read_blk(sb, dquot->dq_type, *treeblk, buf)) < 0) {
1213 printk(KERN_ERR "VFS: Can't read tree quota block %u.\n", *treeblk);
1216 @@ -389,10 +368,10 @@
1217 ret = do_insert_tree(dquot, &newblk, depth+1);
1218 if (newson && ret >= 0) {
1219 ref[GETIDINDEX(dquot->dq_id, depth)] = cpu_to_le32(newblk);
1220 - ret = write_blk(filp, *treeblk, buf);
1221 + ret = write_blk(sb, dquot->dq_type, *treeblk, buf);
1223 else if (newact && ret < 0)
1224 - put_free_dqblk(filp, info, buf, *treeblk);
1225 + put_free_dqblk(sb, dquot->dq_type, buf, *treeblk);
1229 @@ -411,19 +390,14 @@
1230 static int v2_write_dquot(struct dquot *dquot)
1232 int type = dquot->dq_type;
1233 - struct file *filp;
1237 struct v2_disk_dqblk ddquot, empty;
1240 if ((ret = dq_insert_tree(dquot)) < 0) {
1241 - printk(KERN_ERR "VFS: Error %Zd occurred while creating quota.\n", ret);
1242 + printk(KERN_ERR "VFS: Error %d occurred while creating quota.\n", ret);
1245 - filp = sb_dqopt(dquot->dq_sb)->files[type];
1246 - offset = dquot->dq_off;
1247 mem2diskdqb(&ddquot, &dquot->dq_dqb, dquot->dq_id);
1248 /* Argh... We may need to write structure full of zeroes but that would be
1249 * treated as an empty place by the rest of the code. Format change would
1250 @@ -431,10 +405,10 @@
1251 memset(&empty, 0, sizeof(struct v2_disk_dqblk));
1252 if (!memcmp(&empty, &ddquot, sizeof(struct v2_disk_dqblk)))
1253 ddquot.dqb_itime = cpu_to_le64(1);
1255 - set_fs(KERNEL_DS);
1256 - ret = filp->f_op->write(filp, (char *)&ddquot, sizeof(struct v2_disk_dqblk), &offset);
1259 + ret = dquot->dq_sb->s_op->quota_write(dquot->dq_sb, type,
1260 + (char *)&ddquot, sizeof(struct v2_disk_dqblk), dquot->dq_off);
1262 if (ret != sizeof(struct v2_disk_dqblk)) {
1263 printk(KERN_WARNING "VFS: dquota write failed on dev %s\n", dquot->dq_sb->s_id);
1266 /* Free dquot entry in data block */
1267 static int free_dqentry(struct dquot *dquot, uint blk)
1269 - struct file *filp = sb_dqopt(dquot->dq_sb)->files[dquot->dq_type];
1270 - struct mem_dqinfo *info = sb_dqopt(dquot->dq_sb)->info + dquot->dq_type;
1271 + struct super_block *sb = dquot->dq_sb;
1272 + int type = dquot->dq_type;
1273 struct v2_disk_dqdbheader *dh;
1274 dqbuf_t buf = getdqbuf();
1276 @@ -459,34 +433,39 @@
1279 if (dquot->dq_off >> V2_DQBLKSIZE_BITS != blk) {
1280 - printk(KERN_ERR "VFS: Quota structure has offset to other block (%u) than it should (%u).\n", blk, (uint)(dquot->dq_off >> V2_DQBLKSIZE_BITS));
1281 + printk(KERN_ERR "VFS: Quota structure has offset to other "
1282 + "block (%u) than it should (%u).\n", blk,
1283 + (uint)(dquot->dq_off >> V2_DQBLKSIZE_BITS));
1286 - if ((ret = read_blk(filp, blk, buf)) < 0) {
1287 + if ((ret = read_blk(sb, type, blk, buf)) < 0) {
1288 printk(KERN_ERR "VFS: Can't read quota data block %u\n", blk);
1291 dh = (struct v2_disk_dqdbheader *)buf;
1292 dh->dqdh_entries = cpu_to_le16(le16_to_cpu(dh->dqdh_entries)-1);
1293 if (!le16_to_cpu(dh->dqdh_entries)) { /* Block got free? */
1294 - if ((ret = remove_free_dqentry(filp, info, buf, blk)) < 0 ||
1295 - (ret = put_free_dqblk(filp, info, buf, blk)) < 0) {
1296 - printk(KERN_ERR "VFS: Can't move quota data block (%u) to free list.\n", blk);
1297 + if ((ret = remove_free_dqentry(sb, type, buf, blk)) < 0 ||
1298 + (ret = put_free_dqblk(sb, type, buf, blk)) < 0) {
1299 + printk(KERN_ERR "VFS: Can't move quota data block (%u) "
1300 + "to free list.\n", blk);
1305 - memset(buf+(dquot->dq_off & ((1 << V2_DQBLKSIZE_BITS)-1)), 0, sizeof(struct v2_disk_dqblk));
1306 + memset(buf+(dquot->dq_off & ((1 << V2_DQBLKSIZE_BITS)-1)), 0,
1307 + sizeof(struct v2_disk_dqblk));
1308 if (le16_to_cpu(dh->dqdh_entries) == V2_DQSTRINBLK-1) {
1309 /* Insert will write block itself */
1310 - if ((ret = insert_free_dqentry(filp, info, buf, blk)) < 0) {
1311 + if ((ret = insert_free_dqentry(sb, type, buf, blk)) < 0) {
1312 printk(KERN_ERR "VFS: Can't insert quota data block (%u) to free entry list.\n", blk);
1317 - if ((ret = write_blk(filp, blk, buf)) < 0) {
1318 - printk(KERN_ERR "VFS: Can't write quota data block %u\n", blk);
1319 + if ((ret = write_blk(sb, type, blk, buf)) < 0) {
1320 + printk(KERN_ERR "VFS: Can't write quota data "
1321 + "block %u\n", blk);
1326 /* Remove reference to dquot from tree */
1327 static int remove_tree(struct dquot *dquot, uint *blk, int depth)
1329 - struct file *filp = sb_dqopt(dquot->dq_sb)->files[dquot->dq_type];
1330 - struct mem_dqinfo *info = sb_dqopt(dquot->dq_sb)->info + dquot->dq_type;
1331 + struct super_block *sb = dquot->dq_sb;
1332 + int type = dquot->dq_type;
1333 dqbuf_t buf = getdqbuf();
1340 - if ((ret = read_blk(filp, *blk, buf)) < 0) {
1341 + if ((ret = read_blk(sb, type, *blk, buf)) < 0) {
1342 printk(KERN_ERR "VFS: Can't read quota data block %u\n", *blk);
1345 @@ -524,12 +503,13 @@
1346 ref[GETIDINDEX(dquot->dq_id, depth)] = cpu_to_le32(0);
1347 for (i = 0; i < V2_DQBLKSIZE && !buf[i]; i++); /* Block got empty? */
1348 if (i == V2_DQBLKSIZE) {
1349 - put_free_dqblk(filp, info, buf, *blk);
1350 + put_free_dqblk(sb, type, buf, *blk);
1354 - if ((ret = write_blk(filp, *blk, buf)) < 0)
1355 - printk(KERN_ERR "VFS: Can't write quota tree block %u.\n", *blk);
1356 + if ((ret = write_blk(sb, type, *blk, buf)) < 0)
1357 + printk(KERN_ERR "VFS: Can't write quota tree "
1358 + "block %u.\n", *blk);
1363 /* Find entry in block */
1364 static loff_t find_block_dqentry(struct dquot *dquot, uint blk)
1366 - struct file *filp = sb_dqopt(dquot->dq_sb)->files[dquot->dq_type];
1367 dqbuf_t buf = getdqbuf();
1370 @@ -557,27 +536,31 @@
1374 - if ((ret = read_blk(filp, blk, buf)) < 0) {
1375 + if ((ret = read_blk(dquot->dq_sb, dquot->dq_type, blk, buf)) < 0) {
1376 printk(KERN_ERR "VFS: Can't read quota tree block %u.\n", blk);
1380 - for (i = 0; i < V2_DQSTRINBLK && le32_to_cpu(ddquot[i].dqb_id) != dquot->dq_id; i++);
1381 + for (i = 0; i < V2_DQSTRINBLK &&
1382 + le32_to_cpu(ddquot[i].dqb_id) != dquot->dq_id; i++);
1383 else { /* ID 0 as a bit more complicated searching... */
1384 struct v2_disk_dqblk fakedquot;
1386 memset(&fakedquot, 0, sizeof(struct v2_disk_dqblk));
1387 for (i = 0; i < V2_DQSTRINBLK; i++)
1388 - if (!le32_to_cpu(ddquot[i].dqb_id) && memcmp(&fakedquot, ddquot+i, sizeof(struct v2_disk_dqblk)))
1389 + if (!le32_to_cpu(ddquot[i].dqb_id) &&
1390 + memcmp(&fakedquot, ddquot+i, sizeof(struct v2_disk_dqblk)))
1393 if (i == V2_DQSTRINBLK) {
1394 - printk(KERN_ERR "VFS: Quota for id %u referenced but not present.\n", dquot->dq_id);
1395 + printk(KERN_ERR "VFS: Quota for id %u referenced "
1396 + "but not present.\n", dquot->dq_id);
1401 - ret = (blk << V2_DQBLKSIZE_BITS) + sizeof(struct v2_disk_dqdbheader) + i * sizeof(struct v2_disk_dqblk);
1402 + ret = (blk << V2_DQBLKSIZE_BITS) + sizeof(struct
1403 + v2_disk_dqdbheader) + i * sizeof(struct v2_disk_dqblk);
1407 @@ -586,14 +569,13 @@
1408 /* Find entry for given id in the tree */
1409 static loff_t find_tree_dqentry(struct dquot *dquot, uint blk, int depth)
1411 - struct file *filp = sb_dqopt(dquot->dq_sb)->files[dquot->dq_type];
1412 dqbuf_t buf = getdqbuf();
1414 u32 *ref = (u32 *)buf;
1418 - if ((ret = read_blk(filp, blk, buf)) < 0) {
1419 + if ((ret = read_blk(dquot->dq_sb, dquot->dq_type, blk, buf)) < 0) {
1420 printk(KERN_ERR "VFS: Can't read quota tree block %u.\n", blk);
1423 @@ -619,16 +601,13 @@
1424 static int v2_read_dquot(struct dquot *dquot)
1426 int type = dquot->dq_type;
1427 - struct file *filp;
1430 struct v2_disk_dqblk ddquot, empty;
1433 - filp = sb_dqopt(dquot->dq_sb)->files[type];
1435 #ifdef __QUOTA_V2_PARANOIA
1436 - if (!filp || !dquot->dq_sb) { /* Invalidated quota? */
1437 + /* Invalidated quota? */
1438 + if (!dquot->dq_sb || !dquot->dq_sb->s_op->quota_read) {
1439 printk(KERN_ERR "VFS: Quota invalidated while reading!\n");
1443 offset = find_dqentry(dquot);
1444 if (offset <= 0) { /* Entry not present? */
1446 - printk(KERN_ERR "VFS: Can't read quota structure for id %u.\n", dquot->dq_id);
1447 + printk(KERN_ERR "VFS: Can't read quota "
1448 + "structure for id %u.\n", dquot->dq_id);
1450 dquot->dq_flags |= DQ_FAKE;
1451 memset(&dquot->dq_dqb, 0, sizeof(struct mem_dqblk));
1452 @@ -644,12 +624,13 @@
1455 dquot->dq_off = offset;
1457 - set_fs(KERNEL_DS);
1458 - if ((ret = filp->f_op->read(filp, (char *)&ddquot, sizeof(struct v2_disk_dqblk), &offset)) != sizeof(struct v2_disk_dqblk)) {
1459 + if ((ret = dquot->dq_sb->s_op->quota_read(dquot->dq_sb, type,
1460 + (char *)&ddquot, sizeof(struct v2_disk_dqblk), offset))
1461 + != sizeof(struct v2_disk_dqblk)) {
1464 - printk(KERN_ERR "VFS: Error while reading quota structure for id %u.\n", dquot->dq_id);
1465 + printk(KERN_ERR "VFS: Error while reading quota "
1466 + "structure for id %u.\n", dquot->dq_id);
1467 memset(&ddquot, 0, sizeof(struct v2_disk_dqblk));
1471 if (!memcmp(&empty, &ddquot, sizeof(struct v2_disk_dqblk)))
1472 ddquot.dqb_itime = 0;
1475 disk2memdqb(&dquot->dq_dqb, &ddquot);
1478 @@ -668,15 +648,13 @@
1482 -/* Commit changes of dquot to disk - it might also mean deleting it when quota became fake one and user has no blocks... */
1483 -static int v2_commit_dquot(struct dquot *dquot)
1484 +/* Check whether dquot should not be deleted. We know we are
1485 + * * the only one operating on dquot (thanks to dq_lock) */
1486 +static int v2_release_dquot(struct dquot *dquot)
1488 - /* We clear the flag everytime so we don't loop when there was an IO error... */
1489 - dquot->dq_flags &= ~DQ_MOD;
1490 - if (dquot->dq_flags & DQ_FAKE && !(dquot->dq_dqb.dqb_curinodes | dquot->dq_dqb.dqb_curspace))
1491 + if (test_bit(DQ_FAKE_B, &dquot->dq_flags) && !(dquot->dq_dqb.dqb_curinodes | dquot->dq_dqb.dqb_curspace))
1492 return v2_delete_dquot(dquot);
1494 - return v2_write_dquot(dquot);
1498 static struct quota_format_ops v2_format_ops = {
1500 .write_file_info = v2_write_file_info,
1501 .free_file_info = NULL,
1502 .read_dqblk = v2_read_dquot,
1503 - .commit_dqblk = v2_commit_dquot,
1504 + .commit_dqblk = v2_write_dquot,
1505 + .release_dqblk = v2_release_dquot,
1508 static struct quota_format_type v2_quota_format = {
1509 Index: linux-2.6.5-7.276/fs/quota.c
1510 ===================================================================
1511 --- linux-2.6.5-7.276.orig/fs/quota.c 2006-09-15 17:44:47.000000000 +0800
1512 +++ linux-2.6.5-7.276/fs/quota.c 2006-10-26 16:47:10.000000000 +0800
1514 #include <linux/smp_lock.h>
1515 #include <linux/security.h>
1516 #include <linux/audit.h>
1517 +#include <linux/syscalls.h>
1518 +#include <linux/buffer_head.h>
1521 /* Check validity of quotactl */
1522 static int check_quotactl_valid(struct super_block *sb, int type, int cmd, qid_t id)
1523 @@ -134,16 +137,54 @@
1527 +void quota_sync_sb(struct super_block *sb, int type)
1530 + struct inode *discard[MAXQUOTAS];
1532 + sb->s_qcop->quota_sync(sb, type);
1533 + /* This is not very clever (and fast) but currently I don't know about
1534 + * any other simple way of getting quota data to disk and we must get
1535 + * them there for userspace to be visible... */
1536 + if (sb->s_op->sync_fs)
1537 + sb->s_op->sync_fs(sb, 1);
1538 + sync_blockdev(sb->s_bdev);
1540 + /* Now when everything is written we can discard the pagecache so
1541 + * that userspace sees the changes. We need i_sem and so we could
1542 + * not do it inside dqonoff_sem. Moreover we need to be carefull
1543 + * about races with quotaoff() (that is the reason why we have own
1544 + * reference to inode). */
1545 + down(&sb_dqopt(sb)->dqonoff_sem);
1546 + for (cnt = 0; cnt < MAXQUOTAS; cnt++) {
1547 + discard[cnt] = NULL;
1548 + if (type != -1 && cnt != type)
1550 + if (!sb_has_quota_enabled(sb, cnt))
1552 + discard[cnt] = igrab(sb_dqopt(sb)->files[cnt]);
1554 + up(&sb_dqopt(sb)->dqonoff_sem);
1555 + for (cnt = 0; cnt < MAXQUOTAS; cnt++) {
1556 + if (discard[cnt]) {
1557 + down(&discard[cnt]->i_sem);
1558 + truncate_inode_pages(&discard[cnt]->i_data, 0);
1559 + up(&discard[cnt]->i_sem);
1560 + iput(discard[cnt]);
1565 void sync_dquots(struct super_block *sb, int type)
1568 if (sb->s_qcop->quota_sync)
1569 - sb->s_qcop->quota_sync(sb, type);
1570 + quota_sync_sb(sb, type);
1573 - while ((sb = get_super_to_sync(type))) {
1574 + while ((sb = get_super_to_sync(type)) != NULL) {
1575 if (sb->s_qcop->quota_sync)
1576 - sb->s_qcop->quota_sync(sb, type);
1577 + quota_sync_sb(sb, type);
1581 Index: linux-2.6.5-7.276/fs/ext3/inode.c
1582 ===================================================================
1583 --- linux-2.6.5-7.276.orig/fs/ext3/inode.c 2006-09-15 17:44:48.000000000 +0800
1584 +++ linux-2.6.5-7.276/fs/ext3/inode.c 2006-10-26 16:47:10.000000000 +0800
1585 @@ -1015,7 +1015,7 @@
1591 ext3_journal_dirty_data(handle_t *handle, struct buffer_head *bh)
1593 int err = journal_dirty_data(handle, bh);
1594 Index: linux-2.6.5-7.276/fs/ext3/super.c
1595 ===================================================================
1596 --- linux-2.6.5-7.276.orig/fs/ext3/super.c 2006-09-15 17:44:48.000000000 +0800
1597 +++ linux-2.6.5-7.276/fs/ext3/super.c 2006-10-26 16:47:10.000000000 +0800
1599 #include <linux/vfs.h>
1600 #include <linux/random.h>
1601 #include <asm/uaccess.h>
1602 +#include <linux/quotaops.h>
1606 @@ -505,7 +506,33 @@
1607 ext3_discard_reservation(inode);
1610 -static struct dquot_operations ext3_qops;
1611 +#ifdef CONFIG_QUOTA
1613 +static int ext3_dquot_initialize(struct inode *inode, int type);
1614 +static int ext3_dquot_drop(struct inode *inode);
1615 +static int ext3_write_dquot(struct dquot *dquot);
1616 +static int ext3_acquire_dquot(struct dquot *dquot);
1617 +static int ext3_release_dquot(struct dquot *dquot);
1618 +static int ext3_write_info(struct super_block *sb, int type);
1619 +static ssize_t ext3_quota_read(struct super_block *sb, int type, char *data,
1620 + size_t len, loff_t off);
1621 +static ssize_t ext3_quota_write(struct super_block *sb, int type,
1622 + const char *data, size_t len, loff_t off);
1624 +static struct dquot_operations ext3_quota_operations = {
1625 + .initialize = ext3_dquot_initialize,
1626 + .drop = ext3_dquot_drop,
1627 + .alloc_space = dquot_alloc_space,
1628 + .alloc_inode = dquot_alloc_inode,
1629 + .free_space = dquot_free_space,
1630 + .free_inode = dquot_free_inode,
1631 + .transfer = dquot_transfer,
1632 + .write_dquot = ext3_write_dquot,
1633 + .acquire_dquot = ext3_acquire_dquot,
1634 + .release_dquot = ext3_release_dquot,
1635 + .write_info = ext3_write_info
1639 static struct super_operations ext3_sops = {
1640 .alloc_inode = ext3_alloc_inode,
1641 @@ -522,6 +549,10 @@
1642 .statfs = ext3_statfs,
1643 .remount_fs = ext3_remount,
1644 .clear_inode = ext3_clear_inode,
1645 +#ifdef CONFIG_QUOTA
1646 + .quota_read = ext3_quota_read,
1647 + .quota_write = ext3_quota_write,
1651 struct dentry *ext3_get_parent(struct dentry *child);
1652 @@ -1335,7 +1366,9 @@
1654 sb->s_op = &ext3_sops;
1655 sb->s_export_op = &ext3_export_ops;
1656 - sb->dq_op = &ext3_qops;
1657 +#ifdef CONFIG_QUOTA
1658 + sb->dq_op = &ext3_quota_operations;
1660 INIT_LIST_HEAD(&sbi->s_orphan); /* unlinked but open files */
1663 @@ -1998,70 +2031,200 @@
1667 -/* Blocks: (2 data blocks) * (3 indirect + 1 descriptor + 1 bitmap) + superblock */
1668 -#define EXT3_OLD_QFMT_BLOCKS 11
1669 -/* Blocks: quota info + (4 pointer blocks + 1 entry block) * (3 indirect + 1 descriptor + 1 bitmap) + superblock */
1670 -#define EXT3_V0_QFMT_BLOCKS 27
1672 -static int (*old_write_dquot)(struct dquot *dquot);
1673 -static void (*old_drop_dquot)(struct inode *inode);
1675 -static int fmt_to_blocks(int fmt)
1678 - case QFMT_VFS_OLD:
1679 - return EXT3_OLD_QFMT_BLOCKS;
1681 - return EXT3_V0_QFMT_BLOCKS;
1683 - return EXT3_MAX_TRANS_DATA;
1684 +static inline struct inode *dquot_to_inode(struct dquot *dquot)
1686 + return sb_dqopt(dquot->dq_sb)->files[dquot->dq_type];
1689 +static int ext3_dquot_initialize(struct inode *inode, int type)
1694 + /* We may create quota structure so we need to reserve enough blocks */
1695 + handle = ext3_journal_start(inode, 2*EXT3_QUOTA_INIT_BLOCKS);
1696 + if (IS_ERR(handle))
1697 + return PTR_ERR(handle);
1698 + ret = dquot_initialize(inode, type);
1699 + err = ext3_journal_stop(handle);
1705 +static int ext3_dquot_drop(struct inode *inode)
1710 + /* We may delete quota structure so we need to reserve enough blocks */
1711 + handle = ext3_journal_start(inode, 2*EXT3_QUOTA_INIT_BLOCKS);
1712 + if (IS_ERR(handle))
1713 + return PTR_ERR(handle);
1714 + ret = dquot_drop(inode);
1715 + err = ext3_journal_stop(handle);
1721 static int ext3_write_dquot(struct dquot *dquot)
1728 - struct quota_info *dqopt = sb_dqopt(dquot->dq_sb);
1729 - struct inode *qinode;
1730 + struct inode *inode;
1732 - nblocks = fmt_to_blocks(dqopt->info[dquot->dq_type].dqi_format->qf_fmt_id);
1733 - qinode = dqopt->files[dquot->dq_type]->f_dentry->d_inode;
1734 - handle = ext3_journal_start(qinode, nblocks);
1735 - if (IS_ERR(handle)) {
1736 - ret = PTR_ERR(handle);
1739 - ret = old_write_dquot(dquot);
1740 + inode = dquot_to_inode(dquot);
1741 + handle = ext3_journal_start(inode,
1742 + EXT3_QUOTA_TRANS_BLOCKS);
1743 + if (IS_ERR(handle))
1744 + return PTR_ERR(handle);
1745 + ret = dquot_commit(dquot);
1746 err = ext3_journal_stop(handle);
1754 -static void ext3_drop_dquot(struct inode *inode)
1755 +static int ext3_acquire_dquot(struct dquot *dquot)
1757 - int nblocks, type;
1758 - struct quota_info *dqopt = sb_dqopt(inode->i_sb);
1762 - for (type = 0; type < MAXQUOTAS; type++) {
1763 - if (sb_has_quota_enabled(inode->i_sb, type))
1766 - if (type < MAXQUOTAS)
1767 - nblocks = fmt_to_blocks(dqopt->info[type].dqi_format->qf_fmt_id);
1769 - nblocks = 0; /* No quota => no drop */
1770 - handle = ext3_journal_start(inode, 2*nblocks);
1771 + handle = ext3_journal_start(dquot_to_inode(dquot),
1772 + EXT3_QUOTA_INIT_BLOCKS);
1775 - old_drop_dquot(inode);
1776 - ext3_journal_stop(handle);
1778 + return PTR_ERR(handle);
1779 + ret = dquot_acquire(dquot);
1780 + err = ext3_journal_stop(handle);
1786 +static int ext3_release_dquot(struct dquot *dquot)
1791 + handle = ext3_journal_start(dquot_to_inode(dquot),
1792 + EXT3_QUOTA_INIT_BLOCKS);
1793 + if (IS_ERR(handle))
1794 + return PTR_ERR(handle);
1795 + ret = dquot_release(dquot);
1796 + err = ext3_journal_stop(handle);
1802 +static int ext3_write_info(struct super_block *sb, int type)
1807 + /* Data block + inode block */
1808 + handle = ext3_journal_start(sb->s_root->d_inode, 2);
1809 + if (IS_ERR(handle))
1810 + return PTR_ERR(handle);
1811 + ret = dquot_commit_info(sb, type);
1812 + err = ext3_journal_stop(handle);
1818 +/* Read data from quotafile - avoid pagecache and such because we cannot afford
1819 + * acquiring the locks... As quota files are never truncated and quota code
1820 + * itself serializes the operations (and noone else should touch the files)
1821 + * we don't have to be afraid of races */
1822 +static ssize_t ext3_quota_read(struct super_block *sb, int type, char *data,
1823 + size_t len, loff_t off)
1825 + struct inode *inode = sb_dqopt(sb)->files[type];
1826 + sector_t blk = off >> EXT3_BLOCK_SIZE_BITS(sb);
1828 + int offset = off & (sb->s_blocksize - 1);
1831 + struct buffer_head *bh;
1832 + loff_t i_size = i_size_read(inode);
1836 + if (off+len > i_size)
1839 + while (toread > 0) {
1840 + tocopy = sb->s_blocksize - offset < toread ?
1841 + sb->s_blocksize - offset : toread;
1842 + bh = ext3_bread(NULL, inode, blk, 0, &err);
1845 + if (!bh) /* A hole? */
1846 + memset(data, 0, tocopy);
1848 + memcpy(data, bh->b_data+offset, tocopy);
1858 +/* Write to quotafile (we know the transaction is already started and has
1859 + * enough credits) */
1860 +static ssize_t ext3_quota_write(struct super_block *sb, int type,
1861 + const char *data, size_t len, loff_t off)
1863 + struct inode *inode = sb_dqopt(sb)->files[type];
1864 + sector_t blk = off >> EXT3_BLOCK_SIZE_BITS(sb);
1866 + int offset = off & (sb->s_blocksize - 1);
1868 + size_t towrite = len;
1869 + struct buffer_head *bh;
1870 + handle_t *handle = journal_current_handle();
1872 + down(&inode->i_sem);
1873 + while (towrite > 0) {
1874 + tocopy = sb->s_blocksize - offset < towrite ?
1875 + sb->s_blocksize - offset : towrite;
1876 + bh = ext3_bread(handle, inode, blk, 1, &err);
1881 + memcpy(bh->b_data+offset, data, tocopy);
1882 + flush_dcache_page(bh->b_page);
1883 + unlock_buffer(bh);
1884 + /* Always do at least ordered writes for quotas */
1885 + err = ext3_journal_dirty_data(handle, bh);
1886 + mark_buffer_dirty(bh);
1891 + towrite -= tocopy;
1896 + if (len == towrite)
1898 + if (inode->i_size < off+len-towrite) {
1899 + i_size_write(inode, off+len-towrite);
1900 + EXT3_I(inode)->i_disksize = inode->i_size;
1902 + inode->i_version++;
1903 + inode->i_mtime = inode->i_ctime = CURRENT_TIME;
1904 + ext3_mark_inode_dirty(handle, inode);
1905 + up(&inode->i_sem);
1906 + return len - towrite;
1911 static struct super_block *ext3_get_sb(struct file_system_type *fs_type,
1912 @@ -2086,13 +2249,7 @@
1913 err = init_inodecache();
1916 -#ifdef CONFIG_QUOTA
1917 - init_dquot_operations(&ext3_qops);
1918 - old_write_dquot = ext3_qops.write_dquot;
1919 - old_drop_dquot = ext3_qops.drop;
1920 - ext3_qops.write_dquot = ext3_write_dquot;
1921 - ext3_qops.drop = ext3_drop_dquot;
1924 err = register_filesystem_lifo(&ext3_fs_type);
1927 Index: linux-2.6.5-7.276/fs/quota_v1.c
1928 ===================================================================
1929 --- linux-2.6.5-7.276.orig/fs/quota_v1.c 2006-09-15 17:44:47.000000000 +0800
1930 +++ linux-2.6.5-7.276/fs/quota_v1.c 2006-10-26 16:47:10.000000000 +0800
1932 #include <linux/init.h>
1933 #include <linux/module.h>
1935 -#include <asm/uaccess.h>
1936 #include <asm/byteorder.h>
1938 MODULE_AUTHOR("Jan Kara");
1940 static int v1_read_dqblk(struct dquot *dquot)
1942 int type = dquot->dq_type;
1943 - struct file *filp;
1946 struct v1_disk_dqblk dqblk;
1948 - filp = sb_dqopt(dquot->dq_sb)->files[type];
1949 - if (filp == (struct file *)NULL)
1950 + if (!sb_dqopt(dquot->dq_sb)->files[type])
1953 - /* Now we are sure filp is valid */
1954 - offset = v1_dqoff(dquot->dq_id);
1955 /* Set structure to 0s in case read fails/is after end of file */
1956 memset(&dqblk, 0, sizeof(struct v1_disk_dqblk));
1958 - set_fs(KERNEL_DS);
1959 - filp->f_op->read(filp, (char *)&dqblk, sizeof(struct v1_disk_dqblk), &offset);
1961 + dquot->dq_sb->s_op->quota_read(dquot->dq_sb, type, (char *)&dqblk, sizeof(struct v1_disk_dqblk), v1_dqoff(dquot->dq_id));
1963 v1_disk2mem_dqblk(&dquot->dq_dqb, &dqblk);
1964 if (dquot->dq_dqb.dqb_bhardlimit == 0 && dquot->dq_dqb.dqb_bsoftlimit == 0 &&
1966 static int v1_commit_dqblk(struct dquot *dquot)
1968 short type = dquot->dq_type;
1969 - struct file *filp;
1973 struct v1_disk_dqblk dqblk;
1975 - filp = sb_dqopt(dquot->dq_sb)->files[type];
1976 - offset = v1_dqoff(dquot->dq_id);
1978 - set_fs(KERNEL_DS);
1981 * Note: clear the DQ_MOD flag unconditionally,
1982 * so we don't loop forever on failure.
1984 dqblk.dqb_itime = sb_dqopt(dquot->dq_sb)->info[type].dqi_igrace;
1988 - ret = filp->f_op->write(filp, (char *)&dqblk,
1989 - sizeof(struct v1_disk_dqblk), &offset);
1990 + if (sb_dqopt(dquot->dq_sb)->files[type])
1991 + ret = dquot->dq_sb->s_op->quota_write(dquot->dq_sb, type, (char *)&dqblk,
1992 + sizeof(struct v1_disk_dqblk), v1_dqoff(dquot->dq_id));
1994 if (ret != sizeof(struct v1_disk_dqblk)) {
1995 printk(KERN_WARNING "VFS: dquota write failed on dev %s\n",
1996 dquot->dq_sb->s_id);
2005 @@ -126,14 +108,11 @@
2007 static int v1_check_quota_file(struct super_block *sb, int type)
2009 - struct file *f = sb_dqopt(sb)->files[type];
2010 - struct inode *inode = f->f_dentry->d_inode;
2011 + struct inode *inode = sb_dqopt(sb)->files[type];
2014 struct v2_disk_dqheader dqhead;
2017 - loff_t offset = 0;
2019 static const uint quota_magics[] = V2_INITQMAGICS;
2021 @@ -145,10 +124,7 @@
2022 if ((blocks % sizeof(struct v1_disk_dqblk) * BLOCK_SIZE + off) % sizeof(struct v1_disk_dqblk))
2024 /* Doublecheck whether we didn't get file with new format - with old quotactl() this could happen */
2026 - set_fs(KERNEL_DS);
2027 - size = f->f_op->read(f, (char *)&dqhead, sizeof(struct v2_disk_dqheader), &offset);
2029 + size = sb->s_op->quota_read(sb, type, (char *)&dqhead, sizeof(struct v2_disk_dqheader), 0);
2030 if (size != sizeof(struct v2_disk_dqheader))
2031 return 1; /* Probably not new format */
2032 if (le32_to_cpu(dqhead.dqh_magic) != quota_magics[type])
2033 @@ -160,16 +136,10 @@
2034 static int v1_read_file_info(struct super_block *sb, int type)
2036 struct quota_info *dqopt = sb_dqopt(sb);
2039 - struct file *filp = dqopt->files[type];
2040 struct v1_disk_dqblk dqblk;
2043 - offset = v1_dqoff(0);
2045 - set_fs(KERNEL_DS);
2046 - if ((ret = filp->f_op->read(filp, (char *)&dqblk, sizeof(struct v1_disk_dqblk), &offset)) != sizeof(struct v1_disk_dqblk)) {
2047 + if ((ret = sb->s_op->quota_read(sb, type, (char *)&dqblk, sizeof(struct v1_disk_dqblk), v1_dqoff(0))) != sizeof(struct v1_disk_dqblk)) {
2051 @@ -178,38 +148,31 @@
2052 dqopt->info[type].dqi_igrace = dqblk.dqb_itime ? dqblk.dqb_itime : MAX_IQ_TIME;
2053 dqopt->info[type].dqi_bgrace = dqblk.dqb_btime ? dqblk.dqb_btime : MAX_DQ_TIME;
2059 static int v1_write_file_info(struct super_block *sb, int type)
2061 struct quota_info *dqopt = sb_dqopt(sb);
2063 - struct file *filp = dqopt->files[type];
2064 struct v1_disk_dqblk dqblk;
2068 dqopt->info[type].dqi_flags &= ~DQF_INFO_DIRTY;
2069 - offset = v1_dqoff(0);
2071 - set_fs(KERNEL_DS);
2072 - if ((ret = filp->f_op->read(filp, (char *)&dqblk, sizeof(struct v1_disk_dqblk), &offset)) != sizeof(struct v1_disk_dqblk)) {
2073 + if ((ret = sb->s_op->quota_read(sb, type, (char *)&dqblk,
2074 + sizeof(struct v1_disk_dqblk), v1_dqoff(0))) != sizeof(struct v1_disk_dqblk)) {
2079 dqblk.dqb_itime = dqopt->info[type].dqi_igrace;
2080 dqblk.dqb_btime = dqopt->info[type].dqi_bgrace;
2081 - offset = v1_dqoff(0);
2082 - ret = filp->f_op->write(filp, (char *)&dqblk, sizeof(struct v1_disk_dqblk), &offset);
2083 + ret = sb->s_op->quota_write(sb, type, (char *)&dqblk,
2084 + sizeof(struct v1_disk_dqblk), v1_dqoff(0));
2085 if (ret == sizeof(struct v1_disk_dqblk))
2096 fs/dquot.c | 370 +++++++++++++++++++++++++++++++++++------------
2098 fs/ext3/super.c | 271 +++++++++++++++++++++++++++-------
2099 fs/quota.c | 47 +++++
2100 fs/quota_v1.c | 63 +-------
2101 fs/quota_v2.c | 245 ++++++++++++++-----------------
2102 include/linux/ext3_jbd.h | 15 +
2103 include/linux/fs.h | 3
2104 include/linux/quota.h | 31 ++-
2105 include/linux/quotaops.h | 15 +
2106 include/linux/security.h | 6
2107 security/dummy.c | 2
2108 security/selinux/hooks.c | 4
2109 13 files changed, 716 insertions(+), 358 deletions(-)