[DRBD-cvs] r1769 - trunk/drbd

www-data www-data at garcon.linbit.com
Thu Mar 17 14:05:18 CET 2005


Author: phil
Date: 2005-03-17 14:05:16 +0100 (Thu, 17 Mar 2005)
New Revision: 1769

Modified:
   trunk/drbd/drbd_compat_wrappers.h
   trunk/drbd/drbd_fs.c
   trunk/drbd/drbd_int.h
   trunk/drbd/drbd_receiver.c
   trunk/drbd/drbd_req.c
Log:
This fixes the last known open issue with the big BIO support.

* With drbd_merge_bvec() callback we tell the rest of the kernel
  that we do not like BIOs that cross our AL_EXTENT boundaries.
* I take into account that the device below us might have a 
  merge_bvec() function by itself, therefore we must provide
  the sector number before calling bio_add_page()
* biot_add_page() might fail! -- still open



Modified: trunk/drbd/drbd_compat_wrappers.h
===================================================================
--- trunk/drbd/drbd_compat_wrappers.h	2005-03-15 20:51:32 UTC (rev 1768)
+++ trunk/drbd/drbd_compat_wrappers.h	2005-03-17 13:05:16 UTC (rev 1769)
@@ -157,18 +157,14 @@
 }
 
 static inline void
-drbd_ee_prepare_write(drbd_dev *mdev, struct Tl_epoch_entry* e,
-		      sector_t sector)
+drbd_ee_prepare_write(drbd_dev *mdev, struct Tl_epoch_entry* e)
 {
-	e->ee_sector = e->private_bio->bi_sector = sector;
 	e->private_bio->bi_end_io = drbd_dio_end_sec;
 }
 
 static inline void
-drbd_ee_prepare_read(drbd_dev *mdev, struct Tl_epoch_entry* e,
-		     sector_t sector)
+drbd_ee_prepare_read(drbd_dev *mdev, struct Tl_epoch_entry* e)
 {
-	e->ee_sector = e->private_bio->bi_sector = sector;
 	e->private_bio->bi_end_io = enslaved_read_bi_end_io;
 }
 

Modified: trunk/drbd/drbd_fs.c
===================================================================
--- trunk/drbd/drbd_fs.c	2005-03-15 20:51:32 UTC (rev 1768)
+++ trunk/drbd/drbd_fs.c	2005-03-17 13:05:16 UTC (rev 1769)
@@ -382,6 +382,7 @@
 	q->hardsect_size     = max((unsigned short)512,b->hardsect_size);
 	q->seg_boundary_mask = PAGE_SIZE-1;
 	D_ASSERT(q->hardsect_size <= PAGE_SIZE); // or we are really screwed ;-)
+	blk_queue_merge_bvec(q, drbd_merge_bvec);
 #undef min_not_zero
 
 	set_bit(MD_IO_ALLOWED,&mdev->flags);

Modified: trunk/drbd/drbd_int.h
===================================================================
--- trunk/drbd/drbd_int.h	2005-03-15 20:51:32 UTC (rev 1768)
+++ trunk/drbd/drbd_int.h	2005-03-17 13:05:16 UTC (rev 1769)
@@ -1005,6 +1005,7 @@
 extern void drbd_end_req(drbd_request_t *, int, int, sector_t);
 extern int drbd_make_request_26(request_queue_t *q, struct bio *bio);
 extern int drbd_read_remote(drbd_dev *mdev, drbd_request_t *req);
+extern int drbd_merge_bvec(request_queue_t *, struct bio *, struct bio_vec *);
 
 // drbd_fs.c
 extern char* ppsize(char* buf, size_t size);
@@ -1038,6 +1039,7 @@
 // drbd_receiver.c
 extern int drbd_release_ee(drbd_dev* mdev,struct list_head* list);
 extern struct Tl_epoch_entry* drbd_alloc_ee(drbd_dev *mdev, 
+					    sector_t sector,
 					    unsigned int data_size,
 					    unsigned int gfp_mask);
 extern void drbd_free_ee(drbd_dev *mdev, struct Tl_epoch_entry* e);

Modified: trunk/drbd/drbd_receiver.c
===================================================================
--- trunk/drbd/drbd_receiver.c	2005-03-15 20:51:32 UTC (rev 1768)
+++ trunk/drbd/drbd_receiver.c	2005-03-17 13:05:16 UTC (rev 1769)
@@ -237,6 +237,7 @@
 */
 
 struct Tl_epoch_entry* drbd_alloc_ee(drbd_dev *mdev, 
+				     sector_t sector,
 				     unsigned int data_size,
 				     unsigned int gfp_mask)
 {
@@ -245,7 +246,7 @@
 	struct page *page;
 	struct bio *bio;
 	unsigned int ds;
-	int i;
+	int bio_add,i;
 
 	e = kmem_cache_alloc(drbd_ee_cache, gfp_mask);
 	if (!e) return NULL;
@@ -254,17 +255,20 @@
 	if (!bio) goto fail1;
 
 	bio->bi_bdev = mdev->backing_bdev;
-	
+	bio->bi_sector = sector;
+
 	ds = data_size;
 	while(ds) {
 		page = drbd_pp_alloc(mdev, gfp_mask);
 		if (!page) goto fail2;
-		bio_add_page(bio, page, min_t(int, ds, PAGE_SIZE), 0);
+		bio_add=bio_add_page(bio, page, min_t(int, ds, PAGE_SIZE), 0);
+		D_ASSERT(bio_add);
 		ds -= min_t(int, ds, PAGE_SIZE);
 	}
 
 	bio->bi_private = e;
 	e->mdev = mdev;
+	e->ee_sector = sector;
 	e->ee_size = bio->bi_size;
 	D_ASSERT( data_size == bio->bi_size);
 	e->private_bio = bio;
@@ -776,7 +780,7 @@
 }
 
 STATIC struct Tl_epoch_entry *
-read_in_block(drbd_dev *mdev, int data_size)
+read_in_block(drbd_dev *mdev, sector_t sector, int data_size)
 {
 	struct Tl_epoch_entry *e;
 	struct bio_vec *bvec;
@@ -784,7 +788,7 @@
 	struct bio *bio;
 	int ds,i,rr;
 
-	e = drbd_alloc_ee(mdev,data_size,GFP_KERNEL);
+	e = drbd_alloc_ee(mdev,sector,data_size,GFP_KERNEL);
 	if(!e) return 0;
 	bio = e->private_bio;
 	ds = data_size;
@@ -883,7 +887,7 @@
 {
 	struct Tl_epoch_entry *e;
 
-	e = read_in_block(mdev,data_size);
+	e = read_in_block(mdev,sector,data_size);
 	if(!e) return FALSE;
 
 	dec_rs_pending(mdev);
@@ -897,7 +901,7 @@
 		return TRUE;
 	}
 
-	drbd_ee_prepare_write(mdev,e,sector);
+	drbd_ee_prepare_write(mdev,e);
 	e->w.cb     = e_end_resync_block;
 
 	spin_lock_irq(&mdev->ee_lock);
@@ -1055,7 +1059,7 @@
 		return FALSE;
 
 	sector = be64_to_cpu(p->sector);
-	e = read_in_block(mdev,data_size);
+	e = read_in_block(mdev,sector,data_size);
 	if (!e) return FALSE;
 
 	if(!inc_local(mdev)) {
@@ -1067,7 +1071,7 @@
 	}
 
 	e->block_id = p->block_id; // no meaning on this side, e* on partner
-	drbd_ee_prepare_write(mdev, e, sector);
+	drbd_ee_prepare_write(mdev, e);
 	e->w.cb     = e_end_block;
 
 	/* This wait_event is here to make sure that never ever an
@@ -1201,7 +1205,7 @@
 		return FALSE;
 	}
 
-	e = drbd_alloc_ee(mdev,size,GFP_KERNEL);
+	e = drbd_alloc_ee(mdev,sector,size,GFP_KERNEL);
 	if (!e) return FALSE;
 
 	e->block_id = p->block_id; // no meaning on this side, pr* on partner
@@ -1217,7 +1221,7 @@
 		return TRUE;
 	}
 
-	drbd_ee_prepare_read(mdev,e,sector);
+	drbd_ee_prepare_read(mdev,e);
 
 	switch (h->command) {
 	case DataRequest:

Modified: trunk/drbd/drbd_req.c
===================================================================
--- trunk/drbd/drbd_req.c	2005-03-15 20:51:32 UTC (rev 1768)
+++ trunk/drbd/drbd_req.c	2005-03-17 13:05:16 UTC (rev 1769)
@@ -401,3 +401,32 @@
 	return drbd_make_request_common(mdev,bio_rw(bio),bio->bi_size,
 					bio->bi_sector,bio);
 }
+
+/* This is called by bio_add_page(). With this function we prevent
+   that we get BIOs that span over multiple AL_EXTENTs. 
+ */
+int drbd_merge_bvec(request_queue_t *q, struct bio *bio, struct bio_vec *bvec)
+{
+	unsigned int s = (unsigned int)bio->bi_sector << 9; // 32 bit...
+	unsigned int t;
+
+	if (bio->bi_size == 0) {
+		s = max_t(unsigned int,
+			  AL_EXTENT_SIZE - (s & (AL_EXTENT_SIZE-1)), 
+			  PAGE_SIZE);
+		// As long as the BIO is emtpy we allow at least one page.
+	} else {
+		t = s >> AL_EXTENT_SIZE_B;
+		s = (s + bio->bi_size);
+
+		if( s >> AL_EXTENT_SIZE_B != t ) {
+			s = 0;
+			// This BIO already spans over an AL_EXTENTs boundary.
+		} else {
+			s = AL_EXTENT_SIZE - ( s & (AL_EXTENT_SIZE-1) );
+			// Bytes to the next AL_EXTENT boundary.
+		}
+	}
+
+	return s;
+}



More information about the drbd-cvs mailing list