mirror of
https://mirrors.bfsu.edu.cn/git/linux.git
synced 2024-11-24 12:44:11 +08:00
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: Andrew Perepechko <andrew.perepechko@sun.com> Signed-off-by: Jan Kara <jack@suse.cz>
This commit is contained in:
parent
4c5e6c0e70
commit
08261673cb
@ -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) {
|
||||||
|
Loading…
Reference in New Issue
Block a user