1 From: Jan Kara <jack@suse.cz>
3 The four patches in this series fix deadlocks with quotas of pagelock (the
4 problem was lock inversion on PageLock and transaction start - quota code
5 needed to first start a transaction and then write the data which subsequently
6 needed acquisition of PageLock while the standard ordering - PageLock first
7 and transaction start later - was used e.g. by pdflush). They implement a
8 new way of quota access to disk: Every filesystem that would like to implement
9 quotas now has to provide quota_read() and quota_write() functions. These
10 functions must obey quota lock ordering (in particular they should not take
11 PageLock inside a transaction).
13 The first patch implements the changes in the quota core, the other three
14 patches implement needed functions in ext2, ext3 and reiserfs. The patch for
15 reiserfs also fixes several other lock inversion problems (similar as ext3
16 had) and implements the journaled quota functionality (which comes almost for
17 free after the locking fixes...).
19 The quota core patch makes quota support in other filesystems (except XFS
20 which implements everything on its own ;)) unfunctional (quotaon() will refuse
21 to turn on quotas on them). When the patches get reasonable wide testing and
22 it will seem that no major changes will be needed I can make fixes also for
23 the other filesystems (JFS, UDF, UFS).
27 The patch implements the new way of quota io in the quota core. Every
28 filesystem wanting to support quotas has to provide functions quota_read()
29 and quota_write() obeying quota locking rules. As the writes and reads
30 bypass the pagecache there is some ugly stuff ensuring that userspace can
31 see all the data after quotaoff() (or Q_SYNC quotactl). In future I plan
32 to make quota files inaccessible from userspace (with the exception of
33 quotacheck(8) which will take care about the cache flushing and such stuff
34 itself) so that this synchronization stuff can be removed...
36 The rewrite of the quota core. Quota uses the filesystem read() and write()
37 functions no more to avoid possible deadlocks on PageLock. From now on every
38 filesystem supporting quotas must provide functions quota_read() and
39 quota_write() which obey the quota locking rules (e.g. they cannot acquire the
42 Signed-off-by: Jan Kara <jack@suse.cz>
43 Signed-off-by: Andrew Morton <akpm@osdl.org>
46 25-akpm/fs/dquot.c | 162 +++++++++++++--------------
47 25-akpm/fs/quota.c | 45 +++++++
48 25-akpm/fs/quota_v1.c | 62 ++--------
49 25-akpm/fs/quota_v2.c | 227 +++++++++++++++++----------------------
50 25-akpm/include/linux/fs.h | 3
51 25-akpm/include/linux/quota.h | 2
52 25-akpm/include/linux/security.h | 8 -
53 25-akpm/security/dummy.c | 2
54 25-akpm/security/selinux/hooks.c | 4
55 9 files changed, 247 insertions(+), 268 deletions(-)
57 diff -rup RH_2_6_9_55.orig/fs/dquot.c RH_2_6_9_55/fs/dquot.c
58 --- RH_2_6_9_55.orig/fs/dquot.c
59 +++ RH_2_6_9_55/fs/dquot.c
62 * Jan Kara, <jack@suse.cz>, 10/2002
64 - * Added journalled quota support
65 + * Added journalled quota support, fix lock inversion problems
66 * Jan Kara, <jack@suse.cz>, 2003,2004
68 * (C) Copyright 1994 - 1997 Marco van Wieringen
70 #include <linux/proc_fs.h>
71 #include <linux/security.h>
72 #include <linux/kmod.h>
73 -#include <linux/pagemap.h>
74 +#include <linux/namei.h>
75 +#include <linux/buffer_head.h>
77 #include <asm/uaccess.h>
80 * operations on dquots don't hold dq_lock as they copy data under dq_data_lock
81 * spinlock to internal buffers before writing.
83 - * Lock ordering (including related VFS locks) is following:
84 + * Lock ordering (including related VFS locks) is the following:
85 * i_sem > dqonoff_sem > journal_lock > dqptr_sem > dquot->dq_lock >
87 * i_sem on quota files is special (it's below dqio_sem)
88 @@ -183,8 +184,7 @@ static void put_quota_format(struct quot
89 * on all three lists, depending on its current state.
91 * All dquots are placed to the end of inuse_list when first created, and this
92 - * list is used for the sync and invalidate operations, which must look
94 + * list is used for invalidate operation, which must look at every dquot.
96 * Unused dquots (dq_count == 0) are added to the free_dquots list when freed,
97 * and this list is searched whenever we need an available dquot. Dquots are
98 @@ -1341,10 +1341,12 @@ int vfs_quota_off(struct super_block *sb
101 struct quota_info *dqopt = sb_dqopt(sb);
102 + struct inode *toput[MAXQUOTAS];
104 /* We need to serialize quota_off() for device */
105 down(&dqopt->dqonoff_sem);
106 for (cnt = 0; cnt < MAXQUOTAS; cnt++) {
108 if (type != -1 && cnt != type)
110 if (!sb_has_quota_enabled(sb, cnt))
111 @@ -1364,7 +1366,7 @@ int vfs_quota_off(struct super_block *sb
112 dqopt->ops[cnt]->free_file_info(sb, cnt);
113 put_quota_format(dqopt->info[cnt].dqi_format);
115 - fput(dqopt->files[cnt]);
116 + toput[cnt] = dqopt->files[cnt];
117 dqopt->files[cnt] = NULL;
118 dqopt->info[cnt].dqi_flags = 0;
119 dqopt->info[cnt].dqi_igrace = 0;
120 @@ -1372,6 +1374,26 @@ int vfs_quota_off(struct super_block *sb
121 dqopt->ops[cnt] = NULL;
123 up(&dqopt->dqonoff_sem);
124 + /* Sync the superblock so that buffers with quota data are written to
125 + * disk (and so userspace sees correct data afterwards) */
126 + if (sb->s_op->sync_fs)
127 + sb->s_op->sync_fs(sb, 1);
128 + sync_blockdev(sb->s_bdev);
129 + /* Now the quota files are just ordinary files and we can set the
130 + * inode flags back. Moreover we discard the pagecache so that
131 + * userspace sees the writes we did bypassing the pagecache. We
132 + * must also discard the blockdev buffers so that we see the
133 + * changes done by userspace on the next quotaon() */
134 + for (cnt = 0; cnt < MAXQUOTAS; cnt++)
136 + down(&toput[cnt]->i_sem);
137 + toput[cnt]->i_flags &= ~(S_IMMUTABLE | S_NOATIME | S_NOQUOTA);
138 + truncate_inode_pages(&toput[cnt]->i_data, 0);
139 + up(&toput[cnt]->i_sem);
140 + mark_inode_dirty(toput[cnt]);
143 + invalidate_bdev(sb->s_bdev, 0);
147 @@ -1379,68 +1401,56 @@ int vfs_quota_off(struct super_block *sb
148 * Turn quotas on on a device
151 -/* Helper function when we already have file open */
152 -static int vfs_quota_on_file(struct file *f, int type, int format_id)
153 +/* Helper function when we already have the inode */
154 +static int vfs_quota_on_inode(struct inode *inode, int type, int format_id)
156 struct quota_format_type *fmt = find_quota_format(format_id);
157 - struct inode *inode;
158 - struct super_block *sb = f->f_dentry->d_sb;
159 + struct super_block *sb = inode->i_sb;
160 struct quota_info *dqopt = sb_dqopt(sb);
161 - struct dquot *to_drop[MAXQUOTAS];
163 - unsigned int oldflags = -1;
170 - if (!f->f_op || !f->f_op->read || !f->f_op->write)
171 + if (!S_ISREG(inode->i_mode)) {
174 - inode = f->f_dentry->d_inode;
176 - if (!S_ISREG(inode->i_mode))
178 + if (IS_RDONLY(inode)) {
182 + if (!sb->s_op->quota_write || !sb->s_op->quota_read) {
187 + /* As we bypass the pagecache we must now flush the inode so that
188 + * we see all the changes from userspace... */
189 + write_inode_now(inode, 1);
190 + /* And now flush the block cache so that kernel sees the changes */
191 + invalidate_bdev(sb->s_bdev, 0);
193 down(&dqopt->dqonoff_sem);
194 if (sb_has_quota_enabled(sb, type)) {
199 /* We don't want quota and atime on quota files (deadlocks possible)
200 - * We also need to set GFP mask differently because we cannot recurse
201 - * into filesystem when allocating page for quota inode */
202 + * Also nobody should write to the file - we use special IO operations
203 + * which ignore the immutable bit. */
204 down_write(&dqopt->dqptr_sem);
205 - oldflags = inode->i_flags & (S_NOATIME | S_NOQUOTA);
206 - inode->i_flags |= S_NOQUOTA | S_NOATIME;
207 + oldflags = inode->i_flags & (S_NOATIME | S_IMMUTABLE | S_NOQUOTA);
208 + inode->i_flags |= S_NOQUOTA | S_NOATIME | S_IMMUTABLE;
209 up_write(&dqopt->dqptr_sem);
212 - dqopt->files[type] = f;
214 + dqopt->files[type] = igrab(inode);
215 + if (!dqopt->files[type])
218 if (!fmt->qf_ops->check_quota_file(sb, type))
221 - * We write to quota files deep within filesystem code. We don't want
222 - * the VFS to reenter filesystem code when it tries to allocate a
223 - * pagecache page for the quota file write. So clear __GFP_FS in
224 - * the quota file's allocation flags.
226 - mapping_set_gfp_mask(inode->i_mapping,
227 - mapping_gfp_mask(inode->i_mapping) & ~__GFP_FS);
229 - down_write(&dqopt->dqptr_sem);
230 - for (cnt = 0; cnt < MAXQUOTAS; cnt++) {
231 - to_drop[cnt] = inode->i_dquot[cnt];
232 - inode->i_dquot[cnt] = NODQUOT;
234 - up_write(&dqopt->dqptr_sem);
235 - /* We must put dquots outside of dqptr_sem because we may need to
236 - * start transaction for dquot_release() */
237 - for (cnt = 0; cnt < MAXQUOTAS; cnt++) {
239 - dqput(to_drop[cnt]);
242 dqopt->ops[type] = fmt->qf_ops;
243 dqopt->info[type].dqi_format = fmt;
244 @@ -1451,6 +1461,7 @@ static int vfs_quota_on_file(struct file
247 up(&dqopt->dqio_sem);
249 set_enable_flags(dqopt, type);
251 add_dquot_ref(sb, type);
252 @@ -1460,19 +1471,18 @@ static int vfs_quota_on_file(struct file
255 dqopt->files[type] = NULL;
258 up(&dqopt->dqonoff_sem);
259 if (oldflags != -1) {
260 - down(&inode->i_sem);
261 down_write(&dqopt->dqptr_sem);
262 - /* Reset the NOATIME flag back. I know it could change in the
263 - * mean time but playing with NOATIME flags on a quota file is
264 - * never a good idea */
265 - inode->i_flags &= ~(S_NOATIME | S_NOQUOTA);
266 + /* Set the flags back (in the case of accidental quotaon()
267 + * on a wrong file we don't want to mess up the flags) */
268 + inode->i_flags &= ~(S_NOATIME | S_NOQUOTA | S_IMMUTABLE);
269 inode->i_flags |= oldflags;
270 up_write(&dqopt->dqptr_sem);
275 put_quota_format(fmt);
277 @@ -1482,47 +1492,37 @@ out_fmt:
278 /* Actual function called from quotactl() */
279 int vfs_quota_on(struct super_block *sb, int type, int format_id, char *path)
282 + struct nameidata nd;
285 - f = filp_open(path, O_RDWR, 0600);
288 - error = security_quota_on(f);
289 + error = path_lookup(path, LOOKUP_FOLLOW, &nd);
292 + error = security_quota_on(nd.dentry);
295 - error = vfs_quota_on_file(f, type, format_id);
299 - filp_close(f, NULL);
301 + /* Quota file not on the same filesystem? */
302 + if (nd.mnt->mnt_sb != sb)
305 + error = vfs_quota_on_inode(nd.dentry->d_inode, type, format_id);
312 - * Function used by filesystems when filp_open() would fail (filesystem is
313 - * being mounted now). We will use a private file structure. Caller is
314 - * responsible that it's IO functions won't need vfsmnt structure or
315 - * some dentry tricks...
316 + * This function is used when filesystem needs to initialize quotas
317 + * during mount time.
319 int vfs_quota_on_mount(int type, int format_id, struct dentry *dentry)
324 - dget(dentry); /* Get a reference for struct file */
325 - f = dentry_open(dentry, NULL, O_RDWR);
327 - error = PTR_ERR(f);
330 - error = vfs_quota_on_file(f, type, format_id);
337 + error = security_quota_on(dentry);
340 + return vfs_quota_on_inode(dentry->d_inode, type, format_id);
343 /* Generic routine for getting common part of quota structure */
344 diff -rup RH_2_6_9_55.orig/fs/quota.c RH_2_6_9_55/fs/quota.c
345 --- RH_2_6_9_55.orig/fs/quota.c
346 +++ RH_2_6_9_55/fs/quota.c
348 #include <linux/kernel.h>
349 #include <linux/smp_lock.h>
350 #include <linux/security.h>
351 +#include <linux/syscalls.h>
352 +#include <linux/buffer_head.h>
354 /* Check validity of quotactl */
355 static int check_quotactl_valid(struct super_block *sb, int type, int cmd, qid_t id)
356 @@ -134,16 +136,54 @@ restart:
360 +void quota_sync_sb(struct super_block *sb, int type)
363 + struct inode *discard[MAXQUOTAS];
365 + sb->s_qcop->quota_sync(sb, type);
366 + /* This is not very clever (and fast) but currently I don't know about
367 + * any other simple way of getting quota data to disk and we must get
368 + * them there for userspace to be visible... */
369 + if (sb->s_op->sync_fs)
370 + sb->s_op->sync_fs(sb, 1);
371 + sync_blockdev(sb->s_bdev);
373 + /* Now when everything is written we can discard the pagecache so
374 + * that userspace sees the changes. We need i_sem and so we could
375 + * not do it inside dqonoff_sem. Moreover we need to be carefull
376 + * about races with quotaoff() (that is the reason why we have own
377 + * reference to inode). */
378 + down(&sb_dqopt(sb)->dqonoff_sem);
379 + for (cnt = 0; cnt < MAXQUOTAS; cnt++) {
380 + discard[cnt] = NULL;
381 + if (type != -1 && cnt != type)
383 + if (!sb_has_quota_enabled(sb, cnt))
385 + discard[cnt] = igrab(sb_dqopt(sb)->files[cnt]);
387 + up(&sb_dqopt(sb)->dqonoff_sem);
388 + for (cnt = 0; cnt < MAXQUOTAS; cnt++) {
389 + if (discard[cnt]) {
390 + down(&discard[cnt]->i_sem);
391 + truncate_inode_pages(&discard[cnt]->i_data, 0);
392 + up(&discard[cnt]->i_sem);
393 + iput(discard[cnt]);
398 void sync_dquots(struct super_block *sb, int type)
401 if (sb->s_qcop->quota_sync)
402 - sb->s_qcop->quota_sync(sb, type);
403 + quota_sync_sb(sb, type);
406 - while ((sb = get_super_to_sync(type)) != 0) {
407 + while ((sb = get_super_to_sync(type)) != NULL) {
408 if (sb->s_qcop->quota_sync)
409 - sb->s_qcop->quota_sync(sb, type);
410 + quota_sync_sb(sb, type);
414 diff -rup RH_2_6_9_55.orig/fs/quota_v1.c RH_2_6_9_55/fs/quota_v1.c
415 --- RH_2_6_9_55.orig/fs/quota_v1.c
416 +++ RH_2_6_9_55/fs/quota_v1.c
418 #include <linux/init.h>
419 #include <linux/module.h>
421 -#include <asm/uaccess.h>
422 #include <asm/byteorder.h>
424 MODULE_AUTHOR("Jan Kara");
425 @@ -41,23 +40,14 @@ static void v1_mem2disk_dqblk(struct v1_
426 static int v1_read_dqblk(struct dquot *dquot)
428 int type = dquot->dq_type;
432 struct v1_disk_dqblk dqblk;
434 - filp = sb_dqopt(dquot->dq_sb)->files[type];
435 - if (filp == (struct file *)NULL)
436 + if (!sb_dqopt(dquot->dq_sb)->files[type])
439 - /* Now we are sure filp is valid */
440 - offset = v1_dqoff(dquot->dq_id);
441 /* Set structure to 0s in case read fails/is after end of file */
442 memset(&dqblk, 0, sizeof(struct v1_disk_dqblk));
445 - filp->f_op->read(filp, (char *)&dqblk, sizeof(struct v1_disk_dqblk), &offset);
447 + dquot->dq_sb->s_op->quota_read(dquot->dq_sb, type, (char *)&dqblk, sizeof(struct v1_disk_dqblk), v1_dqoff(dquot->dq_id));
449 v1_disk2mem_dqblk(&dquot->dq_dqb, &dqblk);
450 if (dquot->dq_dqb.dqb_bhardlimit == 0 && dquot->dq_dqb.dqb_bsoftlimit == 0 &&
451 @@ -71,26 +61,18 @@ static int v1_read_dqblk(struct dquot *d
452 static int v1_commit_dqblk(struct dquot *dquot)
454 short type = dquot->dq_type;
459 struct v1_disk_dqblk dqblk;
461 - filp = sb_dqopt(dquot->dq_sb)->files[type];
462 - offset = v1_dqoff(dquot->dq_id);
466 v1_mem2disk_dqblk(&dqblk, &dquot->dq_dqb);
467 if (dquot->dq_id == 0) {
468 dqblk.dqb_btime = sb_dqopt(dquot->dq_sb)->info[type].dqi_bgrace;
469 dqblk.dqb_itime = sb_dqopt(dquot->dq_sb)->info[type].dqi_igrace;
473 - ret = filp->f_op->write(filp, (char *)&dqblk,
474 - sizeof(struct v1_disk_dqblk), &offset);
475 + if (sb_dqopt(dquot->dq_sb)->files[type])
476 + ret = dquot->dq_sb->s_op->quota_write(dquot->dq_sb, type, (char *)&dqblk,
477 + sizeof(struct v1_disk_dqblk), v1_dqoff(dquot->dq_id));
478 if (ret != sizeof(struct v1_disk_dqblk)) {
479 printk(KERN_WARNING "VFS: dquota write failed on dev %s\n",
481 @@ -101,7 +83,6 @@ static int v1_commit_dqblk(struct dquot
489 @@ -121,14 +102,11 @@ struct v2_disk_dqheader {
491 static int v1_check_quota_file(struct super_block *sb, int type)
493 - struct file *f = sb_dqopt(sb)->files[type];
494 - struct inode *inode = f->f_dentry->d_inode;
495 + struct inode *inode = sb_dqopt(sb)->files[type];
498 struct v2_disk_dqheader dqhead;
503 static const uint quota_magics[] = V2_INITQMAGICS;
505 @@ -140,10 +118,7 @@ static int v1_check_quota_file(struct su
506 if ((blocks % sizeof(struct v1_disk_dqblk) * BLOCK_SIZE + off) % sizeof(struct v1_disk_dqblk))
508 /* Doublecheck whether we didn't get file with new format - with old quotactl() this could happen */
511 - size = f->f_op->read(f, (char *)&dqhead, sizeof(struct v2_disk_dqheader), &offset);
513 + size = sb->s_op->quota_read(sb, type, (char *)&dqhead, sizeof(struct v2_disk_dqheader), 0);
514 if (size != sizeof(struct v2_disk_dqheader))
515 return 1; /* Probably not new format */
516 if (le32_to_cpu(dqhead.dqh_magic) != quota_magics[type])
517 @@ -155,16 +130,10 @@ static int v1_check_quota_file(struct su
518 static int v1_read_file_info(struct super_block *sb, int type)
520 struct quota_info *dqopt = sb_dqopt(sb);
523 - struct file *filp = dqopt->files[type];
524 struct v1_disk_dqblk dqblk;
527 - offset = v1_dqoff(0);
530 - if ((ret = filp->f_op->read(filp, (char *)&dqblk, sizeof(struct v1_disk_dqblk), &offset)) != sizeof(struct v1_disk_dqblk)) {
531 + if ((ret = sb->s_op->quota_read(sb, type, (char *)&dqblk, sizeof(struct v1_disk_dqblk), v1_dqoff(0))) != sizeof(struct v1_disk_dqblk)) {
535 @@ -173,38 +142,31 @@ static int v1_read_file_info(struct supe
536 dqopt->info[type].dqi_igrace = dqblk.dqb_itime ? dqblk.dqb_itime : MAX_IQ_TIME;
537 dqopt->info[type].dqi_bgrace = dqblk.dqb_btime ? dqblk.dqb_btime : MAX_DQ_TIME;
543 static int v1_write_file_info(struct super_block *sb, int type)
545 struct quota_info *dqopt = sb_dqopt(sb);
547 - struct file *filp = dqopt->files[type];
548 struct v1_disk_dqblk dqblk;
552 dqopt->info[type].dqi_flags &= ~DQF_INFO_DIRTY;
553 - offset = v1_dqoff(0);
556 - if ((ret = filp->f_op->read(filp, (char *)&dqblk, sizeof(struct v1_disk_dqblk), &offset)) != sizeof(struct v1_disk_dqblk)) {
557 + if ((ret = sb->s_op->quota_read(sb, type, (char *)&dqblk,
558 + sizeof(struct v1_disk_dqblk), v1_dqoff(0))) != sizeof(struct v1_disk_dqblk)) {
563 dqblk.dqb_itime = dqopt->info[type].dqi_igrace;
564 dqblk.dqb_btime = dqopt->info[type].dqi_bgrace;
565 - offset = v1_dqoff(0);
566 - ret = filp->f_op->write(filp, (char *)&dqblk, sizeof(struct v1_disk_dqblk), &offset);
567 + ret = sb->s_op->quota_write(sb, type, (char *)&dqblk,
568 + sizeof(struct v1_disk_dqblk), v1_dqoff(0));
569 if (ret == sizeof(struct v1_disk_dqblk))
578 diff -rup RH_2_6_9_55.orig/fs/quota_v2.c RH_2_6_9_55/fs/quota_v2.c
579 --- RH_2_6_9_55.orig/fs/quota_v2.c
580 +++ RH_2_6_9_55/fs/quota_v2.c
582 #include <linux/slab.h>
584 #include <asm/byteorder.h>
585 -#include <asm/uaccess.h>
587 MODULE_AUTHOR("Jan Kara");
588 MODULE_DESCRIPTION("Quota format v2 support");
589 @@ -30,19 +29,15 @@ typedef char *dqbuf_t;
590 static int v2_check_quota_file(struct super_block *sb, int type)
592 struct v2_disk_dqheader dqhead;
593 - struct file *f = sb_dqopt(sb)->files[type];
597 static const uint quota_magics[] = V2_INITQMAGICS;
598 static const uint quota_versions[] = V2_INITQVERSIONS;
602 - size = f->f_op->read(f, (char *)&dqhead, sizeof(struct v2_disk_dqheader), &offset);
604 - if (size != sizeof(struct v2_disk_dqheader))
605 + size = sb->s_op->quota_read(sb, type, (char *)&dqhead, sizeof(struct v2_disk_dqheader), 0);
606 + if (size != sizeof(struct v2_disk_dqheader)) {
607 + printk("failed read\n");
610 if (le32_to_cpu(dqhead.dqh_magic) != quota_magics[type] ||
611 le32_to_cpu(dqhead.dqh_version) != quota_versions[type])
613 @@ -52,20 +47,15 @@ static int v2_check_quota_file(struct su
614 /* Read information header from quota file */
615 static int v2_read_file_info(struct super_block *sb, int type)
618 struct v2_disk_dqinfo dinfo;
619 struct mem_dqinfo *info = sb_dqopt(sb)->info+type;
620 - struct file *f = sb_dqopt(sb)->files[type];
622 - loff_t offset = V2_DQINFOOFF;
626 - size = f->f_op->read(f, (char *)&dinfo, sizeof(struct v2_disk_dqinfo), &offset);
628 + size = sb->s_op->quota_read(sb, type, (char *)&dinfo,
629 + sizeof(struct v2_disk_dqinfo), V2_DQINFOOFF);
630 if (size != sizeof(struct v2_disk_dqinfo)) {
631 printk(KERN_WARNING "Can't read info structure on device %s.\n",
632 - f->f_dentry->d_sb->s_id);
636 info->dqi_bgrace = le32_to_cpu(dinfo.dqi_bgrace);
637 @@ -80,12 +70,9 @@ static int v2_read_file_info(struct supe
638 /* Write information header to quota file */
639 static int v2_write_file_info(struct super_block *sb, int type)
642 struct v2_disk_dqinfo dinfo;
643 struct mem_dqinfo *info = sb_dqopt(sb)->info+type;
644 - struct file *f = sb_dqopt(sb)->files[type];
646 - loff_t offset = V2_DQINFOOFF;
648 spin_lock(&dq_data_lock);
649 info->dqi_flags &= ~DQF_INFO_DIRTY;
650 @@ -96,13 +83,11 @@ static int v2_write_file_info(struct sup
651 dinfo.dqi_blocks = cpu_to_le32(info->u.v2_i.dqi_blocks);
652 dinfo.dqi_free_blk = cpu_to_le32(info->u.v2_i.dqi_free_blk);
653 dinfo.dqi_free_entry = cpu_to_le32(info->u.v2_i.dqi_free_entry);
656 - size = f->f_op->write(f, (char *)&dinfo, sizeof(struct v2_disk_dqinfo), &offset);
658 + size = sb->s_op->quota_write(sb, type, (char *)&dinfo,
659 + sizeof(struct v2_disk_dqinfo), V2_DQINFOOFF);
660 if (size != sizeof(struct v2_disk_dqinfo)) {
661 printk(KERN_WARNING "Can't write info structure on device %s.\n",
662 - f->f_dentry->d_sb->s_id);
667 @@ -146,39 +131,24 @@ static inline void freedqbuf(dqbuf_t buf
671 -static ssize_t read_blk(struct file *filp, uint blk, dqbuf_t buf)
672 +static inline ssize_t read_blk(struct super_block *sb, int type, uint blk, dqbuf_t buf)
676 - loff_t offset = blk<<V2_DQBLKSIZE_BITS;
678 memset(buf, 0, V2_DQBLKSIZE);
681 - ret = filp->f_op->read(filp, (char *)buf, V2_DQBLKSIZE, &offset);
684 + return sb->s_op->quota_read(sb, type, (char *)buf,
685 + V2_DQBLKSIZE, blk << V2_DQBLKSIZE_BITS);
688 -static ssize_t write_blk(struct file *filp, uint blk, dqbuf_t buf)
689 +static inline ssize_t write_blk(struct super_block *sb, int type, uint blk, dqbuf_t buf)
693 - loff_t offset = blk<<V2_DQBLKSIZE_BITS;
697 - ret = filp->f_op->write(filp, (char *)buf, V2_DQBLKSIZE, &offset);
701 + return sb->s_op->quota_write(sb, type, (char *)buf,
702 + V2_DQBLKSIZE, blk << V2_DQBLKSIZE_BITS);
705 /* Remove empty block from list and return it */
706 -static int get_free_dqblk(struct file *filp, int type)
707 +static int get_free_dqblk(struct super_block *sb, int type)
709 dqbuf_t buf = getdqbuf();
710 - struct mem_dqinfo *info = sb_dqinfo(filp->f_dentry->d_sb, type);
711 + struct mem_dqinfo *info = sb_dqinfo(sb, type);
712 struct v2_disk_dqdbheader *dh = (struct v2_disk_dqdbheader *)buf;
715 @@ -186,17 +156,18 @@ static int get_free_dqblk(struct file *f
717 if (info->u.v2_i.dqi_free_blk) {
718 blk = info->u.v2_i.dqi_free_blk;
719 - if ((ret = read_blk(filp, blk, buf)) < 0)
720 + if ((ret = read_blk(sb, type, blk, buf)) < 0)
722 info->u.v2_i.dqi_free_blk = le32_to_cpu(dh->dqdh_next_free);
725 memset(buf, 0, V2_DQBLKSIZE);
726 - if ((ret = write_blk(filp, info->u.v2_i.dqi_blocks, buf)) < 0) /* Assure block allocation... */
727 + /* Assure block allocation... */
728 + if ((ret = write_blk(sb, type, info->u.v2_i.dqi_blocks, buf)) < 0)
730 blk = info->u.v2_i.dqi_blocks++;
732 - mark_info_dirty(filp->f_dentry->d_sb, type);
733 + mark_info_dirty(sb, type);
737 @@ -204,9 +175,9 @@ out_buf:
740 /* Insert empty block to the list */
741 -static int put_free_dqblk(struct file *filp, int type, dqbuf_t buf, uint blk)
742 +static int put_free_dqblk(struct super_block *sb, int type, dqbuf_t buf, uint blk)
744 - struct mem_dqinfo *info = sb_dqinfo(filp->f_dentry->d_sb, type);
745 + struct mem_dqinfo *info = sb_dqinfo(sb, type);
746 struct v2_disk_dqdbheader *dh = (struct v2_disk_dqdbheader *)buf;
749 @@ -214,17 +185,18 @@ static int put_free_dqblk(struct file *f
750 dh->dqdh_prev_free = cpu_to_le32(0);
751 dh->dqdh_entries = cpu_to_le16(0);
752 info->u.v2_i.dqi_free_blk = blk;
753 - mark_info_dirty(filp->f_dentry->d_sb, type);
754 - if ((err = write_blk(filp, blk, buf)) < 0) /* Some strange block. We had better leave it... */
755 + mark_info_dirty(sb, type);
756 + /* Some strange block. We had better leave it... */
757 + if ((err = write_blk(sb, type, blk, buf)) < 0)
762 /* Remove given block from the list of blocks with free entries */
763 -static int remove_free_dqentry(struct file *filp, int type, dqbuf_t buf, uint blk)
764 +static int remove_free_dqentry(struct super_block *sb, int type, dqbuf_t buf, uint blk)
766 dqbuf_t tmpbuf = getdqbuf();
767 - struct mem_dqinfo *info = sb_dqinfo(filp->f_dentry->d_sb, type);
768 + struct mem_dqinfo *info = sb_dqinfo(sb, type);
769 struct v2_disk_dqdbheader *dh = (struct v2_disk_dqdbheader *)buf;
770 uint nextblk = le32_to_cpu(dh->dqdh_next_free), prevblk = le32_to_cpu(dh->dqdh_prev_free);
772 @@ -232,26 +204,27 @@ static int remove_free_dqentry(struct fi
776 - if ((err = read_blk(filp, nextblk, tmpbuf)) < 0)
777 + if ((err = read_blk(sb, type, nextblk, tmpbuf)) < 0)
779 ((struct v2_disk_dqdbheader *)tmpbuf)->dqdh_prev_free = dh->dqdh_prev_free;
780 - if ((err = write_blk(filp, nextblk, tmpbuf)) < 0)
781 + if ((err = write_blk(sb, type, nextblk, tmpbuf)) < 0)
785 - if ((err = read_blk(filp, prevblk, tmpbuf)) < 0)
786 + if ((err = read_blk(sb, type, prevblk, tmpbuf)) < 0)
788 ((struct v2_disk_dqdbheader *)tmpbuf)->dqdh_next_free = dh->dqdh_next_free;
789 - if ((err = write_blk(filp, prevblk, tmpbuf)) < 0)
790 + if ((err = write_blk(sb, type, prevblk, tmpbuf)) < 0)
794 info->u.v2_i.dqi_free_entry = nextblk;
795 - mark_info_dirty(filp->f_dentry->d_sb, type);
796 + mark_info_dirty(sb, type);
799 dh->dqdh_next_free = dh->dqdh_prev_free = cpu_to_le32(0);
800 - if (write_blk(filp, blk, buf) < 0) /* No matter whether write succeeds block is out of list */
801 + /* No matter whether write succeeds block is out of list */
802 + if (write_blk(sb, type, blk, buf) < 0)
803 printk(KERN_ERR "VFS: Can't write block (%u) with free entries.\n", blk);
806 @@ -260,10 +233,10 @@ out_buf:
809 /* Insert given block to the beginning of list with free entries */
810 -static int insert_free_dqentry(struct file *filp, int type, dqbuf_t buf, uint blk)
811 +static int insert_free_dqentry(struct super_block *sb, int type, dqbuf_t buf, uint blk)
813 dqbuf_t tmpbuf = getdqbuf();
814 - struct mem_dqinfo *info = sb_dqinfo(filp->f_dentry->d_sb, type);
815 + struct mem_dqinfo *info = sb_dqinfo(sb, type);
816 struct v2_disk_dqdbheader *dh = (struct v2_disk_dqdbheader *)buf;
819 @@ -271,18 +244,18 @@ static int insert_free_dqentry(struct fi
821 dh->dqdh_next_free = cpu_to_le32(info->u.v2_i.dqi_free_entry);
822 dh->dqdh_prev_free = cpu_to_le32(0);
823 - if ((err = write_blk(filp, blk, buf)) < 0)
824 + if ((err = write_blk(sb, type, blk, buf)) < 0)
826 if (info->u.v2_i.dqi_free_entry) {
827 - if ((err = read_blk(filp, info->u.v2_i.dqi_free_entry, tmpbuf)) < 0)
828 + if ((err = read_blk(sb, type, info->u.v2_i.dqi_free_entry, tmpbuf)) < 0)
830 ((struct v2_disk_dqdbheader *)tmpbuf)->dqdh_prev_free = cpu_to_le32(blk);
831 - if ((err = write_blk(filp, info->u.v2_i.dqi_free_entry, tmpbuf)) < 0)
832 + if ((err = write_blk(sb, type, info->u.v2_i.dqi_free_entry, tmpbuf)) < 0)
836 info->u.v2_i.dqi_free_entry = blk;
837 - mark_info_dirty(filp->f_dentry->d_sb, type);
838 + mark_info_dirty(sb, type);
842 @@ -292,8 +265,8 @@ out_buf:
843 /* Find space for dquot */
844 static uint find_free_dqentry(struct dquot *dquot, int *err)
846 - struct file *filp = sb_dqopt(dquot->dq_sb)->files[dquot->dq_type];
847 - struct mem_dqinfo *info = sb_dqopt(dquot->dq_sb)->info+dquot->dq_type;
848 + struct super_block *sb = dquot->dq_sb;
849 + struct mem_dqinfo *info = sb_dqopt(sb)->info+dquot->dq_type;
851 struct v2_disk_dqdbheader *dh;
852 struct v2_disk_dqblk *ddquot;
853 @@ -309,22 +282,23 @@ static uint find_free_dqentry(struct dqu
854 ddquot = GETENTRIES(buf);
855 if (info->u.v2_i.dqi_free_entry) {
856 blk = info->u.v2_i.dqi_free_entry;
857 - if ((*err = read_blk(filp, blk, buf)) < 0)
858 + if ((*err = read_blk(sb, dquot->dq_type, blk, buf)) < 0)
862 - blk = get_free_dqblk(filp, dquot->dq_type);
863 + blk = get_free_dqblk(sb, dquot->dq_type);
869 memset(buf, 0, V2_DQBLKSIZE);
870 - info->u.v2_i.dqi_free_entry = blk; /* This is enough as block is already zeroed and entry list is empty... */
871 - mark_info_dirty(dquot->dq_sb, dquot->dq_type);
872 + /* This is enough as block is already zeroed and entry list is empty... */
873 + info->u.v2_i.dqi_free_entry = blk;
874 + mark_info_dirty(sb, dquot->dq_type);
876 if (le16_to_cpu(dh->dqdh_entries)+1 >= V2_DQSTRINBLK) /* Block will be full? */
877 - if ((*err = remove_free_dqentry(filp, dquot->dq_type, buf, blk)) < 0) {
878 + if ((*err = remove_free_dqentry(sb, dquot->dq_type, buf, blk)) < 0) {
879 printk(KERN_ERR "VFS: find_free_dqentry(): Can't remove block (%u) from entry free list.\n", blk);
882 @@ -339,7 +313,7 @@ static uint find_free_dqentry(struct dqu
886 - if ((*err = write_blk(filp, blk, buf)) < 0) {
887 + if ((*err = write_blk(sb, dquot->dq_type, blk, buf)) < 0) {
888 printk(KERN_ERR "VFS: find_free_dqentry(): Can't write quota data block %u.\n", blk);
891 @@ -354,7 +328,7 @@ out_buf:
892 /* Insert reference to structure into the trie */
893 static int do_insert_tree(struct dquot *dquot, uint *treeblk, int depth)
895 - struct file *filp = sb_dqopt(dquot->dq_sb)->files[dquot->dq_type];
896 + struct super_block *sb = dquot->dq_sb;
898 int ret = 0, newson = 0, newact = 0;
900 @@ -363,7 +337,7 @@ static int do_insert_tree(struct dquot *
901 if (!(buf = getdqbuf()))
904 - ret = get_free_dqblk(filp, dquot->dq_type);
905 + ret = get_free_dqblk(sb, dquot->dq_type);
909 @@ -371,7 +345,7 @@ static int do_insert_tree(struct dquot *
913 - if ((ret = read_blk(filp, *treeblk, buf)) < 0) {
914 + if ((ret = read_blk(sb, dquot->dq_type, *treeblk, buf)) < 0) {
915 printk(KERN_ERR "VFS: Can't read tree quota block %u.\n", *treeblk);
918 @@ -394,10 +368,10 @@ static int do_insert_tree(struct dquot *
919 ret = do_insert_tree(dquot, &newblk, depth+1);
920 if (newson && ret >= 0) {
921 ref[GETIDINDEX(dquot->dq_id, depth)] = cpu_to_le32(newblk);
922 - ret = write_blk(filp, *treeblk, buf);
923 + ret = write_blk(sb, dquot->dq_type, *treeblk, buf);
925 else if (newact && ret < 0)
926 - put_free_dqblk(filp, dquot->dq_type, buf, *treeblk);
927 + put_free_dqblk(sb, dquot->dq_type, buf, *treeblk);
931 @@ -416,20 +390,15 @@ static inline int dq_insert_tree(struct
932 static int v2_write_dquot(struct dquot *dquot)
934 int type = dquot->dq_type;
939 struct v2_disk_dqblk ddquot, empty;
941 /* dq_off is guarded by dqio_sem */
943 if ((ret = dq_insert_tree(dquot)) < 0) {
944 - printk(KERN_ERR "VFS: Error %Zd occurred while creating quota.\n", ret);
945 + printk(KERN_ERR "VFS: Error %d occurred while creating quota.\n", ret);
948 - filp = sb_dqopt(dquot->dq_sb)->files[type];
949 - offset = dquot->dq_off;
950 spin_lock(&dq_data_lock);
951 mem2diskdqb(&ddquot, &dquot->dq_dqb, dquot->dq_id);
952 /* Argh... We may need to write structure full of zeroes but that would be
953 @@ -439,10 +408,8 @@ static int v2_write_dquot(struct dquot *
954 if (!memcmp(&empty, &ddquot, sizeof(struct v2_disk_dqblk)))
955 ddquot.dqb_itime = cpu_to_le64(1);
956 spin_unlock(&dq_data_lock);
959 - ret = filp->f_op->write(filp, (char *)&ddquot, sizeof(struct v2_disk_dqblk), &offset);
961 + ret = dquot->dq_sb->s_op->quota_write(dquot->dq_sb, type,
962 + (char *)&ddquot, sizeof(struct v2_disk_dqblk), dquot->dq_off);
963 if (ret != sizeof(struct v2_disk_dqblk)) {
964 printk(KERN_WARNING "VFS: dquota write failed on dev %s\n", dquot->dq_sb->s_id);
966 @@ -458,7 +425,8 @@ static int v2_write_dquot(struct dquot *
967 /* Free dquot entry in data block */
968 static int free_dqentry(struct dquot *dquot, uint blk)
970 - struct file *filp = sb_dqopt(dquot->dq_sb)->files[dquot->dq_type];
971 + struct super_block *sb = dquot->dq_sb;
972 + int type = dquot->dq_type;
973 struct v2_disk_dqdbheader *dh;
974 dqbuf_t buf = getdqbuf();
976 @@ -466,34 +434,39 @@ static int free_dqentry(struct dquot *dq
979 if (dquot->dq_off >> V2_DQBLKSIZE_BITS != blk) {
980 - 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));
981 + printk(KERN_ERR "VFS: Quota structure has offset to other "
982 + "block (%u) than it should (%u).\n", blk,
983 + (uint)(dquot->dq_off >> V2_DQBLKSIZE_BITS));
986 - if ((ret = read_blk(filp, blk, buf)) < 0) {
987 + if ((ret = read_blk(sb, type, blk, buf)) < 0) {
988 printk(KERN_ERR "VFS: Can't read quota data block %u\n", blk);
991 dh = (struct v2_disk_dqdbheader *)buf;
992 dh->dqdh_entries = cpu_to_le16(le16_to_cpu(dh->dqdh_entries)-1);
993 if (!le16_to_cpu(dh->dqdh_entries)) { /* Block got free? */
994 - if ((ret = remove_free_dqentry(filp, dquot->dq_type, buf, blk)) < 0 ||
995 - (ret = put_free_dqblk(filp, dquot->dq_type, buf, blk)) < 0) {
996 - printk(KERN_ERR "VFS: Can't move quota data block (%u) to free list.\n", blk);
997 + if ((ret = remove_free_dqentry(sb, type, buf, blk)) < 0 ||
998 + (ret = put_free_dqblk(sb, type, buf, blk)) < 0) {
999 + printk(KERN_ERR "VFS: Can't move quota data block (%u) "
1000 + "to free list.\n", blk);
1005 - memset(buf+(dquot->dq_off & ((1 << V2_DQBLKSIZE_BITS)-1)), 0, sizeof(struct v2_disk_dqblk));
1006 + memset(buf+(dquot->dq_off & ((1 << V2_DQBLKSIZE_BITS)-1)), 0,
1007 + sizeof(struct v2_disk_dqblk));
1008 if (le16_to_cpu(dh->dqdh_entries) == V2_DQSTRINBLK-1) {
1009 /* Insert will write block itself */
1010 - if ((ret = insert_free_dqentry(filp, dquot->dq_type, buf, blk)) < 0) {
1011 + if ((ret = insert_free_dqentry(sb, type, buf, blk)) < 0) {
1012 printk(KERN_ERR "VFS: Can't insert quota data block (%u) to free entry list.\n", blk);
1017 - if ((ret = write_blk(filp, blk, buf)) < 0) {
1018 - printk(KERN_ERR "VFS: Can't write quota data block %u\n", blk);
1019 + if ((ret = write_blk(sb, type, blk, buf)) < 0) {
1020 + printk(KERN_ERR "VFS: Can't write quota data "
1021 + "block %u\n", blk);
1025 @@ -506,7 +479,8 @@ out_buf:
1026 /* Remove reference to dquot from tree */
1027 static int remove_tree(struct dquot *dquot, uint *blk, int depth)
1029 - struct file *filp = sb_dqopt(dquot->dq_sb)->files[dquot->dq_type];
1030 + struct super_block *sb = dquot->dq_sb;
1031 + int type = dquot->dq_type;
1032 dqbuf_t buf = getdqbuf();
1035 @@ -514,7 +488,7 @@ static int remove_tree(struct dquot *dqu
1039 - if ((ret = read_blk(filp, *blk, buf)) < 0) {
1040 + if ((ret = read_blk(sb, type, *blk, buf)) < 0) {
1041 printk(KERN_ERR "VFS: Can't read quota data block %u\n", *blk);
1044 @@ -530,12 +504,13 @@ static int remove_tree(struct dquot *dqu
1045 ref[GETIDINDEX(dquot->dq_id, depth)] = cpu_to_le32(0);
1046 for (i = 0; i < V2_DQBLKSIZE && !buf[i]; i++); /* Block got empty? */
1047 if (i == V2_DQBLKSIZE) {
1048 - put_free_dqblk(filp, dquot->dq_type, buf, *blk);
1049 + put_free_dqblk(sb, type, buf, *blk);
1053 - if ((ret = write_blk(filp, *blk, buf)) < 0)
1054 - printk(KERN_ERR "VFS: Can't write quota tree block %u.\n", *blk);
1055 + if ((ret = write_blk(sb, type, *blk, buf)) < 0)
1056 + printk(KERN_ERR "VFS: Can't write quota tree "
1057 + "block %u.\n", *blk);
1061 @@ -555,7 +530,6 @@ static int v2_delete_dquot(struct dquot
1062 /* Find entry in block */
1063 static loff_t find_block_dqentry(struct dquot *dquot, uint blk)
1065 - struct file *filp = sb_dqopt(dquot->dq_sb)->files[dquot->dq_type];
1066 dqbuf_t buf = getdqbuf();
1069 @@ -563,27 +537,31 @@ static loff_t find_block_dqentry(struct
1073 - if ((ret = read_blk(filp, blk, buf)) < 0) {
1074 + if ((ret = read_blk(dquot->dq_sb, dquot->dq_type, blk, buf)) < 0) {
1075 printk(KERN_ERR "VFS: Can't read quota tree block %u.\n", blk);
1079 - for (i = 0; i < V2_DQSTRINBLK && le32_to_cpu(ddquot[i].dqb_id) != dquot->dq_id; i++);
1080 + for (i = 0; i < V2_DQSTRINBLK &&
1081 + le32_to_cpu(ddquot[i].dqb_id) != dquot->dq_id; i++);
1082 else { /* ID 0 as a bit more complicated searching... */
1083 struct v2_disk_dqblk fakedquot;
1085 memset(&fakedquot, 0, sizeof(struct v2_disk_dqblk));
1086 for (i = 0; i < V2_DQSTRINBLK; i++)
1087 - if (!le32_to_cpu(ddquot[i].dqb_id) && memcmp(&fakedquot, ddquot+i, sizeof(struct v2_disk_dqblk)))
1088 + if (!le32_to_cpu(ddquot[i].dqb_id) &&
1089 + memcmp(&fakedquot, ddquot+i, sizeof(struct v2_disk_dqblk)))
1092 if (i == V2_DQSTRINBLK) {
1093 - printk(KERN_ERR "VFS: Quota for id %u referenced but not present.\n", dquot->dq_id);
1094 + printk(KERN_ERR "VFS: Quota for id %u referenced "
1095 + "but not present.\n", dquot->dq_id);
1100 - ret = (blk << V2_DQBLKSIZE_BITS) + sizeof(struct v2_disk_dqdbheader) + i * sizeof(struct v2_disk_dqblk);
1101 + ret = (blk << V2_DQBLKSIZE_BITS) + sizeof(struct
1102 + v2_disk_dqdbheader) + i * sizeof(struct v2_disk_dqblk);
1106 @@ -592,14 +570,13 @@ out_buf:
1107 /* Find entry for given id in the tree */
1108 static loff_t find_tree_dqentry(struct dquot *dquot, uint blk, int depth)
1110 - struct file *filp = sb_dqopt(dquot->dq_sb)->files[dquot->dq_type];
1111 dqbuf_t buf = getdqbuf();
1113 __le32 *ref = (__le32 *)buf;
1117 - if ((ret = read_blk(filp, blk, buf)) < 0) {
1118 + if ((ret = read_blk(dquot->dq_sb, dquot->dq_type, blk, buf)) < 0) {
1119 printk(KERN_ERR "VFS: Can't read quota tree block %u.\n", blk);
1122 @@ -625,16 +602,13 @@ static inline loff_t find_dqentry(struct
1123 static int v2_read_dquot(struct dquot *dquot)
1125 int type = dquot->dq_type;
1126 - struct file *filp;
1129 struct v2_disk_dqblk ddquot, empty;
1132 - filp = sb_dqopt(dquot->dq_sb)->files[type];
1134 #ifdef __QUOTA_V2_PARANOIA
1135 - if (!filp || !dquot->dq_sb) { /* Invalidated quota? */
1136 + /* Invalidated quota? */
1137 + if (!dquot->dq_sb || !sb_dqopt(dquot->dq_sb)->files[type]) {
1138 printk(KERN_ERR "VFS: Quota invalidated while reading!\n");
1141 @@ -642,7 +616,8 @@ static int v2_read_dquot(struct dquot *d
1142 offset = find_dqentry(dquot);
1143 if (offset <= 0) { /* Entry not present? */
1145 - printk(KERN_ERR "VFS: Can't read quota structure for id %u.\n", dquot->dq_id);
1146 + printk(KERN_ERR "VFS: Can't read quota "
1147 + "structure for id %u.\n", dquot->dq_id);
1149 set_bit(DQ_FAKE_B, &dquot->dq_flags);
1150 memset(&dquot->dq_dqb, 0, sizeof(struct mem_dqblk));
1151 @@ -650,12 +625,13 @@ static int v2_read_dquot(struct dquot *d
1154 dquot->dq_off = offset;
1156 - set_fs(KERNEL_DS);
1157 - if ((ret = filp->f_op->read(filp, (char *)&ddquot, sizeof(struct v2_disk_dqblk), &offset)) != sizeof(struct v2_disk_dqblk)) {
1158 + if ((ret = dquot->dq_sb->s_op->quota_read(dquot->dq_sb, type,
1159 + (char *)&ddquot, sizeof(struct v2_disk_dqblk), offset))
1160 + != sizeof(struct v2_disk_dqblk)) {
1163 - printk(KERN_ERR "VFS: Error while reading quota structure for id %u.\n", dquot->dq_id);
1164 + printk(KERN_ERR "VFS: Error while reading quota "
1165 + "structure for id %u.\n", dquot->dq_id);
1166 memset(&ddquot, 0, sizeof(struct v2_disk_dqblk));
1169 @@ -666,7 +642,6 @@ static int v2_read_dquot(struct dquot *d
1170 if (!memcmp(&empty, &ddquot, sizeof(struct v2_disk_dqblk)))
1171 ddquot.dqb_itime = 0;
1174 disk2memdqb(&dquot->dq_dqb, &ddquot);
1175 if (!dquot->dq_dqb.dqb_bhardlimit &&
1176 !dquot->dq_dqb.dqb_bsoftlimit &&
1177 diff -rup RH_2_6_9_55.orig/include/linux/fs.h RH_2_6_9_55/include/linux/fs.h
1178 --- RH_2_6_9_55.orig/include/linux/fs.h
1179 +++ RH_2_6_9_55/include/linux/fs.h
1180 @@ -1042,6 +1042,9 @@ struct super_operations {
1181 void (*umount_lustre) (struct super_block *);
1183 int (*show_options)(struct seq_file *, struct vfsmount *);
1185 + ssize_t (*quota_read)(struct super_block *, int, char *, size_t, loff_t);
1186 + ssize_t (*quota_write)(struct super_block *, int, const char *, size_t, loff_t);
1189 /* Inode state bits. Protected by inode_lock. */
1190 diff -rup RH_2_6_9_55.orig/include/linux/quota.h RH_2_6_9_55/include/linux/quota.h
1191 --- RH_2_6_9_55.orig/include/linux/quota.h
1192 +++ RH_2_6_9_55/include/linux/quota.h
1193 @@ -285,7 +285,7 @@ struct quota_info {
1194 struct semaphore dqio_sem; /* lock device while I/O in progress */
1195 struct semaphore dqonoff_sem; /* Serialize quotaon & quotaoff */
1196 struct rw_semaphore dqptr_sem; /* serialize ops using quota_info struct, pointers from inode to dquots */
1197 - struct file *files[MAXQUOTAS]; /* fp's to quotafiles */
1198 + struct inode *files[MAXQUOTAS]; /* inodes of quotafiles */
1199 struct mem_dqinfo info[MAXQUOTAS]; /* Information for each quota type */
1200 struct quota_format_ops *ops[MAXQUOTAS]; /* Operations for each type */
1202 diff -rup RH_2_6_9_55.orig/include/linux/security.h RH_2_6_9_55/include/linux/security.h
1203 --- RH_2_6_9_55.orig/include/linux/security.h
1204 +++ RH_2_6_9_55/include/linux/security.h
1205 @@ -1033,7 +1033,7 @@ struct security_operations {
1206 int (*sysctl) (ctl_table * table, int op);
1207 int (*capable) (struct task_struct * tsk, int cap);
1208 int (*quotactl) (int cmds, int type, int id, struct super_block * sb);
1209 - int (*quota_on) (struct file * f);
1210 + int (*quota_on) (struct dentry * dentry);
1211 int (*syslog) (int type);
1212 int (*vm_enough_memory) (long pages);
1214 @@ -1281,9 +1281,9 @@ static inline int security_quotactl (int
1215 return security_ops->quotactl (cmds, type, id, sb);
1218 -static inline int security_quota_on (struct file * file)
1219 +static inline int security_quota_on (struct dentry * dentry)
1221 - return security_ops->quota_on (file);
1222 + return security_ops->quota_on (dentry);
1225 static inline int security_syslog(int type)
1226 @@ -1953,7 +1953,7 @@ static inline int security_quotactl (int
1230 -static inline int security_quota_on (struct file * file)
1231 +static inline int security_quota_on (struct dentry * dentry)
1235 diff -rup RH_2_6_9_55.orig/security/dummy.c RH_2_6_9_55/security/dummy.c
1236 --- RH_2_6_9_55.orig/security/dummy.c
1237 +++ RH_2_6_9_55/security/dummy.c
1238 @@ -92,7 +92,7 @@ static int dummy_quotactl (int cmds, int
1242 -static int dummy_quota_on (struct file *f)
1243 +static int dummy_quota_on (struct dentry *dentry)
1247 diff -rup RH_2_6_9_55.orig/security/selinux/hooks.c RH_2_6_9_55/security/selinux/hooks.c
1248 --- RH_2_6_9_55.orig/security/selinux/hooks.c
1249 +++ RH_2_6_9_55/security/selinux/hooks.c
1250 @@ -1485,9 +1485,9 @@ static int selinux_quotactl(int cmds, in
1254 -static int selinux_quota_on(struct file *f)
1255 +static int selinux_quota_on(struct dentry *dentry)
1257 - return file_has_perm(current, f, FILE__QUOTAON);
1258 + return dentry_has_perm(current, NULL, dentry, FILE__QUOTAON);
1261 static int selinux_syslog(int type)