[DRBD-cvs] drbd by phil; Merged LGE's make_request_take_4.diff. [...

drbd-user@lists.linbit.com drbd-user@lists.linbit.com
Mon, 16 Feb 2004 21:39:05 +0100 (CET)


DRBD CVS committal

Author  : phil
Module  : drbd

Dir     : drbd/drbd


Modified Files:
      Tag: rel-0_7-branch
	drbd_compat_wrappers.h drbd_dsender.c drbd_int.h drbd_main.c 
	drbd_receiver.c drbd_req-2.4.c 


Log Message:
Merged LGE's make_request_take_4.diff. 
[No testing done so far by me...]

===================================================================
RCS file: /var/lib/cvs/drbd/drbd/drbd/Attic/drbd_compat_wrappers.h,v
retrieving revision 1.1.2.22
retrieving revision 1.1.2.23
diff -u -3 -r1.1.2.22 -r1.1.2.23
--- drbd_compat_wrappers.h	9 Feb 2004 10:36:54 -0000	1.1.2.22
+++ drbd_compat_wrappers.h	16 Feb 2004 20:39:00 -0000	1.1.2.23
@@ -8,6 +8,7 @@
 extern void enslaved_read_bi_end_io (struct buffer_head *bh, int uptodate);
 extern void drbd_dio_end_sec        (struct buffer_head *bh, int uptodate);
 extern void drbd_dio_end            (struct buffer_head *bh, int uptodate);
+extern void drbd_read_bi_end_io     (struct buffer_head *bh, int uptodate);
 
 /*
  * because in 2.6.x [sg]et_capacity operate on gendisk->capacity, which is in
@@ -196,7 +197,8 @@
 	// D_ASSERT(buffer_dirty(bh)); // It is not true ?!?
 	D_ASSERT(buffer_uptodate(bh));
 
-	// FIXME should not be necessary
+	// FIXME should not be necessary;
+	// remove if the assertions above do not trigger.
 	bh->b_state = (1 << BH_Uptodate)
 		     |(1 << BH_Dirty)
 		     |(1 << BH_Lock)
@@ -206,9 +208,6 @@
 	req->rq_status = RQ_DRBD_NOTHING;
 }
 
-#if 0
-/* not yet used
- */
 static inline void
 drbd_req_prepare_read(drbd_dev *mdev, struct drbd_request *req)
 {
@@ -218,7 +217,7 @@
 	drbd_bh_clone(bh,bh_src);
 	bh->b_rdev    = mdev->backing_bdev;
 	bh->b_private = mdev;
-	bh->b_end_io  = drbd_read_end_io;
+	bh->b_end_io  = drbd_read_bi_end_io;
 
 	D_ASSERT(buffer_req(bh));
 	D_ASSERT(buffer_launder(bh));
@@ -226,14 +225,14 @@
 	D_ASSERT(buffer_mapped(bh));
 	D_ASSERT(!buffer_uptodate(bh));
 
-	// FIXME should not be necessary
+	// FIXME should not be necessary;
+	// remove if the assertions above do not trigger.
 	bh->b_state = (1 << BH_Lock)
 		     |(1 << BH_Req)
 		     |(1 << BH_Mapped) ;
 
 	req->rq_status = RQ_DRBD_NOTHING;
 }
-#endif
 
 static inline struct page* drbd_bio_get_page(struct buffer_head *bh)
 {
@@ -250,6 +249,13 @@
 	run_task_queue(&tq_disk);
 }
 
+static inline void drbd_plug_device(drbd_dev *mdev)
+{
+	if(!test_and_set_bit(WRITE_HINT_QUEUED,&mdev->flags)) {
+		queue_task(&mdev->write_hint_tq, &tq_disk); // IO HINT
+	}
+}
+
 static inline int _drbd_send_zc_bio(drbd_dev *mdev, struct buffer_head *bh)
 {
 	struct page *page = bh->b_page;
@@ -282,6 +288,7 @@
 extern int enslaved_read_bi_end_io (struct bio *bio, unsigned int bytes_done, int error);
 extern int drbd_dio_end_sec        (struct bio *bio, unsigned int bytes_done, int error);
 extern int drbd_dio_end            (struct bio *bio, unsigned int bytes_done, int error);
+extern int drbd_read_bi_end_io     (struct bio *bio, unsigned int bytes_done, int error);
 
 // we should not accept bios crossing our extent boundaries!
 extern int drbd_merge_bvec_fn(request_queue_t *q, struct bio *bio, struct bio_vec *bv);
@@ -487,12 +494,20 @@
 	req->rq_status = RQ_DRBD_NOTHING;
 }
 
-#if 0
 static inline void
 drbd_req_prepare_read(drbd_dev *mdev, struct drbd_request *req)
 {
+	struct bio * const bio     = &req->private_bio;
+	struct bio * const bio_src =  req->master_bio;
+
+	__bio_clone(bio,bio_src);
+	bio->bi_bdev    = mdev->backing_bdev;
+	bio->bi_private = mdev;
+	bio->bi_end_io  = drbd_read_bi_end_io;	// <- only difference
+	bio->bi_next    = 0;
+
+	req->rq_status = RQ_DRBD_NOTHING;
 }
-#endif
 
 static inline struct page* drbd_bio_get_page(struct bio *bio)
 {
@@ -500,6 +515,9 @@
 	return bvec->bv_page;
 }
 
+/*
+ * used to submit our private bio
+ */
 static inline void drbd_generic_make_request(int rw, struct bio *bio)
 {
 	bio->bi_rw = rw; //??
@@ -509,6 +527,19 @@
 static inline void drbd_kick_lo(drbd_dev *mdev)
 {
 	blk_run_queue(bdev_get_queue(mdev->backing_bdev)); 
+}
+
+static inline void drbd_plug_device(drbd_dev *mdev)
+{
+	request_queue_t *q = bdev_get_queue(mdev->this_bdev);
+
+	spin_lock_irq(q->queue_lock);
+	if(!blk_queue_plugged(q)) {
+		blk_plug_device(q);
+		del_timer(&q->unplug_timer);
+		// unplugging should not happen automatically...
+	}
+	spin_unlock_irq(q->queue_lock);
 }
 
 static inline int _drbd_send_zc_bio(drbd_dev *mdev, struct bio *bio)
===================================================================
RCS file: /var/lib/cvs/drbd/drbd/drbd/Attic/drbd_dsender.c,v
retrieving revision 1.1.2.75
retrieving revision 1.1.2.76
diff -u -3 -r1.1.2.75 -r1.1.2.76
--- drbd_dsender.c	15 Feb 2004 14:40:11 -0000	1.1.2.75
+++ drbd_dsender.c	16 Feb 2004 20:39:00 -0000	1.1.2.76
@@ -148,11 +148,41 @@
 	PARANOIA_BUG_ON(!VALID_POINTER(req));
 
 	drbd_chk_io_error(mdev,!uptodate);
-	drbd_end_req(req, RQ_DRBD_WRITTEN, uptodate, drbd_req_get_sector(req));
+	drbd_end_req(req, RQ_DRBD_LOCAL, uptodate, drbd_req_get_sector(req));
 	drbd_al_complete_io(mdev,drbd_req_get_sector(req));
 	dec_local(mdev);
 }
 
+/* reads on Primary comming from drbd_make_request
+ */
+void drbd_read_bi_end_io(struct buffer_head *bh, int uptodate)
+{
+	struct Drbd_Conf* mdev;
+	drbd_request_t *req;
+
+	mdev = bh->b_private;
+	PARANOIA_BUG_ON(!IS_VALID_MDEV(mdev));
+
+	req = container_of(bh,struct drbd_request,private_bio);
+	PARANOIA_BUG_ON(!VALID_POINTER(req));
+
+	if (!uptodate) {
+		// for the panic:
+		drbd_chk_io_error(mdev,!uptodate);
+		// ok, if we survived this, retry:
+		// FIXME sector ...
+		ERR("local read failed, retrying remotely\n");
+		req->w.cb = w_read_retry_remote;
+		drbd_queue_work(mdev,&mdev->data.work,&req->w);
+	} else {
+		bh->b_end_io(bh,uptodate);
+
+		INVALIDATE_MAGIC(req);
+		mempool_free(req,drbd_request_mempool);
+	}
+	dec_local(mdev);
+}
+
 #else
 
 /* used for synchronous meta data and bitmap IO
@@ -267,19 +297,91 @@
 	PARANOIA_BUG_ON(!VALID_POINTER(req));
 
 	drbd_chk_io_error(mdev,error);
-	drbd_end_req(req, RQ_DRBD_WRITTEN, (error == 0), drbd_req_get_sector(req));
+	drbd_end_req(req, RQ_DRBD_LOCAL, (error == 0), drbd_req_get_sector(req));
 	drbd_al_complete_io(mdev,drbd_req_get_sector(req));
 	dec_local(mdev);
 	return 0;
 }
+
+/* reads on Primary comming from drbd_make_request
+ */
+int drbd_read_bi_end_io(struct bio *bio, unsigned int bytes_done, int error)
+{
+	struct Drbd_Conf* mdev;
+	drbd_request_t *req;
+
+	// see above
+	if (bio->bi_size)
+		return 1;
+
+	mdev = bio->bi_private;
+	PARANOIA_BUG_ON(!IS_VALID_MDEV(mdev));
+
+	req = container_of(bio,struct drbd_request,private_bio);
+	PARANOIA_BUG_ON(!VALID_POINTER(req));
+
+	if (error) {
+		// for the panic:
+		drbd_chk_io_error(mdev,error);
+		// ok, if we survived this, retry:
+		// FIXME sector ...
+		ERR("local read failed, retrying remotely\n");
+		req->w.cb = w_read_retry_remote;
+		drbd_queue_work(mdev,&mdev->data.work,&req->w);
+	} else {
+		bio_endio(bio,bio->bi_size,error);
+
+		INVALIDATE_MAGIC(req);
+		mempool_free(req,drbd_request_mempool);
+	}
+	return 0;
+}
 #endif
 
+int w_read_retry_remote(drbd_dev* mdev, struct drbd_work* w)
+{
+	drbd_request_t *req = (drbd_request_t*)w;
+
+	if ( mdev->cstate <= Connected ||
+	     test_bit(PARTNER_DISKLESS,&mdev->flags) ) {
+
+		// FIXME
+		// local read failed, and we cannot retry.
+		// drbd_chk_io_error has already been called.
+		// what now: PANIC ??
+
+		// propagate, cannot do anything about it.
+		drbd_bio_endio(req->master_bio,0);
+		return 0; // worker will abort.
+	}
+
+	// FIXME: what if partner was SyncTarget, and is out of sync for
+	// this area ?? ... should be handled in the receiver.
+	drbd_read_remote(mdev,req);
+	return 1;
+}
+
 int w_resync_inactive(drbd_dev *mdev, struct drbd_work *w)
 {
 	ERR("resync inactive, but callback triggered??\n");
 	return 0;
 }
 
+int w_is_resync_read(drbd_dev *mdev, struct drbd_work *w)
+{
+	ERR("%s: Typecheck only, should never be called!\n", __FUNCTION__ );
+	return 0;
+}
+
+/* in case we need it. currently unused,
+ * since should be assigned to "w_read_retry_remote"
+ */
+int w_is_app_read(drbd_dev *mdev, struct drbd_work *w)
+{
+	ERR("%s: Typecheck only, should never be called!\n", __FUNCTION__ );
+	return 0;
+}
+
 void resync_timer_fn(unsigned long data)
 {
 	drbd_dev* mdev = (drbd_dev*) data;
@@ -317,6 +419,7 @@
 		pr = mempool_alloc(drbd_pr_mempool, GFP_USER);
 		if (unlikely(pr == NULL)) goto requeue;
 		SET_MAGIC(pr);
+		pr->w.cb = w_is_resync_read;
 
 	next_sector:
 		size = BM_BLOCK_SIZE;
@@ -367,7 +470,7 @@
 	dt = (jiffies - mdev->rs_start) / HZ + 1;
 	n = mdev->rs_total>>1;
 	sector_div(n,dt);
-	INFO("Resync done (total %lu sec; %u K/sec)\n",
+	INFO("Resync done (total %lu sec; %lu K/sec)\n",
 	     dt,(unsigned long)n);
 
 	if (mdev->cstate == SyncTarget) {
===================================================================
RCS file: /var/lib/cvs/drbd/drbd/drbd/drbd_int.h,v
retrieving revision 1.58.2.125
retrieving revision 1.58.2.126
diff -u -3 -r1.58.2.125 -r1.58.2.126
--- drbd_int.h	15 Feb 2004 14:40:11 -0000	1.58.2.125
+++ drbd_int.h	16 Feb 2004 20:39:00 -0000	1.58.2.126
@@ -232,10 +232,9 @@
 /* these defines should go into blkdev.h
    (if it will be ever includet into linus' linux) */
 #define RQ_DRBD_NOTHING	  0x0001
-#define RQ_DRBD_SENT	  0x0010
-#define RQ_DRBD_WRITTEN   0x0020
+#define RQ_DRBD_SENT      0x0010
+#define RQ_DRBD_LOCAL     0x0020
 #define RQ_DRBD_DONE      0x0030
-#define RQ_DRBD_READ      0x0040
 
 enum MetaDataFlags {
 	MDF_Consistent   = 1,
@@ -671,7 +670,8 @@
 	struct list_head read_ee;   // IO in progress
 	// struct list_head rdone_ee;  // send result or CondRequest
 	spinlock_t pr_lock;
-	struct list_head app_reads;
+	// struct list_head app_reads; // FIXME broken on purpose by lge
+	struct list_head new_app_reads;
 	struct list_head resync_reads;
 	int ee_vacant;
 	int ee_in_use;
@@ -803,10 +803,11 @@
 #define ERF_NOTLD    2   /* do not call tl_dependence */
 extern void drbd_end_req(drbd_request_t *, int, int, sector_t);
 #if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0)
-extern int drbd_make_request(request_queue_t *q, int rw, struct buffer_head *bio);
+extern int drbd_make_request_24(request_queue_t *q, int rw, struct buffer_head *bio);
 #else
-extern int drbd_make_request(request_queue_t *q, struct bio *bio);
+extern int drbd_make_request_26(request_queue_t *q, struct bio *bio);
 #endif
+extern void drbd_read_remote(drbd_dev *mdev, drbd_request_t *req);
 
 // drbd_fs.c
 extern int drbd_determin_dev_size(drbd_dev*);
@@ -821,11 +822,14 @@
 // maybe rather drbd_main.c ?
 extern int drbd_md_sync_page_io(drbd_dev *mdev, sector_t sector, int rw);
 // worker callbacks
+extern int w_is_app_read         (drbd_dev *mdev, struct drbd_work *w);
+extern int w_is_resync_read      (drbd_dev *mdev, struct drbd_work *w);
+extern int w_read_retry_remote   (drbd_dev *mdev, struct drbd_work *w);
 extern int w_e_end_data_req      (drbd_dev *mdev, struct drbd_work *w);
 extern int w_e_end_rsdata_req    (drbd_dev *mdev, struct drbd_work *w);
 extern int w_resync_finished     (drbd_dev *mdev, struct drbd_work *w);
 extern int w_resync_inactive     (drbd_dev *mdev, struct drbd_work *w);
-extern int w_resume_next_sg      (drbd_dev* mdev, struct drbd_work *w);
+extern int w_resume_next_sg      (drbd_dev *mdev, struct drbd_work *w);
 
 
 // drbd_receiver.c
@@ -835,7 +839,7 @@
 extern struct Tl_epoch_entry* drbd_get_ee(drbd_dev* mdev);
 extern int recv_resync_read(drbd_dev* mdev, struct Pending_read *pr,
 			    sector_t sector, int data_size);
-extern int recv_dless_read(drbd_dev* mdev, struct Pending_read *pr,
+extern int recv_dless_read(drbd_dev *mdev, drbd_request_t *req,
 			   sector_t sector, int data_size);
 
 // drbd_proc.c
@@ -934,7 +938,7 @@
 			break;
 		case Panic:
 			set_bit(DISKLESS,&mdev->flags);
-			smp_mb();
+			smp_mb(); // but why is there smp_mb__after_clear_bit() ?
 			panic(DEVICE_NAME" : IO error on backing device!\n");
 			break;
 		case Detach:
===================================================================
RCS file: /var/lib/cvs/drbd/drbd/drbd/drbd_main.c,v
retrieving revision 1.73.2.129
retrieving revision 1.73.2.130
diff -u -3 -r1.73.2.129 -r1.73.2.130
--- drbd_main.c	12 Feb 2004 18:27:06 -0000	1.73.2.129
+++ drbd_main.c	16 Feb 2004 20:39:00 -0000	1.73.2.130
@@ -1097,7 +1097,7 @@
 	INIT_LIST_HEAD(&mdev->done_ee);
 	INIT_LIST_HEAD(&mdev->read_ee);
 	INIT_LIST_HEAD(&mdev->busy_blocks);
-	INIT_LIST_HEAD(&mdev->app_reads);
+	INIT_LIST_HEAD(&mdev->new_app_reads);
 	INIT_LIST_HEAD(&mdev->resync_reads);
 	INIT_LIST_HEAD(&mdev->data.work.q);
 	INIT_LIST_HEAD(&mdev->meta.work.q);
@@ -1342,7 +1342,7 @@
 			WARN("Could not bd_claim() myself.");
 		}
 
-		blk_queue_make_request(q,drbd_make_request);
+		blk_queue_make_request(q,drbd_make_request_26);
 		q->unplug_fn = drbd_send_write_hint;
 	}
 #endif
@@ -1405,7 +1405,7 @@
 			      &drbd_ops, NULL);
 #endif
 
-	NOT_IN_26(blk_queue_make_request(BLK_DEFAULT_QUEUE(MAJOR_NR),drbd_make_request);)
+	NOT_IN_26(blk_queue_make_request(BLK_DEFAULT_QUEUE(MAJOR_NR),drbd_make_request_24);)
 
 #if defined(CONFIG_PPC64) || defined(CONFIG_SPARC64) || defined(CONFIG_X86_64)
 	// tell the kernel that we think our ioctls are 64bit clean
===================================================================
RCS file: /var/lib/cvs/drbd/drbd/drbd/drbd_receiver.c,v
retrieving revision 1.97.2.111
retrieving revision 1.97.2.112
diff -u -3 -r1.97.2.111 -r1.97.2.112
--- drbd_receiver.c	15 Feb 2004 14:40:11 -0000	1.97.2.111
+++ drbd_receiver.c	16 Feb 2004 20:39:00 -0000	1.97.2.112
@@ -742,17 +742,15 @@
 	mdev->writ_cnt+=data_size>>9;
 }
 
-int recv_dless_read(drbd_dev *mdev, struct Pending_read *pr,
+int recv_dless_read(drbd_dev *mdev, drbd_request_t *req,
 		    sector_t sector, int data_size)
 {
 	drbd_bio_t *bio;
 	int ok,rr;
 
-	// DBG("%s\n", __func__);
+	bio = req->master_bio;
 
-	bio = pr->d.master_bio;
-
-	D_ASSERT( sector == drbd_pr_get_sector(pr) );
+	D_ASSERT( sector == drbd_req_get_sector(req) );
 
 	rr=drbd_recv(mdev,drbd_bio_kmap(bio),data_size);
 	drbd_bio_kunmap(bio);
@@ -882,6 +880,7 @@
 STATIC int receive_DataReply(drbd_dev *mdev,Drbd_Header* h)
 {
 	struct Pending_read *pr;
+	drbd_request_t *req;
 	sector_t sector;
 	unsigned int header_size,data_size;
 	int ok;
@@ -889,7 +888,7 @@
 
 	static int (*funcs[])(struct Drbd_Conf* , struct Pending_read*,
 			      sector_t,int) = {
-			      [Application]  = recv_dless_read,
+			      [Application]  = NULL,  /* recv_dless_read, */
 			      [Resync]       = recv_resync_read,
 			      [AppAndResync] = recv_both_read
 		      };
@@ -909,26 +908,47 @@
 
 	sector = be64_to_cpu(p->sector);
 
-	pr = (struct Pending_read *)(long)p->block_id;
+	/* FIXME funny runtime type check.
+	 * probably should be distinct packet types!
+	 */
+	req = (drbd_request_t *)(long)p->block_id;
+	if (req->w.cb == w_is_resync_read) {
+		pr  = (struct Pending_read *)(long)p->block_id;
+		req = NULL;
+		ERR_IF(!VALID_POINTER(pr)) return FALSE;
+		// XXX are enums unsigned by default?
+		ERR_IF((unsigned)pr->cause > AppAndResync) {
+			return FALSE;
+		}
+	} else {
+		pr  = NULL;
+		ERR_IF(!VALID_POINTER(req)) return FALSE;
+	}
 
-	// these would be BUG()s ...
-	ERR_IF(!VALID_POINTER(pr)) return FALSE;
 
-	// XXX are enums unsigned by default?
-	ERR_IF((unsigned)pr->cause > AppAndResync) {
-		return FALSE;
-	}
+	if (pr) {
+		/* RESYNC request
+		 */
+		/* Take it out of the list before calling the handler, since the
+		   handler could be changed by make_req as long as it is on the list
+		*/
+		spin_lock(&mdev->pr_lock);
+		list_del(&pr->w.list);
+		spin_unlock(&mdev->pr_lock);
 
-	/* Take it out of the list before calling the handler, since the
-	   handler could be changed by make_req as long as it is on the list
-	*/
-	spin_lock(&mdev->pr_lock);
-	list_del(&pr->w.list);
-	spin_unlock(&mdev->pr_lock);
+		// FIXME get rid of pr (at least its cause field) completely!
+		D_ASSERT(pr->cause == Resync);
 
-	ok = funcs[pr->cause](mdev,pr,sector,data_size);
-	INVALIDATE_MAGIC(pr);
-	mempool_free(pr,drbd_pr_mempool);
+		ok = funcs[pr->cause](mdev,pr,sector,data_size);
+		INVALIDATE_MAGIC(pr);
+		mempool_free(pr,drbd_pr_mempool);
+	} else {
+		/* "diskless" application READ request
+		 */
+		ok = recv_dless_read(mdev,req,sector,data_size);
+		INVALIDATE_MAGIC(req);
+		mempool_free(req,drbd_request_mempool);
+	}
 	return ok;
 }
 
@@ -1314,23 +1334,27 @@
 
 STATIC void drbd_fail_pending_reads(drbd_dev *mdev)
 {
-	struct Pending_read *pr;
 	struct list_head workset,*le;
 	drbd_bio_t *bio;
 
+	/*
+	 * Application READ requests
+	 */
 	spin_lock(&mdev->pr_lock);
-	list_add(&workset,&mdev->app_reads);
-	list_del(&mdev->app_reads);
-	INIT_LIST_HEAD(&mdev->app_reads);
+	list_add(&workset,&mdev->new_app_reads);
+	list_del(&mdev->new_app_reads);
+	INIT_LIST_HEAD(&mdev->new_app_reads);
 	spin_unlock(&mdev->pr_lock);
 
 	while(!list_empty(&workset)) {
+		drbd_request_t *req;
 		le = workset.next;
-		pr = list_entry(le, struct Pending_read, w.list);
+		req = list_entry(le, drbd_request_t, w.list);
 		list_del(le);
 
-		bio = pr->d.master_bio;
+		bio = req->master_bio;
 
+#if 0
 		switch(pr->cause) {
 		case Application:
 			dec_ap_pending(mdev,HERE);
@@ -1345,13 +1369,18 @@
 			break;
 		case Discard:;
 		}
+#endif
 
 		drbd_bio_IO_error(bio);
+		dec_ap_pending(mdev,HERE);
 
-		INVALIDATE_MAGIC(pr);
-		mempool_free(pr,drbd_pr_mempool);
+		INVALIDATE_MAGIC(req);
+		mempool_free(req,drbd_request_mempool);
 	}
 
+	/*
+	 * Resync READ requests
+	 */
 	spin_lock(&mdev->pr_lock);
 	list_add(&workset,&mdev->resync_reads);
 	list_del(&mdev->resync_reads);
@@ -1359,6 +1388,7 @@
 	spin_unlock(&mdev->pr_lock);
 
 	while(!list_empty(&workset)) {
+		struct Pending_read *pr;
 		le = workset.next;
 		list_del(le);
 		pr = list_entry(le, struct Pending_read, w.list);
===================================================================
RCS file: /var/lib/cvs/drbd/drbd/drbd/drbd_req-2.4.c,v
retrieving revision 1.33.2.54
retrieving revision 1.33.2.55
diff -u -3 -r1.33.2.54 -r1.33.2.55
--- drbd_req-2.4.c	11 Feb 2004 13:25:20 -0000	1.33.2.54
+++ drbd_req-2.4.c	16 Feb 2004 20:39:00 -0000	1.33.2.55
@@ -94,6 +94,7 @@
 		wake_asender(mdev);
 }
 
+#if 0
 STATIC struct Pending_read*
 drbd_find_read(sector_t sector, struct list_head *in)
 {
@@ -107,8 +108,10 @@
 
 	return NULL;
 }
+#endif
 
-STATIC void drbd_issue_drequest(struct Drbd_Conf* mdev,drbd_bio_t *bio)
+#if 0
+STATIC void drbd_issue_drequest___FIXME_broken_on_purpose_by_lge(struct Drbd_Conf* mdev,drbd_bio_t *bio)
 {
 	struct Pending_read *pr;
 	pr = mempool_alloc(drbd_pr_mempool, GFP_DRBD);
@@ -134,6 +137,24 @@
 			   (unsigned long)pr);
 #endif
 }
+#endif
+
+void drbd_read_remote(drbd_dev *mdev, drbd_request_t *req)
+{
+	drbd_bio_t *bio = req->master_bio;
+
+	spin_lock(&mdev->pr_lock);
+	list_add(&req->w.list,&mdev->new_app_reads);
+	spin_unlock(&mdev->pr_lock);
+	inc_ap_pending(mdev);
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0)
+	drbd_send_drequest(mdev, DataRequest, bio->b_rsector, bio->b_size,
+			   (unsigned long)req);
+#else
+	drbd_send_drequest(mdev, DataRequest, bio->bi_sector, bio->bi_size,
+			   (unsigned long)req);
+#endif
+}
 
 
 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,0)
@@ -158,110 +179,103 @@
 }
 #endif
 
-#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0)
-int drbd_make_request(request_queue_t *q, int rw, struct buffer_head *bio)
-#else
-int drbd_make_request(request_queue_t *q, struct bio *bio)
-#endif
+STATIC int
+drbd_make_request_common(drbd_dev *mdev, int rw, int size,
+			 sector_t sector, drbd_bio_t *bio)
 {
-	struct Drbd_Conf* mdev =
-#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0)
-		drbd_conf + MINOR(bio->b_rdev);
-#else
-		(drbd_dev*) q->queuedata;
-#endif
 	drbd_request_t *req;
-	int send_ok;
-	int sector, size;
-	ONLY_IN_26(int rw = bio_rw(bio);)
+	int local, remote;
+	int target_area_out_of_sync = FALSE; // only relevant for reads
 
-#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0)
-	if (MINOR(bio->b_rdev) >= minor_count || mdev->cstate < StandAlone) {
-		buffer_IO_error(bio);
+	/* allocate outside of all locks
+	 */
+	req = mempool_alloc(drbd_request_mempool, GFP_DRBD);
+	if (!req) {
+		ERR("could not kmalloc() req\n");
+		drbd_bio_IO_error(bio);
 		return 0;
 	}
+	SET_MAGIC(req);
+	req->master_bio = bio;
 
-#else
-	//#warning "FIXME"
-#endif
+	// XXX maybe merge both variants into one
+	if (rw == WRITE) drbd_req_prepare_write(mdev,req);
+	else             drbd_req_prepare_read(mdev,req);
 
-	/* what do we know?
+	/* XXX req->w.cb = something; drbd_queue_work() ....
+	 * Not yet.
 	 */
-#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0)
-	sector = bio->b_rsector;
-	size   = bio->b_size;
-#else
-	//      rw = bio->bi_rw & RW_MASK;
-	//      ra = bio->bi_rw & RWA_MASK;
-	      size = bio->bi_size;
-	    sector = bio->bi_sector;
-	/* barrier = bio_barrier(bio);
-	nr_sectors = bio_sectors(bio); */
-#endif
 
-	    
-	if( !inc_local(mdev) ) {
-		if( mdev->cstate < Connected ) {
-			drbd_bio_IO_error(bio);
-			return 0;
-		}
+	// down_read(mdev->device_lock);
 
-#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0)
-		if(!test_and_set_bit(WRITE_HINT_QUEUED,&mdev->flags)) {
-			queue_task(&mdev->write_hint_tq, &tq_disk); // IO HINT
-		}
-#else
-		spin_lock_irq(q->queue_lock);
-		if(!blk_queue_plugged(q)) {
-			blk_plug_device(q);
-			del_timer(&q->unplug_timer);
-			// unplugging should not happen automatically...
+	local = inc_local(mdev);
+	// FIXME special case handling of READA ??
+	if (rw == READ || rw == READA) {
+		if (local) {
+			target_area_out_of_sync =
+				(mdev->cstate == SyncTarget) &&
+				bm_get_bit(mdev->mbds_id,sector,size);
+			if (target_area_out_of_sync) {
+				/* whe could kick the syncer to
+				 * sync this extent asap, wait for
+				 * it, then continue locally.
+				 * Or just issue the request remotely.
+				 */
+				local = 0;
+				dec_local(mdev);
+			}
 		}
-		spin_unlock_irq(q->queue_lock);
-#endif
-
+		remote = !local;
+	} else {
+		remote = 1;
+	}
+	remote = remote && (mdev->cstate >= Connected)
+			&& !test_bit(PARTNER_DISKLESS,&mdev->flags);
+
+	if (!(local || remote)) {
+		ERR("IO ERROR: neither local nor remote disk\n");
+		// PANIC ??
+		drbd_bio_IO_error(bio);
+		return 0;
+	}
 
-		// Fail READA ??
-		if( rw == WRITE ) {
-			req = mempool_alloc(drbd_request_mempool, GFP_DRBD);
-
-			if (!req) {
-				ERR("could not kmalloc() req\n");
-				drbd_bio_IO_error(bio);
-				return 0;
-			}
-			SET_MAGIC(req);
+	/* THINK
+	 * maybe we need to
+	 *   if (rw == WRITE) drbd_al_begin_io(mdev, sector);
+	 * right here already?
+	 */
 
-			//WORK_HERE
-			/* FIXME the drbd_make_request function will be
-			 * restructured soon.
-			 * until that is the case,
-			 * at least put the mdev and sector number into the
-			 * private bh!
+	/* do this first, so I do not need to call drbd_end_req,
+	 * but can set the rq_status directly.
+	 */
+	if (!local)
+		req->rq_status |= RQ_DRBD_LOCAL;
+	if (!remote)
+		req->rq_status |= RQ_DRBD_SENT;
+
+	if (remote) {
+		/* either WRITE and Connected,
+		 * or READ, and no local disk,
+		 * or READ, but not in sync.
+		 */
+		drbd_plug_device(mdev);
+		if (rw == WRITE) {
+			/* Syncronization with the syncer is done
+			 * via drbd_[rs|al]_[begin|end]_io()
 			 */
-			req->master_bio = bio;
-			drbd_req_prepare_write(mdev,req);
-			req->rq_status  = RQ_DRBD_WRITTEN | 1;
-
 			if(mdev->conf.wire_protocol != DRBD_PROT_A) {
 				inc_ap_pending(mdev);
 			}
-			drbd_send_dblock(mdev,req); // FIXME error check?
-		} else { // rw == READ || rw == READA
-			drbd_issue_drequest(mdev,bio);
-		}
-		return 0; // Ok everything arranged
-	}
-
-	if ( mdev->cstate == SyncTarget &&
-	     bm_get_bit(mdev->mbds_id,sector,size) ) {
-		struct Pending_read *pr;
-		if( rw == WRITE ) {
-			// Actually nothing special to do.
-			// Just do a mirrored write.
-			// Syncronization with the syncer is done
-			// via drbd_[rs|al]_[begin|end]_io()
-		} else { // rw == READ || rw == READA
+			/* THINK drbd_send_dblock has a return value,
+			 * but we ignore it here. Is it actually void,
+			 * because error handling takes place elsewhere?
+			 */
+			drbd_send_dblock(mdev,req);
+		} else if (target_area_out_of_sync) {
+			#if 0
+			/* lge: I do not like this branch,
+			 * and it currently does not work anyways...
+			 */
 			spin_lock(&mdev->pr_lock);
 			pr=drbd_find_read(sector,&mdev->resync_reads);
 			if(pr) {
@@ -273,84 +287,63 @@
 				list_del(&pr->w.list);
 				list_add(&pr->w.list,&mdev->app_reads);
 				spin_unlock(&mdev->pr_lock);
-				return 0; // Ok everything arranged
+				/* Ok, everything arranged.
+				 * since reads are never done
+				 * on both nodes at the same time,
+				 * we just:
+				 */
+				// up_read(mdev->device_lock);
+				return 0;
 			}
-
 			spin_unlock(&mdev->pr_lock);
-			drbd_issue_drequest(mdev,bio);
-			return 0;
+			#endif
+			drbd_read_remote(mdev,req);
+		} else {
+			// this node is diskless ...
+			drbd_read_remote(mdev,req);
 		}
 	}
 
-	if( rw == READ || rw == READA ) {
-		mdev->read_cnt += size >> 9;
-		dec_local(mdev);  // FIXME TODO -> completion handler
-		/// TODO FIXME shoulbe be able to reissue the request to
-		/// the peer in case it fails locally.
-#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0)
-		bio->b_rdev  = mdev->backing_bdev;
-#else
-		bio->bi_bdev = mdev->backing_bdev;
-#endif
-		return 1; // Not arranged for transfer ( but remapped :)
+	if (local) {
+		if (rw == WRITE) {
+			drbd_al_begin_io(mdev, sector);
+			if (!remote) drbd_set_out_of_sync(mdev,sector,size);
+		} else {
+			D_ASSERT(!remote);
+		}
+		/* FIXME
+		 * Should we add even local reads to some list, so
+		 * they can be grabbed and freed somewhen?
+		 *
+		 * They already have a reference count (sort of...)
+		 * on mdev via inc_local()
+		 */
+		drbd_generic_make_request(rw,&req->private_bio);
 	}
 
-	mdev->writ_cnt += size >> 9;
-
-	if(mdev->cstate<Connected || test_bit(PARTNER_DISKLESS,&mdev->flags)) {
-		drbd_set_out_of_sync(mdev,sector,size);
+	// up_read(mdev->device_lock);
+	return 0;
+}
 
-		/* This should be changed. We should not remap in this 
-		   case !!!!! FIXME TODO FIXME TODO 
-		 */
-		drbd_al_begin_io(mdev, sector);
-		drbd_al_complete_io(mdev, sector); // FIXME TODO -> completion handler
-		dec_local(mdev);  // FIXME TODO -> completion handler
 #if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0)
-		bio->b_rdev  = mdev->backing_bdev;
-#else
-		bio->bi_bdev = mdev->backing_bdev;
-#endif
-		return 1; // Not arranged for transfer ( but remapped :)
+int drbd_make_request_24(request_queue_t *q, int rw, struct buffer_head *bh)
+{
+	struct Drbd_Conf* mdev = drbd_conf + MINOR(bh->b_rdev);
+	if (MINOR(bh->b_rdev) >= minor_count || mdev->cstate < StandAlone) {
+		buffer_IO_error(bh);
+		return 0;
 	}
 
-	// Now its clear that we have to do a mirrored write:
-
-	req = mempool_alloc(drbd_request_mempool, GFP_DRBD);
-
-	if (!req) {
-		ERR("could not kmalloc() req\n");
+	return drbd_make_request_common(mdev,rw,bh->b_size,bh->b_rsector,bh);
+}
+#else
+int drbd_make_request_26(request_queue_t *q, struct bio *bio)
+{
+	struct Drbd_Conf* mdev = (drbd_dev*) q->queuedata;
+	if (mdev->cstate < StandAlone) {
 		drbd_bio_IO_error(bio);
-		dec_local(mdev);
 		return 0;
 	}
-	SET_MAGIC(req);
-
-	req->master_bio = bio;
-	drbd_req_prepare_write(mdev,req);
-
-	send_ok=drbd_send_dblock(mdev,req);
-
-	// FIXME we could remove the send_ok cases, the are redundant to tl_clear()
-	if(send_ok && mdev->conf.wire_protocol!=DRBD_PROT_A) inc_ap_pending(mdev);
-	if(mdev->conf.wire_protocol==DRBD_PROT_A || (!send_ok) ) {
-				/* If sending failed, we can not expect
-				   an ack packet. */
-		drbd_end_req(req, RQ_DRBD_SENT, 1, drbd_req_get_sector(req));
-	}
-	if(!send_ok) drbd_set_out_of_sync(mdev,sector,size);
-
-NOT_IN_26(
-	if(!test_and_set_bit(WRITE_HINT_QUEUED,&mdev->flags)) {
-		queue_task(&mdev->write_hint_tq, &tq_disk);
-	}
-)
-
-	drbd_al_begin_io(mdev, drbd_req_get_sector(req));
-
-	drbd_generic_make_request(rw,&req->private_bio);
-
-	return 0; /* Ok, bh arranged for transfer */
-
+	return drbd_make_request_common(mdev,bio_rw(bio),bio->bi_size,bio->bi_sector,bio);
 }
-
+#endif