Commit 08261673 authored by Andrew Perepechko's avatar Andrew Perepechko Committed by Jan Kara

quota: Fix possible dq_flags corruption

dq_flags are modified non-atomically in do_set_dqblk via __set_bit calls and
atomically for example in mark_dquot_dirty or clear_dquot_dirty.  Hence a
change done by an atomic operation can be overwritten by a change done by a
non-atomic one. Fix the problem by using atomic bitops even in do_set_dqblk.
Signed-off-by: default avatarAndrew Perepechko <andrew.perepechko@sun.com>
Signed-off-by: default avatarJan Kara <jack@suse.cz>
parent 4c5e6c0e
...@@ -2328,34 +2328,34 @@ static int do_set_dqblk(struct dquot *dquot, struct if_dqblk *di) ...@@ -2328,34 +2328,34 @@ static int do_set_dqblk(struct dquot *dquot, struct if_dqblk *di)
if (di->dqb_valid & QIF_SPACE) { if (di->dqb_valid & QIF_SPACE) {
dm->dqb_curspace = di->dqb_curspace - dm->dqb_rsvspace; dm->dqb_curspace = di->dqb_curspace - dm->dqb_rsvspace;
check_blim = 1; check_blim = 1;
__set_bit(DQ_LASTSET_B + QIF_SPACE_B, &dquot->dq_flags); set_bit(DQ_LASTSET_B + QIF_SPACE_B, &dquot->dq_flags);
} }
if (di->dqb_valid & QIF_BLIMITS) { if (di->dqb_valid & QIF_BLIMITS) {
dm->dqb_bsoftlimit = qbtos(di->dqb_bsoftlimit); dm->dqb_bsoftlimit = qbtos(di->dqb_bsoftlimit);
dm->dqb_bhardlimit = qbtos(di->dqb_bhardlimit); dm->dqb_bhardlimit = qbtos(di->dqb_bhardlimit);
check_blim = 1; check_blim = 1;
__set_bit(DQ_LASTSET_B + QIF_BLIMITS_B, &dquot->dq_flags); set_bit(DQ_LASTSET_B + QIF_BLIMITS_B, &dquot->dq_flags);
} }
if (di->dqb_valid & QIF_INODES) { if (di->dqb_valid & QIF_INODES) {
dm->dqb_curinodes = di->dqb_curinodes; dm->dqb_curinodes = di->dqb_curinodes;
check_ilim = 1; check_ilim = 1;
__set_bit(DQ_LASTSET_B + QIF_INODES_B, &dquot->dq_flags); set_bit(DQ_LASTSET_B + QIF_INODES_B, &dquot->dq_flags);
} }
if (di->dqb_valid & QIF_ILIMITS) { if (di->dqb_valid & QIF_ILIMITS) {
dm->dqb_isoftlimit = di->dqb_isoftlimit; dm->dqb_isoftlimit = di->dqb_isoftlimit;
dm->dqb_ihardlimit = di->dqb_ihardlimit; dm->dqb_ihardlimit = di->dqb_ihardlimit;
check_ilim = 1; check_ilim = 1;
__set_bit(DQ_LASTSET_B + QIF_ILIMITS_B, &dquot->dq_flags); set_bit(DQ_LASTSET_B + QIF_ILIMITS_B, &dquot->dq_flags);
} }
if (di->dqb_valid & QIF_BTIME) { if (di->dqb_valid & QIF_BTIME) {
dm->dqb_btime = di->dqb_btime; dm->dqb_btime = di->dqb_btime;
check_blim = 1; check_blim = 1;
__set_bit(DQ_LASTSET_B + QIF_BTIME_B, &dquot->dq_flags); set_bit(DQ_LASTSET_B + QIF_BTIME_B, &dquot->dq_flags);
} }
if (di->dqb_valid & QIF_ITIME) { if (di->dqb_valid & QIF_ITIME) {
dm->dqb_itime = di->dqb_itime; dm->dqb_itime = di->dqb_itime;
check_ilim = 1; check_ilim = 1;
__set_bit(DQ_LASTSET_B + QIF_ITIME_B, &dquot->dq_flags); set_bit(DQ_LASTSET_B + QIF_ITIME_B, &dquot->dq_flags);
} }
if (check_blim) { if (check_blim) {
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment