From: Jan Kara Fixes a problem with some quota operations not writing the quota info they changed which could later cause that some transaction to use more buffers than it had reserved or it could cause corrupted quota files when the system was rebooted at the right time. Signed-off-by: Andrew Morton --- 25-akpm/fs/dquot.c | 30 +++++++++++++++++++++++------- 1 files changed, 23 insertions(+), 7 deletions(-) diff -puN fs/dquot.c~quota-fix-writing-of-quota-info fs/dquot.c --- 25/fs/dquot.c~quota-fix-writing-of-quota-info Wed Jun 2 14:44:30 2004 +++ 25-akpm/fs/dquot.c Wed Jun 2 14:44:30 2004 @@ -306,7 +306,7 @@ EXPORT_SYMBOL(mark_info_dirty); int dquot_acquire(struct dquot *dquot) { - int ret = 0; + int ret = 0, ret2 = 0; struct quota_info *dqopt = sb_dqopt(dquot->dq_sb); down(&dquot->dq_lock); @@ -319,8 +319,15 @@ int dquot_acquire(struct dquot *dquot) /* Instantiate dquot if needed */ if (!test_bit(DQ_ACTIVE_B, &dquot->dq_flags) && !dquot->dq_off) { ret = dqopt->ops[dquot->dq_type]->commit_dqblk(dquot); + /* Write the info if needed */ + if (info_dirty(&dqopt->info[dquot->dq_type])) + ret2 = dqopt->ops[dquot->dq_type]->write_file_info(dquot->dq_sb, dquot->dq_type); if (ret < 0) goto out_iolock; + if (ret2 < 0) { + ret = ret2; + goto out_iolock; + } } set_bit(DQ_ACTIVE_B, &dquot->dq_flags); out_iolock: @@ -334,7 +341,7 @@ out_iolock: */ int dquot_commit(struct dquot *dquot) { - int ret = 0; + int ret = 0, ret2 = 0; struct quota_info *dqopt = sb_dqopt(dquot->dq_sb); down(&dqopt->dqio_sem); @@ -346,12 +353,15 @@ int dquot_commit(struct dquot *dquot) spin_unlock(&dq_list_lock); /* Inactive dquot can be only if there was error during read/init * => we have better not writing it */ - if (test_bit(DQ_ACTIVE_B, &dquot->dq_flags)) + if (test_bit(DQ_ACTIVE_B, &dquot->dq_flags)) { ret = dqopt->ops[dquot->dq_type]->commit_dqblk(dquot); + if (info_dirty(&dqopt->info[dquot->dq_type])) + ret2 = dqopt->ops[dquot->dq_type]->write_file_info(dquot->dq_sb, dquot->dq_type); + if (ret >= 0) + ret = ret2; + } out_sem: up(&dqopt->dqio_sem); - if (info_dirty(&dqopt->info[dquot->dq_type])) - dquot->dq_sb->dq_op->write_info(dquot->dq_sb, dquot->dq_type); return ret; } @@ -360,7 +370,7 @@ out_sem: */ int dquot_release(struct dquot *dquot) { - int ret = 0; + int ret = 0, ret2 = 0; struct quota_info *dqopt = sb_dqopt(dquot->dq_sb); down(&dquot->dq_lock); @@ -368,8 +378,14 @@ int dquot_release(struct dquot *dquot) if (atomic_read(&dquot->dq_count) > 1) goto out_dqlock; down(&dqopt->dqio_sem); - if (dqopt->ops[dquot->dq_type]->release_dqblk) + if (dqopt->ops[dquot->dq_type]->release_dqblk) { ret = dqopt->ops[dquot->dq_type]->release_dqblk(dquot); + /* Write the info */ + if (info_dirty(&dqopt->info[dquot->dq_type])) + ret2 = dqopt->ops[dquot->dq_type]->write_file_info(dquot->dq_sb, dquot->dq_type); + if (ret >= 0) + ret = ret2; + } clear_bit(DQ_ACTIVE_B, &dquot->dq_flags); up(&dqopt->dqio_sem); out_dqlock: _