diff options
author | Lars Ellenberg <lars.ellenberg@linbit.com> | 2010-09-03 04:00:09 -0400 |
---|---|---|
committer | Philipp Reisner <philipp.reisner@linbit.com> | 2010-10-14 12:38:30 -0400 |
commit | ee15b038164fcf19b798021762dee3cf5cbc6433 (patch) | |
tree | 8d2cca781af96296a591a14928ece247fc682ef3 /drivers/block/drbd/drbd_int.h | |
parent | 63106d3c6c769b6219bd04edde513b12abae3f61 (diff) |
drbd: fix race on meta-data update, addendum
addendum to baa33ae4eaa4477b60af7c434c0ddd1d182c1ae7
The race:
drbd_md_sync()
if (!test_and_clear_bit(MD_DIRTY, &mdev->flags))
return;
==> RACE with drbd_md_mark_dirty() rearming the timer.
del_timer(&mdev->md_sync_timer);
Fixed by moving the del_timer before the test_and_clear_bit.
Additionally only rearm the timer in drbd_md_mark_dirty, if MD_DIRTY was
not already set, reduce the grace period from five to one second, and
add an ifdef'ed debuging aid to find code paths missing an explicit
drbd_md_sync, if any, as those are the only relevant ones for this race.
Signed-off-by: Philipp Reisner <philipp.reisner@linbit.com>
Signed-off-by: Lars Ellenberg <lars.ellenberg@linbit.com>
Diffstat (limited to 'drivers/block/drbd/drbd_int.h')
-rw-r--r-- | drivers/block/drbd/drbd_int.h | 12 |
1 files changed, 12 insertions, 0 deletions
diff --git a/drivers/block/drbd/drbd_int.h b/drivers/block/drbd/drbd_int.h index d5e38de83a19..f9b75fc30569 100644 --- a/drivers/block/drbd/drbd_int.h +++ b/drivers/block/drbd/drbd_int.h | |||
@@ -975,6 +975,12 @@ struct drbd_conf { | |||
975 | md_sync_work; | 975 | md_sync_work; |
976 | struct timer_list resync_timer; | 976 | struct timer_list resync_timer; |
977 | struct timer_list md_sync_timer; | 977 | struct timer_list md_sync_timer; |
978 | #ifdef DRBD_DEBUG_MD_SYNC | ||
979 | struct { | ||
980 | unsigned int line; | ||
981 | const char* func; | ||
982 | } last_md_mark_dirty; | ||
983 | #endif | ||
978 | 984 | ||
979 | /* Used after attach while negotiating new disk state. */ | 985 | /* Used after attach while negotiating new disk state. */ |
980 | union drbd_state new_state_tmp; | 986 | union drbd_state new_state_tmp; |
@@ -1253,7 +1259,13 @@ extern void drbd_uuid_set_bm(struct drbd_conf *mdev, u64 val) __must_hold(local) | |||
1253 | extern void drbd_md_set_flag(struct drbd_conf *mdev, int flags) __must_hold(local); | 1259 | extern void drbd_md_set_flag(struct drbd_conf *mdev, int flags) __must_hold(local); |
1254 | extern void drbd_md_clear_flag(struct drbd_conf *mdev, int flags)__must_hold(local); | 1260 | extern void drbd_md_clear_flag(struct drbd_conf *mdev, int flags)__must_hold(local); |
1255 | extern int drbd_md_test_flag(struct drbd_backing_dev *, int); | 1261 | extern int drbd_md_test_flag(struct drbd_backing_dev *, int); |
1262 | #ifndef DRBD_DEBUG_MD_SYNC | ||
1256 | extern void drbd_md_mark_dirty(struct drbd_conf *mdev); | 1263 | extern void drbd_md_mark_dirty(struct drbd_conf *mdev); |
1264 | #else | ||
1265 | #define drbd_md_mark_dirty(m) drbd_md_mark_dirty_(m, __LINE__ , __func__ ) | ||
1266 | extern void drbd_md_mark_dirty_(struct drbd_conf *mdev, | ||
1267 | unsigned int line, const char *func); | ||
1268 | #endif | ||
1257 | extern void drbd_queue_bitmap_io(struct drbd_conf *mdev, | 1269 | extern void drbd_queue_bitmap_io(struct drbd_conf *mdev, |
1258 | int (*io_fn)(struct drbd_conf *), | 1270 | int (*io_fn)(struct drbd_conf *), |
1259 | void (*done)(struct drbd_conf *, int), | 1271 | void (*done)(struct drbd_conf *, int), |