devlogfs.c 31 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522
  1. #ifndef EMU
  2. #include "u.h"
  3. #include "../port/lib.h"
  4. #include "../port/error.h"
  5. #else
  6. #include "error.h"
  7. #endif
  8. #include <dat.h>
  9. #include <fns.h>
  10. #include <kernel.h>
  11. #include <logfs.h>
  12. #include <nandfs.h>
  13. #ifndef EMU
  14. #define Sleep sleep
  15. #define Wakeup wakeup
  16. #endif
  17. #ifndef offsetof
  18. #define offsetof(T,X) ((ulong)&(((T*)0)->X))
  19. #endif
  20. typedef struct Devlogfs Devlogfs;
  21. typedef struct DevlogfsSession DevlogfsSession;
  22. //#define CALLTRACE
  23. enum {
  24. DEVLOGFSDEBUG = 0,
  25. DEVLOGFSIODEBUG = 0,
  26. DEVLOGFSBAD = 1,
  27. };
  28. enum {
  29. Qdir,
  30. Qctl,
  31. Qusers,
  32. Qdump,
  33. Qfs,
  34. Qfsboot,
  35. Qend,
  36. };
  37. typedef enum DevlogfsServerState { Closed, BootOpen, NeedVersion, NeedAttach, Attached, Hungup } DevlogfsServerState;
  38. struct Devlogfs {
  39. QLock qlock;
  40. Ref ref;
  41. int instance;
  42. int trace; /* (debugging) trace of read/write actions */
  43. int nand;
  44. char *name;
  45. char *device;
  46. char *filename[Qend - Qfs];
  47. LogfsLowLevel *ll;
  48. Chan *flash, *flashctl;
  49. QLock bootqlock;
  50. int logfstrace;
  51. LogfsBoot *lb;
  52. /* stuff for server */
  53. ulong openflags;
  54. Fcall in;
  55. Fcall out;
  56. int reading;
  57. DevlogfsServerState state;
  58. Rendez readrendez;
  59. Rendez writerendez;
  60. uint readcount;
  61. ulong readbufsize;
  62. uchar *readbuf;
  63. uchar *readp;
  64. LogfsServer *server;
  65. Devlogfs *next;
  66. };
  67. #define MAXMSIZE 8192
  68. static struct {
  69. RWlock rwlock; /* rlock when walking, wlock when changing */
  70. QLock configqlock; /* serialises addition of new configurations */
  71. Devlogfs *head;
  72. char *defname;
  73. } devlogfslist;
  74. static LogfsIdentityStore *is;
  75. #ifndef EMU
  76. char Eunknown[] = "unknown user or group id";
  77. #endif
  78. static void devlogfsfree(Devlogfs*);
  79. #define SPLITPATH(path, qtype, instance, qid, qt) { instance = path >> 4; qid = path & 0xf; qt = qtype & QTDIR; }
  80. #define DATAQID(q, qt) (!(qt) && (q) >= Qfs && (q) < Qend)
  81. #define MKPATH(instance, qid) ((instance << 4) | qid)
  82. #define PREFIX "logfs"
  83. static char *devlogfsprefix = PREFIX;
  84. static char *devlogfsctlname = PREFIX "ctl";
  85. static char *devlogfsusersname = PREFIX "users";
  86. static char *devlogfsdumpname = PREFIX "dump";
  87. static char *devlogfsbootsuffix = "boot";
  88. static char *devlogfs9pversion = "9P2000";
  89. enum {
  90. Toshiba = 0x98,
  91. Samsung = 0xec,
  92. };
  93. static struct {
  94. uchar manufacturer;
  95. uchar device;
  96. } nandtab[] = {
  97. { 0, 0xe6 },
  98. { 0, 0xea },
  99. { 0, 0xe3 },
  100. { 0, 0xe5 },
  101. { 0, 0x73 },
  102. { 0, 0x75 },
  103. { 0, 0x76 },
  104. };
  105. static void
  106. errorany(char *errmsg)
  107. {
  108. if (errmsg)
  109. error(errmsg);
  110. }
  111. static void *
  112. emalloc(ulong size)
  113. {
  114. void *p;
  115. p = logfsrealloc(nil, size);
  116. if (p == nil)
  117. error(Enomem);
  118. return p;
  119. }
  120. static char *
  121. estrdup(char *q)
  122. {
  123. void *p;
  124. if (q == nil)
  125. return nil;
  126. p = logfsrealloc(nil, strlen(q) + 1);
  127. if (p == nil)
  128. error(Enomem);
  129. return strcpy(p, q);
  130. }
  131. static char *
  132. estrconcat(char *a, ...)
  133. {
  134. va_list l;
  135. char *p, *r;
  136. int t;
  137. t = strlen(a);
  138. va_start(l, a);
  139. while ((p = va_arg(l, char *)) != nil)
  140. t += strlen(p);
  141. r = logfsrealloc(nil, t + 1);
  142. if (r == nil)
  143. error(Enomem);
  144. strcpy(r, a);
  145. va_start(l, a);
  146. while ((p = va_arg(l, char *)) != nil)
  147. strcat(r, p);
  148. va_end(l);
  149. return r;
  150. }
  151. static int
  152. gen(Chan *c, int i, Dir *dp, int lockit)
  153. {
  154. Devlogfs *l;
  155. long size;
  156. Qid qid;
  157. qid.vers = 0;
  158. qid.type = 0;
  159. if (i + Qctl < Qfs) {
  160. switch (i + Qctl) {
  161. case Qctl:
  162. qid.path = Qctl;
  163. devdir(c, qid, devlogfsctlname, 0, eve, 0666, dp);
  164. return 1;
  165. case Qusers:
  166. qid.path = Qusers;
  167. devdir(c, qid, devlogfsusersname, 0, eve, 0444, dp);
  168. return 1;
  169. case Qdump:
  170. qid.path = Qdump;
  171. devdir(c, qid, devlogfsdumpname, 0, eve, 0444, dp);
  172. return 1;
  173. }
  174. }
  175. i -= Qfs - Qctl;
  176. if (lockit)
  177. rlock(&devlogfslist.rwlock);
  178. if (waserror()) {
  179. if (lockit)
  180. runlock(&devlogfslist.rwlock);
  181. nexterror();
  182. }
  183. for (l = devlogfslist.head; l; l = l->next) {
  184. if (i < Qend - Qfs)
  185. break;
  186. i -= Qend - Qfs;
  187. }
  188. if (l == nil) {
  189. poperror();
  190. if (lockit)
  191. runlock(&devlogfslist.rwlock);
  192. return -1;
  193. }
  194. switch (Qfs + i) {
  195. case Qfsboot:
  196. size = l->lb ? logfsbootgetsize(l->lb) : 0;
  197. break;
  198. default:
  199. size = 0;
  200. break;
  201. }
  202. /* perhaps the user id should come from the underlying file */
  203. qid.path = MKPATH(l->instance, Qfs + i);
  204. devdir(c, qid, l->filename[i], size, eve, 0666, dp);
  205. poperror();
  206. if (lockit)
  207. runlock(&devlogfslist.rwlock);
  208. return 1;
  209. }
  210. static int
  211. devlogfsgen(Chan *c, char *n, Dirtab *tab, int ntab, int i, Dir *dp)
  212. {
  213. USED(n);
  214. USED(tab);
  215. USED(ntab);
  216. return gen(c, i, dp, 1);
  217. }
  218. static int
  219. devlogfsgennolock(Chan *c, char *n, Dirtab *tab, int ntab, int i, Dir *dp)
  220. {
  221. USED(n);
  222. USED(tab);
  223. USED(ntab);
  224. return gen(c, i, dp, 0);
  225. }
  226. /* called under lock */
  227. static Devlogfs *
  228. devlogfsfind(int instance)
  229. {
  230. Devlogfs *l;
  231. for (l = devlogfslist.head; l; l = l->next)
  232. if (l->instance == instance)
  233. break;
  234. return l;
  235. }
  236. static Devlogfs *
  237. devlogfsget(int instance)
  238. {
  239. Devlogfs *l;
  240. rlock(&devlogfslist.rwlock);
  241. for (l = devlogfslist.head; l; l = l->next)
  242. if (l->instance == instance)
  243. break;
  244. if (l)
  245. incref(&l->ref);
  246. runlock(&devlogfslist.rwlock);
  247. return l;
  248. }
  249. static Devlogfs *
  250. devlogfsfindbyname(char *name)
  251. {
  252. Devlogfs *l;
  253. rlock(&devlogfslist.rwlock);
  254. for (l = devlogfslist.head; l; l = l->next)
  255. if (strcmp(l->name, name) == 0)
  256. break;
  257. runlock(&devlogfslist.rwlock);
  258. return l;
  259. }
  260. static Devlogfs *
  261. devlogfssetdefname(char *name)
  262. {
  263. Devlogfs *l;
  264. char *searchname;
  265. wlock(&devlogfslist.rwlock);
  266. if (waserror()) {
  267. wunlock(&devlogfslist.rwlock);
  268. nexterror();
  269. }
  270. if (name == nil)
  271. searchname = devlogfslist.defname;
  272. else
  273. searchname = name;
  274. for (l = devlogfslist.head; l; l = l->next)
  275. if (strcmp(l->name, searchname) == 0)
  276. break;
  277. if (l == nil) {
  278. logfsfreemem(devlogfslist.defname);
  279. devlogfslist.defname = nil;
  280. }
  281. else if (name) {
  282. if (devlogfslist.defname) {
  283. logfsfreemem(devlogfslist.defname);
  284. devlogfslist.defname = nil;
  285. }
  286. devlogfslist.defname = estrdup(name);
  287. }
  288. poperror();
  289. wunlock(&devlogfslist.rwlock);
  290. return l;
  291. }
  292. static Chan *
  293. devlogfskopen(char *name, char *suffix, int mode)
  294. {
  295. Chan *c;
  296. char *fn;
  297. int fd;
  298. fn = estrconcat(name, suffix, 0);
  299. fd = kopen(fn, mode);
  300. logfsfreemem(fn);
  301. if (fd < 0)
  302. error(up->env->errstr);
  303. c = fdtochan(up->env->fgrp, fd, mode, 0, 1);
  304. kclose(fd);
  305. return c;
  306. }
  307. static char *
  308. xread(void *a, void *buf, long nbytes, ulong offset)
  309. {
  310. Devlogfs *l = a;
  311. long rv;
  312. if (DEVLOGFSIODEBUG || l->trace)
  313. print("devlogfs: %s: read(0x%lux, %ld)\n", l->device, offset, nbytes);
  314. l->flash->offset = offset;
  315. rv = kchanio(l->flash, buf, nbytes, OREAD);
  316. if (rv < 0) {
  317. print("devlogfs: %s: flash read error: %s\n", l->device, up->env->errstr);
  318. return up->env->errstr;
  319. }
  320. if (rv != nbytes) {
  321. print("devlogfs: %s: short flash read: offset %lud, %ld not %ld\n", l->device, offset, rv, nbytes);
  322. return "short read";
  323. }
  324. return nil;
  325. }
  326. static char *
  327. xwrite(void *a, void *buf, long nbytes, ulong offset)
  328. {
  329. Devlogfs *l = a;
  330. long rv;
  331. if (DEVLOGFSIODEBUG || l->trace)
  332. print("devlogfs: %s: write(0x%lux, %ld)\n", l->device, offset, nbytes);
  333. l->flash->offset = offset;
  334. rv = kchanio(l->flash, buf, nbytes, OWRITE);
  335. if (rv < 0) {
  336. print("devlogfs: %s: flash write error: %s\n", l->device, up->env->errstr);
  337. return up->env->errstr;
  338. }
  339. if (rv != nbytes) {
  340. print("devlogfs: %s: short flash write: offset %lud, %ld not %ld\n", l->device, offset, rv, nbytes);
  341. return "short write";
  342. }
  343. return nil;
  344. }
  345. static char *
  346. xerase(void *a, long address)
  347. {
  348. Devlogfs *l = a;
  349. char cmd[40];
  350. if (DEVLOGFSIODEBUG || l->trace)
  351. print("devlogfs: %s: erase(0x%lux)\n", l->device, address);
  352. snprint(cmd, sizeof(cmd), "erase 0x%8.8lux", address);
  353. if (kchanio(l->flashctl, cmd, strlen(cmd), OWRITE) <= 0) {
  354. print("devlogfs: %s: flash erase error: %s\n", l->device, up->env->errstr);
  355. return up->env->errstr;
  356. }
  357. return nil;
  358. }
  359. static char *
  360. xsync(void *a)
  361. {
  362. Devlogfs *l = a;
  363. uchar statbuf[STATFIXLEN];
  364. if (DEVLOGFSIODEBUG || l->trace)
  365. print("devlogfs: %s: sync()\n", l->device);
  366. memset(statbuf, 0xff, sizeof(statbuf));
  367. memset(statbuf + STATFIXLEN - 8, 0x00, 8);
  368. PBIT16(statbuf, sizeof(statbuf) - BIT16SZ);
  369. if (kwstat(l->device, statbuf, sizeof(statbuf)) < 0)
  370. return up->env->errstr;
  371. return nil;
  372. }
  373. //#define LEAKHUNT
  374. #ifdef LEAKHUNT
  375. #define MAXLIVE 2000
  376. typedef struct Live {
  377. void *p;
  378. int freed;
  379. ulong callerpc;
  380. } Live;
  381. static Live livemem[MAXLIVE];
  382. static void
  383. leakalloc(void *p, ulong callerpc)
  384. {
  385. int x;
  386. int use = -1;
  387. for (x = 0; x < MAXLIVE; x++) {
  388. if (livemem[x].p == p) {
  389. if (!livemem[x].freed)
  390. print("leakalloc: unexpected realloc of 0x%.8lux from 0x%.8lux\n", p, callerpc);
  391. // else
  392. // print("leakalloc: reusing address 0x%.8lux from 0x%.8lux\n", p, callerpc);
  393. livemem[x].freed = 0;
  394. livemem[x].callerpc = callerpc;
  395. return;
  396. }
  397. else if (use < 0 && livemem[x].p == 0)
  398. use = x;
  399. }
  400. if (use < 0)
  401. panic("leakalloc: too many live entries");
  402. livemem[use].p = p;
  403. livemem[use].freed = 0;
  404. livemem[use].callerpc = callerpc;
  405. }
  406. static void
  407. leakaudit(void)
  408. {
  409. int x;
  410. for (x = 0; x < MAXLIVE; x++) {
  411. if (livemem[x].p && !livemem[x].freed)
  412. print("leakaudit: 0x%.8lux from 0x%.8lux\n", livemem[x].p, livemem[x].callerpc);
  413. }
  414. }
  415. static void
  416. leakfree(void *p, ulong callerpc)
  417. {
  418. int x;
  419. if (p == nil)
  420. return;
  421. for (x = 0; x < MAXLIVE; x++) {
  422. if (livemem[x].p == p) {
  423. if (livemem[x].freed)
  424. print("leakfree: double free of 0x%.8lux from 0x%.8lux, originally by 0x%.8lux\n",
  425. p, callerpc, livemem[x].callerpc);
  426. livemem[x].freed = 1;
  427. livemem[x].callerpc = callerpc;
  428. return;
  429. }
  430. }
  431. print("leakfree: free of unalloced address 0x%.8lux from 0x%.8lux\n", p, callerpc);
  432. leakaudit();
  433. }
  434. static void
  435. leakrealloc(void *newp, void *oldp, ulong callerpc)
  436. {
  437. leakfree(oldp, callerpc);
  438. leakalloc(newp, callerpc);
  439. }
  440. #endif
  441. #ifdef LEAKHUNT
  442. static void *_realloc(void *p, ulong size, ulong callerpc)
  443. #else
  444. void *
  445. logfsrealloc(void *p, ulong size)
  446. #endif
  447. {
  448. void *q;
  449. ulong osize;
  450. if (waserror()) {
  451. print("wobbly thrown in memory allocator: %s\n", up->env->errstr);
  452. nexterror();
  453. }
  454. if (p == nil) {
  455. q = smalloc(size);
  456. poperror();
  457. #ifdef LEAKHUNT
  458. leakrealloc(q, nil, callerpc);
  459. #endif
  460. return q;
  461. }
  462. q = realloc(p, size);
  463. if (q) {
  464. poperror();
  465. #ifdef LEAKHUNT
  466. leakrealloc(q, p, callerpc);
  467. #endif
  468. return q;
  469. }
  470. q = smalloc(size);
  471. osize = msize(p);
  472. if (osize > size)
  473. osize = size;
  474. memmove(q, p, osize);
  475. free(p);
  476. poperror();
  477. #ifdef LEAKHUNT
  478. leakrealloc(q, p, callerpc);
  479. #endif
  480. return q;
  481. }
  482. #ifdef LEAKHUNT
  483. void *
  484. logfsrealloc(void *p, ulong size)
  485. {
  486. return _realloc(p, size, getcallerpc(&p));
  487. }
  488. void *
  489. nandfsrealloc(void *p, ulong size)
  490. {
  491. return _realloc(p, size, getcallerpc(&p));
  492. }
  493. #else
  494. void *
  495. nandfsrealloc(void *p, ulong size)
  496. {
  497. return logfsrealloc(p, size);
  498. }
  499. #endif
  500. void
  501. logfsfreemem(void *p)
  502. {
  503. #ifdef LEAKHUNT
  504. leakfree(p, getcallerpc(&p));
  505. #endif
  506. free(p);
  507. }
  508. void
  509. nandfsfreemem(void *p)
  510. {
  511. #ifdef LEAKHUNT
  512. leakfree(p, getcallerpc(&p));
  513. #endif
  514. free(p);
  515. }
  516. static Devlogfs *
  517. devlogfsconfig(char *name, char *device)
  518. {
  519. Devlogfs *newl, *l;
  520. int i;
  521. int n;
  522. char buf[100], *fields[8];
  523. long rawblocksize, rawsize;
  524. newl = nil;
  525. qlock(&devlogfslist.configqlock);
  526. if (waserror()) {
  527. qunlock(&devlogfslist.configqlock);
  528. devlogfsfree(newl);
  529. nexterror();
  530. }
  531. rlock(&devlogfslist.rwlock);
  532. for (l = devlogfslist.head; l; l = l->next)
  533. if (strcmp(l->name, name) == 0) {
  534. runlock(&devlogfslist.rwlock);
  535. error(Einuse);
  536. }
  537. /* horrid n^2 solution to finding a unique instance number */
  538. for (i = 0;; i++) {
  539. for (l = devlogfslist.head; l; l = l->next)
  540. if (l->instance == i)
  541. break;
  542. if (l == nil)
  543. break;
  544. }
  545. runlock(&devlogfslist.rwlock);
  546. newl = emalloc(sizeof(Devlogfs));
  547. newl->instance = i;
  548. newl->name = estrdup(name);
  549. newl->device = estrdup(device);
  550. newl->filename[Qfs - Qfs] = estrconcat(devlogfsprefix, name, nil);
  551. newl->filename[Qfsboot - Qfs] = estrconcat(devlogfsprefix, name, devlogfsbootsuffix, nil);
  552. newl->flash = devlogfskopen(device, nil, ORDWR);
  553. newl->flashctl = devlogfskopen(device, "ctl", ORDWR);
  554. newl->flashctl->offset = 0;
  555. if ((n = kchanio(newl->flashctl, buf, sizeof(buf), OREAD)) <= 0) {
  556. print("devlogfsconfig: read ctl failed: %s\n", up->env->errstr);
  557. error(up->env->errstr);
  558. }
  559. if (n >= sizeof(buf))
  560. n = sizeof(buf) - 1;
  561. buf[n] = 0;
  562. n = getfields(buf, fields, nelem(fields), 1, " \t\n");
  563. newl->nand = 0;
  564. if (n >= 2) {
  565. /* detect NAND devices, and learn parameters from there */
  566. ulong manufacturer = strtoul(fields[0], nil, 16);
  567. ulong device = strtoul(fields[1], nil, 16);
  568. int d;
  569. for (d = 0; d < sizeof(nandtab) / sizeof(nandtab[0]); d++) {
  570. if ((nandtab[d].manufacturer == manufacturer
  571. && nandtab[d].device == device)
  572. || (nandtab[d].manufacturer == 0
  573. && (manufacturer == Toshiba || manufacturer == Samsung)
  574. && nandtab[d].device == device))
  575. {
  576. if (DEVLOGFSDEBUG)
  577. print("devlogfsconfig: nand device detected\n");
  578. newl->nand = 1;
  579. break;
  580. }
  581. }
  582. }
  583. if (n < 4)
  584. error("unknown erase size");
  585. rawblocksize = strtol(fields[5], nil, 0);
  586. rawsize = strtol(fields[4], nil, 0)-strtol(fields[3], nil, 0);
  587. if (newl->nand == 0)
  588. error("only NAND supported at the moment");
  589. errorany(nandfsinit(newl, rawsize, rawblocksize, xread, xwrite, xerase, xsync, &newl->ll));
  590. wlock(&devlogfslist.rwlock);
  591. newl->next = devlogfslist.head;
  592. devlogfslist.head = newl;
  593. logfsfreemem(devlogfslist.defname);
  594. devlogfslist.defname = nil;
  595. if (waserror()) {
  596. }
  597. else {
  598. devlogfslist.defname = estrdup(name);
  599. poperror();
  600. }
  601. wunlock(&devlogfslist.rwlock);
  602. poperror();
  603. qunlock(&devlogfslist.configqlock);
  604. return newl;
  605. }
  606. void
  607. devlogfsunconfig(Devlogfs *devlogfs)
  608. {
  609. Devlogfs **lp;
  610. qlock(&devlogfslist.configqlock);
  611. if (waserror()) {
  612. qunlock(&devlogfslist.configqlock);
  613. nexterror();
  614. }
  615. wlock(&devlogfslist.rwlock);
  616. if (waserror()) {
  617. wunlock(&devlogfslist.rwlock);
  618. nexterror();
  619. }
  620. for (lp = &devlogfslist.head; *lp && (*lp) != devlogfs; lp = &(*lp)->next)
  621. ;
  622. if (*lp == nil) {
  623. if (DEVLOGFSBAD)
  624. print("devlogfsunconfig: not in list\n");
  625. }
  626. else
  627. *lp = devlogfs->next;
  628. poperror();
  629. wunlock(&devlogfslist.rwlock);
  630. /* now invisible to the naked eye */
  631. devlogfsfree(devlogfs);
  632. poperror();
  633. qunlock(&devlogfslist.configqlock);
  634. }
  635. static void
  636. devlogfsllopen(Devlogfs *l)
  637. {
  638. qlock(&l->qlock);
  639. if (waserror()) {
  640. qunlock(&l->qlock);
  641. nexterror();
  642. }
  643. if (l->lb == nil)
  644. errorany(logfsbootopen(l->ll, 0, 0, l->logfstrace, 1, &l->lb));
  645. l->state = BootOpen;
  646. poperror();
  647. qunlock(&l->qlock);
  648. }
  649. static void
  650. devlogfsllformat(Devlogfs *l, long bootsize)
  651. {
  652. qlock(&l->qlock);
  653. if (waserror()) {
  654. qunlock(&l->qlock);
  655. nexterror();
  656. }
  657. if (l->lb == nil)
  658. errorany(logfsformat(l->ll, 0, 0, bootsize, l->logfstrace));
  659. poperror();
  660. qunlock(&l->qlock);
  661. }
  662. static Chan *
  663. devlogfsattach(char *spec)
  664. {
  665. Chan *c;
  666. #ifdef CALLTRACE
  667. print("devlogfsattach(spec = %s) - start\n", spec);
  668. #endif
  669. /* create the identity store on first attach */
  670. if (is == nil)
  671. errorany(logfsisnew(&is));
  672. c = devattach(0x29f, spec);
  673. // c = devattach(L'ʟ', spec);
  674. #ifdef CALLTRACE
  675. print("devlogfsattach(spec = %s) - return %.8lux\n", spec, (ulong)c);
  676. #endif
  677. return c;
  678. }
  679. static Walkqid*
  680. devlogfswalk(Chan *c, Chan *nc, char **name, int nname)
  681. {
  682. int instance, qid, qt, clone;
  683. Walkqid *wq;
  684. #ifdef CALLTRACE
  685. print("devlogfswalk(c = 0x%.8lux, nc = 0x%.8lux, name = 0x%.8lux, nname = %d) - start\n",
  686. (ulong)c, (ulong)nc, (ulong)name, nname);
  687. #endif
  688. clone = 0;
  689. if(nc == nil){
  690. nc = devclone(c);
  691. nc->type = 0;
  692. SPLITPATH(c->qid.path, c->qid.type, instance, qid, qt);
  693. if(DATAQID(qid, qt))
  694. nc->aux = devlogfsget(instance);
  695. clone = 1;
  696. }
  697. wq = devwalk(c, nc, name, nname, 0, 0, devlogfsgen);
  698. if (wq == nil || wq->nqid < nname) {
  699. if(clone)
  700. cclose(nc);
  701. }
  702. else if (clone) {
  703. wq->clone = nc;
  704. nc->type = c->type;
  705. }
  706. #ifdef CALLTRACE
  707. print("devlogfswalk(c = 0x%.8lux, nc = 0x%.8lux, name = 0x%.8lux, nname = %d) - return\n",
  708. (ulong)c, (ulong)nc, (ulong)name, nname);
  709. #endif
  710. return wq;
  711. }
  712. static int
  713. devlogfsstat(Chan *c, uchar *dp, int n)
  714. {
  715. #ifdef CALLTRACE
  716. print("devlogfsstat(c = 0x%.8lux, dp = 0x%.8lux n= %d)\n",
  717. (ulong)c, (ulong)dp, n);
  718. #endif
  719. return devstat(c, dp, n, 0, 0, devlogfsgen);
  720. }
  721. static Chan*
  722. devlogfsopen(Chan *c, int omode)
  723. {
  724. int instance, qid, qt;
  725. omode = openmode(omode);
  726. SPLITPATH(c->qid.path, c->qid.type, instance, qid, qt);
  727. #ifdef CALLTRACE
  728. print("devlogfsopen(c = 0x%.8lux, omode = %o, instance = %d, qid = %d, qt = %d)\n",
  729. (ulong)c, omode, instance, qid, qt);
  730. #endif
  731. rlock(&devlogfslist.rwlock);
  732. if (waserror()) {
  733. runlock(&devlogfslist.rwlock);
  734. #ifdef CALLTRACE
  735. print("devlogfsopen(c = 0x%.8lux, omode = %o) - error %s\n", (ulong)c, omode, up->env->errstr);
  736. #endif
  737. nexterror();
  738. }
  739. if (DATAQID(qid, qt)) {
  740. Devlogfs *d;
  741. d = devlogfsfind(instance);
  742. if (d == nil)
  743. error(Enodev);
  744. if (strcmp(up->env->user, eve) != 0)
  745. error(Eperm);
  746. if (qid == Qfs && d->state != BootOpen)
  747. error(Eperm);
  748. if (d->server == nil) {
  749. errorany(logfsservernew(d->lb, d->ll, is, d->openflags, d->logfstrace, &d->server));
  750. d->state = NeedVersion;
  751. }
  752. c = devopen(c, omode, 0, 0, devlogfsgennolock);
  753. incref(&d->ref);
  754. c->aux = d;
  755. }
  756. else if (qid == Qctl || qid == Qusers) {
  757. if (strcmp(up->env->user, eve) != 0)
  758. error(Eperm);
  759. c = devopen(c, omode, 0, 0, devlogfsgennolock);
  760. }
  761. else
  762. c = devopen(c, omode, 0, 0, devlogfsgennolock);
  763. poperror();
  764. runlock(&devlogfslist.rwlock);
  765. #ifdef CALLTRACE
  766. print("devlogfsopen(c = 0x%.8lux, omode = %o) - return\n", (ulong)c, omode);
  767. #endif
  768. return c;
  769. }
  770. static void
  771. devlogfsclose(Chan *c)
  772. {
  773. int instance, qid, qt;
  774. #ifdef CALLTRACE
  775. print("devlogfsclose(c = 0x%.8lux)\n", (ulong)c);
  776. #endif
  777. SPLITPATH(c->qid.path, c->qid.type, instance, qid, qt);
  778. USED(instance);
  779. if(DATAQID(qid, qt) && (c->flag & COPEN) != 0) {
  780. Devlogfs *d;
  781. d = c->aux;
  782. qlock(&d->qlock);
  783. if (qid == Qfs && d->state == Attached) {
  784. logfsserverflush(d->server);
  785. logfsserverfree(&d->server);
  786. d->state = BootOpen;
  787. }
  788. qunlock(&d->qlock);
  789. decref(&d->ref);
  790. }
  791. #ifdef CALLTRACE
  792. print("devlogfsclose(c = 0x%.8lux) - return\n", (ulong)c);
  793. #endif
  794. }
  795. typedef char *(SMARTIOFN)(void *magic, void *buf, long n, ulong offset, int write);
  796. void
  797. smartio(SMARTIOFN *io, void *magic, void *buf, long n, ulong offset, long blocksize, int write)
  798. {
  799. void *tmp = nil;
  800. ulong blocks, toread;
  801. if (waserror()) {
  802. logfsfreemem(tmp);
  803. nexterror();
  804. }
  805. if (offset % blocksize) {
  806. ulong aoffset;
  807. int tmpoffset;
  808. int tocopy;
  809. if (tmp == nil)
  810. tmp = emalloc(blocksize);
  811. aoffset = offset / blocksize;
  812. aoffset *= blocksize;
  813. errorany((*io)(magic, tmp, blocksize, aoffset, 0));
  814. tmpoffset = offset - aoffset;
  815. tocopy = blocksize - tmpoffset;
  816. if (tocopy > n)
  817. tocopy = n;
  818. if (write) {
  819. memmove((uchar *)tmp + tmpoffset, buf, tocopy);
  820. errorany((*io)(magic, tmp, blocksize, aoffset, 1));
  821. }
  822. else
  823. memmove(buf, (uchar *)tmp + tmpoffset, tocopy);
  824. buf = (uchar *)buf + tocopy;
  825. n -= tocopy;
  826. offset = aoffset + blocksize;
  827. }
  828. blocks = n / blocksize;
  829. toread = blocks * blocksize;
  830. errorany((*io)(magic, buf, toread, offset, write));
  831. buf = (uchar *)buf + toread;
  832. n -= toread;
  833. offset += toread;
  834. if (n) {
  835. if (tmp == nil)
  836. tmp = emalloc(blocksize);
  837. errorany((*io)(magic, tmp, blocksize, offset, 0));
  838. if (write) {
  839. memmove(tmp, buf, n);
  840. errorany((*io)(magic, tmp, blocksize, offset, 1));
  841. }
  842. memmove(buf, tmp, n);
  843. }
  844. poperror();
  845. logfsfreemem(tmp);
  846. }
  847. static int
  848. readok(void *a)
  849. {
  850. Devlogfs *d = a;
  851. return d->reading;
  852. }
  853. static int
  854. writeok(void *a)
  855. {
  856. Devlogfs *d = a;
  857. return !d->reading;
  858. }
  859. long
  860. devlogfsserverread(Devlogfs *d, void *buf, long n)
  861. {
  862. if (d->state == Hungup)
  863. error(Ehungup);
  864. Sleep(&d->readrendez, readok, d);
  865. if (n > d->readcount)
  866. n = d->readcount;
  867. memmove(buf, d->readp, n);
  868. d->readp += n;
  869. d->readcount -= n;
  870. if (d->readcount == 0) {
  871. d->reading = 0;
  872. Wakeup(&d->writerendez);
  873. }
  874. return n;
  875. }
  876. static void
  877. reply(Devlogfs *d)
  878. {
  879. d->readp = d->readbuf;
  880. d->readcount = convS2M(&d->out, d->readp, d->readbufsize);
  881. //print("reply is %d bytes\n", d->readcount);
  882. if (d->readcount == 0)
  883. panic("logfs: reply: did not fit\n");
  884. d->reading = 1;
  885. Wakeup(&d->readrendez);
  886. }
  887. static void
  888. rerror(Devlogfs *d, char *ename)
  889. {
  890. d->out.type = Rerror;
  891. d->out.ename = ename;
  892. reply(d);
  893. }
  894. static struct {
  895. QLock qlock;
  896. int (*read)(void *magic, Devlogfs *d, int line, char *buf, int buflen);
  897. void *magic;
  898. Devlogfs *d;
  899. int line;
  900. } dump;
  901. static void *
  902. extentdumpinit(Devlogfs *d, int argc, char **argv)
  903. {
  904. int *p;
  905. ulong path;
  906. ulong flashaddr, length;
  907. long block;
  908. int page, offset;
  909. if (argc != 1)
  910. error(Ebadarg);
  911. path = strtoul(argv[0], 0, 0);
  912. errorany(logfsserverreadpathextent(d->server, path, 0, &flashaddr, &length, &block, &page, &offset));
  913. p = emalloc(sizeof(ulong));
  914. *p = path;
  915. return p;
  916. }
  917. static int
  918. extentdumpread(void *magic, Devlogfs *d, int line, char *buf, int buflen)
  919. {
  920. ulong *p = magic;
  921. ulong flashaddr, length;
  922. long block;
  923. int page, offset;
  924. USED(d);
  925. errorany(logfsserverreadpathextent(d->server, *p, line, &flashaddr, &length, &block, &page, &offset));
  926. if (length == 0)
  927. return 0;
  928. return snprint(buf, buflen, "%.8ux %ud %ld %d %d\n", flashaddr, length, block, page, offset);
  929. }
  930. void
  931. devlogfsdumpinit(Devlogfs *d,
  932. void *(*init)(Devlogfs *d, int argc, char **argv),
  933. int (*read)(void *magic, Devlogfs *d, int line, char *buf, int buflen), int argc, char **argv)
  934. {
  935. qlock(&dump.qlock);
  936. if (waserror()) {
  937. qunlock(&dump.qlock);
  938. nexterror();
  939. }
  940. if (d) {
  941. if (d->state < NeedVersion)
  942. error("not mounted");
  943. qlock(&d->qlock);
  944. if (waserror()) {
  945. qunlock(&d->qlock);
  946. nexterror();
  947. }
  948. }
  949. if (dump.magic) {
  950. logfsfreemem(dump.magic);
  951. dump.magic = nil;
  952. }
  953. dump.d = d;
  954. dump.magic = (*init)(d, argc, argv);
  955. dump.read = read;
  956. dump.line = 0;
  957. if (d) {
  958. poperror();
  959. qunlock(&d->qlock);
  960. }
  961. poperror();
  962. qunlock(&dump.qlock);
  963. }
  964. long
  965. devlogfsdumpread(char *buf, int buflen)
  966. {
  967. char *tmp = nil;
  968. long n;
  969. qlock(&dump.qlock);
  970. if (waserror()) {
  971. logfsfreemem(tmp);
  972. qunlock(&dump.qlock);
  973. nexterror();
  974. }
  975. if (dump.magic == nil)
  976. error(Eio);
  977. tmp = emalloc(READSTR);
  978. if (dump.d) {
  979. if (dump.d->state < NeedVersion)
  980. error("not mounted");
  981. qlock(&dump.d->qlock);
  982. if (waserror()) {
  983. qunlock(&dump.d->qlock);
  984. nexterror();
  985. }
  986. }
  987. n = (*dump.read)(dump.magic, dump.d, dump.line, tmp, READSTR);
  988. if (n) {
  989. dump.line++;
  990. n = readstr(0, buf, buflen, tmp);
  991. }
  992. if (dump.d) {
  993. poperror();
  994. qunlock(&dump.d->qlock);
  995. }
  996. logfsfreemem(tmp);
  997. poperror();
  998. qunlock(&dump.qlock);
  999. return n;
  1000. }
  1001. void
  1002. devlogfsserverlogsweep(Devlogfs *d, int justone)
  1003. {
  1004. int didsomething;
  1005. if (d->state < NeedVersion)
  1006. error("not mounted");
  1007. qlock(&d->qlock);
  1008. if (waserror()) {
  1009. qunlock(&d->qlock);
  1010. nexterror();
  1011. }
  1012. errorany(logfsserverlogsweep(d->server, justone, &didsomething));
  1013. poperror();
  1014. qunlock(&d->qlock);
  1015. }
  1016. void
  1017. devlogfsserverwrite(Devlogfs *d, void *buf, long n)
  1018. {
  1019. int locked = 0;
  1020. if (d->state == Hungup)
  1021. error(Ehungup);
  1022. Sleep(&d->writerendez, writeok, d);
  1023. if (convM2S(buf, n, &d->in) != n) {
  1024. /*
  1025. * someone is writing drivel; have nothing to do with them anymore
  1026. * most common cause; trying to mount authenticated
  1027. */
  1028. d->state = Hungup;
  1029. error(Ehungup);
  1030. }
  1031. d->out.tag = d->in.tag;
  1032. d->out.fid = d->in.fid;
  1033. d->out.type = d->in.type + 1;
  1034. if (waserror()) {
  1035. if (locked)
  1036. qunlock(&d->qlock);
  1037. rerror(d, up->env->errstr);
  1038. return;
  1039. }
  1040. if (d->in.type != Tversion && d->in.type != Tattach) {
  1041. if (d->state != Attached)
  1042. error("must be attached");
  1043. qlock(&d->qlock);
  1044. locked = 1;
  1045. }
  1046. switch (d->in.type) {
  1047. case Tauth:
  1048. error("no authentication needed");
  1049. case Tversion: {
  1050. char *rversion;
  1051. if (d->state != NeedVersion)
  1052. error("unexpected Tversion");
  1053. if (d->in.tag != NOTAG)
  1054. error("protocol botch");
  1055. /*
  1056. * check the version string
  1057. */
  1058. if (strcmp(d->in.version, devlogfs9pversion) != 0)
  1059. rversion = "unknown";
  1060. else
  1061. rversion = devlogfs9pversion;
  1062. /*
  1063. * allocate the reply buffer
  1064. */
  1065. d->readbufsize = d->in.msize;
  1066. if (d->readbufsize > MAXMSIZE)
  1067. d->readbufsize = MAXMSIZE;
  1068. d->readbuf = emalloc(d->readbufsize);
  1069. /*
  1070. * compose the Rversion
  1071. */
  1072. d->out.msize = d->readbufsize;
  1073. d->out.version = rversion;
  1074. d->state = NeedAttach;
  1075. break;
  1076. }
  1077. case Tattach:
  1078. if (d->state != NeedAttach)
  1079. error("unexpected attach");
  1080. if (d->in.afid != NOFID)
  1081. error("unexpected afid");
  1082. errorany(logfsserverattach(d->server, d->in.fid, d->in.uname, &d->out.qid));
  1083. d->state = Attached;
  1084. break;
  1085. case Tclunk:
  1086. errorany(logfsserverclunk(d->server, d->in.fid));
  1087. break;
  1088. case Tcreate:
  1089. errorany(logfsservercreate(d->server, d->in.fid, d->in.name, d->in.perm, d->in.mode, &d->out.qid));
  1090. d->out.iounit = d->readbufsize - 11;
  1091. break;
  1092. case Tflush:
  1093. break;
  1094. case Topen:
  1095. errorany(logfsserveropen(d->server, d->in.fid, d->in.mode, &d->out.qid));
  1096. d->out.iounit = d->readbufsize - 11;
  1097. break;
  1098. case Tread:
  1099. d->out.data = (char *)d->readbuf + 11;
  1100. /* TODO - avoid memmove */
  1101. errorany(logfsserverread(d->server, d->in.fid, d->in.offset, d->in.count, (uchar *)d->out.data,
  1102. d->readbufsize - 11, &d->out.count));
  1103. break;
  1104. case Tremove:
  1105. errorany(logfsserverremove(d->server, d->in.fid));
  1106. break;
  1107. case Tstat:
  1108. d->out.stat = d->readbuf + 9;
  1109. /* TODO - avoid memmove */
  1110. errorany(logfsserverstat(d->server, d->in.fid, d->out.stat, d->readbufsize - 9, &d->out.nstat));
  1111. // print("nstat %d\n", d->out.nstat);
  1112. break;
  1113. case Twalk:
  1114. errorany(logfsserverwalk(d->server, d->in.fid, d->in.newfid,
  1115. d->in.nwname, d->in.wname, &d->out.nwqid, d->out.wqid));
  1116. break;
  1117. case Twrite:
  1118. errorany(logfsserverwrite(d->server, d->in.fid, d->in.offset, d->in.count, (uchar *)d->in.data,
  1119. &d->out.count));
  1120. break;
  1121. case Twstat:
  1122. errorany(logfsserverwstat(d->server, d->in.fid, d->in.stat, d->in.nstat));
  1123. break;
  1124. default:
  1125. print("devlogfsserverwrite: msg %d unimplemented\n", d->in.type);
  1126. error("unimplemented");
  1127. }
  1128. poperror();
  1129. if (locked)
  1130. qunlock(&d->qlock);
  1131. reply(d);
  1132. }
  1133. static long
  1134. devlogfsread(Chan *c, void *buf, long n, vlong off)
  1135. {
  1136. int instance, qid, qt;
  1137. SPLITPATH(c->qid.path, c->qid.type, instance, qid, qt);
  1138. USED(instance);
  1139. #ifdef CALLTRACE
  1140. print("devlogfsread(c = 0x%.8lux, buf = 0x%.8lux, n = %ld, instance = %d, qid = %d, qt = %d) - start\n",
  1141. (ulong)c, (ulong)buf, n, instance, qid, qt);
  1142. #endif
  1143. if(qt & QTDIR) {
  1144. #ifdef CALLTRACE
  1145. print("devlogfsread(c = 0x%.8lux, buf = 0x%.8lux, n = %ld, instance = %d, qid = %d, qt = %d) - calling devdirread\n",
  1146. (ulong)c, (ulong)buf, n, instance, qid, qt);
  1147. #endif
  1148. return devdirread(c, buf, n, 0, 0, devlogfsgen);
  1149. }
  1150. if(DATAQID(qid, qt)) {
  1151. if (qid == Qfsboot) {
  1152. Devlogfs *l = c->aux;
  1153. qlock(&l->bootqlock);
  1154. if (waserror()) {
  1155. qunlock(&l->bootqlock);
  1156. nexterror();
  1157. }
  1158. smartio((SMARTIOFN *)logfsbootio, l->lb, buf, n, off, logfsbootgetiosize(l->lb), 0);
  1159. poperror();
  1160. qunlock(&l->bootqlock);
  1161. return n;
  1162. }
  1163. else if (qid == Qfs) {
  1164. Devlogfs *d = c->aux;
  1165. return devlogfsserverread(d, buf, n);
  1166. }
  1167. error(Eio);
  1168. }
  1169. if (qid == Qusers) {
  1170. long nr;
  1171. errorany(logfsisusersread(is, buf, n, (ulong)off, &nr));
  1172. return nr;
  1173. }
  1174. else if (qid == Qdump)
  1175. return devlogfsdumpread(buf, n);
  1176. if (qid != Qctl)
  1177. error(Egreg);
  1178. return 0;
  1179. }
  1180. static long
  1181. devlogfswrite(Chan *c, void *buf, long n, vlong off)
  1182. {
  1183. char cmd[64], *realfields[6];
  1184. int i;
  1185. int instance, qid, qt;
  1186. if(n <= 0)
  1187. return 0;
  1188. SPLITPATH(c->qid.path, c->qid.type, instance, qid, qt);
  1189. #ifdef CALLTRACE
  1190. print("devlogfswrite(c = 0x%.8lux, buf = 0x%.8lux, n = %ld, instance = %d, qid = %d, qt = %d) - start\n",
  1191. (ulong)c, (ulong)buf, n, instance, qid, qt);
  1192. #endif
  1193. USED(instance);
  1194. if(DATAQID(qid, qt)){
  1195. if (qid == Qfsboot) {
  1196. Devlogfs *l = c->aux;
  1197. qlock(&l->bootqlock);
  1198. if (waserror()) {
  1199. qunlock(&l->bootqlock);
  1200. nexterror();
  1201. }
  1202. smartio((SMARTIOFN *)logfsbootio, l->lb, buf, n, off, logfsbootgetiosize(l->lb), 1);
  1203. poperror();
  1204. qunlock(&l->bootqlock);
  1205. return n;
  1206. }
  1207. else if (qid == Qfs) {
  1208. Devlogfs *d = c->aux;
  1209. devlogfsserverwrite(d, buf, n);
  1210. return n;
  1211. }
  1212. error(Eio);
  1213. }
  1214. else if (qid == Qctl) {
  1215. Devlogfs *l = nil;
  1216. char **fields;
  1217. if(n > sizeof(cmd)-1)
  1218. n = sizeof(cmd)-1;
  1219. memmove(cmd, buf, n);
  1220. cmd[n] = 0;
  1221. i = getfields(cmd, realfields, 6, 1, " \t\n");
  1222. //print("i = %d\n", i);
  1223. if (i <= 0)
  1224. error(Ebadarg);
  1225. fields = realfields;
  1226. if (i == 3 && strcmp(fields[0], "uname") == 0) {
  1227. switch (fields[2][0]) {
  1228. default:
  1229. errorany(logfsisgroupcreate(is, fields[1], fields[2]));
  1230. break;
  1231. case ':':
  1232. errorany(logfsisgroupcreate(is, fields[1], fields[2] + 1));
  1233. break;
  1234. case '%':
  1235. errorany(logfsisgrouprename(is, fields[1], fields[2] + 1));
  1236. break;
  1237. case '=':
  1238. errorany(logfsisgroupsetleader(is, fields[1], fields[2] + 1));
  1239. break;
  1240. case '+':
  1241. errorany(logfsisgroupaddmember(is, fields[1], fields[2] + 1));
  1242. break;
  1243. case '-':
  1244. errorany(logfsisgroupremovemember(is, fields[1], fields[2] + 1));
  1245. break;
  1246. }
  1247. i = 0;
  1248. }
  1249. if (i == 4 && strcmp(fields[0], "fsys") == 0 && strcmp(fields[2], "config") == 0) {
  1250. l = devlogfsconfig(fields[1], fields[3]);
  1251. i = 0;
  1252. }
  1253. else if (i >= 2 && strcmp(fields[0], "fsys") == 0) {
  1254. l = devlogfssetdefname(fields[1]);
  1255. if (l == nil)
  1256. error(Ebadarg);
  1257. i -= 2;
  1258. fields += 2;
  1259. }
  1260. if (i != 0) {
  1261. if (l == nil)
  1262. l = devlogfssetdefname(nil);
  1263. if (i >= 1 && strcmp(fields[0], "open") == 0) {
  1264. int a;
  1265. if (l == nil)
  1266. error(Ebadarg);
  1267. for (a = 1; a < i; a++)
  1268. if (fields[a][0] == '-')
  1269. switch (fields[a][1]) {
  1270. case 'P':
  1271. l->openflags |= LogfsOpenFlagNoPerm;
  1272. break;
  1273. case 'W':
  1274. l->openflags |= LogfsOpenFlagWstatAllow;
  1275. break;
  1276. default:
  1277. error(Ebadarg);
  1278. }
  1279. devlogfsllopen(l);
  1280. i = 0;
  1281. }
  1282. else if (i == 2 && strcmp(fields[0], "format") == 0) {
  1283. if (l == nil)
  1284. error(Ebadarg);
  1285. devlogfsllformat(l, strtol(fields[1], nil, 0));
  1286. i = 0;
  1287. }
  1288. else if (i >= 1 && strcmp(fields[0], "sweep") == 0) {
  1289. if (l == nil)
  1290. error(Ebadarg);
  1291. devlogfsserverlogsweep(l, 0);
  1292. i = 0;
  1293. }
  1294. else if (i >= 1 && strcmp(fields[0], "sweepone") == 0) {
  1295. if (l == nil)
  1296. error(Ebadarg);
  1297. devlogfsserverlogsweep(l, 1);
  1298. i = 0;
  1299. }
  1300. else if (i <= 2&& strcmp(fields[0], "trace") == 0) {
  1301. if (l == nil)
  1302. error(Ebadarg);
  1303. l->logfstrace = i > 1 ? strtol(fields[1], nil, 0) : 0;
  1304. if (l->server)
  1305. logfsservertrace(l->server, l->logfstrace);
  1306. if (l->lb)
  1307. logfsboottrace(l->lb, l->logfstrace);
  1308. i = 0;
  1309. }
  1310. else if (i == 1 && strcmp(fields[0], "unconfig") == 0) {
  1311. if (l == nil)
  1312. error(Ebadarg);
  1313. if (l->ref.ref > 0)
  1314. error(Einuse);
  1315. devlogfsunconfig(l);
  1316. i = 0;
  1317. }
  1318. else if (i == 2 && strcmp(fields[0], "extent") == 0) {
  1319. if (l == nil)
  1320. error(Ebadarg);
  1321. devlogfsdumpinit(l, extentdumpinit, extentdumpread, i - 1, fields + 1);
  1322. i = 0;
  1323. }
  1324. else if (i >= 2 && strcmp(fields[0], "test") == 0) {
  1325. if (l == nil)
  1326. error(Ebadarg);
  1327. errorany(logfsservertestcmd(l->server, i - 1, fields + 1));
  1328. i = 0;
  1329. }
  1330. #ifdef LEAKHUNT
  1331. else if (i == 1 && strcmp(fields[0], "leakaudit") == 0) {
  1332. leakaudit();
  1333. i = 0;
  1334. }
  1335. #endif
  1336. }
  1337. if (i != 0)
  1338. error(Ebadarg);
  1339. return n;
  1340. }
  1341. error(Egreg);
  1342. return 0; /* not reached */
  1343. }
  1344. static void
  1345. devlogfsfree(Devlogfs *devlogfs)
  1346. {
  1347. if (devlogfs != nil) {
  1348. int i;
  1349. logfsfreemem(devlogfs->device);
  1350. logfsfreemem(devlogfs->name);
  1351. for (i = 0; i < Qend - Qfs; i++)
  1352. logfsfreemem(devlogfs->filename[i]);
  1353. cclose(devlogfs->flash);
  1354. cclose(devlogfs->flashctl);
  1355. qlock(&devlogfs->qlock);
  1356. logfsserverfree(&devlogfs->server);
  1357. logfsbootfree(devlogfs->lb);
  1358. if (devlogfs->ll)
  1359. (*devlogfs->ll->free)(devlogfs->ll);
  1360. logfsfreemem(devlogfs->readbuf);
  1361. qunlock(&devlogfs->qlock);
  1362. logfsfreemem(devlogfs);
  1363. }
  1364. }
  1365. #ifdef EMU
  1366. ulong
  1367. logfsnow(void)
  1368. {
  1369. extern vlong timeoffset;
  1370. return (timeoffset + osusectime()) / 1000000;
  1371. }
  1372. #endif
  1373. Dev logfsdevtab = {
  1374. 0x29f,
  1375. // L'ʟ',
  1376. "logfs",
  1377. #ifndef EMU
  1378. devreset,
  1379. #endif
  1380. devinit,
  1381. #ifndef EMU
  1382. devshutdown,
  1383. #endif
  1384. devlogfsattach,
  1385. devlogfswalk,
  1386. devlogfsstat,
  1387. devlogfsopen,
  1388. devcreate,
  1389. devlogfsclose,
  1390. devlogfsread,
  1391. devbread,
  1392. devlogfswrite,
  1393. devbwrite,
  1394. devremove,
  1395. devwstat,
  1396. };