aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/md/bitmap.c
diff options
context:
space:
mode:
authorNeilBrown <neilb@suse.de>2009-12-13 20:49:46 -0500
committerNeilBrown <neilb@suse.de>2009-12-13 20:49:46 -0500
commitaa5cbd103887011b4830355f88fb055f9ad2d556 (patch)
tree92ef7c80999c6d0bfc6fef9a9cd3e4a75ee16c06 /drivers/md/bitmap.c
parentf40542532e96dda5506eb76badea322f2ae4731c (diff)
md/bitmap: protect against bitmap removal while being updated.
A write intent bitmap can be removed from an array while the array is active. When this happens, all IO is suspended and flushed before the bitmap is removed. However it is possible that bitmap_daemon_work is still running to clear old bits from the bitmap. If it is, it can dereference the bitmap after it has been freed. So introduce a new mutex to protect bitmap_daemon_work and get it before destroying a bitmap. This is suitable for any current -stable kernel. Signed-off-by: NeilBrown <neilb@suse.de> Cc: stable@kernel.org
Diffstat (limited to 'drivers/md/bitmap.c')
-rw-r--r--drivers/md/bitmap.c24
1 files changed, 18 insertions, 6 deletions
diff --git a/drivers/md/bitmap.c b/drivers/md/bitmap.c
index 60e2b322db11..a5e5f2fbf963 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,
1078 * out to disk 1078 * out to disk
1079 */ 1079 */
1080 1080
1081void bitmap_daemon_work(struct bitmap *bitmap) 1081void bitmap_daemon_work(mddev_t *mddev)
1082{ 1082{
1083 struct bitmap *bitmap;
1083 unsigned long j; 1084 unsigned long j;
1084 unsigned long flags; 1085 unsigned long flags;
1085 struct page *page = NULL, *lastpage = NULL; 1086 struct page *page = NULL, *lastpage = NULL;
1086 int blocks; 1087 int blocks;
1087 void *paddr; 1088 void *paddr;
1088 1089
1089 if (bitmap == NULL) 1090 /* Use a mutex to guard daemon_work against
1091 * bitmap_destroy.
1092 */
1093 mutex_lock(&mddev->bitmap_mutex);
1094 bitmap = mddev->bitmap;
1095 if (bitmap == NULL) {
1096 mutex_unlock(&mddev->bitmap_mutex);
1090 return; 1097 return;
1098 }
1091 if (time_before(jiffies, bitmap->daemon_lastrun + bitmap->daemon_sleep*HZ)) 1099 if (time_before(jiffies, bitmap->daemon_lastrun + bitmap->daemon_sleep*HZ))
1092 goto done; 1100 goto done;
1093 1101
1094 bitmap->daemon_lastrun = jiffies; 1102 bitmap->daemon_lastrun = jiffies;
1095 if (bitmap->allclean) { 1103 if (bitmap->allclean) {
1096 bitmap->mddev->thread->timeout = MAX_SCHEDULE_TIMEOUT; 1104 bitmap->mddev->thread->timeout = MAX_SCHEDULE_TIMEOUT;
1097 return; 1105 goto done;
1098 } 1106 }
1099 bitmap->allclean = 1; 1107 bitmap->allclean = 1;
1100 1108
@@ -1203,6 +1211,7 @@ void bitmap_daemon_work(struct bitmap *bitmap)
1203 done: 1211 done:
1204 if (bitmap->allclean == 0) 1212 if (bitmap->allclean == 0)
1205 bitmap->mddev->thread->timeout = bitmap->daemon_sleep * HZ; 1213 bitmap->mddev->thread->timeout = bitmap->daemon_sleep * HZ;
1214 mutex_unlock(&mddev->bitmap_mutex);
1206} 1215}
1207 1216
1208static bitmap_counter_t *bitmap_get_counter(struct bitmap *bitmap, 1217static bitmap_counter_t *bitmap_get_counter(struct bitmap *bitmap,
@@ -1541,9 +1550,9 @@ void bitmap_flush(mddev_t *mddev)
1541 */ 1550 */
1542 sleep = bitmap->daemon_sleep; 1551 sleep = bitmap->daemon_sleep;
1543 bitmap->daemon_sleep = 0; 1552 bitmap->daemon_sleep = 0;
1544 bitmap_daemon_work(bitmap); 1553 bitmap_daemon_work(mddev);
1545 bitmap_daemon_work(bitmap); 1554 bitmap_daemon_work(mddev);
1546 bitmap_daemon_work(bitmap); 1555 bitmap_daemon_work(mddev);
1547 bitmap->daemon_sleep = sleep; 1556 bitmap->daemon_sleep = sleep;
1548 bitmap_update_sb(bitmap); 1557 bitmap_update_sb(bitmap);
1549} 1558}
@@ -1574,6 +1583,7 @@ static void bitmap_free(struct bitmap *bitmap)
1574 kfree(bp); 1583 kfree(bp);
1575 kfree(bitmap); 1584 kfree(bitmap);
1576} 1585}
1586
1577void bitmap_destroy(mddev_t *mddev) 1587void bitmap_destroy(mddev_t *mddev)
1578{ 1588{
1579 struct bitmap *bitmap = mddev->bitmap; 1589 struct bitmap *bitmap = mddev->bitmap;
@@ -1581,7 +1591,9 @@ void bitmap_destroy(mddev_t *mddev)
1581 if (!bitmap) /* there was no bitmap */ 1591 if (!bitmap) /* there was no bitmap */
1582 return; 1592 return;
1583 1593
1594 mutex_lock(&mddev->bitmap_mutex);
1584 mddev->bitmap = NULL; /* disconnect from the md device */ 1595 mddev->bitmap = NULL; /* disconnect from the md device */
1596 mutex_unlock(&mddev->bitmap_mutex);
1585 if (mddev->thread) 1597 if (mddev->thread)
1586 mddev->thread->timeout = MAX_SCHEDULE_TIMEOUT; 1598 mddev->thread->timeout = MAX_SCHEDULE_TIMEOUT;
1587 1599