[DRBD-cvs] drbd by phil; * Noticed by the way that is_syncer_blk(...

drbd-user@lists.linbit.com drbd-user@lists.linbit.com
Thu, 11 Mar 2004 14:50:22 +0100 (CET)


DRBD CVS committal

Author  : phil
Module  : drbd

Dir     : drbd/drbd


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


Log Message:
* Noticed by the way that is_syncer_blk() was broken for the longest 
  time. Now it works again, since we use ID_SYNCER again.

* Removed struct Pending_read. Got obsoleted by the resync_lru
  and other means.

* Introduced RSDataReply and NegRSDReply packets.

* Much nicer receive_DataReply() and receive_RSDataReply() functions.

* New drbd_rs_cancel_all() function that removes a locks from the 
  resync_lru. [untested]

* got_NegDReply() missed to do a drbd_rs_complete_io(). Now there is
  a new got_NegRSDReply() which handles this right.

This patch removes more than it adds, thus it is a good thing. Of
course it might add some new bugs, but on the other hand it
might even cure strange bugs since is_syncer_blk() works now
again. 

===================================================================
RCS file: /var/lib/cvs/drbd/drbd/drbd/Attic/drbd_actlog.c,v
retrieving revision 1.1.2.76
retrieving revision 1.1.2.77
diff -u -3 -r1.1.2.76 -r1.1.2.77
--- drbd_actlog.c	7 Mar 2004 17:57:25 -0000	1.1.2.76
+++ drbd_actlog.c	11 Mar 2004 13:50:16 -0000	1.1.2.77
@@ -123,7 +123,7 @@
 	if (unlikely(bm_ext!=NULL)) {
 		if(test_bit(BME_NO_WRITES,&bm_ext->flags)) {
 			spin_unlock_irq(&mdev->al_lock);
-			INFO("Delaying app write until sync read is done\n");
+			//INFO("Delaying app write until sync read is done\n");
 			return 0;
 		}
 	}
@@ -722,10 +722,11 @@
 	}
 	spin_unlock_irq(&mdev->al_lock);
 
+	/*
 	if(unlikely(rv)) {
 		INFO("Delaying sync read until app's write is done\n");
 	}
-
+	*/
 	return rv;
 }
 
@@ -774,3 +775,27 @@
 	spin_unlock_irq(&mdev->al_lock);
 }
 
+/**
+ * drbd_rs_cancel_all: Removes extents from the resync LRU. Even
+ * if they are BME_LOCKED.
+ */
+void drbd_rs_cancel_all(drbd_dev* mdev)
+{
+	struct bm_extent* bm_ext;
+	int i;
+
+	spin_lock_irq(&mdev->al_lock);
+
+	for(i=0;i<mdev->resync->nr_elements;i++) {
+		bm_ext = (struct bm_extent*) lc_entry(mdev->resync,i);
+		if(bm_ext->lce.lc_number == LC_FREE) continue;
+		bm_ext->lce.refcnt = 0; // Rude but ok.
+		bm_ext->rs_left = 0;
+		clear_bit(BME_LOCKED,&bm_ext->flags);
+		clear_bit(BME_NO_WRITES,&bm_ext->flags);
+		lc_del(mdev->resync,&bm_ext->lce);
+	}
+
+	wake_up(&mdev->al_wait);
+	spin_unlock_irq(&mdev->al_lock);	
+}
===================================================================
RCS file: /var/lib/cvs/drbd/drbd/drbd/Attic/drbd_compat_wrappers.h,v
retrieving revision 1.1.2.33
retrieving revision 1.1.2.34
diff -u -3 -r1.1.2.33 -r1.1.2.34
--- drbd_compat_wrappers.h	7 Mar 2004 11:49:23 -0000	1.1.2.33
+++ drbd_compat_wrappers.h	11 Mar 2004 13:50:16 -0000	1.1.2.34
@@ -77,16 +77,6 @@
 	return ee->private_bio.b_size;
 }
 
-static inline sector_t drbd_pr_get_sector(struct Pending_read *pr)
-{
-	return pr->d.master_bio->b_rsector;
-}
-
-static inline short drbd_bio_get_size(struct buffer_head *bh)
-{
-	return bh->b_size;
-}
-
 static inline char *drbd_bio_kmap(struct buffer_head *bh)
 {
 	return bh_kmap(bh);
@@ -357,21 +347,6 @@
 static inline unsigned short drbd_ee_get_size(struct Tl_epoch_entry *ee)
 {
 	return ee->ee_size;
-}
-
-static inline sector_t drbd_pr_get_sector(struct Pending_read *pr)
-{
-	return pr->d.master_bio->bi_sector;
-}
-
-/* this is valid, since the only place where it is used is in recv_both_read,
- * on the untouched master_bio of the Pending_read.
- * DO NOT use it for anything but an untouched bio,
- * bi_size is mutable, see bio_endio()
- */
-static inline short drbd_bio_get_size(struct bio *bio)
-{
-	return bio->bi_size;
 }
 
 #ifdef CONFIG_HIGHMEM
===================================================================
RCS file: /var/lib/cvs/drbd/drbd/drbd/Attic/drbd_dsender.c,v
retrieving revision 1.1.2.83
retrieving revision 1.1.2.84
diff -u -3 -r1.1.2.83 -r1.1.2.84
--- drbd_dsender.c	7 Mar 2004 20:17:18 -0000	1.1.2.83
+++ drbd_dsender.c	11 Mar 2004 13:50:16 -0000	1.1.2.84
@@ -398,7 +398,6 @@
 
 int w_make_resync_request(drbd_dev* mdev, struct drbd_work* w)
 {
-	struct Pending_read *pr;
 	sector_t sector;
 	int number,i,size;
 
@@ -419,18 +418,12 @@
 	}
 
 	for(i=0;i<number;i++) {
-		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;
 		sector = bm_get_sector(mdev->mbds_id,&size);
 
 		if (sector == MBDS_DONE) {
-			INVALIDATE_MAGIC(pr);
-			mempool_free(pr,drbd_pr_mempool);
 			mdev->resync_work.cb = w_resync_inactive;
 			return 1;
 		}
@@ -442,15 +435,9 @@
 			goto next_sector;
 		}
 
-		pr->d.sector = sector;
-		pr->cause = Resync;
-		spin_lock(&mdev->pr_lock);
-		list_add(&pr->w.list,&mdev->resync_reads);
-		spin_unlock(&mdev->pr_lock);
-
 		inc_rs_pending(mdev);
 		ERR_IF(!drbd_send_drequest(mdev,RSDataRequest,
-					   sector,size,(unsigned long)pr)) {
+					   sector,size,ID_SYNCER)) {
 			dec_rs_pending(mdev,HERE);
 			return 0; // FAILED. worker will abort!
 		}
@@ -527,9 +514,9 @@
 
 	if(likely(drbd_bio_uptodate(&e->private_bio))) {
 		inc_rs_pending(mdev);
-		ok=drbd_send_block(mdev, DataReply, e);
+		ok=drbd_send_block(mdev, RSDataReply, e);
 	} else {
-		ok=drbd_send_ack(mdev,NegDReply,e);
+		ok=drbd_send_ack(mdev,NegRSDReply,e);
 		ERR("Sending NegDReply. I guess it gets messy.\n");
 		drbd_io_error(mdev);
 	}
===================================================================
RCS file: /var/lib/cvs/drbd/drbd/drbd/drbd_int.h,v
retrieving revision 1.58.2.136
retrieving revision 1.58.2.137
diff -u -3 -r1.58.2.136 -r1.58.2.137
--- drbd_int.h	8 Mar 2004 07:38:01 -0000	1.58.2.136
+++ drbd_int.h	11 Mar 2004 13:50:16 -0000	1.58.2.137
@@ -282,7 +282,8 @@
 
 typedef enum {
 	Data,
-	DataReply,
+	DataReply,     // Response to DataRequest
+	RSDataReply,   // Response to RSDataRequest
 	Barrier,
 	ReportParams,
 	ReportBitMap,
@@ -299,6 +300,7 @@
 	WriteAck,     // Used in protocol C
 	NegAck,       // Sent if local disk is unusable
 	NegDReply,    // Local disk is broken...
+	NegRSDReply,  // Local disk is broken...
 	BarrierAck,
 
 	MAX_CMD,
@@ -311,6 +313,7 @@
 	static const char *cmdnames[] = {
 		[Data]             = "Data",
 		[DataReply]        = "DataReply",
+		[RSDataReply]      = "RSDataReply",
 		[Barrier]          = "Barrier",
 		[ReportParams]     = "ReportParams",
 		[ReportBitMap]     = "ReportBitMap",
@@ -326,6 +329,7 @@
 		[WriteAck]         = "WriteAck",
 		[NegAck]           = "NegAck",
 		[NegDReply]        = "NegDReply",
+		[NegRSDReply]      = "NegRSDReply",
 		[BarrierAck]       = "BarrierAck"
 	};
 
@@ -536,21 +540,6 @@
 	ONLY_IN_26(struct bio_vec ee_bvec;)
 };
 
-struct Pending_read {
-	struct drbd_work w;
-	long magic;
-	union {
-		drbd_bio_t *master_bio;
-		sector_t sector;
-	} d;
-	enum {
-		Discard = 0,        // unused now.
-		Application = 1,
-		Resync = 2,
-		AppAndResync = 3,
-	} cause;
-};
-
 // bitfield? enum?
 /* flag bits */
 #define ISSUE_BARRIER      0
@@ -583,7 +572,7 @@
 
 struct bm_extent { // 16MB sized extents.
 	struct lc_element lce;
-	int rs_left; //number of sectors our of sync in this extent.
+	int rs_left; //number of sectors out of sync in this extent.
 	unsigned long flags;
 };
 
@@ -816,10 +805,8 @@
 extern drbd_dev *drbd_conf;
 extern int minor_count;
 extern kmem_cache_t *drbd_request_cache;
-extern kmem_cache_t *drbd_pr_cache;
 extern kmem_cache_t *drbd_ee_cache;
 extern mempool_t *drbd_request_mempool;
-extern mempool_t *drbd_pr_mempool;
 
 // drbd_req
 #define ERF_NOTLD    2   /* do not call tl_dependence */
@@ -859,10 +846,6 @@
 extern int drbd_init_ee(drbd_dev* mdev);
 extern void drbd_put_ee(drbd_dev* mdev,struct Tl_epoch_entry *e);
 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, drbd_request_t *req,
-			   sector_t sector, int data_size);
 
 // drbd_proc.c
 extern struct proc_dir_entry *drbd_proc;
@@ -873,6 +856,7 @@
 extern void drbd_al_complete_io(struct Drbd_Conf *mdev, sector_t sector);
 extern void drbd_rs_complete_io(struct Drbd_Conf *mdev, sector_t sector);
 extern void drbd_rs_begin_io(struct Drbd_Conf *mdev, sector_t sector);
+extern void drbd_rs_cancel_all(drbd_dev* mdev);
 extern void drbd_al_read_log(struct Drbd_Conf *mdev);
 extern void drbd_set_in_sync(drbd_dev* mdev, sector_t sector,int blk_size);
 extern void drbd_read_bm(struct Drbd_Conf *mdev);
===================================================================
RCS file: /var/lib/cvs/drbd/drbd/drbd/drbd_main.c,v
retrieving revision 1.73.2.144
retrieving revision 1.73.2.145
diff -u -3 -r1.73.2.144 -r1.73.2.145
--- drbd_main.c	9 Mar 2004 16:28:42 -0000	1.73.2.144
+++ drbd_main.c	11 Mar 2004 13:50:16 -0000	1.73.2.145
@@ -113,10 +113,8 @@
 )
 struct Drbd_Conf *drbd_conf;
 kmem_cache_t *drbd_request_cache;
-kmem_cache_t *drbd_pr_cache;
 kmem_cache_t *drbd_ee_cache;
 mempool_t *drbd_request_mempool;
-mempool_t *drbd_pr_mempool;
 
 STATIC struct block_device_operations drbd_ops = {
 #if LINUX_VERSION_CODE > KERNEL_VERSION(2,4,10)
@@ -1130,25 +1128,18 @@
 
 void drbd_destroy_mempools(void)
 {
-	if (drbd_pr_mempool)
-		mempool_destroy(drbd_pr_mempool);
 	if (drbd_request_mempool)
 		mempool_destroy(drbd_request_mempool);
 	if (drbd_ee_cache && kmem_cache_destroy(drbd_ee_cache))
 		printk(KERN_ERR DEVICE_NAME
 		       ": kmem_cache_destroy(drbd_ee_cache) FAILED\n");
-	if (drbd_pr_cache && kmem_cache_destroy(drbd_pr_cache))
-		printk(KERN_ERR DEVICE_NAME
-		       ": kmem_cache_destroy(drbd_pr_cache) FAILED\n");
 	if (drbd_request_cache && kmem_cache_destroy(drbd_request_cache))
 		printk(KERN_ERR DEVICE_NAME
 		       ": kmem_cache_destroy(drbd_request_cache) FAILED\n");
 	// FIXME what can we do if we fail to destroy them?
 
-	drbd_pr_mempool      = NULL;
 	drbd_request_mempool = NULL;
 	drbd_ee_cache        = NULL;
-	drbd_pr_cache        = NULL;
 	drbd_request_cache   = NULL;
 
 	return;
@@ -1157,10 +1148,8 @@
 int drbd_create_mempools(void)
 {
 	// prepare our caches and mempools
-	drbd_pr_mempool      = NULL;
 	drbd_request_mempool = NULL;
 	drbd_ee_cache        = NULL;
-	drbd_pr_cache        = NULL;
 	drbd_request_cache   = NULL;
 
 	// caches
@@ -1170,12 +1159,6 @@
 	if (drbd_request_cache == NULL)
 		goto Enomem;
 
-	drbd_pr_cache = kmem_cache_create(
-		"drbd_pr_cache", sizeof(struct Pending_read),
-		0, SLAB_NO_REAP, NULL, NULL);
-	if (drbd_pr_cache == NULL)
-		goto Enomem;
-
 	drbd_ee_cache = kmem_cache_create(
 		"drbd_ee_cache", sizeof(struct Tl_epoch_entry),
 		0, SLAB_NO_REAP, NULL, NULL);
@@ -1186,11 +1169,6 @@
 	drbd_request_mempool = mempool_create(16, //TODO; reasonable value
 		mempool_alloc_slab, mempool_free_slab, drbd_request_cache);
 	if (drbd_request_mempool == NULL)
-		goto Enomem;
-
-	drbd_pr_mempool = mempool_create(16, //TODO; reasonable value
-		mempool_alloc_slab, mempool_free_slab, drbd_pr_cache);
-	if (drbd_pr_mempool == NULL)
 		goto Enomem;
 
 		return 0;
===================================================================
RCS file: /var/lib/cvs/drbd/drbd/drbd/drbd_receiver.c,v
retrieving revision 1.97.2.122
retrieving revision 1.97.2.123
diff -u -3 -r1.97.2.122 -r1.97.2.123
--- drbd_receiver.c	8 Mar 2004 10:43:19 -0000	1.97.2.122
+++ drbd_receiver.c	11 Mar 2004 13:50:16 -0000	1.97.2.123
@@ -752,8 +752,8 @@
 	mdev->writ_cnt+=data_size>>9;
 }
 
-int recv_dless_read(drbd_dev *mdev, drbd_request_t *req,
-		    sector_t sector, int data_size)
+STATIC int recv_dless_read(drbd_dev *mdev, drbd_request_t *req,
+			   sector_t sector, int data_size)
 {
 	drbd_bio_t *bio;
 	int ok,rr;
@@ -791,13 +791,10 @@
 	return ok;
 }
 
-int recv_resync_read(drbd_dev *mdev, struct Pending_read *pr,
-		     sector_t sector, int data_size)
+STATIC int recv_resync_read(drbd_dev *mdev,sector_t sector, int data_size)
 {
 	struct Tl_epoch_entry *e;
 
-	D_ASSERT( pr->d.sector == sector);
-
 	e = read_in_block(mdev,data_size);
 	ERR_IF(!e) return FALSE;
 
@@ -828,81 +825,51 @@
 	return TRUE;
 }
 
-int recv_both_read(drbd_dev *mdev, struct Pending_read *pr,
-		   sector_t sector, int data_size)
+STATIC int receive_DataReply(drbd_dev *mdev,Drbd_Header* h)
 {
-	struct Tl_epoch_entry *e;
-	drbd_bio_t *bio;
-
-	ERR("should not happen anymore%s\n", __func__);
-
-	bio = pr->d.master_bio;
-
-	D_ASSERT( sector == drbd_pr_get_sector(pr) );
-
-	e = read_in_block(mdev,data_size);
+	drbd_request_t *req;
+	sector_t sector;
+	unsigned int header_size,data_size;
+	int ok;
+	Drbd_Data_Packet *p = (Drbd_Data_Packet*)h;
 
-	if (!e) {
-		drbd_bio_IO_error(bio);
-		return FALSE;
-	}
+	header_size = sizeof(*p) - sizeof(*h);
+	data_size   = h->length  - header_size;
 
-	// Do not use data_size in the memcpy. The app read might be smaller.
-	/* XXX for exactly this reason: maybe don't memcpy at all, but first
-	 * write it to disk, and only then propagate the read to upper layers?
-	 * the next app read might target the very same region!
+	/* I expect a block to be a multiple of 512 byte, and
+	 * no more than 4K (8K). is this too restrictive?
 	 */
-	memcpy(drbd_bio_kmap(bio),drbd_bio_kmap(&e->private_bio),
-	       drbd_bio_get_size(bio));
-	drbd_bio_kunmap(bio);
-	drbd_bio_kunmap(&e->private_bio);
-
-	drbd_bio_endio(bio,1); // propagate success for application read
+	ERR_IF(data_size == 0) return FALSE;
+	ERR_IF(data_size &  0xff) return FALSE;
+	ERR_IF(data_size >  PAGE_SIZE) return FALSE;
 
-	dec_rs_pending(mdev,HERE);
-	dec_ap_pending(mdev,HERE);
+	if (drbd_recv(mdev, h->payload, header_size) != header_size)
+		return FALSE;
 
-	if(!inc_local(mdev)) {
-		ERR("Can not write resync data to local disk.\n");
-		drbd_send_ack(mdev,NegAck,e);
-		spin_lock_irq(&mdev->ee_lock);
-		drbd_put_ee(mdev,e);
-		spin_unlock_irq(&mdev->ee_lock);
-		return TRUE;
-	}
+	sector = be64_to_cpu(p->sector);
 
-	drbd_ee_prepare_write(mdev, e, sector, data_size);
-	e->block_id = ID_SYNCER;
-	e->w.cb     = e_end_resync_block;
+	req = (drbd_request_t *)(long)p->block_id;
+	D_ASSERT(req->w.cb == w_is_app_read);
 
-	spin_lock_irq(&mdev->ee_lock);
-	list_add(&e->w.list,&mdev->sync_ee);
-	spin_unlock_irq(&mdev->ee_lock);
+	spin_lock(&mdev->pr_lock);
+	list_del(&req->w.list);
+	spin_unlock(&mdev->pr_lock);
 
-	inc_unacked(mdev);
+	ok = recv_dless_read(mdev,req,sector,data_size);
 
-	drbd_generic_make_request(WRITE,&e->private_bio);
+	INVALIDATE_MAGIC(req);
+	mempool_free(req,drbd_request_mempool);
 
-	receive_data_tail(mdev,data_size);
-	return TRUE;
+	return ok;
 }
 
-STATIC int receive_DataReply(drbd_dev *mdev,Drbd_Header* h)
+STATIC int receive_RSDataReply(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;
 	Drbd_Data_Packet *p = (Drbd_Data_Packet*)h;
 
-	static int (*funcs[])(struct Drbd_Conf* , struct Pending_read*,
-			      sector_t,int) = {
-			      [Application]  = NULL,  /* recv_dless_read, */
-			      [Resync]       = recv_resync_read,
-			      [AppAndResync] = recv_both_read
-		      };
-
 	header_size = sizeof(*p) - sizeof(*h);
 	data_size   = h->length  - header_size;
 
@@ -917,48 +884,10 @@
 		return FALSE;
 
 	sector = be64_to_cpu(p->sector);
+	D_ASSERT(p->block_id == ID_SYNCER);
 
-	/* 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;
-	}
-
+	ok = recv_resync_read(mdev,sector,data_size);
 
-	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);
-
-		// 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);
-	} 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;
 }
 
@@ -1372,52 +1301,12 @@
 
 		bio = req->master_bio;
 
-#if 0
-		switch(pr->cause) {
-		case Application:
-			dec_ap_pending(mdev,HERE);
-			break;
-		case AppAndResync:
-			dec_ap_pending(mdev,HERE);
-			dec_rs_pending(mdev,HERE);
-			drbd_rs_complete_io(mdev,drbd_pr_get_sector(pr));
-			break;
-		case Resync:
-			ERR("pr with cause 'Resync' on app_reads list.");
-			break;
-		case Discard:;
-		}
-#endif
-
 		drbd_bio_IO_error(bio);
 		dec_ap_pending(mdev,HERE);
 
 		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);
-	INIT_LIST_HEAD(&mdev->resync_reads);
-	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);
-
-		D_ASSERT(pr->cause == Resync);
-		dec_rs_pending(mdev,HERE);
-		drbd_rs_complete_io(mdev,pr->d.sector);
-
-		mempool_free(pr,drbd_pr_mempool);
-		INVALIDATE_MAGIC(pr);
-	}
 }
 
 STATIC int receive_skip(drbd_dev *mdev,Drbd_Header *h)
@@ -1471,6 +1360,7 @@
 static drbd_cmd_handler_f drbd_default_handler[] = {
 	[Data]             = receive_Data,
 	[DataReply]        = receive_DataReply,
+	[RSDataReply]      = receive_RSDataReply,
 	[RecvAck]          = NULL, //receive_RecvAck,
 	[WriteAck]         = NULL, //receive_WriteAck,
 	[Barrier]          = receive_Barrier,
@@ -1552,6 +1442,7 @@
 		set_cstate(mdev,Unconnected);
 
 	drbd_fail_pending_reads(mdev);
+	drbd_rs_cancel_all(mdev);
 
 	tl_clear(mdev);
 	clear_bit(ISSUE_BARRIER,&mdev->flags);
@@ -1707,21 +1598,39 @@
 
 STATIC int got_NegDReply(drbd_dev *mdev, Drbd_Header* h)
 {
-	struct Pending_read *pr;
+	drbd_request_t *req;
 	Drbd_BlockAck_Packet *p = (Drbd_BlockAck_Packet*)h;
 
-	pr = (struct Pending_read *)(long)p->block_id;
-	ERR_IF(!VALID_POINTER(pr)) return FALSE;
+	req = (drbd_request_t *)(long)p->block_id;
+	D_ASSERT(req->w.cb == w_is_app_read);
 
 	spin_lock(&mdev->pr_lock);
-	list_del(&pr->w.list);
+	list_del(&req->w.list);
 	spin_unlock(&mdev->pr_lock);
 
+	INVALIDATE_MAGIC(req);
+	mempool_free(req,drbd_request_mempool);
+
 	ERR("Get NegDReply. WE ARE LOST. We lost our up-to-date disk.\n");
 	// TODO: Do something like panic() or shut_down_cluster(). 
 	return TRUE;
 }
 
+STATIC int got_NegRSDReply(drbd_dev *mdev, Drbd_Header* h)
+{
+	sector_t sector;
+	Drbd_BlockAck_Packet *p = (Drbd_BlockAck_Packet*)h;
+
+	sector = be64_to_cpu(p->sector);
+	D_ASSERT(p->block_id == ID_SYNCER);
+
+	drbd_rs_complete_io(mdev,sector);
+
+	ERR("Get NegRSDReply. WE ARE LOST. We lost our up-to-date disk.\n");
+	// TODO: Do something like panic() or shut_down_cluster(). 
+	return TRUE;
+}
+
 STATIC int got_BarrierAck(drbd_dev *mdev, Drbd_Header* h)
 {
 	Drbd_BarrierAck_Packet *p = (Drbd_BarrierAck_Packet*)h;
@@ -1757,6 +1666,7 @@
 		[WriteAck]  ={ sizeof(Drbd_BlockAck_Packet),  got_BlockAck },
 		[NegAck]    ={ sizeof(Drbd_BlockAck_Packet),  got_NegAck },
 		[NegDReply] ={ sizeof(Drbd_BlockAck_Packet),  got_NegDReply },
+		[NegRSDReply]={sizeof(Drbd_BlockAck_Packet),  got_NegRSDReply},
 		[BarrierAck]={ sizeof(Drbd_BarrierAck_Packet),got_BarrierAck },
 	};
 
===================================================================
RCS file: /var/lib/cvs/drbd/drbd/drbd/drbd_req-2.4.c,v
retrieving revision 1.33.2.57
retrieving revision 1.33.2.58
diff -u -3 -r1.33.2.57 -r1.33.2.58
--- drbd_req-2.4.c	18 Feb 2004 15:42:32 -0000	1.33.2.57
+++ drbd_req-2.4.c	11 Mar 2004 13:50:17 -0000	1.33.2.58
@@ -97,51 +97,6 @@
 		wake_asender(mdev);
 }
 
-#if 0
-STATIC struct Pending_read*
-drbd_find_read(sector_t sector, struct list_head *in)
-{
-	struct list_head *le;
-	struct Pending_read *pr;
-
-	list_for_each(le,in) {
-		pr = list_entry(le, struct Pending_read, w.list);
-		if(pr->d.sector == sector) return pr;
-	}
-
-	return NULL;
-}
-#endif
-
-#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);
-
-	if (!pr) {
-		ERR("could not kmalloc() pr\n");
-		drbd_bio_IO_error(bio);
-		return;
-	}
-	SET_MAGIC(pr);
-
-	pr->d.master_bio = bio;
-	pr->cause = Application;
-	spin_lock(&mdev->pr_lock);
-	list_add(&pr->w.list,&mdev->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)pr);
-#else
-	drbd_send_drequest(mdev, DataRequest, bio->bi_sector, bio->bi_size,
-			   (unsigned long)pr);
-#endif
-}
-#endif
-
 void drbd_read_remote(drbd_dev *mdev, drbd_request_t *req)
 {
 	drbd_bio_t *bio = req->master_bio;