From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1161468AbXBGW3H (ORCPT ); Wed, 7 Feb 2007 17:29:07 -0500 Received: (majordomo@vger.kernel.org) by vger.kernel.org id S1161465AbXBGW3H (ORCPT ); Wed, 7 Feb 2007 17:29:07 -0500 Received: from ns2.suse.de ([195.135.220.15]:56023 "EHLO mx2.suse.de" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1161454AbXBGW3D (ORCPT ); Wed, 7 Feb 2007 17:29:03 -0500 From: Neil Brown To: akpm@linux-foundation.org Date: Thu, 8 Feb 2007 09:28:28 +1100 MIME-Version: 1.0 Content-Type: text/plain; charset=us-ascii Content-Transfer-Encoding: 7bit Message-ID: <17866.21132.606116.583062@notabene.brown> Cc: linux-raid@vger.kernel.org, linux-kernel@vger.kernel.org Cc: stable@kernel.org Subject: [PATCH] md: Avoid possible BUG_ON in md bitmap handling. X-Mailer: VM 7.19 under Emacs 21.4.1 X-face: [Gw_3E*Gng}4rRrKRYotwlE?.2|**#s9D ### Diffstat output ./drivers/md/bitmap.c | 22 +++++++++++++++++++++- ./include/linux/raid/bitmap.h | 1 + 2 files changed, 22 insertions(+), 1 deletion(-) diff .prev/drivers/md/bitmap.c ./drivers/md/bitmap.c --- .prev/drivers/md/bitmap.c 2007-02-07 13:03:56.000000000 +1100 +++ ./drivers/md/bitmap.c 2007-02-07 21:34:47.000000000 +1100 @@ -1160,6 +1160,22 @@ int bitmap_startwrite(struct bitmap *bit return 0; } + if (unlikely((*bmc & COUNTER_MAX) == COUNTER_MAX)) { + DEFINE_WAIT(__wait); + /* note that it is safe to do the prepare_to_wait + * after the test as long as we do it before dropping + * the spinlock. + */ + prepare_to_wait(&bitmap->overflow_wait, &__wait, + TASK_UNINTERRUPTIBLE); + spin_unlock_irq(&bitmap->lock); + bitmap->mddev->queue + ->unplug_fn(bitmap->mddev->queue); + schedule(); + finish_wait(&bitmap->overflow_wait, &__wait); + continue; + } + switch(*bmc) { case 0: bitmap_file_set_bit(bitmap, offset); @@ -1169,7 +1185,7 @@ int bitmap_startwrite(struct bitmap *bit case 1: *bmc = 2; } - BUG_ON((*bmc & COUNTER_MAX) == COUNTER_MAX); + (*bmc)++; spin_unlock_irq(&bitmap->lock); @@ -1207,6 +1223,9 @@ void bitmap_endwrite(struct bitmap *bitm if (!success && ! (*bmc & NEEDED_MASK)) *bmc |= NEEDED_MASK; + if ((*bmc & COUNTER_MAX) == COUNTER_MAX) + wake_up(&bitmap->overflow_wait); + (*bmc)--; if (*bmc <= 2) { set_page_attr(bitmap, @@ -1431,6 +1450,7 @@ int bitmap_create(mddev_t *mddev) spin_lock_init(&bitmap->lock); atomic_set(&bitmap->pending_writes, 0); init_waitqueue_head(&bitmap->write_wait); + init_waitqueue_head(&bitmap->overflow_wait); bitmap->mddev = mddev; diff .prev/include/linux/raid/bitmap.h ./include/linux/raid/bitmap.h --- .prev/include/linux/raid/bitmap.h 2007-02-07 13:03:56.000000000 +1100 +++ ./include/linux/raid/bitmap.h 2007-02-07 20:57:57.000000000 +1100 @@ -247,6 +247,7 @@ struct bitmap { atomic_t pending_writes; /* pending writes to the bitmap file */ wait_queue_head_t write_wait; + wait_queue_head_t overflow_wait; };