shim_handle.c 24 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953
  1. /* -*- mode:c; c-file-style:"k&r"; c-basic-offset: 4; tab-width:4; indent-tabs-mode:nil; mode:auto-fill; fill-column:78; -*- */
  2. /* vim: set ts=4 sw=4 et tw=78 fo=cqt wm=0: */
  3. /* Copyright (C) 2014 OSCAR lab, Stony Brook University
  4. This file is part of Graphene Library OS.
  5. Graphene Library OS is free software: you can redistribute it and/or
  6. modify it under the terms of the GNU General Public License
  7. as published by the Free Software Foundation, either version 3 of the
  8. License, or (at your option) any later version.
  9. Graphene Library OS is distributed in the hope that it will be useful,
  10. but WITHOUT ANY WARRANTY; without even the implied warranty of
  11. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  12. GNU General Public License for more details.
  13. You should have received a copy of the GNU General Public License
  14. along with this program. If not, see <http://www.gnu.org/licenses/>. */
  15. /*
  16. * shim_handle.c
  17. *
  18. * This file contains codes to maintain bookkeeping for handles in library OS.
  19. */
  20. #include <shim_internal.h>
  21. #include <shim_thread.h>
  22. #include <shim_handle.h>
  23. #include <shim_checkpoint.h>
  24. #include <shim_fs.h>
  25. #include <pal.h>
  26. #include <pal_error.h>
  27. static LOCKTYPE handle_mgr_lock;
  28. #define HANDLE_MGR_ALLOC 32
  29. #define system_lock() lock(handle_mgr_lock)
  30. #define system_unlock() unlock(handle_mgr_lock)
  31. #define PAGE_SIZE allocsize
  32. #define OBJ_TYPE struct shim_handle
  33. #include <memmgr.h>
  34. static MEM_MGR handle_mgr = NULL;
  35. #define INIT_HANDLE_MAP_SIZE 32
  36. //#define DEBUG_REF
  37. static inline int init_tty_handle (struct shim_handle * hdl, bool write)
  38. {
  39. struct shim_dentry * dent = NULL;
  40. int ret;
  41. if ((ret = path_lookupat(NULL, "/dev/tty", LOOKUP_OPEN, &dent)) < 0)
  42. return ret;
  43. int flags = (write ? O_WRONLY : O_RDONLY)|O_APPEND;
  44. struct shim_mount * fs = dent->fs;
  45. ret = fs->d_ops->open(hdl, dent, flags);
  46. if (ret < 0)
  47. return ret;
  48. set_handle_fs(hdl, fs);
  49. hdl->dentry = dent;
  50. hdl->flags = O_RDWR|O_APPEND|0100000;
  51. int size;
  52. char * path = dentry_get_path(dent, true, &size);
  53. if (path)
  54. qstrsetstr(&hdl->path, path, size);
  55. else
  56. qstrsetstr(&hdl->path, "/dev/tty", 8);
  57. return 0;
  58. }
  59. static inline int init_exec_handle (struct shim_thread * thread)
  60. {
  61. if (!PAL_CB(executable))
  62. return 0;
  63. struct shim_handle * exec = get_new_handle();
  64. if (!exec)
  65. return -ENOMEM;
  66. qstrsetstr(&exec->uri, PAL_CB(executable), strlen(PAL_CB(executable)));
  67. exec->type = TYPE_FILE;
  68. exec->flags = O_RDONLY;
  69. exec->acc_mode = MAY_READ;
  70. struct shim_mount * fs = find_mount_from_uri(PAL_CB(executable));
  71. if (fs) {
  72. path_lookupat(fs->root, PAL_CB(executable) + fs->uri.len, 0,
  73. &exec->dentry);
  74. set_handle_fs(exec, fs);
  75. if (exec->dentry) {
  76. int len;
  77. const char * path = dentry_get_path(exec->dentry, true, &len);
  78. qstrsetstr(&exec->path, path, len);
  79. }
  80. put_mount(fs);
  81. } else {
  82. set_handle_fs(exec, &chroot_builtin_fs);
  83. }
  84. lock(thread->lock);
  85. thread->exec = exec;
  86. unlock(thread->lock);
  87. return 0;
  88. }
  89. static struct shim_handle_map * get_new_handle_map (FDTYPE size);
  90. PAL_HANDLE shim_stdio = NULL;
  91. static int __set_new_fd_handle(struct shim_fd_handle ** fdhdl, FDTYPE fd,
  92. struct shim_handle * hdl, int flags);
  93. static struct shim_handle_map * __enlarge_handle_map
  94. (struct shim_handle_map * map, FDTYPE size);
  95. int init_handle (void)
  96. {
  97. create_lock(handle_mgr_lock);
  98. handle_mgr = create_mem_mgr(init_align_up(HANDLE_MGR_ALLOC));
  99. if (!handle_mgr)
  100. return -ENOMEM;
  101. return 0;
  102. }
  103. int init_important_handles (void)
  104. {
  105. struct shim_thread * thread = get_cur_thread();
  106. if (thread->handle_map)
  107. goto done;
  108. struct shim_handle_map * handle_map = get_cur_handle_map(thread);
  109. if (!handle_map) {
  110. handle_map = get_new_handle_map(INIT_HANDLE_MAP_SIZE);
  111. if (!handle_map)
  112. return -ENOMEM;
  113. set_handle_map(thread, handle_map);
  114. }
  115. lock(handle_map->lock);
  116. if (handle_map->fd_size < 3) {
  117. if (!__enlarge_handle_map(handle_map, INIT_HANDLE_MAP_SIZE)) {
  118. unlock(handle_map->lock);
  119. return -ENOMEM;
  120. }
  121. }
  122. struct shim_handle * hdl = NULL;
  123. int ret;
  124. for (int fd = 0 ; fd < 3 ; fd++)
  125. if (!HANDLE_ALLOCATED(handle_map->map[fd])) {
  126. if (!hdl) {
  127. hdl = get_new_handle();
  128. if (!hdl)
  129. return -ENOMEM;
  130. if ((ret = init_tty_handle(hdl, fd)) < 0) {
  131. put_handle(hdl);
  132. return ret;
  133. }
  134. } else {
  135. get_handle(hdl);
  136. }
  137. __set_new_fd_handle(&handle_map->map[fd], fd, hdl, 0);
  138. put_handle(hdl);
  139. if (fd != 1)
  140. hdl = NULL;
  141. } else {
  142. if (fd == 1)
  143. hdl = handle_map->map[fd]->handle;
  144. }
  145. if (handle_map->fd_top == FD_NULL || handle_map->fd_top < 2)
  146. handle_map->fd_top = 2;
  147. unlock(handle_map->lock);
  148. done:
  149. init_exec_handle(thread);
  150. return 0;
  151. }
  152. struct shim_handle * __get_fd_handle (FDTYPE fd, int * flags,
  153. struct shim_handle_map * map)
  154. {
  155. struct shim_fd_handle * fd_handle = NULL;
  156. if (map->fd_top != FD_NULL &&
  157. fd <= map->fd_top) {
  158. fd_handle = map->map[fd];
  159. if (!HANDLE_ALLOCATED(fd_handle))
  160. return NULL;
  161. if (flags)
  162. *flags = fd_handle->flags;
  163. return fd_handle->handle;
  164. }
  165. return NULL;
  166. }
  167. struct shim_handle * get_fd_handle (FDTYPE fd, int * flags,
  168. struct shim_handle_map * map)
  169. {
  170. if (!map)
  171. map = get_cur_handle_map(NULL);
  172. struct shim_handle * hdl = NULL;
  173. lock(map->lock);
  174. if ((hdl = __get_fd_handle(fd, flags, map)))
  175. get_handle(hdl);
  176. unlock(map->lock);
  177. return hdl;
  178. }
  179. struct shim_handle *
  180. __detach_fd_handle (struct shim_fd_handle * fd, int * flags,
  181. struct shim_handle_map * map)
  182. {
  183. struct shim_handle * handle = NULL;
  184. if (HANDLE_ALLOCATED(fd)) {
  185. int vfd = fd->vfd;
  186. handle = fd->handle;
  187. if (flags)
  188. *flags = fd->flags;
  189. fd->vfd = FD_NULL;
  190. fd->handle = NULL;
  191. fd->flags = 0;
  192. if (vfd == map->fd_top)
  193. do {
  194. map->fd_top = vfd ? vfd - 1 : FD_NULL;
  195. vfd--;
  196. } while (vfd >= 0 &&
  197. !HANDLE_ALLOCATED(map->map[vfd]));
  198. }
  199. return handle;
  200. }
  201. struct shim_handle * detach_fd_handle (FDTYPE fd, int * flags,
  202. struct shim_handle_map * handle_map)
  203. {
  204. struct shim_handle * handle = NULL;
  205. if (!handle_map && !(handle_map = get_cur_handle_map(NULL)))
  206. return NULL;
  207. lock(handle_map->lock);
  208. if (fd < handle_map->fd_size)
  209. handle = __detach_fd_handle(handle_map->map[fd], flags,
  210. handle_map);
  211. unlock(handle_map->lock);
  212. return handle;
  213. }
  214. struct shim_handle * get_new_handle (void)
  215. {
  216. struct shim_handle * new_handle =
  217. get_mem_obj_from_mgr_enlarge(handle_mgr,
  218. size_align_up(HANDLE_MGR_ALLOC));
  219. if (!new_handle)
  220. return NULL;
  221. memset(new_handle, 0, sizeof(struct shim_handle));
  222. REF_SET(new_handle->ref_count, 1);
  223. create_lock(new_handle->lock);
  224. new_handle->owner = cur_process.vmid;
  225. INIT_LIST_HEAD(&new_handle->epolls);
  226. return new_handle;
  227. }
  228. static int __set_new_fd_handle(struct shim_fd_handle ** fdhdl, FDTYPE fd,
  229. struct shim_handle * hdl, int flags)
  230. {
  231. struct shim_fd_handle * new_handle = *fdhdl;
  232. if (!new_handle) {
  233. new_handle = malloc(sizeof(struct shim_fd_handle));
  234. if (!new_handle)
  235. return -ENOMEM;
  236. *fdhdl = new_handle;
  237. }
  238. new_handle->vfd = fd;
  239. new_handle->flags = flags;
  240. open_handle(hdl);
  241. new_handle->handle = hdl;
  242. return 0;
  243. }
  244. int set_new_fd_handle (struct shim_handle * hdl, int flags,
  245. struct shim_handle_map * handle_map)
  246. {
  247. FDTYPE fd = 0;
  248. int new_size = 0;
  249. int ret = 0;
  250. if (!handle_map && !(handle_map = get_cur_handle_map(NULL)))
  251. return -EBADF;
  252. lock(handle_map->lock);
  253. if (!handle_map->map ||
  254. handle_map->fd_size < INIT_HANDLE_MAP_SIZE)
  255. new_size = INIT_HANDLE_MAP_SIZE;
  256. if (!handle_map->map)
  257. goto extend;
  258. if (handle_map->fd_top != FD_NULL)
  259. do {
  260. ++fd;
  261. if (fd == handle_map->fd_size) {
  262. new_size = handle_map->fd_size < new_size ? new_size :
  263. handle_map->fd_size * 2;
  264. extend:
  265. if (!__enlarge_handle_map(handle_map, new_size)) {
  266. ret = -ENOMEM;
  267. goto out;
  268. }
  269. }
  270. } while (handle_map->fd_top != FD_NULL &&
  271. fd <= handle_map->fd_top &&
  272. HANDLE_ALLOCATED(handle_map->map[fd]));
  273. if (handle_map->fd_top == FD_NULL ||
  274. fd > handle_map->fd_top)
  275. handle_map->fd_top = fd;
  276. ret = __set_new_fd_handle(&handle_map->map[fd], fd, hdl, flags);
  277. if (ret < 0) {
  278. if (fd == handle_map->fd_top)
  279. handle_map->fd_top = fd ? fd - 1 : FD_NULL;
  280. } else
  281. ret = fd;
  282. out:
  283. unlock(handle_map->lock);
  284. return ret;
  285. }
  286. int set_new_fd_handle_by_fd (FDTYPE fd, struct shim_handle * hdl, int flags,
  287. struct shim_handle_map * handle_map)
  288. {
  289. int new_size = 0;
  290. int ret = 0;
  291. if (!handle_map && !(handle_map = get_cur_handle_map(NULL)))
  292. return -EBADF;
  293. lock(handle_map->lock);
  294. if (!handle_map->map ||
  295. handle_map->fd_size < INIT_HANDLE_MAP_SIZE)
  296. new_size = INIT_HANDLE_MAP_SIZE;
  297. if (!handle_map->map)
  298. goto extend;
  299. if (fd >= handle_map->fd_size) {
  300. new_size = handle_map->fd_size < new_size ? new_size :
  301. handle_map->fd_size;
  302. extend:
  303. while (new_size <= fd)
  304. new_size *= 2;
  305. if (!__enlarge_handle_map(handle_map, new_size)) {
  306. ret = -ENOMEM;
  307. goto out;
  308. }
  309. }
  310. if (handle_map->fd_top != FD_NULL &&
  311. fd <= handle_map->fd_top &&
  312. HANDLE_ALLOCATED(handle_map->map[fd])) {
  313. ret = -EBADF;
  314. goto out;
  315. }
  316. if (handle_map->fd_top == FD_NULL ||
  317. fd > handle_map->fd_top)
  318. handle_map->fd_top = fd;
  319. struct shim_fd_handle * new_handle = handle_map->map[fd];
  320. if (!new_handle) {
  321. new_handle = malloc(sizeof(struct shim_fd_handle));
  322. if (!new_handle) {
  323. ret = -ENOMEM;
  324. goto out;
  325. }
  326. handle_map->map[fd] = new_handle;
  327. }
  328. ret = __set_new_fd_handle(&handle_map->map[fd], fd, hdl, flags);
  329. if (ret < 0) {
  330. if (fd == handle_map->fd_top)
  331. handle_map->fd_top = fd ? fd - 1 : FD_NULL;
  332. } else
  333. ret = fd;
  334. out:
  335. unlock(handle_map->lock);
  336. return fd;
  337. }
  338. void flush_handle (struct shim_handle * hdl)
  339. {
  340. if (hdl->fs && hdl->fs->fs_ops &&
  341. hdl->fs->fs_ops->flush)
  342. hdl->fs->fs_ops->flush(hdl);
  343. }
  344. static inline __attribute__((unused))
  345. const char * __handle_name (struct shim_handle * hdl)
  346. {
  347. if (!qstrempty(&hdl->path))
  348. return qstrgetstr(&hdl->path);
  349. if (!qstrempty(&hdl->uri))
  350. return qstrgetstr(&hdl->uri);
  351. if (hdl->fs_type[0])
  352. return hdl->fs_type;
  353. return "(unknown)";
  354. }
  355. void open_handle (struct shim_handle * hdl)
  356. {
  357. get_handle(hdl);
  358. #ifdef DEBUG_REF
  359. int opened = REF_INC(hdl->opened);
  360. debug("open handle %p(%s) (opened = %d)\n", hdl, __handle_name(hdl),
  361. opened);
  362. #else
  363. REF_INC(hdl->opened);
  364. #endif
  365. }
  366. extern int delete_from_epoll_handles (struct shim_handle * handle);
  367. void close_handle (struct shim_handle * hdl)
  368. {
  369. int opened = REF_DEC(hdl->opened);
  370. #ifdef DEBUG_REF
  371. debug("close handle %p(%s) (opened = %d)\n", hdl, __handle_name(hdl),
  372. opened);
  373. #endif
  374. if (!opened) {
  375. if (hdl->type == TYPE_DIR) {
  376. struct shim_dir_handle * dir = &hdl->info.dir;
  377. if (dir->dot) {
  378. put_dentry(dir->dot);
  379. dir->dot = NULL;
  380. }
  381. if (dir->dotdot) {
  382. put_dentry(dir->dotdot);
  383. dir->dotdot = NULL;
  384. }
  385. while (dir->ptr && *dir->ptr) {
  386. struct shim_dentry * dent = *dir->ptr;
  387. put_dentry(dent);
  388. *(dir->ptr++) = NULL;
  389. }
  390. } else {
  391. if (hdl->fs && hdl->fs->fs_ops &&
  392. hdl->fs->fs_ops->close)
  393. hdl->fs->fs_ops->close(hdl);
  394. }
  395. delete_from_epoll_handles(hdl);
  396. }
  397. put_handle(hdl);
  398. }
  399. void get_handle (struct shim_handle * hdl)
  400. {
  401. #ifdef DEBUG_REF
  402. int ref_count = REF_INC(hdl->ref_count);
  403. debug("get handle %p(%s) (ref_count = %d)\n", hdl, __handle_name(hdl),
  404. ref_count);
  405. #else
  406. REF_INC(hdl->ref_count);
  407. #endif
  408. }
  409. static void destroy_handle (struct shim_handle * hdl)
  410. {
  411. destroy_lock(hdl->lock);
  412. if (MEMORY_MIGRATED(hdl))
  413. memset(hdl, 0, sizeof(struct shim_handle));
  414. else
  415. free_mem_obj_to_mgr(handle_mgr, hdl);
  416. }
  417. void put_handle (struct shim_handle * hdl)
  418. {
  419. int ref_count = REF_DEC(hdl->ref_count);
  420. #ifdef DEBUG_REF
  421. debug("put handle %p(%s) (ref_count = %d)\n", hdl, __handle_name(hdl),
  422. ref_count);
  423. #endif
  424. if (!ref_count) {
  425. if (hdl->fs && hdl->fs->fs_ops &&
  426. hdl->fs->fs_ops->hput)
  427. hdl->fs->fs_ops->hput(hdl);
  428. qstrfree(&hdl->path);
  429. qstrfree(&hdl->uri);
  430. if (hdl->pal_handle)
  431. DkObjectClose(hdl->pal_handle);
  432. if (hdl->dentry)
  433. put_dentry(hdl->dentry);
  434. if (hdl->fs)
  435. put_mount(hdl->fs);
  436. destroy_handle(hdl);
  437. }
  438. }
  439. size_t get_file_size (struct shim_handle * hdl)
  440. {
  441. if (!hdl->fs || !hdl->fs->fs_ops)
  442. return -EINVAL;
  443. if (hdl->fs->fs_ops->poll)
  444. return hdl->fs->fs_ops->poll(hdl, FS_POLL_SZ);
  445. if (hdl->fs->fs_ops->hstat) {
  446. struct stat stat;
  447. int ret = hdl->fs->fs_ops->hstat(hdl, &stat);
  448. if (ret < 0)
  449. return ret;
  450. return stat.st_size;
  451. }
  452. return 0;
  453. }
  454. void dup_fd_handle (struct shim_handle_map * map,
  455. const struct shim_fd_handle * old,
  456. struct shim_fd_handle * new)
  457. {
  458. struct shim_handle * replaced = NULL;
  459. lock(map->lock);
  460. if (old->vfd != FD_NULL) {
  461. open_handle(old->handle);
  462. replaced = new->handle;
  463. new->handle = old->handle;
  464. }
  465. unlock(map->lock);
  466. if (replaced)
  467. close_handle(replaced);
  468. }
  469. static struct shim_handle_map * get_new_handle_map (FDTYPE size)
  470. {
  471. struct shim_handle_map * handle_map =
  472. malloc(sizeof(struct shim_handle_map));
  473. if (handle_map == NULL)
  474. return NULL;
  475. memset(handle_map, 0, sizeof(struct shim_handle_map));
  476. handle_map->map = malloc(sizeof(struct shim_fd_handle) * size);
  477. if (handle_map->map == NULL) {
  478. free(handle_map);
  479. return NULL;
  480. }
  481. memset(handle_map->map, 0,
  482. sizeof(struct shim_fd_handle) * size);
  483. handle_map->fd_top = FD_NULL;
  484. handle_map->fd_size = size;
  485. create_lock(handle_map->lock);
  486. return handle_map;
  487. }
  488. static struct shim_handle_map * __enlarge_handle_map
  489. (struct shim_handle_map * map, FDTYPE size)
  490. {
  491. if (size <= map->fd_size)
  492. return NULL;
  493. struct shim_fd_handle ** old_map = map->map;
  494. map->map = malloc(sizeof(struct shim_fd_handle *) * size);
  495. if (map->map == NULL) {
  496. map->map = old_map;
  497. return NULL;
  498. }
  499. size_t copy_size = sizeof(struct shim_fd_handle *) * map->fd_size;
  500. map->fd_size = size;
  501. memset(map->map, 0, sizeof(struct shim_fd_handle *) * size);
  502. if (old_map) {
  503. if (copy_size)
  504. memcpy(map->map, old_map, copy_size);
  505. free(old_map);
  506. }
  507. return map;
  508. }
  509. int dup_handle_map (struct shim_handle_map ** new,
  510. struct shim_handle_map * old_map)
  511. {
  512. lock(old_map->lock);
  513. /* allocate a new handle mapping with the same size as
  514. the old one */
  515. struct shim_handle_map * new_map =
  516. get_new_handle_map(old_map->fd_size);
  517. new_map->fd_top = old_map->fd_top;
  518. if (old_map->fd_top == FD_NULL)
  519. goto done;
  520. for (int i = 0 ; i <= old_map->fd_top ; i++) {
  521. struct shim_fd_handle * fd_old = old_map->map[i];
  522. struct shim_fd_handle * fd_new;
  523. /* now we go through the handle map and reassign each
  524. of them being allocated */
  525. if (HANDLE_ALLOCATED(fd_old)) {
  526. /* first, get the handle to prevent it from being deleted */
  527. struct shim_handle * hdl = fd_old->handle;
  528. open_handle(hdl);
  529. /* DP: I assume we really need a deep copy of the handle map? */
  530. fd_new = malloc(sizeof(struct shim_fd_handle));
  531. new_map->map[i] = fd_new;
  532. fd_new->vfd = fd_old->vfd;
  533. fd_new->handle = hdl;
  534. fd_new->flags = fd_old->flags;
  535. }
  536. }
  537. done:
  538. unlock(old_map->lock);
  539. *new = new_map;
  540. return 0;
  541. }
  542. void get_handle_map (struct shim_handle_map * map)
  543. {
  544. REF_INC(map->ref_count);
  545. }
  546. void put_handle_map (struct shim_handle_map * map)
  547. {
  548. int ref_count = REF_DEC(map->ref_count);
  549. if (!ref_count) {
  550. if (map->fd_top == FD_NULL)
  551. goto done;
  552. for (int i = 0 ; i <= map->fd_top ; i++) {
  553. if (!map->map[i])
  554. continue;
  555. if (map->map[i]->vfd != FD_NULL) {
  556. struct shim_handle * handle = map->map[i]->handle;
  557. if (handle)
  558. close_handle(handle);
  559. }
  560. free(map->map[i]);
  561. }
  562. done:
  563. destroy_lock(map->lock);
  564. free(map->map);
  565. free(map);
  566. }
  567. }
  568. int flush_handle_map (struct shim_handle_map * map)
  569. {
  570. get_handle_map(map);
  571. lock(map->lock);
  572. if (map->fd_top == FD_NULL)
  573. goto done;
  574. /* now we go through the handle map and flush each handle */
  575. for (int i = 0 ; i <= map->fd_top ; i++) {
  576. if (!HANDLE_ALLOCATED(map->map[i]))
  577. continue;
  578. struct shim_handle * handle = map->map[i]->handle;
  579. if (handle)
  580. flush_handle(handle);
  581. }
  582. done:
  583. unlock(map->lock);
  584. put_handle_map(map);
  585. return 0;
  586. }
  587. int walk_handle_map (int (*callback) (struct shim_fd_handle *,
  588. struct shim_handle_map *, void *),
  589. struct shim_handle_map * map, void * arg)
  590. {
  591. int ret = 0;
  592. lock(map->lock);
  593. if (map->fd_top == FD_NULL)
  594. goto done;
  595. for (int i = 0 ; i <= map->fd_top ; i++) {
  596. if (!HANDLE_ALLOCATED(map->map[i]))
  597. continue;
  598. if ((ret = (*callback) (map->map[i], map, arg)) < 0)
  599. break;
  600. }
  601. done:
  602. unlock(map->lock);
  603. return ret;
  604. }
  605. BEGIN_CP_FUNC(handle)
  606. {
  607. assert(size == sizeof(struct shim_handle));
  608. struct shim_handle * hdl = (struct shim_handle *) obj;
  609. struct shim_handle * new_hdl = NULL;
  610. ptr_t off = GET_FROM_CP_MAP(obj);
  611. if (!off) {
  612. off = ADD_CP_OFFSET(sizeof(struct shim_handle));
  613. ADD_TO_CP_MAP(obj, off);
  614. new_hdl = (struct shim_handle *) (base + off);
  615. lock(hdl->lock);
  616. struct shim_mount * fs = hdl->fs;
  617. *new_hdl = *hdl;
  618. if (fs && fs->fs_ops && fs->fs_ops->checkout)
  619. fs->fs_ops->checkout(new_hdl);
  620. new_hdl->dentry = NULL;
  621. REF_SET(new_hdl->opened, 0);
  622. REF_SET(new_hdl->ref_count, 0);
  623. clear_lock(new_hdl->lock);
  624. DO_CP_IN_MEMBER(qstr, new_hdl, path);
  625. DO_CP_IN_MEMBER(qstr, new_hdl, uri);
  626. if (fs && hdl->dentry) {
  627. DO_CP_MEMBER(mount, hdl, new_hdl, fs);
  628. } else {
  629. new_hdl->fs = NULL;
  630. }
  631. if (hdl->dentry)
  632. DO_CP_MEMBER(dentry, hdl, new_hdl, dentry);
  633. if (new_hdl->pal_handle) {
  634. struct shim_palhdl_entry * entry;
  635. DO_CP(palhdl, hdl->pal_handle, &entry);
  636. entry->uri = &new_hdl->uri;
  637. entry->phandle = &new_hdl->pal_handle;
  638. }
  639. if (hdl->type == TYPE_EPOLL)
  640. DO_CP(epoll_fd, &hdl->info.epoll.fds, &new_hdl->info.epoll.fds);
  641. INIT_LIST_HEAD(&new_hdl->epolls);
  642. unlock(hdl->lock);
  643. ADD_CP_FUNC_ENTRY(off);
  644. } else {
  645. new_hdl = (struct shim_handle *) (base + off);
  646. }
  647. if (objp)
  648. *objp = (void *) new_hdl;
  649. }
  650. END_CP_FUNC(handle)
  651. BEGIN_RS_FUNC(handle)
  652. {
  653. struct shim_handle * hdl = (void *) (base + GET_CP_FUNC_ENTRY());
  654. CP_REBASE(hdl->fs);
  655. CP_REBASE(hdl->dentry);
  656. CP_REBASE(hdl->epolls);
  657. create_lock(hdl->lock);
  658. if (!hdl->fs) {
  659. assert(hdl->fs_type);
  660. search_builtin_fs(hdl->fs_type, &hdl->fs);
  661. if (!hdl->fs)
  662. return -EINVAL;
  663. }
  664. if (hdl->fs && hdl->fs->fs_ops &&
  665. hdl->fs->fs_ops->checkin)
  666. hdl->fs->fs_ops->checkin(hdl);
  667. DEBUG_RS("path=%s,type=%s,uri=%s,flags=%03o",
  668. qstrgetstr(&hdl->path), hdl->fs_type, qstrgetstr(&hdl->uri),
  669. hdl->flags);
  670. }
  671. END_RS_FUNC(handle)
  672. BEGIN_CP_FUNC(fd_handle)
  673. {
  674. assert(size == sizeof(struct shim_fd_handle));
  675. struct shim_fd_handle * fdhdl = (struct shim_fd_handle *) obj;
  676. struct shim_fd_handle * new_fdhdl = NULL;
  677. ptr_t off = ADD_CP_OFFSET(sizeof(struct shim_fd_handle));
  678. new_fdhdl = (struct shim_fd_handle *) (base + off);
  679. memcpy(new_fdhdl, fdhdl, sizeof(struct shim_fd_handle));
  680. DO_CP(handle, fdhdl->handle, &new_fdhdl->handle);
  681. ADD_CP_FUNC_ENTRY(off);
  682. if (objp)
  683. *objp = (void *) new_fdhdl;
  684. }
  685. END_CP_FUNC_NO_RS(fd_handle)
  686. BEGIN_CP_FUNC(handle_map)
  687. {
  688. assert(size >= sizeof(struct shim_handle_map));
  689. struct shim_handle_map * handle_map = (struct shim_handle_map *) obj;
  690. struct shim_handle_map * new_handle_map = NULL;
  691. struct shim_fd_handle ** ptr_array;
  692. lock(handle_map->lock);
  693. int fd_size = handle_map->fd_top != FD_NULL ?
  694. handle_map->fd_top + 1 : 0;
  695. size = sizeof(struct shim_handle_map) +
  696. (sizeof(struct shim_fd_handle *) * fd_size);
  697. ptr_t off = GET_FROM_CP_MAP(obj);
  698. if (!off) {
  699. off = ADD_CP_OFFSET(size);
  700. new_handle_map = (struct shim_handle_map *) (base + off);
  701. memcpy(new_handle_map, handle_map,
  702. sizeof(struct shim_handle_map));
  703. ptr_array = (void *) new_handle_map + sizeof(struct shim_handle_map);
  704. new_handle_map->fd_size = fd_size;
  705. new_handle_map->map = fd_size ? ptr_array : NULL;
  706. REF_SET(new_handle_map->ref_count, 0);
  707. clear_lock(new_handle_map->lock);
  708. for (int i = 0 ; i < fd_size ; i++) {
  709. if (HANDLE_ALLOCATED(handle_map->map[i]))
  710. DO_CP(fd_handle, handle_map->map[i], &ptr_array[i]);
  711. else
  712. ptr_array[i] = NULL;
  713. }
  714. ADD_CP_FUNC_ENTRY(off);
  715. } else {
  716. new_handle_map = (struct shim_handle_map *) (base + off);
  717. }
  718. unlock(handle_map->lock);
  719. if (objp)
  720. *objp = (void *) new_handle_map;
  721. }
  722. END_CP_FUNC(handle_map)
  723. BEGIN_RS_FUNC(handle_map)
  724. {
  725. struct shim_handle_map * handle_map = (void *) (base + GET_CP_FUNC_ENTRY());
  726. CP_REBASE(handle_map->map);
  727. assert(handle_map->map);
  728. DEBUG_RS("size=%d,top=%d", handle_map->fd_size, handle_map->fd_top);
  729. create_lock(handle_map->lock);
  730. lock(handle_map->lock);
  731. if (handle_map->fd_top != FD_NULL)
  732. for (int i = 0 ; i <= handle_map->fd_top ; i++) {
  733. CP_REBASE(handle_map->map[i]);
  734. if (HANDLE_ALLOCATED(handle_map->map[i])) {
  735. CP_REBASE(handle_map->map[i]->handle);
  736. struct shim_handle * hdl = handle_map->map[i]->handle;
  737. assert(hdl);
  738. open_handle(hdl);
  739. DEBUG_RS("[%d]%s", i, qstrempty(&hdl->uri) ? hdl->fs_type :
  740. qstrgetstr(&hdl->uri));
  741. }
  742. }
  743. unlock(handle_map->lock);
  744. }
  745. END_RS_FUNC(handle_map)