2
0

9p-proxy.c 35 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237
  1. /*
  2. * 9p Proxy callback
  3. *
  4. * Copyright IBM, Corp. 2011
  5. *
  6. * Authors:
  7. * M. Mohan Kumar <mohan@in.ibm.com>
  8. *
  9. * This work is licensed under the terms of the GNU GPL, version 2. See
  10. * the COPYING file in the top-level directory.
  11. */
  12. #include "qemu/osdep.h"
  13. #include <sys/socket.h>
  14. #include <sys/un.h>
  15. #include "qemu-common.h"
  16. #include "9p.h"
  17. #include "qapi/error.h"
  18. #include "qemu/cutils.h"
  19. #include "qemu/error-report.h"
  20. #include "qemu/option.h"
  21. #include "fsdev/qemu-fsdev.h"
  22. #include "9p-proxy.h"
  23. typedef struct V9fsProxy {
  24. int sockfd;
  25. QemuMutex mutex;
  26. struct iovec in_iovec;
  27. struct iovec out_iovec;
  28. } V9fsProxy;
  29. /*
  30. * Return received file descriptor on success in *status.
  31. * errno is also returned on *status (which will be < 0)
  32. * return < 0 on transport error.
  33. */
  34. static int v9fs_receivefd(int sockfd, int *status)
  35. {
  36. struct iovec iov;
  37. struct msghdr msg;
  38. struct cmsghdr *cmsg;
  39. int retval, data, fd;
  40. union MsgControl msg_control;
  41. iov.iov_base = &data;
  42. iov.iov_len = sizeof(data);
  43. memset(&msg, 0, sizeof(msg));
  44. msg.msg_iov = &iov;
  45. msg.msg_iovlen = 1;
  46. msg.msg_control = &msg_control;
  47. msg.msg_controllen = sizeof(msg_control);
  48. do {
  49. retval = recvmsg(sockfd, &msg, 0);
  50. } while (retval < 0 && errno == EINTR);
  51. if (retval <= 0) {
  52. return retval;
  53. }
  54. /*
  55. * data is set to V9FS_FD_VALID, if ancillary data is sent. If this
  56. * request doesn't need ancillary data (fd) or an error occurred,
  57. * data is set to negative errno value.
  58. */
  59. if (data != V9FS_FD_VALID) {
  60. *status = data;
  61. return 0;
  62. }
  63. /*
  64. * File descriptor (fd) is sent in the ancillary data. Check if we
  65. * indeed received it. One of the reasons to fail to receive it is if
  66. * we exceeded the maximum number of file descriptors!
  67. */
  68. for (cmsg = CMSG_FIRSTHDR(&msg); cmsg; cmsg = CMSG_NXTHDR(&msg, cmsg)) {
  69. if (cmsg->cmsg_len != CMSG_LEN(sizeof(int)) ||
  70. cmsg->cmsg_level != SOL_SOCKET ||
  71. cmsg->cmsg_type != SCM_RIGHTS) {
  72. continue;
  73. }
  74. fd = *((int *)CMSG_DATA(cmsg));
  75. *status = fd;
  76. return 0;
  77. }
  78. *status = -ENFILE; /* Ancillary data sent but not received */
  79. return 0;
  80. }
  81. static ssize_t socket_read(int sockfd, void *buff, size_t size)
  82. {
  83. ssize_t retval, total = 0;
  84. while (size) {
  85. retval = read(sockfd, buff, size);
  86. if (retval == 0) {
  87. return -EIO;
  88. }
  89. if (retval < 0) {
  90. if (errno == EINTR) {
  91. continue;
  92. }
  93. return -errno;
  94. }
  95. size -= retval;
  96. buff += retval;
  97. total += retval;
  98. }
  99. return total;
  100. }
  101. /* Converts proxy_statfs to VFS statfs structure */
  102. static void prstatfs_to_statfs(struct statfs *stfs, ProxyStatFS *prstfs)
  103. {
  104. memset(stfs, 0, sizeof(*stfs));
  105. stfs->f_type = prstfs->f_type;
  106. stfs->f_bsize = prstfs->f_bsize;
  107. stfs->f_blocks = prstfs->f_blocks;
  108. stfs->f_bfree = prstfs->f_bfree;
  109. stfs->f_bavail = prstfs->f_bavail;
  110. stfs->f_files = prstfs->f_files;
  111. stfs->f_ffree = prstfs->f_ffree;
  112. stfs->f_fsid.__val[0] = prstfs->f_fsid[0] & 0xFFFFFFFFU;
  113. stfs->f_fsid.__val[1] = prstfs->f_fsid[1] >> 32 & 0xFFFFFFFFU;
  114. stfs->f_namelen = prstfs->f_namelen;
  115. stfs->f_frsize = prstfs->f_frsize;
  116. }
  117. /* Converts proxy_stat structure to VFS stat structure */
  118. static void prstat_to_stat(struct stat *stbuf, ProxyStat *prstat)
  119. {
  120. memset(stbuf, 0, sizeof(*stbuf));
  121. stbuf->st_dev = prstat->st_dev;
  122. stbuf->st_ino = prstat->st_ino;
  123. stbuf->st_nlink = prstat->st_nlink;
  124. stbuf->st_mode = prstat->st_mode;
  125. stbuf->st_uid = prstat->st_uid;
  126. stbuf->st_gid = prstat->st_gid;
  127. stbuf->st_rdev = prstat->st_rdev;
  128. stbuf->st_size = prstat->st_size;
  129. stbuf->st_blksize = prstat->st_blksize;
  130. stbuf->st_blocks = prstat->st_blocks;
  131. stbuf->st_atim.tv_sec = prstat->st_atim_sec;
  132. stbuf->st_atim.tv_nsec = prstat->st_atim_nsec;
  133. stbuf->st_mtime = prstat->st_mtim_sec;
  134. stbuf->st_mtim.tv_nsec = prstat->st_mtim_nsec;
  135. stbuf->st_ctime = prstat->st_ctim_sec;
  136. stbuf->st_ctim.tv_nsec = prstat->st_ctim_nsec;
  137. }
  138. /*
  139. * Response contains two parts
  140. * {header, data}
  141. * header.type == T_ERROR, data -> -errno
  142. * header.type == T_SUCCESS, data -> response
  143. * size of errno/response is given by header.size
  144. * returns < 0, on transport error. response is
  145. * valid only if status >= 0.
  146. */
  147. static int v9fs_receive_response(V9fsProxy *proxy, int type,
  148. int *status, void *response)
  149. {
  150. int retval;
  151. ProxyHeader header;
  152. struct iovec *reply = &proxy->in_iovec;
  153. *status = 0;
  154. reply->iov_len = 0;
  155. retval = socket_read(proxy->sockfd, reply->iov_base, PROXY_HDR_SZ);
  156. if (retval < 0) {
  157. return retval;
  158. }
  159. reply->iov_len = PROXY_HDR_SZ;
  160. retval = proxy_unmarshal(reply, 0, "dd", &header.type, &header.size);
  161. assert(retval == 4 * 2);
  162. /*
  163. * if response size > PROXY_MAX_IO_SZ, read the response but ignore it and
  164. * return -ENOBUFS
  165. */
  166. if (header.size > PROXY_MAX_IO_SZ) {
  167. int count;
  168. while (header.size > 0) {
  169. count = MIN(PROXY_MAX_IO_SZ, header.size);
  170. count = socket_read(proxy->sockfd, reply->iov_base, count);
  171. if (count < 0) {
  172. return count;
  173. }
  174. header.size -= count;
  175. }
  176. *status = -ENOBUFS;
  177. return 0;
  178. }
  179. retval = socket_read(proxy->sockfd,
  180. reply->iov_base + PROXY_HDR_SZ, header.size);
  181. if (retval < 0) {
  182. return retval;
  183. }
  184. reply->iov_len += header.size;
  185. /* there was an error during processing request */
  186. if (header.type == T_ERROR) {
  187. int ret;
  188. ret = proxy_unmarshal(reply, PROXY_HDR_SZ, "d", status);
  189. assert(ret == 4);
  190. return 0;
  191. }
  192. switch (type) {
  193. case T_LSTAT: {
  194. ProxyStat prstat;
  195. retval = proxy_unmarshal(reply, PROXY_HDR_SZ,
  196. "qqqdddqqqqqqqqqq", &prstat.st_dev,
  197. &prstat.st_ino, &prstat.st_nlink,
  198. &prstat.st_mode, &prstat.st_uid,
  199. &prstat.st_gid, &prstat.st_rdev,
  200. &prstat.st_size, &prstat.st_blksize,
  201. &prstat.st_blocks,
  202. &prstat.st_atim_sec, &prstat.st_atim_nsec,
  203. &prstat.st_mtim_sec, &prstat.st_mtim_nsec,
  204. &prstat.st_ctim_sec, &prstat.st_ctim_nsec);
  205. assert(retval == 8 * 3 + 4 * 3 + 8 * 10);
  206. prstat_to_stat(response, &prstat);
  207. break;
  208. }
  209. case T_STATFS: {
  210. ProxyStatFS prstfs;
  211. retval = proxy_unmarshal(reply, PROXY_HDR_SZ,
  212. "qqqqqqqqqqq", &prstfs.f_type,
  213. &prstfs.f_bsize, &prstfs.f_blocks,
  214. &prstfs.f_bfree, &prstfs.f_bavail,
  215. &prstfs.f_files, &prstfs.f_ffree,
  216. &prstfs.f_fsid[0], &prstfs.f_fsid[1],
  217. &prstfs.f_namelen, &prstfs.f_frsize);
  218. assert(retval == 8 * 11);
  219. prstatfs_to_statfs(response, &prstfs);
  220. break;
  221. }
  222. case T_READLINK: {
  223. V9fsString target;
  224. v9fs_string_init(&target);
  225. retval = proxy_unmarshal(reply, PROXY_HDR_SZ, "s", &target);
  226. strcpy(response, target.data);
  227. v9fs_string_free(&target);
  228. break;
  229. }
  230. case T_LGETXATTR:
  231. case T_LLISTXATTR: {
  232. V9fsString xattr;
  233. v9fs_string_init(&xattr);
  234. retval = proxy_unmarshal(reply, PROXY_HDR_SZ, "s", &xattr);
  235. memcpy(response, xattr.data, xattr.size);
  236. v9fs_string_free(&xattr);
  237. break;
  238. }
  239. case T_GETVERSION:
  240. retval = proxy_unmarshal(reply, PROXY_HDR_SZ, "q", response);
  241. assert(retval == 8);
  242. break;
  243. default:
  244. return -1;
  245. }
  246. if (retval < 0) {
  247. *status = retval;
  248. }
  249. return 0;
  250. }
  251. /*
  252. * return < 0 on transport error.
  253. * *status is valid only if return >= 0
  254. */
  255. static int v9fs_receive_status(V9fsProxy *proxy,
  256. struct iovec *reply, int *status)
  257. {
  258. int retval;
  259. ProxyHeader header;
  260. *status = 0;
  261. reply->iov_len = 0;
  262. retval = socket_read(proxy->sockfd, reply->iov_base, PROXY_HDR_SZ);
  263. if (retval < 0) {
  264. return retval;
  265. }
  266. reply->iov_len = PROXY_HDR_SZ;
  267. retval = proxy_unmarshal(reply, 0, "dd", &header.type, &header.size);
  268. assert(retval == 4 * 2);
  269. retval = socket_read(proxy->sockfd,
  270. reply->iov_base + PROXY_HDR_SZ, header.size);
  271. if (retval < 0) {
  272. return retval;
  273. }
  274. reply->iov_len += header.size;
  275. retval = proxy_unmarshal(reply, PROXY_HDR_SZ, "d", status);
  276. assert(retval == 4);
  277. return 0;
  278. }
  279. /*
  280. * Proxy->header and proxy->request written to socket by QEMU process.
  281. * This request read by proxy helper process
  282. * returns 0 on success and -errno on error
  283. */
  284. static int v9fs_request(V9fsProxy *proxy, int type, void *response, ...)
  285. {
  286. dev_t rdev;
  287. va_list ap;
  288. int size = 0;
  289. int retval = 0;
  290. uint64_t offset;
  291. ProxyHeader header = { 0, 0};
  292. struct timespec spec[2];
  293. int flags, mode, uid, gid;
  294. V9fsString *name, *value;
  295. V9fsString *path, *oldpath;
  296. struct iovec *iovec = NULL, *reply = NULL;
  297. qemu_mutex_lock(&proxy->mutex);
  298. if (proxy->sockfd == -1) {
  299. retval = -EIO;
  300. goto err_out;
  301. }
  302. iovec = &proxy->out_iovec;
  303. reply = &proxy->in_iovec;
  304. va_start(ap, response);
  305. switch (type) {
  306. case T_OPEN:
  307. path = va_arg(ap, V9fsString *);
  308. flags = va_arg(ap, int);
  309. retval = proxy_marshal(iovec, PROXY_HDR_SZ, "sd", path, flags);
  310. if (retval > 0) {
  311. header.size = retval;
  312. header.type = T_OPEN;
  313. }
  314. break;
  315. case T_CREATE:
  316. path = va_arg(ap, V9fsString *);
  317. flags = va_arg(ap, int);
  318. mode = va_arg(ap, int);
  319. uid = va_arg(ap, int);
  320. gid = va_arg(ap, int);
  321. retval = proxy_marshal(iovec, PROXY_HDR_SZ, "sdddd", path,
  322. flags, mode, uid, gid);
  323. if (retval > 0) {
  324. header.size = retval;
  325. header.type = T_CREATE;
  326. }
  327. break;
  328. case T_MKNOD:
  329. path = va_arg(ap, V9fsString *);
  330. mode = va_arg(ap, int);
  331. rdev = va_arg(ap, long int);
  332. uid = va_arg(ap, int);
  333. gid = va_arg(ap, int);
  334. retval = proxy_marshal(iovec, PROXY_HDR_SZ, "ddsdq",
  335. uid, gid, path, mode, rdev);
  336. if (retval > 0) {
  337. header.size = retval;
  338. header.type = T_MKNOD;
  339. }
  340. break;
  341. case T_MKDIR:
  342. path = va_arg(ap, V9fsString *);
  343. mode = va_arg(ap, int);
  344. uid = va_arg(ap, int);
  345. gid = va_arg(ap, int);
  346. retval = proxy_marshal(iovec, PROXY_HDR_SZ, "ddsd",
  347. uid, gid, path, mode);
  348. if (retval > 0) {
  349. header.size = retval;
  350. header.type = T_MKDIR;
  351. }
  352. break;
  353. case T_SYMLINK:
  354. oldpath = va_arg(ap, V9fsString *);
  355. path = va_arg(ap, V9fsString *);
  356. uid = va_arg(ap, int);
  357. gid = va_arg(ap, int);
  358. retval = proxy_marshal(iovec, PROXY_HDR_SZ, "ddss",
  359. uid, gid, oldpath, path);
  360. if (retval > 0) {
  361. header.size = retval;
  362. header.type = T_SYMLINK;
  363. }
  364. break;
  365. case T_LINK:
  366. oldpath = va_arg(ap, V9fsString *);
  367. path = va_arg(ap, V9fsString *);
  368. retval = proxy_marshal(iovec, PROXY_HDR_SZ, "ss",
  369. oldpath, path);
  370. if (retval > 0) {
  371. header.size = retval;
  372. header.type = T_LINK;
  373. }
  374. break;
  375. case T_LSTAT:
  376. path = va_arg(ap, V9fsString *);
  377. retval = proxy_marshal(iovec, PROXY_HDR_SZ, "s", path);
  378. if (retval > 0) {
  379. header.size = retval;
  380. header.type = T_LSTAT;
  381. }
  382. break;
  383. case T_READLINK:
  384. path = va_arg(ap, V9fsString *);
  385. size = va_arg(ap, int);
  386. retval = proxy_marshal(iovec, PROXY_HDR_SZ, "sd", path, size);
  387. if (retval > 0) {
  388. header.size = retval;
  389. header.type = T_READLINK;
  390. }
  391. break;
  392. case T_STATFS:
  393. path = va_arg(ap, V9fsString *);
  394. retval = proxy_marshal(iovec, PROXY_HDR_SZ, "s", path);
  395. if (retval > 0) {
  396. header.size = retval;
  397. header.type = T_STATFS;
  398. }
  399. break;
  400. case T_CHMOD:
  401. path = va_arg(ap, V9fsString *);
  402. mode = va_arg(ap, int);
  403. retval = proxy_marshal(iovec, PROXY_HDR_SZ, "sd", path, mode);
  404. if (retval > 0) {
  405. header.size = retval;
  406. header.type = T_CHMOD;
  407. }
  408. break;
  409. case T_CHOWN:
  410. path = va_arg(ap, V9fsString *);
  411. uid = va_arg(ap, int);
  412. gid = va_arg(ap, int);
  413. retval = proxy_marshal(iovec, PROXY_HDR_SZ, "sdd", path, uid, gid);
  414. if (retval > 0) {
  415. header.size = retval;
  416. header.type = T_CHOWN;
  417. }
  418. break;
  419. case T_TRUNCATE:
  420. path = va_arg(ap, V9fsString *);
  421. offset = va_arg(ap, uint64_t);
  422. retval = proxy_marshal(iovec, PROXY_HDR_SZ, "sq", path, offset);
  423. if (retval > 0) {
  424. header.size = retval;
  425. header.type = T_TRUNCATE;
  426. }
  427. break;
  428. case T_UTIME:
  429. path = va_arg(ap, V9fsString *);
  430. spec[0].tv_sec = va_arg(ap, long);
  431. spec[0].tv_nsec = va_arg(ap, long);
  432. spec[1].tv_sec = va_arg(ap, long);
  433. spec[1].tv_nsec = va_arg(ap, long);
  434. retval = proxy_marshal(iovec, PROXY_HDR_SZ, "sqqqq", path,
  435. spec[0].tv_sec, spec[1].tv_nsec,
  436. spec[1].tv_sec, spec[1].tv_nsec);
  437. if (retval > 0) {
  438. header.size = retval;
  439. header.type = T_UTIME;
  440. }
  441. break;
  442. case T_RENAME:
  443. oldpath = va_arg(ap, V9fsString *);
  444. path = va_arg(ap, V9fsString *);
  445. retval = proxy_marshal(iovec, PROXY_HDR_SZ, "ss", oldpath, path);
  446. if (retval > 0) {
  447. header.size = retval;
  448. header.type = T_RENAME;
  449. }
  450. break;
  451. case T_REMOVE:
  452. path = va_arg(ap, V9fsString *);
  453. retval = proxy_marshal(iovec, PROXY_HDR_SZ, "s", path);
  454. if (retval > 0) {
  455. header.size = retval;
  456. header.type = T_REMOVE;
  457. }
  458. break;
  459. case T_LGETXATTR:
  460. size = va_arg(ap, int);
  461. path = va_arg(ap, V9fsString *);
  462. name = va_arg(ap, V9fsString *);
  463. retval = proxy_marshal(iovec, PROXY_HDR_SZ,
  464. "dss", size, path, name);
  465. if (retval > 0) {
  466. header.size = retval;
  467. header.type = T_LGETXATTR;
  468. }
  469. break;
  470. case T_LLISTXATTR:
  471. size = va_arg(ap, int);
  472. path = va_arg(ap, V9fsString *);
  473. retval = proxy_marshal(iovec, PROXY_HDR_SZ, "ds", size, path);
  474. if (retval > 0) {
  475. header.size = retval;
  476. header.type = T_LLISTXATTR;
  477. }
  478. break;
  479. case T_LSETXATTR:
  480. path = va_arg(ap, V9fsString *);
  481. name = va_arg(ap, V9fsString *);
  482. value = va_arg(ap, V9fsString *);
  483. size = va_arg(ap, int);
  484. flags = va_arg(ap, int);
  485. retval = proxy_marshal(iovec, PROXY_HDR_SZ, "sssdd",
  486. path, name, value, size, flags);
  487. if (retval > 0) {
  488. header.size = retval;
  489. header.type = T_LSETXATTR;
  490. }
  491. break;
  492. case T_LREMOVEXATTR:
  493. path = va_arg(ap, V9fsString *);
  494. name = va_arg(ap, V9fsString *);
  495. retval = proxy_marshal(iovec, PROXY_HDR_SZ, "ss", path, name);
  496. if (retval > 0) {
  497. header.size = retval;
  498. header.type = T_LREMOVEXATTR;
  499. }
  500. break;
  501. case T_GETVERSION:
  502. path = va_arg(ap, V9fsString *);
  503. retval = proxy_marshal(iovec, PROXY_HDR_SZ, "s", path);
  504. if (retval > 0) {
  505. header.size = retval;
  506. header.type = T_GETVERSION;
  507. }
  508. break;
  509. default:
  510. error_report("Invalid type %d", type);
  511. retval = -EINVAL;
  512. break;
  513. }
  514. va_end(ap);
  515. if (retval < 0) {
  516. goto err_out;
  517. }
  518. /* marshal the header details */
  519. proxy_marshal(iovec, 0, "dd", header.type, header.size);
  520. header.size += PROXY_HDR_SZ;
  521. retval = qemu_write_full(proxy->sockfd, iovec->iov_base, header.size);
  522. if (retval != header.size) {
  523. goto close_error;
  524. }
  525. switch (type) {
  526. case T_OPEN:
  527. case T_CREATE:
  528. /*
  529. * A file descriptor is returned as response for
  530. * T_OPEN,T_CREATE on success
  531. */
  532. if (v9fs_receivefd(proxy->sockfd, &retval) < 0) {
  533. goto close_error;
  534. }
  535. break;
  536. case T_MKNOD:
  537. case T_MKDIR:
  538. case T_SYMLINK:
  539. case T_LINK:
  540. case T_CHMOD:
  541. case T_CHOWN:
  542. case T_RENAME:
  543. case T_TRUNCATE:
  544. case T_UTIME:
  545. case T_REMOVE:
  546. case T_LSETXATTR:
  547. case T_LREMOVEXATTR:
  548. if (v9fs_receive_status(proxy, reply, &retval) < 0) {
  549. goto close_error;
  550. }
  551. break;
  552. case T_LSTAT:
  553. case T_READLINK:
  554. case T_STATFS:
  555. case T_GETVERSION:
  556. if (v9fs_receive_response(proxy, type, &retval, response) < 0) {
  557. goto close_error;
  558. }
  559. break;
  560. case T_LGETXATTR:
  561. case T_LLISTXATTR:
  562. if (!size) {
  563. if (v9fs_receive_status(proxy, reply, &retval) < 0) {
  564. goto close_error;
  565. }
  566. } else {
  567. if (v9fs_receive_response(proxy, type, &retval, response) < 0) {
  568. goto close_error;
  569. }
  570. }
  571. break;
  572. }
  573. err_out:
  574. qemu_mutex_unlock(&proxy->mutex);
  575. return retval;
  576. close_error:
  577. close(proxy->sockfd);
  578. proxy->sockfd = -1;
  579. qemu_mutex_unlock(&proxy->mutex);
  580. return -EIO;
  581. }
  582. static int proxy_lstat(FsContext *fs_ctx, V9fsPath *fs_path, struct stat *stbuf)
  583. {
  584. int retval;
  585. retval = v9fs_request(fs_ctx->private, T_LSTAT, stbuf, fs_path);
  586. if (retval < 0) {
  587. errno = -retval;
  588. return -1;
  589. }
  590. return retval;
  591. }
  592. static ssize_t proxy_readlink(FsContext *fs_ctx, V9fsPath *fs_path,
  593. char *buf, size_t bufsz)
  594. {
  595. int retval;
  596. retval = v9fs_request(fs_ctx->private, T_READLINK, buf, fs_path, bufsz);
  597. if (retval < 0) {
  598. errno = -retval;
  599. return -1;
  600. }
  601. return strlen(buf);
  602. }
  603. static int proxy_close(FsContext *ctx, V9fsFidOpenState *fs)
  604. {
  605. return close(fs->fd);
  606. }
  607. static int proxy_closedir(FsContext *ctx, V9fsFidOpenState *fs)
  608. {
  609. return closedir(fs->dir.stream);
  610. }
  611. static int proxy_open(FsContext *ctx, V9fsPath *fs_path,
  612. int flags, V9fsFidOpenState *fs)
  613. {
  614. fs->fd = v9fs_request(ctx->private, T_OPEN, NULL, fs_path, flags);
  615. if (fs->fd < 0) {
  616. errno = -fs->fd;
  617. fs->fd = -1;
  618. }
  619. return fs->fd;
  620. }
  621. static int proxy_opendir(FsContext *ctx,
  622. V9fsPath *fs_path, V9fsFidOpenState *fs)
  623. {
  624. int serrno, fd;
  625. fs->dir.stream = NULL;
  626. fd = v9fs_request(ctx->private, T_OPEN, NULL, fs_path, O_DIRECTORY);
  627. if (fd < 0) {
  628. errno = -fd;
  629. return -1;
  630. }
  631. fs->dir.stream = fdopendir(fd);
  632. if (!fs->dir.stream) {
  633. serrno = errno;
  634. close(fd);
  635. errno = serrno;
  636. return -1;
  637. }
  638. return 0;
  639. }
  640. static void proxy_rewinddir(FsContext *ctx, V9fsFidOpenState *fs)
  641. {
  642. rewinddir(fs->dir.stream);
  643. }
  644. static off_t proxy_telldir(FsContext *ctx, V9fsFidOpenState *fs)
  645. {
  646. return telldir(fs->dir.stream);
  647. }
  648. static struct dirent *proxy_readdir(FsContext *ctx, V9fsFidOpenState *fs)
  649. {
  650. return readdir(fs->dir.stream);
  651. }
  652. static void proxy_seekdir(FsContext *ctx, V9fsFidOpenState *fs, off_t off)
  653. {
  654. seekdir(fs->dir.stream, off);
  655. }
  656. static ssize_t proxy_preadv(FsContext *ctx, V9fsFidOpenState *fs,
  657. const struct iovec *iov,
  658. int iovcnt, off_t offset)
  659. {
  660. ssize_t ret;
  661. #ifdef CONFIG_PREADV
  662. ret = preadv(fs->fd, iov, iovcnt, offset);
  663. #else
  664. ret = lseek(fs->fd, offset, SEEK_SET);
  665. if (ret >= 0) {
  666. ret = readv(fs->fd, iov, iovcnt);
  667. }
  668. #endif
  669. return ret;
  670. }
  671. static ssize_t proxy_pwritev(FsContext *ctx, V9fsFidOpenState *fs,
  672. const struct iovec *iov,
  673. int iovcnt, off_t offset)
  674. {
  675. ssize_t ret;
  676. #ifdef CONFIG_PREADV
  677. ret = pwritev(fs->fd, iov, iovcnt, offset);
  678. #else
  679. ret = lseek(fs->fd, offset, SEEK_SET);
  680. if (ret >= 0) {
  681. ret = writev(fs->fd, iov, iovcnt);
  682. }
  683. #endif
  684. #ifdef CONFIG_SYNC_FILE_RANGE
  685. if (ret > 0 && ctx->export_flags & V9FS_IMMEDIATE_WRITEOUT) {
  686. /*
  687. * Initiate a writeback. This is not a data integrity sync.
  688. * We want to ensure that we don't leave dirty pages in the cache
  689. * after write when writeout=immediate is sepcified.
  690. */
  691. sync_file_range(fs->fd, offset, ret,
  692. SYNC_FILE_RANGE_WAIT_BEFORE | SYNC_FILE_RANGE_WRITE);
  693. }
  694. #endif
  695. return ret;
  696. }
  697. static int proxy_chmod(FsContext *fs_ctx, V9fsPath *fs_path, FsCred *credp)
  698. {
  699. int retval;
  700. retval = v9fs_request(fs_ctx->private, T_CHMOD, NULL, fs_path,
  701. credp->fc_mode);
  702. if (retval < 0) {
  703. errno = -retval;
  704. }
  705. return retval;
  706. }
  707. static int proxy_mknod(FsContext *fs_ctx, V9fsPath *dir_path,
  708. const char *name, FsCred *credp)
  709. {
  710. int retval;
  711. V9fsString fullname;
  712. v9fs_string_init(&fullname);
  713. v9fs_string_sprintf(&fullname, "%s/%s", dir_path->data, name);
  714. retval = v9fs_request(fs_ctx->private, T_MKNOD, NULL, &fullname,
  715. credp->fc_mode, credp->fc_rdev,
  716. credp->fc_uid, credp->fc_gid);
  717. v9fs_string_free(&fullname);
  718. if (retval < 0) {
  719. errno = -retval;
  720. retval = -1;
  721. }
  722. return retval;
  723. }
  724. static int proxy_mkdir(FsContext *fs_ctx, V9fsPath *dir_path,
  725. const char *name, FsCred *credp)
  726. {
  727. int retval;
  728. V9fsString fullname;
  729. v9fs_string_init(&fullname);
  730. v9fs_string_sprintf(&fullname, "%s/%s", dir_path->data, name);
  731. retval = v9fs_request(fs_ctx->private, T_MKDIR, NULL, &fullname,
  732. credp->fc_mode, credp->fc_uid, credp->fc_gid);
  733. v9fs_string_free(&fullname);
  734. if (retval < 0) {
  735. errno = -retval;
  736. retval = -1;
  737. }
  738. return retval;
  739. }
  740. static int proxy_fstat(FsContext *fs_ctx, int fid_type,
  741. V9fsFidOpenState *fs, struct stat *stbuf)
  742. {
  743. int fd;
  744. if (fid_type == P9_FID_DIR) {
  745. fd = dirfd(fs->dir.stream);
  746. } else {
  747. fd = fs->fd;
  748. }
  749. return fstat(fd, stbuf);
  750. }
  751. static int proxy_open2(FsContext *fs_ctx, V9fsPath *dir_path, const char *name,
  752. int flags, FsCred *credp, V9fsFidOpenState *fs)
  753. {
  754. V9fsString fullname;
  755. v9fs_string_init(&fullname);
  756. v9fs_string_sprintf(&fullname, "%s/%s", dir_path->data, name);
  757. fs->fd = v9fs_request(fs_ctx->private, T_CREATE, NULL, &fullname, flags,
  758. credp->fc_mode, credp->fc_uid, credp->fc_gid);
  759. v9fs_string_free(&fullname);
  760. if (fs->fd < 0) {
  761. errno = -fs->fd;
  762. fs->fd = -1;
  763. }
  764. return fs->fd;
  765. }
  766. static int proxy_symlink(FsContext *fs_ctx, const char *oldpath,
  767. V9fsPath *dir_path, const char *name, FsCred *credp)
  768. {
  769. int retval;
  770. V9fsString fullname, target;
  771. v9fs_string_init(&fullname);
  772. v9fs_string_init(&target);
  773. v9fs_string_sprintf(&fullname, "%s/%s", dir_path->data, name);
  774. v9fs_string_sprintf(&target, "%s", oldpath);
  775. retval = v9fs_request(fs_ctx->private, T_SYMLINK, NULL, &target, &fullname,
  776. credp->fc_uid, credp->fc_gid);
  777. v9fs_string_free(&fullname);
  778. v9fs_string_free(&target);
  779. if (retval < 0) {
  780. errno = -retval;
  781. retval = -1;
  782. }
  783. return retval;
  784. }
  785. static int proxy_link(FsContext *ctx, V9fsPath *oldpath,
  786. V9fsPath *dirpath, const char *name)
  787. {
  788. int retval;
  789. V9fsString newpath;
  790. v9fs_string_init(&newpath);
  791. v9fs_string_sprintf(&newpath, "%s/%s", dirpath->data, name);
  792. retval = v9fs_request(ctx->private, T_LINK, NULL, oldpath, &newpath);
  793. v9fs_string_free(&newpath);
  794. if (retval < 0) {
  795. errno = -retval;
  796. retval = -1;
  797. }
  798. return retval;
  799. }
  800. static int proxy_truncate(FsContext *ctx, V9fsPath *fs_path, off_t size)
  801. {
  802. int retval;
  803. retval = v9fs_request(ctx->private, T_TRUNCATE, NULL, fs_path, size);
  804. if (retval < 0) {
  805. errno = -retval;
  806. return -1;
  807. }
  808. return 0;
  809. }
  810. static int proxy_rename(FsContext *ctx, const char *oldpath,
  811. const char *newpath)
  812. {
  813. int retval;
  814. V9fsString oldname, newname;
  815. v9fs_string_init(&oldname);
  816. v9fs_string_init(&newname);
  817. v9fs_string_sprintf(&oldname, "%s", oldpath);
  818. v9fs_string_sprintf(&newname, "%s", newpath);
  819. retval = v9fs_request(ctx->private, T_RENAME, NULL, &oldname, &newname);
  820. v9fs_string_free(&oldname);
  821. v9fs_string_free(&newname);
  822. if (retval < 0) {
  823. errno = -retval;
  824. }
  825. return retval;
  826. }
  827. static int proxy_chown(FsContext *fs_ctx, V9fsPath *fs_path, FsCred *credp)
  828. {
  829. int retval;
  830. retval = v9fs_request(fs_ctx->private, T_CHOWN, NULL, fs_path,
  831. credp->fc_uid, credp->fc_gid);
  832. if (retval < 0) {
  833. errno = -retval;
  834. }
  835. return retval;
  836. }
  837. static int proxy_utimensat(FsContext *s, V9fsPath *fs_path,
  838. const struct timespec *buf)
  839. {
  840. int retval;
  841. retval = v9fs_request(s->private, T_UTIME, NULL, fs_path,
  842. buf[0].tv_sec, buf[0].tv_nsec,
  843. buf[1].tv_sec, buf[1].tv_nsec);
  844. if (retval < 0) {
  845. errno = -retval;
  846. }
  847. return retval;
  848. }
  849. static int proxy_remove(FsContext *ctx, const char *path)
  850. {
  851. int retval;
  852. V9fsString name;
  853. v9fs_string_init(&name);
  854. v9fs_string_sprintf(&name, "%s", path);
  855. retval = v9fs_request(ctx->private, T_REMOVE, NULL, &name);
  856. v9fs_string_free(&name);
  857. if (retval < 0) {
  858. errno = -retval;
  859. }
  860. return retval;
  861. }
  862. static int proxy_fsync(FsContext *ctx, int fid_type,
  863. V9fsFidOpenState *fs, int datasync)
  864. {
  865. int fd;
  866. if (fid_type == P9_FID_DIR) {
  867. fd = dirfd(fs->dir.stream);
  868. } else {
  869. fd = fs->fd;
  870. }
  871. if (datasync) {
  872. return qemu_fdatasync(fd);
  873. } else {
  874. return fsync(fd);
  875. }
  876. }
  877. static int proxy_statfs(FsContext *s, V9fsPath *fs_path, struct statfs *stbuf)
  878. {
  879. int retval;
  880. retval = v9fs_request(s->private, T_STATFS, stbuf, fs_path);
  881. if (retval < 0) {
  882. errno = -retval;
  883. return -1;
  884. }
  885. return retval;
  886. }
  887. static ssize_t proxy_lgetxattr(FsContext *ctx, V9fsPath *fs_path,
  888. const char *name, void *value, size_t size)
  889. {
  890. int retval;
  891. V9fsString xname;
  892. v9fs_string_init(&xname);
  893. v9fs_string_sprintf(&xname, "%s", name);
  894. retval = v9fs_request(ctx->private, T_LGETXATTR, value, size, fs_path,
  895. &xname);
  896. v9fs_string_free(&xname);
  897. if (retval < 0) {
  898. errno = -retval;
  899. }
  900. return retval;
  901. }
  902. static ssize_t proxy_llistxattr(FsContext *ctx, V9fsPath *fs_path,
  903. void *value, size_t size)
  904. {
  905. int retval;
  906. retval = v9fs_request(ctx->private, T_LLISTXATTR, value, size, fs_path);
  907. if (retval < 0) {
  908. errno = -retval;
  909. }
  910. return retval;
  911. }
  912. static int proxy_lsetxattr(FsContext *ctx, V9fsPath *fs_path, const char *name,
  913. void *value, size_t size, int flags)
  914. {
  915. int retval;
  916. V9fsString xname, xvalue;
  917. v9fs_string_init(&xname);
  918. v9fs_string_sprintf(&xname, "%s", name);
  919. v9fs_string_init(&xvalue);
  920. xvalue.size = size;
  921. xvalue.data = g_malloc(size);
  922. memcpy(xvalue.data, value, size);
  923. retval = v9fs_request(ctx->private, T_LSETXATTR, value, fs_path, &xname,
  924. &xvalue, size, flags);
  925. v9fs_string_free(&xname);
  926. v9fs_string_free(&xvalue);
  927. if (retval < 0) {
  928. errno = -retval;
  929. }
  930. return retval;
  931. }
  932. static int proxy_lremovexattr(FsContext *ctx, V9fsPath *fs_path,
  933. const char *name)
  934. {
  935. int retval;
  936. V9fsString xname;
  937. v9fs_string_init(&xname);
  938. v9fs_string_sprintf(&xname, "%s", name);
  939. retval = v9fs_request(ctx->private, T_LREMOVEXATTR, NULL, fs_path, &xname);
  940. v9fs_string_free(&xname);
  941. if (retval < 0) {
  942. errno = -retval;
  943. }
  944. return retval;
  945. }
  946. static int proxy_name_to_path(FsContext *ctx, V9fsPath *dir_path,
  947. const char *name, V9fsPath *target)
  948. {
  949. if (dir_path) {
  950. v9fs_path_sprintf(target, "%s/%s", dir_path->data, name);
  951. } else {
  952. v9fs_path_sprintf(target, "%s", name);
  953. }
  954. return 0;
  955. }
  956. static int proxy_renameat(FsContext *ctx, V9fsPath *olddir,
  957. const char *old_name, V9fsPath *newdir,
  958. const char *new_name)
  959. {
  960. int ret;
  961. V9fsString old_full_name, new_full_name;
  962. v9fs_string_init(&old_full_name);
  963. v9fs_string_init(&new_full_name);
  964. v9fs_string_sprintf(&old_full_name, "%s/%s", olddir->data, old_name);
  965. v9fs_string_sprintf(&new_full_name, "%s/%s", newdir->data, new_name);
  966. ret = proxy_rename(ctx, old_full_name.data, new_full_name.data);
  967. v9fs_string_free(&old_full_name);
  968. v9fs_string_free(&new_full_name);
  969. return ret;
  970. }
  971. static int proxy_unlinkat(FsContext *ctx, V9fsPath *dir,
  972. const char *name, int flags)
  973. {
  974. int ret;
  975. V9fsString fullname;
  976. v9fs_string_init(&fullname);
  977. v9fs_string_sprintf(&fullname, "%s/%s", dir->data, name);
  978. ret = proxy_remove(ctx, fullname.data);
  979. v9fs_string_free(&fullname);
  980. return ret;
  981. }
  982. static int proxy_ioc_getversion(FsContext *fs_ctx, V9fsPath *path,
  983. mode_t st_mode, uint64_t *st_gen)
  984. {
  985. int err;
  986. /* Do not try to open special files like device nodes, fifos etc
  987. * we can get fd for regular files and directories only
  988. */
  989. if (!S_ISREG(st_mode) && !S_ISDIR(st_mode)) {
  990. errno = ENOTTY;
  991. return -1;
  992. }
  993. err = v9fs_request(fs_ctx->private, T_GETVERSION, st_gen, path);
  994. if (err < 0) {
  995. errno = -err;
  996. err = -1;
  997. }
  998. return err;
  999. }
  1000. static int connect_namedsocket(const char *path, Error **errp)
  1001. {
  1002. int sockfd;
  1003. struct sockaddr_un helper;
  1004. if (strlen(path) >= sizeof(helper.sun_path)) {
  1005. error_setg(errp, "socket name too long");
  1006. return -1;
  1007. }
  1008. sockfd = socket(AF_UNIX, SOCK_STREAM, 0);
  1009. if (sockfd < 0) {
  1010. error_setg_errno(errp, errno, "failed to create client socket");
  1011. return -1;
  1012. }
  1013. strcpy(helper.sun_path, path);
  1014. helper.sun_family = AF_UNIX;
  1015. if (connect(sockfd, (struct sockaddr *)&helper, sizeof(helper)) < 0) {
  1016. error_setg_errno(errp, errno, "failed to connect to '%s'", path);
  1017. close(sockfd);
  1018. return -1;
  1019. }
  1020. /* remove the socket for security reasons */
  1021. unlink(path);
  1022. return sockfd;
  1023. }
  1024. static void error_append_socket_sockfd_hint(Error **errp)
  1025. {
  1026. error_append_hint(errp, "Either specify socket=/some/path where /some/path"
  1027. " points to a listening AF_UNIX socket or sock_fd=fd"
  1028. " where fd is a file descriptor to a connected AF_UNIX"
  1029. " socket\n");
  1030. }
  1031. static int proxy_parse_opts(QemuOpts *opts, FsDriverEntry *fs, Error **errp)
  1032. {
  1033. const char *socket = qemu_opt_get(opts, "socket");
  1034. const char *sock_fd = qemu_opt_get(opts, "sock_fd");
  1035. if (!socket && !sock_fd) {
  1036. error_setg(errp, "both socket and sock_fd properties are missing");
  1037. error_append_socket_sockfd_hint(errp);
  1038. return -1;
  1039. }
  1040. if (socket && sock_fd) {
  1041. error_setg(errp, "both socket and sock_fd properties are set");
  1042. error_append_socket_sockfd_hint(errp);
  1043. return -1;
  1044. }
  1045. if (socket) {
  1046. fs->path = g_strdup(socket);
  1047. fs->export_flags = V9FS_PROXY_SOCK_NAME;
  1048. } else {
  1049. fs->path = g_strdup(sock_fd);
  1050. fs->export_flags = V9FS_PROXY_SOCK_FD;
  1051. }
  1052. return 0;
  1053. }
  1054. static int proxy_init(FsContext *ctx, Error **errp)
  1055. {
  1056. V9fsProxy *proxy = g_malloc(sizeof(V9fsProxy));
  1057. int sock_id;
  1058. if (ctx->export_flags & V9FS_PROXY_SOCK_NAME) {
  1059. sock_id = connect_namedsocket(ctx->fs_root, errp);
  1060. } else {
  1061. sock_id = atoi(ctx->fs_root);
  1062. if (sock_id < 0) {
  1063. error_setg(errp, "socket descriptor not initialized");
  1064. }
  1065. }
  1066. if (sock_id < 0) {
  1067. g_free(proxy);
  1068. return -1;
  1069. }
  1070. g_free(ctx->fs_root);
  1071. ctx->fs_root = NULL;
  1072. proxy->in_iovec.iov_base = g_malloc(PROXY_MAX_IO_SZ + PROXY_HDR_SZ);
  1073. proxy->in_iovec.iov_len = PROXY_MAX_IO_SZ + PROXY_HDR_SZ;
  1074. proxy->out_iovec.iov_base = g_malloc(PROXY_MAX_IO_SZ + PROXY_HDR_SZ);
  1075. proxy->out_iovec.iov_len = PROXY_MAX_IO_SZ + PROXY_HDR_SZ;
  1076. ctx->private = proxy;
  1077. proxy->sockfd = sock_id;
  1078. qemu_mutex_init(&proxy->mutex);
  1079. ctx->export_flags |= V9FS_PATHNAME_FSCONTEXT;
  1080. ctx->exops.get_st_gen = proxy_ioc_getversion;
  1081. return 0;
  1082. }
  1083. static void proxy_cleanup(FsContext *ctx)
  1084. {
  1085. V9fsProxy *proxy = ctx->private;
  1086. if (!proxy) {
  1087. return;
  1088. }
  1089. g_free(proxy->out_iovec.iov_base);
  1090. g_free(proxy->in_iovec.iov_base);
  1091. if (ctx->export_flags & V9FS_PROXY_SOCK_NAME) {
  1092. close(proxy->sockfd);
  1093. }
  1094. g_free(proxy);
  1095. }
  1096. FileOperations proxy_ops = {
  1097. .parse_opts = proxy_parse_opts,
  1098. .init = proxy_init,
  1099. .cleanup = proxy_cleanup,
  1100. .lstat = proxy_lstat,
  1101. .readlink = proxy_readlink,
  1102. .close = proxy_close,
  1103. .closedir = proxy_closedir,
  1104. .open = proxy_open,
  1105. .opendir = proxy_opendir,
  1106. .rewinddir = proxy_rewinddir,
  1107. .telldir = proxy_telldir,
  1108. .readdir = proxy_readdir,
  1109. .seekdir = proxy_seekdir,
  1110. .preadv = proxy_preadv,
  1111. .pwritev = proxy_pwritev,
  1112. .chmod = proxy_chmod,
  1113. .mknod = proxy_mknod,
  1114. .mkdir = proxy_mkdir,
  1115. .fstat = proxy_fstat,
  1116. .open2 = proxy_open2,
  1117. .symlink = proxy_symlink,
  1118. .link = proxy_link,
  1119. .truncate = proxy_truncate,
  1120. .rename = proxy_rename,
  1121. .chown = proxy_chown,
  1122. .utimensat = proxy_utimensat,
  1123. .remove = proxy_remove,
  1124. .fsync = proxy_fsync,
  1125. .statfs = proxy_statfs,
  1126. .lgetxattr = proxy_lgetxattr,
  1127. .llistxattr = proxy_llistxattr,
  1128. .lsetxattr = proxy_lsetxattr,
  1129. .lremovexattr = proxy_lremovexattr,
  1130. .name_to_path = proxy_name_to_path,
  1131. .renameat = proxy_renameat,
  1132. .unlinkat = proxy_unlinkat,
  1133. };