shim_handle.c 24 KB

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