/*
- * © 2005-10 coraid
+ * © 2005-13 coraid
* aoe storage initiator
*/
#include "ureg.h"
#include "../port/error.h"
#include "../port/netif.h"
-#include "etherif.h"
+#include "../port/etherif.h"
#include "../ip/ip.h"
#include "../port/aoe.h"
#include <fis.h>
#define uprint(...) snprint(up->genbuf, sizeof up->genbuf, __VA_ARGS__);
enum {
- Maxunits = 0xff,
+ Typebits = 4,
+ Unitbits = 12,
+ L3bits = 4,
+ Maxtype = (1<<Typebits)-1,
+ Maxunits = (1<<Unitbits)-1,
+ Maxl3 = (1<<L3bits)-1,
Maxframes = 128,
Maxmtu = 100000,
Ndevlink = 6,
Nnetlink = 6,
};
-#define TYPE(q) ((ulong)(q).path & 0xf)
-#define UNIT(q) (((ulong)(q).path>>4) & 0xff)
-#define L(q) (((ulong)(q).path>>12) & 0xf)
-#define QID(u, t) ((u)<<4 | (t))
-#define Q3(l, u, t) ((l)<<8 | QID(u, t))
+#define TYPE(q) ((ulong)(q).path & Maxtype)
+#define UNIT(q) (((ulong)(q).path>>Typebits) & Maxunits)
+#define L(q) (((ulong)(q).path>>Typebits+Unitbits) & Maxl3)
+#define QID(u, t) ((u)<<Typebits | (t))
+#define Q3(l, u, t) ((l)<<Typebits+Unitbits | QID(u, t))
#define UP(d) ((d)->flag & Dup)
#define Ticks MACHP(0)->ticks
if(srb == d->inprocess)
d->inprocess = nil;
else
- for(ll = &d->head; x = *ll; ll = &x->next){
+ for(ll = &d->head; (x = *ll) != nil; ll = &x->next){
d->tail = x;
if(x == srb)
*ll = x->next;
srb = f->srb;
f->srb = nil;
f->tag = Tfree; /* don't get fooled by way-slow responses */
- if(!srb)
+ if(srb == nil)
return;
srb->nout--;
srberror(d, srb, s);
/* the concern here is page faults in memmove below */
if(waserror()){
- free(buf);
qunlock(&events);
+ free(buf);
nexterror();
}
memmove(a, buf, n);
poperror();
}
- free(buf);
qunlock(&events);
+ free(buf);
return n;
}
for(i = 0; i < d->ndl; i++){
n = d->dlidx++ % d->ndl;
l = d->dl + n;
- if(l && l->flag & Dup)
+ if(l->flag & Dup)
return l;
}
- return 0;
+ return nil;
}
static int
pickea(Devlink *l)
{
- if(l == 0)
+ if(l == nil)
return -1;
if(l->nea == 0)
return -1;
#define Nofail(d, s) (((d)->flag&Dnofail) == Dnofail)
static int
-hset(Aoedev *d, Frame *f, Aoehdr *h, int cmd)
+hset(Aoedev *d, Frame *f, Aoehdr *h, int cmd, int new)
{
int i;
Devlink *l;
- if(f->srb)
+ if(f->srb != nil)
if((long)(Ticks-f->srb->ticksent) > Srbtimeout){
eventlog("%æ: srb timeout\n", d);
if(cmd == ACata && Nofail(d, s))
l = pickdevlink(d);
i = pickea(l);
if(i == -1){
- if(!(cmd == ACata && f->srb && Nofail(d, s)))
+ if(!(cmd == ACata && f->srb != nil && Nofail(d, s)))
downdev(d, "resend fails; no netlink/ea");
return -1;
}
h->minor = d->minor;
h->cmd = cmd;
- hnputl(h->tag, f->tag = newtag(d));
+ if(new)
+ f->tag = newtag(d);
+ hnputl(h->tag, f->tag);
f->dl = l;
f->nl = l->nl;
f->eaidx = i;
Aoehdr *h;
h = (Aoehdr*)f->hdr;
- if(hset(d, f, h, h->cmd) == -1)
+ if(hset(d, f, h, h->cmd, 0) == -1)
return -1;
a = (Aoeata*)(f->hdr + Aoehsz);
n = f->bcnt;
}
starttick = Ticks;
rlock(&devs);
- for(d = devs.d; d; d = d->next){
+ for(d = devs.d; d != nil; d = d->next){
if(!canqlock(d))
continue;
if(!UP(d)){
}
runlock(&devs);
i = Nms - TK2MS(Ticks - starttick);
- if(i > 0)
+ if(i > 0 && !waserror()){
tsleep(&up->sleep, return0, 0, i);
+ poperror();
+ }
goto loop;
}
return c;
}
-static Aoedev*
-unitseq(ulong unit)
+static int
+unitseq(Chan *c, uint unit, Dir *dp)
{
- int i;
+ int i, rv;
+ Qid q;
Aoedev *d;
i = 0;
+ rv = -1;
rlock(&devs);
- for(d = devs.d; d; d = d->next)
- if(i++ == unit)
+ for(d = devs.d; d != nil; d = d->next)
+ if(i++ == unit){
+ mkqid(&q, QID(d->unit, Qunitdir), 0, QTDIR);
+ devdir(c, q, unitname(d), 0, eve, 0555, dp);
+ rv = 1;
break;
+ }
runlock(&devs);
- return d;
+ return rv;
}
static Aoedev*
Aoedev *d;
rlock(&devs);
- for(d = devs.d; d; d = d->next)
+ for(d = devs.d; d != nil; d = d->next)
if(d->unit == unit){
runlock(&devs);
return d;
Qid q;
d = unit2dev(UNIT(c->qid));
- perm = 0644;
+ perm = 0664;
size = 0;
vers = d->vers;
t = QTFILE;
break;
case Qdata:
p = "data";
- perm = 0640;
+ perm = 0660;
if(UP(d))
size = d->bsize;
break;
return -1;
case Qtopctl:
p = "ctl";
- perm = 0644;
+ perm = 0664;
break;
case Qtoplog:
p = "log";
if(s < Qtopfiles)
return topgen(c, Qtopbase + s, dp);
s -= Qtopfiles;
- if((d = unitseq(s)) == 0)
- return -1;
- mkqid(&q, QID(d->unit, Qunitdir), 0, QTDIR);
- devdir(c, q, unitname(d), 0, eve, 0555, dp);
- return 1;
+ return unitseq(c, s, dp);
case Qtopctl:
case Qtoplog:
return topgen(c, TYPE(c->qid), dp);
return unitgen(c, TYPE(c->qid), dp);
case Qdevlinkdir:
i = UNIT(c->qid);
+ if(i >= Maxunits || i >= units.ref)
+ return -1;
+ d = unit2dev(i);
if(s == DEVDOTDOT){
mkqid(&q, QID(i, Qunitdir), 0, QTDIR);
- devdir(c, q, "devlink", 0, eve, 0555, dp);
+ devdir(c, q, unitname(d), 0, eve, 0555, dp);
return 1;
}
- if(i >= units.ref)
- return -1;
- d = unit2dev(i);
if(s >= d->ndl)
return -1;
uprint("%d", s);
mkqid(&q, Q3(s, i, Qdevlink), 0, QTFILE);
- devdir(c, q, up->genbuf, 0, eve, 0755, dp);
+ devdir(c, q, up->genbuf, 0, eve, 0444, dp);
return 1;
case Qdevlink:
uprint("%d", s);
mkqid(&q, Q3(s, UNIT(c->qid), Qdevlink), 0, QTFILE);
- devdir(c, q, up->genbuf, 0, eve, 0755, dp);
+ devdir(c, q, up->genbuf, 0, eve, 0444, dp);
return 1;
}
}
f->nhdr = Aoehsz + Aoeatasz;
memset(f->hdr, 0, f->nhdr);
h = (Aoehdr*)f->hdr;
- if(hset(d, f, h, ACata) == -1){
+ if(hset(d, f, h, ACata, 1) == -1){
d->inprocess = nil;
return;
}
};
if((h->verflag & AFerr) == 0)
- return 0;
+ return nil;
n = h->error;
- if(n > nelem(errs))
+ if(n >= nelem(errs))
n = 0;
return errs[n];
}
if(!UP(d))
error(Eio);
srb->next = nil;
- if(d->tail)
+ if(d->tail != nil)
d->tail->next = srb;
d->tail = srb;
if(d->head == nil)
if(write && !copy)
memmove(srb->data, db, n);
strategy(d, srb);
- if(srb->error)
+ if(srb->error != nil)
error(srb->error);
if(!write && !copy)
memmove(db, srb->data, n);
int i;
char *state, *s, *p, *e;
- s = p = malloc(READSTR);
+ s = p = smalloc(READSTR);
e = p + READSTR;
state = "down";
return 0;
l = d->dl + i;
- s = p = malloc(READSTR);
+ s = p = smalloc(READSTR);
e = s + READSTR;
p = seprint(p, e, "addr: ");
char *s, *p, *e;
Netlink *n;
- s = p = malloc(READSTR);
+ s = p = smalloc(READSTR);
e = s + READSTR;
p = seprint(p, e, "debug: %d\n", debug);
for(i = 0; i < Nnetlink; i++){
n = netlinks.nl+i;
- if(n->cc == 0)
+ if(n->cc == nil)
continue;
p = seprint(p, e, "if%d path: %s\n", i, n->path);
p = seprint(p, e, "if%d ea: %E\n", i, n->ea);
f->nhdr = Aoehsz + Aoecfgsz;
memset(f->hdr, 0, f->nhdr);
h = (Aoehdr*)f->hdr;
- if(hset(d, f, h, ACconfig) == -1)
+ if(hset(d, f, h, ACconfig, 1) == -1)
return 0;
ch = (Aoecfg*)(f->hdr + Aoehsz);
f->srb = srb;
case Qconfig:
if(off + n > sizeof d->config)
error(Etoobig);
- buf = malloc(sizeof d->config);
+ buf = smalloc(sizeof d->config);
if(waserror()){
free(buf);
nexterror();
}
nl = netlinks.nl;
e = nl + nelem(netlinks.nl);
- for(; nl < e && nl->cc; nl++)
+ for(; nl < e && nl->cc != nil; nl++)
continue;
if(nl == e)
error("out of netlink structures");
nl->mtu = mtu;
strncpy(nl->path, path, sizeof(nl->path)-1);
nl->path[sizeof(nl->path)-1] = 0;
- memmove(nl->ea, ea, sizeof(nl->ea));
+ memmove(nl->ea, ea, sizeof nl->ea);
poperror();
nl->flag |= Dup;
unlock(&netlinks);
{
int x;
- lock(&units);
- if(units.ref == Maxunits)
+ x = incref(&units)-1;
+ if(x >= Maxunits){
+ decref(&units);
x = -1;
- else
- x = units.ref++;
- unlock(&units);
+ }
return x;
}
static int
dropunit(void)
{
- int x;
-
- lock(&units);
- x = --units.ref;
- unlock(&units);
- return x;
+ return decref(&units);
}
/*
d = malloc(sizeof *d);
f = malloc(sizeof *f*Maxframes);
- if(!d || !f) {
+ if(d == nil || f == nil) {
free(d);
free(f);
error("aoe device allocation failure");
f->nhdr = Aoehsz + Aoeatasz;
memset(f->hdr, 0, f->nhdr);
h = (Aoehdr*)f->hdr;
- if(hset(d, f, h, ACata) == -1)
+ if(hset(d, f, h, ACata, 1) == -1)
return;
a = (Aoeata*)(f->hdr + Aoehsz);
f->srb = srbkalloc(0, 0);
if(n == Tmgmt || n == Tfree)
return;
d = mm2dev(nhgets(h->major), h->minor);
- if(d == 0)
+ if(d == nil)
return;
if(f = getframe(d, n))
frameerror(d, f, s);
int cmd, cslen, blen;
uint n, major;
Aoedev *d;
- Aoehdr *h;
+ Aoehdr *h, *h0;
Aoecfg *ch;
Devlink *l;
Frame *f;
ch = (Aoecfg*)(b->rp + Aoehsz);
major = nhgets(h->major);
n = nhgetl(h->tag);
- if(n != Tmgmt){
+ if(n != Tmgmt && n != Tfree){
d = mm2dev(major, h->minor);
if(d == nil)
return;
eventlog("%æ: unknown response tag %ux\n", d, n);
return;
}
+ h0 = (Aoehdr*)f->hdr;
+ cmd = h0->cmd;
+ if(cmd != ACconfig){
+ qunlock(d);
+ eventlog("%æ: malicious server got ACconfig want %d; tag %ux\n", d, cmd, n);
+ return;
+ }
cslen = nhgets(ch->cslen);
blen = BLEN(b) - (Aoehsz + Aoecfgsz);
if(cslen < blen && BLEN(b) > 60)
d, n, cslen, blen);
cslen = blen;
}
- memmove(f->dp, (uchar*)ch + Aoehsz + Aoecfgsz, cslen);
+ memmove(f->dp, b->rp + Aoehsz + Aoecfgsz, cslen);
srb = f->srb;
f->dp = nil;
f->srb = nil;
- if(srb){
+ if(srb != nil){
srb->nout--;
srbwakeup(srb);
d->nout--;
l = newdevlink(d, nl, h); /* add this interface. */
d->fwver = nhgets(ch->fwver);
- n = nhgets(ch->cslen);
- if(n > sizeof d->config)
- n = sizeof d->config;
- d->nconfig = n;
- memmove(d->config, (uchar*)ch + Aoehsz + Aoecfgsz, n);
+ cslen = nhgets(ch->cslen);
+ if(cslen > sizeof d->config)
+ cslen = sizeof d->config;
+ if(Aoehsz + Aoecfgsz + cslen > BLEN(b))
+ cslen = BLEN(b) - (Aoehsz + Aoecfgsz);
+ d->nconfig = cslen;
+ memmove(d->config, b->rp + Aoehsz + Aoecfgsz, cslen);
/* manually set mtu may be reset lower if conditions warrant */
if(l){
vlong s;
s = idfeat(d, id);
- if(s == -1)
+ if(s == -1){
+ eventlog("%æ: idfeat returns -1\n", d);
return -1;
+ }
if((d->feat&Dlba) == 0){
- dprint("%æ: no lba support\n", d);
+ eventlog("%æ: no lba support\n", d);
return -1;
}
d->flag |= Dup;
static void
newvers(Aoedev *d)
{
- lock(&drivevers);
- d->vers = drivevers.ref++;
- unlock(&drivevers);
+ d->vers = incref(&drivevers);
}
static int
static void
atarsp(Block *b)
{
- uint n;
+ uint n, cmd;
ushort major;
Aoeata *ahin, *ahout;
- Aoehdr *h;
+ Aoehdr *h, *h0;
Aoedev *d;
Frame *f;
Srb *srb;
nexterror();
}
n = nhgetl(h->tag);
+ if(n == Tfree || n == Tmgmt)
+ goto bail;
f = getframe(d, n);
if(f == nil){
- dprint("%æ: unexpected response; tag %ux\n", d, n);
+ eventlog("%æ: unexpected response; tag %ux\n", d, n);
+ goto bail;
+ }
+ h0 = (Aoehdr*)f->hdr;
+ cmd = h0->cmd;
+ if(cmd != ACata){
+ eventlog("%æ: malicious server got ACata want %d; tag %ux\n", d, cmd, n);
goto bail;
}
+
rtupdate(f->dl, tsince(f->tag));
ahout = (Aoeata*)(f->hdr + Aoehsz);
srb = f->srb;
if(ahin->cmdstat & 0xa9){
eventlog("%æ: ata error cmd %.2ux stat %.2ux\n",
d, ahout->cmdstat, ahin->cmdstat);
- if(srb)
+ if(srb != nil)
srb->error = Eio;
} else {
n = ahout->scnt * Aoesectsz;
case Crd:
case Crdext:
if(BLEN(b) - (Aoehsz + Aoeatasz) != n){
- eventlog("%æ: misread blen %ld expect %d\n",
+ eventlog("%æ: misread blen %zd expect %d\n",
d, BLEN(b), n);
goto bail;
}
break;
case Cid:
if(BLEN(b) - (Aoehsz + Aoeatasz) < 512){
- eventlog("%æ: runt identify blen %ld expect %d\n",
+ eventlog("%æ: runt identify blen %zd expect %d\n",
d, BLEN(b), 512 + Aoehsz + Aoeatasz);
goto bail;
}
}
f->srb = nil;
- if(srb){
+ if(srb != nil){
srb->nout--;
srbwakeup(srb);
}
h = (Aoehdr*)b->rp;
if(h->verflag & AFrsp)
if(s = aoeerror(h)){
- eventlog("%s: %s\n", nl->path, s);
+ eventlog("%s: %d.%d %s\n", nl->path,
+ h->major[0]<<8 | h->major[1], h->minor, s);
errrsp(b, s);
}else if(h->cmd == ACata)
atarsp(b);
else if(h->cmd == ACconfig)
qcfgrsp(b, nl);
- else if((h->cmd & 0xf0) == 0){
+ else if((h->cmd & 0xf0) != 0xf0){
eventlog("%s: unknown cmd %d\n",
nl->path, h->cmd);
errrsp(b, "unknown command");
cclose(c);
nexterror();
}
- if(c == nil)
- panic("æ: getaddr: c == nil");
n = devtab[c->type]->read(c, buf, sizeof buf-1, 0);
- poperror();
cclose(c);
+ poperror();
buf[n] = 0;
if(parseether(ea, buf) < 0)
error("parseether failure");
snprint(addr, sizeof addr, "%s!0x%x", path, Aoetype);
dc = chandial(addr, nil, nil, &cc);
snprint(addr, sizeof addr, "%s/mtu", path);
- if(waserror())
- mtu = nil;
- else {
+ mtu = nil;
+ if(!waserror()){
mtu = namec(addr, Aopen, OREAD, 0);
poperror();
}
-
if(waserror()){
cclose(dc);
cclose(cc);
- if(mtu)
+ if(mtu != nil)
cclose(mtu);
nexterror();
}
- if(dc == nil || cc == nil)
+ if(dc == nil || cc == nil)
error(Enonexist);
getaddr(path, ea);
nl = addnet(path, cc, dc, mtu, ea);
/* reschedule packets. */
wlock(&devs);
- for(d = devs.d; d; d = d->next){
+ for(d = devs.d; d != nil; d = d->next){
qlock(d);
for(i = 0; i < d->nframes; i++){
f = d->frames + i;
/* squeeze devlink pool. (we assert nobody is using them now) */
wlock(&devs);
- for(d = devs.d; d; d = d->next){
+ for(d = devs.d; d != nil; d = d->next){
qlock(d);
for(i = 0; i < d->ndl; i++){
l = d->dl + i;
lock(&netlinks);
dc = n->dc;
cc = n->cc;
- if(n->mtu)
+ if(n->mtu != nil)
cclose(n->mtu);
memset(n, 0, sizeof *n);
unlock(&netlinks);
/* squeeze orphan devices */
wlock(&devs);
- for(p = d = devs.d; d; d = next){
+ for(p = d = devs.d; d != nil; d = next){
next = d->next;
if(d->ndl > 0){
p = d;
*shelf = 0xffff;
*slot = 0xff;
- if(!f)
+ if(f == nil)
return;
*shelf = strtol(f, &s, 0);
if(s == f || *shelf > 0xffff)
wlock(&devs);
p = 0;
if(d != devs.d)
- for(p = devs.d; p; p = p->next)
+ for(p = devs.d; p != nil; p = p->next)
if(p->next == d)
break;
qlock(d);
for(i = 0; i < d->nframes; i++)
frameerror(d, d->frames+i, Enotup);
- if(p)
+ if(p != nil)
p->next = d->next;
else
devs.d = d->next;
strtoss(f, &shelf, &slot);
wlock(&devs);
- for(d = devs.d; d; d = d->next)
+ for(d = devs.d; d != nil; d = d->next)
if(shelf == d->major && slot == d->minor){
wunlock(&devs); /* BOTCH */
removedev(d);