
From: Jan Kara <jack@ucw.cz>

This patch fixes possible quota files corruption which could happen when root
did not have any inodes&space allocated.

Originally this could not happen as structure would not be written to disk in
that case but with journalled quota we need to write even all-zero structure. 
The fix is not very nice but change of the format on disk is probably worse (I
made a mistake with not including the usage-bitmaps into format :().


---

 25-akpm/fs/dquot.c                 |    7 +++++--
 25-akpm/fs/quota_v2.c              |   18 +++++++++++++++---
 25-akpm/include/linux/quotaio_v2.h |    2 +-
 3 files changed, 21 insertions(+), 6 deletions(-)

diff -puN fs/dquot.c~quota-fix-3-quota-file-corruption fs/dquot.c
--- 25/fs/dquot.c~quota-fix-3-quota-file-corruption	Mon May 17 13:46:03 2004
+++ 25-akpm/fs/dquot.c	Mon May 17 13:46:03 2004
@@ -1205,8 +1205,11 @@ int dquot_transfer(struct inode *inode, 
 		if (transfer_to[cnt] == NODQUOT)
 			continue;
 
-		dquot_decr_inodes(transfer_from[cnt], 1);
-		dquot_decr_space(transfer_from[cnt], space);
+		/* Due to IO error we might not have transfer_from[] structure */
+		if (transfer_from[cnt]) {
+			dquot_decr_inodes(transfer_from[cnt], 1);
+			dquot_decr_space(transfer_from[cnt], space);
+		}
 
 		dquot_incr_inodes(transfer_to[cnt], 1);
 		dquot_incr_space(transfer_to[cnt], space);
diff -puN fs/quota_v2.c~quota-fix-3-quota-file-corruption fs/quota_v2.c
--- 25/fs/quota_v2.c~quota-fix-3-quota-file-corruption	Mon May 17 13:46:03 2004
+++ 25-akpm/fs/quota_v2.c	Mon May 17 13:51:52 2004
@@ -420,7 +420,7 @@ static int v2_write_dquot(struct dquot *
 	mm_segment_t fs;
 	loff_t offset;
 	ssize_t ret;
-	struct v2_disk_dqblk ddquot;
+	struct v2_disk_dqblk ddquot, empty;
 
 	/* dq_off is guarded by dqio_sem */
 	if (!dquot->dq_off)
@@ -432,6 +432,12 @@ static int v2_write_dquot(struct dquot *
 	offset = dquot->dq_off;
 	spin_lock(&dq_data_lock);
 	mem2diskdqb(&ddquot, &dquot->dq_dqb, dquot->dq_id);
+	/* Argh... We may need to write structure full of zeroes but that would be
+	 * treated as an empty place by the rest of the code. Format change would
+	 * be definitely cleaner but the problems probably are not worth it */
+	memset(&empty, 0, sizeof(struct v2_disk_dqblk));
+	if (!memcmp(&empty, &ddquot, sizeof(struct v2_disk_dqblk)))
+		ddquot.dqb_itime = cpu_to_le64(1);
 	spin_unlock(&dq_data_lock);
 	fs = get_fs();
 	set_fs(KERNEL_DS);
@@ -622,7 +628,7 @@ static int v2_read_dquot(struct dquot *d
 	struct file *filp;
 	mm_segment_t fs;
 	loff_t offset;
-	struct v2_disk_dqblk ddquot;
+	struct v2_disk_dqblk ddquot, empty;
 	int ret = 0;
 
 	filp = sb_dqopt(dquot->dq_sb)->files[type];
@@ -652,8 +658,14 @@ static int v2_read_dquot(struct dquot *d
 			printk(KERN_ERR "VFS: Error while reading quota structure for id %u.\n", dquot->dq_id);
 			memset(&ddquot, 0, sizeof(struct v2_disk_dqblk));
 		}
-		else
+		else {
 			ret = 0;
+			/* We need to escape back all-zero structure */
+			memset(&empty, 0, sizeof(struct v2_disk_dqblk));
+			empty.dqb_itime = cpu_to_le64(1);
+			if (!memcmp(&empty, &ddquot, sizeof(struct v2_disk_dqblk)))
+				ddquot.dqb_itime = 0;
+		}
 		set_fs(fs);
 		disk2memdqb(&dquot->dq_dqb, &ddquot);
 		if (!dquot->dq_dqb.dqb_bhardlimit &&
diff -puN include/linux/quotaio_v2.h~quota-fix-3-quota-file-corruption include/linux/quotaio_v2.h
--- 25/include/linux/quotaio_v2.h~quota-fix-3-quota-file-corruption	Mon May 17 13:46:03 2004
+++ 25-akpm/include/linux/quotaio_v2.h	Mon May 17 13:46:03 2004
@@ -59,7 +59,7 @@ struct v2_disk_dqinfo {
 
 /*
  *  Structure of header of block with quota structures. It is padded to 16 bytes so
- *  there will be space for exactly 18 quota-entries in a block
+ *  there will be space for exactly 21 quota-entries in a block
  */
 struct v2_disk_dqdbheader {
 	__u32 dqdh_next_free;	/* Number of next block with free entry */

_
