aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorNeil Brown <neilb@suse.de>2007-02-08 17:20:37 -0500
committerLinus Torvalds <torvalds@woody.linux-foundation.org>2007-02-09 12:25:47 -0500
commitda6e1a32fb8d7539a27f699c8671f64d7fefd0cc (patch)
tree8faa7713ad1333b30d8ba668627251dbc1e0b4ad
parentaaf68cfbf2241d24d46583423f6bff5c47e088b3 (diff)
[PATCH] md: avoid possible BUG_ON in md bitmap handling
md/bitmap tracks how many active write requests are pending on blocks associated with each bit in the bitmap, so that it knows when it can clear the bit (when count hits zero). The counter has 14 bits of space, so if there are ever more than 16383, we cannot cope. Currently the code just calles BUG_ON as "all" drivers have request queue limits much smaller than this. However is seems that some don't. Apparently some multipath configurations can allow more than 16383 concurrent write requests. So, in this unlikely situation, instead of calling BUG_ON we now wait for the count to drop down a bit. This requires a new wait_queue_head, some waiting code, and a wakeup call. Tested by limiting the counter to 20 instead of 16383 (writes go a lot slower in that case...). Signed-off-by: Neil Brown <neilb@suse.de> Cc: <stable@kernel.org> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
-rw-r--r--drivers/md/bitmap.c22
-rw-r--r--include/linux/raid/bitmap.h1
2 files changed, 22 insertions, 1 deletions
diff --git a/drivers/md/bitmap.c b/drivers/md/bitmap.c
index 11108165e264..059704fbb753 100644
--- a/drivers/md/bitmap.c
+++ b/drivers/md/bitmap.c
@@ -1160,6 +1160,22 @@ int bitmap_startwrite(struct bitmap *bitmap, sector_t offset, unsigned long sect
1160 return 0; 1160 return 0;
1161 } 1161 }
1162 1162
1163 if (unlikely((*bmc & COUNTER_MAX) == COUNTER_MAX)) {
1164 DEFINE_WAIT(__wait);
1165 /* note that it is safe to do the prepare_to_wait
1166 * after the test as long as we do it before dropping
1167 * the spinlock.
1168 */
1169 prepare_to_wait(&bitmap->overflow_wait, &__wait,
1170 TASK_UNINTERRUPTIBLE);
1171 spin_unlock_irq(&bitmap->lock);
1172 bitmap->mddev->queue
1173 ->unplug_fn(bitmap->mddev->queue);
1174 schedule();
1175 finish_wait(&bitmap->overflow_wait, &__wait);
1176 continue;
1177 }
1178
1163 switch(*bmc) { 1179 switch(*bmc) {
1164 case 0: 1180 case 0:
1165 bitmap_file_set_bit(bitmap, offset); 1181 bitmap_file_set_bit(bitmap, offset);
@@ -1169,7 +1185,7 @@ int bitmap_startwrite(struct bitmap *bitmap, sector_t offset, unsigned long sect
1169 case 1: 1185 case 1:
1170 *bmc = 2; 1186 *bmc = 2;
1171 } 1187 }
1172 BUG_ON((*bmc & COUNTER_MAX) == COUNTER_MAX); 1188
1173 (*bmc)++; 1189 (*bmc)++;
1174 1190
1175 spin_unlock_irq(&bitmap->lock); 1191 spin_unlock_irq(&bitmap->lock);
@@ -1207,6 +1223,9 @@ void bitmap_endwrite(struct bitmap *bitmap, sector_t offset, unsigned long secto
1207 if (!success && ! (*bmc & NEEDED_MASK)) 1223 if (!success && ! (*bmc & NEEDED_MASK))
1208 *bmc |= NEEDED_MASK; 1224 *bmc |= NEEDED_MASK;
1209 1225
1226 if ((*bmc & COUNTER_MAX) == COUNTER_MAX)
1227 wake_up(&bitmap->overflow_wait);
1228
1210 (*bmc)--; 1229 (*bmc)--;
1211 if (*bmc <= 2) { 1230 if (*bmc <= 2) {
1212 set_page_attr(bitmap, 1231 set_page_attr(bitmap,
@@ -1431,6 +1450,7 @@ int bitmap_create(mddev_t *mddev)
1431 spin_lock_init(&bitmap->lock); 1450 spin_lock_init(&bitmap->lock);
1432 atomic_set(&bitmap->pending_writes, 0); 1451 atomic_set(&bitmap->pending_writes, 0);
1433 init_waitqueue_head(&bitmap->write_wait); 1452 init_waitqueue_head(&bitmap->write_wait);
1453 init_waitqueue_head(&bitmap->overflow_wait);
1434 1454
1435 bitmap->mddev = mddev; 1455 bitmap->mddev = mddev;
1436 1456
diff --git a/include/linux/raid/bitmap.h b/include/linux/raid/bitmap.h
index ebd42a3710b4..6db9a4c15355 100644
--- a/include/linux/raid/bitmap.h
+++ b/include/linux/raid/bitmap.h
@@ -247,6 +247,7 @@ struct bitmap {
247 247
248 atomic_t pending_writes; /* pending writes to the bitmap file */ 248 atomic_t pending_writes; /* pending writes to the bitmap file */
249 wait_queue_head_t write_wait; 249 wait_queue_head_t write_wait;
250 wait_queue_head_t overflow_wait;
250 251
251}; 252};
252 253