aboutsummaryrefslogtreecommitdiff
path: root/src/libdiskfs
diff options
context:
space:
mode:
authorrsc <devnull@localhost>2006-06-15 05:52:24 +0000
committerrsc <devnull@localhost>2006-06-15 05:52:24 +0000
commitfa5af687114e590d63af995951f6092f42ed0d58 (patch)
treefe06ee86153322de487dfad8e64e46d40d95d1a7 /src/libdiskfs
parentdbf91a04cc556bad9b03d8eb11f92468ee9da092 (diff)
downloadplan9port-fa5af687114e590d63af995951f6092f42ed0d58.tar.gz
plan9port-fa5af687114e590d63af995951f6092f42ed0d58.tar.bz2
plan9port-fa5af687114e590d63af995951f6092f42ed0d58.zip
better ext2 block read (sigh)
Diffstat (limited to 'src/libdiskfs')
-rw-r--r--src/libdiskfs/ext2.c48
1 files changed, 25 insertions, 23 deletions
diff --git a/src/libdiskfs/ext2.c b/src/libdiskfs/ext2.c
index 87437f84..25c21c82 100644
--- a/src/libdiskfs/ext2.c
+++ b/src/libdiskfs/ext2.c
@@ -655,7 +655,7 @@ ext2readfile(Fsys *fsys, SunAuthUnix *au, Nfs3Handle *h, u32int count,
uchar *data;
Block *b;
Ext2 *fs;
- int off, want, fragcount;
+ int skip1, tot, want, fragcount;
Inode ino;
Nfs3Status ok;
@@ -674,34 +674,36 @@ ext2readfile(Fsys *fsys, SunAuthUnix *au, Nfs3Handle *h, u32int count,
}
if(offset+count > ino.size)
count = ino.size-offset;
- if(offset/fs->blocksize != (offset+count-1)/fs->blocksize)
- count = fs->blocksize - offset%fs->blocksize;
data = malloc(count);
if(data == nil)
return Nfs3ErrNoMem;
-
- want = offset%fs->blocksize+count;
- if(want%fs->blocksize)
- want += fs->blocksize - want%fs->blocksize;
-
- b = ext2fileblock(fs, &ino, offset/fs->blocksize, want);
- if(b == nil){
- /* BUG: distinguish sparse file from I/O error */
- memset(data, 0, count);
- }else{
- off = offset%fs->blocksize;
- fragcount = count; /* need signed variable */
- if(off+fragcount > b->len){
- fragcount = b->len - off;
- if(fragcount < 0)
- fragcount = 0;
- }
- if(fragcount > 0)
- memmove(data, b->data+off, fragcount);
- count = fragcount;
+ memset(data, 0, count);
+
+ skip1 = offset%fs->blocksize;
+ offset -= skip1;
+ want = skip1+count;
+
+ /*
+ * have to read multiple blocks if we get asked for a big read.
+ * Linux NFS client assumes that if you ask for 8k and only get 4k
+ * back, the remaining 4k is zeros.
+ */
+ for(tot=0; tot<want; tot+=fragcount){
+ b = ext2fileblock(fs, &ino, (offset+tot)/fs->blocksize, fs->blocksize);
+ fragcount = fs->blocksize;
+ if(b == nil)
+ continue;
+ if(tot+fragcount > want)
+ fragcount = want - tot;
+ if(tot == 0)
+ memmove(data, b->data+skip1, fragcount-skip1);
+ else
+ memmove(data+tot-skip1, b->data, fragcount);
blockput(b);
}
+ count = tot - skip1;
+
*peof = (offset+count == ino.size);
*pcount = count;
*pdata = data;