fix indirect block reading

This commit is contained in:
rsc 2005-07-28 05:16:42 +00:00
parent 725d9fd795
commit 9f4a65a0d8

View file

@ -15,6 +15,7 @@ static Block *ffsblockread(Fsys*, u64int);
static int ffssync(Fsys*); static int ffssync(Fsys*);
static void ffsclose(Fsys*); static void ffsclose(Fsys*);
static u64int ffsxfileblock(Fsys *fs, Nfs3Handle *h, u64int offset);
static Nfs3Status ffsroot(Fsys*, Nfs3Handle*); static Nfs3Status ffsroot(Fsys*, Nfs3Handle*);
static Nfs3Status ffsgetattr(Fsys*, SunAuthUnix *au, Nfs3Handle*, Nfs3Attr*); static Nfs3Status ffsgetattr(Fsys*, SunAuthUnix *au, Nfs3Handle*, Nfs3Attr*);
static Nfs3Status ffslookup(Fsys*, SunAuthUnix *au, Nfs3Handle*, char*, Nfs3Handle*); static Nfs3Status ffslookup(Fsys*, SunAuthUnix *au, Nfs3Handle*, char*, Nfs3Handle*);
@ -43,6 +44,7 @@ fsysopenffs(Disk *disk)
fsys->_readfile = ffsreadfile; fsys->_readfile = ffsreadfile;
fsys->_readlink = ffsreadlink; fsys->_readlink = ffsreadlink;
fsys->_readdir = ffsreaddir; fsys->_readdir = ffsreaddir;
fsys->fileblock = ffsxfileblock;
if(ffssync(fsys) < 0) if(ffssync(fsys) < 0)
goto error; goto error;
@ -288,35 +290,60 @@ ffsdatablock(Ffs *fs, u32int bno, int size)
return b; return b;
} }
static Block* static u32int
ffsfileblock(Ffs *fs, Inode *ino, u32int bno, int size) ifetch(Ffs *fs, u32int bno, u32int off)
{
u32int *a;
Block *b;
if(bno == ~0)
return ~0;
b = ffsdatablock(fs, bno, fs->blocksize);
if(b == nil)
return ~0;
a = (u32int*)b->data;
bno = a[off];
blockput(b);
return bno;
}
static u32int
ffsfileblockno(Ffs *fs, Inode *ino, u32int bno)
{ {
int ppb; int ppb;
Block *b;
u32int *a;
if(bno < NDADDR){ if(bno < NDADDR){
if(debug) fprint(2, "ffsfileblock %lud: direct %#lux\n", (ulong)bno, (ulong)ino->db[bno]); if(debug) fprint(2, "ffsfileblock %lud: direct %#lux\n", (ulong)bno, (ulong)ino->db[bno]);
return ffsdatablock(fs, ino->db[bno], size); return ino->db[bno];
} }
bno -= NDADDR; bno -= NDADDR;
ppb = fs->blocksize/4; ppb = fs->blocksize/4;
if(bno/ppb < NIADDR){ if(bno < ppb) /* single indirect */
if(debug) fprint(2, "ffsfileblock %lud: indirect %#lux\n", (ulong)(bno+NDADDR), return ifetch(fs, ino->ib[0], bno);
(ulong)ino->ib[bno/ppb]); bno -= ppb;
b = ffsdatablock(fs, ino->ib[bno/ppb], fs->blocksize);
if(b == nil) if(bno < ppb*ppb)
return nil; return ifetch(fs, ifetch(fs, ino->ib[1], bno/ppb), bno%ppb);
a = (u32int*)b->data; bno -= ppb*ppb;
bno = a[bno%ppb];
if(debug) fprint(2, "ffsfileblock: indirect fetch %#lux size %d\n", (ulong)bno, size); if(bno/ppb/ppb/ppb == 0) /* bno < ppb*ppb*ppb w/o overflow */
blockput(b); return ifetch(fs, ifetch(fs, ifetch(fs, ino->ib[2], bno/ppb/ppb), (bno/ppb)%ppb), bno%ppb);
return ffsdatablock(fs, bno, size); bno -= ppb*ppb*ppb;
fprint(2, "ffsfileblock %lud: way too big\n", (ulong)bno+NDADDR);
return ~0;
} }
fprint(2, "ffsfileblock %lud: too big\n", (ulong)bno+NDADDR); static Block*
ffsfileblock(Ffs *fs, Inode *ino, u32int bno, int size)
{
u32int b;
b = ffsfileblockno(fs, ino, bno);
if(b == ~0)
return nil; return nil;
return ffsdatablock(fs, b, size);
} }
/* /*
@ -338,6 +365,8 @@ byte2u32(uchar *p)
return (p[0]<<24) | (p[1]<<16) | (p[2]<<8) | p[3]; return (p[0]<<24) | (p[1]<<16) | (p[2]<<8) | p[3];
} }
static u64int iaddr;
static Nfs3Status static Nfs3Status
handle2ino(Ffs *fs, Nfs3Handle *h, u32int *pinum, Inode *ino) handle2ino(Ffs *fs, Nfs3Handle *h, u32int *pinum, Inode *ino)
{ {
@ -370,6 +399,8 @@ handle2ino(Ffs *fs, Nfs3Handle *h, u32int *pinum, Inode *ino)
if((b = diskread(fs->disk, fs->blocksize, if((b = diskread(fs->disk, fs->blocksize,
(cg->ibno+ioff/fs->inosperblock)*(vlong)fs->blocksize)) == nil) (cg->ibno+ioff/fs->inosperblock)*(vlong)fs->blocksize)) == nil)
return Nfs3ErrIo; return Nfs3ErrIo;
iaddr = (cg->ibno+ioff/fs->inosperblock)*(vlong)fs->blocksize
+ (ioff%fs->inosperblock)*sizeof(Inode);
*ino = ((Inode*)b->data)[ioff%fs->inosperblock]; *ino = ((Inode*)b->data)[ioff%fs->inosperblock];
blockput(b); blockput(b);
@ -458,6 +489,9 @@ inoperm(Inode *ino, SunAuthUnix *au, int need)
{ {
int have; int have;
if(au == nil)
return Nfs3Ok;
have = ino->mode&0777; have = ino->mode&0777;
if(ino->uid == au->uid) if(ino->uid == au->uid)
have >>= 6; have >>= 6;
@ -680,6 +714,32 @@ ffsreaddir(Fsys *fsys, SunAuthUnix *au, Nfs3Handle *h, u32int count, u64int cook
return Nfs3Ok; return Nfs3Ok;
} }
static u64int
ffsxfileblock(Fsys *fsys, Nfs3Handle *h, u64int offset)
{
u32int bno;
Inode ino;
Nfs3Status ok;
Ffs *fs;
fs = fsys->priv;
if((ok = handle2ino(fs, h, nil, &ino)) != Nfs3Ok){
nfs3errstr(ok);
return 0;
}
if(offset == 1)
return iaddr;
if(offset >= ino.size){
werrstr("beyond end of file");
return 0;
}
bno = offset/fs->blocksize;
bno = ffsfileblockno(fs, &ino, bno);
if(bno == ~0)
return 0;
return bno*(u64int)fs->fragsize;
}
static Nfs3Status static Nfs3Status
ffsreadfile(Fsys *fsys, SunAuthUnix *au, Nfs3Handle *h, u32int count, ffsreadfile(Fsys *fsys, SunAuthUnix *au, Nfs3Handle *h, u32int count,
u64int offset, uchar **pdata, u32int *pcount, u1int *peof) u64int offset, uchar **pdata, u32int *pcount, u1int *peof)