/* * © 2005-13 coraid * aoe storage initiator */ #include "u.h"#include "../port/lib.h"#include "mem.h"#include "dat.h"#include "fns.h"#include "io.h"#include "ureg.h"#include "../port/error.h"#include "../port/netif.h"#include "etherif.h"#include "../ip/ip.h"#include "../port/aoe.h"#include <fis.h> #pragma varargck argpos eventlog 1 #define dprint(...) if(debug) eventlog(__VA_ARGS__); else USED(debug);#define uprint(...) snprint(up->genbuf, sizeof up->genbuf, __VA_ARGS__); enum { Typebits = 4, Unitbits = 12, L3bits = 4, Maxtype = (1<<Typebits)-1, Maxunits = (1<<Unitbits)-1, Maxl3 = (1<<L3bits)-1, Maxframes = 128, Maxmtu = 100000, Ndevlink = 6, Nea = 6, Nnetlink = 6,}; #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#define Ms2tk(t) (((t)*HZ)/1000)#define Tk2ms(t) (((t)*1000)/HZ) enum { Qzero, Qtopdir = 1, Qtopbase, Qtopctl = Qtopbase, Qtoplog, Qtopend, Qunitdir, Qunitbase, Qctl = Qunitbase, Qdata, Qconfig, Qident, Qdevlinkdir, Qdevlinkbase, Qdevlink = Qdevlinkbase, Qdevlinkend, Qtopfiles = Qtopend-Qtopbase, Qdevlinkfiles = Qdevlinkend-Qdevlinkbase, Eventlen = 256, Nevents = 64, Fread = 0, Fwrite, Tfree = -1, Tmgmt, /* round trip bounds, timeouts, in ticks */ Rtmax = Ms2tk(320), Rtmin = Ms2tk(20), Srbtimeout = 45*HZ, Dbcnt = 1024, Crd = 0x20, Crdext = 0x24, Cwr = 0x30, Cwrext = 0x34, Cid = 0xec, Alloc = 0x01234567, Free = 0x89abcdef,}; enum { Read, Write,}; /* * unified set of flags * a Netlink + Aoedev most both be jumbo capable * to send jumbograms to that interface. */enum { Dup = 1<<0, Djumbo = 1<<1, Dnofail = 1<<2,}; static char *flagname[] = { "up", "jumbo", "nofail",}; typedef struct { uchar flag; uint lostjumbo; Chan *cc; Chan *dc; Chan *mtu; /* open early to prevent bind issues. */ char path[Maxpath]; uchar ea[Eaddrlen];} Netlink; typedef struct { Netlink *nl; int nea; ulong eaidx; uchar eatab[Nea][Eaddrlen]; int datamtu; ulong npkt; ulong resent; uchar flag; ulong rttavg; ulong mintimer;} Devlink; typedef struct Srb Srb;struct Srb { Rendez; uint state; Srb *next; ulong ticksent; ulong len; vlong sector; short write; short nout; char *error; void *dp; void *data;}; typedef struct { int tag; ulong bcnt; ulong dlen; vlong lba; ulong ticksent; int nhdr; uchar hdr[ETHERMINTU]; void *dp; Devlink *dl; Netlink *nl; int eaidx; Srb *srb;} Frame; typedef struct Aoedev Aoedev;struct Aoedev { QLock; Aoedev *next; ulong vers; int ndl; ulong dlidx; Devlink *dl; Devlink dltab[Ndevlink]; uchar flag; ushort fwver; int nopen; uint major; uint minor; int unit; int lasttag; int nframes; Frame *frames; vlong bsize; vlong realbsize; uint maxbcnt; uint maxmtu; ulong lostjumbo; ushort nout; ushort maxout; ulong lastwadj; Srb *head; Srb *tail; Srb *inprocess; Sfis; char serial[20+1]; char firmware[8+1]; char model[40+1]; int nconfig; uchar config[1024]; uchar ident[512];}; #pragma varargck type "æ" Aoedev* static struct { Lock; QLock; Rendez; char buf[Eventlen*Nevents]; char *rp; char *wp;} events; static struct { RWlock; int nd; Aoedev *d;} devs; static struct { Lock; int reader[Nnetlink]; /* reader is running. */ Rendez rendez[Nnetlink]; /* confirm exit. */ Netlink nl[Nnetlink];} netlinks; extern Dev aoedevtab;static Ref units;static Ref drivevers;static int debug;static int autodiscover = 1;static int rediscover;extern char Enotup[] = "aoe device is down"; static Srb*srballoc(ulong sz){ Srb *srb; srb = smalloc(sizeof *srb+sz); srb->state = Alloc; srb->dp = srb->data = srb+1; srb->ticksent = Ticks; return srb;} static Srb*srbkalloc(void *db, ulong){ Srb *srb; srb = smalloc(sizeof *srb); srb->state = Alloc; srb->dp = srb->data = db; srb->ticksent = Ticks; return srb;} static intsrbready(void *v){ Srb *s; s = v; return s->nout == 0 && (s->len == 0 || s->error != nil);} static voidsrbfree(Srb *srb){ int n; for(n = 0; srb->state != Free; n++) sched(); free(srb);} /* under Aoedev qlock() so setting of srb->state is safe */static voidsrbwakeup(Srb *srb){ if(srbready(srb)){ assert(srb->state == Alloc); wakeup(srb); srb->state = Free; }} static voidsrbcleanout(Aoedev *d, Srb *srb){ Srb *x, **ll; if(srb == d->inprocess) d->inprocess = nil; else for(ll = &d->head; (x = *ll) != nil; ll = &x->next){ d->tail = x; if(x == srb) *ll = x->next; }} static voidsrberror(Aoedev *d, Srb *srb, char *s){ srbcleanout(d, srb); srb->error = s; srbwakeup(srb);} static voidframeerror(Aoedev *d, Frame *f, char *s){ Srb *srb; if(f->tag == Tfree) return; srb = f->srb; f->srb = nil; f->tag = Tfree; /* don't get fooled by way-slow responses */ if(srb == nil) return; srb->nout--; srberror(d, srb, s); d->nout--;} static char*unitname(Aoedev *d){ uprint("%ud.%ud", d->major, d->minor); return up->genbuf;} static longeventlogread(void *a, long n){ int len; char *p, *buf; buf = smalloc(Eventlen); qlock(&events); lock(&events); p = events.rp; len = *p; if(len == 0){ n = 0; unlock(&events); } else { if(n > len) n = len; /* can't move directly into pageable space with events lock held */ memmove(buf, p+1, n); *p = 0; events.rp = p += Eventlen; if(p >= events.buf + sizeof events.buf) events.rp = events.buf; unlock(&events); /* the concern here is page faults in memmove below */ if(waserror()){ qunlock(&events); free(buf); nexterror(); } memmove(a, buf, n); poperror(); } qunlock(&events); free(buf); return n;} static inteventlog(char *fmt, ...){ int dragrp, n; char *p; va_list arg; lock(&events); p = events.wp; dragrp = *p++; va_start(arg, fmt); n = vsnprint(p, Eventlen-1, fmt, arg); *--p = n; p = events.wp += Eventlen; if(p >= events.buf + sizeof events.buf) p = events.wp = events.buf; if(dragrp) events.rp = p; unlock(&events); wakeup(&events); return n;} static inteventcount(void){ uint n; lock(&events); if(*events.rp == 0) n = 0; else n = events.wp - events.rp & Nevents - 1; unlock(&events); return n/Eventlen;} static inttsince(int tag){ int n; n = Ticks & 0xffff; n -= tag & 0xffff; if(n < 0) n += 1<<16; return n;} static intnewtag(Aoedev *d){ int t; do { t = ++d->lasttag << 16; t |= Ticks & 0xffff; } while (t == Tfree || t == Tmgmt); return t;} static voiddowndev(Aoedev *d, char *err){ Frame *f, *e; d->flag &= ~Dup; f = d->frames; e = f + d->nframes; for(; f < e; f++) frameerror(d, f, Enotup); d->inprocess = nil; eventlog("%æ: removed; %s\n", d, err);} static Block*allocfb(Frame *f){ int len; Block *b; len = f->nhdr + f->dlen; if(len < ETHERMINTU) len = ETHERMINTU; b = allocb(len); memmove(b->wp, f->hdr, f->nhdr); if(f->dlen) memmove(b->wp + f->nhdr, f->dp, f->dlen); b->wp += len; return b;} static voidputlba(Aoeata *a, vlong lba){ uchar *c; c = a->lba; c[0] = lba; c[1] = lba >> 8; c[2] = lba >> 16; c[3] = lba >> 24; c[4] = lba >> 32; c[5] = lba >> 40;} static Devlink*pickdevlink(Aoedev *d){ ulong i, n; Devlink *l;Lines 1–500 of 2604. Load more
/* * © 2005-13 coraid * aoe storage initiator */ #include "u.h" #include "../port/lib.h" #include "mem.h" #include "dat.h" #include "fns.h" #include "io.h" #include "ureg.h" #include "../port/error.h" #include "../port/netif.h" #include "etherif.h" #include "../ip/ip.h" #include "../port/aoe.h" #include <fis.h> #pragma varargck argpos eventlog 1 #define dprint(...) if(debug) eventlog(__VA_ARGS__); else USED(debug); #define uprint(...) snprint(up->genbuf, sizeof up->genbuf, __VA_ARGS__); enum { Typebits = 4, Unitbits = 12, L3bits = 4, Maxtype = (1<<Typebits)-1, Maxunits = (1<<Unitbits)-1, Maxl3 = (1<<L3bits)-1, Maxframes = 128, Maxmtu = 100000, Ndevlink = 6, Nea = 6, Nnetlink = 6, }; #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 #define Ms2tk(t) (((t)*HZ)/1000) #define Tk2ms(t) (((t)*1000)/HZ) enum { Qzero, Qtopdir = 1, Qtopbase, Qtopctl = Qtopbase, Qtoplog, Qtopend, Qunitdir, Qunitbase, Qctl = Qunitbase, Qdata, Qconfig, Qident, Qdevlinkdir, Qdevlinkbase, Qdevlink = Qdevlinkbase, Qdevlinkend, Qtopfiles = Qtopend-Qtopbase, Qdevlinkfiles = Qdevlinkend-Qdevlinkbase, Eventlen = 256, Nevents = 64, Fread = 0, Fwrite, Tfree = -1, Tmgmt, /* round trip bounds, timeouts, in ticks */ Rtmax = Ms2tk(320), Rtmin = Ms2tk(20), Srbtimeout = 45*HZ, Dbcnt = 1024, Crd = 0x20, Crdext = 0x24, Cwr = 0x30, Cwrext = 0x34, Cid = 0xec, Alloc = 0x01234567, Free = 0x89abcdef, }; enum { Read, Write, }; /* * unified set of flags * a Netlink + Aoedev most both be jumbo capable * to send jumbograms to that interface. */ enum { Dup = 1<<0, Djumbo = 1<<1, Dnofail = 1<<2, }; static char *flagname[] = { "up", "jumbo", "nofail", }; typedef struct { uchar flag; uint lostjumbo; Chan *cc; Chan *dc; Chan *mtu; /* open early to prevent bind issues. */ char path[Maxpath]; uchar ea[Eaddrlen]; } Netlink; typedef struct { Netlink *nl; int nea; ulong eaidx; uchar eatab[Nea][Eaddrlen]; int datamtu; ulong npkt; ulong resent; uchar flag; ulong rttavg; ulong mintimer; } Devlink; typedef struct Srb Srb; struct Srb { Rendez; uint state; Srb *next; ulong ticksent; ulong len; vlong sector; short write; short nout; char *error; void *dp; void *data; }; typedef struct { int tag; ulong bcnt; ulong dlen; vlong lba; ulong ticksent; int nhdr; uchar hdr[ETHERMINTU]; void *dp; Devlink *dl; Netlink *nl; int eaidx; Srb *srb; } Frame; typedef struct Aoedev Aoedev; struct Aoedev { QLock; Aoedev *next; ulong vers; int ndl; ulong dlidx; Devlink *dl; Devlink dltab[Ndevlink]; uchar flag; ushort fwver; int nopen; uint major; uint minor; int unit; int lasttag; int nframes; Frame *frames; vlong bsize; vlong realbsize; uint maxbcnt; uint maxmtu; ulong lostjumbo; ushort nout; ushort maxout; ulong lastwadj; Srb *head; Srb *tail; Srb *inprocess; Sfis; char serial[20+1]; char firmware[8+1]; char model[40+1]; int nconfig; uchar config[1024]; uchar ident[512]; }; #pragma varargck type "æ" Aoedev* static struct { Lock; QLock; Rendez; char buf[Eventlen*Nevents]; char *rp; char *wp; } events; static struct { RWlock; int nd; Aoedev *d; } devs; static struct { Lock; int reader[Nnetlink]; /* reader is running. */ Rendez rendez[Nnetlink]; /* confirm exit. */ Netlink nl[Nnetlink]; } netlinks; extern Dev aoedevtab; static Ref units; static Ref drivevers; static int debug; static int autodiscover = 1; static int rediscover; extern char Enotup[] = "aoe device is down"; static Srb* srballoc(ulong sz) { Srb *srb; srb = smalloc(sizeof *srb+sz); srb->state = Alloc; srb->dp = srb->data = srb+1; srb->ticksent = Ticks; return srb; } static Srb* srbkalloc(void *db, ulong) { Srb *srb; srb = smalloc(sizeof *srb); srb->state = Alloc; srb->dp = srb->data = db; srb->ticksent = Ticks; return srb; } static int srbready(void *v) { Srb *s; s = v; return s->nout == 0 && (s->len == 0 || s->error != nil); } static void srbfree(Srb *srb) { int n; for(n = 0; srb->state != Free; n++) sched(); free(srb); } /* under Aoedev qlock() so setting of srb->state is safe */ static void srbwakeup(Srb *srb) { if(srbready(srb)){ assert(srb->state == Alloc); wakeup(srb); srb->state = Free; } } static void srbcleanout(Aoedev *d, Srb *srb) { Srb *x, **ll; if(srb == d->inprocess) d->inprocess = nil; else for(ll = &d->head; (x = *ll) != nil; ll = &x->next){ d->tail = x; if(x == srb) *ll = x->next; } } static void srberror(Aoedev *d, Srb *srb, char *s) { srbcleanout(d, srb); srb->error = s; srbwakeup(srb); } static void frameerror(Aoedev *d, Frame *f, char *s) { Srb *srb; if(f->tag == Tfree) return; srb = f->srb; f->srb = nil; f->tag = Tfree; /* don't get fooled by way-slow responses */ if(srb == nil) return; srb->nout--; srberror(d, srb, s); d->nout--; } static char* unitname(Aoedev *d) { uprint("%ud.%ud", d->major, d->minor); return up->genbuf; } static long eventlogread(void *a, long n) { int len; char *p, *buf; buf = smalloc(Eventlen); qlock(&events); lock(&events); p = events.rp; len = *p; if(len == 0){ n = 0; unlock(&events); } else { if(n > len) n = len; /* can't move directly into pageable space with events lock held */ memmove(buf, p+1, n); *p = 0; events.rp = p += Eventlen; if(p >= events.buf + sizeof events.buf) events.rp = events.buf; unlock(&events); /* the concern here is page faults in memmove below */ if(waserror()){ qunlock(&events); free(buf); nexterror(); } memmove(a, buf, n); poperror(); } qunlock(&events); free(buf); return n; } static int eventlog(char *fmt, ...) { int dragrp, n; char *p; va_list arg; lock(&events); p = events.wp; dragrp = *p++; va_start(arg, fmt); n = vsnprint(p, Eventlen-1, fmt, arg); *--p = n; p = events.wp += Eventlen; if(p >= events.buf + sizeof events.buf) p = events.wp = events.buf; if(dragrp) events.rp = p; unlock(&events); wakeup(&events); return n; } static int eventcount(void) { uint n; lock(&events); if(*events.rp == 0) n = 0; else n = events.wp - events.rp & Nevents - 1; unlock(&events); return n/Eventlen; } static int tsince(int tag) { int n; n = Ticks & 0xffff; n -= tag & 0xffff; if(n < 0) n += 1<<16; return n; } static int newtag(Aoedev *d) { int t; do { t = ++d->lasttag << 16; t |= Ticks & 0xffff; } while (t == Tfree || t == Tmgmt); return t; } static void downdev(Aoedev *d, char *err) { Frame *f, *e; d->flag &= ~Dup; f = d->frames; e = f + d->nframes; for(; f < e; f++) frameerror(d, f, Enotup); d->inprocess = nil; eventlog("%æ: removed; %s\n", d, err); } static Block* allocfb(Frame *f) { int len; Block *b; len = f->nhdr + f->dlen; if(len < ETHERMINTU) len = ETHERMINTU; b = allocb(len); memmove(b->wp, f->hdr, f->nhdr); if(f->dlen) memmove(b->wp + f->nhdr, f->dp, f->dlen); b->wp += len; return b; } static void putlba(Aoeata *a, vlong lba) { uchar *c; c = a->lba; c[0] = lba; c[1] = lba >> 8; c[2] = lba >> 16; c[3] = lba >> 24; c[4] = lba >> 32; c[5] = lba >> 40; } static Devlink* pickdevlink(Aoedev *d) { ulong i, n; Devlink *l;