devaoe.c 42 KB

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