Whamcloud - gitweb
Branch HEAD
[fs/lustre-release.git] / lustre / kernel_patches / patches / 2.6.5-quotafix.patch
1 %patch
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
6 @@ -72,6 +72,19 @@
7  
8  #define EXT3_INDEX_EXTRA_TRANS_BLOCKS  8
9  
10 +#ifdef CONFIG_QUOTA
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)
18 +#else
19 +#define EXT3_QUOTA_TRANS_BLOCKS 0
20 +#define EXT3_QUOTA_INIT_BLOCKS 0
21 +#endif
22 +
23  int
24  ext3_mark_iloc_dirty(handle_t *handle, 
25                      struct inode *inode,
26 @@ -97,6 +110,8 @@
27  void ext3_journal_abort_handle(const char *caller, const char *err_fn,
28                 struct buffer_head *bh, handle_t *handle, int err);
29  
30 +int ext3_journal_dirty_data(handle_t *handle, struct buffer_head *bh);
31 +
32  static inline int
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
39 @@ -967,6 +967,9 @@
40         void (*umount_begin) (struct super_block *);
41  
42         int (*show_options)(struct seq_file *, struct vfsmount *);
43 +
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);
46  };
47  
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
53 @@ -138,6 +138,10 @@
54  #include <linux/dqblk_v1.h>
55  #include <linux/dqblk_v2.h>
56  
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
60 +
61  /*
62   * Data for one user/group kept in memory
63   */
64 @@ -168,22 +172,21 @@
65         } u;
66  };
67  
68 +struct super_block;
69 +
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? */
75  
76 -extern inline void mark_info_dirty(struct mem_dqinfo *info)
77 -{
78 -       set_bit(DQF_INFO_DIRTY_B, &info->dqi_flags);
79 -}
80 -
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))
85  
86  #define sb_dqopt(sb) (&(sb)->s_dquot)
87 +#define sb_dqinfo(sb, type) (sb_dqopt(sb)->info+(type))
88  
89  struct dqstats {
90         int lookups;
91 @@ -204,6 +207,9 @@
92  #define DQ_BLKS_B      1
93  #define DQ_INODES_B    2
94  #define DQ_FAKE_B      3
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) */
98  
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 */
106  };
107  
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" */
125  };
126  
127  /* Operations handling requests from userspace */
128 @@ -283,7 +293,8 @@
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 */
137  };
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
142 @@ -22,17 +22,22 @@
143   */
144  extern void sync_dquots(struct super_block *sb, int type);
145  
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);
150  
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);
153  
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);
158  
159  extern int  dquot_transfer(struct inode *inode, struct iattr *iattr);
160  
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);
165 +
166  /*
167   * Operations supported for diskquotas.
168   */
169 @@ -143,7 +148,7 @@
170  {
171         int ret = -ENOSYS;
172  
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);
176         return ret;
177  }
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);
190  
191 @@ -1292,9 +1292,9 @@
192                          0);
193  }
194  
195 -static inline int security_quota_on (struct file * file)
196 +static inline int security_quota_on (struct dentry * dentry)
197  {
198 -       return COND_SECURITY(quota_on (file), 
199 +       return COND_SECURITY(quota_on (dentry), 
200                          0);
201  }
202  
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
207 @@ -90,7 +90,7 @@
208         return 0;
209  }
210  
211 -static int dummy_quota_on (struct file *f)
212 +static int dummy_quota_on (struct dentry *dentry)
213  {
214         return 0;
215  }
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 @@
221         return rc;
222  }
223  
224 -static int selinux_quota_on(struct file *f)
225 +static int selinux_quota_on(struct dentry *dentry)
226  {
227 -       return file_has_perm(current, f, FILE__QUOTAON);
228 +       return dentry_has_perm(current, NULL, dentry, FILE__QUOTAON);
229  }
230  
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
236 @@ -52,6 +52,9 @@
237   *             New SMP locking.
238   *             Jan Kara, <jack@suse.cz>, 10/2002
239   *
240 + *             Fix lock inversion problems
241 + *             Jan Kara, <jack@suse.cz>, 2003,2004
242 + *
243   * (C) Copyright 1994 - 1997 Marco van Wieringen 
244   */
245  
246 @@ -75,7 +78,8 @@
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>
253  
254  #include <asm/uaccess.h>
255  
256 @@ -109,7 +113,7 @@
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.
259   *
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
263   */
264  spinlock_t dq_list_lock = SPIN_LOCK_UNLOCKED;
265 @@ -175,8 +179,7 @@
266   * on all three lists, depending on its current state.
267   *
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
270 - * at every dquot.
271 + * list is used for invalidate operation, which must look at every dquot.
272   *
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 @@
276         up(&dquot->dq_lock);
277  }
278  
279 -static int read_dqblk(struct dquot *dquot)
280 +void mark_info_dirty(struct super_block *sb, int type)
281  {
282 -       int ret;
283 +       set_bit(DQF_INFO_DIRTY_B, &sb_dqopt(sb)->info[type].dqi_flags);
284 +}
285 +EXPORT_SYMBOL(mark_info_dirty);
286 +
287 +/*
288 + *     Read dquot from disk and alloc space for it
289 + */
290 +
291 +int dquot_acquire(struct dquot *dquot)
292 +{
293 +       int ret = 0, ret2 = 0;
294         struct quota_info *dqopt = sb_dqopt(dquot->dq_sb);
295  
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);
301 +       if (ret < 0)
302 +               goto out_iolock;
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);
310 +               if (ret < 0)
311 +                       goto out_iolock;
312 +               if (ret2 < 0) {
313 +                       ret = ret2;
314 +                       goto out_iolock;
315 +               }
316 +       }
317 +       set_bit(DQ_ACTIVE_B, &dquot->dq_flags);
318 +out_iolock:
319         up(&dqopt->dqio_sem);
320         up(&dquot->dq_lock);
321         return ret;
322  }
323  
324 -static int commit_dqblk(struct dquot *dquot)
325 +/*
326 + *     Write dquot to disk
327 + */
328 +int dquot_commit(struct dquot *dquot)
329  {
330 -       int ret;
331 +       int ret = 0, ret2 = 0;
332         struct quota_info *dqopt = sb_dqopt(dquot->dq_sb);
333  
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);
339 +               goto out_sem;
340 +       }
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);
348 +               if (ret >= 0)
349 +                       ret = ret2;
350 +       }
351 +out_sem:
352         up(&dqopt->dqio_sem);
353         return ret;
354  }
355  
356 +/*
357 + *     Release dquot
358 + */
359 +int dquot_release(struct dquot *dquot)
360 +{
361 +       int ret = 0, ret2 = 0;
362 +       struct quota_info *dqopt = sb_dqopt(dquot->dq_sb);
363 +
364 +       down(&dquot->dq_lock);
365 +       /* Check whether we are not racing with some other dqget() */
366 +       if (atomic_read(&dquot->dq_count) > 1)
367 +               goto out_dqlock;
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);
374 +               if (ret >= 0)
375 +                       ret = ret2;
376 +       }
377 +       clear_bit(DQ_ACTIVE_B, &dquot->dq_flags);
378 +       up(&dqopt->dqio_sem);
379 +out_dqlock:
380 +       up(&dquot->dq_lock);
381 +       return ret;
382 +}
383 +
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
387 @@ -343,6 +421,11 @@
388                         continue;
389                 if (!dquot_dirty(dquot))
390                         continue;
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);
394 +                       continue;
395 +               }                       
396                 atomic_inc(&dquot->dq_count);
397                 dqstats.lookups++;
398                 spin_unlock(&dq_list_lock);
399 @@ -353,11 +436,9 @@
400         spin_unlock(&dq_list_lock);
401  
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);
407 -               }
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);
412         dqstats.syncs++;
413         spin_unlock(&dq_list_lock);
414 @@ -432,11 +513,19 @@
415                 spin_unlock(&dq_list_lock);
416                 return;
417         }
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);
422                 goto we_slept;
423         }
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);
429 +               goto we_slept;
430 +       }
431 +                       
432         atomic_dec(&dquot->dq_count);
433  #ifdef __DQUOT_PARANOIA
434         /* sanity check */
435 @@ -495,7 +584,6 @@
436                 insert_dquot_hash(dquot);
437                 dqstats.lookups++;
438                 spin_unlock(&dq_list_lock);
439 -               read_dqblk(dquot);
440         } else {
441                 if (!atomic_read(&dquot->dq_count))
442                         remove_free_dquot(dquot);
443 @@ -503,10 +591,15 @@
444                 dqstats.cache_hits++;
445                 dqstats.lookups++;
446                 spin_unlock(&dq_list_lock);
447 -               wait_on_dquot(dquot);
448                 if (empty)
449                         kmem_cache_free(dquot_cachep, empty);
450         }
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) {
454 +               dqput(dquot);
455 +               return NODQUOT;
456 +       }
457  
458  #ifdef __DQUOT_PARANOIA
459         if (!dquot->dq_sb)      /* Has somebody invalidated entry under us? */
460 @@ -819,19 +912,19 @@
461   *
462   * Note: this is a blocking operation.
463   */
464 -void dquot_initialize(struct inode *inode, int type)
465 +int dquot_initialize(struct inode *inode, int type)
466  {
467         unsigned int id = 0;
468         int cnt;
469  
470         /* Solve deadlock when we recurse when holding dqptr_sem... */
471         if (IS_NOQUOTA(inode))
472 -               return;
473 +               return 0;
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);
478 -               return;
479 +               return 0;
480         }
481         /* Build list of quotas to initialize... */
482         for (cnt = 0; cnt < MAXQUOTAS; cnt++) {
483 @@ -852,13 +945,14 @@
484                 }
485         }
486         up_write(&sb_dqopt(inode->i_sb)->dqptr_sem);
487 +       return 0;
488  }
489  
490  /*
491   *     Release all quotas referenced by inode
492   *     Needs dqonoff_sem to guard dqput()
493   */
494 -void dquot_drop(struct inode *inode)
495 +int dquot_drop(struct inode *inode)
496  {
497         int cnt;
498  
499 @@ -871,6 +965,7 @@
500                 }
501         }
502         up_write(&sb_dqopt(inode->i_sb)->dqptr_sem);
503 +       return 0;
504  }
505  
506  /*
507 @@ -958,14 +1053,14 @@
508  /*
509   * This is a non-blocking operation.
510   */
511 -void dquot_free_space(struct inode *inode, qsize_t number)
512 +int dquot_free_space(struct inode *inode, qsize_t number)
513  {
514         unsigned int cnt;
515  
516         /* Solve deadlock when we recurse when holding dqptr_sem... */
517         if (IS_NOQUOTA(inode)) {
518                 inode_add_bytes(inode, number);
519 -               return;
520 +               return QUOTA_OK;
521         }
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);
528 +       return QUOTA_OK;
529  }
530  
531  /*
532   * This is a non-blocking operation.
533   */
534 -void dquot_free_inode(const struct inode *inode, unsigned long number)
535 +int dquot_free_inode(const struct inode *inode, unsigned long number)
536  {
537         unsigned int cnt;
538  
539         /* Solve deadlock when we recurse when holding dqptr_sem... */
540         if (IS_NOQUOTA(inode))
541 -               return;
542 +               return QUOTA_OK;
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);
547 -               return;
548 +               return QUOTA_OK;
549         }
550         spin_lock(&dq_data_lock);
551         for (cnt = 0; cnt < MAXQUOTAS; cnt++) {
552 @@ -1007,6 +1103,7 @@
553         }
554         spin_unlock(&dq_data_lock);
555         up_read(&sb_dqopt(inode->i_sb)->dqptr_sem);
556 +       return QUOTA_OK;
557  }
558  
559  /*
560 @@ -1104,6 +1201,20 @@
561  }
562  
563  /*
564 + * Write info of quota file to disk
565 + */
566 +int dquot_commit_info(struct super_block *sb, int type)
567 +{
568 +       int ret;
569 +       struct quota_info *dqopt = sb_dqopt(sb);
570 +
571 +       down(&dqopt->dqio_sem);
572 +       ret = dqopt->ops[type]->write_file_info(sb, type);
573 +       up(&dqopt->dqio_sem);
574 +       return ret;
575 +}
576 +
577 +/*
578   * Definitions of diskquota operations.
579   */
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                             
590  };
591  
592  /* Function used by filesystems for initializing the dquot_operations structure */
593 @@ -1154,13 +1268,14 @@
594  {
595         int cnt;
596         struct quota_info *dqopt = sb_dqopt(sb);
597 -
598 -       if (!sb)
599 -               goto out;
600 +       struct inode *toputinode[MAXQUOTAS];
601 +       struct vfsmount *toputmnt[MAXQUOTAS];
602  
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)
609                         continue;
610                 if (!sb_has_quota_enabled(sb, cnt))
611 @@ -1172,94 +1287,115 @@
612                 invalidate_dquots(sb, cnt);
613                 /*
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.
617                  */
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);
622 -               }
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);
628  
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;
639         }
640         up(&dqopt->dqonoff_sem);
641 -out:
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
659 +                        * nothing to do */
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]);
668 +                       }
669 +                       up(&dqopt->dqonoff_sem);
670 +                       /* We don't hold the reference when we turned on quotas
671 +                        * just for the journal replay... */
672 +                       if (toputmnt[cnt])
673 +                               mntput(toputmnt[cnt]);
674 +               }
675 +       invalidate_bdev(sb->s_bdev, 0);
676         return 0;
677  }
678  
679 -int vfs_quota_on(struct super_block *sb, int type, int format_id, char *path)
680 +/*
681 + *     Turn quotas on on a device
682 + */
683 +
684 +/* Helper function when we already have the inode */
685 +static int vfs_quota_on_inode(struct inode *inode, int type, int format_id)
686  {
687 -       struct file *f;
688 -       struct inode *inode;
689 -       struct quota_info *dqopt = sb_dqopt(sb);
690         struct quota_format_type *fmt = find_quota_format(format_id);
691 -       int error, cnt;
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);
696 +       int error;
697 +       int oldflags = -1;
698  
699         if (!fmt)
700                 return -ESRCH;
701 -       f = filp_open(path, O_RDWR, 0600);
702 -       if (IS_ERR(f)) {
703 -               error = PTR_ERR(f);
704 +       if (!S_ISREG(inode->i_mode)) {
705 +               error = -EACCES;
706 +               goto out_fmt;
707 +       }
708 +       if (IS_RDONLY(inode)) {
709 +               error = -EROFS;
710 +               goto out_fmt;
711 +       }
712 +       if (!sb->s_op->quota_write || !sb->s_op->quota_read) {
713 +               error = -EINVAL;
714                 goto out_fmt;
715         }
716 -       error = -EIO;
717 -       if (!f->f_op || !f->f_op->read || !f->f_op->write)
718 -               goto out_f;
719 -       error = security_quota_on(f);
720 -       if (error)
721 -               goto out_f;
722 -       inode = f->f_dentry->d_inode;
723 -       error = -EACCES;
724 -       if (!S_ISREG(inode->i_mode))
725 -               goto out_f;
726  
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)) {
735                 error = -EBUSY;
736                 goto out_lock;
737         }
738 -       oldflags = inode->i_flags;
739 -       dqopt->files[type] = f;
740 -       error = -EINVAL;
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;
750 -
751 -       /*
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.
756 -        */
757 -       mapping_set_gfp_mask(inode->i_mapping,
758 -               mapping_gfp_mask(inode->i_mapping) & ~__GFP_FS);
759 -
760 -       for (cnt = 0; cnt < MAXQUOTAS; cnt++) {
761 -               to_drop[cnt] = inode->i_dquot[cnt];
762 -               inode->i_dquot[cnt] = NODQUOT;
763 -       }
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++) {
771 -               if (to_drop[cnt])
772 -                       dqput(to_drop[cnt]);
773 -       }
774 +
775 +       error = -EIO;
776 +       dqopt->files[type] = igrab(inode);
777 +       if (!dqopt->files[type])
778 +               goto out_lock;
779 +       error = -EINVAL;
780 +       if (!fmt->qf_ops->check_quota_file(sb, type))
781 +               goto out_file_init;
782  
783         dqopt->ops[type] = fmt->qf_ops;
784         dqopt->info[type].dqi_format = fmt;
785 @@ -1269,6 +1405,7 @@
786                 goto out_file_init;
787         }
788         up(&dqopt->dqio_sem);
789 +       up(&inode->i_sem);
790         set_enable_flags(dqopt, type);
791  
792         add_dquot_ref(sb, type);
793 @@ -1277,18 +1414,51 @@
794         return 0;
795  
796  out_file_init:
797 -       inode->i_flags = oldflags;
798         dqopt->files[type] = NULL;
799 +       iput(inode);
800  out_lock:
801         up(&dqopt->dqonoff_sem);
802 -out_f:
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);
811 +       }
812 +       up(&inode->i_sem);
813  out_fmt:
814         put_quota_format(fmt);
815  
816         return error; 
817  }
818  
819 +/* Actual function called from quotactl() */
820 +int vfs_quota_on(struct super_block *sb, int type, int format_id, char *path)
821 +{
822 +       struct nameidata nd;
823 +       int error;
824 +
825 +       error = path_lookup(path, LOOKUP_FOLLOW, &nd);
826 +       if (error < 0)
827 +               return error;
828 +       error = security_quota_on(nd.dentry);
829 +       if (error)
830 +               goto out_path;
831 +       /* Quota file not on the same filesystem? */
832 +       if (nd.mnt->mnt_sb != sb)
833 +               error = -EXDEV;
834 +       else {
835 +               error = vfs_quota_on_inode(nd.dentry->d_inode, type, format_id);
836 +               if (!error)
837 +                       sb_dqopt(sb)->mnt[type] = mntget(nd.mnt);
838 +       }
839 +
840 +out_path:
841 +       path_release(&nd);
842 +       return error;
843 +}
844 +
845  /* Generic routine for getting common part of quota structure */
846  static void do_get_dqblk(struct dquot *dquot, struct if_dqblk *di)
847  {
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);
858         return 0;
859  }
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);
875 +
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
880 @@ -13,7 +13,6 @@
881  #include <linux/slab.h>
882  
883  #include <asm/byteorder.h>
884 -#include <asm/uaccess.h>
885  
886  MODULE_AUTHOR("Jan Kara");
887  MODULE_DESCRIPTION("Quota format v2 support");
888 @@ -30,19 +29,15 @@
889  static int v2_check_quota_file(struct super_block *sb, int type)
890  {
891         struct v2_disk_dqheader dqhead;
892 -       struct file *f = sb_dqopt(sb)->files[type];
893 -       mm_segment_t fs;
894         ssize_t size;
895 -       loff_t offset = 0;
896         static const uint quota_magics[] = V2_INITQMAGICS;
897         static const uint quota_versions[] = V2_INITQVERSIONS;
898   
899 -       fs = get_fs();
900 -       set_fs(KERNEL_DS);
901 -       size = f->f_op->read(f, (char *)&dqhead, sizeof(struct v2_disk_dqheader), &offset);
902 -       set_fs(fs);
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");
907                 return 0;
908 +       }
909         if (le32_to_cpu(dqhead.dqh_magic) != quota_magics[type] ||
910             le32_to_cpu(dqhead.dqh_version) != quota_versions[type])
911                 return 0;
912 @@ -52,20 +47,15 @@
913  /* Read information header from quota file */
914  static int v2_read_file_info(struct super_block *sb, int type)
915  {
916 -       mm_segment_t fs;
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];
920         ssize_t size;
921 -       loff_t offset = V2_DQINFOOFF;
922  
923 -       fs = get_fs();
924 -       set_fs(KERNEL_DS);
925 -       size = f->f_op->read(f, (char *)&dinfo, sizeof(struct v2_disk_dqinfo), &offset);
926 -       set_fs(fs);
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);
932 +                       sb->s_id);
933                 return -1;
934         }
935         info->dqi_bgrace = le32_to_cpu(dinfo.dqi_bgrace);
936 @@ -80,12 +70,9 @@
937  /* Write information header to quota file */
938  static int v2_write_file_info(struct super_block *sb, int type)
939  {
940 -       mm_segment_t fs;
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];
944         ssize_t size;
945 -       loff_t offset = V2_DQINFOOFF;
946  
947         info->dqi_flags &= ~DQF_INFO_DIRTY;
948         dinfo.dqi_bgrace = cpu_to_le32(info->dqi_bgrace);
949 @@ -94,13 +81,13 @@
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);
953 -       fs = get_fs();
954 -       set_fs(KERNEL_DS);
955 -       size = f->f_op->write(f, (char *)&dinfo, sizeof(struct v2_disk_dqinfo), &offset);
956 -       set_fs(fs);
957 +       
958 +       size = sb->s_op->quota_write(sb, type, (char *)&dinfo,
959 +                       sizeof(struct v2_disk_dqinfo), V2_DQINFOOFF);
960 +
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);
964 +                       sb->s_id);
965                 return -1;
966         }
967         return 0;
968 @@ -144,38 +131,24 @@
969         kfree(buf);
970  }
971  
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)
974  {
975 -       mm_segment_t fs;
976 -       ssize_t ret;
977 -       loff_t offset = blk<<V2_DQBLKSIZE_BITS;
978 -
979         memset(buf, 0, V2_DQBLKSIZE);
980 -       fs = get_fs();
981 -       set_fs(KERNEL_DS);
982 -       ret = filp->f_op->read(filp, (char *)buf, V2_DQBLKSIZE, &offset);
983 -       set_fs(fs);
984 -       return ret;
985 +       return sb->s_op->quota_read(sb, type, (char *)buf,
986 +                       V2_DQBLKSIZE, blk << V2_DQBLKSIZE_BITS);
987  }
988  
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)
991  {
992 -       mm_segment_t fs;
993 -       ssize_t ret;
994 -       loff_t offset = blk<<V2_DQBLKSIZE_BITS;
995 -
996 -       fs = get_fs();
997 -       set_fs(KERNEL_DS);
998 -       ret = filp->f_op->write(filp, (char *)buf, V2_DQBLKSIZE, &offset);
999 -       set_fs(fs);
1000 -       return ret;
1001 -
1002 +       return sb->s_op->quota_write(sb, type, (char *)buf,
1003 +                       V2_DQBLKSIZE, blk << V2_DQBLKSIZE_BITS);
1004  }
1005  
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)
1009  {
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;
1013         int ret, blk;
1014  
1015 @@ -183,17 +156,18 @@
1016                 return -ENOMEM;
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)
1021                         goto out_buf;
1022                 info->u.v2_i.dqi_free_blk = le32_to_cpu(dh->dqdh_next_free);
1023         }
1024         else {
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)
1029                         goto out_buf;
1030                 blk = info->u.v2_i.dqi_blocks++;
1031         }
1032 -       mark_info_dirty(info);
1033 +       mark_info_dirty(sb, type);
1034         ret = blk;
1035  out_buf:
1036         freedqbuf(buf);
1037 @@ -201,8 +175,9 @@
1038  }
1039  
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)
1043  {
1044 +       struct mem_dqinfo *info = sb_dqinfo(sb, type);
1045         struct v2_disk_dqdbheader *dh = (struct v2_disk_dqdbheader *)buf;
1046         int err;
1047  
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)
1057                 return err;
1058         return 0;
1059  }
1060  
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)
1064  {
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);
1069         int err;
1070 @@ -227,26 +204,27 @@
1071         if (!tmpbuf)
1072                 return -ENOMEM;
1073         if (nextblk) {
1074 -               if ((err = read_blk(filp, nextblk, tmpbuf)) < 0)
1075 +               if ((err = read_blk(sb, type, nextblk, tmpbuf)) < 0)
1076                         goto out_buf;
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)
1080                         goto out_buf;
1081         }
1082         if (prevblk) {
1083 -               if ((err = read_blk(filp, prevblk, tmpbuf)) < 0)
1084 +               if ((err = read_blk(sb, type, prevblk, tmpbuf)) < 0)
1085                         goto out_buf;
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)
1089                         goto out_buf;
1090         }
1091         else {
1092                 info->u.v2_i.dqi_free_entry = nextblk;
1093 -               mark_info_dirty(info);
1094 +               mark_info_dirty(sb, type);
1095         }
1096         freedqbuf(tmpbuf);
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);
1102         return 0;
1103  out_buf:
1104 @@ -255,9 +233,10 @@
1105  }
1106  
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)
1110  {
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;
1114         int err;
1115  
1116 @@ -265,18 +244,18 @@
1117                 return -ENOMEM;
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)
1122                 goto out_buf;
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)
1126                         goto out_buf;
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)
1130                         goto out_buf;
1131         }
1132         freedqbuf(tmpbuf);
1133         info->u.v2_i.dqi_free_entry = blk;
1134 -       mark_info_dirty(info);
1135 +       mark_info_dirty(sb, type);
1136         return 0;
1137  out_buf:
1138         freedqbuf(tmpbuf);
1139 @@ -286,8 +265,8 @@
1140  /* Find space for dquot */
1141  static uint find_free_dqentry(struct dquot *dquot, int *err)
1142  {
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;
1147         uint blk, i;
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)
1156                         goto out_buf;
1157         }
1158         else {
1159 -               blk = get_free_dqblk(filp, info);
1160 +               blk = get_free_dqblk(sb, dquot->dq_type);
1161                 if ((int)blk < 0) {
1162                         *err = blk;
1163                         freedqbuf(buf);
1164                         return 0;
1165                 }
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);
1172         }
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);
1177                         goto out_buf;
1178                 }
1179 @@ -333,7 +313,7 @@
1180                 goto out_buf;
1181         }
1182  #endif
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);
1186                 goto out_buf;
1187         }
1188 @@ -348,8 +328,7 @@
1189  /* Insert reference to structure into the trie */
1190  static int do_insert_tree(struct dquot *dquot, uint *treeblk, int depth)
1191  {
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;
1195         dqbuf_t buf;
1196         int ret = 0, newson = 0, newact = 0;
1197         u32 *ref;
1198 @@ -358,7 +337,7 @@
1199         if (!(buf = getdqbuf()))
1200                 return -ENOMEM;
1201         if (!*treeblk) {
1202 -               ret = get_free_dqblk(filp, info);
1203 +               ret = get_free_dqblk(sb, dquot->dq_type);
1204                 if (ret < 0)
1205                         goto out_buf;
1206                 *treeblk = ret;
1207 @@ -366,7 +345,7 @@
1208                 newact = 1;
1209         }
1210         else {
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);
1214                         goto out_buf;
1215                 }
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);
1222         }
1223         else if (newact && ret < 0)
1224 -               put_free_dqblk(filp, info, buf, *treeblk);
1225 +               put_free_dqblk(sb, dquot->dq_type, buf, *treeblk);
1226  out_buf:
1227         freedqbuf(buf);
1228         return ret;
1229 @@ -411,19 +390,14 @@
1230  static int v2_write_dquot(struct dquot *dquot)
1231  {
1232         int type = dquot->dq_type;
1233 -       struct file *filp;
1234 -       mm_segment_t fs;
1235 -       loff_t offset;
1236         ssize_t ret;
1237         struct v2_disk_dqblk ddquot, empty;
1238  
1239         if (!dquot->dq_off)
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);
1243                         return ret;
1244                 }
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);
1254 -       fs = get_fs();
1255 -       set_fs(KERNEL_DS);
1256 -       ret = filp->f_op->write(filp, (char *)&ddquot, sizeof(struct v2_disk_dqblk), &offset);
1257 -       set_fs(fs);
1258 +       
1259 +       ret = dquot->dq_sb->s_op->quota_write(dquot->dq_sb, type,
1260 +                       (char *)&ddquot, sizeof(struct v2_disk_dqblk), dquot->dq_off);
1261 +
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);
1264                 if (ret >= 0)
1265 @@ -450,8 +424,8 @@
1266  /* Free dquot entry in data block */
1267  static int free_dqentry(struct dquot *dquot, uint blk)
1268  {
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();
1275         int ret = 0;
1276 @@ -459,34 +433,39 @@
1277         if (!buf)
1278                 return -ENOMEM;
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));
1284                 goto out_buf;
1285         }
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);
1289                 goto out_buf;
1290         }
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);
1301                         goto out_buf;
1302                 }
1303         }
1304         else {
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);
1313                                 goto out_buf;
1314                         }
1315                 }
1316                 else
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);
1322                                 goto out_buf;
1323                         }
1324         }
1325 @@ -499,8 +478,8 @@
1326  /* Remove reference to dquot from tree */
1327  static int remove_tree(struct dquot *dquot, uint *blk, int depth)
1328  {
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();
1334         int ret = 0;
1335         uint newblk;
1336 @@ -508,7 +487,7 @@
1337         
1338         if (!buf)
1339                 return -ENOMEM;
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);
1343                 goto out_buf;
1344         }
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);
1351                         *blk = 0;
1352                 }
1353                 else
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);
1359         }
1360  out_buf:
1361         freedqbuf(buf);
1362 @@ -549,7 +529,6 @@
1363  /* Find entry in block */
1364  static loff_t find_block_dqentry(struct dquot *dquot, uint blk)
1365  {
1366 -       struct file *filp = sb_dqopt(dquot->dq_sb)->files[dquot->dq_type];
1367         dqbuf_t buf = getdqbuf();
1368         loff_t ret = 0;
1369         int i;
1370 @@ -557,27 +536,31 @@
1371  
1372         if (!buf)
1373                 return -ENOMEM;
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);
1377                 goto out_buf;
1378         }
1379         if (dquot->dq_id)
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;
1385  
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)))
1391                                 break;
1392         }
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);
1397                 ret = -EIO;
1398                 goto out_buf;
1399         }
1400         else
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);
1404  out_buf:
1405         freedqbuf(buf);
1406         return ret;
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)
1410  {
1411 -       struct file *filp = sb_dqopt(dquot->dq_sb)->files[dquot->dq_type];
1412         dqbuf_t buf = getdqbuf();
1413         loff_t ret = 0;
1414         u32 *ref = (u32 *)buf;
1415  
1416         if (!buf)
1417                 return -ENOMEM;
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);
1421                 goto out_buf;
1422         }
1423 @@ -619,16 +601,13 @@
1424  static int v2_read_dquot(struct dquot *dquot)
1425  {
1426         int type = dquot->dq_type;
1427 -       struct file *filp;
1428 -       mm_segment_t fs;
1429         loff_t offset;
1430         struct v2_disk_dqblk ddquot, empty;
1431         int ret = 0;
1432  
1433 -       filp = sb_dqopt(dquot->dq_sb)->files[type];
1434 -
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");
1440                 return -EIO;
1441         }
1442 @@ -636,7 +615,8 @@
1443         offset = find_dqentry(dquot);
1444         if (offset <= 0) {      /* Entry not present? */
1445                 if (offset < 0)
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);
1449                 dquot->dq_off = 0;
1450                 dquot->dq_flags |= DQ_FAKE;
1451                 memset(&dquot->dq_dqb, 0, sizeof(struct mem_dqblk));
1452 @@ -644,12 +624,13 @@
1453         }
1454         else {
1455                 dquot->dq_off = offset;
1456 -               fs = get_fs();
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)) {
1462                         if (ret >= 0)
1463                                 ret = -EIO;
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));
1468                 }
1469                 else {
1470 @@ -660,7 +641,6 @@
1471                         if (!memcmp(&empty, &ddquot, sizeof(struct v2_disk_dqblk)))
1472                                 ddquot.dqb_itime = 0;
1473                 }
1474 -               set_fs(fs);
1475                 disk2memdqb(&dquot->dq_dqb, &ddquot);
1476         }
1477         dqstats.reads++;
1478 @@ -668,15 +648,13 @@
1479         return ret;
1480  }
1481  
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)
1487  {
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);
1493 -       else
1494 -               return v2_write_dquot(dquot);
1495 +       return 0;
1496  }
1497  
1498  static struct quota_format_ops v2_format_ops = {
1499 @@ -685,7 +663,8 @@
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,
1506  };
1507  
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
1513 @@ -14,6 +14,9 @@
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>
1519 +
1520  
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 @@
1524         return NULL;
1525  }
1526  
1527 +void quota_sync_sb(struct super_block *sb, int type)
1528 +{
1529 +       int cnt;
1530 +       struct inode *discard[MAXQUOTAS];
1531 +
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);
1539 +
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)
1549 +                       continue;
1550 +               if (!sb_has_quota_enabled(sb, cnt))
1551 +                       continue;
1552 +               discard[cnt] = igrab(sb_dqopt(sb)->files[cnt]);
1553 +       }
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]);
1561 +               }
1562 +       }
1563 +}
1564 +
1565  void sync_dquots(struct super_block *sb, int type)
1566  {
1567         if (sb) {
1568                 if (sb->s_qcop->quota_sync)
1569 -                       sb->s_qcop->quota_sync(sb, type);
1570 +                       quota_sync_sb(sb, type);
1571         }
1572         else {
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);
1578                         drop_super(sb);
1579                 }
1580         }
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 @@
1586         return ret;
1587  }
1588  
1589 -static int
1590 +int
1591  ext3_journal_dirty_data(handle_t *handle, struct buffer_head *bh)
1592  {
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
1598 @@ -33,6 +33,7 @@
1599  #include <linux/vfs.h>
1600  #include <linux/random.h>
1601  #include <asm/uaccess.h>
1602 +#include <linux/quotaops.h>
1603  #include "xattr.h"
1604  #include "acl.h"
1605  
1606 @@ -505,7 +506,33 @@
1607         ext3_discard_reservation(inode);
1608  }
1609  
1610 -static struct dquot_operations ext3_qops;
1611 +#ifdef CONFIG_QUOTA
1612 +
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);
1623 +
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
1636 +};
1637 +#endif
1638  
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,
1648 +#endif
1649  };
1650  
1651  struct dentry *ext3_get_parent(struct dentry *child);
1652 @@ -1335,7 +1366,9 @@
1653          */
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;
1659 +#endif
1660         INIT_LIST_HEAD(&sbi->s_orphan); /* unlinked but open files */
1661  
1662         sb->s_root = 0;
1663 @@ -1998,70 +2031,200 @@
1664  
1665  #ifdef CONFIG_QUOTA
1666  
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
1671 -
1672 -static int (*old_write_dquot)(struct dquot *dquot);
1673 -static void (*old_drop_dquot)(struct inode *inode);
1674 -
1675 -static int fmt_to_blocks(int fmt)
1676 -{
1677 -       switch (fmt) {
1678 -               case QFMT_VFS_OLD:
1679 -                       return  EXT3_OLD_QFMT_BLOCKS;
1680 -               case QFMT_VFS_V0:
1681 -                       return EXT3_V0_QFMT_BLOCKS;
1682 -       }
1683 -       return EXT3_MAX_TRANS_DATA;
1684 +static inline struct inode *dquot_to_inode(struct dquot *dquot)
1685 +{
1686 +       return sb_dqopt(dquot->dq_sb)->files[dquot->dq_type];
1687 +}
1688 +
1689 +static int ext3_dquot_initialize(struct inode *inode, int type)
1690 +{
1691 +       handle_t *handle;
1692 +       int ret, err;
1693 +
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);
1700 +       if (!ret)
1701 +               ret = err;
1702 +       return ret;
1703 +}
1704 +
1705 +static int ext3_dquot_drop(struct inode *inode)
1706 +{
1707 +       handle_t *handle;
1708 +       int ret, err;
1709 +
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);
1716 +       if (!ret)
1717 +               ret = err;
1718 +       return ret;
1719  }
1720  
1721  static int ext3_write_dquot(struct dquot *dquot)
1722  {
1723 -       int nblocks;
1724 -       int ret;
1725 -       int err;
1726 +       int ret, err;
1727         handle_t *handle;
1728 -       struct quota_info *dqopt = sb_dqopt(dquot->dq_sb);
1729 -       struct inode *qinode;
1730 +       struct inode *inode;
1731  
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);
1737 -               goto out;
1738 -       }
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);
1747 -       if (ret == 0)
1748 +       if (!ret)
1749                 ret = err;
1750 -out:
1751         return ret;
1752  }
1753  
1754 -static void ext3_drop_dquot(struct inode *inode)
1755 +static int ext3_acquire_dquot(struct dquot *dquot)
1756  {
1757 -       int nblocks, type;
1758 -       struct quota_info *dqopt = sb_dqopt(inode->i_sb);
1759 +       int ret, err;
1760         handle_t *handle;
1761  
1762 -       for (type = 0; type < MAXQUOTAS; type++) {
1763 -               if (sb_has_quota_enabled(inode->i_sb, type))
1764 -                       break;
1765 -       }
1766 -       if (type < MAXQUOTAS)
1767 -               nblocks = fmt_to_blocks(dqopt->info[type].dqi_format->qf_fmt_id);
1768 -       else
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);
1773         if (IS_ERR(handle))
1774 -               return;
1775 -       old_drop_dquot(inode);
1776 -       ext3_journal_stop(handle);
1777 -       return;
1778 +               return PTR_ERR(handle);
1779 +       ret = dquot_acquire(dquot);
1780 +       err = ext3_journal_stop(handle);
1781 +       if (!ret)
1782 +               ret = err;
1783 +       return ret;
1784  }
1785 +
1786 +static int ext3_release_dquot(struct dquot *dquot)
1787 +{
1788 +       int ret, err;
1789 +       handle_t *handle;
1790 +
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);
1797 +       if (!ret)
1798 +               ret = err;
1799 +       return ret;
1800 +}
1801 +
1802 +static int ext3_write_info(struct super_block *sb, int type)
1803 +{
1804 +       int ret, err;
1805 +       handle_t *handle;
1806 +
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);
1813 +       if (!ret)
1814 +               ret = err;
1815 +       return ret;
1816 +}
1817 +
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)
1824 +{
1825 +       struct inode *inode = sb_dqopt(sb)->files[type];
1826 +       sector_t blk = off >> EXT3_BLOCK_SIZE_BITS(sb);
1827 +       int err = 0;
1828 +       int offset = off & (sb->s_blocksize - 1);
1829 +       int tocopy;
1830 +       size_t toread;
1831 +       struct buffer_head *bh;
1832 +       loff_t i_size = i_size_read(inode);
1833 +
1834 +       if (off > i_size)
1835 +               return 0;
1836 +       if (off+len > i_size)
1837 +               len = i_size-off;
1838 +       toread = len;
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);
1843 +               if (err)
1844 +                       return err;
1845 +               if (!bh)        /* A hole? */
1846 +                       memset(data, 0, tocopy);
1847 +               else
1848 +                       memcpy(data, bh->b_data+offset, tocopy);
1849 +               brelse(bh);
1850 +               offset = 0;
1851 +               toread -= tocopy;
1852 +               data += tocopy;
1853 +               blk++;
1854 +       }
1855 +       return len;
1856 +}
1857 +
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)
1862 +{
1863 +       struct inode *inode = sb_dqopt(sb)->files[type];
1864 +       sector_t blk = off >> EXT3_BLOCK_SIZE_BITS(sb);
1865 +       int err = 0;
1866 +       int offset = off & (sb->s_blocksize - 1);
1867 +       int tocopy;
1868 +       size_t towrite = len;
1869 +       struct buffer_head *bh;
1870 +       handle_t *handle = journal_current_handle();
1871 +
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);
1877 +               if (!bh)
1878 +                       goto out;
1879 +               
1880 +               lock_buffer(bh);
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);
1887 +               brelse(bh);
1888 +               if (err)
1889 +                       goto out;
1890 +               offset = 0;
1891 +               towrite -= tocopy;
1892 +               data += tocopy;
1893 +               blk++;
1894 +       }
1895 +out:
1896 +       if (len == towrite)
1897 +               return err;
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;
1901 +       }
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;
1907 +}
1908 +
1909  #endif
1910  
1911  static struct super_block *ext3_get_sb(struct file_system_type *fs_type,
1912 @@ -2086,13 +2249,7 @@
1913         err = init_inodecache();
1914         if (err)
1915                 goto out1;
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;
1922 -#endif
1923 +
1924          err = register_filesystem_lifo(&ext3_fs_type);
1925         if (err)
1926                 goto out;
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
1931 @@ -7,7 +7,6 @@
1932  #include <linux/init.h>
1933  #include <linux/module.h>
1934  
1935 -#include <asm/uaccess.h>
1936  #include <asm/byteorder.h>
1937  
1938  MODULE_AUTHOR("Jan Kara");
1939 @@ -41,23 +40,14 @@
1940  static int v1_read_dqblk(struct dquot *dquot)
1941  {
1942         int type = dquot->dq_type;
1943 -       struct file *filp;
1944 -       mm_segment_t fs;
1945 -       loff_t offset;
1946         struct v1_disk_dqblk dqblk;
1947  
1948 -       filp = sb_dqopt(dquot->dq_sb)->files[type];
1949 -       if (filp == (struct file *)NULL)
1950 +       if (!sb_dqopt(dquot->dq_sb)->files[type])
1951                 return -EINVAL;
1952  
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));
1957 -       fs = get_fs();
1958 -       set_fs(KERNEL_DS);
1959 -       filp->f_op->read(filp, (char *)&dqblk, sizeof(struct v1_disk_dqblk), &offset);
1960 -       set_fs(fs);
1961 +       dquot->dq_sb->s_op->quota_read(dquot->dq_sb, type, (char *)&dqblk, sizeof(struct v1_disk_dqblk), v1_dqoff(dquot->dq_id));
1962  
1963         v1_disk2mem_dqblk(&dquot->dq_dqb, &dqblk);
1964         if (dquot->dq_dqb.dqb_bhardlimit == 0 && dquot->dq_dqb.dqb_bsoftlimit == 0 &&
1965 @@ -71,17 +61,9 @@
1966  static int v1_commit_dqblk(struct dquot *dquot)
1967  {
1968         short type = dquot->dq_type;
1969 -       struct file *filp;
1970 -       mm_segment_t fs;
1971 -       loff_t offset;
1972         ssize_t ret;
1973         struct v1_disk_dqblk dqblk;
1974  
1975 -       filp = sb_dqopt(dquot->dq_sb)->files[type];
1976 -       offset = v1_dqoff(dquot->dq_id);
1977 -       fs = get_fs();
1978 -       set_fs(KERNEL_DS);
1979 -
1980         /*
1981          * Note: clear the DQ_MOD flag unconditionally,
1982          * so we don't loop forever on failure.
1983 @@ -93,9 +75,10 @@
1984                 dqblk.dqb_itime = sb_dqopt(dquot->dq_sb)->info[type].dqi_igrace;
1985         }
1986         ret = 0;
1987 -       if (filp)
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));
1993 +
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);
1997 @@ -106,7 +89,6 @@
1998         ret = 0;
1999  
2000  out:
2001 -       set_fs(fs);
2002         dqstats.writes++;
2003  
2004         return ret;
2005 @@ -126,14 +108,11 @@
2006  
2007  static int v1_check_quota_file(struct super_block *sb, int type)
2008  {
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];
2012         ulong blocks;
2013         size_t off; 
2014         struct v2_disk_dqheader dqhead;
2015 -       mm_segment_t fs;
2016         ssize_t size;
2017 -       loff_t offset = 0;
2018         loff_t isize;
2019         static const uint quota_magics[] = V2_INITQMAGICS;
2020  
2021 @@ -145,10 +124,7 @@
2022         if ((blocks % sizeof(struct v1_disk_dqblk) * BLOCK_SIZE + off) % sizeof(struct v1_disk_dqblk))
2023                 return 0;
2024         /* Doublecheck whether we didn't get file with new format - with old quotactl() this could happen */
2025 -       fs = get_fs();
2026 -       set_fs(KERNEL_DS);
2027 -       size = f->f_op->read(f, (char *)&dqhead, sizeof(struct v2_disk_dqheader), &offset);
2028 -       set_fs(fs);
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)
2035  {
2036         struct quota_info *dqopt = sb_dqopt(sb);
2037 -       mm_segment_t fs;
2038 -       loff_t offset;
2039 -       struct file *filp = dqopt->files[type];
2040         struct v1_disk_dqblk dqblk;
2041         int ret;
2042  
2043 -       offset = v1_dqoff(0);
2044 -       fs = get_fs();
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)) {
2048                 if (ret >= 0)
2049                         ret = -EIO;
2050                 goto out;
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;
2054  out:
2055 -       set_fs(fs);
2056         return ret;
2057  }
2058  
2059  static int v1_write_file_info(struct super_block *sb, int type)
2060  {
2061         struct quota_info *dqopt = sb_dqopt(sb);
2062 -       mm_segment_t fs;
2063 -       struct file *filp = dqopt->files[type];
2064         struct v1_disk_dqblk dqblk;
2065 -       loff_t offset;
2066         int ret;
2067  
2068         dqopt->info[type].dqi_flags &= ~DQF_INFO_DIRTY;
2069 -       offset = v1_dqoff(0);
2070 -       fs = get_fs();
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)) {
2075                 if (ret >= 0)
2076                         ret = -EIO;
2077                 goto out;
2078         }
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))
2086                 ret = 0;
2087         else if (ret > 0)
2088                 ret = -EIO;
2089  out:
2090 -       set_fs(fs);
2091         return ret;
2092  }
2093  
2094
2095 %diffstat
2096  fs/dquot.c               |  370 +++++++++++++++++++++++++++++++++++------------
2097  fs/ext3/inode.c          |    2 
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(-)
2110