Whamcloud - gitweb
Branch HEAD
[fs/lustre-release.git] / lustre / kernel_patches / patches / 2.6.5-quotafix.patch
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
6  
7  #define EXT3_INDEX_EXTRA_TRANS_BLOCKS  8
8  
9 +#ifdef CONFIG_QUOTA
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)
17 +#else
18 +#define EXT3_QUOTA_TRANS_BLOCKS 0
19 +#define EXT3_QUOTA_INIT_BLOCKS 0
20 +#endif
21 +
22  int
23  ext3_mark_iloc_dirty(handle_t *handle, 
24                      struct inode *inode,
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);
28  
29 +int ext3_journal_dirty_data(handle_t *handle, struct buffer_head *bh);
30 +
31  static inline int
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 *);
40  
41         int (*show_options)(struct seq_file *, struct vfsmount *);
42 +
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);
45  };
46  
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>
55  
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
59 +
60  /*
61   * Data for one user/group kept in memory
62   */
63 @@ -168,22 +172,21 @@ struct mem_dqinfo {
64         } u;
65  };
66  
67 +struct super_block;
68 +
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? */
74  
75 -extern inline void mark_info_dirty(struct mem_dqinfo *info)
76 -{
77 -       set_bit(DQF_INFO_DIRTY_B, &info->dqi_flags);
78 -}
79 -
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))
84  
85  #define sb_dqopt(sb) (&(sb)->s_dquot)
86 +#define sb_dqinfo(sb, type) (sb_dqopt(sb)->info+(type))
87  
88  struct dqstats {
89         int lookups;
90 @@ -204,6 +207,9 @@ extern struct dqstats dqstats;
91  #define DQ_BLKS_B      1
92  #define DQ_INODES_B    2
93  #define DQ_FAKE_B      3
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) */
97  
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 */
105  };
106  
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" */
124  };
125  
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 */
136  };
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
141 @@ -22,17 +22,22 @@
142   */
143  extern void sync_dquots(struct super_block *sb, int type);
144  
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);
149  
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);
152  
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);
157  
158  extern int  dquot_transfer(struct inode *inode, struct iattr *iattr);
159  
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);
164 +
165  /*
166   * Operations supported for diskquotas.
167   */
168 @@ -143,7 +148,7 @@ static __inline__ int DQUOT_OFF(struct s
169  {
170         int ret = -ENOSYS;
171  
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);
175         return ret;
176  }
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);
189  
190 @@ -1292,9 +1292,9 @@ static inline int security_quotactl (int
191                          0);
192  }
193  
194 -static inline int security_quota_on (struct file * file)
195 +static inline int security_quota_on (struct dentry * dentry)
196  {
197 -       return COND_SECURITY(quota_on (file), 
198 +       return COND_SECURITY(quota_on (dentry), 
199                          0);
200  }
201  
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
207         return 0;
208  }
209  
210 -static int dummy_quota_on (struct file *f)
211 +static int dummy_quota_on (struct dentry *dentry)
212  {
213         return 0;
214  }
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
220         return rc;
221  }
222  
223 -static int selinux_quota_on(struct file *f)
224 +static int selinux_quota_on(struct dentry *dentry)
225  {
226 -       return file_has_perm(current, f, FILE__QUOTAON);
227 +       return dentry_has_perm(current, NULL, dentry, FILE__QUOTAON);
228  }
229  
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
235 @@ -52,6 +52,9 @@
236   *             New SMP locking.
237   *             Jan Kara, <jack@suse.cz>, 10/2002
238   *
239 + *             Fix lock inversion problems
240 + *             Jan Kara, <jack@suse.cz>, 2003,2004
241 + *
242   * (C) Copyright 1994 - 1997 Marco van Wieringen 
243   */
244  
245 @@ -75,7 +78,8 @@
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>
252  
253  #include <asm/uaccess.h>
254  
255 @@ -109,7 +113,7 @@
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.
258   *
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
262   */
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.
266   *
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
269 - * at every dquot.
270 + * list is used for invalidate operation, which must look at every dquot.
271   *
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 *
275         up(&dquot->dq_lock);
276  }
277  
278 -static int read_dqblk(struct dquot *dquot)
279 +void mark_info_dirty(struct super_block *sb, int type)
280  {
281 -       int ret;
282 +       set_bit(DQF_INFO_DIRTY_B, &sb_dqopt(sb)->info[type].dqi_flags);
283 +}
284 +EXPORT_SYMBOL(mark_info_dirty);
285 +
286 +/*
287 + *     Read dquot from disk and alloc space for it
288 + */
289 +
290 +int dquot_acquire(struct dquot *dquot)
291 +{
292 +       int ret = 0, ret2 = 0;
293         struct quota_info *dqopt = sb_dqopt(dquot->dq_sb);
294  
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);
300 +       if (ret < 0)
301 +               goto out_iolock;
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);
309 +               if (ret < 0)
310 +                       goto out_iolock;
311 +               if (ret2 < 0) {
312 +                       ret = ret2;
313 +                       goto out_iolock;
314 +               }
315 +       }
316 +       set_bit(DQ_ACTIVE_B, &dquot->dq_flags);
317 +out_iolock:
318         up(&dqopt->dqio_sem);
319         up(&dquot->dq_lock);
320         return ret;
321  }
322  
323 -static int commit_dqblk(struct dquot *dquot)
324 +/*
325 + *     Write dquot to disk
326 + */
327 +int dquot_commit(struct dquot *dquot)
328  {
329 -       int ret;
330 +       int ret = 0, ret2 = 0;
331         struct quota_info *dqopt = sb_dqopt(dquot->dq_sb);
332  
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);
338 +               goto out_sem;
339 +       }
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);
347 +               if (ret >= 0)
348 +                       ret = ret2;
349 +       }
350 +out_sem:
351         up(&dqopt->dqio_sem);
352         return ret;
353  }
354  
355 +/*
356 + *     Release dquot
357 + */
358 +int dquot_release(struct dquot *dquot)
359 +{
360 +       int ret = 0, ret2 = 0;
361 +       struct quota_info *dqopt = sb_dqopt(dquot->dq_sb);
362 +
363 +       down(&dquot->dq_lock);
364 +       /* Check whether we are not racing with some other dqget() */
365 +       if (atomic_read(&dquot->dq_count) > 1)
366 +               goto out_dqlock;
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);
373 +               if (ret >= 0)
374 +                       ret = ret2;
375 +       }
376 +       clear_bit(DQ_ACTIVE_B, &dquot->dq_flags);
377 +       up(&dqopt->dqio_sem);
378 +out_dqlock:
379 +       up(&dquot->dq_lock);
380 +       return ret;
381 +}
382 +
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:
387                         continue;
388                 if (!dquot_dirty(dquot))
389                         continue;
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);
393 +                       continue;
394 +               }                       
395                 atomic_inc(&dquot->dq_count);
396                 dqstats.lookups++;
397                 spin_unlock(&dq_list_lock);
398 @@ -353,11 +436,9 @@ restart:
399         spin_unlock(&dq_list_lock);
400  
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);
406 -               }
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);
411         dqstats.syncs++;
412         spin_unlock(&dq_list_lock);
413 @@ -432,11 +513,19 @@ we_slept:
414                 spin_unlock(&dq_list_lock);
415                 return;
416         }
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);
421                 goto we_slept;
422         }
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);
428 +               goto we_slept;
429 +       }
430 +                       
431         atomic_dec(&dquot->dq_count);
432  #ifdef __DQUOT_PARANOIA
433         /* sanity check */
434 @@ -495,7 +584,6 @@ we_slept:
435                 insert_dquot_hash(dquot);
436                 dqstats.lookups++;
437                 spin_unlock(&dq_list_lock);
438 -               read_dqblk(dquot);
439         } else {
440                 if (!atomic_read(&dquot->dq_count))
441                         remove_free_dquot(dquot);
442 @@ -503,10 +591,15 @@ we_slept:
443                 dqstats.cache_hits++;
444                 dqstats.lookups++;
445                 spin_unlock(&dq_list_lock);
446 -               wait_on_dquot(dquot);
447                 if (empty)
448                         kmem_cache_free(dquot_cachep, empty);
449         }
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) {
453 +               dqput(dquot);
454 +               return NODQUOT;
455 +       }
456  
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
460   *
461   * Note: this is a blocking operation.
462   */
463 -void dquot_initialize(struct inode *inode, int type)
464 +int dquot_initialize(struct inode *inode, int type)
465  {
466         unsigned int id = 0;
467         int cnt;
468  
469         /* Solve deadlock when we recurse when holding dqptr_sem... */
470         if (IS_NOQUOTA(inode))
471 -               return;
472 +               return 0;
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);
477 -               return;
478 +               return 0;
479         }
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
483                 }
484         }
485         up_write(&sb_dqopt(inode->i_sb)->dqptr_sem);
486 +       return 0;
487  }
488  
489  /*
490   *     Release all quotas referenced by inode
491   *     Needs dqonoff_sem to guard dqput()
492   */
493 -void dquot_drop(struct inode *inode)
494 +int dquot_drop(struct inode *inode)
495  {
496         int cnt;
497  
498 @@ -871,6 +965,7 @@ void dquot_drop(struct inode *inode)
499                 }
500         }
501         up_write(&sb_dqopt(inode->i_sb)->dqptr_sem);
502 +       return 0;
503  }
504  
505  /*
506 @@ -958,14 +1053,14 @@ warn_put_all:
507  /*
508   * This is a non-blocking operation.
509   */
510 -void dquot_free_space(struct inode *inode, qsize_t number)
511 +int dquot_free_space(struct inode *inode, qsize_t number)
512  {
513         unsigned int cnt;
514  
515         /* Solve deadlock when we recurse when holding dqptr_sem... */
516         if (IS_NOQUOTA(inode)) {
517                 inode_add_bytes(inode, number);
518 -               return;
519 +               return QUOTA_OK;
520         }
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);
527 +       return QUOTA_OK;
528  }
529  
530  /*
531   * This is a non-blocking operation.
532   */
533 -void dquot_free_inode(const struct inode *inode, unsigned long number)
534 +int dquot_free_inode(const struct inode *inode, unsigned long number)
535  {
536         unsigned int cnt;
537  
538         /* Solve deadlock when we recurse when holding dqptr_sem... */
539         if (IS_NOQUOTA(inode))
540 -               return;
541 +               return QUOTA_OK;
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);
546 -               return;
547 +               return QUOTA_OK;
548         }
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
552         }
553         spin_unlock(&dq_data_lock);
554         up_read(&sb_dqopt(inode->i_sb)->dqptr_sem);
555 +       return QUOTA_OK;
556  }
557  
558  /*
559 @@ -1104,6 +1201,20 @@ warn_put_all:
560  }
561  
562  /*
563 + * Write info of quota file to disk
564 + */
565 +int dquot_commit_info(struct super_block *sb, int type)
566 +{
567 +       int ret;
568 +       struct quota_info *dqopt = sb_dqopt(sb);
569 +
570 +       down(&dqopt->dqio_sem);
571 +       ret = dqopt->ops[type]->write_file_info(sb, type);
572 +       up(&dqopt->dqio_sem);
573 +       return ret;
574 +}
575 +
576 +/*
577   * Definitions of diskquota operations.
578   */
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                             
589  };
590  
591  /* Function used by filesystems for initializing the dquot_operations structure */
592 @@ -1154,13 +1268,14 @@ int vfs_quota_off(struct super_block *sb
593  {
594         int cnt;
595         struct quota_info *dqopt = sb_dqopt(sb);
596 -
597 -       if (!sb)
598 -               goto out;
599 +       struct inode *toputinode[MAXQUOTAS];
600 +       struct vfsmount *toputmnt[MAXQUOTAS];
601  
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)
608                         continue;
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);
612                 /*
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.
616                  */
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);
621 -               }
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);
627  
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;
638         }
639         up(&dqopt->dqonoff_sem);
640 -out:
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
658 +                        * nothing to do */
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]);
667 +                       }
668 +                       up(&dqopt->dqonoff_sem);
669 +                       /* We don't hold the reference when we turned on quotas
670 +                        * just for the journal replay... */
671 +                       if (toputmnt[cnt])
672 +                               mntput(toputmnt[cnt]);
673 +               }
674 +       invalidate_bdev(sb->s_bdev, 0);
675         return 0;
676  }
677  
678 -int vfs_quota_on(struct super_block *sb, int type, int format_id, char *path)
679 +/*
680 + *     Turn quotas on on a device
681 + */
682 +
683 +/* Helper function when we already have the inode */
684 +static int vfs_quota_on_inode(struct inode *inode, int type, int format_id)
685  {
686 -       struct file *f;
687 -       struct inode *inode;
688 -       struct quota_info *dqopt = sb_dqopt(sb);
689         struct quota_format_type *fmt = find_quota_format(format_id);
690 -       int error, cnt;
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);
695 +       int error;
696 +       int oldflags = -1;
697  
698         if (!fmt)
699                 return -ESRCH;
700 -       f = filp_open(path, O_RDWR, 0600);
701 -       if (IS_ERR(f)) {
702 -               error = PTR_ERR(f);
703 +       if (!S_ISREG(inode->i_mode)) {
704 +               error = -EACCES;
705 +               goto out_fmt;
706 +       }
707 +       if (IS_RDONLY(inode)) {
708 +               error = -EROFS;
709 +               goto out_fmt;
710 +       }
711 +       if (!sb->s_op->quota_write || !sb->s_op->quota_read) {
712 +               error = -EINVAL;
713                 goto out_fmt;
714         }
715 -       error = -EIO;
716 -       if (!f->f_op || !f->f_op->read || !f->f_op->write)
717 -               goto out_f;
718 -       error = security_quota_on(f);
719 -       if (error)
720 -               goto out_f;
721 -       inode = f->f_dentry->d_inode;
722 -       error = -EACCES;
723 -       if (!S_ISREG(inode->i_mode))
724 -               goto out_f;
725  
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)) {
734                 error = -EBUSY;
735                 goto out_lock;
736         }
737 -       oldflags = inode->i_flags;
738 -       dqopt->files[type] = f;
739 -       error = -EINVAL;
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;
749 -
750 -       /*
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.
755 -        */
756 -       mapping_set_gfp_mask(inode->i_mapping,
757 -               mapping_gfp_mask(inode->i_mapping) & ~__GFP_FS);
758 -
759 -       for (cnt = 0; cnt < MAXQUOTAS; cnt++) {
760 -               to_drop[cnt] = inode->i_dquot[cnt];
761 -               inode->i_dquot[cnt] = NODQUOT;
762 -       }
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++) {
770 -               if (to_drop[cnt])
771 -                       dqput(to_drop[cnt]);
772 -       }
773 +
774 +       error = -EIO;
775 +       dqopt->files[type] = igrab(inode);
776 +       if (!dqopt->files[type])
777 +               goto out_lock;
778 +       error = -EINVAL;
779 +       if (!fmt->qf_ops->check_quota_file(sb, type))
780 +               goto out_file_init;
781  
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,
785                 goto out_file_init;
786         }
787         up(&dqopt->dqio_sem);
788 +       up(&inode->i_sem);
789         set_enable_flags(dqopt, type);
790  
791         add_dquot_ref(sb, type);
792 @@ -1277,18 +1414,51 @@ int vfs_quota_on(struct super_block *sb,
793         return 0;
794  
795  out_file_init:
796 -       inode->i_flags = oldflags;
797         dqopt->files[type] = NULL;
798 +       iput(inode);
799  out_lock:
800         up(&dqopt->dqonoff_sem);
801 -out_f:
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);
810 +       }
811 +       up(&inode->i_sem);
812  out_fmt:
813         put_quota_format(fmt);
814  
815         return error; 
816  }
817  
818 +/* Actual function called from quotactl() */
819 +int vfs_quota_on(struct super_block *sb, int type, int format_id, char *path)
820 +{
821 +       struct nameidata nd;
822 +       int error;
823 +
824 +       error = path_lookup(path, LOOKUP_FOLLOW, &nd);
825 +       if (error < 0)
826 +               return error;
827 +       error = security_quota_on(nd.dentry);
828 +       if (error)
829 +               goto out_path;
830 +       /* Quota file not on the same filesystem? */
831 +       if (nd.mnt->mnt_sb != sb)
832 +               error = -EXDEV;
833 +       else {
834 +               error = vfs_quota_on_inode(nd.dentry->d_inode, type, format_id);
835 +               if (!error)
836 +                       sb_dqopt(sb)->mnt[type] = mntget(nd.mnt);
837 +       }
838 +
839 +out_path:
840 +       path_release(&nd);
841 +       return error;
842 +}
843 +
844  /* Generic routine for getting common part of quota structure */
845  static void do_get_dqblk(struct dquot *dquot, struct if_dqblk *di)
846  {
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);
857         return 0;
858  }
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);
874 +
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
879 @@ -13,7 +13,6 @@
880  #include <linux/slab.h>
881  
882  #include <asm/byteorder.h>
883 -#include <asm/uaccess.h>
884  
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)
889  {
890         struct v2_disk_dqheader dqhead;
891 -       struct file *f = sb_dqopt(sb)->files[type];
892 -       mm_segment_t fs;
893         ssize_t size;
894 -       loff_t offset = 0;
895         static const uint quota_magics[] = V2_INITQMAGICS;
896         static const uint quota_versions[] = V2_INITQVERSIONS;
897   
898 -       fs = get_fs();
899 -       set_fs(KERNEL_DS);
900 -       size = f->f_op->read(f, (char *)&dqhead, sizeof(struct v2_disk_dqheader), &offset);
901 -       set_fs(fs);
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");
906                 return 0;
907 +       }
908         if (le32_to_cpu(dqhead.dqh_magic) != quota_magics[type] ||
909             le32_to_cpu(dqhead.dqh_version) != quota_versions[type])
910                 return 0;
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)
914  {
915 -       mm_segment_t fs;
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];
919         ssize_t size;
920 -       loff_t offset = V2_DQINFOOFF;
921  
922 -       fs = get_fs();
923 -       set_fs(KERNEL_DS);
924 -       size = f->f_op->read(f, (char *)&dinfo, sizeof(struct v2_disk_dqinfo), &offset);
925 -       set_fs(fs);
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);
931 +                       sb->s_id);
932                 return -1;
933         }
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)
938  {
939 -       mm_segment_t fs;
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];
943         ssize_t size;
944 -       loff_t offset = V2_DQINFOOFF;
945  
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);
952 -       fs = get_fs();
953 -       set_fs(KERNEL_DS);
954 -       size = f->f_op->write(f, (char *)&dinfo, sizeof(struct v2_disk_dqinfo), &offset);
955 -       set_fs(fs);
956 +       
957 +       size = sb->s_op->quota_write(sb, type, (char *)&dinfo,
958 +                       sizeof(struct v2_disk_dqinfo), V2_DQINFOOFF);
959 +
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);
963 +                       sb->s_id);
964                 return -1;
965         }
966         return 0;
967 @@ -144,38 +131,24 @@ static inline void freedqbuf(dqbuf_t buf
968         kfree(buf);
969  }
970  
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)
973  {
974 -       mm_segment_t fs;
975 -       ssize_t ret;
976 -       loff_t offset = blk<<V2_DQBLKSIZE_BITS;
977 -
978         memset(buf, 0, V2_DQBLKSIZE);
979 -       fs = get_fs();
980 -       set_fs(KERNEL_DS);
981 -       ret = filp->f_op->read(filp, (char *)buf, V2_DQBLKSIZE, &offset);
982 -       set_fs(fs);
983 -       return ret;
984 +       return sb->s_op->quota_read(sb, type, (char *)buf,
985 +                       V2_DQBLKSIZE, blk << V2_DQBLKSIZE_BITS);
986  }
987  
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)
990  {
991 -       mm_segment_t fs;
992 -       ssize_t ret;
993 -       loff_t offset = blk<<V2_DQBLKSIZE_BITS;
994 -
995 -       fs = get_fs();
996 -       set_fs(KERNEL_DS);
997 -       ret = filp->f_op->write(filp, (char *)buf, V2_DQBLKSIZE, &offset);
998 -       set_fs(fs);
999 -       return ret;
1000 -
1001 +       return sb->s_op->quota_write(sb, type, (char *)buf,
1002 +                       V2_DQBLKSIZE, blk << V2_DQBLKSIZE_BITS);
1003  }
1004  
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)
1008  {
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;
1012         int ret, blk;
1013  
1014 @@ -183,17 +156,18 @@ static int get_free_dqblk(struct file *f
1015                 return -ENOMEM;
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)
1020                         goto out_buf;
1021                 info->u.v2_i.dqi_free_blk = le32_to_cpu(dh->dqdh_next_free);
1022         }
1023         else {
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)
1028                         goto out_buf;
1029                 blk = info->u.v2_i.dqi_blocks++;
1030         }
1031 -       mark_info_dirty(info);
1032 +       mark_info_dirty(sb, type);
1033         ret = blk;
1034  out_buf:
1035         freedqbuf(buf);
1036 @@ -201,8 +175,9 @@ out_buf:
1037  }
1038  
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)
1042  {
1043 +       struct mem_dqinfo *info = sb_dqinfo(sb, type);
1044         struct v2_disk_dqdbheader *dh = (struct v2_disk_dqdbheader *)buf;
1045         int err;
1046  
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)
1056                 return err;
1057         return 0;
1058  }
1059  
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)
1063  {
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);
1068         int err;
1069 @@ -227,26 +204,27 @@ static int remove_free_dqentry(struct fi
1070         if (!tmpbuf)
1071                 return -ENOMEM;
1072         if (nextblk) {
1073 -               if ((err = read_blk(filp, nextblk, tmpbuf)) < 0)
1074 +               if ((err = read_blk(sb, type, nextblk, tmpbuf)) < 0)
1075                         goto out_buf;
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)
1079                         goto out_buf;
1080         }
1081         if (prevblk) {
1082 -               if ((err = read_blk(filp, prevblk, tmpbuf)) < 0)
1083 +               if ((err = read_blk(sb, type, prevblk, tmpbuf)) < 0)
1084                         goto out_buf;
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)
1088                         goto out_buf;
1089         }
1090         else {
1091                 info->u.v2_i.dqi_free_entry = nextblk;
1092 -               mark_info_dirty(info);
1093 +               mark_info_dirty(sb, type);
1094         }
1095         freedqbuf(tmpbuf);
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);
1101         return 0;
1102  out_buf:
1103 @@ -255,9 +233,10 @@ out_buf:
1104  }
1105  
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)
1109  {
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;
1113         int err;
1114  
1115 @@ -265,18 +244,18 @@ static int insert_free_dqentry(struct fi
1116                 return -ENOMEM;
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)
1121                 goto out_buf;
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)
1125                         goto out_buf;
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)
1129                         goto out_buf;
1130         }
1131         freedqbuf(tmpbuf);
1132         info->u.v2_i.dqi_free_entry = blk;
1133 -       mark_info_dirty(info);
1134 +       mark_info_dirty(sb, type);
1135         return 0;
1136  out_buf:
1137         freedqbuf(tmpbuf);
1138 @@ -286,8 +265,8 @@ out_buf:
1139  /* Find space for dquot */
1140  static uint find_free_dqentry(struct dquot *dquot, int *err)
1141  {
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;
1146         uint blk, i;
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)
1155                         goto out_buf;
1156         }
1157         else {
1158 -               blk = get_free_dqblk(filp, info);
1159 +               blk = get_free_dqblk(sb, dquot->dq_type);
1160                 if ((int)blk < 0) {
1161                         *err = blk;
1162                         freedqbuf(buf);
1163                         return 0;
1164                 }
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);
1171         }
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);
1176                         goto out_buf;
1177                 }
1178 @@ -333,7 +313,7 @@ static uint find_free_dqentry(struct dqu
1179                 goto out_buf;
1180         }
1181  #endif
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);
1185                 goto out_buf;
1186         }
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)
1190  {
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;
1194         dqbuf_t buf;
1195         int ret = 0, newson = 0, newact = 0;
1196         u32 *ref;
1197 @@ -358,7 +337,7 @@ static int do_insert_tree(struct dquot *
1198         if (!(buf = getdqbuf()))
1199                 return -ENOMEM;
1200         if (!*treeblk) {
1201 -               ret = get_free_dqblk(filp, info);
1202 +               ret = get_free_dqblk(sb, dquot->dq_type);
1203                 if (ret < 0)
1204                         goto out_buf;
1205                 *treeblk = ret;
1206 @@ -366,7 +345,7 @@ static int do_insert_tree(struct dquot *
1207                 newact = 1;
1208         }
1209         else {
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);
1213                         goto out_buf;
1214                 }
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);
1221         }
1222         else if (newact && ret < 0)
1223 -               put_free_dqblk(filp, info, buf, *treeblk);
1224 +               put_free_dqblk(sb, dquot->dq_type, buf, *treeblk);
1225  out_buf:
1226         freedqbuf(buf);
1227         return ret;
1228 @@ -411,19 +390,14 @@ static inline int dq_insert_tree(struct 
1229  static int v2_write_dquot(struct dquot *dquot)
1230  {
1231         int type = dquot->dq_type;
1232 -       struct file *filp;
1233 -       mm_segment_t fs;
1234 -       loff_t offset;
1235         ssize_t ret;
1236         struct v2_disk_dqblk ddquot, empty;
1237  
1238         if (!dquot->dq_off)
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);
1242                         return ret;
1243                 }
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);
1253 -       fs = get_fs();
1254 -       set_fs(KERNEL_DS);
1255 -       ret = filp->f_op->write(filp, (char *)&ddquot, sizeof(struct v2_disk_dqblk), &offset);
1256 -       set_fs(fs);
1257 +       
1258 +       ret = dquot->dq_sb->s_op->quota_write(dquot->dq_sb, type,
1259 +                       (char *)&ddquot, sizeof(struct v2_disk_dqblk), dquot->dq_off);
1260 +
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);
1263                 if (ret >= 0)
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)
1267  {
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();
1274         int ret = 0;
1275 @@ -459,34 +433,39 @@ static int free_dqentry(struct dquot *dq
1276         if (!buf)
1277                 return -ENOMEM;
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));
1283                 goto out_buf;
1284         }
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);
1288                 goto out_buf;
1289         }
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);
1300                         goto out_buf;
1301                 }
1302         }
1303         else {
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);
1312                                 goto out_buf;
1313                         }
1314                 }
1315                 else
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);
1321                                 goto out_buf;
1322                         }
1323         }
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)
1327  {
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();
1333         int ret = 0;
1334         uint newblk;
1335 @@ -508,7 +487,7 @@ static int remove_tree(struct dquot *dqu
1336         
1337         if (!buf)
1338                 return -ENOMEM;
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);
1342                 goto out_buf;
1343         }
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);
1350                         *blk = 0;
1351                 }
1352                 else
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);
1358         }
1359  out_buf:
1360         freedqbuf(buf);
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)
1364  {
1365 -       struct file *filp = sb_dqopt(dquot->dq_sb)->files[dquot->dq_type];
1366         dqbuf_t buf = getdqbuf();
1367         loff_t ret = 0;
1368         int i;
1369 @@ -557,27 +536,31 @@ static loff_t find_block_dqentry(struct 
1370  
1371         if (!buf)
1372                 return -ENOMEM;
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);
1376                 goto out_buf;
1377         }
1378         if (dquot->dq_id)
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;
1384  
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)))
1390                                 break;
1391         }
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);
1396                 ret = -EIO;
1397                 goto out_buf;
1398         }
1399         else
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);
1403  out_buf:
1404         freedqbuf(buf);
1405         return ret;
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)
1409  {
1410 -       struct file *filp = sb_dqopt(dquot->dq_sb)->files[dquot->dq_type];
1411         dqbuf_t buf = getdqbuf();
1412         loff_t ret = 0;
1413         u32 *ref = (u32 *)buf;
1414  
1415         if (!buf)
1416                 return -ENOMEM;
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);
1420                 goto out_buf;
1421         }
1422 @@ -619,16 +601,13 @@ static inline loff_t find_dqentry(struct
1423  static int v2_read_dquot(struct dquot *dquot)
1424  {
1425         int type = dquot->dq_type;
1426 -       struct file *filp;
1427 -       mm_segment_t fs;
1428         loff_t offset;
1429         struct v2_disk_dqblk ddquot, empty;
1430         int ret = 0;
1431  
1432 -       filp = sb_dqopt(dquot->dq_sb)->files[type];
1433 -
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");
1439                 return -EIO;
1440         }
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? */
1444                 if (offset < 0)
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);
1448                 dquot->dq_off = 0;
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
1452         }
1453         else {
1454                 dquot->dq_off = offset;
1455 -               fs = get_fs();
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)) {
1461                         if (ret >= 0)
1462                                 ret = -EIO;
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));
1467                 }
1468                 else {
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;
1472                 }
1473 -               set_fs(fs);
1474                 disk2memdqb(&dquot->dq_dqb, &ddquot);
1475         }
1476         dqstats.reads++;
1477 @@ -668,15 +648,13 @@ static int v2_read_dquot(struct dquot *d
1478         return ret;
1479  }
1480  
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)
1486  {
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);
1492 -       else
1493 -               return v2_write_dquot(dquot);
1494 +       return 0;
1495  }
1496  
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,
1505  };
1506  
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
1512 @@ -14,6 +14,9 @@
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>
1518 +
1519  
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:
1523         return NULL;
1524  }
1525  
1526 +void quota_sync_sb(struct super_block *sb, int type)
1527 +{
1528 +       int cnt;
1529 +       struct inode *discard[MAXQUOTAS];
1530 +
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);
1538 +
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)
1548 +                       continue;
1549 +               if (!sb_has_quota_enabled(sb, cnt))
1550 +                       continue;
1551 +               discard[cnt] = igrab(sb_dqopt(sb)->files[cnt]);
1552 +       }
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]);
1560 +               }
1561 +       }
1562 +}
1563 +
1564  void sync_dquots(struct super_block *sb, int type)
1565  {
1566         if (sb) {
1567                 if (sb->s_qcop->quota_sync)
1568 -                       sb->s_qcop->quota_sync(sb, type);
1569 +                       quota_sync_sb(sb, type);
1570         }
1571         else {
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);
1577                         drop_super(sb);
1578                 }
1579         }
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:
1585         return ret;
1586  }
1587  
1588 -static int
1589 +int
1590  ext3_journal_dirty_data(handle_t *handle, struct buffer_head *bh)
1591  {
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
1597 @@ -33,6 +33,7 @@
1598  #include <linux/vfs.h>
1599  #include <linux/random.h>
1600  #include <asm/uaccess.h>
1601 +#include <linux/quotaops.h>
1602  #include "xattr.h"
1603  #include "acl.h"
1604  
1605 @@ -505,7 +506,33 @@ static void ext3_clear_inode(struct inod
1606         ext3_discard_reservation(inode);
1607  }
1608  
1609 -static struct dquot_operations ext3_qops;
1610 +#ifdef CONFIG_QUOTA
1611 +
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);
1622 +
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
1635 +};
1636 +#endif
1637  
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,
1647 +#endif
1648  };
1649  
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
1652          */
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;
1658 +#endif
1659         INIT_LIST_HEAD(&sbi->s_orphan); /* unlinked but open files */
1660  
1661         sb->s_root = 0;
1662 @@ -2040,70 +2073,200 @@ int ext3_statfs (struct super_block * sb
1663  
1664  #ifdef CONFIG_QUOTA
1665  
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
1670 -
1671 -static int (*old_write_dquot)(struct dquot *dquot);
1672 -static void (*old_drop_dquot)(struct inode *inode);
1673 -
1674 -static int fmt_to_blocks(int fmt)
1675 -{
1676 -       switch (fmt) {
1677 -               case QFMT_VFS_OLD:
1678 -                       return  EXT3_OLD_QFMT_BLOCKS;
1679 -               case QFMT_VFS_V0:
1680 -                       return EXT3_V0_QFMT_BLOCKS;
1681 -       }
1682 -       return EXT3_MAX_TRANS_DATA;
1683 +static inline struct inode *dquot_to_inode(struct dquot *dquot)
1684 +{
1685 +       return sb_dqopt(dquot->dq_sb)->files[dquot->dq_type];
1686 +}
1687 +
1688 +static int ext3_dquot_initialize(struct inode *inode, int type)
1689 +{
1690 +       handle_t *handle;
1691 +       int ret, err;
1692 +
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);
1699 +       if (!ret)
1700 +               ret = err;
1701 +       return ret;
1702 +}
1703 +
1704 +static int ext3_dquot_drop(struct inode *inode)
1705 +{
1706 +       handle_t *handle;
1707 +       int ret, err;
1708 +
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);
1715 +       if (!ret)
1716 +               ret = err;
1717 +       return ret;
1718  }
1719  
1720  static int ext3_write_dquot(struct dquot *dquot)
1721  {
1722 -       int nblocks;
1723 -       int ret;
1724 -       int err;
1725 +       int ret, err;
1726         handle_t *handle;
1727 -       struct quota_info *dqopt = sb_dqopt(dquot->dq_sb);
1728 -       struct inode *qinode;
1729 +       struct inode *inode;
1730  
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);
1736 -               goto out;
1737 -       }
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);
1746 -       if (ret == 0)
1747 +       if (!ret)
1748                 ret = err;
1749 -out:
1750         return ret;
1751  }
1752  
1753 -static void ext3_drop_dquot(struct inode *inode)
1754 +static int ext3_acquire_dquot(struct dquot *dquot)
1755  {
1756 -       int nblocks, type;
1757 -       struct quota_info *dqopt = sb_dqopt(inode->i_sb);
1758 +       int ret, err;
1759         handle_t *handle;
1760  
1761 -       for (type = 0; type < MAXQUOTAS; type++) {
1762 -               if (sb_has_quota_enabled(inode->i_sb, type))
1763 -                       break;
1764 -       }
1765 -       if (type < MAXQUOTAS)
1766 -               nblocks = fmt_to_blocks(dqopt->info[type].dqi_format->qf_fmt_id);
1767 -       else
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);
1772         if (IS_ERR(handle))
1773 -               return;
1774 -       old_drop_dquot(inode);
1775 -       ext3_journal_stop(handle);
1776 -       return;
1777 +               return PTR_ERR(handle);
1778 +       ret = dquot_acquire(dquot);
1779 +       err = ext3_journal_stop(handle);
1780 +       if (!ret)
1781 +               ret = err;
1782 +       return ret;
1783  }
1784 +
1785 +static int ext3_release_dquot(struct dquot *dquot)
1786 +{
1787 +       int ret, err;
1788 +       handle_t *handle;
1789 +
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);
1796 +       if (!ret)
1797 +               ret = err;
1798 +       return ret;
1799 +}
1800 +
1801 +static int ext3_write_info(struct super_block *sb, int type)
1802 +{
1803 +       int ret, err;
1804 +       handle_t *handle;
1805 +
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);
1812 +       if (!ret)
1813 +               ret = err;
1814 +       return ret;
1815 +}
1816 +
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)
1823 +{
1824 +       struct inode *inode = sb_dqopt(sb)->files[type];
1825 +       sector_t blk = off >> EXT3_BLOCK_SIZE_BITS(sb);
1826 +       int err = 0;
1827 +       int offset = off & (sb->s_blocksize - 1);
1828 +       int tocopy;
1829 +       size_t toread;
1830 +       struct buffer_head *bh;
1831 +       loff_t i_size = i_size_read(inode);
1832 +
1833 +       if (off > i_size)
1834 +               return 0;
1835 +       if (off+len > i_size)
1836 +               len = i_size-off;
1837 +       toread = len;
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);
1842 +               if (err)
1843 +                       return err;
1844 +               if (!bh)        /* A hole? */
1845 +                       memset(data, 0, tocopy);
1846 +               else
1847 +                       memcpy(data, bh->b_data+offset, tocopy);
1848 +               brelse(bh);
1849 +               offset = 0;
1850 +               toread -= tocopy;
1851 +               data += tocopy;
1852 +               blk++;
1853 +       }
1854 +       return len;
1855 +}
1856 +
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)
1861 +{
1862 +       struct inode *inode = sb_dqopt(sb)->files[type];
1863 +       sector_t blk = off >> EXT3_BLOCK_SIZE_BITS(sb);
1864 +       int err = 0;
1865 +       int offset = off & (sb->s_blocksize - 1);
1866 +       int tocopy;
1867 +       size_t towrite = len;
1868 +       struct buffer_head *bh;
1869 +       handle_t *handle = journal_current_handle();
1870 +
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);
1876 +               if (!bh)
1877 +                       goto out;
1878 +               
1879 +               lock_buffer(bh);
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);
1886 +               brelse(bh);
1887 +               if (err)
1888 +                       goto out;
1889 +               offset = 0;
1890 +               towrite -= tocopy;
1891 +               data += tocopy;
1892 +               blk++;
1893 +       }
1894 +out:
1895 +       if (len == towrite)
1896 +               return err;
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;
1900 +       }
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;
1906 +}
1907 +
1908  #endif
1909  
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();
1913         if (err)
1914                 goto out1;
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;
1921 -#endif
1922 +
1923          err = register_filesystem_lifo(&ext3_fs_type);
1924         if (err)
1925                 goto out;
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
1930 @@ -7,7 +7,6 @@
1931  #include <linux/init.h>
1932  #include <linux/module.h>
1933  
1934 -#include <asm/uaccess.h>
1935  #include <asm/byteorder.h>
1936  
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)
1940  {
1941         int type = dquot->dq_type;
1942 -       struct file *filp;
1943 -       mm_segment_t fs;
1944 -       loff_t offset;
1945         struct v1_disk_dqblk dqblk;
1946  
1947 -       filp = sb_dqopt(dquot->dq_sb)->files[type];
1948 -       if (filp == (struct file *)NULL)
1949 +       if (!sb_dqopt(dquot->dq_sb)->files[type])
1950                 return -EINVAL;
1951  
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));
1956 -       fs = get_fs();
1957 -       set_fs(KERNEL_DS);
1958 -       filp->f_op->read(filp, (char *)&dqblk, sizeof(struct v1_disk_dqblk), &offset);
1959 -       set_fs(fs);
1960 +       dquot->dq_sb->s_op->quota_read(dquot->dq_sb, type, (char *)&dqblk, sizeof(struct v1_disk_dqblk), v1_dqoff(dquot->dq_id));
1961  
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)
1966  {
1967         short type = dquot->dq_type;
1968 -       struct file *filp;
1969 -       mm_segment_t fs;
1970 -       loff_t offset;
1971         ssize_t ret;
1972         struct v1_disk_dqblk dqblk;
1973  
1974 -       filp = sb_dqopt(dquot->dq_sb)->files[type];
1975 -       offset = v1_dqoff(dquot->dq_id);
1976 -       fs = get_fs();
1977 -       set_fs(KERNEL_DS);
1978 -
1979         /*
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;
1984         }
1985         ret = 0;
1986 -       if (filp)
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));
1992 +
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 
1997         ret = 0;
1998  
1999  out:
2000 -       set_fs(fs);
2001         dqstats.writes++;
2002  
2003         return ret;
2004 @@ -126,14 +108,11 @@ struct v2_disk_dqheader {
2005  
2006  static int v1_check_quota_file(struct super_block *sb, int type)
2007  {
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];
2011         ulong blocks;
2012         size_t off; 
2013         struct v2_disk_dqheader dqhead;
2014 -       mm_segment_t fs;
2015         ssize_t size;
2016 -       loff_t offset = 0;
2017         loff_t isize;
2018         static const uint quota_magics[] = V2_INITQMAGICS;
2019  
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))
2022                 return 0;
2023         /* Doublecheck whether we didn't get file with new format - with old quotactl() this could happen */
2024 -       fs = get_fs();
2025 -       set_fs(KERNEL_DS);
2026 -       size = f->f_op->read(f, (char *)&dqhead, sizeof(struct v2_disk_dqheader), &offset);
2027 -       set_fs(fs);
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)
2034  {
2035         struct quota_info *dqopt = sb_dqopt(sb);
2036 -       mm_segment_t fs;
2037 -       loff_t offset;
2038 -       struct file *filp = dqopt->files[type];
2039         struct v1_disk_dqblk dqblk;
2040         int ret;
2041  
2042 -       offset = v1_dqoff(0);
2043 -       fs = get_fs();
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)) {
2047                 if (ret >= 0)
2048                         ret = -EIO;
2049                 goto out;
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;
2053  out:
2054 -       set_fs(fs);
2055         return ret;
2056  }
2057  
2058  static int v1_write_file_info(struct super_block *sb, int type)
2059  {
2060         struct quota_info *dqopt = sb_dqopt(sb);
2061 -       mm_segment_t fs;
2062 -       struct file *filp = dqopt->files[type];
2063         struct v1_disk_dqblk dqblk;
2064 -       loff_t offset;
2065         int ret;
2066  
2067         dqopt->info[type].dqi_flags &= ~DQF_INFO_DIRTY;
2068 -       offset = v1_dqoff(0);
2069 -       fs = get_fs();
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)) {
2074                 if (ret >= 0)
2075                         ret = -EIO;
2076                 goto out;
2077         }
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))
2085                 ret = 0;
2086         else if (ret > 0)
2087                 ret = -EIO;
2088  out:
2089 -       set_fs(fs);
2090         return ret;
2091  }
2092  
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)
2099  
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);
2103  
2104  static int fmt_to_blocks(int fmt)
2105  {
2106 @@ -1697,10 +1697,8 @@ static int reiserfs_write_dquot(struct d
2107         int err;
2108         struct reiserfs_transaction_handle handle;
2109         struct quota_info *dqopt = sb_dqopt(dquot->dq_sb);
2110 -       struct inode *qinode;
2111  
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);
2116         if (ret)
2117 @@ -1713,11 +1711,12 @@ static int reiserfs_write_dquot(struct d
2118         return ret;
2119  }
2120  
2121 -static void reiserfs_drop_dquot(struct inode *inode)
2122 +static int reiserfs_drop_dquot(struct inode *inode)
2123  {
2124         int nblocks, type;
2125         struct quota_info *dqopt = sb_dqopt(inode->i_sb);
2126         struct reiserfs_transaction_handle handle;
2127 +       int err, ret;
2128  
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
2132         else
2133                 nblocks = 0;    /* No quota => no drop */ 
2134         reiserfs_write_lock(inode->i_sb);
2135 -       if (journal_begin(&handle, inode->i_sb, 2*nblocks))
2136 -               return;
2137 -       old_drop_dquot(inode);
2138 -       journal_end(&handle, inode->i_sb, 2*nblocks);
2139 +       err = journal_begin(&handle, inode->i_sb, 2*nblocks);
2140 +       if (err);
2141 +               return err;
2142 +       ret = old_drop_dquot(inode);
2143 +       err = journal_end(&handle, inode->i_sb, 2*nblocks);
2144 +       if (!ret)
2145 +               ret = err;
2146         reiserfs_write_unlock(inode->i_sb);
2147 -       return;
2148 +       return ret;
2149  }
2150  #endif
2151