diff options
Diffstat (limited to 'drivers')
-rw-r--r-- | drivers/md/bitmap.c | 27 |
1 files changed, 22 insertions, 5 deletions
diff --git a/drivers/md/bitmap.c b/drivers/md/bitmap.c index 23563f545651..1a7f402b79ba 100644 --- a/drivers/md/bitmap.c +++ b/drivers/md/bitmap.c @@ -416,6 +416,21 @@ out: * bitmap file superblock operations */ +/* + * bitmap_wait_writes() should be called before writing any bitmap + * blocks, to ensure previous writes, particularly from + * bitmap_daemon_work(), have completed. + */ +static void bitmap_wait_writes(struct bitmap *bitmap) +{ + if (bitmap->storage.file) + wait_event(bitmap->write_wait, + atomic_read(&bitmap->pending_writes)==0); + else + md_super_wait(bitmap->mddev); +} + + /* update the event counter and sync the superblock to disk */ void bitmap_update_sb(struct bitmap *bitmap) { @@ -978,6 +993,7 @@ void bitmap_unplug(struct bitmap *bitmap) { unsigned long i; int dirty, need_write; + int writing = 0; if (!bitmap || !bitmap->storage.filemap || test_bit(BITMAP_STALE, &bitmap->flags)) @@ -992,15 +1008,15 @@ void bitmap_unplug(struct bitmap *bitmap) need_write = test_and_clear_page_attr(bitmap, i, BITMAP_PAGE_NEEDWRITE); if (dirty || need_write) { + if (!writing) + bitmap_wait_writes(bitmap); clear_page_attr(bitmap, i, BITMAP_PAGE_PENDING); write_page(bitmap, bitmap->storage.filemap[i], 0); + writing = 1; } } - if (bitmap->storage.file) - wait_event(bitmap->write_wait, - atomic_read(&bitmap->pending_writes)==0); - else - md_super_wait(bitmap->mddev); + if (writing) + bitmap_wait_writes(bitmap); if (test_bit(BITMAP_WRITE_ERROR, &bitmap->flags)) bitmap_file_kick(bitmap); @@ -1282,6 +1298,7 @@ void bitmap_daemon_work(struct mddev *mddev) } spin_unlock_irq(&counts->lock); + bitmap_wait_writes(bitmap); /* Now start writeout on any page in NEEDWRITE that isn't DIRTY. * DIRTY pages need to be written by bitmap_unplug so it can wait * for them. |