[Tux3] Patch: Use negative seg count to indicate read hole

Daniel Phillips phillips at phunq.net
Tue Dec 16 15:23:42 PST 2008


Whoops, I forgot to delete the loop over segs from tux3_get_block,
which would have oopsed on a hole.  Instead, tux3_get_block just
asks for a single segment from get_segs, and we expect get_segs to
make that segment as long as it can.

diff -r 3193c496333d user/kernel/filemap.c
--- a/user/kernel/filemap.c	Mon Dec 15 22:35:29 2008 -0800
+++ b/user/kernel/filemap.c	Tue Dec 16 15:19:28 2008 -0800
@@ -9,7 +9,7 @@
 #define trace trace_on
 #endif
 
-struct seg { block_t block; unsigned count; };
+struct seg { block_t block; int count; };
 
 int get_segs(struct inode *inode, block_t start, unsigned limit, struct seg seg[], unsigned max_segs, int write)
 {
@@ -55,7 +55,6 @@
 			trace("emit %Lx/%x", (L)extent_block(*next_extent), extent_count(*next_extent));
 			seg[segs++] = (struct seg){ extent_block(*next_extent), extent_count(*next_extent) };
 
-
 			unsigned count = extent_count(*next_extent);
 			if (start > dwalk_index(walk))
 				count -= start - dwalk_index(walk);
@@ -85,7 +84,7 @@
 
 			/* there is gap, so stop */
 			if (!write) {
-				seg[segs++] = (struct seg){ 0, gap };
+				seg[segs++] = (struct seg){ .count = -gap };
 				break;
 			}
 
@@ -214,7 +213,9 @@
 
 	int err = 0;
 	for (int i = 0, index = start; !err && index < limit; i++) {
-		unsigned count = seg[i].count;
+		int count = seg[i].count, hole = count < 0;
+		if (hole)
+			count = -count;
 		trace_on("extent 0x%Lx/%x => %Lx", (L)index, count, (L)seg[i].block);
 		for (int j = 0; !err && j < count; j++) {
 			block_t block = seg[i].block + j;
@@ -223,7 +224,7 @@
 			if (write) {
 				err = diskwrite(dev->fd, bufdata(buffer), sb->blocksize, block << dev->bits);
 			} else {
-				if (!block) { /* block zero is never allocated */
+				if (hole) {
 					trace("zero fill buffer");
 					memset(bufdata(buffer), 0, sb->blocksize);
 					continue;
@@ -245,33 +246,29 @@
 
 	struct sb *sbi = tux_sb(inode->i_sb);
 	size_t max_blocks = bh_result->b_size >> inode->i_blkbits;
-	int depth = tux_inode(inode)->btree.root.depth, i;
+	int depth = tux_inode(inode)->btree.root.depth;
 	if (!depth) {
 		trace("unmapped block %Lx", (L)iblock);
 		return 0;
 	}
 
 	block_t start = iblock, limit = iblock + max_blocks;
-	struct seg seg[10];
-	int segs = get_segs(inode, start, limit, seg, ARRAY_SIZE(seg), write);
+	struct seg seg;
+	int segs = get_segs(inode, start, limit, &seg, 1, write);
 	if (segs < 0) {
 		warn("get_segs failed: %d", -segs);
 		return -EIO;
 	}
-	block_t block = seg[0].block;
-	size_t count = seg[0].count;
-	for (i = 1; i < segs; i++) {
-		if (block + count != seg[i].block)
-			break;
-		count += seg[i].count;
-	}
-	if (block) {
-		unsigned blocks = min(max_blocks, count);
+	block_t block = seg.block;
+	int count = seg.count;
+	if (count < 0)
+		set_buffer_uptodate(bh_result);
+	else {
+		unsigned blocks = min(max_blocks, (unsigned)count);
 		map_bh(bh_result, inode->i_sb, block);
 		bh_result->b_size = blocks << sbi->blockbits;
 		inode->i_blocks += blocks << (sbi->blockbits - 9);
-	} else
-		set_buffer_new(bh_result);
+	}
 	trace("<== inum %Lu, mapped %d, block %Lu, size %zu",
 	      (L)tux_inode(inode)->inum, buffer_mapped(bh_result),
 	      (L)bh_result->b_blocknr, bh_result->b_size);

_______________________________________________
Tux3 mailing list
Tux3 at tux3.org
http://mailman.tux3.org/cgi-bin/mailman/listinfo/tux3



More information about the Tux3 mailing list