[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]

[dm-devel] [PATCH] Fixes for clone_bio and __clone_and_map functions in dm.c



Hi Alasdair and others,

I found a small bug in the clone_bio() function in dm.c . The number of bio
vectors in the cloned bio is incorrectly set to the index of the last bio
vector in its range. I have corrected it in the attached patch.

I encountered another problem in the final else condition of __clone_and_map()
function where the bio vector is split in to two parts. This is perhaps based
on the assumption that the next target can completely accomodate the bio
vector. However, I have encountered situations when this assumption can be
violated and have introduced a do-while loop to correct it.

Please review the attached patch and let me know if you need more information.

Thanks

Abhishek Gupta
2nd Year Graduate Student
Department of Computer Science, UBC.
Vancouver, Canada.


diff -uNr linux-2.6.15.6.vanilla/drivers/md/dm.c linux-2.6.15.6.new/drivers/md/dm.c
--- linux-2.6.15.6.vanilla/drivers/md/dm.c	2006-03-05 11:07:54.000000000 -0800
+++ linux-2.6.15.6.new/drivers/md/dm.c	2006-03-18 11:48:22.000000000 -0800
@@ -441,7 +441,7 @@
 	clone = bio_clone(bio, GFP_NOIO);
 	clone->bi_sector = sector;
 	clone->bi_idx = idx;
-	clone->bi_vcnt = idx + bv_count;
+	clone->bi_vcnt = bv_count;
 	clone->bi_size = to_bytes(len);
 	clone->bi_flags &= ~(1 << BIO_SEG_VALID);
 
@@ -501,30 +501,43 @@
 
 	} else {
 		/*
-		 * Create two copy bios to deal with io that has
+		 * Create multiple copies of bios to deal with io that has
 		 * been split across a target.
 		 */
+		unsigned int offset = 0;  
 		struct bio_vec *bv = bio->bi_io_vec + ci->idx;
+	
+		len = to_sector(bv->bv_len);
+		do {
+			if (len > max) {
+				clone = split_bvec(bio, ci->sector, ci->idx,
+						   bv->bv_offset + offset, max);
+			}
+			else {
+				clone = split_bvec(bio, ci->sector, ci->idx,
+						   bv->bv_offset + offset, len);
+                                /* Terminate do-while. */
+				max = len; 
+			}
+			
+			__map_bio(ti, clone, tio);
+	
+			ci->sector += max;
+			ci->sector_count -= max;
+	
+			len = len - max;
+			if (len > 0) {
+				offset += to_bytes(max);
+				ti = dm_table_find_target(ci->map, ci->sector);
+				max = max_io_len(ci->md, ci->sector, ti);
+
+				tio = alloc_tio(ci->md);
+				tio->io = ci->io;
+				tio->ti = ti;
+				memset(&tio->info, 0, sizeof(tio->info));
+			}
+		} while (len > 0);
 
-		clone = split_bvec(bio, ci->sector, ci->idx,
-				   bv->bv_offset, max);
-		__map_bio(ti, clone, tio);
-
-		ci->sector += max;
-		ci->sector_count -= max;
-		ti = dm_table_find_target(ci->map, ci->sector);
-
-		len = to_sector(bv->bv_len) - max;
-		clone = split_bvec(bio, ci->sector, ci->idx,
-				   bv->bv_offset + to_bytes(max), len);
-		tio = alloc_tio(ci->md);
-		tio->io = ci->io;
-		tio->ti = ti;
-		memset(&tio->info, 0, sizeof(tio->info));
-		__map_bio(ti, clone, tio);
-
-		ci->sector += len;
-		ci->sector_count -= len;
 		ci->idx++;
 	}
 }


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]