[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