dfs_9pfs.c 29 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186
  1. /*
  2. * Copyright (c) 2006-2023, RT-Thread Development Team
  3. *
  4. * SPDX-License-Identifier: Apache-2.0
  5. *
  6. * Change Logs:
  7. * Date Author Notes
  8. * 2023-02-25 GuEe-GUI the first version
  9. */
  10. #include <rthw.h>
  11. #include <rtthread.h>
  12. #include <rtservice.h>
  13. #define DBG_TAG "dfs.9p"
  14. #define DBG_LVL DBG_INFO
  15. #include <rtdbg.h>
  16. #include "dfs_9pfs.h"
  17. #include <drivers/misc.h>
  18. #include <drivers/byteorder.h>
  19. #include <posix/string.h>
  20. #define OREAD 0 /* open for read */
  21. #define OWRITE 1 /* write */
  22. #define ORDWR 2 /* read and write */
  23. #define OEXEC 3 /* execute, == read but check execute permission */
  24. #define OEXCL 4
  25. #define OTRUNC 16 /* or'ed in (except for exec), truncate file first */
  26. #define OCEXEC 32 /* or'ed in, close on exec */
  27. #define ORCLOSE 64 /* or'ed in, remove on close */
  28. #define OAPPEND 128 /* or'ed in, append */
  29. #define NOTAG ((rt_uint16_t)~0)
  30. #define NOFID ((rt_uint32_t)~0)
  31. #define TAG 1
  32. static rt_list_t _protocol_nodes = RT_LIST_OBJECT_INIT(_protocol_nodes);
  33. static struct rt_spinlock _protocol_lock = { 0 };
  34. #ifndef rt_le8_to_cpu
  35. #define rt_le8_to_cpu
  36. #endif
  37. #ifndef rt_cpu_to_le8
  38. #define rt_cpu_to_le8
  39. #endif
  40. #define P9_OF_OPS_GET(width, dir) \
  41. rt_inline rt_uint##width##_t get_##dir##_##value##width##_of( \
  42. struct p9_connection *conn, unsigned idx) \
  43. { \
  44. rt_uint##width##_t *vp = (void *)&conn->dir##_buffer[idx]; \
  45. return rt_le##width##_to_cpu(*vp); \
  46. }
  47. #define P9_OF_OPS_PUT(width, dir) \
  48. rt_inline void put_##dir##_##value##width##_of( \
  49. struct p9_connection *conn, unsigned idx, \
  50. rt_uint##width##_t value) \
  51. { \
  52. rt_uint##width##_t *vp = (void *)&conn->dir##_buffer[idx]; \
  53. *vp = rt_cpu_to_le##width(value); \
  54. }
  55. #define P9_OPS_PUT(width) \
  56. rt_inline rt_off_t put_value##width(struct p9_connection *conn, \
  57. rt_off_t off, rt_uint##width##_t value) \
  58. { \
  59. ((rt_uint##width##_t *)(conn->tx_buffer + off))[0] = \
  60. rt_cpu_to_le##width(value); \
  61. return off + sizeof(value); \
  62. }
  63. #define P9_OPS_GROUP(width) \
  64. P9_OF_OPS_GET(width, rx) \
  65. P9_OF_OPS_GET(width, tx) \
  66. P9_OF_OPS_PUT(width, rx) \
  67. P9_OF_OPS_PUT(width, tx) \
  68. P9_OPS_PUT(width)
  69. P9_OPS_GROUP(8)
  70. P9_OPS_GROUP(16)
  71. P9_OPS_GROUP(32)
  72. P9_OPS_GROUP(64)
  73. #undef P9_OF_OPS_GET
  74. #undef P9_OF_OPS_PUT
  75. #undef P9_OPS_GET
  76. #undef P9_OPS_GROUP
  77. rt_inline rt_uint32_t put_header(struct p9_connection *conn,
  78. rt_uint8_t hd, rt_uint16_t tag_flags)
  79. {
  80. rt_uint8_t *stack = conn->tx_buffer;
  81. ((rt_uint32_t *)stack)[0] = rt_cpu_to_le32(0);
  82. stack += sizeof(rt_uint32_t);
  83. stack[0] = hd;
  84. stack += sizeof(rt_uint8_t);
  85. ((rt_uint16_t *)stack)[0] = rt_cpu_to_le16(tag_flags);
  86. stack += sizeof(rt_uint16_t);
  87. return stack - conn->tx_buffer;
  88. }
  89. rt_inline rt_off_t put_bytes(struct p9_connection *conn, rt_off_t off,
  90. rt_uint8_t *bytes, rt_uint32_t count)
  91. {
  92. rt_uint8_t *stack = conn->tx_buffer + off;
  93. ((rt_uint16_t *)stack)[0] = rt_cpu_to_le16(count);
  94. stack += sizeof(rt_uint16_t);
  95. rt_memcpy(stack, bytes, count);
  96. stack += count;
  97. return stack - conn->tx_buffer;
  98. }
  99. rt_inline rt_off_t put_string(struct p9_connection *conn, rt_off_t off,
  100. char *string)
  101. {
  102. rt_uint32_t len = rt_strlen(string);
  103. rt_uint8_t *stack = conn->tx_buffer + off;
  104. ((rt_uint16_t *)stack)[0] = rt_cpu_to_le16(len);
  105. stack += sizeof(rt_uint16_t);
  106. rt_memcpy(stack, string, len);
  107. stack += len;
  108. return stack - conn->tx_buffer;
  109. }
  110. struct p9_connection *p9_connection_alloc(struct p9_protocol *p9p,
  111. const char *aname, rt_uint32_t buffer_size)
  112. {
  113. struct p9_connection *conn;
  114. if (!p9p || !aname)
  115. {
  116. return RT_NULL;
  117. }
  118. /* Buffer size expected to be 1M */
  119. buffer_size = rt_max_t(rt_uint32_t, buffer_size, 0x100000);
  120. if (!(conn = rt_malloc(sizeof(*conn) + buffer_size)))
  121. {
  122. return RT_NULL;
  123. }
  124. conn->msg_size = buffer_size;
  125. conn->fid = P9_ROOT_FID;
  126. #ifdef RT_USING_SMART
  127. conn->uname = "rt-smart";
  128. #else
  129. conn->uname = "rt-thread";
  130. #endif
  131. conn->aname = (char *)aname;
  132. conn->rx_buffer = (void *)conn + sizeof(*conn);
  133. conn->tx_buffer = conn->rx_buffer + buffer_size / 2;
  134. rt_mutex_init(&conn->lock, conn->aname, RT_IPC_FLAG_PRIO);
  135. conn->protocol = p9p;
  136. return conn;
  137. }
  138. rt_err_t p9_connection_free(struct p9_connection *conn)
  139. {
  140. rt_free(conn);
  141. return RT_EOK;
  142. }
  143. int p9_transaction(struct p9_connection *conn,
  144. rt_uint32_t tx_size, rt_uint32_t *out_rx_size)
  145. {
  146. rt_err_t err;
  147. rt_uint32_t rx_size;
  148. RT_ASSERT(conn != RT_NULL);
  149. RT_ASSERT(conn->protocol != RT_NULL);
  150. rx_size = conn->msg_size;
  151. if ((err = conn->protocol->transport(conn->protocol,
  152. conn->tx_buffer, tx_size, conn->rx_buffer, &rx_size)))
  153. {
  154. return P9_TRANSPORT_ERROR;
  155. }
  156. if (get_rx_value16_of(conn, P9_MSG_TAG) !=
  157. get_tx_value16_of(conn, P9_MSG_TAG))
  158. {
  159. return P9_UNEXPECTED_TAG;
  160. }
  161. if (get_rx_value8_of(conn, P9_MSG_ID) == P9_MSG_ERR)
  162. {
  163. rt_uint32_t err_len = rt_min_t(rt_uint32_t, sizeof(conn->error) - 1,
  164. get_rx_value16_of(conn, P9_MSG_ERR_STR_LEN));
  165. rt_strncpy(conn->error, (void *)&conn->rx_buffer[P9_MSG_ERR_STR], err_len);
  166. return P9_R_ERROR;
  167. }
  168. if ((get_tx_value8_of(conn, P9_MSG_ID) + 1) !=
  169. get_rx_value8_of(conn, P9_MSG_ID))
  170. {
  171. return P9_UNEXPECTED_MSG;
  172. }
  173. if (out_rx_size)
  174. {
  175. *out_rx_size = rx_size;
  176. }
  177. return 0;
  178. }
  179. int p9_version(struct p9_connection *conn)
  180. {
  181. int rc;
  182. rt_uint32_t size;
  183. RT_ASSERT(conn != RT_NULL);
  184. rt_mutex_take(&conn->lock, RT_WAITING_FOREVER);
  185. /*
  186. * size[4] Tversion tag[2] msize[4] version[s]
  187. * size[4] Rversion tag[2] msize[4] version[s]
  188. */
  189. size = put_header(conn, P9_HD_TVERSION, NOTAG);
  190. size = put_value32(conn, size, conn->msg_size);
  191. size = put_string(conn, size, P9_VERSION);
  192. put_tx_value32_of(conn, P9_MSG_SIZE, size);
  193. if (!(rc = p9_transaction(conn, size, RT_NULL)))
  194. {
  195. char *version;
  196. rt_uint32_t version_len;
  197. rt_uint32_t msg_size = get_rx_value32_of(conn, P9_MSG_VER_MSIZE);
  198. conn->msg_size = rt_min_t(rt_uint32_t, conn->msg_size, msg_size);
  199. version = (char *)&conn->rx_buffer[P9_MSG_VER_STR];
  200. version_len = get_rx_value16_of(conn, P9_MSG_VER_STR_LEN);
  201. LOG_D("Version: %s", version);
  202. if (!rt_strncmp(P9_VERSION_UNKNOWN, version, version_len))
  203. {
  204. rc = P9_UNKNOWN_VERSION;
  205. }
  206. }
  207. rt_mutex_release(&conn->lock);
  208. return rc;
  209. }
  210. int p9_attach(struct p9_connection *conn)
  211. {
  212. int rc;
  213. rt_uint32_t size;
  214. RT_ASSERT(conn != RT_NULL);
  215. if (19 + rt_strlen(conn->uname) + rt_strlen(conn->aname) > conn->msg_size)
  216. {
  217. return P9_MSG_TOO_LONG;
  218. }
  219. rt_mutex_take(&conn->lock, RT_WAITING_FOREVER);
  220. /*
  221. * size[4] Tattach tag[2] fid[4] afid[4] uname[s] aname[s]
  222. * size[4] Rattach tag[2] qid[13]
  223. */
  224. size = put_header(conn, P9_HD_TATTACH, TAG);
  225. size = put_value32(conn, size, conn->fid);
  226. size = put_value32(conn, size, NOFID);
  227. size = put_string(conn, size, conn->uname);
  228. size = put_string(conn, size, conn->aname);
  229. size = put_value32(conn, size, RT_UINT32_MAX);
  230. put_tx_value32_of(conn, P9_MSG_SIZE, size);
  231. rc = p9_transaction(conn, size, RT_NULL);
  232. rt_mutex_release(&conn->lock);
  233. return rc;
  234. }
  235. static int p9_clunk_lockess(struct p9_connection *conn, rt_uint32_t fid)
  236. {
  237. rt_uint32_t size;
  238. /*
  239. * size[4] Tclunk tag[2] fid[4]
  240. * size[4] Rclunk tag[2]
  241. */
  242. size = put_header(conn, P9_HD_TCLUNK, TAG);
  243. size = put_value32(conn, size, fid);
  244. put_tx_value32_of(conn, P9_MSG_SIZE, size);
  245. return p9_transaction(conn, size, RT_NULL);
  246. }
  247. int p9_clunk(struct p9_connection *conn, rt_uint32_t fid)
  248. {
  249. int rc;
  250. RT_ASSERT(conn != RT_NULL);
  251. rt_mutex_take(&conn->lock, RT_WAITING_FOREVER);
  252. rc = p9_clunk_lockess(conn, fid);
  253. rt_mutex_release(&conn->lock);
  254. return rc;
  255. }
  256. rt_err_t dfs_9pfs_add_tag(struct p9_protocol *p9p)
  257. {
  258. rt_ubase_t level;
  259. if (!p9p || !p9p->tag || !p9p->transport)
  260. {
  261. return -RT_EINVAL;
  262. }
  263. rt_list_init(&p9p->list);
  264. level = rt_spin_lock_irqsave(&_protocol_lock);
  265. rt_list_insert_before(&_protocol_nodes, &p9p->list);
  266. rt_spin_unlock_irqrestore(&_protocol_lock, level);
  267. LOG_D("Add tag(%s) on %s", p9p->tag, p9p->name);
  268. return RT_EOK;
  269. }
  270. rt_err_t dfs_9pfs_del_tag(struct p9_protocol *p9p)
  271. {
  272. rt_ubase_t level;
  273. if (!p9p)
  274. {
  275. return -RT_EINVAL;
  276. }
  277. level = rt_spin_lock_irqsave(&_protocol_lock);
  278. rt_list_remove(&p9p->list);
  279. rt_spin_unlock_irqrestore(&_protocol_lock, level);
  280. LOG_D("Delete tag(%s) on %s", p9p->tag, p9p->name);
  281. return RT_EOK;
  282. }
  283. static int p9_to_fs_err(int rc)
  284. {
  285. const int p9_err[] =
  286. {
  287. [0] = RT_EOK,
  288. [-P9_ERROR] = -EIO,
  289. [-P9_UNKNOWN_VERSION] = -ENOSYS,
  290. [-P9_R_ERROR] = -EIO,
  291. [-P9_MSG_TOO_LONG] = -ENOSPC,
  292. [-P9_UNEXPECTED_MSG] = -EINVAL,
  293. [-P9_UNEXPECTED_TAG] = -EINVAL,
  294. [-P9_TRANSPORT_ERROR] = -EIO,
  295. [-P9_NO_TRANSPORT] = -EINVAL,
  296. [-P9_NULL_PATH] = -EINVAL,
  297. [-P9_PATH_ELEMENT_TOO_LONG] = -EINVAL,
  298. [-P9_READ_UNEXPECTED_DATA] = -EINVAL,
  299. [-P9_NO_BUFFER] = -ENOSPC,
  300. [-P9_MSG_SIZE_TOO_BIG] = -ENOSPC,
  301. };
  302. return p9_err[-rc];
  303. }
  304. static int p9_alloc_fid(struct p9_connection *conn)
  305. {
  306. int fid = rt_bitmap_next_clear_bit(conn->fid_map, 0, DFS_FD_MAX);
  307. if (fid < DFS_FD_MAX)
  308. {
  309. rt_bitmap_set_bit(conn->fid_map, fid);
  310. return fid + P9_FILE_FID;
  311. }
  312. return NOFID;
  313. }
  314. static void p9_free_fid(struct p9_connection *conn, int fid)
  315. {
  316. if (fid >= P9_FILE_FID)
  317. {
  318. rt_bitmap_clear_bit(conn->fid_map, fid - P9_FILE_FID);
  319. }
  320. }
  321. static int p9_free_fid_clunk(struct p9_connection *conn, int fid)
  322. {
  323. int rc;
  324. if (!(rc = p9_clunk_lockess(conn, fid)))
  325. {
  326. p9_free_fid(conn, fid);
  327. }
  328. return rc;
  329. }
  330. static rt_uint8_t fs_to_p9_flags(rt_uint32_t raw_flags)
  331. {
  332. rt_uint8_t flags = 0;
  333. switch (raw_flags & 3)
  334. {
  335. case O_RDONLY: flags = OREAD; break;
  336. case O_WRONLY: flags = OWRITE; break;
  337. case O_RDWR: flags = ORDWR; break;
  338. default: RT_ASSERT(0); break;
  339. }
  340. if (raw_flags & O_TRUNC)
  341. {
  342. flags |= OTRUNC;
  343. }
  344. if (raw_flags & O_APPEND)
  345. {
  346. flags |= OAPPEND;
  347. }
  348. if (raw_flags & O_EXCL)
  349. {
  350. flags |= OEXCL;
  351. }
  352. return flags;
  353. }
  354. static char *p9_basename(const char *path)
  355. {
  356. const char *basename = strrchr(path, '/');
  357. return (char *)(basename ? basename + 1 : path);
  358. }
  359. static int p9_walk_path_raw(struct p9_connection *conn, const char *path,
  360. rt_bool_t submode)
  361. {
  362. rt_uint32_t size;
  363. const char *split;
  364. int rc, count = 0, len, fid = conn->fid, new_fid;
  365. new_fid = p9_alloc_fid(conn);
  366. if (new_fid < 0)
  367. {
  368. return P9_NO_BUFFER;
  369. }
  370. if (submode)
  371. {
  372. --count;
  373. }
  374. /* Pass '/' */
  375. ++path;
  376. /*
  377. * size[4] Twalk tag[2] fid[4] newfid[4] nwname[2] nwname*(wname[s])
  378. * size[4] Rwalk tag[2] nwqid[2] nwqid*(wqid[13])
  379. */
  380. size = put_header(conn, P9_HD_TWALK, TAG);
  381. size = put_value32(conn, size, fid);
  382. size = put_value32(conn, size, new_fid);
  383. size = put_value16(conn, size, 0); /* Fill later */
  384. do {
  385. split = strchrnul(path, '/');
  386. len = split - path;
  387. size = put_bytes(conn, size, (rt_uint8_t *)path, len);
  388. path += len + 1;
  389. ++count;
  390. } while (*split && count < P9_MSG_WALK_MAX_ELMT);
  391. if (count < P9_MSG_WALK_MAX_ELMT)
  392. {
  393. put_value16(conn, P9_MSG_WALK_TX_ELMT, count);
  394. if (!(rc = p9_transaction(conn, size, RT_NULL)))
  395. {
  396. if (count == get_rx_value16_of(conn, P9_MSG_WALK_RX_ELMT))
  397. {
  398. rc = new_fid;
  399. }
  400. else
  401. {
  402. /* Should be `P9_PARTIAL_WALK` if support longer path. */
  403. rc = P9_ERROR;
  404. p9_free_fid(conn, new_fid);
  405. }
  406. }
  407. }
  408. else
  409. {
  410. rc = P9_PATH_ELEMENT_TOO_LONG;
  411. p9_free_fid(conn, new_fid);
  412. }
  413. return rc;
  414. }
  415. rt_inline int p9_walk_path(struct p9_connection *conn, const char *path)
  416. {
  417. return p9_walk_path_raw(conn, path, RT_FALSE);
  418. }
  419. rt_inline int p9_walk_subpath(struct p9_connection *conn, const char *path)
  420. {
  421. return p9_walk_path_raw(conn, path, RT_TRUE);
  422. }
  423. static int dfs_9pfs_open(struct dfs_file *fd)
  424. {
  425. int rc;
  426. rt_uint32_t size;
  427. rt_bool_t is_root;
  428. struct p9_connection *conn;
  429. struct p9_file *p9f = rt_calloc(1, sizeof(*p9f));
  430. if (!p9f)
  431. {
  432. return -RT_ENOMEM;
  433. }
  434. conn = fd->vnode->fs->data;
  435. p9f->fid = conn->fid;
  436. p9f->connection = conn;
  437. is_root = !rt_strcmp(fd->vnode->path, "/");
  438. rt_mutex_take(&conn->lock, RT_WAITING_FOREVER);
  439. if (!is_root)
  440. {
  441. if ((rc = p9_walk_path(p9f->connection, fd->vnode->path)) > 0)
  442. {
  443. p9f->fid = rc;
  444. }
  445. else if (fd->flags & O_CREAT)
  446. {
  447. rt_uint32_t parent_fid, perm = 0755;
  448. if (fd->flags & O_DIRECTORY)
  449. {
  450. perm |= P9_STAT_MODE_DIR;
  451. }
  452. parent_fid = p9_walk_subpath(conn, fd->vnode->path);
  453. /*
  454. * size[4] Tcreate tag[2] fid[4] name[s] perm[4] mode[1] extension[s]
  455. * size[4] Rcreate tag[2] qid[13] iounit[4]
  456. */
  457. size = put_header(conn, P9_HD_TCREATE, TAG);
  458. size = put_value32(conn, size, parent_fid);
  459. size = put_string(conn, size, p9_basename(fd->vnode->path));
  460. size = put_value32(conn, size, perm);
  461. size = put_value8(conn, size, fs_to_p9_flags(fd->flags));
  462. size = put_string(conn, size, "");
  463. put_tx_value32_of(conn, P9_MSG_SIZE, size);
  464. if (!(rc = p9_transaction(conn, size, RT_NULL)))
  465. {
  466. p9f->iounit = get_rx_value32_of(conn, P9_MSG_CREATE_IOUNIT);
  467. if ((rc = p9_walk_path(p9f->connection, fd->vnode->path)) > 0)
  468. {
  469. p9f->fid = rc;
  470. }
  471. }
  472. p9_free_fid_clunk(conn, parent_fid);
  473. }
  474. }
  475. if (is_root || rc >= 0)
  476. {
  477. /*
  478. * size[4] Tstat tag[2] fid[4]
  479. * size[4] Rstat tag[2] stat[n]
  480. */
  481. size = put_header(conn, P9_HD_TSTAT, TAG);
  482. size = put_value32(conn, size, p9f->fid);
  483. put_tx_value32_of(conn, P9_MSG_SIZE, size);
  484. if (!(rc = p9_transaction(conn, size, RT_NULL)))
  485. {
  486. fd->vnode->size = get_rx_value64_of(conn, P9_MSG_STAT_LEN);
  487. /*
  488. * size[4] Topen tag[2] fid[4] mode[1]
  489. * size[4] Ropen tag[2] qid[13] iounit[4]
  490. */
  491. size = put_header(conn, P9_HD_TOPEN, TAG);
  492. size = put_value32(conn, size, p9f->fid);
  493. size = put_value8(conn, size, fs_to_p9_flags(fd->flags));
  494. put_tx_value32_of(conn, P9_MSG_SIZE, size);
  495. if (!(rc = p9_transaction(conn, size, RT_NULL)))
  496. {
  497. p9f->iounit = get_rx_value32_of(conn, P9_MSG_OPEN_IOUNIT);
  498. }
  499. }
  500. }
  501. rt_mutex_release(&conn->lock);
  502. if (!is_root && rc)
  503. {
  504. if (p9f->fid != conn->fid)
  505. {
  506. p9_free_fid(conn, p9f->fid);
  507. }
  508. rt_free(p9f);
  509. return p9_to_fs_err(rc);
  510. }
  511. fd->vnode->data = p9f;
  512. return 0;
  513. }
  514. static int dfs_9pfs_close(struct dfs_file *fd)
  515. {
  516. int rc = 0;
  517. struct p9_file *p9f = fd->vnode->data;
  518. struct p9_connection *conn = p9f->connection;
  519. if (p9f->fid != conn->fid)
  520. {
  521. rt_mutex_take(&conn->lock, RT_WAITING_FOREVER);
  522. rc = p9_free_fid_clunk(conn, p9f->fid);
  523. rt_mutex_release(&conn->lock);
  524. }
  525. if (!rc)
  526. {
  527. rt_free(p9f);
  528. }
  529. return p9_to_fs_err(rc);
  530. }
  531. static ssize_t dfs_9pfs_read(struct dfs_file *fd, void *buf, size_t count)
  532. {
  533. int rc;
  534. size_t tcount = 0;
  535. rt_uint32_t max_count, set, size, got;
  536. struct p9_file *p9f = fd->vnode->data;
  537. struct p9_connection *conn = p9f->connection;
  538. max_count = conn->msg_size - P9_MSG_READ_DATA;
  539. rt_mutex_take(&conn->lock, RT_WAITING_FOREVER);
  540. while ((ssize_t)count > 0)
  541. {
  542. set = rt_min_t(rt_uint32_t, max_count, count);
  543. /*
  544. * size[4] Tread tag[2] fid[4] offset[8] count[4]
  545. * size[4] Rread tag[2] count[4] data[count]
  546. */
  547. size = put_header(conn, P9_HD_TREAD, TAG);
  548. size = put_value32(conn, size, p9f->fid);
  549. size = put_value64(conn, size, fd->pos);
  550. size = put_value32(conn, size, set);
  551. put_tx_value32_of(conn, P9_MSG_SIZE, size);
  552. if (!(rc = p9_transaction(conn, size, RT_NULL)))
  553. {
  554. got = get_rx_value32_of(conn, P9_MSG_READ_COUNT);
  555. if (got == 0)
  556. {
  557. break;
  558. }
  559. else if (got <= set)
  560. {
  561. fd->pos += got;
  562. rt_memcpy(buf, conn->rx_buffer + P9_MSG_READ_DATA, got);
  563. }
  564. else
  565. {
  566. tcount = p9_to_fs_err(P9_READ_UNEXPECTED_DATA);
  567. break;
  568. }
  569. count -= got;
  570. tcount += got;
  571. }
  572. }
  573. rt_mutex_release(&conn->lock);
  574. return tcount;
  575. }
  576. static ssize_t dfs_9pfs_write(struct dfs_file *fd, const void *buf, size_t count)
  577. {
  578. int rc;
  579. size_t tcount = 0;
  580. rt_uint32_t max_count, set, size, got;
  581. struct p9_file *p9f = fd->vnode->data;
  582. struct p9_connection *conn = p9f->connection;
  583. max_count = conn->msg_size - P9_MSG_WRITE_DATA;
  584. rt_mutex_take(&conn->lock, RT_WAITING_FOREVER);
  585. while ((ssize_t)count > 0)
  586. {
  587. set = rt_min_t(rt_uint32_t, max_count, count);
  588. /*
  589. * size[4] Twrite tag[2] fid[4] offset[8] count[4] data[count]
  590. * size[4] Rwrite tag[2] count[4]
  591. */
  592. size = put_header(conn, P9_HD_TWRITE, TAG);
  593. size = put_value32(conn, size, p9f->fid);
  594. size = put_value64(conn, size, fd->pos);
  595. size = put_value32(conn, size, set);
  596. rt_memcpy(conn->tx_buffer + P9_MSG_WRITE_DATA, buf, set);
  597. size += set;
  598. put_tx_value32_of(conn, P9_MSG_SIZE, size);
  599. if (!(rc = p9_transaction(conn, size, RT_NULL)))
  600. {
  601. got = get_rx_value32_of(conn, P9_MSG_WRITE_COUNT);
  602. if (got <= set)
  603. {
  604. fd->pos += set;
  605. }
  606. else
  607. {
  608. tcount = p9_to_fs_err(P9_READ_UNEXPECTED_DATA);
  609. break;
  610. }
  611. count -= got;
  612. tcount += got;
  613. }
  614. }
  615. rt_mutex_release(&conn->lock);
  616. return tcount;
  617. }
  618. static int dfs_9pfs_flush(struct dfs_file *fd)
  619. {
  620. int rc;
  621. rt_uint32_t size;
  622. struct p9_file *p9f = fd->vnode->data;
  623. struct p9_connection *conn = p9f->connection;
  624. /*
  625. * size[4] Tfsync tag[2] fid[4] datasync[4]
  626. * size[4] Rfsync tag[2]
  627. */
  628. size = put_header(conn, P9_HD_TFSYNC, TAG);
  629. size = put_value32(conn, size, p9f->fid);
  630. size = put_value32(conn, size, 1);
  631. put_tx_value32_of(conn, P9_MSG_SIZE, size);
  632. rc = p9_transaction(conn, size, RT_NULL);
  633. return p9_to_fs_err(rc);
  634. }
  635. static off_t dfs_9pfs_lseek(struct dfs_file *fd, off_t offset)
  636. {
  637. int ret = -EIO;
  638. if (offset <= fd->vnode->size)
  639. {
  640. fd->pos = offset;
  641. ret = fd->pos;
  642. }
  643. return ret;
  644. }
  645. static int dfs_9pfs_getdents(struct dfs_file *fd, struct dirent *dirp, uint32_t count)
  646. {
  647. int rc;
  648. rt_uint64_t off;
  649. rt_uint32_t ret, end, stat_size, size;
  650. struct p9_file *p9f = fd->vnode->data;
  651. struct p9_connection *conn = p9f->connection;
  652. count = (count / sizeof(struct dirent));
  653. if (!count)
  654. {
  655. return -EINVAL;
  656. }
  657. end = fd->pos + count;
  658. count = 0;
  659. rt_mutex_take(&conn->lock, RT_WAITING_FOREVER);
  660. /*
  661. * size[4] Tread tag[2] fid[4] offset[8] count[4]
  662. * size[4] Rread tag[2] count[4] stat[n]
  663. */
  664. size = put_header(conn, P9_HD_TREAD, TAG);
  665. size = put_value32(conn, size, p9f->fid);
  666. size = put_value64(conn, size, 0);
  667. size = put_value32(conn, size, fd->vnode->size);
  668. put_tx_value32_of(conn, P9_MSG_SIZE, size);
  669. if (!(rc = p9_transaction(conn, size, RT_NULL)))
  670. {
  671. ret = get_rx_value32_of(conn, P9_MSG_READ_COUNT);
  672. off = P9_MSG_READ_DATA - P9_MSG_STAT_SIZE;
  673. for (int i = 0; (rt_int32_t)ret > 0; off += stat_size, ret -= stat_size, ++i)
  674. {
  675. /*
  676. * size[2] type[2] dev[4] qid[1+4+8] mode[4] atime[4] mtime[4] length[8]
  677. */
  678. stat_size = get_rx_value16_of(conn, off + P9_MSG_STAT_SIZE) + sizeof(rt_uint16_t);
  679. if (i < fd->pos)
  680. {
  681. continue;
  682. }
  683. if (get_rx_value16_of(conn, off + P9_MSG_STAT_TYPE) & P9_STAT_MODE_DIR)
  684. {
  685. dirp->d_type = DT_DIR;
  686. }
  687. else
  688. {
  689. dirp->d_type = DT_REG;
  690. }
  691. /*
  692. * name_size[2] name[name_size]
  693. * uid_size[2] uid[uid_size]
  694. * gid_size[2] gid[gid_size]
  695. * muid_size[2] muid[muid_size]
  696. * extension_size[2] extension[extension_size]
  697. * n_uid[4]
  698. * n_gid[4]
  699. * n_muid[4]
  700. */
  701. dirp->d_namlen = get_rx_value16_of(conn, off + P9_MSG_STAT_NAME_LEN);
  702. dirp->d_reclen = (rt_uint16_t)sizeof(struct dirent);
  703. rt_strncpy(dirp->d_name,
  704. (void *)conn->rx_buffer + off + P9_MSG_STAT_NAME,
  705. dirp->d_namlen);
  706. dirp->d_name[dirp->d_namlen] = '\0';
  707. if (!rt_strcmp(dirp->d_name, ".") || !rt_strcmp(dirp->d_name, ".."))
  708. {
  709. ++fd->pos;
  710. continue;
  711. }
  712. ++fd->pos;
  713. ++dirp;
  714. ++count;
  715. if (fd->pos >= end)
  716. {
  717. break;
  718. }
  719. }
  720. }
  721. rt_mutex_release(&conn->lock);
  722. count *= sizeof(struct dirent);
  723. return count;
  724. }
  725. static const struct dfs_file_ops _9pfs_fops =
  726. {
  727. .open = dfs_9pfs_open,
  728. .close = dfs_9pfs_close,
  729. .read = dfs_9pfs_read,
  730. .write = dfs_9pfs_write,
  731. .flush = dfs_9pfs_flush,
  732. .lseek = dfs_9pfs_lseek,
  733. .getdents = dfs_9pfs_getdents,
  734. };
  735. static int dfs_9pfs_mount(struct dfs_filesystem *fs,
  736. unsigned long rwflag, const void *data)
  737. {
  738. rt_ubase_t level;
  739. struct p9_protocol *p9p, *p9p_tmp;
  740. struct p9_connection *conn = RT_NULL;
  741. if (!data)
  742. {
  743. return (int)-RT_EINVAL;
  744. }
  745. level = rt_spin_lock_irqsave(&_protocol_lock);
  746. rt_list_for_each_entry(p9p_tmp, &_protocol_nodes, list)
  747. {
  748. if (!rt_strcmp(p9p_tmp->tag, data))
  749. {
  750. p9p = p9p_tmp;
  751. break;
  752. }
  753. }
  754. rt_spin_unlock_irqrestore(&_protocol_lock, level);
  755. if (!p9p)
  756. {
  757. return (int)-RT_EINVAL;
  758. }
  759. if (!(conn = p9_connection_alloc(p9p, p9p->tag, 0)))
  760. {
  761. return (int)-RT_ENOMEM;
  762. }
  763. if (p9_version(conn) || p9_attach(conn))
  764. {
  765. p9_connection_free(conn);
  766. return (int)-RT_EINVAL;
  767. }
  768. fs->data = conn;
  769. return (int)RT_EOK;
  770. }
  771. static int dfs_9pfs_unmount(struct dfs_filesystem *fs)
  772. {
  773. struct p9_connection *conn = fs->data;
  774. p9_clunk(conn, conn->fid);
  775. return p9_connection_free(conn);
  776. }
  777. static int dfs_9pfs_statfs(struct dfs_filesystem *fs, struct statfs *buf)
  778. {
  779. int rc;
  780. rt_uint32_t size;
  781. struct p9_connection *conn = fs->data;
  782. rt_mutex_take(&conn->lock, RT_WAITING_FOREVER);
  783. /*
  784. * size[4] Tstatfs tag[2] fid[4]
  785. * size[4] Rstatfs tag[2]
  786. * f_type[4]
  787. * f_bsize[4]
  788. * f_blocks[8]
  789. * f_bfree[8]
  790. * f_bavail[8]
  791. * f_files[8]
  792. * f_ffree[8]
  793. * fsid_val[8]
  794. * f_namelen[4]
  795. */
  796. size = put_header(conn, P9_HD_TSTATFS, TAG);
  797. size = put_value32(conn, size, conn->fid);
  798. put_tx_value32_of(conn, P9_MSG_SIZE, size);
  799. if (!(rc = p9_transaction(conn, size, RT_NULL)))
  800. {
  801. buf->f_bsize = get_rx_value32_of(conn, P9_MSG_F_BSIZE);
  802. buf->f_blocks = get_rx_value64_of(conn, P9_MSG_F_BLOCKS);
  803. buf->f_bfree = get_rx_value64_of(conn, P9_MSG_F_BFREE);
  804. buf->f_bavail = get_rx_value64_of(conn, P9_MSG_F_BAVAIL);
  805. }
  806. rt_mutex_release(&conn->lock);
  807. return p9_to_fs_err(rc);
  808. }
  809. static int dfs_9pfs_unlink(struct dfs_filesystem *fs, const char *pathname)
  810. {
  811. rt_uint32_t size;
  812. int rc = 0, fid;
  813. struct p9_connection *conn = fs->data;
  814. rt_mutex_take(&conn->lock, RT_WAITING_FOREVER);
  815. if ((rc = p9_walk_path(conn, pathname)) > 0)
  816. {
  817. fid = rc;
  818. /*
  819. * size[4] Tremove tag[2] fid[4]
  820. * size[4] Rremove tag[2]
  821. */
  822. size = put_header(conn, P9_HD_TREMOVE, TAG);
  823. size = put_value32(conn, size, fid);
  824. put_tx_value32_of(conn, P9_MSG_SIZE, size);
  825. rc = p9_transaction(conn, size, RT_NULL);
  826. p9_free_fid_clunk(conn, fid);
  827. }
  828. rt_mutex_release(&conn->lock);
  829. return p9_to_fs_err(rc);
  830. }
  831. static int dfs_9pfs_stat(struct dfs_filesystem *fs,
  832. const char *filename, struct stat *st)
  833. {
  834. int rc = 0, fid;
  835. rt_uint32_t size, mode;
  836. struct p9_connection *conn = fs->data;
  837. rt_mutex_take(&conn->lock, RT_WAITING_FOREVER);
  838. if ((rc = p9_walk_path(conn, filename)) > 0)
  839. {
  840. fid = rc;
  841. /*
  842. * size[4] Tstat tag[2] fid[4]
  843. * size[4] Rstat tag[2] stat[n]
  844. */
  845. size = put_header(conn, P9_HD_TSTAT, TAG);
  846. size = put_value32(conn, size, fid);
  847. put_tx_value32_of(conn, P9_MSG_SIZE, size);
  848. if (!(rc = p9_transaction(conn, size, RT_NULL)))
  849. {
  850. st->st_dev = 0;
  851. mode = get_rx_value32_of(conn, P9_MSG_STAT_MODE);
  852. st->st_mode = 0;
  853. if (mode & P9_STAT_MODE_DIR)
  854. {
  855. st->st_mode |= S_IFDIR;
  856. }
  857. else
  858. {
  859. st->st_mode |= S_IFREG;
  860. }
  861. if (mode & P9_STAT_MODE_SYMLINK)
  862. {
  863. st->st_mode |= S_IFLNK;
  864. }
  865. if (mode & P9_STAT_MODE_SOCKET)
  866. {
  867. st->st_mode |= S_IFSOCK;
  868. }
  869. if (mode & P9_STAT_MODE_NAMED_PIPE)
  870. {
  871. st->st_mode |= S_IFIFO;
  872. }
  873. if (mode & P9_STAT_MODE_SETUID)
  874. {
  875. st->st_mode |= S_ISUID;
  876. }
  877. if (mode & P9_STAT_MODE_SETGID)
  878. {
  879. st->st_mode |= S_ISGID;
  880. }
  881. if (mode & P9_STAT_MODE_SETVTX)
  882. {
  883. st->st_mode |= S_ISVTX;
  884. }
  885. st->st_atime = get_rx_value32_of(conn, P9_MSG_STAT_ATIME);
  886. st->st_mtime = get_rx_value32_of(conn, P9_MSG_STAT_MTIME);
  887. st->st_size = get_rx_value64_of(conn, P9_MSG_STAT_LEN);
  888. /*
  889. * name_size[2] name[name_size]
  890. * uid_size[2] uid[uid_size]
  891. * gid_size[2] gid[gid_size]
  892. * muid_size[2] muid[muid_size]
  893. * extension_size[2] extension[extension_size]
  894. * n_uid[4]
  895. * n_gid[4]
  896. * n_muid[4]
  897. */
  898. size = P9_MSG_STAT_NAME_LEN;
  899. size += sizeof(rt_uint16_t) + get_rx_value16_of(conn, size);
  900. size += sizeof(rt_uint16_t) + get_rx_value16_of(conn, size);
  901. size += sizeof(rt_uint16_t) + get_rx_value16_of(conn, size);
  902. size += sizeof(rt_uint16_t) + get_rx_value16_of(conn, size);
  903. st->st_uid = get_rx_value32_of(conn, size) + sizeof(rt_uint32_t);
  904. st->st_gid = get_rx_value32_of(conn, size) + sizeof(rt_uint32_t);
  905. }
  906. p9_free_fid_clunk(conn, fid);
  907. }
  908. rt_mutex_release(&conn->lock);
  909. return p9_to_fs_err(rc);
  910. }
  911. static int dfs_9pfs_rename(struct dfs_filesystem *fs,
  912. const char *oldpath, const char *newpath)
  913. {
  914. int rc = 0, fid;
  915. rt_uint32_t size;
  916. struct p9_connection *conn = fs->data;
  917. rt_mutex_take(&conn->lock, RT_WAITING_FOREVER);
  918. if ((fid = p9_walk_path(conn, oldpath)) > 0)
  919. {
  920. /*
  921. * size[4] Trename tag[2] fid[4] new_fid[4] name[s]
  922. * size[4] Rrename tag[2]
  923. */
  924. size = put_header(conn, P9_HD_TRENAME, TAG);
  925. size = put_value32(conn, size, fid);
  926. size = put_value32(conn, size, NOFID);
  927. size = put_string(conn, size, p9_basename(newpath));
  928. put_tx_value32_of(conn, P9_MSG_SIZE, size);
  929. rc = p9_transaction(conn, size, RT_NULL);
  930. p9_free_fid_clunk(conn, fid);
  931. }
  932. rt_mutex_release(&conn->lock);
  933. return p9_to_fs_err(rc);
  934. }
  935. static const struct dfs_filesystem_ops _9pfs =
  936. {
  937. .name = "9p",
  938. .flags = DFS_FS_FLAG_DEFAULT,
  939. .fops = &_9pfs_fops,
  940. .mount = dfs_9pfs_mount,
  941. .unmount = dfs_9pfs_unmount,
  942. .statfs = dfs_9pfs_statfs,
  943. .unlink = dfs_9pfs_unlink,
  944. .stat = dfs_9pfs_stat,
  945. .rename = dfs_9pfs_rename,
  946. };
  947. int dfs_9pfs_init(void)
  948. {
  949. /* register 9p file system */
  950. return dfs_register(&_9pfs);
  951. }
  952. INIT_COMPONENT_EXPORT(dfs_9pfs_init);