aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/block/drbd/drbd_main.c
diff options
context:
space:
mode:
authorLars Ellenberg <lars.ellenberg@linbit.com>2010-09-03 04:00:09 -0400
committerPhilipp Reisner <philipp.reisner@linbit.com>2010-10-14 12:38:30 -0400
commitee15b038164fcf19b798021762dee3cf5cbc6433 (patch)
tree8d2cca781af96296a591a14928ece247fc682ef3 /drivers/block/drbd/drbd_main.c
parent63106d3c6c769b6219bd04edde513b12abae3f61 (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_main.c')
-rw-r--r--drivers/block/drbd/drbd_main.c24
1 files changed, 19 insertions, 5 deletions
diff --git a/drivers/block/drbd/drbd_main.c b/drivers/block/drbd/drbd_main.c
index 5dd071e5c921..ab1244e0045c 100644
--- a/drivers/block/drbd/drbd_main.c
+++ b/drivers/block/drbd/drbd_main.c
@@ -3402,9 +3402,10 @@ void drbd_md_sync(struct drbd_conf *mdev)
3402 sector_t sector; 3402 sector_t sector;
3403 int i; 3403 int i;
3404 3404
3405 del_timer(&mdev->md_sync_timer);
3406 /* timer may be rearmed by drbd_md_mark_dirty() now. */
3405 if (!test_and_clear_bit(MD_DIRTY, &mdev->flags)) 3407 if (!test_and_clear_bit(MD_DIRTY, &mdev->flags))
3406 return; 3408 return;
3407 del_timer(&mdev->md_sync_timer);
3408 3409
3409 /* We use here D_FAILED and not D_ATTACHING because we try to write 3410 /* We use here D_FAILED and not D_ATTACHING because we try to write
3410 * metadata even if we detach due to a disk failure! */ 3411 * metadata even if we detach due to a disk failure! */
@@ -3529,12 +3530,22 @@ int drbd_md_read(struct drbd_conf *mdev, struct drbd_backing_dev *bdev)
3529 * the meta-data super block. This function sets MD_DIRTY, and starts a 3530 * the meta-data super block. This function sets MD_DIRTY, and starts a
3530 * timer that ensures that within five seconds you have to call drbd_md_sync(). 3531 * timer that ensures that within five seconds you have to call drbd_md_sync().
3531 */ 3532 */
3533#ifdef DRBD_DEBUG_MD_SYNC
3534void drbd_md_mark_dirty_(struct drbd_conf *mdev, unsigned int line, const char *func)
3535{
3536 if (!test_and_set_bit(MD_DIRTY, &mdev->flags)) {
3537 mod_timer(&mdev->md_sync_timer, jiffies + HZ);
3538 mdev->last_md_mark_dirty.line = line;
3539 mdev->last_md_mark_dirty.func = func;
3540 }
3541}
3542#else
3532void drbd_md_mark_dirty(struct drbd_conf *mdev) 3543void drbd_md_mark_dirty(struct drbd_conf *mdev)
3533{ 3544{
3534 set_bit(MD_DIRTY, &mdev->flags); 3545 if (!test_and_set_bit(MD_DIRTY, &mdev->flags))
3535 mod_timer(&mdev->md_sync_timer, jiffies + 5*HZ); 3546 mod_timer(&mdev->md_sync_timer, jiffies + HZ);
3536} 3547}
3537 3548#endif
3538 3549
3539static void drbd_uuid_move_history(struct drbd_conf *mdev) __must_hold(local) 3550static void drbd_uuid_move_history(struct drbd_conf *mdev) __must_hold(local)
3540{ 3551{
@@ -3775,8 +3786,11 @@ static void md_sync_timer_fn(unsigned long data)
3775static int w_md_sync(struct drbd_conf *mdev, struct drbd_work *w, int unused) 3786static int w_md_sync(struct drbd_conf *mdev, struct drbd_work *w, int unused)
3776{ 3787{
3777 dev_warn(DEV, "md_sync_timer expired! Worker calls drbd_md_sync().\n"); 3788 dev_warn(DEV, "md_sync_timer expired! Worker calls drbd_md_sync().\n");
3789#ifdef DEBUG
3790 dev_warn(DEV, "last md_mark_dirty: %s:%u\n",
3791 mdev->last_md_mark_dirty.func, mdev->last_md_mark_dirty.line);
3792#endif
3778 drbd_md_sync(mdev); 3793 drbd_md_sync(mdev);
3779
3780 return 1; 3794 return 1;
3781} 3795}
3782 3796