[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