devaoe.c 41 KB

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