Subversion Repositories planix.SVN

Rev

Rev 2 | Blame | Compare with Previous | Last modification | View Log | RSS feed

#include        "all.h"

Dentry*
getdir(Iobuf *p, int slot)
{
        Dentry *d;

        if(!p)
                return 0;
        d = (Dentry*)p->iobuf + slot%DIRPERBUF;
        return d;
}

void
accessdir(Iobuf *p, Dentry *d, int f)
{
        long t;

        if(p && !isro(p->dev)) {
                if(!(f & (FWRITE|FWSTAT)) && noatime)
                        return;
                t = time(nil);
                if(f & (FREAD|FWRITE|FWSTAT)){
                        d->atime = t;
                        p->flags |= Bmod;
                }
                if(f & FWRITE) {
                        d->mtime = t;
                        d->qid.version++;
                        p->flags |= Bmod;
                }
        }
}

void
dbufread(Iobuf *p, Dentry *d, long a)
{
        USED(p, d, a);
}

long
rel2abs(Iobuf *p, Dentry *d, long a, int tag, int putb)
{
        long addr, qpath;
        Device dev;

        if(a < 0) {
                print("dnodebuf: neg\n");
                return 0;
        }
        qpath = d->qid.path;
        dev = p->dev;
        if(a < NDBLOCK) {
                addr = d->dblock[a];
                if(!addr && tag) {
                        addr = balloc(dev, tag, qpath);
                        d->dblock[a] = addr;
                        p->flags |= Bmod|Bimm;
                }
                if(putb)
                        putbuf(p);
                return addr;
        }
        a -= NDBLOCK;
        if(a < INDPERBUF) {
                addr = d->iblock;
                if(!addr && tag) {
                        addr = balloc(dev, Tind1, qpath);
                        d->iblock = addr;
                        p->flags |= Bmod|Bimm;
                }
                if(putb)
                        putbuf(p);
                addr = indfetch(p, d, addr, a, Tind1, tag);
                return addr;
        }
        a -= INDPERBUF;
        if(a < INDPERBUF2) {
                addr = d->diblock;
                if(!addr && tag) {
                        addr = balloc(dev, Tind2, qpath);
                        d->diblock = addr;
                        p->flags |= Bmod|Bimm;
                }
                if(putb)
                        putbuf(p);
                addr = indfetch(p, d, addr, a/INDPERBUF, Tind2, Tind1);
                addr = indfetch(p, d, addr, a%INDPERBUF, Tind1, tag);
                return addr;
        }
        if(putb)
                putbuf(p);
        print("dnodebuf: trip indirect\n");
        return 0;
}

Iobuf*
dnodebuf(Iobuf *p, Dentry *d, long a, int tag)
{
        long addr;

        addr = rel2abs(p, d, a, tag, 0);
        if(addr)
                return getbuf(p->dev, addr, Bread);
        return 0;
}

/*
 * same as dnodebuf but it calls putpuf(p)
 * to reduce interference.
 */
Iobuf*
dnodebuf1(Iobuf *p, Dentry *d, long a, int tag)
{
        long addr;
        Device dev;

        dev = p->dev;
        addr = rel2abs(p, d, a, tag, 1);
        if(addr)
                return getbuf(dev, addr, Bread);
        return 0;

}

long
indfetch(Iobuf *p, Dentry *d, long addr, long a, int itag, int tag)
{
        Iobuf *bp;

        if(!addr)
                return 0;
        bp = getbuf(p->dev, addr, Bread);
        if(!bp || checktag(bp, itag, d->qid.path)) {
                if(!bp) {
                        print("ind fetch bp = 0\n");
                        return 0;
                }
                print("ind fetch tag\n");
                putbuf(bp);
                return 0;
        }
        addr = ((long*)bp->iobuf)[a];
        if(!addr && tag) {
                addr = balloc(p->dev, tag, d->qid.path);
                if(addr) {
                        ((long*)bp->iobuf)[a] = addr;
                        bp->flags |= Bmod;
                        if(localfs || tag == Tdir)
                                bp->flags |= Bimm;
                        settag(bp, itag, d->qid.path);
                }
        }
        putbuf(bp);
        return addr;
}

void
dtrunc(Iobuf *p, Dentry *d)
{
        int i;

        bfree(p->dev, d->diblock, 2);
        d->diblock = 0;
        bfree(p->dev, d->iblock, 1);
        d->iblock = 0;
        for(i=NDBLOCK-1; i>=0; i--) {
                bfree(p->dev, d->dblock[i], 0);
                d->dblock[i] = 0;
        }
        d->size = 0;
        p->flags |= Bmod|Bimm;
        accessdir(p, d, FWRITE);
}