diff options
author | Andrew Perepechko <andrew.perepechko@sun.com> | 2010-04-12 14:16:50 -0400 |
---|---|---|
committer | Jan Kara <jack@suse.cz> | 2010-04-12 15:12:36 -0400 |
commit | 08261673cb6dc638c39f44d69b76fffb57b92a8b (patch) | |
tree | 752b396f409897a4357ca29bc2f9c3384d29e07d | |
parent | 4c5e6c0e70fd6ca2fa67184fd36a261b3b7b38d0 (diff) |
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>
-rw-r--r-- | fs/quota/dquot.c | 12 |
1 files changed, 6 insertions, 6 deletions
diff --git a/fs/quota/dquot.c b/fs/quota/dquot.c index f9a37513f24c..a0a9405b202a 100644 --- a/fs/quota/dquot.c +++ b/fs/quota/dquot.c | |||
@@ -2328,34 +2328,34 @@ static int do_set_dqblk(struct dquot *dquot, struct if_dqblk *di) | |||
2328 | if (di->dqb_valid & QIF_SPACE) { | 2328 | if (di->dqb_valid & QIF_SPACE) { |
2329 | dm->dqb_curspace = di->dqb_curspace - dm->dqb_rsvspace; | 2329 | dm->dqb_curspace = di->dqb_curspace - dm->dqb_rsvspace; |
2330 | check_blim = 1; | 2330 | check_blim = 1; |
2331 | __set_bit(DQ_LASTSET_B + QIF_SPACE_B, &dquot->dq_flags); | 2331 | set_bit(DQ_LASTSET_B + QIF_SPACE_B, &dquot->dq_flags); |
2332 | } | 2332 | } |
2333 | if (di->dqb_valid & QIF_BLIMITS) { | 2333 | if (di->dqb_valid & QIF_BLIMITS) { |
2334 | dm->dqb_bsoftlimit = qbtos(di->dqb_bsoftlimit); | 2334 | dm->dqb_bsoftlimit = qbtos(di->dqb_bsoftlimit); |
2335 | dm->dqb_bhardlimit = qbtos(di->dqb_bhardlimit); | 2335 | dm->dqb_bhardlimit = qbtos(di->dqb_bhardlimit); |
2336 | check_blim = 1; | 2336 | check_blim = 1; |
2337 | __set_bit(DQ_LASTSET_B + QIF_BLIMITS_B, &dquot->dq_flags); | 2337 | set_bit(DQ_LASTSET_B + QIF_BLIMITS_B, &dquot->dq_flags); |
2338 | } | 2338 | } |
2339 | if (di->dqb_valid & QIF_INODES) { | 2339 | if (di->dqb_valid & QIF_INODES) { |
2340 | dm->dqb_curinodes = di->dqb_curinodes; | 2340 | dm->dqb_curinodes = di->dqb_curinodes; |
2341 | check_ilim = 1; | 2341 | check_ilim = 1; |
2342 | __set_bit(DQ_LASTSET_B + QIF_INODES_B, &dquot->dq_flags); | 2342 | set_bit(DQ_LASTSET_B + QIF_INODES_B, &dquot->dq_flags); |
2343 | } | 2343 | } |
2344 | if (di->dqb_valid & QIF_ILIMITS) { | 2344 | if (di->dqb_valid & QIF_ILIMITS) { |
2345 | dm->dqb_isoftlimit = di->dqb_isoftlimit; | 2345 | dm->dqb_isoftlimit = di->dqb_isoftlimit; |
2346 | dm->dqb_ihardlimit = di->dqb_ihardlimit; | 2346 | dm->dqb_ihardlimit = di->dqb_ihardlimit; |
2347 | check_ilim = 1; | 2347 | check_ilim = 1; |
2348 | __set_bit(DQ_LASTSET_B + QIF_ILIMITS_B, &dquot->dq_flags); | 2348 | set_bit(DQ_LASTSET_B + QIF_ILIMITS_B, &dquot->dq_flags); |
2349 | } | 2349 | } |
2350 | if (di->dqb_valid & QIF_BTIME) { | 2350 | if (di->dqb_valid & QIF_BTIME) { |
2351 | dm->dqb_btime = di->dqb_btime; | 2351 | dm->dqb_btime = di->dqb_btime; |
2352 | check_blim = 1; | 2352 | check_blim = 1; |
2353 | __set_bit(DQ_LASTSET_B + QIF_BTIME_B, &dquot->dq_flags); | 2353 | set_bit(DQ_LASTSET_B + QIF_BTIME_B, &dquot->dq_flags); |
2354 | } | 2354 | } |
2355 | if (di->dqb_valid & QIF_ITIME) { | 2355 | if (di->dqb_valid & QIF_ITIME) { |
2356 | dm->dqb_itime = di->dqb_itime; | 2356 | dm->dqb_itime = di->dqb_itime; |
2357 | check_ilim = 1; | 2357 | check_ilim = 1; |
2358 | __set_bit(DQ_LASTSET_B + QIF_ITIME_B, &dquot->dq_flags); | 2358 | set_bit(DQ_LASTSET_B + QIF_ITIME_B, &dquot->dq_flags); |
2359 | } | 2359 | } |
2360 | 2360 | ||
2361 | if (check_blim) { | 2361 | if (check_blim) { |