[DRBD-cvs] svn commit by phil - r2056 - branches/drbd-0.7/drbd - Neil Brown created a patch that serializes recursive ca

drbd-cvs at lists.linbit.com drbd-cvs at lists.linbit.com
Sun Jan 29 12:40:34 CET 2006


Author: phil
Date: 2006-01-29 12:40:33 +0100 (Sun, 29 Jan 2006)
New Revision: 2056

Modified:
   branches/drbd-0.7/drbd/drbd_actlog.c
Log:
Neil Brown created a patch that serializes recursive calls
to generic_make_request(). FC4 included that patch in one
of their kernel updates. Since DRBD made a call to 
generi_make_request() from it's make_request function,
it deadlocked on that latest FC4 kernel.

This patch solves the issue by offloding the writing of 
AL transaction to our worker thread.


Modified: branches/drbd-0.7/drbd/drbd_actlog.c
===================================================================
--- branches/drbd-0.7/drbd/drbd_actlog.c	2006-01-25 22:20:32 UTC (rev 2055)
+++ branches/drbd-0.7/drbd/drbd_actlog.c	2006-01-29 11:40:33 UTC (rev 2056)
@@ -191,8 +191,15 @@
 	unsigned int enr;
 };
 
-STATIC void drbd_al_write_transaction(struct Drbd_Conf *,struct lc_element *,
-				      unsigned int );
+struct update_al_work {
+	struct drbd_work w;
+	struct lc_element * al_ext;
+	struct completion event;
+	unsigned int enr;
+};
+
+STATIC int w_al_write_transaction(struct Drbd_Conf *, struct drbd_work *, int);
+
 static inline
 struct lc_element* _al_get(struct Drbd_Conf *mdev, unsigned int enr)
 {
@@ -229,6 +236,7 @@
 {
 	unsigned int enr = (sector >> (AL_EXTENT_SIZE_B-9));
 	struct lc_element *al_ext;
+	struct update_al_work al_work;
 
 	D_ASSERT(atomic_read(&mdev->local_cnt)>0);
 	wait_event(mdev->al_wait, (al_ext = _al_get(mdev,enr)) );
@@ -242,7 +250,19 @@
 		if(mdev->cstate < Connected && evicted != LC_FREE ) {
 			drbd_bm_write_sect(mdev, evicted/AL_EXT_PER_BM_SECT );
 		}
-		drbd_al_write_transaction(mdev,al_ext,enr);
+
+		/* drbd_al_write_transaction(mdev,al_ext,enr);
+		   generic_make_request() are serialized on the 
+		   current->bio_tail list now. Therefore we have
+		   to deligate writing something to AL to the
+		   worker thread. */
+		init_completion(&al_work.event);
+		al_work.al_ext = al_ext;
+		al_work.enr = enr;
+		al_work.w.cb = w_al_write_transaction;
+		drbd_queue_work_front(mdev,&mdev->data.work,&al_work.w);
+		wait_for_completion(&al_work.event);
+		
 		mdev->al_writ_cnt++;
 
 		/*
@@ -279,9 +299,8 @@
 	spin_unlock_irqrestore(&mdev->al_lock,flags);
 }
 
-STATIC void
-drbd_al_write_transaction(struct Drbd_Conf *mdev,struct lc_element *updated,
-			  unsigned int new_enr)
+STATIC int
+w_al_write_transaction(struct Drbd_Conf *mdev, struct drbd_work *w, int unused)
 {
 	int i,n,mx;
 	unsigned int extent_nr;
@@ -289,6 +308,9 @@
 	sector_t sector;
 	u32 xor_sum=0;
 
+	struct lc_element *updated = ((struct update_al_work*)w)->al_ext;
+	unsigned int new_enr = ((struct update_al_work*)w)->enr;
+
 	down(&mdev->md_io_mutex); // protects md_io_buffer, al_tr_cycle, ...
 	buffer = (struct al_transaction*)page_address(mdev->md_io_page);
 
@@ -340,6 +362,10 @@
 	mdev->al_tr_number++;
 
 	up(&mdev->md_io_mutex);
+
+	complete(&((struct update_al_work*)w)->event);
+
+	return 1;
 }
 
 STATIC int drbd_al_read_tr(struct Drbd_Conf *mdev,



More information about the drbd-cvs mailing list