From: Jan Kara <jack@ucw.cz>

here's patch which should fix deadlock with quotas+ext3 reported in 2.4
(the same problem existed in 2.6 but nobody found it).



 fs/dquot.c            |   10 +++++-----
 fs/ext3/super.c       |   10 +++++-----
 include/linux/quota.h |    2 +-
 3 files changed, 11 insertions(+), 11 deletions(-)

diff -puN fs/dquot.c~ext3-quota-deadlock-fix fs/dquot.c
--- 25/fs/dquot.c~ext3-quota-deadlock-fix	2003-11-24 09:53:41.000000000 -0800
+++ 25-akpm/fs/dquot.c	2003-11-24 09:53:41.000000000 -0800
@@ -344,7 +344,7 @@ restart:
 		atomic_inc(&dquot->dq_count);
 		dqstats.lookups++;
 		spin_unlock(&dq_list_lock);
-		sb->dq_op->sync_dquot(dquot);
+		sb->dq_op->write_dquot(dquot);
 		dqput(dquot);
 		goto restart;
 	}
@@ -432,7 +432,7 @@ we_slept:
 	}
 	if (dquot_dirty(dquot)) {
 		spin_unlock(&dq_list_lock);
-		commit_dqblk(dquot);
+		dquot->dq_sb->dq_op->write_dquot(dquot);
 		goto we_slept;
 	}
 	atomic_dec(&dquot->dq_count);
@@ -1088,7 +1088,7 @@ struct dquot_operations dquot_operations
 	.free_space	= dquot_free_space,
 	.free_inode	= dquot_free_inode,
 	.transfer	= dquot_transfer,
-	.sync_dquot	= commit_dqblk
+	.write_dquot	= commit_dqblk
 };
 
 /* Function used by filesystems for initializing the dquot_operations structure */
@@ -1212,9 +1212,9 @@ int vfs_quota_on(struct super_block *sb,
 	error = -EINVAL;
 	if (!fmt->qf_ops->check_quota_file(sb, type))
 		goto out_file_init;
-	/* We don't want quota on quota files */
+	/* We don't want quota and atime on quota files (deadlocks possible) */
 	dquot_drop_nolock(inode);
-	inode->i_flags |= S_NOQUOTA;
+	inode->i_flags |= S_NOQUOTA | S_NOATIME;
 
 	dqopt->ops[type] = fmt->qf_ops;
 	dqopt->info[type].dqi_format = fmt;
diff -puN fs/ext3/super.c~ext3-quota-deadlock-fix fs/ext3/super.c
--- 25/fs/ext3/super.c~ext3-quota-deadlock-fix	2003-11-24 09:53:41.000000000 -0800
+++ 25-akpm/fs/ext3/super.c	2003-11-24 09:53:41.000000000 -0800
@@ -1952,9 +1952,9 @@ int ext3_statfs (struct super_block * sb
 /* Blocks: quota info + (4 pointer blocks + 1 entry block) * (3 indirect + 1 descriptor + 1 bitmap) + superblock */
 #define EXT3_V0_QFMT_BLOCKS 27
 
-static int (*old_sync_dquot)(struct dquot *dquot);
+static int (*old_write_dquot)(struct dquot *dquot);
 
-static int ext3_sync_dquot(struct dquot *dquot)
+static int ext3_write_dquot(struct dquot *dquot)
 {
 	int nblocks;
 	int ret;
@@ -1979,7 +1979,7 @@ static int ext3_sync_dquot(struct dquot 
 		ret = PTR_ERR(handle);
 		goto out;
 	}
-	ret = old_sync_dquot(dquot);
+	ret = old_write_dquot(dquot);
 	err = ext3_journal_stop(handle);
 	if (ret == 0)
 		ret = err;
@@ -2012,8 +2012,8 @@ static int __init init_ext3_fs(void)
 		goto out1;
 #ifdef CONFIG_QUOTA
 	init_dquot_operations(&ext3_qops);
-	old_sync_dquot = ext3_qops.sync_dquot;
-	ext3_qops.sync_dquot = ext3_sync_dquot;
+	old_write_dquot = ext3_qops.write_dquot;
+	ext3_qops.write_dquot = ext3_write_dquot;
 #endif
         err = register_filesystem(&ext3_fs_type);
 	if (err)
diff -puN include/linux/quota.h~ext3-quota-deadlock-fix include/linux/quota.h
--- 25/include/linux/quota.h~ext3-quota-deadlock-fix	2003-11-24 09:53:41.000000000 -0800
+++ 25-akpm/include/linux/quota.h	2003-11-24 09:53:41.000000000 -0800
@@ -250,7 +250,7 @@ struct dquot_operations {
 	void (*free_space) (struct inode *, qsize_t);
 	void (*free_inode) (const struct inode *, unsigned long);
 	int (*transfer) (struct inode *, struct iattr *);
-	int (*sync_dquot) (struct dquot *);
+	int (*write_dquot) (struct dquot *);
 };
 
 /* Operations handling requests from userspace */

_