[DRBD-cvs] svn commit by phil - r2812 - trunk/drbd - In the
unlikely case that all bios of the bios array we
drbd-cvs at lists.linbit.com
drbd-cvs at lists.linbit.com
Fri Mar 23 17:14:48 CET 2007
Author: phil
Date: 2007-03-23 17:14:47 +0100 (Fri, 23 Mar 2007)
New Revision: 2812
Modified:
trunk/drbd/drbd_actlog.c
Log:
In the unlikely case that all bios of the bios array were
used in drbd_al_to_on_disk_bm(), the for-loop submitting
them might run over its bounds...
In drbd_al_to_on_disk_bm():
* BUGFIX: The for loops do not test bios[i], but i<nr_elements, and
the loop also terminates if the first bios[i] == NULL is found.
* Improvement: Only look at mdev->act_log->nr_elements after we got
the lock bit on the act_log.
drbd_al_to_on_disk_bm_slow():
* Improvement: lc_unlock() in any case if we got the lock.
Modified: trunk/drbd/drbd_actlog.c
===================================================================
--- trunk/drbd/drbd_actlog.c 2007-03-21 17:10:53 UTC (rev 2811)
+++ trunk/drbd/drbd_actlog.c 2007-03-23 16:14:47 UTC (rev 2812)
@@ -533,10 +533,11 @@
drbd_bm_write_sect(mdev, enr/AL_EXT_PER_BM_SECT );
}
- lc_unlock(mdev->act_log);
- wake_up(&mdev->al_wait);
dec_local(mdev);
} else D_ASSERT(0);
+
+ lc_unlock(mdev->act_log);
+ wake_up(&mdev->al_wait);
}
struct drbd_atodb_wait {
@@ -646,30 +647,33 @@
*/
void drbd_al_to_on_disk_bm(struct Drbd_Conf *mdev)
{
- int i;
+ int i, nr_elements;
unsigned int enr;
struct bio **bios;
struct page *page;
unsigned int page_offset=PAGE_SIZE;
struct drbd_atodb_wait wc;
- bios = kzalloc(sizeof(struct bio*) * mdev->act_log->nr_elements,
- GFP_KERNEL);
+ wait_event(mdev->al_wait, lc_try_lock(mdev->act_log));
+ nr_elements = mdev->act_log->nr_elements;
+
+ bios = kzalloc(sizeof(struct bio*) * nr_elements, GFP_KERNEL);
+
if(!bios) {
+ lc_unlock(mdev->act_log);
+
drbd_al_to_on_disk_bm_slow(mdev);
return;
}
- wait_event(mdev->al_wait, lc_try_lock(mdev->act_log));
-
if (inc_local_if_state(mdev,Attaching)) {
atomic_set(&wc.count,0);
init_completion(&wc.io_done);
wc.mdev = mdev;
wc.error = 0;
- for(i=0;i<mdev->act_log->nr_elements;i++) {
+ for(i=0;i<nr_elements;i++) {
enr = lc_entry(mdev->act_log,i)->lc_number;
if(enr == LC_FREE) continue;
/* next statement also does atomic_inc wc.count */
@@ -684,7 +688,8 @@
wake_up(&mdev->al_wait);
/* all prepared, submit them */
- for(i=0; bios[i]; i++) {
+ for(i=0;i<nr_elements;i++) {
+ if (bios[i]==NULL) break;
if (FAULT_ACTIVE( mdev, DRBD_FAULT_MD_WR )) {
bios[i]->bi_rw = WRITE;
bio_endio(bios[i],bios[i]->bi_size,-EIO);
@@ -718,7 +723,8 @@
wake_up(&mdev->al_wait);
// free everything by calling the endio callback directly.
- for(i=0; bios[i]; i++) {
+ for(i=0;i<nr_elements;i++) {
+ if(bios[i]==NULL) break;
bios[i]->bi_size=0;
atodb_endio(bios[i], MD_HARDSECT, 0);
}
More information about the drbd-cvs
mailing list