devaoe.c 43 KB

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