From: Jan Kara 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 */ _