[DRBD-cvs] svn commit by lars - r2420 - trunk/drbd - get the "bio_split" calculation right again. it is obvi

drbd-cvs at lists.linbit.com drbd-cvs at lists.linbit.com
Wed Sep 13 23:46:17 CEST 2006


Author: lars
Date: 2006-09-13 23:46:16 +0200 (Wed, 13 Sep 2006)
New Revision: 2420

Modified:
   trunk/drbd/drbd_req.c
   trunk/drbd/drbd_req.h
Log:
get the "bio_split" calculation right again.
it is obvious, if you just do what you mean :-/

the condition to remove a req from the tl was wrong
(at least for the "never to occur" conflicting writes).
unconditionally list_del again, but make sure it was
INIT_LIST_HEAD()ed before, so it won't harm if it is
not on the transfer log.



Modified: trunk/drbd/drbd_req.c
===================================================================
--- trunk/drbd/drbd_req.c	2006-09-13 19:23:05 UTC (rev 2419)
+++ trunk/drbd/drbd_req.c	2006-09-13 21:46:16 UTC (rev 2420)
@@ -195,10 +195,13 @@
 		 * bit(s) out-of-sync first. If it had a local part, we need to
 		 * release the reference to the activity log. */
 		if (rw == WRITE) {
-			/* remove it from the transfer log.  well, only if it
-			 * had been there in the first place... */
-			if (s & RQ_NET_MASK)
-				list_del(&req->tl_requests);
+			/* remove it from the transfer log.
+			 * well, only if it had been there in the first
+			 * place... if it had not (local only or conflicting
+			 * and never sent), it should still be "empty" as
+			 * initialised in drbd_req_new(), so we can list_del() it
+			 * here unconditionally */
+			list_del(&req->tl_requests);
 			/* Set out-of-sync unless both OK flags are set 
 			 * (local only or remote failed).
 			 * Other places where we set out-of-sync:
@@ -1029,15 +1032,32 @@
 	 * only force allignment within AL_EXTENT boundaries */
 	s_enr = bio->bi_sector >> (AL_EXTENT_SIZE_B-9);
 	e_enr = (bio->bi_sector+(bio->bi_size>>9)-1) >> (AL_EXTENT_SIZE_B-9);
+	D_ASSERT(e_enr >= s_enr);
 #endif
-	D_ASSERT(e_enr >= s_enr);
 
 	if(unlikely(s_enr != e_enr)) {
 		/* This bio crosses some boundary, so we have to split it.
 		 * [So far, only XFS is known to do this...] */
 		struct bio_pair *bp;
+#if 1
+		/* works for the "do not cross hash slot boundaries" case
+		 * e.g. sector 262269, size 4096
+		 * s_enr = 262269 >> 6 = 4097
+		 * e_enr = (262269+8-1) >> 6 = 4098
+		 * HT_SHIFT = 6
+		 * sps = 64, mask = 63
+		 * first_sectors = 64 - (262269 & 63) = 3
+		 */
+		const sector_t sect = bio->bi_sector;
+		const int sps = 1<<HT_SHIFT; /* sectors per slot */
+		const int mask = sps -1;
+		const sector_t first_sectors = sps - (sect & mask);
+		bp = bio_split(bio, bio_split_pool, first_sectors);
+#else
+		/* works for the al-extent boundary case */
 		bp = bio_split(bio, bio_split_pool,
 			       (e_enr<<(AL_EXTENT_SIZE_B-9)) - bio->bi_sector);
+#endif
 		drbd_make_request_26(q,&bp->bio1);
 		drbd_make_request_26(q,&bp->bio2);
 		bio_pair_release(bp);
@@ -1068,7 +1088,11 @@
 	unsigned int bio_size = bio->bi_size;
 	int max;
 
+#if 1
+	max = DRBD_MAX_SEGMENT_SIZE - ((bio_offset & (DRBD_MAX_SEGMENT_SIZE-1)) + bio_size);
+#else
 	max = AL_EXTENT_SIZE - ((bio_offset & (AL_EXTENT_SIZE-1)) + bio_size);
+#endif
 	if (max < 0) max = 0;
 	if (max <= bvec->bv_len && bio_size == 0)
 		return bvec->bv_len;

Modified: trunk/drbd/drbd_req.h
===================================================================
--- trunk/drbd/drbd_req.h	2006-09-13 19:23:05 UTC (rev 2419)
+++ trunk/drbd/drbd_req.h	2006-09-13 21:46:16 UTC (rev 2420)
@@ -273,6 +273,7 @@
 		req->sector      = bio->bi_sector;
 		req->size        = bio->bi_size;
 		INIT_HLIST_NODE(&req->colision);
+		INIT_LIST_HEAD(&req->tl_requests);
 
 		bio->bi_private  = req;
 		bio->bi_end_io   = drbd_endio_pri;



More information about the drbd-cvs mailing list