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
[email protected]
http://mailman.tux3.org/cgi-bin/mailman/listinfo/tux3

Reply via email to