1 Index: linux-2.6.5-7.283/include/linux/ext3_jbd.h
2 ===================================================================
3 --- linux-2.6.5-7.283.orig/include/linux/ext3_jbd.h
4 +++ linux-2.6.5-7.283/include/linux/ext3_jbd.h
5 @@ -72,6 +72,19 @@ extern int ext3_writepage_trans_blocks(s
7 #define EXT3_INDEX_EXTRA_TRANS_BLOCKS 8
10 +/* Amount of blocks needed for quota update - we know that the structure was
11 + * allocated so we need to update only inode+data */
12 +#define EXT3_QUOTA_TRANS_BLOCKS 2
13 +/* Amount of blocks needed for quota insert/delete - we do some block writes
14 + * but inode, sb and group updates are done only once */
15 +#define EXT3_QUOTA_INIT_BLOCKS (DQUOT_MAX_WRITES*\
16 + (EXT3_SINGLEDATA_TRANS_BLOCKS-3)+3)
18 +#define EXT3_QUOTA_TRANS_BLOCKS 0
19 +#define EXT3_QUOTA_INIT_BLOCKS 0
23 ext3_mark_iloc_dirty(handle_t *handle,
25 @@ -97,6 +110,8 @@ int ext3_mark_inode_dirty(handle_t *hand
26 void ext3_journal_abort_handle(const char *caller, const char *err_fn,
27 struct buffer_head *bh, handle_t *handle, int err);
29 +int ext3_journal_dirty_data(handle_t *handle, struct buffer_head *bh);
32 __ext3_journal_get_undo_access(const char *where, handle_t *handle,
33 struct buffer_head *bh, int *credits)
34 Index: linux-2.6.5-7.283/include/linux/fs.h
35 ===================================================================
36 --- linux-2.6.5-7.283.orig/include/linux/fs.h
37 +++ linux-2.6.5-7.283/include/linux/fs.h
38 @@ -967,6 +967,9 @@ struct super_operations {
39 void (*umount_begin) (struct super_block *);
41 int (*show_options)(struct seq_file *, struct vfsmount *);
43 + ssize_t (*quota_read)(struct super_block *, int, char *, size_t, loff_t);
44 + ssize_t (*quota_write)(struct super_block *, int, const char *, size_t, loff_t);
47 /* Inode state bits. Protected by inode_lock. */
48 Index: linux-2.6.5-7.283/include/linux/quota.h
49 ===================================================================
50 --- linux-2.6.5-7.283.orig/include/linux/quota.h
51 +++ linux-2.6.5-7.283/include/linux/quota.h
52 @@ -138,6 +138,10 @@ struct if_dqinfo {
53 #include <linux/dqblk_v1.h>
54 #include <linux/dqblk_v2.h>
56 +/* Maximal numbers of writes for quota operation (insert/delete/update)
57 + * (over all formats) - info block, 4 pointer blocks, data block */
58 +#define DQUOT_MAX_WRITES 6
61 * Data for one user/group kept in memory
63 @@ -168,22 +172,21 @@ struct mem_dqinfo {
69 #define DQF_MASK 0xffff /* Mask for format specific flags */
70 #define DQF_INFO_DIRTY_B 16
71 #define DQF_ANY_DQUOT_DIRTY_B 17
72 #define DQF_INFO_DIRTY (1 << DQF_INFO_DIRTY_B) /* Is info dirty? */
73 #define DQF_ANY_DQUOT_DIRTY (1 << DQF_ANY_DQUOT_DIRTY_B) /* Is any dquot dirty? */
75 -extern inline void mark_info_dirty(struct mem_dqinfo *info)
77 - set_bit(DQF_INFO_DIRTY_B, &info->dqi_flags);
80 +extern void mark_info_dirty(struct super_block *sb, int type);
81 #define info_dirty(info) test_bit(DQF_INFO_DIRTY_B, &(info)->dqi_flags)
82 #define info_any_dquot_dirty(info) test_bit(DQF_ANY_DQUOT_DIRTY_B, &(info)->dqi_flags)
83 #define info_any_dirty(info) (info_dirty(info) || info_any_dquot_dirty(info))
85 #define sb_dqopt(sb) (&(sb)->s_dquot)
86 +#define sb_dqinfo(sb, type) (sb_dqopt(sb)->info+(type))
90 @@ -204,6 +207,9 @@ extern struct dqstats dqstats;
94 +#define DQ_READ_B 4 /* dquot was read into memory */
95 +#define DQ_ACTIVE_B 5 /* dquot is active (dquot_release not called) */
96 +#define DQ_WAITFREE_B 6 /* dquot being waited (by invalidate_dquots) */
98 #define DQ_MOD (1 << DQ_MOD_B) /* dquot modified since read */
99 #define DQ_BLKS (1 << DQ_BLKS_B) /* uid/gid has been warned about blk limit */
100 @@ -239,18 +245,22 @@ struct quota_format_ops {
101 int (*free_file_info)(struct super_block *sb, int type); /* Called on quotaoff() */
102 int (*read_dqblk)(struct dquot *dquot); /* Read structure for one user */
103 int (*commit_dqblk)(struct dquot *dquot); /* Write (or delete) structure for one user */
104 + int (*release_dqblk)(struct dquot *dquot); /* Called when last reference to dquot is being dropped */
107 /* Operations working with dquots */
108 struct dquot_operations {
109 - void (*initialize) (struct inode *, int);
110 - void (*drop) (struct inode *);
111 + int (*initialize) (struct inode *, int);
112 + int (*drop) (struct inode *);
113 int (*alloc_space) (struct inode *, qsize_t, int);
114 int (*alloc_inode) (const struct inode *, unsigned long);
115 - void (*free_space) (struct inode *, qsize_t);
116 - void (*free_inode) (const struct inode *, unsigned long);
117 + int (*free_space) (struct inode *, qsize_t);
118 + int (*free_inode) (const struct inode *, unsigned long);
119 int (*transfer) (struct inode *, struct iattr *);
120 int (*write_dquot) (struct dquot *);
121 + int (*acquire_dquot) (struct dquot *); /* Quota is going to be created on disk */
122 + int (*release_dquot) (struct dquot *); /* Quota is going to be deleted from disk */
123 + int (*write_info) (struct super_block *, int); /* Write of quota "superblock" */
126 /* Operations handling requests from userspace */
127 @@ -283,7 +293,8 @@ struct quota_info {
128 struct semaphore dqio_sem; /* lock device while I/O in progress */
129 struct semaphore dqonoff_sem; /* Serialize quotaon & quotaoff */
130 struct rw_semaphore dqptr_sem; /* serialize ops using quota_info struct, pointers from inode to dquots */
131 - struct file *files[MAXQUOTAS]; /* fp's to quotafiles */
132 + struct inode *files[MAXQUOTAS]; /* inodes of quotafiles */
133 + struct vfsmount *mnt[MAXQUOTAS]; /* mountpoint entries of filesystems with quota files */
134 struct mem_dqinfo info[MAXQUOTAS]; /* Information for each quota type */
135 struct quota_format_ops *ops[MAXQUOTAS]; /* Operations for each type */
137 Index: linux-2.6.5-7.283/include/linux/quotaops.h
138 ===================================================================
139 --- linux-2.6.5-7.283.orig/include/linux/quotaops.h
140 +++ linux-2.6.5-7.283/include/linux/quotaops.h
143 extern void sync_dquots(struct super_block *sb, int type);
145 -extern void dquot_initialize(struct inode *inode, int type);
146 -extern void dquot_drop(struct inode *inode);
147 +extern int dquot_initialize(struct inode *inode, int type);
148 +extern int dquot_drop(struct inode *inode);
150 extern int dquot_alloc_space(struct inode *inode, qsize_t number, int prealloc);
151 extern int dquot_alloc_inode(const struct inode *inode, unsigned long number);
153 -extern void dquot_free_space(struct inode *inode, qsize_t number);
154 -extern void dquot_free_inode(const struct inode *inode, unsigned long number);
155 +extern int dquot_free_space(struct inode *inode, qsize_t number);
156 +extern int dquot_free_inode(const struct inode *inode, unsigned long number);
158 extern int dquot_transfer(struct inode *inode, struct iattr *iattr);
160 +extern int dquot_commit(struct dquot *dquot);
161 +extern int dquot_commit_info(struct super_block *sb, int type);
162 +extern int dquot_acquire(struct dquot *dquot);
163 +extern int dquot_release(struct dquot *dquot);
166 * Operations supported for diskquotas.
168 @@ -143,7 +148,7 @@ static __inline__ int DQUOT_OFF(struct s
172 - if (sb->s_qcop && sb->s_qcop->quota_off)
173 + if (sb_any_quota_enabled(sb) && sb->s_qcop && sb->s_qcop->quota_off)
174 ret = sb->s_qcop->quota_off(sb, -1);
177 Index: linux-2.6.5-7.283/include/linux/security.h
178 ===================================================================
179 --- linux-2.6.5-7.283.orig/include/linux/security.h
180 +++ linux-2.6.5-7.283/include/linux/security.h
181 @@ -1020,7 +1020,7 @@ struct security_operations {
182 int (*sysctl) (ctl_table * table, int op);
183 int (*capable) (struct task_struct * tsk, int cap);
184 int (*quotactl) (int cmds, int type, int id, struct super_block * sb);
185 - int (*quota_on) (struct file * f);
186 + int (*quota_on) (struct dentry * dentry);
187 int (*syslog) (int type);
188 int (*vm_enough_memory) (long pages);
190 @@ -1292,9 +1292,9 @@ static inline int security_quotactl (int
194 -static inline int security_quota_on (struct file * file)
195 +static inline int security_quota_on (struct dentry * dentry)
197 - return COND_SECURITY(quota_on (file),
198 + return COND_SECURITY(quota_on (dentry),
202 Index: linux-2.6.5-7.283/security/dummy.c
203 ===================================================================
204 --- linux-2.6.5-7.283.orig/security/dummy.c
205 +++ linux-2.6.5-7.283/security/dummy.c
206 @@ -90,7 +90,7 @@ static int dummy_quotactl (int cmds, int
210 -static int dummy_quota_on (struct file *f)
211 +static int dummy_quota_on (struct dentry *dentry)
215 Index: linux-2.6.5-7.283/security/selinux/hooks.c
216 ===================================================================
217 --- linux-2.6.5-7.283.orig/security/selinux/hooks.c
218 +++ linux-2.6.5-7.283/security/selinux/hooks.c
219 @@ -1454,9 +1454,9 @@ static int selinux_quotactl(int cmds, in
223 -static int selinux_quota_on(struct file *f)
224 +static int selinux_quota_on(struct dentry *dentry)
226 - return file_has_perm(current, f, FILE__QUOTAON);
227 + return dentry_has_perm(current, NULL, dentry, FILE__QUOTAON);
230 static int selinux_syslog(int type)
231 Index: linux-2.6.5-7.283/fs/dquot.c
232 ===================================================================
233 --- linux-2.6.5-7.283.orig/fs/dquot.c
234 +++ linux-2.6.5-7.283/fs/dquot.c
237 * Jan Kara, <jack@suse.cz>, 10/2002
239 + * Fix lock inversion problems
240 + * Jan Kara, <jack@suse.cz>, 2003,2004
242 * (C) Copyright 1994 - 1997 Marco van Wieringen
246 #include <linux/proc_fs.h>
247 #include <linux/security.h>
248 #include <linux/kmod.h>
249 -#include <linux/pagemap.h>
250 +#include <linux/namei.h>
251 +#include <linux/buffer_head.h>
253 #include <asm/uaccess.h>
256 * dqget(). Write operations on dquots don't hold dq_lock as they copy data
257 * under dq_data_lock spinlock to internal buffers before writing.
259 - * Lock ordering (including journal_lock) is following:
260 + * Lock ordering (including journal_lock) is the following:
261 * dqonoff_sem > journal_lock > dqptr_sem > dquot->dq_lock > dqio_sem
263 spinlock_t dq_list_lock = SPIN_LOCK_UNLOCKED;
264 @@ -175,8 +179,7 @@ static void put_quota_format(struct quot
265 * on all three lists, depending on its current state.
267 * All dquots are placed to the end of inuse_list when first created, and this
268 - * list is used for the sync and invalidate operations, which must look
270 + * list is used for invalidate operation, which must look at every dquot.
272 * Unused dquots (dq_count == 0) are added to the free_dquots list when freed,
273 * and this list is searched whenever we need an available dquot. Dquots are
274 @@ -264,30 +267,105 @@ static void wait_on_dquot(struct dquot *
278 -static int read_dqblk(struct dquot *dquot)
279 +void mark_info_dirty(struct super_block *sb, int type)
282 + set_bit(DQF_INFO_DIRTY_B, &sb_dqopt(sb)->info[type].dqi_flags);
284 +EXPORT_SYMBOL(mark_info_dirty);
287 + * Read dquot from disk and alloc space for it
290 +int dquot_acquire(struct dquot *dquot)
292 + int ret = 0, ret2 = 0;
293 struct quota_info *dqopt = sb_dqopt(dquot->dq_sb);
295 down(&dquot->dq_lock);
296 down(&dqopt->dqio_sem);
297 - ret = dqopt->ops[dquot->dq_type]->read_dqblk(dquot);
298 + if (!test_bit(DQ_READ_B, &dquot->dq_flags))
299 + ret = dqopt->ops[dquot->dq_type]->read_dqblk(dquot);
302 + set_bit(DQ_READ_B, &dquot->dq_flags);
303 + /* Instantiate dquot if needed */
304 + if (!test_bit(DQ_ACTIVE_B, &dquot->dq_flags) && !dquot->dq_off) {
305 + ret = dqopt->ops[dquot->dq_type]->commit_dqblk(dquot);
306 + /* Write the info if needed */
307 + if (info_dirty(&dqopt->info[dquot->dq_type]))
308 + ret2 = dqopt->ops[dquot->dq_type]->write_file_info(dquot->dq_sb, dquot->dq_type);
316 + set_bit(DQ_ACTIVE_B, &dquot->dq_flags);
318 up(&dqopt->dqio_sem);
323 -static int commit_dqblk(struct dquot *dquot)
325 + * Write dquot to disk
327 +int dquot_commit(struct dquot *dquot)
330 + int ret = 0, ret2 = 0;
331 struct quota_info *dqopt = sb_dqopt(dquot->dq_sb);
333 down(&dqopt->dqio_sem);
334 - ret = dqopt->ops[dquot->dq_type]->commit_dqblk(dquot);
335 + spin_lock(&dq_list_lock);
336 + if (!test_and_clear_bit(DQ_MOD_B, &dquot->dq_flags)) {
337 + spin_unlock(&dq_list_lock);
340 + spin_unlock(&dq_list_lock);
341 + /* Inactive dquot can be only if there was error during read/init
342 + * => we have better not writing it */
343 + if (test_bit(DQ_ACTIVE_B, &dquot->dq_flags)) {
344 + ret = dqopt->ops[dquot->dq_type]->commit_dqblk(dquot);
345 + if (info_dirty(&dqopt->info[dquot->dq_type]))
346 + ret2 = dqopt->ops[dquot->dq_type]->write_file_info(dquot->dq_sb, dquot->dq_type);
351 up(&dqopt->dqio_sem);
358 +int dquot_release(struct dquot *dquot)
360 + int ret = 0, ret2 = 0;
361 + struct quota_info *dqopt = sb_dqopt(dquot->dq_sb);
363 + down(&dquot->dq_lock);
364 + /* Check whether we are not racing with some other dqget() */
365 + if (atomic_read(&dquot->dq_count) > 1)
367 + down(&dqopt->dqio_sem);
368 + if (dqopt->ops[dquot->dq_type]->release_dqblk) {
369 + ret = dqopt->ops[dquot->dq_type]->release_dqblk(dquot);
370 + /* Write the info */
371 + if (info_dirty(&dqopt->info[dquot->dq_type]))
372 + ret2 = dqopt->ops[dquot->dq_type]->write_file_info(dquot->dq_sb, dquot->dq_type);
376 + clear_bit(DQ_ACTIVE_B, &dquot->dq_flags);
377 + up(&dqopt->dqio_sem);
379 + up(&dquot->dq_lock);
383 /* Invalidate all dquots on the list. Note that this function is called after
384 * quota is disabled so no new quota might be created. Because we hold
385 * dqonoff_sem and pointers were already removed from inodes we actually know
386 @@ -343,6 +421,11 @@ restart:
388 if (!dquot_dirty(dquot))
390 + /* Dirty and inactive can be only bad dquot... */
391 + if (!test_bit(DQ_ACTIVE_B, &dquot->dq_flags)) {
392 + test_and_clear_bit(DQ_MOD_B, &dquot->dq_flags);
395 atomic_inc(&dquot->dq_count);
397 spin_unlock(&dq_list_lock);
398 @@ -353,11 +436,9 @@ restart:
399 spin_unlock(&dq_list_lock);
401 for (cnt = 0; cnt < MAXQUOTAS; cnt++)
402 - if ((cnt == type || type == -1) && sb_has_quota_enabled(sb, cnt) && info_dirty(&dqopt->info[cnt])) {
403 - down(&dqopt->dqio_sem);
404 - dqopt->ops[cnt]->write_file_info(sb, cnt);
405 - up(&dqopt->dqio_sem);
407 + if ((cnt == type || type == -1) && sb_has_quota_enabled(sb, cnt)
408 + && info_dirty(&dqopt->info[cnt]))
409 + sb->dq_op->write_info(sb, cnt);
410 spin_lock(&dq_list_lock);
412 spin_unlock(&dq_list_lock);
413 @@ -432,11 +513,19 @@ we_slept:
414 spin_unlock(&dq_list_lock);
417 - if (dquot_dirty(dquot)) {
418 + if (test_bit(DQ_ACTIVE_B, &dquot->dq_flags) && dquot_dirty(dquot)) {
419 spin_unlock(&dq_list_lock);
420 dquot->dq_sb->dq_op->write_dquot(dquot);
423 + /* Clear flag in case dquot was inactive (something bad happened) */
424 + test_and_clear_bit(DQ_MOD_B, &dquot->dq_flags);
425 + if (test_bit(DQ_ACTIVE_B, &dquot->dq_flags)) {
426 + spin_unlock(&dq_list_lock);
427 + dquot->dq_sb->dq_op->release_dquot(dquot);
431 atomic_dec(&dquot->dq_count);
432 #ifdef __DQUOT_PARANOIA
434 @@ -495,7 +584,6 @@ we_slept:
435 insert_dquot_hash(dquot);
437 spin_unlock(&dq_list_lock);
440 if (!atomic_read(&dquot->dq_count))
441 remove_free_dquot(dquot);
442 @@ -503,10 +591,15 @@ we_slept:
443 dqstats.cache_hits++;
445 spin_unlock(&dq_list_lock);
446 - wait_on_dquot(dquot);
448 kmem_cache_free(dquot_cachep, empty);
450 + wait_on_dquot(dquot);
451 + /* Read the dquot and instantiate it (everything done only if needed) */
452 + if (!test_bit(DQ_ACTIVE_B, &dquot->dq_flags) && sb->dq_op->acquire_dquot(dquot) < 0) {
457 #ifdef __DQUOT_PARANOIA
458 if (!dquot->dq_sb) /* Has somebody invalidated entry under us? */
459 @@ -819,19 +912,19 @@ static int check_bdq(struct dquot *dquot
461 * Note: this is a blocking operation.
463 -void dquot_initialize(struct inode *inode, int type)
464 +int dquot_initialize(struct inode *inode, int type)
469 /* Solve deadlock when we recurse when holding dqptr_sem... */
470 if (IS_NOQUOTA(inode))
473 down_write(&sb_dqopt(inode->i_sb)->dqptr_sem);
474 /* Having dqptr_sem we know NOQUOTA flags can't be altered... */
475 if (IS_NOQUOTA(inode)) {
476 up_write(&sb_dqopt(inode->i_sb)->dqptr_sem);
480 /* Build list of quotas to initialize... */
481 for (cnt = 0; cnt < MAXQUOTAS; cnt++) {
482 @@ -852,13 +945,14 @@ void dquot_initialize(struct inode *inod
485 up_write(&sb_dqopt(inode->i_sb)->dqptr_sem);
490 * Release all quotas referenced by inode
491 * Needs dqonoff_sem to guard dqput()
493 -void dquot_drop(struct inode *inode)
494 +int dquot_drop(struct inode *inode)
498 @@ -871,6 +965,7 @@ void dquot_drop(struct inode *inode)
501 up_write(&sb_dqopt(inode->i_sb)->dqptr_sem);
506 @@ -958,14 +1053,14 @@ warn_put_all:
508 * This is a non-blocking operation.
510 -void dquot_free_space(struct inode *inode, qsize_t number)
511 +int dquot_free_space(struct inode *inode, qsize_t number)
515 /* Solve deadlock when we recurse when holding dqptr_sem... */
516 if (IS_NOQUOTA(inode)) {
517 inode_add_bytes(inode, number);
521 down_read(&sb_dqopt(inode->i_sb)->dqptr_sem);
522 spin_lock(&dq_data_lock);
523 @@ -981,23 +1076,24 @@ sub_bytes:
524 inode_sub_bytes(inode, number);
525 spin_unlock(&dq_data_lock);
526 up_read(&sb_dqopt(inode->i_sb)->dqptr_sem);
531 * This is a non-blocking operation.
533 -void dquot_free_inode(const struct inode *inode, unsigned long number)
534 +int dquot_free_inode(const struct inode *inode, unsigned long number)
538 /* Solve deadlock when we recurse when holding dqptr_sem... */
539 if (IS_NOQUOTA(inode))
542 down_read(&sb_dqopt(inode->i_sb)->dqptr_sem);
543 /* Now recheck reliably when holding dqptr_sem */
544 if (IS_NOQUOTA(inode)) {
545 up_read(&sb_dqopt(inode->i_sb)->dqptr_sem);
549 spin_lock(&dq_data_lock);
550 for (cnt = 0; cnt < MAXQUOTAS; cnt++) {
551 @@ -1007,6 +1103,7 @@ void dquot_free_inode(const struct inode
553 spin_unlock(&dq_data_lock);
554 up_read(&sb_dqopt(inode->i_sb)->dqptr_sem);
559 @@ -1104,6 +1201,20 @@ warn_put_all:
563 + * Write info of quota file to disk
565 +int dquot_commit_info(struct super_block *sb, int type)
568 + struct quota_info *dqopt = sb_dqopt(sb);
570 + down(&dqopt->dqio_sem);
571 + ret = dqopt->ops[type]->write_file_info(sb, type);
572 + up(&dqopt->dqio_sem);
577 * Definitions of diskquota operations.
579 struct dquot_operations dquot_operations = {
580 @@ -1114,7 +1225,10 @@ struct dquot_operations dquot_operations
581 .free_space = dquot_free_space,
582 .free_inode = dquot_free_inode,
583 .transfer = dquot_transfer,
584 - .write_dquot = commit_dqblk
585 + .write_dquot = dquot_commit,
586 + .acquire_dquot = dquot_acquire,
587 + .release_dquot = dquot_release,
588 + .write_info = dquot_commit_info
591 /* Function used by filesystems for initializing the dquot_operations structure */
592 @@ -1154,13 +1268,14 @@ int vfs_quota_off(struct super_block *sb
595 struct quota_info *dqopt = sb_dqopt(sb);
599 + struct inode *toputinode[MAXQUOTAS];
600 + struct vfsmount *toputmnt[MAXQUOTAS];
602 /* We need to serialize quota_off() for device */
603 down(&dqopt->dqonoff_sem);
604 for (cnt = 0; cnt < MAXQUOTAS; cnt++) {
605 + toputinode[cnt] = NULL;
606 + toputmnt[cnt] = NULL;
607 if (type != -1 && cnt != type)
609 if (!sb_has_quota_enabled(sb, cnt))
610 @@ -1172,94 +1287,115 @@ int vfs_quota_off(struct super_block *sb
611 invalidate_dquots(sb, cnt);
613 * Now all dquots should be invalidated, all writes done so we should be only
614 - * users of the info. No locks needed.
615 + * users of the info.
617 - if (info_dirty(&dqopt->info[cnt])) {
618 - down(&dqopt->dqio_sem);
619 - dqopt->ops[cnt]->write_file_info(sb, cnt);
620 - up(&dqopt->dqio_sem);
622 + if (info_dirty(&dqopt->info[cnt]))
623 + sb->dq_op->write_info(sb, cnt);
624 if (dqopt->ops[cnt]->free_file_info)
625 dqopt->ops[cnt]->free_file_info(sb, cnt);
626 put_quota_format(dqopt->info[cnt].dqi_format);
628 - fput(dqopt->files[cnt]);
629 - dqopt->files[cnt] = (struct file *)NULL;
630 + toputinode[cnt] = dqopt->files[cnt];
631 + toputmnt[cnt] = dqopt->mnt[cnt];
632 + dqopt->files[cnt] = NULL;
633 + dqopt->mnt[cnt] = NULL;
634 dqopt->info[cnt].dqi_flags = 0;
635 dqopt->info[cnt].dqi_igrace = 0;
636 dqopt->info[cnt].dqi_bgrace = 0;
637 dqopt->ops[cnt] = NULL;
639 up(&dqopt->dqonoff_sem);
641 + /* Sync the superblock so that buffers with quota data are written to
642 + * disk (and so userspace sees correct data afterwards).
643 + * The reference to vfsmnt we are still holding protects us from
644 + * umount (we don't have it only when quotas are turned on/off for
645 + * journal replay but in that case we are guarded by the fs anyway). */
646 + if (sb->s_op->sync_fs)
647 + sb->s_op->sync_fs(sb, 1);
648 + sync_blockdev(sb->s_bdev);
649 + /* Now the quota files are just ordinary files and we can set the
650 + * inode flags back. Moreover we discard the pagecache so that
651 + * userspace sees the writes we did bypassing the pagecache. We
652 + * must also discard the blockdev buffers so that we see the
653 + * changes done by userspace on the next quotaon() */
654 + for (cnt = 0; cnt < MAXQUOTAS; cnt++)
655 + if (toputinode[cnt]) {
656 + down(&dqopt->dqonoff_sem);
657 + /* If quota was reenabled in the meantime, we have
659 + if (!sb_has_quota_enabled(sb, cnt)) {
660 + down(&toputinode[cnt]->i_sem);
661 + toputinode[cnt]->i_flags &= ~(S_IMMUTABLE |
662 + S_NOATIME | S_NOQUOTA);
663 + truncate_inode_pages(&toputinode[cnt]->i_data, 0);
664 + up(&toputinode[cnt]->i_sem);
665 + mark_inode_dirty(toputinode[cnt]);
666 + iput(toputinode[cnt]);
668 + up(&dqopt->dqonoff_sem);
669 + /* We don't hold the reference when we turned on quotas
670 + * just for the journal replay... */
672 + mntput(toputmnt[cnt]);
674 + invalidate_bdev(sb->s_bdev, 0);
678 -int vfs_quota_on(struct super_block *sb, int type, int format_id, char *path)
680 + * Turn quotas on on a device
683 +/* Helper function when we already have the inode */
684 +static int vfs_quota_on_inode(struct inode *inode, int type, int format_id)
687 - struct inode *inode;
688 - struct quota_info *dqopt = sb_dqopt(sb);
689 struct quota_format_type *fmt = find_quota_format(format_id);
691 - struct dquot *to_drop[MAXQUOTAS];
692 - unsigned int oldflags;
693 + struct super_block *sb = inode->i_sb;
694 + struct quota_info *dqopt = sb_dqopt(sb);
700 - f = filp_open(path, O_RDWR, 0600);
702 - error = PTR_ERR(f);
703 + if (!S_ISREG(inode->i_mode)) {
707 + if (IS_RDONLY(inode)) {
711 + if (!sb->s_op->quota_write || !sb->s_op->quota_read) {
716 - if (!f->f_op || !f->f_op->read || !f->f_op->write)
718 - error = security_quota_on(f);
721 - inode = f->f_dentry->d_inode;
723 - if (!S_ISREG(inode->i_mode))
726 + /* As we bypass the pagecache we must now flush the inode so that
727 + * we see all the changes from userspace... */
728 + write_inode_now(inode, 1);
729 + /* And now flush the block cache so that kernel sees the changes */
730 + invalidate_bdev(sb->s_bdev, 0);
731 + down(&inode->i_sem);
732 down(&dqopt->dqonoff_sem);
733 if (sb_has_quota_enabled(sb, type)) {
737 - oldflags = inode->i_flags;
738 - dqopt->files[type] = f;
740 - if (!fmt->qf_ops->check_quota_file(sb, type))
741 - goto out_file_init;
742 /* We don't want quota and atime on quota files (deadlocks possible)
743 - * We also need to set GFP mask differently because we cannot recurse
744 - * into filesystem when allocating page for quota inode */
745 + * Also nobody should write to the file - we use special IO operations
746 + * which ignore the immutable bit. */
747 down_write(&dqopt->dqptr_sem);
748 - inode->i_flags |= S_NOQUOTA | S_NOATIME;
751 - * We write to quota files deep within filesystem code. We don't want
752 - * the VFS to reenter filesystem code when it tries to allocate a
753 - * pagecache page for the quota file write. So clear __GFP_FS in
754 - * the quota file's allocation flags.
756 - mapping_set_gfp_mask(inode->i_mapping,
757 - mapping_gfp_mask(inode->i_mapping) & ~__GFP_FS);
759 - for (cnt = 0; cnt < MAXQUOTAS; cnt++) {
760 - to_drop[cnt] = inode->i_dquot[cnt];
761 - inode->i_dquot[cnt] = NODQUOT;
763 - inode->i_flags &= ~S_QUOTA;
764 + oldflags = inode->i_flags & (S_NOATIME | S_IMMUTABLE | S_NOQUOTA);
765 + inode->i_flags |= S_NOQUOTA | S_NOATIME | S_IMMUTABLE;
766 up_write(&dqopt->dqptr_sem);
767 - /* We must put dquots outside of dqptr_sem because we may need to
768 - * start transaction for write */
769 - for (cnt = 0; cnt < MAXQUOTAS; cnt++) {
771 - dqput(to_drop[cnt]);
775 + dqopt->files[type] = igrab(inode);
776 + if (!dqopt->files[type])
779 + if (!fmt->qf_ops->check_quota_file(sb, type))
780 + goto out_file_init;
782 dqopt->ops[type] = fmt->qf_ops;
783 dqopt->info[type].dqi_format = fmt;
784 @@ -1269,6 +1405,7 @@ int vfs_quota_on(struct super_block *sb,
787 up(&dqopt->dqio_sem);
789 set_enable_flags(dqopt, type);
791 add_dquot_ref(sb, type);
792 @@ -1277,18 +1414,51 @@ int vfs_quota_on(struct super_block *sb,
796 - inode->i_flags = oldflags;
797 dqopt->files[type] = NULL;
800 up(&dqopt->dqonoff_sem);
802 - filp_close(f, NULL);
803 + if (oldflags != -1) {
804 + down_write(&dqopt->dqptr_sem);
805 + /* Set the flags back (in the case of accidental quotaon()
806 + * on a wrong file we don't want to mess up the flags) */
807 + inode->i_flags &= ~(S_NOATIME | S_NOQUOTA | S_IMMUTABLE);
808 + inode->i_flags |= oldflags;
809 + up_write(&dqopt->dqptr_sem);
813 put_quota_format(fmt);
818 +/* Actual function called from quotactl() */
819 +int vfs_quota_on(struct super_block *sb, int type, int format_id, char *path)
821 + struct nameidata nd;
824 + error = path_lookup(path, LOOKUP_FOLLOW, &nd);
827 + error = security_quota_on(nd.dentry);
830 + /* Quota file not on the same filesystem? */
831 + if (nd.mnt->mnt_sb != sb)
834 + error = vfs_quota_on_inode(nd.dentry->d_inode, type, format_id);
836 + sb_dqopt(sb)->mnt[type] = mntget(nd.mnt);
844 /* Generic routine for getting common part of quota structure */
845 static void do_get_dqblk(struct dquot *dquot, struct if_dqblk *di)
847 @@ -1430,8 +1600,10 @@ int vfs_set_dqinfo(struct super_block *s
848 mi->dqi_igrace = ii->dqi_igrace;
849 if (ii->dqi_valid & IIF_FLAGS)
850 mi->dqi_flags = (mi->dqi_flags & ~DQF_MASK) | (ii->dqi_flags & DQF_MASK);
851 - mark_info_dirty(mi);
852 spin_unlock(&dq_data_lock);
853 + mark_info_dirty(sb, type);
854 + /* Force write to disk */
855 + sb->dq_op->write_info(sb, type);
856 up(&sb_dqopt(sb)->dqonoff_sem);
859 @@ -1564,3 +1736,15 @@ EXPORT_SYMBOL(dqstats);
860 EXPORT_SYMBOL(dq_list_lock);
861 EXPORT_SYMBOL(dq_data_lock);
862 EXPORT_SYMBOL(init_dquot_operations);
863 +EXPORT_SYMBOL(dquot_commit);
864 +EXPORT_SYMBOL(dquot_commit_info);
865 +EXPORT_SYMBOL(dquot_acquire);
866 +EXPORT_SYMBOL(dquot_release);
867 +EXPORT_SYMBOL(dquot_initialize);
868 +EXPORT_SYMBOL(dquot_drop);
869 +EXPORT_SYMBOL(dquot_alloc_space);
870 +EXPORT_SYMBOL(dquot_alloc_inode);
871 +EXPORT_SYMBOL(dquot_free_space);
872 +EXPORT_SYMBOL(dquot_free_inode);
873 +EXPORT_SYMBOL(dquot_transfer);
875 Index: linux-2.6.5-7.283/fs/quota_v2.c
876 ===================================================================
877 --- linux-2.6.5-7.283.orig/fs/quota_v2.c
878 +++ linux-2.6.5-7.283/fs/quota_v2.c
880 #include <linux/slab.h>
882 #include <asm/byteorder.h>
883 -#include <asm/uaccess.h>
885 MODULE_AUTHOR("Jan Kara");
886 MODULE_DESCRIPTION("Quota format v2 support");
887 @@ -30,19 +29,15 @@ typedef char *dqbuf_t;
888 static int v2_check_quota_file(struct super_block *sb, int type)
890 struct v2_disk_dqheader dqhead;
891 - struct file *f = sb_dqopt(sb)->files[type];
895 static const uint quota_magics[] = V2_INITQMAGICS;
896 static const uint quota_versions[] = V2_INITQVERSIONS;
900 - size = f->f_op->read(f, (char *)&dqhead, sizeof(struct v2_disk_dqheader), &offset);
902 - if (size != sizeof(struct v2_disk_dqheader))
903 + size = sb->s_op->quota_read(sb, type, (char *)&dqhead, sizeof(struct v2_disk_dqheader), 0);
904 + if (size != sizeof(struct v2_disk_dqheader)) {
905 + printk("failed read\n");
908 if (le32_to_cpu(dqhead.dqh_magic) != quota_magics[type] ||
909 le32_to_cpu(dqhead.dqh_version) != quota_versions[type])
911 @@ -52,20 +47,15 @@ static int v2_check_quota_file(struct su
912 /* Read information header from quota file */
913 static int v2_read_file_info(struct super_block *sb, int type)
916 struct v2_disk_dqinfo dinfo;
917 struct mem_dqinfo *info = sb_dqopt(sb)->info+type;
918 - struct file *f = sb_dqopt(sb)->files[type];
920 - loff_t offset = V2_DQINFOOFF;
924 - size = f->f_op->read(f, (char *)&dinfo, sizeof(struct v2_disk_dqinfo), &offset);
926 + size = sb->s_op->quota_read(sb, type, (char *)&dinfo,
927 + sizeof(struct v2_disk_dqinfo), V2_DQINFOOFF);
928 if (size != sizeof(struct v2_disk_dqinfo)) {
929 printk(KERN_WARNING "Can't read info structure on device %s.\n",
930 - f->f_vfsmnt->mnt_sb->s_id);
934 info->dqi_bgrace = le32_to_cpu(dinfo.dqi_bgrace);
935 @@ -80,12 +70,9 @@ static int v2_read_file_info(struct supe
936 /* Write information header to quota file */
937 static int v2_write_file_info(struct super_block *sb, int type)
940 struct v2_disk_dqinfo dinfo;
941 struct mem_dqinfo *info = sb_dqopt(sb)->info+type;
942 - struct file *f = sb_dqopt(sb)->files[type];
944 - loff_t offset = V2_DQINFOOFF;
946 info->dqi_flags &= ~DQF_INFO_DIRTY;
947 dinfo.dqi_bgrace = cpu_to_le32(info->dqi_bgrace);
948 @@ -94,13 +81,13 @@ static int v2_write_file_info(struct sup
949 dinfo.dqi_blocks = cpu_to_le32(info->u.v2_i.dqi_blocks);
950 dinfo.dqi_free_blk = cpu_to_le32(info->u.v2_i.dqi_free_blk);
951 dinfo.dqi_free_entry = cpu_to_le32(info->u.v2_i.dqi_free_entry);
954 - size = f->f_op->write(f, (char *)&dinfo, sizeof(struct v2_disk_dqinfo), &offset);
957 + size = sb->s_op->quota_write(sb, type, (char *)&dinfo,
958 + sizeof(struct v2_disk_dqinfo), V2_DQINFOOFF);
960 if (size != sizeof(struct v2_disk_dqinfo)) {
961 printk(KERN_WARNING "Can't write info structure on device %s.\n",
962 - f->f_vfsmnt->mnt_sb->s_id);
967 @@ -144,38 +131,24 @@ static inline void freedqbuf(dqbuf_t buf
971 -static ssize_t read_blk(struct file *filp, uint blk, dqbuf_t buf)
972 +static inline ssize_t read_blk(struct super_block *sb, int type, uint blk, dqbuf_t buf)
976 - loff_t offset = blk<<V2_DQBLKSIZE_BITS;
978 memset(buf, 0, V2_DQBLKSIZE);
981 - ret = filp->f_op->read(filp, (char *)buf, V2_DQBLKSIZE, &offset);
984 + return sb->s_op->quota_read(sb, type, (char *)buf,
985 + V2_DQBLKSIZE, blk << V2_DQBLKSIZE_BITS);
988 -static ssize_t write_blk(struct file *filp, uint blk, dqbuf_t buf)
989 +static inline ssize_t write_blk(struct super_block *sb, int type, uint blk, dqbuf_t buf)
993 - loff_t offset = blk<<V2_DQBLKSIZE_BITS;
997 - ret = filp->f_op->write(filp, (char *)buf, V2_DQBLKSIZE, &offset);
1001 + return sb->s_op->quota_write(sb, type, (char *)buf,
1002 + V2_DQBLKSIZE, blk << V2_DQBLKSIZE_BITS);
1005 /* Remove empty block from list and return it */
1006 -static int get_free_dqblk(struct file *filp, struct mem_dqinfo *info)
1007 +static int get_free_dqblk(struct super_block *sb, int type)
1009 dqbuf_t buf = getdqbuf();
1010 + struct mem_dqinfo *info = sb_dqinfo(sb, type);
1011 struct v2_disk_dqdbheader *dh = (struct v2_disk_dqdbheader *)buf;
1014 @@ -183,17 +156,18 @@ static int get_free_dqblk(struct file *f
1016 if (info->u.v2_i.dqi_free_blk) {
1017 blk = info->u.v2_i.dqi_free_blk;
1018 - if ((ret = read_blk(filp, blk, buf)) < 0)
1019 + if ((ret = read_blk(sb, type, blk, buf)) < 0)
1021 info->u.v2_i.dqi_free_blk = le32_to_cpu(dh->dqdh_next_free);
1024 memset(buf, 0, V2_DQBLKSIZE);
1025 - if ((ret = write_blk(filp, info->u.v2_i.dqi_blocks, buf)) < 0) /* Assure block allocation... */
1026 + /* Assure block allocation... */
1027 + if ((ret = write_blk(sb, type, info->u.v2_i.dqi_blocks, buf)) < 0)
1029 blk = info->u.v2_i.dqi_blocks++;
1031 - mark_info_dirty(info);
1032 + mark_info_dirty(sb, type);
1036 @@ -201,8 +175,9 @@ out_buf:
1039 /* Insert empty block to the list */
1040 -static int put_free_dqblk(struct file *filp, struct mem_dqinfo *info, dqbuf_t buf, uint blk)
1041 +static int put_free_dqblk(struct super_block *sb, int type, dqbuf_t buf, uint blk)
1043 + struct mem_dqinfo *info = sb_dqinfo(sb, type);
1044 struct v2_disk_dqdbheader *dh = (struct v2_disk_dqdbheader *)buf;
1047 @@ -210,16 +185,18 @@ static int put_free_dqblk(struct file *f
1048 dh->dqdh_prev_free = cpu_to_le32(0);
1049 dh->dqdh_entries = cpu_to_le16(0);
1050 info->u.v2_i.dqi_free_blk = blk;
1051 - mark_info_dirty(info);
1052 - if ((err = write_blk(filp, blk, buf)) < 0) /* Some strange block. We had better leave it... */
1053 + mark_info_dirty(sb, type);
1054 + /* Some strange block. We had better leave it... */
1055 + if ((err = write_blk(sb, type, blk, buf)) < 0)
1060 /* Remove given block from the list of blocks with free entries */
1061 -static int remove_free_dqentry(struct file *filp, struct mem_dqinfo *info, dqbuf_t buf, uint blk)
1062 +static int remove_free_dqentry(struct super_block *sb, int type, dqbuf_t buf, uint blk)
1064 dqbuf_t tmpbuf = getdqbuf();
1065 + struct mem_dqinfo *info = sb_dqinfo(sb, type);
1066 struct v2_disk_dqdbheader *dh = (struct v2_disk_dqdbheader *)buf;
1067 uint nextblk = le32_to_cpu(dh->dqdh_next_free), prevblk = le32_to_cpu(dh->dqdh_prev_free);
1069 @@ -227,26 +204,27 @@ static int remove_free_dqentry(struct fi
1073 - if ((err = read_blk(filp, nextblk, tmpbuf)) < 0)
1074 + if ((err = read_blk(sb, type, nextblk, tmpbuf)) < 0)
1076 ((struct v2_disk_dqdbheader *)tmpbuf)->dqdh_prev_free = dh->dqdh_prev_free;
1077 - if ((err = write_blk(filp, nextblk, tmpbuf)) < 0)
1078 + if ((err = write_blk(sb, type, nextblk, tmpbuf)) < 0)
1082 - if ((err = read_blk(filp, prevblk, tmpbuf)) < 0)
1083 + if ((err = read_blk(sb, type, prevblk, tmpbuf)) < 0)
1085 ((struct v2_disk_dqdbheader *)tmpbuf)->dqdh_next_free = dh->dqdh_next_free;
1086 - if ((err = write_blk(filp, prevblk, tmpbuf)) < 0)
1087 + if ((err = write_blk(sb, type, prevblk, tmpbuf)) < 0)
1091 info->u.v2_i.dqi_free_entry = nextblk;
1092 - mark_info_dirty(info);
1093 + mark_info_dirty(sb, type);
1096 dh->dqdh_next_free = dh->dqdh_prev_free = cpu_to_le32(0);
1097 - if (write_blk(filp, blk, buf) < 0) /* No matter whether write succeeds block is out of list */
1098 + /* No matter whether write succeeds block is out of list */
1099 + if (write_blk(sb, type, blk, buf) < 0)
1100 printk(KERN_ERR "VFS: Can't write block (%u) with free entries.\n", blk);
1103 @@ -255,9 +233,10 @@ out_buf:
1106 /* Insert given block to the beginning of list with free entries */
1107 -static int insert_free_dqentry(struct file *filp, struct mem_dqinfo *info, dqbuf_t buf, uint blk)
1108 +static int insert_free_dqentry(struct super_block *sb, int type, dqbuf_t buf, uint blk)
1110 dqbuf_t tmpbuf = getdqbuf();
1111 + struct mem_dqinfo *info = sb_dqinfo(sb, type);
1112 struct v2_disk_dqdbheader *dh = (struct v2_disk_dqdbheader *)buf;
1115 @@ -265,18 +244,18 @@ static int insert_free_dqentry(struct fi
1117 dh->dqdh_next_free = cpu_to_le32(info->u.v2_i.dqi_free_entry);
1118 dh->dqdh_prev_free = cpu_to_le32(0);
1119 - if ((err = write_blk(filp, blk, buf)) < 0)
1120 + if ((err = write_blk(sb, type, blk, buf)) < 0)
1122 if (info->u.v2_i.dqi_free_entry) {
1123 - if ((err = read_blk(filp, info->u.v2_i.dqi_free_entry, tmpbuf)) < 0)
1124 + if ((err = read_blk(sb, type, info->u.v2_i.dqi_free_entry, tmpbuf)) < 0)
1126 ((struct v2_disk_dqdbheader *)tmpbuf)->dqdh_prev_free = cpu_to_le32(blk);
1127 - if ((err = write_blk(filp, info->u.v2_i.dqi_free_entry, tmpbuf)) < 0)
1128 + if ((err = write_blk(sb, type, info->u.v2_i.dqi_free_entry, tmpbuf)) < 0)
1132 info->u.v2_i.dqi_free_entry = blk;
1133 - mark_info_dirty(info);
1134 + mark_info_dirty(sb, type);
1138 @@ -286,8 +265,8 @@ out_buf:
1139 /* Find space for dquot */
1140 static uint find_free_dqentry(struct dquot *dquot, int *err)
1142 - struct file *filp = sb_dqopt(dquot->dq_sb)->files[dquot->dq_type];
1143 - struct mem_dqinfo *info = sb_dqopt(dquot->dq_sb)->info+dquot->dq_type;
1144 + struct super_block *sb = dquot->dq_sb;
1145 + struct mem_dqinfo *info = sb_dqopt(sb)->info+dquot->dq_type;
1147 struct v2_disk_dqdbheader *dh;
1148 struct v2_disk_dqblk *ddquot;
1149 @@ -303,22 +282,23 @@ static uint find_free_dqentry(struct dqu
1150 ddquot = GETENTRIES(buf);
1151 if (info->u.v2_i.dqi_free_entry) {
1152 blk = info->u.v2_i.dqi_free_entry;
1153 - if ((*err = read_blk(filp, blk, buf)) < 0)
1154 + if ((*err = read_blk(sb, dquot->dq_type, blk, buf)) < 0)
1158 - blk = get_free_dqblk(filp, info);
1159 + blk = get_free_dqblk(sb, dquot->dq_type);
1165 memset(buf, 0, V2_DQBLKSIZE);
1166 - info->u.v2_i.dqi_free_entry = blk; /* This is enough as block is already zeroed and entry list is empty... */
1167 - mark_info_dirty(info);
1168 + /* This is enough as block is already zeroed and entry list is empty... */
1169 + info->u.v2_i.dqi_free_entry = blk;
1170 + mark_info_dirty(sb, dquot->dq_type);
1172 if (le16_to_cpu(dh->dqdh_entries)+1 >= V2_DQSTRINBLK) /* Block will be full? */
1173 - if ((*err = remove_free_dqentry(filp, info, buf, blk)) < 0) {
1174 + if ((*err = remove_free_dqentry(sb, dquot->dq_type, buf, blk)) < 0) {
1175 printk(KERN_ERR "VFS: find_free_dqentry(): Can't remove block (%u) from entry free list.\n", blk);
1178 @@ -333,7 +313,7 @@ static uint find_free_dqentry(struct dqu
1182 - if ((*err = write_blk(filp, blk, buf)) < 0) {
1183 + if ((*err = write_blk(sb, dquot->dq_type, blk, buf)) < 0) {
1184 printk(KERN_ERR "VFS: find_free_dqentry(): Can't write quota data block %u.\n", blk);
1187 @@ -348,8 +328,7 @@ out_buf:
1188 /* Insert reference to structure into the trie */
1189 static int do_insert_tree(struct dquot *dquot, uint *treeblk, int depth)
1191 - struct file *filp = sb_dqopt(dquot->dq_sb)->files[dquot->dq_type];
1192 - struct mem_dqinfo *info = sb_dqopt(dquot->dq_sb)->info + dquot->dq_type;
1193 + struct super_block *sb = dquot->dq_sb;
1195 int ret = 0, newson = 0, newact = 0;
1197 @@ -358,7 +337,7 @@ static int do_insert_tree(struct dquot *
1198 if (!(buf = getdqbuf()))
1201 - ret = get_free_dqblk(filp, info);
1202 + ret = get_free_dqblk(sb, dquot->dq_type);
1206 @@ -366,7 +345,7 @@ static int do_insert_tree(struct dquot *
1210 - if ((ret = read_blk(filp, *treeblk, buf)) < 0) {
1211 + if ((ret = read_blk(sb, dquot->dq_type, *treeblk, buf)) < 0) {
1212 printk(KERN_ERR "VFS: Can't read tree quota block %u.\n", *treeblk);
1215 @@ -389,10 +368,10 @@ static int do_insert_tree(struct dquot *
1216 ret = do_insert_tree(dquot, &newblk, depth+1);
1217 if (newson && ret >= 0) {
1218 ref[GETIDINDEX(dquot->dq_id, depth)] = cpu_to_le32(newblk);
1219 - ret = write_blk(filp, *treeblk, buf);
1220 + ret = write_blk(sb, dquot->dq_type, *treeblk, buf);
1222 else if (newact && ret < 0)
1223 - put_free_dqblk(filp, info, buf, *treeblk);
1224 + put_free_dqblk(sb, dquot->dq_type, buf, *treeblk);
1228 @@ -411,19 +390,14 @@ static inline int dq_insert_tree(struct
1229 static int v2_write_dquot(struct dquot *dquot)
1231 int type = dquot->dq_type;
1232 - struct file *filp;
1236 struct v2_disk_dqblk ddquot, empty;
1239 if ((ret = dq_insert_tree(dquot)) < 0) {
1240 - printk(KERN_ERR "VFS: Error %Zd occurred while creating quota.\n", ret);
1241 + printk(KERN_ERR "VFS: Error %d occurred while creating quota.\n", ret);
1244 - filp = sb_dqopt(dquot->dq_sb)->files[type];
1245 - offset = dquot->dq_off;
1246 mem2diskdqb(&ddquot, &dquot->dq_dqb, dquot->dq_id);
1247 /* Argh... We may need to write structure full of zeroes but that would be
1248 * treated as an empty place by the rest of the code. Format change would
1249 @@ -431,10 +405,10 @@ static int v2_write_dquot(struct dquot *
1250 memset(&empty, 0, sizeof(struct v2_disk_dqblk));
1251 if (!memcmp(&empty, &ddquot, sizeof(struct v2_disk_dqblk)))
1252 ddquot.dqb_itime = cpu_to_le64(1);
1254 - set_fs(KERNEL_DS);
1255 - ret = filp->f_op->write(filp, (char *)&ddquot, sizeof(struct v2_disk_dqblk), &offset);
1258 + ret = dquot->dq_sb->s_op->quota_write(dquot->dq_sb, type,
1259 + (char *)&ddquot, sizeof(struct v2_disk_dqblk), dquot->dq_off);
1261 if (ret != sizeof(struct v2_disk_dqblk)) {
1262 printk(KERN_WARNING "VFS: dquota write failed on dev %s\n", dquot->dq_sb->s_id);
1264 @@ -450,8 +424,8 @@ static int v2_write_dquot(struct dquot *
1265 /* Free dquot entry in data block */
1266 static int free_dqentry(struct dquot *dquot, uint blk)
1268 - struct file *filp = sb_dqopt(dquot->dq_sb)->files[dquot->dq_type];
1269 - struct mem_dqinfo *info = sb_dqopt(dquot->dq_sb)->info + dquot->dq_type;
1270 + struct super_block *sb = dquot->dq_sb;
1271 + int type = dquot->dq_type;
1272 struct v2_disk_dqdbheader *dh;
1273 dqbuf_t buf = getdqbuf();
1275 @@ -459,34 +433,39 @@ static int free_dqentry(struct dquot *dq
1278 if (dquot->dq_off >> V2_DQBLKSIZE_BITS != blk) {
1279 - 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));
1280 + printk(KERN_ERR "VFS: Quota structure has offset to other "
1281 + "block (%u) than it should (%u).\n", blk,
1282 + (uint)(dquot->dq_off >> V2_DQBLKSIZE_BITS));
1285 - if ((ret = read_blk(filp, blk, buf)) < 0) {
1286 + if ((ret = read_blk(sb, type, blk, buf)) < 0) {
1287 printk(KERN_ERR "VFS: Can't read quota data block %u\n", blk);
1290 dh = (struct v2_disk_dqdbheader *)buf;
1291 dh->dqdh_entries = cpu_to_le16(le16_to_cpu(dh->dqdh_entries)-1);
1292 if (!le16_to_cpu(dh->dqdh_entries)) { /* Block got free? */
1293 - if ((ret = remove_free_dqentry(filp, info, buf, blk)) < 0 ||
1294 - (ret = put_free_dqblk(filp, info, buf, blk)) < 0) {
1295 - printk(KERN_ERR "VFS: Can't move quota data block (%u) to free list.\n", blk);
1296 + if ((ret = remove_free_dqentry(sb, type, buf, blk)) < 0 ||
1297 + (ret = put_free_dqblk(sb, type, buf, blk)) < 0) {
1298 + printk(KERN_ERR "VFS: Can't move quota data block (%u) "
1299 + "to free list.\n", blk);
1304 - memset(buf+(dquot->dq_off & ((1 << V2_DQBLKSIZE_BITS)-1)), 0, sizeof(struct v2_disk_dqblk));
1305 + memset(buf+(dquot->dq_off & ((1 << V2_DQBLKSIZE_BITS)-1)), 0,
1306 + sizeof(struct v2_disk_dqblk));
1307 if (le16_to_cpu(dh->dqdh_entries) == V2_DQSTRINBLK-1) {
1308 /* Insert will write block itself */
1309 - if ((ret = insert_free_dqentry(filp, info, buf, blk)) < 0) {
1310 + if ((ret = insert_free_dqentry(sb, type, buf, blk)) < 0) {
1311 printk(KERN_ERR "VFS: Can't insert quota data block (%u) to free entry list.\n", blk);
1316 - if ((ret = write_blk(filp, blk, buf)) < 0) {
1317 - printk(KERN_ERR "VFS: Can't write quota data block %u\n", blk);
1318 + if ((ret = write_blk(sb, type, blk, buf)) < 0) {
1319 + printk(KERN_ERR "VFS: Can't write quota data "
1320 + "block %u\n", blk);
1324 @@ -499,8 +478,8 @@ out_buf:
1325 /* Remove reference to dquot from tree */
1326 static int remove_tree(struct dquot *dquot, uint *blk, int depth)
1328 - struct file *filp = sb_dqopt(dquot->dq_sb)->files[dquot->dq_type];
1329 - struct mem_dqinfo *info = sb_dqopt(dquot->dq_sb)->info + dquot->dq_type;
1330 + struct super_block *sb = dquot->dq_sb;
1331 + int type = dquot->dq_type;
1332 dqbuf_t buf = getdqbuf();
1335 @@ -508,7 +487,7 @@ static int remove_tree(struct dquot *dqu
1339 - if ((ret = read_blk(filp, *blk, buf)) < 0) {
1340 + if ((ret = read_blk(sb, type, *blk, buf)) < 0) {
1341 printk(KERN_ERR "VFS: Can't read quota data block %u\n", *blk);
1344 @@ -524,12 +503,13 @@ static int remove_tree(struct dquot *dqu
1345 ref[GETIDINDEX(dquot->dq_id, depth)] = cpu_to_le32(0);
1346 for (i = 0; i < V2_DQBLKSIZE && !buf[i]; i++); /* Block got empty? */
1347 if (i == V2_DQBLKSIZE) {
1348 - put_free_dqblk(filp, info, buf, *blk);
1349 + put_free_dqblk(sb, type, buf, *blk);
1353 - if ((ret = write_blk(filp, *blk, buf)) < 0)
1354 - printk(KERN_ERR "VFS: Can't write quota tree block %u.\n", *blk);
1355 + if ((ret = write_blk(sb, type, *blk, buf)) < 0)
1356 + printk(KERN_ERR "VFS: Can't write quota tree "
1357 + "block %u.\n", *blk);
1361 @@ -549,7 +529,6 @@ static int v2_delete_dquot(struct dquot
1362 /* Find entry in block */
1363 static loff_t find_block_dqentry(struct dquot *dquot, uint blk)
1365 - struct file *filp = sb_dqopt(dquot->dq_sb)->files[dquot->dq_type];
1366 dqbuf_t buf = getdqbuf();
1369 @@ -557,27 +536,31 @@ static loff_t find_block_dqentry(struct
1373 - if ((ret = read_blk(filp, blk, buf)) < 0) {
1374 + if ((ret = read_blk(dquot->dq_sb, dquot->dq_type, blk, buf)) < 0) {
1375 printk(KERN_ERR "VFS: Can't read quota tree block %u.\n", blk);
1379 - for (i = 0; i < V2_DQSTRINBLK && le32_to_cpu(ddquot[i].dqb_id) != dquot->dq_id; i++);
1380 + for (i = 0; i < V2_DQSTRINBLK &&
1381 + le32_to_cpu(ddquot[i].dqb_id) != dquot->dq_id; i++);
1382 else { /* ID 0 as a bit more complicated searching... */
1383 struct v2_disk_dqblk fakedquot;
1385 memset(&fakedquot, 0, sizeof(struct v2_disk_dqblk));
1386 for (i = 0; i < V2_DQSTRINBLK; i++)
1387 - if (!le32_to_cpu(ddquot[i].dqb_id) && memcmp(&fakedquot, ddquot+i, sizeof(struct v2_disk_dqblk)))
1388 + if (!le32_to_cpu(ddquot[i].dqb_id) &&
1389 + memcmp(&fakedquot, ddquot+i, sizeof(struct v2_disk_dqblk)))
1392 if (i == V2_DQSTRINBLK) {
1393 - printk(KERN_ERR "VFS: Quota for id %u referenced but not present.\n", dquot->dq_id);
1394 + printk(KERN_ERR "VFS: Quota for id %u referenced "
1395 + "but not present.\n", dquot->dq_id);
1400 - ret = (blk << V2_DQBLKSIZE_BITS) + sizeof(struct v2_disk_dqdbheader) + i * sizeof(struct v2_disk_dqblk);
1401 + ret = (blk << V2_DQBLKSIZE_BITS) + sizeof(struct
1402 + v2_disk_dqdbheader) + i * sizeof(struct v2_disk_dqblk);
1406 @@ -586,14 +569,13 @@ out_buf:
1407 /* Find entry for given id in the tree */
1408 static loff_t find_tree_dqentry(struct dquot *dquot, uint blk, int depth)
1410 - struct file *filp = sb_dqopt(dquot->dq_sb)->files[dquot->dq_type];
1411 dqbuf_t buf = getdqbuf();
1413 u32 *ref = (u32 *)buf;
1417 - if ((ret = read_blk(filp, blk, buf)) < 0) {
1418 + if ((ret = read_blk(dquot->dq_sb, dquot->dq_type, blk, buf)) < 0) {
1419 printk(KERN_ERR "VFS: Can't read quota tree block %u.\n", blk);
1422 @@ -619,16 +601,13 @@ static inline loff_t find_dqentry(struct
1423 static int v2_read_dquot(struct dquot *dquot)
1425 int type = dquot->dq_type;
1426 - struct file *filp;
1429 struct v2_disk_dqblk ddquot, empty;
1432 - filp = sb_dqopt(dquot->dq_sb)->files[type];
1434 #ifdef __QUOTA_V2_PARANOIA
1435 - if (!filp || !dquot->dq_sb) { /* Invalidated quota? */
1436 + /* Invalidated quota? */
1437 + if (!dquot->dq_sb || !dquot->dq_sb->s_op->quota_read) {
1438 printk(KERN_ERR "VFS: Quota invalidated while reading!\n");
1441 @@ -636,7 +615,8 @@ static int v2_read_dquot(struct dquot *d
1442 offset = find_dqentry(dquot);
1443 if (offset <= 0) { /* Entry not present? */
1445 - printk(KERN_ERR "VFS: Can't read quota structure for id %u.\n", dquot->dq_id);
1446 + printk(KERN_ERR "VFS: Can't read quota "
1447 + "structure for id %u.\n", dquot->dq_id);
1449 dquot->dq_flags |= DQ_FAKE;
1450 memset(&dquot->dq_dqb, 0, sizeof(struct mem_dqblk));
1451 @@ -644,12 +624,13 @@ static int v2_read_dquot(struct dquot *d
1454 dquot->dq_off = offset;
1456 - set_fs(KERNEL_DS);
1457 - if ((ret = filp->f_op->read(filp, (char *)&ddquot, sizeof(struct v2_disk_dqblk), &offset)) != sizeof(struct v2_disk_dqblk)) {
1458 + if ((ret = dquot->dq_sb->s_op->quota_read(dquot->dq_sb, type,
1459 + (char *)&ddquot, sizeof(struct v2_disk_dqblk), offset))
1460 + != sizeof(struct v2_disk_dqblk)) {
1463 - printk(KERN_ERR "VFS: Error while reading quota structure for id %u.\n", dquot->dq_id);
1464 + printk(KERN_ERR "VFS: Error while reading quota "
1465 + "structure for id %u.\n", dquot->dq_id);
1466 memset(&ddquot, 0, sizeof(struct v2_disk_dqblk));
1469 @@ -660,7 +641,6 @@ static int v2_read_dquot(struct dquot *d
1470 if (!memcmp(&empty, &ddquot, sizeof(struct v2_disk_dqblk)))
1471 ddquot.dqb_itime = 0;
1474 disk2memdqb(&dquot->dq_dqb, &ddquot);
1477 @@ -668,15 +648,13 @@ static int v2_read_dquot(struct dquot *d
1481 -/* Commit changes of dquot to disk - it might also mean deleting it when quota became fake one and user has no blocks... */
1482 -static int v2_commit_dquot(struct dquot *dquot)
1483 +/* Check whether dquot should not be deleted. We know we are
1484 + * * the only one operating on dquot (thanks to dq_lock) */
1485 +static int v2_release_dquot(struct dquot *dquot)
1487 - /* We clear the flag everytime so we don't loop when there was an IO error... */
1488 - dquot->dq_flags &= ~DQ_MOD;
1489 - if (dquot->dq_flags & DQ_FAKE && !(dquot->dq_dqb.dqb_curinodes | dquot->dq_dqb.dqb_curspace))
1490 + if (test_bit(DQ_FAKE_B, &dquot->dq_flags) && !(dquot->dq_dqb.dqb_curinodes | dquot->dq_dqb.dqb_curspace))
1491 return v2_delete_dquot(dquot);
1493 - return v2_write_dquot(dquot);
1497 static struct quota_format_ops v2_format_ops = {
1498 @@ -685,7 +663,8 @@ static struct quota_format_ops v2_format
1499 .write_file_info = v2_write_file_info,
1500 .free_file_info = NULL,
1501 .read_dqblk = v2_read_dquot,
1502 - .commit_dqblk = v2_commit_dquot,
1503 + .commit_dqblk = v2_write_dquot,
1504 + .release_dqblk = v2_release_dquot,
1507 static struct quota_format_type v2_quota_format = {
1508 Index: linux-2.6.5-7.283/fs/quota.c
1509 ===================================================================
1510 --- linux-2.6.5-7.283.orig/fs/quota.c
1511 +++ linux-2.6.5-7.283/fs/quota.c
1513 #include <linux/smp_lock.h>
1514 #include <linux/security.h>
1515 #include <linux/audit.h>
1516 +#include <linux/syscalls.h>
1517 +#include <linux/buffer_head.h>
1520 /* Check validity of quotactl */
1521 static int check_quotactl_valid(struct super_block *sb, int type, int cmd, qid_t id)
1522 @@ -134,16 +137,54 @@ restart:
1526 +void quota_sync_sb(struct super_block *sb, int type)
1529 + struct inode *discard[MAXQUOTAS];
1531 + sb->s_qcop->quota_sync(sb, type);
1532 + /* This is not very clever (and fast) but currently I don't know about
1533 + * any other simple way of getting quota data to disk and we must get
1534 + * them there for userspace to be visible... */
1535 + if (sb->s_op->sync_fs)
1536 + sb->s_op->sync_fs(sb, 1);
1537 + sync_blockdev(sb->s_bdev);
1539 + /* Now when everything is written we can discard the pagecache so
1540 + * that userspace sees the changes. We need i_sem and so we could
1541 + * not do it inside dqonoff_sem. Moreover we need to be carefull
1542 + * about races with quotaoff() (that is the reason why we have own
1543 + * reference to inode). */
1544 + down(&sb_dqopt(sb)->dqonoff_sem);
1545 + for (cnt = 0; cnt < MAXQUOTAS; cnt++) {
1546 + discard[cnt] = NULL;
1547 + if (type != -1 && cnt != type)
1549 + if (!sb_has_quota_enabled(sb, cnt))
1551 + discard[cnt] = igrab(sb_dqopt(sb)->files[cnt]);
1553 + up(&sb_dqopt(sb)->dqonoff_sem);
1554 + for (cnt = 0; cnt < MAXQUOTAS; cnt++) {
1555 + if (discard[cnt]) {
1556 + down(&discard[cnt]->i_sem);
1557 + truncate_inode_pages(&discard[cnt]->i_data, 0);
1558 + up(&discard[cnt]->i_sem);
1559 + iput(discard[cnt]);
1564 void sync_dquots(struct super_block *sb, int type)
1567 if (sb->s_qcop->quota_sync)
1568 - sb->s_qcop->quota_sync(sb, type);
1569 + quota_sync_sb(sb, type);
1572 - while ((sb = get_super_to_sync(type))) {
1573 + while ((sb = get_super_to_sync(type)) != NULL) {
1574 if (sb->s_qcop->quota_sync)
1575 - sb->s_qcop->quota_sync(sb, type);
1576 + quota_sync_sb(sb, type);
1580 Index: linux-2.6.5-7.283/fs/ext3/inode.c
1581 ===================================================================
1582 --- linux-2.6.5-7.283.orig/fs/ext3/inode.c
1583 +++ linux-2.6.5-7.283/fs/ext3/inode.c
1584 @@ -1015,7 +1015,7 @@ out:
1590 ext3_journal_dirty_data(handle_t *handle, struct buffer_head *bh)
1592 int err = journal_dirty_data(handle, bh);
1593 Index: linux-2.6.5-7.283/fs/ext3/super.c
1594 ===================================================================
1595 --- linux-2.6.5-7.283.orig/fs/ext3/super.c
1596 +++ linux-2.6.5-7.283/fs/ext3/super.c
1598 #include <linux/vfs.h>
1599 #include <linux/random.h>
1600 #include <asm/uaccess.h>
1601 +#include <linux/quotaops.h>
1605 @@ -505,7 +506,33 @@ static void ext3_clear_inode(struct inod
1606 ext3_discard_reservation(inode);
1609 -static struct dquot_operations ext3_qops;
1610 +#ifdef CONFIG_QUOTA
1612 +static int ext3_dquot_initialize(struct inode *inode, int type);
1613 +static int ext3_dquot_drop(struct inode *inode);
1614 +static int ext3_write_dquot(struct dquot *dquot);
1615 +static int ext3_acquire_dquot(struct dquot *dquot);
1616 +static int ext3_release_dquot(struct dquot *dquot);
1617 +static int ext3_write_info(struct super_block *sb, int type);
1618 +static ssize_t ext3_quota_read(struct super_block *sb, int type, char *data,
1619 + size_t len, loff_t off);
1620 +static ssize_t ext3_quota_write(struct super_block *sb, int type,
1621 + const char *data, size_t len, loff_t off);
1623 +static struct dquot_operations ext3_quota_operations = {
1624 + .initialize = ext3_dquot_initialize,
1625 + .drop = ext3_dquot_drop,
1626 + .alloc_space = dquot_alloc_space,
1627 + .alloc_inode = dquot_alloc_inode,
1628 + .free_space = dquot_free_space,
1629 + .free_inode = dquot_free_inode,
1630 + .transfer = dquot_transfer,
1631 + .write_dquot = ext3_write_dquot,
1632 + .acquire_dquot = ext3_acquire_dquot,
1633 + .release_dquot = ext3_release_dquot,
1634 + .write_info = ext3_write_info
1638 static struct super_operations ext3_sops = {
1639 .alloc_inode = ext3_alloc_inode,
1640 @@ -522,6 +549,10 @@ static struct super_operations ext3_sops
1641 .statfs = ext3_statfs,
1642 .remount_fs = ext3_remount,
1643 .clear_inode = ext3_clear_inode,
1644 +#ifdef CONFIG_QUOTA
1645 + .quota_read = ext3_quota_read,
1646 + .quota_write = ext3_quota_write,
1650 static struct dentry *ext3_get_dentry(struct super_block *sb, void *vobjp)
1651 @@ -1377,7 +1408,9 @@ static int ext3_fill_super (struct super
1653 sb->s_op = &ext3_sops;
1654 sb->s_export_op = &ext3_export_ops;
1655 - sb->dq_op = &ext3_qops;
1656 +#ifdef CONFIG_QUOTA
1657 + sb->dq_op = &ext3_quota_operations;
1659 INIT_LIST_HEAD(&sbi->s_orphan); /* unlinked but open files */
1662 @@ -2040,70 +2073,200 @@ int ext3_statfs (struct super_block * sb
1666 -/* Blocks: (2 data blocks) * (3 indirect + 1 descriptor + 1 bitmap) + superblock */
1667 -#define EXT3_OLD_QFMT_BLOCKS 11
1668 -/* Blocks: quota info + (4 pointer blocks + 1 entry block) * (3 indirect + 1 descriptor + 1 bitmap) + superblock */
1669 -#define EXT3_V0_QFMT_BLOCKS 27
1671 -static int (*old_write_dquot)(struct dquot *dquot);
1672 -static void (*old_drop_dquot)(struct inode *inode);
1674 -static int fmt_to_blocks(int fmt)
1677 - case QFMT_VFS_OLD:
1678 - return EXT3_OLD_QFMT_BLOCKS;
1680 - return EXT3_V0_QFMT_BLOCKS;
1682 - return EXT3_MAX_TRANS_DATA;
1683 +static inline struct inode *dquot_to_inode(struct dquot *dquot)
1685 + return sb_dqopt(dquot->dq_sb)->files[dquot->dq_type];
1688 +static int ext3_dquot_initialize(struct inode *inode, int type)
1693 + /* We may create quota structure so we need to reserve enough blocks */
1694 + handle = ext3_journal_start(inode, 2*EXT3_QUOTA_INIT_BLOCKS);
1695 + if (IS_ERR(handle))
1696 + return PTR_ERR(handle);
1697 + ret = dquot_initialize(inode, type);
1698 + err = ext3_journal_stop(handle);
1704 +static int ext3_dquot_drop(struct inode *inode)
1709 + /* We may delete quota structure so we need to reserve enough blocks */
1710 + handle = ext3_journal_start(inode, 2*EXT3_QUOTA_INIT_BLOCKS);
1711 + if (IS_ERR(handle))
1712 + return PTR_ERR(handle);
1713 + ret = dquot_drop(inode);
1714 + err = ext3_journal_stop(handle);
1720 static int ext3_write_dquot(struct dquot *dquot)
1727 - struct quota_info *dqopt = sb_dqopt(dquot->dq_sb);
1728 - struct inode *qinode;
1729 + struct inode *inode;
1731 - nblocks = fmt_to_blocks(dqopt->info[dquot->dq_type].dqi_format->qf_fmt_id);
1732 - qinode = dqopt->files[dquot->dq_type]->f_dentry->d_inode;
1733 - handle = ext3_journal_start(qinode, nblocks);
1734 - if (IS_ERR(handle)) {
1735 - ret = PTR_ERR(handle);
1738 - ret = old_write_dquot(dquot);
1739 + inode = dquot_to_inode(dquot);
1740 + handle = ext3_journal_start(inode,
1741 + EXT3_QUOTA_TRANS_BLOCKS);
1742 + if (IS_ERR(handle))
1743 + return PTR_ERR(handle);
1744 + ret = dquot_commit(dquot);
1745 err = ext3_journal_stop(handle);
1753 -static void ext3_drop_dquot(struct inode *inode)
1754 +static int ext3_acquire_dquot(struct dquot *dquot)
1756 - int nblocks, type;
1757 - struct quota_info *dqopt = sb_dqopt(inode->i_sb);
1761 - for (type = 0; type < MAXQUOTAS; type++) {
1762 - if (sb_has_quota_enabled(inode->i_sb, type))
1765 - if (type < MAXQUOTAS)
1766 - nblocks = fmt_to_blocks(dqopt->info[type].dqi_format->qf_fmt_id);
1768 - nblocks = 0; /* No quota => no drop */
1769 - handle = ext3_journal_start(inode, 2*nblocks);
1770 + handle = ext3_journal_start(dquot_to_inode(dquot),
1771 + EXT3_QUOTA_INIT_BLOCKS);
1774 - old_drop_dquot(inode);
1775 - ext3_journal_stop(handle);
1777 + return PTR_ERR(handle);
1778 + ret = dquot_acquire(dquot);
1779 + err = ext3_journal_stop(handle);
1785 +static int ext3_release_dquot(struct dquot *dquot)
1790 + handle = ext3_journal_start(dquot_to_inode(dquot),
1791 + EXT3_QUOTA_INIT_BLOCKS);
1792 + if (IS_ERR(handle))
1793 + return PTR_ERR(handle);
1794 + ret = dquot_release(dquot);
1795 + err = ext3_journal_stop(handle);
1801 +static int ext3_write_info(struct super_block *sb, int type)
1806 + /* Data block + inode block */
1807 + handle = ext3_journal_start(sb->s_root->d_inode, 2);
1808 + if (IS_ERR(handle))
1809 + return PTR_ERR(handle);
1810 + ret = dquot_commit_info(sb, type);
1811 + err = ext3_journal_stop(handle);
1817 +/* Read data from quotafile - avoid pagecache and such because we cannot afford
1818 + * acquiring the locks... As quota files are never truncated and quota code
1819 + * itself serializes the operations (and noone else should touch the files)
1820 + * we don't have to be afraid of races */
1821 +static ssize_t ext3_quota_read(struct super_block *sb, int type, char *data,
1822 + size_t len, loff_t off)
1824 + struct inode *inode = sb_dqopt(sb)->files[type];
1825 + sector_t blk = off >> EXT3_BLOCK_SIZE_BITS(sb);
1827 + int offset = off & (sb->s_blocksize - 1);
1830 + struct buffer_head *bh;
1831 + loff_t i_size = i_size_read(inode);
1835 + if (off+len > i_size)
1838 + while (toread > 0) {
1839 + tocopy = sb->s_blocksize - offset < toread ?
1840 + sb->s_blocksize - offset : toread;
1841 + bh = ext3_bread(NULL, inode, blk, 0, &err);
1844 + if (!bh) /* A hole? */
1845 + memset(data, 0, tocopy);
1847 + memcpy(data, bh->b_data+offset, tocopy);
1857 +/* Write to quotafile (we know the transaction is already started and has
1858 + * enough credits) */
1859 +static ssize_t ext3_quota_write(struct super_block *sb, int type,
1860 + const char *data, size_t len, loff_t off)
1862 + struct inode *inode = sb_dqopt(sb)->files[type];
1863 + sector_t blk = off >> EXT3_BLOCK_SIZE_BITS(sb);
1865 + int offset = off & (sb->s_blocksize - 1);
1867 + size_t towrite = len;
1868 + struct buffer_head *bh;
1869 + handle_t *handle = journal_current_handle();
1871 + down(&inode->i_sem);
1872 + while (towrite > 0) {
1873 + tocopy = sb->s_blocksize - offset < towrite ?
1874 + sb->s_blocksize - offset : towrite;
1875 + bh = ext3_bread(handle, inode, blk, 1, &err);
1880 + memcpy(bh->b_data+offset, data, tocopy);
1881 + flush_dcache_page(bh->b_page);
1882 + unlock_buffer(bh);
1883 + /* Always do at least ordered writes for quotas */
1884 + err = ext3_journal_dirty_data(handle, bh);
1885 + mark_buffer_dirty(bh);
1890 + towrite -= tocopy;
1895 + if (len == towrite)
1897 + if (inode->i_size < off+len-towrite) {
1898 + i_size_write(inode, off+len-towrite);
1899 + EXT3_I(inode)->i_disksize = inode->i_size;
1901 + inode->i_version++;
1902 + inode->i_mtime = inode->i_ctime = CURRENT_TIME;
1903 + ext3_mark_inode_dirty(handle, inode);
1904 + up(&inode->i_sem);
1905 + return len - towrite;
1910 static struct super_block *ext3_get_sb(struct file_system_type *fs_type,
1911 @@ -2128,13 +2291,7 @@ static int __init init_ext3_fs(void)
1912 err = init_inodecache();
1915 -#ifdef CONFIG_QUOTA
1916 - init_dquot_operations(&ext3_qops);
1917 - old_write_dquot = ext3_qops.write_dquot;
1918 - old_drop_dquot = ext3_qops.drop;
1919 - ext3_qops.write_dquot = ext3_write_dquot;
1920 - ext3_qops.drop = ext3_drop_dquot;
1923 err = register_filesystem_lifo(&ext3_fs_type);
1926 Index: linux-2.6.5-7.283/fs/quota_v1.c
1927 ===================================================================
1928 --- linux-2.6.5-7.283.orig/fs/quota_v1.c
1929 +++ linux-2.6.5-7.283/fs/quota_v1.c
1931 #include <linux/init.h>
1932 #include <linux/module.h>
1934 -#include <asm/uaccess.h>
1935 #include <asm/byteorder.h>
1937 MODULE_AUTHOR("Jan Kara");
1938 @@ -41,23 +40,14 @@ static void v1_mem2disk_dqblk(struct v1_
1939 static int v1_read_dqblk(struct dquot *dquot)
1941 int type = dquot->dq_type;
1942 - struct file *filp;
1945 struct v1_disk_dqblk dqblk;
1947 - filp = sb_dqopt(dquot->dq_sb)->files[type];
1948 - if (filp == (struct file *)NULL)
1949 + if (!sb_dqopt(dquot->dq_sb)->files[type])
1952 - /* Now we are sure filp is valid */
1953 - offset = v1_dqoff(dquot->dq_id);
1954 /* Set structure to 0s in case read fails/is after end of file */
1955 memset(&dqblk, 0, sizeof(struct v1_disk_dqblk));
1957 - set_fs(KERNEL_DS);
1958 - filp->f_op->read(filp, (char *)&dqblk, sizeof(struct v1_disk_dqblk), &offset);
1960 + dquot->dq_sb->s_op->quota_read(dquot->dq_sb, type, (char *)&dqblk, sizeof(struct v1_disk_dqblk), v1_dqoff(dquot->dq_id));
1962 v1_disk2mem_dqblk(&dquot->dq_dqb, &dqblk);
1963 if (dquot->dq_dqb.dqb_bhardlimit == 0 && dquot->dq_dqb.dqb_bsoftlimit == 0 &&
1964 @@ -71,17 +61,9 @@ static int v1_read_dqblk(struct dquot *d
1965 static int v1_commit_dqblk(struct dquot *dquot)
1967 short type = dquot->dq_type;
1968 - struct file *filp;
1972 struct v1_disk_dqblk dqblk;
1974 - filp = sb_dqopt(dquot->dq_sb)->files[type];
1975 - offset = v1_dqoff(dquot->dq_id);
1977 - set_fs(KERNEL_DS);
1980 * Note: clear the DQ_MOD flag unconditionally,
1981 * so we don't loop forever on failure.
1982 @@ -93,9 +75,10 @@ static int v1_commit_dqblk(struct dquot
1983 dqblk.dqb_itime = sb_dqopt(dquot->dq_sb)->info[type].dqi_igrace;
1987 - ret = filp->f_op->write(filp, (char *)&dqblk,
1988 - sizeof(struct v1_disk_dqblk), &offset);
1989 + if (sb_dqopt(dquot->dq_sb)->files[type])
1990 + ret = dquot->dq_sb->s_op->quota_write(dquot->dq_sb, type, (char *)&dqblk,
1991 + sizeof(struct v1_disk_dqblk), v1_dqoff(dquot->dq_id));
1993 if (ret != sizeof(struct v1_disk_dqblk)) {
1994 printk(KERN_WARNING "VFS: dquota write failed on dev %s\n",
1995 dquot->dq_sb->s_id);
1996 @@ -106,7 +89,6 @@ static int v1_commit_dqblk(struct dquot
2004 @@ -126,14 +108,11 @@ struct v2_disk_dqheader {
2006 static int v1_check_quota_file(struct super_block *sb, int type)
2008 - struct file *f = sb_dqopt(sb)->files[type];
2009 - struct inode *inode = f->f_dentry->d_inode;
2010 + struct inode *inode = sb_dqopt(sb)->files[type];
2013 struct v2_disk_dqheader dqhead;
2016 - loff_t offset = 0;
2018 static const uint quota_magics[] = V2_INITQMAGICS;
2020 @@ -145,10 +124,7 @@ static int v1_check_quota_file(struct su
2021 if ((blocks % sizeof(struct v1_disk_dqblk) * BLOCK_SIZE + off) % sizeof(struct v1_disk_dqblk))
2023 /* Doublecheck whether we didn't get file with new format - with old quotactl() this could happen */
2025 - set_fs(KERNEL_DS);
2026 - size = f->f_op->read(f, (char *)&dqhead, sizeof(struct v2_disk_dqheader), &offset);
2028 + size = sb->s_op->quota_read(sb, type, (char *)&dqhead, sizeof(struct v2_disk_dqheader), 0);
2029 if (size != sizeof(struct v2_disk_dqheader))
2030 return 1; /* Probably not new format */
2031 if (le32_to_cpu(dqhead.dqh_magic) != quota_magics[type])
2032 @@ -160,16 +136,10 @@ static int v1_check_quota_file(struct su
2033 static int v1_read_file_info(struct super_block *sb, int type)
2035 struct quota_info *dqopt = sb_dqopt(sb);
2038 - struct file *filp = dqopt->files[type];
2039 struct v1_disk_dqblk dqblk;
2042 - offset = v1_dqoff(0);
2044 - set_fs(KERNEL_DS);
2045 - if ((ret = filp->f_op->read(filp, (char *)&dqblk, sizeof(struct v1_disk_dqblk), &offset)) != sizeof(struct v1_disk_dqblk)) {
2046 + if ((ret = sb->s_op->quota_read(sb, type, (char *)&dqblk, sizeof(struct v1_disk_dqblk), v1_dqoff(0))) != sizeof(struct v1_disk_dqblk)) {
2050 @@ -178,38 +148,31 @@ static int v1_read_file_info(struct supe
2051 dqopt->info[type].dqi_igrace = dqblk.dqb_itime ? dqblk.dqb_itime : MAX_IQ_TIME;
2052 dqopt->info[type].dqi_bgrace = dqblk.dqb_btime ? dqblk.dqb_btime : MAX_DQ_TIME;
2058 static int v1_write_file_info(struct super_block *sb, int type)
2060 struct quota_info *dqopt = sb_dqopt(sb);
2062 - struct file *filp = dqopt->files[type];
2063 struct v1_disk_dqblk dqblk;
2067 dqopt->info[type].dqi_flags &= ~DQF_INFO_DIRTY;
2068 - offset = v1_dqoff(0);
2070 - set_fs(KERNEL_DS);
2071 - if ((ret = filp->f_op->read(filp, (char *)&dqblk, sizeof(struct v1_disk_dqblk), &offset)) != sizeof(struct v1_disk_dqblk)) {
2072 + if ((ret = sb->s_op->quota_read(sb, type, (char *)&dqblk,
2073 + sizeof(struct v1_disk_dqblk), v1_dqoff(0))) != sizeof(struct v1_disk_dqblk)) {
2078 dqblk.dqb_itime = dqopt->info[type].dqi_igrace;
2079 dqblk.dqb_btime = dqopt->info[type].dqi_bgrace;
2080 - offset = v1_dqoff(0);
2081 - ret = filp->f_op->write(filp, (char *)&dqblk, sizeof(struct v1_disk_dqblk), &offset);
2082 + ret = sb->s_op->quota_write(sb, type, (char *)&dqblk,
2083 + sizeof(struct v1_disk_dqblk), v1_dqoff(0));
2084 if (ret == sizeof(struct v1_disk_dqblk))
2093 Index: linux-2.6.5-7.283/fs/reiserfs/super.c
2094 ===================================================================
2095 --- linux-2.6.5-7.283.orig/fs/reiserfs/super.c
2096 +++ linux-2.6.5-7.283/fs/reiserfs/super.c
2097 @@ -1677,7 +1677,7 @@ inversion between quota and journal lock
2098 #define REISERFS_V0_QFMT_BLOCKS (4*(JOURNAL_PER_BALANCE_CNT+2)+2+1)
2100 static int (*old_write_dquot)(struct dquot *dquot);
2101 -static void (*old_drop_dquot)(struct inode *inode);
2102 +static int (*old_drop_dquot)(struct inode *inode);
2104 static int fmt_to_blocks(int fmt)
2106 @@ -1697,10 +1697,8 @@ static int reiserfs_write_dquot(struct d
2108 struct reiserfs_transaction_handle handle;
2109 struct quota_info *dqopt = sb_dqopt(dquot->dq_sb);
2110 - struct inode *qinode;
2112 nblocks = fmt_to_blocks(dqopt->info[dquot->dq_type].dqi_format->qf_fmt_id);
2113 - qinode = dqopt->files[dquot->dq_type]->f_dentry->d_inode;
2114 reiserfs_write_lock(dquot->dq_sb);
2115 ret = journal_begin(&handle, dquot->dq_sb, nblocks);
2117 @@ -1713,11 +1711,12 @@ static int reiserfs_write_dquot(struct d
2121 -static void reiserfs_drop_dquot(struct inode *inode)
2122 +static int reiserfs_drop_dquot(struct inode *inode)
2125 struct quota_info *dqopt = sb_dqopt(inode->i_sb);
2126 struct reiserfs_transaction_handle handle;
2129 for (type = 0; type < MAXQUOTAS; type++) {
2130 if (sb_has_quota_enabled(inode->i_sb, type))
2131 @@ -1728,12 +1727,15 @@ static void reiserfs_drop_dquot(struct i
2133 nblocks = 0; /* No quota => no drop */
2134 reiserfs_write_lock(inode->i_sb);
2135 - if (journal_begin(&handle, inode->i_sb, 2*nblocks))
2137 - old_drop_dquot(inode);
2138 - journal_end(&handle, inode->i_sb, 2*nblocks);
2139 + err = journal_begin(&handle, inode->i_sb, 2*nblocks);
2142 + ret = old_drop_dquot(inode);
2143 + err = journal_end(&handle, inode->i_sb, 2*nblocks);
2146 reiserfs_write_unlock(inode->i_sb);