cofile.c 7.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280
  1. /*
  2. * 9p backend
  3. *
  4. * Copyright IBM, Corp. 2011
  5. *
  6. * Authors:
  7. * Aneesh Kumar K.V <aneesh.kumar@linux.vnet.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. */
  13. #include "qemu/osdep.h"
  14. #include "fsdev/qemu-fsdev.h"
  15. #include "qemu/thread.h"
  16. #include "qemu/coroutine.h"
  17. #include "qemu/main-loop.h"
  18. #include "coth.h"
  19. int coroutine_fn v9fs_co_st_gen(V9fsPDU *pdu, V9fsPath *path, mode_t st_mode,
  20. V9fsStatDotl *v9stat)
  21. {
  22. int err = 0;
  23. V9fsState *s = pdu->s;
  24. if (v9fs_request_cancelled(pdu)) {
  25. return -EINTR;
  26. }
  27. if (s->ctx.exops.get_st_gen) {
  28. v9fs_path_read_lock(s);
  29. v9fs_co_run_in_worker(
  30. {
  31. err = s->ctx.exops.get_st_gen(&s->ctx, path, st_mode,
  32. &v9stat->st_gen);
  33. if (err < 0) {
  34. err = -errno;
  35. }
  36. });
  37. v9fs_path_unlock(s);
  38. }
  39. return err;
  40. }
  41. int coroutine_fn v9fs_co_lstat(V9fsPDU *pdu, V9fsPath *path, struct stat *stbuf)
  42. {
  43. int err;
  44. V9fsState *s = pdu->s;
  45. if (v9fs_request_cancelled(pdu)) {
  46. return -EINTR;
  47. }
  48. v9fs_path_read_lock(s);
  49. v9fs_co_run_in_worker(
  50. {
  51. err = s->ops->lstat(&s->ctx, path, stbuf);
  52. if (err < 0) {
  53. err = -errno;
  54. }
  55. });
  56. v9fs_path_unlock(s);
  57. return err;
  58. }
  59. int coroutine_fn v9fs_co_fstat(V9fsPDU *pdu, V9fsFidState *fidp,
  60. struct stat *stbuf)
  61. {
  62. int err;
  63. V9fsState *s = pdu->s;
  64. if (v9fs_request_cancelled(pdu)) {
  65. return -EINTR;
  66. }
  67. v9fs_co_run_in_worker(
  68. {
  69. err = s->ops->fstat(&s->ctx, fidp->fid_type, &fidp->fs, stbuf);
  70. if (err < 0) {
  71. err = -errno;
  72. }
  73. });
  74. /*
  75. * Some FS driver (local:mapped-file) can't support fetching attributes
  76. * using file descriptor. Use Path name in that case.
  77. */
  78. if (err == -EOPNOTSUPP) {
  79. err = v9fs_co_lstat(pdu, &fidp->path, stbuf);
  80. if (err == -ENOENT) {
  81. /*
  82. * fstat on an unlinked file. Work with partial results
  83. * returned from s->ops->fstat
  84. */
  85. err = 0;
  86. }
  87. }
  88. return err;
  89. }
  90. int coroutine_fn v9fs_co_open(V9fsPDU *pdu, V9fsFidState *fidp, int flags)
  91. {
  92. int err;
  93. V9fsState *s = pdu->s;
  94. if (v9fs_request_cancelled(pdu)) {
  95. return -EINTR;
  96. }
  97. v9fs_path_read_lock(s);
  98. v9fs_co_run_in_worker(
  99. {
  100. err = s->ops->open(&s->ctx, &fidp->path, flags, &fidp->fs);
  101. if (err == -1) {
  102. err = -errno;
  103. } else {
  104. err = 0;
  105. }
  106. });
  107. v9fs_path_unlock(s);
  108. if (!err) {
  109. total_open_fd++;
  110. if (total_open_fd > open_fd_hw) {
  111. v9fs_reclaim_fd(pdu);
  112. }
  113. }
  114. return err;
  115. }
  116. int coroutine_fn v9fs_co_open2(V9fsPDU *pdu, V9fsFidState *fidp,
  117. V9fsString *name, gid_t gid, int flags, int mode,
  118. struct stat *stbuf)
  119. {
  120. int err;
  121. FsCred cred;
  122. V9fsPath path;
  123. V9fsState *s = pdu->s;
  124. if (v9fs_request_cancelled(pdu)) {
  125. return -EINTR;
  126. }
  127. cred_init(&cred);
  128. cred.fc_mode = mode & 07777;
  129. cred.fc_uid = fidp->uid;
  130. cred.fc_gid = gid;
  131. /*
  132. * Hold the directory fid lock so that directory path name
  133. * don't change. Take the write lock to be sure this fid
  134. * cannot be used by another operation.
  135. */
  136. v9fs_path_write_lock(s);
  137. v9fs_co_run_in_worker(
  138. {
  139. err = s->ops->open2(&s->ctx, &fidp->path,
  140. name->data, flags, &cred, &fidp->fs);
  141. if (err < 0) {
  142. err = -errno;
  143. } else {
  144. v9fs_path_init(&path);
  145. err = v9fs_name_to_path(s, &fidp->path, name->data, &path);
  146. if (!err) {
  147. err = s->ops->lstat(&s->ctx, &path, stbuf);
  148. if (err < 0) {
  149. err = -errno;
  150. s->ops->close(&s->ctx, &fidp->fs);
  151. } else {
  152. v9fs_path_copy(&fidp->path, &path);
  153. }
  154. } else {
  155. s->ops->close(&s->ctx, &fidp->fs);
  156. }
  157. v9fs_path_free(&path);
  158. }
  159. });
  160. v9fs_path_unlock(s);
  161. if (!err) {
  162. total_open_fd++;
  163. if (total_open_fd > open_fd_hw) {
  164. v9fs_reclaim_fd(pdu);
  165. }
  166. }
  167. return err;
  168. }
  169. int coroutine_fn v9fs_co_close(V9fsPDU *pdu, V9fsFidOpenState *fs)
  170. {
  171. int err;
  172. V9fsState *s = pdu->s;
  173. if (v9fs_request_cancelled(pdu)) {
  174. return -EINTR;
  175. }
  176. v9fs_co_run_in_worker(
  177. {
  178. err = s->ops->close(&s->ctx, fs);
  179. if (err < 0) {
  180. err = -errno;
  181. }
  182. });
  183. if (!err) {
  184. total_open_fd--;
  185. }
  186. return err;
  187. }
  188. int coroutine_fn v9fs_co_fsync(V9fsPDU *pdu, V9fsFidState *fidp, int datasync)
  189. {
  190. int err;
  191. V9fsState *s = pdu->s;
  192. if (v9fs_request_cancelled(pdu)) {
  193. return -EINTR;
  194. }
  195. v9fs_co_run_in_worker(
  196. {
  197. err = s->ops->fsync(&s->ctx, fidp->fid_type, &fidp->fs, datasync);
  198. if (err < 0) {
  199. err = -errno;
  200. }
  201. });
  202. return err;
  203. }
  204. int coroutine_fn v9fs_co_link(V9fsPDU *pdu, V9fsFidState *oldfid,
  205. V9fsFidState *newdirfid, V9fsString *name)
  206. {
  207. int err;
  208. V9fsState *s = pdu->s;
  209. if (v9fs_request_cancelled(pdu)) {
  210. return -EINTR;
  211. }
  212. v9fs_path_read_lock(s);
  213. v9fs_co_run_in_worker(
  214. {
  215. err = s->ops->link(&s->ctx, &oldfid->path,
  216. &newdirfid->path, name->data);
  217. if (err < 0) {
  218. err = -errno;
  219. }
  220. });
  221. v9fs_path_unlock(s);
  222. return err;
  223. }
  224. int coroutine_fn v9fs_co_pwritev(V9fsPDU *pdu, V9fsFidState *fidp,
  225. struct iovec *iov, int iovcnt, int64_t offset)
  226. {
  227. int err;
  228. V9fsState *s = pdu->s;
  229. if (v9fs_request_cancelled(pdu)) {
  230. return -EINTR;
  231. }
  232. fsdev_co_throttle_request(s->ctx.fst, true, iov, iovcnt);
  233. v9fs_co_run_in_worker(
  234. {
  235. err = s->ops->pwritev(&s->ctx, &fidp->fs, iov, iovcnt, offset);
  236. if (err < 0) {
  237. err = -errno;
  238. }
  239. });
  240. return err;
  241. }
  242. int coroutine_fn v9fs_co_preadv(V9fsPDU *pdu, V9fsFidState *fidp,
  243. struct iovec *iov, int iovcnt, int64_t offset)
  244. {
  245. int err;
  246. V9fsState *s = pdu->s;
  247. if (v9fs_request_cancelled(pdu)) {
  248. return -EINTR;
  249. }
  250. fsdev_co_throttle_request(s->ctx.fst, false, iov, iovcnt);
  251. v9fs_co_run_in_worker(
  252. {
  253. err = s->ops->preadv(&s->ctx, &fidp->fs, iov, iovcnt, offset);
  254. if (err < 0) {
  255. err = -errno;
  256. }
  257. });
  258. return err;
  259. }