devaoe.c 43 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836183718381839184018411842184318441845184618471848184918501851185218531854185518561857185818591860186118621863186418651866186718681869187018711872187318741875187618771878187918801881188218831884188518861887188818891890189118921893189418951896189718981899190019011902190319041905190619071908190919101911191219131914191519161917191819191920192119221923192419251926192719281929193019311932193319341935193619371938193919401941194219431944194519461947194819491950195119521953195419551956195719581959196019611962196319641965196619671968196919701971197219731974197519761977197819791980198119821983198419851986198719881989199019911992199319941995199619971998199920002001200220032004200520062007200820092010201120122013201420152016201720182019202020212022202320242025202620272028202920302031203220332034203520362037203820392040204120422043204420452046204720482049205020512052205320542055205620572058205920602061206220632064206520662067206820692070207120722073207420752076207720782079208020812082208320842085208620872088208920902091209220932094209520962097209820992100210121022103210421052106210721082109211021112112211321142115211621172118211921202121212221232124212521262127212821292130213121322133213421352136213721382139214021412142214321442145214621472148214921502151215221532154215521562157215821592160216121622163216421652166216721682169217021712172217321742175217621772178217921802181218221832184218521862187218821892190219121922193219421952196219721982199220022012202220322042205220622072208220922102211221222132214221522162217221822192220222122222223222422252226222722282229223022312232223322342235223622372238223922402241224222432244224522462247224822492250225122522253225422552256225722582259226022612262226322642265226622672268226922702271227222732274227522762277227822792280228122822283228422852286228722882289229022912292229322942295229622972298229923002301230223032304230523062307230823092310231123122313231423152316231723182319232023212322232323242325232623272328232923302331233223332334233523362337233823392340234123422343234423452346234723482349235023512352235323542355235623572358235923602361236223632364236523662367236823692370237123722373237423752376237723782379238023812382238323842385238623872388238923902391239223932394239523962397239823992400240124022403240424052406240724082409241024112412241324142415241624172418241924202421242224232424242524262427242824292430243124322433243424352436243724382439244024412442244324442445244624472448244924502451245224532454245524562457245824592460246124622463246424652466246724682469247024712472247324742475247624772478247924802481248224832484248524862487248824892490249124922493249424952496249724982499250025012502250325042505250625072508250925102511251225132514251525162517251825192520252125222523252425252526252725282529253025312532253325342535253625372538253925402541254225432544
  1. /*
  2. * This file is part of the UCB release of Plan 9. It is subject to the license
  3. * terms in the LICENSE file found in the top-level directory of this
  4. * distribution and at http://akaros.cs.berkeley.edu/files/Plan9License. No
  5. * part of the UCB release of Plan 9, including this file, may be copied,
  6. * modified, propagated, or distributed except according to the terms contained
  7. * in the LICENSE file.
  8. */
  9. /*
  10. * © 2005-7 coraid
  11. * aoe storage initiator
  12. */
  13. #include "u.h"
  14. #include "../port/lib.h"
  15. #include "mem.h"
  16. #include "dat.h"
  17. #include "fns.h"
  18. #include "../port/error.h"
  19. #include "../port/netif.h"
  20. #include "../ip/ip.h"
  21. #include "etherif.h"
  22. #include "aoe.h"
  23. #pragma varargck argpos eventlog 1
  24. #define dprint(...) if(debug) eventlog(__VA_ARGS__); else USED(debug);
  25. #define uprint(...) snprint(up->genbuf, sizeof up->genbuf, __VA_ARGS__);
  26. enum {
  27. Maxunits = 0xff,
  28. Maxframes = 128,
  29. Ndevlink = 6,
  30. Nea = 6,
  31. Nnetlink = 6,
  32. // ETHERMINTU = 60, /* minimum transmit size */
  33. // ETHERMAXTU = 1514, /* maximum transmit size */
  34. };
  35. #define TYPE(q) ((uint32_t)(q).path & 0xf)
  36. #define UNIT(q) (((uint32_t)(q).path>>4) & 0xff)
  37. #define L(q) (((uint32_t)(q).path>>12) & 0xf)
  38. #define QID(u, t) ((u)<<4 | (t))
  39. #define Q3(l, u, t) ((l)<<8 | QID(u, t))
  40. #define UP(d) ((d)->flag & Dup)
  41. #define Ms2tk(t) (((t)*HZ)/1000)
  42. #define Tk2ms(t) (((t)*1000)/HZ)
  43. enum {
  44. Qzero,
  45. Qtopdir = 1,
  46. Qtopbase,
  47. Qtopctl = Qtopbase,
  48. Qtoplog,
  49. Qtopend,
  50. Qunitdir,
  51. Qunitbase,
  52. Qctl = Qunitbase,
  53. Qdata,
  54. Qconfig,
  55. Qident,
  56. Qdevlinkdir,
  57. Qdevlinkbase,
  58. Qdevlink = Qdevlinkbase,
  59. Qdevlinkend,
  60. Qtopfiles = Qtopend-Qtopbase,
  61. Qdevlinkfiles = Qdevlinkend-Qdevlinkbase,
  62. Eventlen = 256,
  63. Nevents = 64,
  64. Fread = 0,
  65. Fwrite,
  66. Tfree = -1,
  67. Tmgmt,
  68. /* round trip bounds, timeouts, in ticks */
  69. Rtmax = Ms2tk(320),
  70. Rtmin = Ms2tk(20),
  71. Srbtimeout = 4*60*HZ,
  72. Dbcnt = 1024,
  73. Crd = 0x20,
  74. Crdext = 0x24,
  75. Cwr = 0x30,
  76. Cwrext = 0x34,
  77. Cid = 0xec,
  78. };
  79. enum {
  80. Read,
  81. Write,
  82. };
  83. /*
  84. * unified set of flags
  85. * a Netlink + Aoedev most both be jumbo capable
  86. * to send jumbograms to that interface.
  87. */
  88. enum {
  89. /* sync with ahci.h */
  90. Dllba = 1<<0,
  91. Dsmart = 1<<1,
  92. Dpower = 1<<2,
  93. Dnop = 1<<3,
  94. Datapi = 1<<4,
  95. Datapi16= 1<<5,
  96. /* aoe specific */
  97. Dup = 1<<6,
  98. Djumbo = 1<<7,
  99. };
  100. static char *flagname[] = {
  101. "llba",
  102. "smart",
  103. "power",
  104. "nop",
  105. "atapi",
  106. "atapi16",
  107. "up",
  108. "jumbo",
  109. };
  110. typedef struct {
  111. uint8_t flag;
  112. uint8_t lostjumbo;
  113. int datamtu;
  114. Chan *cc;
  115. Chan *dc;
  116. Chan *mtu; /* open early to prevent bind issues. */
  117. char path[Maxpath];
  118. uint8_t ea[Eaddrlen];
  119. } Netlink;
  120. typedef struct {
  121. Netlink *nl;
  122. int nea;
  123. uint32_t eaidx;
  124. uint8_t eatab[Nea][Eaddrlen];
  125. uint32_t npkt;
  126. uint32_t resent;
  127. uint8_t flag;
  128. uint32_t rttavg;
  129. uint32_t mintimer;
  130. } Devlink;
  131. typedef struct Srb Srb;
  132. struct Srb {
  133. Rendez;
  134. Srb *next;
  135. uint32_t ticksent;
  136. uint32_t len;
  137. int64_t sector;
  138. short write;
  139. short nout;
  140. char *error;
  141. void *dp;
  142. void *data;
  143. };
  144. typedef struct {
  145. int tag;
  146. uint32_t bcnt;
  147. uint32_t dlen;
  148. int64_t lba;
  149. uint32_t ticksent;
  150. int nhdr;
  151. uint8_t hdr[ETHERMINTU];
  152. void *dp;
  153. Devlink *dl;
  154. Netlink *nl;
  155. int eaidx;
  156. Srb *srb;
  157. } Frame;
  158. typedef struct Aoedev Aoedev;
  159. struct Aoedev {
  160. QLock;
  161. Aoedev *next;
  162. uint32_t vers;
  163. int ndl;
  164. uint32_t dlidx;
  165. Devlink *dl;
  166. Devlink dltab[Ndevlink];
  167. uint16_t fwver;
  168. unsigned char flag;
  169. int nopen;
  170. int major;
  171. int minor;
  172. int unit;
  173. int lasttag;
  174. int nframes;
  175. Frame *frames;
  176. int64_t bsize;
  177. int64_t realbsize;
  178. uint maxbcnt;
  179. uint32_t lostjumbo;
  180. uint16_t nout;
  181. uint16_t maxout;
  182. uint32_t lastwadj;
  183. Srb *_head;
  184. Srb *_tail;
  185. Srb *inprocess;
  186. /* magic numbers 'R' us */
  187. char serial[20+1];
  188. char firmware[8+1];
  189. char model[40+1];
  190. int nconfig;
  191. unsigned char config[1024];
  192. unsigned char ident[512];
  193. };
  194. #pragma varargck type "æ" Aoedev*
  195. static struct {
  196. Lock;
  197. QLock;
  198. Rendez _rendez;
  199. char buf[Eventlen*Nevents];
  200. char *rp;
  201. char *wp;
  202. } events;
  203. static struct {
  204. RWlock;
  205. int nd;
  206. Aoedev *d;
  207. } devs;
  208. static struct {
  209. Lock;
  210. int reader[Nnetlink]; /* reader is running. */
  211. Rendez rendez[Nnetlink]; /* confirm exit. */
  212. Netlink nl[Nnetlink];
  213. } netlinks;
  214. extern Dev aoedevtab;
  215. static Ref units;
  216. static Ref drivevers;
  217. static int debug;
  218. static int autodiscover = 1;
  219. static int rediscover;
  220. char Enotup[] = "aoe device is down";
  221. char Echange[] = "media or partition has changed";
  222. static Srb*
  223. srballoc(uint32_t sz)
  224. {
  225. Srb *srb;
  226. srb = malloc(sizeof *srb+sz);
  227. srb->dp = srb->data = srb+1;
  228. srb->ticksent = sys->ticks;
  229. return srb;
  230. }
  231. static Srb*
  232. srbkalloc(void *db, uint32_t n)
  233. {
  234. Srb *srb;
  235. srb = malloc(sizeof *srb);
  236. srb->dp = srb->data = db;
  237. srb->ticksent = sys->ticks;
  238. return srb;
  239. }
  240. #define srbfree(srb) free(srb)
  241. static void
  242. srberror(Srb *srb, char *s)
  243. {
  244. srb->error = s;
  245. srb->nout--;
  246. if (srb->nout == 0)
  247. wakeup(srb);
  248. }
  249. static void
  250. frameerror(Aoedev *d, Frame *f, char *s)
  251. {
  252. Srb *srb;
  253. srb = f->srb;
  254. if(f->tag == Tfree || !srb)
  255. return;
  256. f->srb = nil;
  257. f->tag = Tfree; /* don't get fooled by way-slow responses */
  258. srberror(srb, s);
  259. d->nout--;
  260. }
  261. static char*
  262. unitname(Aoedev *d)
  263. {
  264. Proc *up = externup();
  265. uprint("%d.%d", d->major, d->minor);
  266. return up->genbuf;
  267. }
  268. #if 0
  269. static int
  270. eventlogready(void* v)
  271. {
  272. return *events.rp;
  273. }
  274. #endif
  275. static int32_t
  276. eventlogread(void *a, int32_t n)
  277. {
  278. Proc *up = externup();
  279. int len;
  280. char *p, *buf;
  281. buf = smalloc(Eventlen);
  282. qlock(&events);
  283. lock(&events);
  284. p = events.rp;
  285. len = *p;
  286. if(len == 0){
  287. n = 0;
  288. unlock(&events);
  289. } else {
  290. if(n > len)
  291. n = len;
  292. /* can't move directly into pageable space with events lock held */
  293. memmove(buf, p+1, n);
  294. *p = 0;
  295. events.rp = p += Eventlen;
  296. if(p >= events.buf + sizeof events.buf)
  297. events.rp = events.buf;
  298. unlock(&events);
  299. /* the concern here is page faults in memmove below */
  300. if(waserror()){
  301. free(buf);
  302. qunlock(&events);
  303. nexterror();
  304. }
  305. memmove(a, buf, n);
  306. poperror();
  307. }
  308. free(buf);
  309. qunlock(&events);
  310. return n;
  311. }
  312. static int
  313. eventlog(char *fmt, ...)
  314. {
  315. int dragrp, n;
  316. char *p;
  317. va_list arg;
  318. lock(&events);
  319. p = events.wp;
  320. dragrp = *p++;
  321. va_start(arg, fmt);
  322. n = vsnprint(p, Eventlen-1, fmt, arg);
  323. *--p = n;
  324. p = events.wp += Eventlen;
  325. if(p >= events.buf + sizeof events.buf)
  326. p = events.wp = events.buf;
  327. if(dragrp)
  328. events.rp = p;
  329. unlock(&events);
  330. wakeup(&events._rendez);
  331. return n;
  332. }
  333. static int
  334. eventcount(void)
  335. {
  336. int n;
  337. lock(&events);
  338. if(*events.rp == 0)
  339. n = 0;
  340. else if(events.wp < events.rp)
  341. n = Nevents - (events.rp - events.wp);
  342. else
  343. n = events.wp - events.rp;
  344. unlock(&events);
  345. return n/Eventlen;
  346. }
  347. static int
  348. tsince(int tag)
  349. {
  350. int n;
  351. n = sys->ticks & 0xffff;
  352. n -= tag & 0xffff;
  353. if(n < 0)
  354. n += 1<<16;
  355. return n;
  356. }
  357. static int
  358. newtag(Aoedev *d)
  359. {
  360. int t;
  361. do {
  362. t = ++d->lasttag << 16;
  363. t |= sys->ticks & 0xffff;
  364. } while (t == Tfree || t == Tmgmt);
  365. return t;
  366. }
  367. static void
  368. downdev(Aoedev *d, char *err)
  369. {
  370. Frame *f, *e;
  371. d->flag &= ~Dup;
  372. f = d->frames;
  373. e = f + d->nframes;
  374. for(; f < e; f->tag = Tfree, f->srb = nil, f++)
  375. frameerror(d, f, Enotup);
  376. d->inprocess = nil;
  377. eventlog("%æ: removed; %s\n", d, err);
  378. }
  379. static Block*
  380. allocfb(Frame *f)
  381. {
  382. int len;
  383. Block *b;
  384. len = f->nhdr + f->dlen;
  385. if(len < ETHERMINTU)
  386. len = ETHERMINTU;
  387. b = allocb(len);
  388. memmove(b->wp, f->hdr, f->nhdr);
  389. if(f->dlen)
  390. memmove(b->wp + f->nhdr, f->dp, f->dlen);
  391. b->wp += len;
  392. return b;
  393. }
  394. static void
  395. putlba(Aoeata *a, int64_t lba)
  396. {
  397. uint8_t *c;
  398. c = a->lba;
  399. c[0] = lba;
  400. c[1] = lba >> 8;
  401. c[2] = lba >> 16;
  402. c[3] = lba >> 24;
  403. c[4] = lba >> 32;
  404. c[5] = lba >> 40;
  405. }
  406. static Devlink*
  407. pickdevlink(Aoedev *d)
  408. {
  409. uint32_t i, n;
  410. Devlink *l;
  411. for(i = 0; i < d->ndl; i++){
  412. n = d->dlidx++ % d->ndl;
  413. l = d->dl + n;
  414. if(l && l->flag & Dup)
  415. return l;
  416. }
  417. return 0;
  418. }
  419. static int
  420. pickea(Devlink *l)
  421. {
  422. if(l == 0)
  423. return -1;
  424. if(l->nea == 0)
  425. return -1;
  426. return l->eaidx++ % l->nea;
  427. }
  428. static int
  429. hset(Aoedev *d, Frame *f, Aoehdr *h, int cmd)
  430. {
  431. int i;
  432. Devlink *l;
  433. l = pickdevlink(d);
  434. i = pickea(l);
  435. if(i == -1){
  436. downdev(d, "resend fails; no netlink/ea");
  437. return -1;
  438. }
  439. if(f->srb && sys->ticks - f->srb->ticksent > Srbtimeout){
  440. eventlog("%æ: srb timeout\n", d);
  441. frameerror(d, f, Etimedout);
  442. return -1;
  443. }
  444. memmove(h->dst, l->eatab[i], Eaddrlen);
  445. memmove(h->src, l->nl->ea, sizeof h->src);
  446. hnputs(h->type, Aoetype);
  447. h->verflag = Aoever << 4;
  448. h->error = 0;
  449. hnputs(h->major, d->major);
  450. h->minor = d->minor;
  451. h->cmd = cmd;
  452. hnputl(h->tag, f->tag = newtag(d));
  453. f->dl = l;
  454. f->nl = l->nl;
  455. f->eaidx = i;
  456. f->ticksent = sys->ticks;
  457. return f->tag;
  458. }
  459. static int
  460. resend(Aoedev *d, Frame *f)
  461. {
  462. Proc *up = externup();
  463. uint32_t n;
  464. Aoeata *a;
  465. a = (Aoeata*)f->hdr;
  466. if(hset(d, f, a, a->cmd) == -1)
  467. return -1;
  468. n = f->bcnt;
  469. if(n > d->maxbcnt){
  470. n = d->maxbcnt; /* mtu mismatch (jumbo fail?) */
  471. if(f->dlen > n)
  472. f->dlen = n;
  473. }
  474. a->scnt = n / Aoesectsz;
  475. f->dl->resent++;
  476. f->dl->npkt++;
  477. if(waserror())
  478. return -1;
  479. f->nl->dc->dev->bwrite(f->nl->dc, allocfb(f), 0);
  480. poperror();
  481. return 0;
  482. }
  483. static void
  484. discover(int major, int minor)
  485. {
  486. Proc *up = externup();
  487. Aoehdr *h;
  488. Block *b;
  489. Netlink *nl, *e;
  490. nl = netlinks.nl;
  491. e = nl + nelem(netlinks.nl);
  492. for(; nl < e; nl++){
  493. if(nl->cc == nil)
  494. continue;
  495. b = allocb(ETHERMINTU);
  496. if(waserror()){
  497. freeb(b);
  498. nexterror();
  499. }
  500. b->wp = b->rp + ETHERMINTU;
  501. memset(b->rp, 0, ETHERMINTU);
  502. h = (Aoehdr*)b->rp;
  503. memset(h->dst, 0xff, sizeof h->dst);
  504. memmove(h->src, nl->ea, sizeof h->src);
  505. hnputs(h->type, Aoetype);
  506. h->verflag = Aoever << 4;
  507. hnputs(h->major, major);
  508. h->minor = minor;
  509. h->cmd = ACconfig;
  510. poperror();
  511. /* send b down the queue */
  512. nl->dc->dev->bwrite(nl->dc, b, 0);
  513. }
  514. }
  515. /*
  516. * Check all frames on device and resend any frames that have been
  517. * outstanding for 200% of the device round trip time average.
  518. */
  519. static void
  520. aoesweepproc(void* v)
  521. {
  522. Proc *up = externup();
  523. uint32_t i, tx, timeout, nbc;
  524. int64_t starttick;
  525. enum { Nms = 100, Nbcms = 30*1000, };
  526. uint8_t *ea;
  527. Aoeata *a;
  528. Aoedev *d;
  529. Devlink *l;
  530. Frame *f, *e;
  531. nbc = Nbcms/Nms;
  532. loop:
  533. if(nbc-- == 0){
  534. if(rediscover && !waserror()){
  535. discover(0xffff, 0xff);
  536. poperror();
  537. }
  538. nbc = Nbcms/Nms;
  539. }
  540. starttick = sys->ticks;
  541. rlock(&devs);
  542. for(d = devs.d; d; d = d->next){
  543. if(!canqlock(d))
  544. continue;
  545. if(!UP(d)){
  546. qunlock(d);
  547. continue;
  548. }
  549. tx = 0;
  550. f = d->frames;
  551. e = f + d->nframes;
  552. for (; f < e; f++){
  553. if(f->tag == Tfree)
  554. continue;
  555. l = f->dl;
  556. timeout = l->rttavg << 1;
  557. i = tsince(f->tag);
  558. if(i < timeout)
  559. continue;
  560. if(d->nout == d->maxout){
  561. if(d->maxout > 1)
  562. d->maxout--;
  563. d->lastwadj = sys->ticks;
  564. }
  565. a = (Aoeata*)f->hdr;
  566. if(a->scnt > Dbcnt / Aoesectsz &&
  567. ++f->nl->lostjumbo > (d->nframes << 1)){
  568. ea = f->dl->eatab[f->eaidx];
  569. eventlog("%æ: jumbo failure on %s:%E; lba%lld\n",
  570. d, f->nl->path, ea, f->lba);
  571. d->maxbcnt = Dbcnt;
  572. d->flag &= ~Djumbo;
  573. }
  574. resend(d, f);
  575. if(tx++ == 0){
  576. if((l->rttavg <<= 1) > Rtmax)
  577. l->rttavg = Rtmax;
  578. eventlog("%æ: rtt %ldms\n", d, Tk2ms(l->rttavg));
  579. }
  580. }
  581. if(d->nout == d->maxout && d->maxout < d->nframes &&
  582. TK2MS(sys->ticks - d->lastwadj) > 10*1000){
  583. d->maxout++;
  584. d->lastwadj = sys->ticks;
  585. }
  586. qunlock(d);
  587. }
  588. runlock(&devs);
  589. i = Nms - TK2MS(sys->ticks - starttick);
  590. if(i > 0)
  591. tsleep(&up->sleep, return0, 0, i);
  592. goto loop;
  593. }
  594. static int
  595. fmta(Fmt *f)
  596. {
  597. char buf[8];
  598. Aoedev *d;
  599. d = va_arg(f->args, Aoedev*);
  600. snprint(buf, sizeof buf, "aoe%d.%d", d->major, d->minor);
  601. return fmtstrcpy(f, buf);
  602. }
  603. static void netbind(char *path);
  604. static void
  605. aoecfg(void)
  606. {
  607. Proc *up = externup();
  608. int n, i;
  609. char *p, *f[32], buf[24];
  610. // if((p = getconf("aoeif")) == nil || (n = tokenize(p, f, nelem(f))) < 1)
  611. return;
  612. /* goo! */
  613. for(i = 0; i < n; i++){
  614. p = f[i];
  615. if(strncmp(p, "ether", 5) == 0)
  616. snprint(buf, sizeof buf, "#l%c/ether%c", p[5], p[5]);
  617. else if(strncmp(p, "#l", 2) == 0)
  618. snprint(buf, sizeof buf, "#l%c/ether%c", p[2], p[2]);
  619. else
  620. continue;
  621. if(!waserror()){
  622. netbind(buf);
  623. poperror();
  624. }
  625. }
  626. }
  627. static void
  628. aoeinit(void)
  629. {
  630. static int init;
  631. static QLock l;
  632. if(!canqlock(&l))
  633. return;
  634. if(init == 0){
  635. fmtinstall(L'a', fmta);
  636. events.rp = events.wp = events.buf;
  637. kproc("aoesweep", aoesweepproc, nil);
  638. aoecfg();
  639. init = 1;
  640. }
  641. qunlock(&l);
  642. }
  643. static Chan*
  644. aoeattach(char *spec)
  645. {
  646. Chan *c;
  647. if(*spec)
  648. error(Enonexist);
  649. aoeinit();
  650. c = devattach(L'æ', spec);
  651. mkqid(&c->qid, Qzero, 0, QTDIR);
  652. return c;
  653. }
  654. static Aoedev*
  655. unit2dev(uint32_t unit)
  656. {
  657. Proc *up = externup();
  658. int i;
  659. Aoedev *d;
  660. rlock(&devs);
  661. i = 0;
  662. for(d = devs.d; d; d = d->next)
  663. if(i++ == unit){
  664. runlock(&devs);
  665. return d;
  666. }
  667. runlock(&devs);
  668. uprint("unit lookup failure: %lux pc %p", unit, getcallerpc(&unit));
  669. error(up->genbuf);
  670. return nil;
  671. }
  672. static int
  673. unitgen(Chan *c, uint32_t type, Dir *dp)
  674. {
  675. int perm, t;
  676. uint32_t vers;
  677. int64_t size;
  678. char *p;
  679. Aoedev *d;
  680. Qid q;
  681. d = unit2dev(UNIT(c->qid));
  682. perm = 0644;
  683. size = 0;
  684. vers = d->vers;
  685. t = QTFILE;
  686. switch(type){
  687. default:
  688. return -1;
  689. case Qctl:
  690. p = "ctl";
  691. break;
  692. case Qdata:
  693. p = "data";
  694. perm = 0640;
  695. if(UP(d))
  696. size = d->bsize;
  697. break;
  698. case Qconfig:
  699. p = "config";
  700. if(UP(d))
  701. size = d->nconfig;
  702. break;
  703. case Qident:
  704. p = "ident";
  705. if(UP(d))
  706. size = sizeof d->ident;
  707. break;
  708. case Qdevlinkdir:
  709. p = "devlink";
  710. t = QTDIR;
  711. perm = 0555;
  712. break;
  713. }
  714. mkqid(&q, QID(UNIT(c->qid), type), vers, t);
  715. devdir(c, q, p, size, eve, perm, dp);
  716. return 1;
  717. }
  718. static int
  719. topgen(Chan *c, uint32_t type, Dir *d)
  720. {
  721. int perm;
  722. int64_t size;
  723. char *p;
  724. Qid q;
  725. perm = 0444;
  726. size = 0;
  727. switch(type){
  728. default:
  729. return -1;
  730. case Qtopctl:
  731. p = "ctl";
  732. perm = 0644;
  733. break;
  734. case Qtoplog:
  735. p = "log";
  736. size = eventcount();
  737. break;
  738. }
  739. mkqid(&q, type, 0, QTFILE);
  740. devdir(c, q, p, size, eve, perm, d);
  741. return 1;
  742. }
  743. static int
  744. aoegen(Chan *c, char *e, Dirtab *dir, int j, int s, Dir *dp)
  745. {
  746. Proc *up = externup();
  747. int i;
  748. Aoedev *d;
  749. Qid q;
  750. if(c->qid.path == 0){
  751. switch(s){
  752. case DEVDOTDOT:
  753. q.path = 0;
  754. q.type = QTDIR;
  755. devdir(c, q, "#æ", 0, eve, 0555, dp);
  756. break;
  757. case 0:
  758. q.path = Qtopdir;
  759. q.type = QTDIR;
  760. devdir(c, q, "aoe", 0, eve, 0555, dp);
  761. break;
  762. default:
  763. return -1;
  764. }
  765. return 1;
  766. }
  767. switch(TYPE(c->qid)){
  768. default:
  769. return -1;
  770. case Qtopdir:
  771. if(s == DEVDOTDOT){
  772. mkqid(&q, Qzero, 0, QTDIR);
  773. devdir(c, q, "aoe", 0, eve, 0555, dp);
  774. return 1;
  775. }
  776. if(s < Qtopfiles)
  777. return topgen(c, Qtopbase + s, dp);
  778. s -= Qtopfiles;
  779. if(s >= units.ref)
  780. return -1;
  781. mkqid(&q, QID(s, Qunitdir), 0, QTDIR);
  782. d = unit2dev(s);
  783. devdir(c, q, unitname(d), 0, eve, 0555, dp);
  784. return 1;
  785. case Qtopctl:
  786. case Qtoplog:
  787. return topgen(c, TYPE(c->qid), dp);
  788. case Qunitdir:
  789. if(s == DEVDOTDOT){
  790. mkqid(&q, QID(0, Qtopdir), 0, QTDIR);
  791. uprint("%uld", UNIT(c->qid));
  792. devdir(c, q, up->genbuf, 0, eve, 0555, dp);
  793. return 1;
  794. }
  795. return unitgen(c, Qunitbase+s, dp);
  796. case Qctl:
  797. case Qdata:
  798. case Qconfig:
  799. case Qident:
  800. return unitgen(c, TYPE(c->qid), dp);
  801. case Qdevlinkdir:
  802. i = UNIT(c->qid);
  803. if(s == DEVDOTDOT){
  804. mkqid(&q, QID(i, Qunitdir), 0, QTDIR);
  805. devdir(c, q, "devlink", 0, eve, 0555, dp);
  806. return 1;
  807. }
  808. if(i >= units.ref)
  809. return -1;
  810. d = unit2dev(i);
  811. if(s >= d->ndl)
  812. return -1;
  813. uprint("%d", s);
  814. mkqid(&q, Q3(s, i, Qdevlink), 0, QTFILE);
  815. devdir(c, q, up->genbuf, 0, eve, 0755, dp);
  816. return 1;
  817. case Qdevlink:
  818. uprint("%d", s);
  819. mkqid(&q, Q3(s, UNIT(c->qid), Qdevlink), 0, QTFILE);
  820. devdir(c, q, up->genbuf, 0, eve, 0755, dp);
  821. return 1;
  822. }
  823. }
  824. static Walkqid*
  825. aoewalk(Chan *c, Chan *nc, char **name, int nname)
  826. {
  827. return devwalk(c, nc, name, nname, nil, 0, aoegen);
  828. }
  829. static int32_t
  830. aoestat(Chan *c, uint8_t *db, int32_t n)
  831. {
  832. return devstat(c, db, n, nil, 0, aoegen);
  833. }
  834. static Chan*
  835. aoeopen(Chan *c, int omode)
  836. {
  837. Proc *up = externup();
  838. Aoedev *d;
  839. if(TYPE(c->qid) != Qdata)
  840. return devopen(c, omode, 0, 0, aoegen);
  841. d = unit2dev(UNIT(c->qid));
  842. qlock(d);
  843. if(waserror()){
  844. qunlock(d);
  845. nexterror();
  846. }
  847. if(!UP(d))
  848. error(Enotup);
  849. c = devopen(c, omode, 0, 0, aoegen);
  850. d->nopen++;
  851. poperror();
  852. qunlock(d);
  853. return c;
  854. }
  855. static void
  856. aoeclose(Chan *c)
  857. {
  858. Proc *up = externup();
  859. Aoedev *d;
  860. if(TYPE(c->qid) != Qdata || (c->flag&COPEN) == 0)
  861. return;
  862. d = unit2dev(UNIT(c->qid));
  863. qlock(d);
  864. if(--d->nopen == 0 && !waserror()){
  865. discover(d->major, d->minor);
  866. poperror();
  867. }
  868. qunlock(d);
  869. }
  870. static void
  871. atarw(Aoedev *d, Frame *f)
  872. {
  873. Proc *up = externup();
  874. uint32_t bcnt;
  875. char extbit, writebit;
  876. Aoeata *ah;
  877. Srb *srb;
  878. extbit = 0x4;
  879. writebit = 0x10;
  880. srb = d->inprocess;
  881. bcnt = d->maxbcnt;
  882. if(bcnt > srb->len)
  883. bcnt = srb->len;
  884. f->nhdr = AOEATASZ;
  885. memset(f->hdr, 0, f->nhdr);
  886. ah = (Aoeata*)f->hdr;
  887. if(hset(d, f, ah, ACata) == -1)
  888. return;
  889. f->dp = srb->dp;
  890. f->bcnt = bcnt;
  891. f->lba = srb->sector;
  892. f->srb = srb;
  893. ah->scnt = bcnt / Aoesectsz;
  894. putlba(ah, f->lba);
  895. if(d->flag & Dllba)
  896. ah->aflag |= AAFext;
  897. else {
  898. extbit = 0;
  899. ah->lba[3] &= 0x0f;
  900. ah->lba[3] |= 0xe0; /* LBA bit+obsolete 0xa0 */
  901. }
  902. if(srb->write){
  903. ah->aflag |= AAFwrite;
  904. f->dlen = bcnt;
  905. }else{
  906. writebit = 0;
  907. f->dlen = 0;
  908. }
  909. ah->cmdstat = 0x20 | writebit | extbit;
  910. /* mark tracking fields and load out */
  911. srb->nout++;
  912. srb->dp = (uint8_t*)srb->dp + bcnt;
  913. srb->len -= bcnt;
  914. srb->sector += bcnt / Aoesectsz;
  915. if(srb->len == 0)
  916. d->inprocess = nil;
  917. d->nout++;
  918. f->dl->npkt++;
  919. if(waserror()){
  920. f->tag = Tfree;
  921. d->inprocess = nil;
  922. nexterror();
  923. }
  924. f->nl->dc->dev->bwrite(f->nl->dc, allocfb(f), 0);
  925. poperror();
  926. }
  927. static char*
  928. aoeerror(Aoehdr *h)
  929. {
  930. int n;
  931. static char *errs[] = {
  932. "aoe protocol error: unknown",
  933. "aoe protocol error: bad command code",
  934. "aoe protocol error: bad argument param",
  935. "aoe protocol error: device unavailable",
  936. "aoe protocol error: config string present",
  937. "aoe protocol error: unsupported version",
  938. };
  939. if((h->verflag & AFerr) == 0)
  940. return 0;
  941. n = h->error;
  942. if(n > nelem(errs))
  943. n = 0;
  944. return errs[n];
  945. }
  946. static void
  947. rtupdate(Devlink *l, int rtt)
  948. {
  949. int n;
  950. n = rtt;
  951. if(rtt < 0){
  952. n = -rtt;
  953. if(n < Rtmin)
  954. n = Rtmin;
  955. else if(n > Rtmax)
  956. n = Rtmax;
  957. l->mintimer += (n - l->mintimer) >> 1;
  958. } else if(n < l->mintimer)
  959. n = l->mintimer;
  960. else if(n > Rtmax)
  961. n = Rtmax;
  962. /* g == .25; cf. Congestion Avoidance and Control, Jacobson&Karels; 1988 */
  963. n -= l->rttavg;
  964. l->rttavg += n >> 2;
  965. }
  966. static int
  967. srbready(void *v)
  968. {
  969. Srb *s;
  970. s = v;
  971. return s->error || (!s->nout && !s->len);
  972. }
  973. static Frame*
  974. getframe(Aoedev *d, int tag)
  975. {
  976. Frame *f, *e;
  977. f = d->frames;
  978. e = f + d->nframes;
  979. for(; f < e; f++)
  980. if(f->tag == tag)
  981. return f;
  982. return nil;
  983. }
  984. static Frame*
  985. freeframe(Aoedev *d)
  986. {
  987. if(d->nout < d->maxout)
  988. return getframe(d, Tfree);
  989. return nil;
  990. }
  991. static void
  992. work(Aoedev *d)
  993. {
  994. Frame *f;
  995. while ((f = freeframe(d)) != nil) {
  996. if(d->inprocess == nil){
  997. if(d->head == nil)
  998. return;
  999. d->inprocess = d->_head;
  1000. d->_head = d->_head->next;
  1001. if(d->head == nil)
  1002. d->tail = nil;
  1003. }
  1004. atarw(d, f);
  1005. }
  1006. }
  1007. static void
  1008. strategy(Aoedev *d, Srb *srb)
  1009. {
  1010. Proc *up = externup();
  1011. qlock(d);
  1012. if(waserror()){
  1013. qunlock(d);
  1014. nexterror();
  1015. }
  1016. srb->next = nil;
  1017. if(d->tail)
  1018. d->_tail->next = srb;
  1019. d->_tail = srb;
  1020. if(d->_head == nil)
  1021. d->_head = srb;
  1022. work(d);
  1023. poperror();
  1024. qunlock(d);
  1025. while(waserror())
  1026. ;
  1027. sleep(srb, srbready, srb);
  1028. poperror();
  1029. }
  1030. #define iskaddr(a) ((uintptr)(a) > KZERO)
  1031. static int32_t
  1032. rw(Aoedev *d, int write, uint8_t *db, int32_t len, uint64_t off)
  1033. {
  1034. Proc *up = externup();
  1035. int32_t n, nlen, copy;
  1036. enum { Srbsz = 1<<18, };
  1037. Srb *srb;
  1038. if((off|len) & (Aoesectsz-1))
  1039. error("offset and length must be sector multiple.\n");
  1040. if(off > d->bsize || len == 0)
  1041. return 0;
  1042. if(off + len > d->bsize)
  1043. len = d->bsize - off;
  1044. copy = 0;
  1045. if(iskaddr(db)){
  1046. srb = srbkalloc(db, len);
  1047. copy = 1;
  1048. }else
  1049. srb = srballoc(Srbsz <= len? Srbsz: len);
  1050. if(waserror()){
  1051. srbfree(srb);
  1052. nexterror();
  1053. }
  1054. nlen = len;
  1055. srb->write = write;
  1056. do {
  1057. if(!UP(d))
  1058. error(Eio);
  1059. srb->sector = off / Aoesectsz;
  1060. srb->dp = srb->data;
  1061. n = nlen;
  1062. if(n > Srbsz)
  1063. n = Srbsz;
  1064. srb->len = n;
  1065. if(write && !copy)
  1066. memmove(srb->data, db, n);
  1067. strategy(d, srb);
  1068. if(srb->error)
  1069. error(srb->error);
  1070. if(!write && !copy)
  1071. memmove(db, srb->data, n);
  1072. nlen -= n;
  1073. db += n;
  1074. off += n;
  1075. } while (nlen > 0);
  1076. poperror();
  1077. srbfree(srb);
  1078. return len;
  1079. }
  1080. static int32_t
  1081. readmem(uint32_t off, void *dst, int32_t n, void *src, int32_t size)
  1082. {
  1083. if(off >= size)
  1084. return 0;
  1085. if(off + n > size)
  1086. n = size - off;
  1087. memmove(dst, (uint8_t*)src + off, n);
  1088. return n;
  1089. }
  1090. static char *
  1091. pflag(char *s, char *e, uint8_t f)
  1092. {
  1093. uint8_t i, m;
  1094. for(i = 0; i < 8; i++){
  1095. m = 1 << i;
  1096. if(f & m)
  1097. s = seprint(s, e, "%s ", flagname[i]? flagname[i]: "oops");
  1098. }
  1099. return seprint(s, e, "\n");
  1100. }
  1101. static int
  1102. pstat(Aoedev *d, char *db, int len, int off)
  1103. {
  1104. int i;
  1105. char *state, *s, *p, *e;
  1106. s = p = malloc(READSTR);
  1107. e = p + READSTR;
  1108. state = "down";
  1109. if(UP(d))
  1110. state = "up";
  1111. p = seprint(p, e,
  1112. "state: %s\n" "nopen: %d\n" "nout: %d\n"
  1113. "nmaxout: %d\n" "nframes: %d\n" "maxbcnt: %d\n"
  1114. "fw: %.4ux\n"
  1115. "model: %s\n" "serial: %s\n" "firmware: %s\n",
  1116. state, d->nopen, d->nout,
  1117. d->maxout, d->nframes, d->maxbcnt,
  1118. d->fwver,
  1119. d->model, d->serial, d->firmware);
  1120. p = seprint(p, e, "flag: ");
  1121. p = pflag(p, e, d->flag);
  1122. if(p - s < len)
  1123. len = p - s;
  1124. i = readstr(off, db, len, s);
  1125. free(s);
  1126. return i;
  1127. }
  1128. static int32_t
  1129. unitread(Chan *c, void *db, int32_t len, int64_t off)
  1130. {
  1131. Aoedev *d;
  1132. d = unit2dev(UNIT(c->qid));
  1133. if(d->vers != c->qid.vers)
  1134. error(Echange);
  1135. switch(TYPE(c->qid)){
  1136. default:
  1137. error(Ebadarg);
  1138. case Qctl:
  1139. return pstat(d, db, len, off);
  1140. case Qdata:
  1141. return rw(d, Read, db, len, off);
  1142. case Qconfig:
  1143. if (!UP(d))
  1144. error(Enotup);
  1145. return readmem(off, db, len, d->config, d->nconfig);
  1146. case Qident:
  1147. if (!UP(d))
  1148. error(Enotup);
  1149. return readmem(off, db, len, d->ident, sizeof d->ident);
  1150. }
  1151. }
  1152. static int
  1153. devlinkread(Chan *c, void *db, int len, int off)
  1154. {
  1155. int i;
  1156. char *s, *p, *e;
  1157. Aoedev *d;
  1158. Devlink *l;
  1159. d = unit2dev(UNIT(c->qid));
  1160. i = L(c->qid);
  1161. if(i >= d->ndl)
  1162. return 0;
  1163. l = d->dl + i;
  1164. s = p = malloc(READSTR);
  1165. e = s + READSTR;
  1166. p = seprint(p, e, "addr: ");
  1167. for(i = 0; i < l->nea; i++)
  1168. p = seprint(p, e, "%E ", l->eatab[i]);
  1169. p = seprint(p, e, "\n");
  1170. p = seprint(p, e, "npkt: %uld\n", l->npkt);
  1171. p = seprint(p, e, "resent: %uld\n", l->resent);
  1172. p = seprint(p, e, "flag: "); p = pflag(p, e, l->flag);
  1173. p = seprint(p, e, "rttavg: %uld\n", Tk2ms(l->rttavg));
  1174. p = seprint(p, e, "mintimer: %uld\n", Tk2ms(l->mintimer));
  1175. p = seprint(p, e, "nl path: %s\n", l->nl->path);
  1176. p = seprint(p, e, "nl ea: %E\n", l->nl->ea);
  1177. p = seprint(p, e, "nl flag: "); p = pflag(p, e, l->flag);
  1178. p = seprint(p, e, "nl lostjumbo: %d\n", l->nl->lostjumbo);
  1179. p = seprint(p, e, "nl datamtu: %d\n", l->nl->datamtu);
  1180. if(p - s < len)
  1181. len = p - s;
  1182. i = readstr(off, db, len, s);
  1183. free(s);
  1184. return i;
  1185. }
  1186. static int32_t
  1187. topctlread(Chan *c, void *db, int len, int off)
  1188. {
  1189. int i;
  1190. char *s, *p, *e;
  1191. Netlink *n;
  1192. s = p = malloc(READSTR);
  1193. e = s + READSTR;
  1194. p = seprint(p, e, "debug: %d\n", debug);
  1195. p = seprint(p, e, "autodiscover: %d\n", autodiscover);
  1196. p = seprint(p, e, "rediscover: %d\n", rediscover);
  1197. for(i = 0; i < Nnetlink; i++){
  1198. n = netlinks.nl+i;
  1199. if(n->cc == 0)
  1200. continue;
  1201. p = seprint(p, e, "if%d path: %s\n", i, n->path);
  1202. p = seprint(p, e, "if%d ea: %E\n", i, n->ea);
  1203. p = seprint(p, e, "if%d flag: ", i); p = pflag(p, e, n->flag);
  1204. p = seprint(p, e, "if%d lostjumbo: %d\n", i, n->lostjumbo);
  1205. p = seprint(p, e, "if%d datamtu: %d\n", i, n->datamtu);
  1206. }
  1207. if(p - s < len)
  1208. len = p - s;
  1209. i = readstr(off, db, len, s);
  1210. free(s);
  1211. return i;
  1212. }
  1213. static int32_t
  1214. aoeread(Chan *c, void *db, int32_t n, int64_t off)
  1215. {
  1216. switch(TYPE(c->qid)){
  1217. default:
  1218. error(Eperm);
  1219. case Qzero:
  1220. case Qtopdir:
  1221. case Qunitdir:
  1222. case Qdevlinkdir:
  1223. return devdirread(c, db, n, 0, 0, aoegen);
  1224. case Qtopctl:
  1225. return topctlread(c, db, n, off);
  1226. case Qtoplog:
  1227. return eventlogread(db, n);
  1228. case Qctl:
  1229. case Qdata:
  1230. case Qconfig:
  1231. case Qident:
  1232. return unitread(c, db, n, off);
  1233. case Qdevlink:
  1234. return devlinkread(c, db, n, off);
  1235. }
  1236. }
  1237. static int32_t
  1238. configwrite(Aoedev *d, void *db, int32_t len)
  1239. {
  1240. Proc *up = externup();
  1241. char *s;
  1242. Aoeqc *ch;
  1243. Frame *f;
  1244. Srb *srb;
  1245. if(!UP(d))
  1246. error(Enotup);
  1247. if(len > ETHERMAXTU - AOEQCSZ)
  1248. error(Etoobig);
  1249. srb = srballoc(len);
  1250. s = malloc(len);
  1251. memmove(s, db, len);
  1252. if(waserror()){
  1253. srbfree(srb);
  1254. free(s);
  1255. nexterror();
  1256. }
  1257. for (;;) {
  1258. qlock(d);
  1259. if(waserror()){
  1260. qunlock(d);
  1261. nexterror();
  1262. }
  1263. f = freeframe(d);
  1264. if(f != nil)
  1265. break;
  1266. poperror();
  1267. qunlock(d);
  1268. if(waserror())
  1269. nexterror();
  1270. tsleep(&up->sleep, return0, 0, 100);
  1271. poperror();
  1272. }
  1273. f->nhdr = AOEQCSZ;
  1274. memset(f->hdr, 0, f->nhdr);
  1275. ch = (Aoeqc*)f->hdr;
  1276. if(hset(d, f, ch, ACconfig) == -1)
  1277. return 0;
  1278. f->srb = srb;
  1279. f->dp = s;
  1280. ch->verccmd = AQCfset;
  1281. hnputs(ch->cslen, len);
  1282. d->nout++;
  1283. srb->nout++;
  1284. f->dl->npkt++;
  1285. f->dlen = len;
  1286. /*
  1287. * these refer to qlock & waserror in the above for loop.
  1288. * there's still the first waserror outstanding.
  1289. */
  1290. poperror();
  1291. qunlock(d);
  1292. f->nl->dc->dev->bwrite(f->nl->dc, allocfb(f), 0);
  1293. sleep(srb, srbready, srb);
  1294. if(srb->error)
  1295. error(srb->error);
  1296. qlock(d);
  1297. if(waserror()){
  1298. qunlock(d);
  1299. nexterror();
  1300. }
  1301. memmove(d->config, s, len);
  1302. d->nconfig = len;
  1303. poperror();
  1304. qunlock(d);
  1305. poperror(); /* pop first waserror */
  1306. srbfree(srb);
  1307. memmove(db, s, len);
  1308. free(s);
  1309. return len;
  1310. }
  1311. static int getmtu(Chan*);
  1312. static int
  1313. devmaxdata(Aoedev *d)
  1314. {
  1315. int i, mm, mtu;
  1316. Devlink *l;
  1317. Netlink *n;
  1318. mtu = 100000;
  1319. for(i = 0; i < d->ndl; i++){
  1320. l = d->dl + i;
  1321. n = l->nl;
  1322. if((l->flag & Dup) == 0 || (n->flag & Dup) == 0)
  1323. continue;
  1324. mm = getmtu(n->mtu);
  1325. if(mm < mtu)
  1326. mtu = mm;
  1327. }
  1328. if(mtu == 100000)
  1329. mtu = 0;
  1330. mtu -= AOEATASZ;
  1331. return mtu;
  1332. }
  1333. static int
  1334. toggle(char *s, int init)
  1335. {
  1336. if(s == nil)
  1337. return init ^ 1;
  1338. return strcmp(s, "on") == 0;
  1339. }
  1340. static void ataident(Aoedev*);
  1341. static int32_t
  1342. unitctlwrite(Aoedev *d, void *db, int32_t n)
  1343. {
  1344. Proc *up = externup();
  1345. uint maxbcnt, mm;
  1346. uint64_t bsize;
  1347. enum {
  1348. Failio,
  1349. Ident,
  1350. Jumbo,
  1351. Maxbno,
  1352. Mtu,
  1353. Setsize,
  1354. };
  1355. Cmdbuf *cb;
  1356. Cmdtab *ct;
  1357. static Cmdtab cmds[] = {
  1358. {Failio, "failio", 1 },
  1359. {Ident, "identify", 1 },
  1360. {Jumbo, "jumbo", 0 },
  1361. {Maxbno, "maxbno", 0 },
  1362. {Mtu, "mtu", 0 },
  1363. {Setsize, "setsize", 0 },
  1364. };
  1365. cb = parsecmd(db, n);
  1366. qlock(d);
  1367. if(waserror()){
  1368. qunlock(d);
  1369. free(cb);
  1370. nexterror();
  1371. }
  1372. ct = lookupcmd(cb, cmds, nelem(cmds));
  1373. switch(ct->index){
  1374. case Failio:
  1375. downdev(d, "i/o failure");
  1376. break;
  1377. case Ident:
  1378. ataident(d);
  1379. break;
  1380. case Jumbo:
  1381. mm = 0;
  1382. if(d->flag & Djumbo)
  1383. mm = 1;
  1384. toggle(cb->f[1], mm);
  1385. if(mm)
  1386. d->flag |= Djumbo;
  1387. else
  1388. d->flag &= ~Djumbo;
  1389. break;
  1390. case Maxbno:
  1391. case Mtu:
  1392. maxbcnt = devmaxdata(d);
  1393. if(cb->nf > 2)
  1394. error(Ecmdargs);
  1395. if(cb->nf == 2){
  1396. mm = strtoul(cb->f[1], 0, 0);
  1397. if(ct->index == Maxbno)
  1398. mm *= Aoesectsz;
  1399. else{
  1400. mm -= AOEATASZ;
  1401. mm &= ~(Aoesectsz-1);
  1402. }
  1403. if(mm > maxbcnt)
  1404. cmderror(cb, "maxb greater than media mtu");
  1405. maxbcnt = mm;
  1406. }
  1407. d->maxbcnt = maxbcnt;
  1408. break;
  1409. case Setsize:
  1410. bsize = d->realbsize;
  1411. if(cb->nf > 2)
  1412. error(Ecmdargs);
  1413. if(cb->nf == 2){
  1414. bsize = strtoull(cb->f[1], 0, 0);
  1415. if(bsize % Aoesectsz)
  1416. cmderror(cb, "disk size must be sector aligned");
  1417. }
  1418. d->bsize = bsize;
  1419. break;
  1420. default:
  1421. cmderror(cb, "unknown aoe control message");
  1422. }
  1423. poperror();
  1424. qunlock(d);
  1425. free(cb);
  1426. return n;
  1427. }
  1428. static int32_t
  1429. unitwrite(Chan *c, void *db, int32_t n, int64_t off)
  1430. {
  1431. int32_t rv;
  1432. char *buf;
  1433. Aoedev *d;
  1434. d = unit2dev(UNIT(c->qid));
  1435. switch(TYPE(c->qid)){
  1436. default:
  1437. error(Ebadarg);
  1438. case Qctl:
  1439. return unitctlwrite(d, db, n);
  1440. case Qident:
  1441. error(Eperm);
  1442. case Qdata:
  1443. return rw(d, Write, db, n, off);
  1444. case Qconfig:
  1445. if(off + n > sizeof d->config)
  1446. error(Etoobig);
  1447. buf = malloc(sizeof d->config);
  1448. memmove(buf, d->config, d->nconfig);
  1449. memmove(buf + off, db, n);
  1450. rv = configwrite(d, buf, n + off);
  1451. free(buf);
  1452. return rv;
  1453. }
  1454. }
  1455. static Netlink*
  1456. addnet(char *path, Chan *cc, Chan *dc, Chan *mtu, uint8_t *ea)
  1457. {
  1458. Proc *up = externup();
  1459. Netlink *nl, *e;
  1460. lock(&netlinks);
  1461. if(waserror()){
  1462. unlock(&netlinks);
  1463. nexterror();
  1464. }
  1465. nl = netlinks.nl;
  1466. e = nl + nelem(netlinks.nl);
  1467. for(; nl < e && nl->cc; nl++)
  1468. continue;
  1469. if (nl >= e)
  1470. error("out of netlink structures");
  1471. nl->cc = cc;
  1472. nl->dc = dc;
  1473. nl->mtu = mtu;
  1474. strncpy(nl->path, path, sizeof nl->path);
  1475. memmove(nl->ea, ea, sizeof nl->ea);
  1476. poperror();
  1477. nl->flag |= Dup;
  1478. unlock(&netlinks);
  1479. return nl;
  1480. }
  1481. static int
  1482. newunit(void)
  1483. {
  1484. int x;
  1485. lock(&units);
  1486. if(units.ref == Maxunits)
  1487. x = -1;
  1488. else
  1489. x = units.ref++;
  1490. unlock(&units);
  1491. return x;
  1492. }
  1493. static int
  1494. dropunit(void)
  1495. {
  1496. int x;
  1497. lock(&units);
  1498. x = --units.ref;
  1499. unlock(&units);
  1500. return x;
  1501. }
  1502. static Aoedev*
  1503. newdev(int32_t major, int32_t minor, int n)
  1504. {
  1505. Aoedev *d;
  1506. Frame *f, *e;
  1507. d = mallocz(sizeof *d, 1);
  1508. f = mallocz(sizeof *f * n, 1);
  1509. if (!d || !f) {
  1510. free(d);
  1511. free(f);
  1512. error("aoe device allocation failure");
  1513. }
  1514. d->nframes = n;
  1515. d->frames = f;
  1516. for (e = f + n; f < e; f++)
  1517. f->tag = Tfree;
  1518. d->maxout = n;
  1519. d->major = major;
  1520. d->minor = minor;
  1521. d->maxbcnt = Dbcnt;
  1522. d->flag = Djumbo;
  1523. d->unit = newunit(); /* bzzt. inaccurate if units removed */
  1524. if(d->unit == -1){
  1525. free(d);
  1526. free(d->frames);
  1527. error("too many units");
  1528. }
  1529. d->dl = d->dltab;
  1530. return d;
  1531. }
  1532. static Aoedev*
  1533. mm2dev(int major, int minor)
  1534. {
  1535. Aoedev *d;
  1536. rlock(&devs);
  1537. for(d = devs.d; d; d = d->next)
  1538. if(d->major == major && d->minor == minor){
  1539. runlock(&devs);
  1540. return d;
  1541. }
  1542. runlock(&devs);
  1543. eventlog("mm2dev: %d.%d not found\n", major, minor);
  1544. return nil;
  1545. }
  1546. /* Find the device in our list. If not known, add it */
  1547. static Aoedev*
  1548. getdev(int32_t major, int32_t minor, int n)
  1549. {
  1550. Proc *up = externup();
  1551. Aoedev *d;
  1552. wlock(&devs);
  1553. if(waserror()){
  1554. wunlock(&devs);
  1555. nexterror();
  1556. }
  1557. for(d = devs.d; d; d = d->next)
  1558. if(d->major == major && d->minor == minor)
  1559. break;
  1560. if (d == nil) {
  1561. d = newdev(major, minor, n);
  1562. d->next = devs.d;
  1563. devs.d = d;
  1564. }
  1565. poperror();
  1566. wunlock(&devs);
  1567. return d;
  1568. }
  1569. static uint16_t
  1570. gbit16(void *a)
  1571. {
  1572. uint8_t *i;
  1573. i = a;
  1574. return i[1] << 8 | i[0];
  1575. }
  1576. static uint32_t
  1577. gbit32(void *a)
  1578. {
  1579. uint32_t j;
  1580. uint8_t *i;
  1581. i = a;
  1582. j = i[3] << 24;
  1583. j |= i[2] << 16;
  1584. j |= i[1] << 8;
  1585. j |= i[0];
  1586. return j;
  1587. }
  1588. static uint64_t
  1589. gbit64(void *a)
  1590. {
  1591. uint8_t *i;
  1592. i = a;
  1593. return (uint64_t)gbit32(i+4) << 32 | gbit32(a);
  1594. }
  1595. static void
  1596. ataident(Aoedev *d)
  1597. {
  1598. Aoeata *a;
  1599. Block *b;
  1600. Frame *f;
  1601. f = freeframe(d);
  1602. if(f == nil)
  1603. return;
  1604. f->nhdr = AOEATASZ;
  1605. memset(f->hdr, 0, f->nhdr);
  1606. a = (Aoeata*)f->hdr;
  1607. if(hset(d, f, a, ACata) == -1)
  1608. return;
  1609. a->cmdstat = Cid; /* ata 6, page 110 */
  1610. a->scnt = 1;
  1611. a->lba[3] = 0xa0;
  1612. d->nout++;
  1613. f->dl->npkt++;
  1614. f->bcnt = 512;
  1615. f->dlen = 0;
  1616. b = allocfb(f);
  1617. f->nl->dc->dev->bwrite(f->nl->dc, b, 0);
  1618. }
  1619. static int
  1620. getmtu(Chan *mm)
  1621. {
  1622. Proc *up = externup();
  1623. int n, mtu;
  1624. char buf[36];
  1625. mtu = 1514;
  1626. if(mm == nil || waserror())
  1627. return mtu;
  1628. n = mm->dev->read(mm, buf, sizeof buf - 1, 0);
  1629. if(n > 12){
  1630. buf[n] = 0;
  1631. mtu = strtoul(buf + 12, 0, 0);
  1632. }
  1633. poperror();
  1634. return mtu;
  1635. }
  1636. static int
  1637. newdlea(Devlink *l, uint8_t *ea)
  1638. {
  1639. int i;
  1640. uint8_t *t;
  1641. for(i = 0; i < Nea; i++){
  1642. t = l->eatab[i];
  1643. if(i == l->nea){
  1644. memmove(t, ea, Eaddrlen);
  1645. return l->nea++;
  1646. }
  1647. if(memcmp(t, ea, Eaddrlen) == 0)
  1648. return i;
  1649. }
  1650. return -1;
  1651. }
  1652. static Devlink*
  1653. newdevlink(Aoedev *d, Netlink *n, Aoeqc *c)
  1654. {
  1655. int i;
  1656. Devlink *l;
  1657. for(i = 0; i < Ndevlink; i++){
  1658. l = d->dl + i;
  1659. if(i == d->ndl){
  1660. d->ndl++;
  1661. newdlea(l, c->src);
  1662. l->nl = n;
  1663. l->flag |= Dup;
  1664. l->mintimer = Rtmin;
  1665. l->rttavg = Rtmax;
  1666. return l;
  1667. }
  1668. if(l->nl == n)
  1669. return l;
  1670. }
  1671. eventlog("%æ: out of links: %s:%E to %E\n", d, n->path, n->ea, c->src);
  1672. return 0;
  1673. }
  1674. static void
  1675. errrsp(Block *b, char *s)
  1676. {
  1677. int n;
  1678. Aoedev *d;
  1679. Aoehdr *h;
  1680. Frame *f;
  1681. h = (Aoehdr*)b->rp;
  1682. n = nhgetl(h->tag);
  1683. if(n == Tmgmt || n == Tfree)
  1684. return;
  1685. d = mm2dev(nhgets(h->major), h->minor);
  1686. if(d == 0)
  1687. return;
  1688. if(f = getframe(d, n))
  1689. frameerror(d, f, s);
  1690. }
  1691. static void
  1692. qcfgrsp(Block *b, Netlink *nl)
  1693. {
  1694. Proc *up = externup();
  1695. int major, cmd, cslen, blen;
  1696. unsigned n;
  1697. Aoedev *d;
  1698. Aoeqc *ch;
  1699. Devlink *l;
  1700. Frame *f;
  1701. ch = (Aoeqc*)b->rp;
  1702. major = nhgets(ch->major);
  1703. n = nhgetl(ch->tag);
  1704. if(n != Tmgmt){
  1705. d = mm2dev(major, ch->minor);
  1706. if(d == nil)
  1707. return;
  1708. qlock(d);
  1709. f = getframe(d, n);
  1710. if(f == nil){
  1711. qunlock(d);
  1712. eventlog("%æ: unknown response tag %ux\n", d, n);
  1713. return;
  1714. }
  1715. cslen = nhgets(ch->cslen);
  1716. blen = BLEN(b) - AOEQCSZ;
  1717. if(cslen < blen)
  1718. eventlog("%æ: cfgrsp: tag %.8ux oversized %d %d\n",
  1719. d, n, cslen, blen);
  1720. if(cslen > blen){
  1721. eventlog("%æ: cfgrsp: tag %.8ux runt %d %d\n",
  1722. d, n, cslen, blen);
  1723. cslen = blen;
  1724. }
  1725. memmove(f->dp, ch + 1, cslen);
  1726. f->srb->nout--;
  1727. wakeup(f->srb);
  1728. d->nout--;
  1729. f->srb = nil;
  1730. f->tag = Tfree;
  1731. qunlock(d);
  1732. return;
  1733. }
  1734. cmd = ch->verccmd & 0xf;
  1735. if(cmd != 0){
  1736. eventlog("aoe%d.%d: cfgrsp: bad command %d\n", major, ch->minor, cmd);
  1737. return;
  1738. }
  1739. n = nhgets(ch->bufcnt);
  1740. if(n > Maxframes)
  1741. n = Maxframes;
  1742. if(waserror()){
  1743. eventlog("getdev: %d.%d ignored: %s\n", major, ch->minor, up->errstr);
  1744. return;
  1745. }
  1746. d = getdev(major, ch->minor, n);
  1747. poperror();
  1748. qlock(d);
  1749. if(waserror()){
  1750. qunlock(d);
  1751. eventlog("%æ: %s\n", d, up->errstr);
  1752. nexterror();
  1753. }
  1754. l = newdevlink(d, nl, ch); /* add this interface. */
  1755. d->fwver = nhgets(ch->fwver);
  1756. n = nhgets(ch->cslen);
  1757. if(n > sizeof d->config)
  1758. n = sizeof d->config;
  1759. d->nconfig = n;
  1760. memmove(d->config, ch + 1, n);
  1761. if(l != 0 && d->flag & Djumbo){
  1762. n = getmtu(nl->mtu) - AOEATASZ;
  1763. n /= Aoesectsz;
  1764. if(n > ch->scnt)
  1765. n = ch->scnt;
  1766. n = n? n * Aoesectsz: Dbcnt;
  1767. if(n != d->maxbcnt){
  1768. eventlog("%æ: setting %d byte data frames on %s:%E\n",
  1769. d, n, nl->path, nl->ea);
  1770. d->maxbcnt = n;
  1771. }
  1772. }
  1773. if(d->nopen == 0)
  1774. ataident(d);
  1775. poperror();
  1776. qunlock(d);
  1777. }
  1778. void
  1779. aoeidmove(char *p, uint16_t *u, unsigned n)
  1780. {
  1781. int i;
  1782. char *op, *e, *s;
  1783. op = p;
  1784. /*
  1785. * the ushort `a' is sometimes not aligned on a short boundary,
  1786. * so dereferencing a[i] would cause an alignment exception on
  1787. * some machines.
  1788. */
  1789. s = (char *)u;
  1790. for(i = 0; i < n; i += 2){
  1791. *p++ = s[i + 1];
  1792. *p++ = s[i];
  1793. }
  1794. *p = 0;
  1795. while(p > op && *--p == ' ')
  1796. *p = 0;
  1797. e = p;
  1798. p = op;
  1799. while(*p == ' ')
  1800. p++;
  1801. memmove(op, p, n - (e - p));
  1802. }
  1803. static int64_t
  1804. aoeidentify(Aoedev *d, uint16_t *id)
  1805. {
  1806. int i;
  1807. int64_t s;
  1808. d->flag &= ~(Dllba|Dpower|Dsmart|Dnop|Dup);
  1809. i = gbit16(id+83) | gbit16(id+86);
  1810. if(i & (1<<10)){
  1811. d->flag |= Dllba;
  1812. s = gbit64(id+100);
  1813. }else
  1814. s = gbit32(id+60);
  1815. i = gbit16(id+83);
  1816. if((i>>14) == 1) {
  1817. if(i & (1<<3))
  1818. d->flag |= Dpower;
  1819. i = gbit16(id+82);
  1820. if(i & 1)
  1821. d->flag |= Dsmart;
  1822. if(i & (1<<14))
  1823. d->flag |= Dnop;
  1824. }
  1825. // eventlog("%æ up\n", d);
  1826. d->flag |= Dup;
  1827. memmove(d->ident, id, sizeof d->ident);
  1828. return s;
  1829. }
  1830. static void
  1831. newvers(Aoedev *d)
  1832. {
  1833. lock(&drivevers);
  1834. d->vers = drivevers.ref++;
  1835. unlock(&drivevers);
  1836. }
  1837. static int
  1838. identify(Aoedev *d, uint16_t *id)
  1839. {
  1840. int64_t osectors, s;
  1841. uint8_t oserial[21];
  1842. s = aoeidentify(d, id);
  1843. if(s == -1)
  1844. return -1;
  1845. osectors = d->realbsize;
  1846. memmove(oserial, d->serial, sizeof d->serial);
  1847. aoeidmove(d->serial, id+10, 20);
  1848. aoeidmove(d->firmware, id+23, 8);
  1849. aoeidmove(d->model, id+27, 40);
  1850. s *= Aoesectsz;
  1851. if((osectors == 0 || osectors != s) &&
  1852. memcmp(oserial, d->serial, sizeof oserial) != 0){
  1853. d->bsize = s;
  1854. d->realbsize = s;
  1855. // d->mediachange = 1;
  1856. newvers(d);
  1857. }
  1858. return 0;
  1859. }
  1860. static void
  1861. atarsp(Block *b)
  1862. {
  1863. Proc *up = externup();
  1864. unsigned n;
  1865. int16_t major;
  1866. Aoeata *ahin, *ahout;
  1867. Aoedev *d;
  1868. Frame *f;
  1869. Srb *srb;
  1870. ahin = (Aoeata*)b->rp;
  1871. major = nhgets(ahin->major);
  1872. d = mm2dev(major, ahin->minor);
  1873. if(d == nil)
  1874. return;
  1875. qlock(d);
  1876. if(waserror()){
  1877. qunlock(d);
  1878. nexterror();
  1879. }
  1880. n = nhgetl(ahin->tag);
  1881. f = getframe(d, n);
  1882. if(f == nil){
  1883. dprint("%æ: unexpected response; tag %ux\n", d, n);
  1884. goto bail;
  1885. }
  1886. rtupdate(f->dl, tsince(f->tag));
  1887. ahout = (Aoeata*)f->hdr;
  1888. srb = f->srb;
  1889. if(ahin->cmdstat & 0xa9){
  1890. eventlog("%æ: ata error cmd %.2ux stat %.2ux\n",
  1891. d, ahout->cmdstat, ahin->cmdstat);
  1892. if(srb)
  1893. srb->error = Eio;
  1894. } else {
  1895. n = ahout->scnt * Aoesectsz;
  1896. switch(ahout->cmdstat){
  1897. case Crd:
  1898. case Crdext:
  1899. if(BLEN(b) - AOEATASZ < n){
  1900. eventlog("%æ: runt read blen %ld expect %d\n",
  1901. d, BLEN(b), n);
  1902. goto bail;
  1903. }
  1904. memmove(f->dp, (uint8_t *)ahin + AOEATASZ, n);
  1905. case Cwr:
  1906. case Cwrext:
  1907. if(n > Dbcnt)
  1908. f->nl->lostjumbo = 0;
  1909. if(f->bcnt -= n){
  1910. f->lba += n / Aoesectsz;
  1911. f->dp = (uint8_t*)f->dp + n;
  1912. resend(d, f);
  1913. goto bail;
  1914. }
  1915. break;
  1916. case Cid:
  1917. if(BLEN(b) - AOEATASZ < 512){
  1918. eventlog("%æ: runt identify blen %ld expect %d\n",
  1919. d, BLEN(b), n);
  1920. goto bail;
  1921. }
  1922. identify(d, (uint16_t*)((uint8_t *)ahin + AOEATASZ));
  1923. break;
  1924. default:
  1925. eventlog("%æ: unknown ata command %.2ux \n",
  1926. d, ahout->cmdstat);
  1927. }
  1928. }
  1929. if(srb && --srb->nout == 0 && srb->len == 0)
  1930. wakeup(srb);
  1931. f->srb = nil;
  1932. f->tag = Tfree;
  1933. d->nout--;
  1934. work(d);
  1935. bail:
  1936. poperror();
  1937. qunlock(d);
  1938. }
  1939. static void
  1940. netrdaoeproc(void *v)
  1941. {
  1942. Proc *up = externup();
  1943. int idx;
  1944. char name[Maxpath+1], *s;
  1945. Aoehdr *h;
  1946. Block *b;
  1947. Netlink *nl;
  1948. nl = (Netlink*)v;
  1949. idx = nl - netlinks.nl;
  1950. netlinks.reader[idx] = 1;
  1951. kstrcpy(name, nl->path, Maxpath);
  1952. if(waserror()){
  1953. eventlog("netrdaoe exiting: %s\n", up->errstr);
  1954. netlinks.reader[idx] = 0;
  1955. wakeup(netlinks.rendez + idx);
  1956. pexit(up->errstr, 1);
  1957. }
  1958. if(autodiscover)
  1959. discover(0xffff, 0xff);
  1960. for (;;) {
  1961. if(!(nl->flag & Dup)) {
  1962. uprint("%s: netlink is down", name);
  1963. error(up->genbuf);
  1964. }
  1965. if (nl->dc == nil)
  1966. panic("netrdaoe: nl->dc == nil");
  1967. b = nl->dc->dev->bread(nl->dc, 1<<16, 0);
  1968. if(b == nil) {
  1969. uprint("%s: nil read from network", name);
  1970. error(up->genbuf);
  1971. }
  1972. h = (Aoehdr*)b->rp;
  1973. if(h->verflag & AFrsp)
  1974. if(s = aoeerror(h)){
  1975. eventlog("%s: %s\n", nl->path, up->errstr);
  1976. errrsp(b, s);
  1977. }else
  1978. switch(h->cmd){
  1979. case ACata:
  1980. atarsp(b);
  1981. break;
  1982. case ACconfig:
  1983. qcfgrsp(b, nl);
  1984. break;
  1985. default:
  1986. eventlog("%s: unknown cmd %d\n",
  1987. nl->path, h->cmd);
  1988. errrsp(b, "unknown command");
  1989. }
  1990. freeb(b);
  1991. }
  1992. }
  1993. static void
  1994. getaddr(char *path, uint8_t *ea)
  1995. {
  1996. Proc *up = externup();
  1997. int n;
  1998. char buf[2*Eaddrlen+1];
  1999. Chan *c;
  2000. extern int parseether(uint8_t*, char*);
  2001. uprint("%s/addr", path);
  2002. c = namec(up->genbuf, Aopen, OREAD, 0);
  2003. if(waserror()) {
  2004. cclose(c);
  2005. nexterror();
  2006. }
  2007. if (c == nil)
  2008. panic("æ: getaddr: c == nil");
  2009. n = c->dev->read(c, buf, sizeof buf-1, 0);
  2010. poperror();
  2011. cclose(c);
  2012. buf[n] = 0;
  2013. if(parseether(ea, buf) < 0)
  2014. error("parseether failure");
  2015. }
  2016. static void
  2017. netbind(char *path)
  2018. {
  2019. Proc *up = externup();
  2020. char addr[Maxpath];
  2021. uint8_t ea[2*Eaddrlen+1];
  2022. Chan *dc, *cc, *mtu;
  2023. Netlink *nl;
  2024. snprint(addr, sizeof addr, "%s!0x%x", path, Aoetype);
  2025. dc = chandial(addr, nil, nil, &cc);
  2026. snprint(addr, sizeof addr, "%s/mtu", path);
  2027. if(waserror())
  2028. mtu = nil;
  2029. else {
  2030. mtu = namec(addr, Aopen, OREAD, 0);
  2031. poperror();
  2032. }
  2033. if(waserror()){
  2034. cclose(dc);
  2035. cclose(cc);
  2036. if(mtu)
  2037. cclose(mtu);
  2038. nexterror();
  2039. }
  2040. if(dc == nil || cc == nil)
  2041. error(Enonexist);
  2042. getaddr(path, ea);
  2043. nl = addnet(path, cc, dc, mtu, ea);
  2044. snprint(addr, sizeof addr, "netrdaoe@%s", path);
  2045. kproc(addr, netrdaoeproc, nl);
  2046. poperror();
  2047. }
  2048. static int
  2049. unbound(void *v)
  2050. {
  2051. return *(int*)v != 0;
  2052. }
  2053. static void
  2054. netunbind(char *path)
  2055. {
  2056. Proc *up = externup();
  2057. int i, idx;
  2058. Aoedev *d, *p, *next;
  2059. Chan *dc, *cc;
  2060. Devlink *l;
  2061. Frame *f;
  2062. Netlink *n, *e;
  2063. n = netlinks.nl;
  2064. e = n + nelem(netlinks.nl);
  2065. lock(&netlinks);
  2066. for(; n < e; n++)
  2067. if(n->dc && strcmp(n->path, path) == 0)
  2068. break;
  2069. unlock(&netlinks);
  2070. if (n >= e)
  2071. error("device not bound");
  2072. /*
  2073. * hunt down devices using this interface; disable
  2074. * this also terminates the reader.
  2075. */
  2076. idx = n - netlinks.nl;
  2077. wlock(&devs);
  2078. for(d = devs.d; d; d = d->next){
  2079. qlock(d);
  2080. for(i = 0; i < d->ndl; i++){
  2081. l = d->dl + i;
  2082. if(l->nl == n)
  2083. l->flag &= ~Dup;
  2084. }
  2085. qunlock(d);
  2086. }
  2087. n->flag &= ~Dup;
  2088. wunlock(&devs);
  2089. /* confirm reader is down. */
  2090. while(waserror())
  2091. ;
  2092. sleep(netlinks.rendez + idx, unbound, netlinks.reader + idx);
  2093. poperror();
  2094. /* reschedule packets. */
  2095. wlock(&devs);
  2096. for(d = devs.d; d; d = d->next){
  2097. qlock(d);
  2098. for(i = 0; i < d->nframes; i++){
  2099. f = d->frames + i;
  2100. if(f->tag != Tfree && f->nl == n)
  2101. resend(d, f);
  2102. }
  2103. qunlock(d);
  2104. }
  2105. wunlock(&devs);
  2106. /* squeeze devlink pool. (we assert nobody is using them now) */
  2107. wlock(&devs);
  2108. for(d = devs.d; d; d = d->next){
  2109. qlock(d);
  2110. for(i = 0; i < d->ndl; i++){
  2111. l = d->dl + i;
  2112. if(l->nl == n)
  2113. memmove(l, l + 1, sizeof *l * (--d->ndl - i));
  2114. }
  2115. qunlock(d);
  2116. }
  2117. wunlock(&devs);
  2118. /* close device link. */
  2119. lock(&netlinks);
  2120. dc = n->dc;
  2121. cc = n->cc;
  2122. if(n->mtu)
  2123. cclose(n->mtu);
  2124. memset(n, 0, sizeof *n);
  2125. unlock(&netlinks);
  2126. cclose(dc);
  2127. cclose(cc);
  2128. /* squeeze orphan devices */
  2129. wlock(&devs);
  2130. for(p = d = devs.d; d; p = d, d = next){
  2131. next = d->next;
  2132. if(d->ndl > 0)
  2133. continue;
  2134. if(p != devs.d)
  2135. p->next = next;
  2136. else
  2137. devs.d = next;
  2138. free(d->frames);
  2139. free(d);
  2140. dropunit();
  2141. }
  2142. wunlock(&devs);
  2143. }
  2144. static void
  2145. removedev(char *name)
  2146. {
  2147. int i;
  2148. Aoedev *d, *p;
  2149. wlock(&devs);
  2150. for(p = d = devs.d; d; p = d, d = d->next)
  2151. if(strcmp(name, unitname(d)) == 0)
  2152. goto found;
  2153. wunlock(&devs);
  2154. error("device not bound");
  2155. found:
  2156. d->flag &= ~Dup;
  2157. newvers(d);
  2158. d->ndl = 0;
  2159. for(i = 0; i < d->nframes; i++)
  2160. frameerror(d, d->frames+i, Enotup);
  2161. if(p != devs.d)
  2162. p->next = d->next;
  2163. else
  2164. devs.d = d->next;
  2165. free(d->frames);
  2166. free(d);
  2167. dropunit();
  2168. wunlock(&devs);
  2169. }
  2170. static void
  2171. discoverstr(char *f)
  2172. {
  2173. uint16_t shelf, slot;
  2174. uint32_t sh;
  2175. char *s;
  2176. if(f == 0){
  2177. discover(0xffff, 0xff);
  2178. return;
  2179. }
  2180. shelf = sh = strtol(f, &s, 0);
  2181. if(s == f || sh > 0xffff)
  2182. error("bad shelf");
  2183. f = s;
  2184. if(*f++ == '.'){
  2185. slot = strtol(f, &s, 0);
  2186. if(s == f || slot > 0xff)
  2187. error("bad shelf");
  2188. }else
  2189. slot = 0xff;
  2190. discover(shelf, slot);
  2191. }
  2192. static int32_t
  2193. topctlwrite(void *db, int32_t n)
  2194. {
  2195. enum {
  2196. Autodiscover,
  2197. Bind,
  2198. Debug,
  2199. Discover,
  2200. Closewait,
  2201. Rediscover,
  2202. Remove,
  2203. Unbind,
  2204. };
  2205. Proc *up = externup();
  2206. char *f;
  2207. Cmdbuf *cb;
  2208. Cmdtab *ct;
  2209. static Cmdtab cmds[] = {
  2210. { Autodiscover, "autodiscover", 0 },
  2211. { Bind, "bind", 2 },
  2212. { Debug, "debug", 0 },
  2213. { Discover, "discover", 0 },
  2214. { Rediscover, "rediscover", 0 },
  2215. { Remove, "remove", 2 },
  2216. { Unbind, "unbind", 2 },
  2217. };
  2218. cb = parsecmd(db, n);
  2219. if(waserror()){
  2220. free(cb);
  2221. nexterror();
  2222. }
  2223. ct = lookupcmd(cb, cmds, nelem(cmds));
  2224. f = cb->f[1];
  2225. switch(ct->index){
  2226. case Autodiscover:
  2227. autodiscover = toggle(f, autodiscover);
  2228. break;
  2229. case Bind:
  2230. netbind(f);
  2231. break;
  2232. case Debug:
  2233. debug = toggle(f, debug);
  2234. break;
  2235. case Discover:
  2236. discoverstr(f);
  2237. break;
  2238. case Rediscover:
  2239. rediscover = toggle(f, rediscover);
  2240. break;
  2241. case Remove:
  2242. removedev(f);
  2243. break;
  2244. case Unbind:
  2245. netunbind(f);
  2246. break;
  2247. default:
  2248. cmderror(cb, "unknown aoe control message");
  2249. }
  2250. poperror();
  2251. free(cb);
  2252. return n;
  2253. }
  2254. static int32_t
  2255. aoewrite(Chan *c, void *db, int32_t n, int64_t off)
  2256. {
  2257. switch(TYPE(c->qid)){
  2258. default:
  2259. case Qzero:
  2260. case Qtopdir:
  2261. case Qunitdir:
  2262. case Qtoplog:
  2263. error(Eperm);
  2264. case Qtopctl:
  2265. return topctlwrite(db, n);
  2266. case Qctl:
  2267. case Qdata:
  2268. case Qconfig:
  2269. case Qident:
  2270. return unitwrite(c, db, n, off);
  2271. }
  2272. }
  2273. Dev aoedevtab = {
  2274. L'æ',
  2275. "aoe",
  2276. devreset,
  2277. devinit,
  2278. devshutdown,
  2279. aoeattach,
  2280. aoewalk,
  2281. aoestat,
  2282. aoeopen,
  2283. devcreate,
  2284. aoeclose,
  2285. aoeread,
  2286. devbread,
  2287. aoewrite,
  2288. devbwrite,
  2289. devremove,
  2290. devwstat,
  2291. devpower,
  2292. devconfig,
  2293. };