diff --git a/drivers/md/bitmap.c b/drivers/md/bitmap.c index 60e2b322db110b96d52f66e4f502610b29d822fe..a5e5f2fbf96351baca4fb443a472f1f58692d379 100644 --- a/drivers/md/bitmap.c +++ b/drivers/md/bitmap.c @@ -1078,23 +1078,31 @@ static bitmap_counter_t *bitmap_get_counter(struct bitmap *bitmap, * out to disk */ -void bitmap_daemon_work(struct bitmap *bitmap) +void bitmap_daemon_work(mddev_t *mddev) { + struct bitmap *bitmap; unsigned long j; unsigned long flags; struct page *page = NULL, *lastpage = NULL; int blocks; void *paddr; - if (bitmap == NULL) + /* Use a mutex to guard daemon_work against + * bitmap_destroy. + */ + mutex_lock(&mddev->bitmap_mutex); + bitmap = mddev->bitmap; + if (bitmap == NULL) { + mutex_unlock(&mddev->bitmap_mutex); return; + } if (time_before(jiffies, bitmap->daemon_lastrun + bitmap->daemon_sleep*HZ)) goto done; bitmap->daemon_lastrun = jiffies; if (bitmap->allclean) { bitmap->mddev->thread->timeout = MAX_SCHEDULE_TIMEOUT; - return; + goto done; } bitmap->allclean = 1; @@ -1203,6 +1211,7 @@ void bitmap_daemon_work(struct bitmap *bitmap) done: if (bitmap->allclean == 0) bitmap->mddev->thread->timeout = bitmap->daemon_sleep * HZ; + mutex_unlock(&mddev->bitmap_mutex); } static bitmap_counter_t *bitmap_get_counter(struct bitmap *bitmap, @@ -1541,9 +1550,9 @@ void bitmap_flush(mddev_t *mddev) */ sleep = bitmap->daemon_sleep; bitmap->daemon_sleep = 0; - bitmap_daemon_work(bitmap); - bitmap_daemon_work(bitmap); - bitmap_daemon_work(bitmap); + bitmap_daemon_work(mddev); + bitmap_daemon_work(mddev); + bitmap_daemon_work(mddev); bitmap->daemon_sleep = sleep; bitmap_update_sb(bitmap); } @@ -1574,6 +1583,7 @@ static void bitmap_free(struct bitmap *bitmap) kfree(bp); kfree(bitmap); } + void bitmap_destroy(mddev_t *mddev) { struct bitmap *bitmap = mddev->bitmap; @@ -1581,7 +1591,9 @@ void bitmap_destroy(mddev_t *mddev) if (!bitmap) /* there was no bitmap */ return; + mutex_lock(&mddev->bitmap_mutex); mddev->bitmap = NULL; /* disconnect from the md device */ + mutex_unlock(&mddev->bitmap_mutex); if (mddev->thread) mddev->thread->timeout = MAX_SCHEDULE_TIMEOUT; diff --git a/drivers/md/bitmap.h b/drivers/md/bitmap.h index e98900671ca91d7a4f76ae91ac7393f6613bd5ee..7e38d13ddcacce54b47206f191af739ce84d436c 100644 --- a/drivers/md/bitmap.h +++ b/drivers/md/bitmap.h @@ -282,7 +282,7 @@ void bitmap_close_sync(struct bitmap *bitmap); void bitmap_cond_end_sync(struct bitmap *bitmap, sector_t sector); void bitmap_unplug(struct bitmap *bitmap); -void bitmap_daemon_work(struct bitmap *bitmap); +void bitmap_daemon_work(mddev_t *mddev); #endif #endif diff --git a/drivers/md/md.c b/drivers/md/md.c index 5f154ef1e4befeeef26358d9ae37e424c62cee47..1be7a16a7a53898196b4b9f03894e755e73d1894 100644 --- a/drivers/md/md.c +++ b/drivers/md/md.c @@ -363,6 +363,7 @@ static mddev_t * mddev_find(dev_t unit) mutex_init(&new->open_mutex); mutex_init(&new->reconfig_mutex); + mutex_init(&new->bitmap_mutex); INIT_LIST_HEAD(&new->disks); INIT_LIST_HEAD(&new->all_mddevs); init_timer(&new->safemode_timer); @@ -6625,7 +6626,7 @@ void md_check_recovery(mddev_t *mddev) if (mddev->bitmap) - bitmap_daemon_work(mddev->bitmap); + bitmap_daemon_work(mddev); if (mddev->ro) return; diff --git a/drivers/md/md.h b/drivers/md/md.h index f184b69ef337514d460d669ffc4309a7d5dcc515..87430fea28752fa40486de40e2563d838368b1fc 100644 --- a/drivers/md/md.h +++ b/drivers/md/md.h @@ -289,6 +289,7 @@ struct mddev_s * hot-adding a bitmap. It should * eventually be settable by sysfs. */ + struct mutex bitmap_mutex; struct list_head all_mddevs; };