Fcall reply; /* Incoming reply */
Mnt* m; /* Mount device during rpc */
Rendez* z; /* Place to hang out */
- uchar* rpc; /* I/O Data buffer */
- uint rpclen; /* len of buffer */
+ Block* w; /* copy of write rpc for cache */
Block* b; /* reply blocks */
Mntrpc* flushed; /* message this one flushes */
char done; /* Rpc completed */
enum
{
- TAGSHIFT = 5, /* ulong has to be 32 bits */
+ TAGSHIFT = 5,
TAGMASK = (1<<TAGSHIFT)-1,
NMASK = (64*1024)>>TAGSHIFT,
};
ulong nrpcfree;
ulong nrpcused;
ulong id;
- ulong tagmask[NMASK];
+ u32int tagmask[NMASK];
} mntalloc;
static Chan* mntchan(void);
static void mountrpc(Mnt*, Mntrpc*);
static int rpcattn(void*);
+#define cachedchan(c) (((c)->flag & CCACHE) != 0 && (c)->mcp != nil)
+
char Esbadstat[] = "invalid directory entry received from server";
char Enoversion[] = "version not established for mount channel";
{
mntalloc.id = 1;
mntalloc.tagmask[0] = 1; /* don't allow 0 as a tag */
- mntalloc.tagmask[NMASK-1] = 0x80000000UL; /* don't allow NOTAG */
+ mntalloc.tagmask[NMASK-1] = 0x80000000; /* don't allow NOTAG */
fmtinstall('F', fcallfmt);
fmtinstall('D', dirfmt);
/* We can't install %M since eipfmt does and is used in the kernel [sape] */
Mnt *m;
Mntrpc *r;
+ if(ac != nil && ac->mchan != c)
+ error(Ebadusefd);
+
m = c->mux;
if(m == nil){
mntversion(c, nil, 0, 0);
poperror();
mntfree(r);
- if(c->flag & CCACHE)
- copen(c);
+ if(c->flag & CCACHE){
+ if(copen(c))
+ if(type == Tcreate || (omode&OTRUNC) != 0)
+ ctrunc(c);
+ }
return c;
}
mountrpc(m, r);
poperror();
mntfree(r);
+
+ if(c->flag & CCACHE)
+ if(GBIT64(&dp[STATFIXLEN-4*BIT16SZ-BIT64SZ]) != ~0ULL)
+ ctrunc(c);
+
return n;
}
Chan *c;
c = r->c;
- if((c->flag & CCACHE) == 0 || c->mcp == nil)
+ if(!cachedchan(c))
return;
off = r->request.offset;
switch(r->reply.type){
}
break;
case Rwrite:
- if(convM2S(r->rpc, r->rpclen, &r->request) == 0)
+ b = r->w;
+ if(convM2S(b->rp, BLEN(b), &r->request) == 0)
panic("convM2S");
- cwrite(c, (uchar*)r->request.data, r->request.count, off);
+ m = r->reply.count;
+ if(m > r->request.count)
+ m = r->request.count;
+ cwrite(c, (uchar*)r->request.data, m, off);
break;
}
}
if(nreq > c->iounit)
nreq = c->iounit;
- if(type == Tread && (c->flag&CCACHE) != 0) {
+ if(type == Tread && cachedchan(c)) {
nr = cread(c, (uchar*)uba, nreq, off);
if(nr > 0) {
nreq = nr;
if(nr > nreq)
nr = nreq;
if(type == Tread)
- r->b = bl2mem((uchar*)uba, r->b, nr);
+ nr = readblist(r->b, (uchar*)uba, nr, 0);
mntfree(r);
poperror();
if(rah->seq >= 2*c->iounit){
w = (off / c->iounit) * c->iounit;
e = w + rah->seq;
- for(o = w; w < e; o += c->iounit){
+ for(o = w; o < e; o += c->iounit){
if(rahfindrpc(rah, o) != nil)
continue;
static void
mountio(Mnt *m, Mntrpc *r)
{
+ Block *b;
int n;
while(waserror()) {
/* Transmit a file system rpc */
n = sizeS2M(&r->request);
- if(n > r->rpclen) {
- free(r->rpc);
- r->rpc = mallocz(((uint)n+127) & ~127, 0);
- if(r->rpc == nil) {
- r->rpclen = 0;
- exhausted("mount rpc buffer");
- }
- r->rpclen = msize(r->rpc);
+ b = allocb(n);
+ if(waserror()){
+ freeb(b);
+ nexterror();
}
- n = convS2M(&r->request, r->rpc, r->rpclen);
+ n = convS2M(&r->request, b->wp, n);
if(n <= 0 || n > m->msize) {
print("mountio: proc %s %lud: convS2M returned %d for tag %d fid %d T%d\n",
up->text, up->pid, n, r->request.tag, r->request.fid, r->request.type);
error(Emountrpc);
}
- if(devtab[m->c->type]->write(m->c, r->rpc, n, 0) != n)
- error(Emountrpc);
+ b->wp += n;
+ if(r->request.type == Twrite && cachedchan(r->c))
+ r->w = copyblock(b, n);
+ poperror();
+ devtab[m->c->type]->bwrite(m->c, b, 0);
/* Gate readers onto the mount point one at a time */
for(;;) {
while(qlen(m->q) < len){
b = devtab[m->c->type]->bread(m->c, m->msize, 0);
- if(b == nil)
- return -1;
- if(blocklen(b) == 0){
- freeblist(b);
+ if(b == nil || qaddlist(m->q, b) == 0)
return -1;
- }
- qaddlist(m->q, b);
}
return 0;
}
l = &q->list;
}
unlock(m);
- print("unexpected reply tag %ud; type %d\n", r->reply.tag, r->reply.type);
+ print("mnt: unexpected reply from %s tag %ud; type %d\n",
+ chanpath(m->c), r->reply.tag, r->reply.type);
}
/*
alloctag(void)
{
int i, j;
- ulong v;
+ u32int v;
for(i = 0; i < NMASK; i++){
v = mntalloc.tagmask[i];
- if(v == ~0UL)
+ if(v == -1)
continue;
- for(j = 0; j < 1<<TAGSHIFT; j++)
- if((v & (1<<j)) == 0){
- mntalloc.tagmask[i] |= 1<<j;
- return (i<<TAGSHIFT) + j;
- }
+ for(j = 0; (v & 1) != 0; j++)
+ v >>= 1;
+ mntalloc.tagmask[i] |= 1<<j;
+ return i<<TAGSHIFT | j;
}
panic("no friggin tags left");
return NOTAG;
new = malloc(sizeof(Mntrpc));
if(new == nil)
exhausted("mount rpc header");
- new->rpc = nil;
- new->rpclen = 0;
lock(&mntalloc);
new->request.tag = alloctag();
} else {
new->done = 0;
new->flushed = nil;
new->b = nil;
+ new->w = nil;
return new;
}
static void
mntfree(Mntrpc *r)
{
+ freeb(r->w);
freeblist(r->b);
lock(&mntalloc);
mntalloc.nrpcused--;
}
freetag(r->request.tag);
unlock(&mntalloc);
- free(r->rpc);
free(r);
}