shim_handle.c 23 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928
  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. set_handle_fs(exec, &chroot_builtin_fs);
  67. qstrsetstr(&exec->uri, PAL_CB(executable), strlen(PAL_CB(executable)));
  68. exec->type = TYPE_FILE;
  69. exec->flags = O_RDONLY;
  70. exec->acc_mode = MAY_READ;
  71. lock(thread->lock);
  72. thread->exec = exec;
  73. unlock(thread->lock);
  74. return 0;
  75. }
  76. static struct shim_handle_map * get_new_handle_map (FDTYPE size);
  77. PAL_HANDLE shim_stdio = NULL;
  78. static int __set_new_fd_handle(struct shim_fd_handle ** fdhdl, FDTYPE fd,
  79. struct shim_handle * hdl, int flags);
  80. static struct shim_handle_map * __enlarge_handle_map
  81. (struct shim_handle_map * map, FDTYPE size);
  82. int init_handle (void)
  83. {
  84. create_lock(handle_mgr_lock);
  85. handle_mgr = create_mem_mgr(init_align_up(HANDLE_MGR_ALLOC));
  86. if (!handle_mgr)
  87. return -ENOMEM;
  88. return 0;
  89. }
  90. int init_important_handles (void)
  91. {
  92. struct shim_thread * thread = get_cur_thread();
  93. if (thread->handle_map)
  94. goto done;
  95. struct shim_handle_map * handle_map = get_cur_handle_map(thread);
  96. if (!handle_map) {
  97. handle_map = get_new_handle_map(INIT_HANDLE_MAP_SIZE);
  98. if (!handle_map)
  99. return -ENOMEM;
  100. set_handle_map(thread, handle_map);
  101. }
  102. lock(handle_map->lock);
  103. if (handle_map->fd_size < 3) {
  104. if (!__enlarge_handle_map(handle_map, INIT_HANDLE_MAP_SIZE)) {
  105. unlock(handle_map->lock);
  106. return -ENOMEM;
  107. }
  108. }
  109. struct shim_handle * hdl = NULL;
  110. int ret;
  111. for (int fd = 0 ; fd < 3 ; fd++)
  112. if (!HANDLE_ALLOCATED(handle_map->map[fd])) {
  113. if (!hdl) {
  114. hdl = get_new_handle();
  115. if (!hdl)
  116. return -ENOMEM;
  117. if ((ret = init_tty_handle(hdl, fd)) < 0) {
  118. put_handle(hdl);
  119. return ret;
  120. }
  121. } else {
  122. get_handle(hdl);
  123. }
  124. __set_new_fd_handle(&handle_map->map[fd], fd, hdl, 0);
  125. put_handle(hdl);
  126. if (fd != 1)
  127. hdl = NULL;
  128. } else {
  129. if (fd == 1)
  130. hdl = handle_map->map[fd]->handle;
  131. }
  132. if (handle_map->fd_top == FD_NULL || handle_map->fd_top < 2)
  133. handle_map->fd_top = 2;
  134. unlock(handle_map->lock);
  135. done:
  136. init_exec_handle(thread);
  137. return 0;
  138. }
  139. struct shim_handle * __get_fd_handle (FDTYPE fd, int * flags,
  140. struct shim_handle_map * map)
  141. {
  142. struct shim_fd_handle * fd_handle = NULL;
  143. if (map->fd_top != FD_NULL &&
  144. fd <= map->fd_top) {
  145. fd_handle = map->map[fd];
  146. if (!HANDLE_ALLOCATED(fd_handle))
  147. return NULL;
  148. if (flags)
  149. *flags = fd_handle->flags;
  150. return fd_handle->handle;
  151. }
  152. return NULL;
  153. }
  154. struct shim_handle * get_fd_handle (FDTYPE fd, int * flags,
  155. struct shim_handle_map * map)
  156. {
  157. if (!map)
  158. map = get_cur_handle_map(NULL);
  159. struct shim_handle * hdl = NULL;
  160. lock(map->lock);
  161. if ((hdl = __get_fd_handle(fd, flags, map)))
  162. get_handle(hdl);
  163. unlock(map->lock);
  164. return hdl;
  165. }
  166. struct shim_handle *
  167. __detach_fd_handle (struct shim_fd_handle * fd, int * flags,
  168. struct shim_handle_map * map)
  169. {
  170. struct shim_handle * handle = NULL;
  171. if (HANDLE_ALLOCATED(fd)) {
  172. int vfd = fd->vfd;
  173. handle = fd->handle;
  174. if (flags)
  175. *flags = fd->flags;
  176. fd->vfd = FD_NULL;
  177. fd->handle = NULL;
  178. fd->flags = 0;
  179. if (vfd == map->fd_top)
  180. do {
  181. map->fd_top = vfd ? vfd - 1 : FD_NULL;
  182. vfd--;
  183. } while (vfd >= 0 &&
  184. !HANDLE_ALLOCATED(map->map[vfd]));
  185. }
  186. return handle;
  187. }
  188. struct shim_handle * detach_fd_handle (FDTYPE fd, int * flags,
  189. struct shim_handle_map * handle_map)
  190. {
  191. struct shim_handle * handle = NULL;
  192. if (!handle_map && !(handle_map = get_cur_handle_map(NULL)))
  193. return NULL;
  194. lock(handle_map->lock);
  195. if (fd < handle_map->fd_size)
  196. handle = __detach_fd_handle(handle_map->map[fd], flags,
  197. handle_map);
  198. unlock(handle_map->lock);
  199. return handle;
  200. }
  201. struct shim_handle * get_new_handle (void)
  202. {
  203. struct shim_handle * new_handle =
  204. get_mem_obj_from_mgr_enlarge(handle_mgr,
  205. size_align_up(HANDLE_MGR_ALLOC));
  206. if (!new_handle)
  207. return NULL;
  208. memset(new_handle, 0, sizeof(struct shim_handle));
  209. REF_SET(new_handle->ref_count, 1);
  210. create_lock(new_handle->lock);
  211. new_handle->owner = cur_process.vmid;
  212. return new_handle;
  213. }
  214. static int __set_new_fd_handle(struct shim_fd_handle ** fdhdl, FDTYPE fd,
  215. struct shim_handle * hdl, int flags)
  216. {
  217. struct shim_fd_handle * new_handle = *fdhdl;
  218. if (!new_handle) {
  219. new_handle = malloc(sizeof(struct shim_fd_handle));
  220. if (!new_handle)
  221. return -ENOMEM;
  222. *fdhdl = new_handle;
  223. }
  224. new_handle->vfd = fd;
  225. new_handle->flags = flags;
  226. open_handle(hdl);
  227. new_handle->handle = hdl;
  228. return 0;
  229. }
  230. int set_new_fd_handle (struct shim_handle * hdl, int flags,
  231. struct shim_handle_map * handle_map)
  232. {
  233. FDTYPE fd = 0;
  234. int new_size = 0;
  235. int ret = 0;
  236. if (!handle_map && !(handle_map = get_cur_handle_map(NULL)))
  237. return -EBADF;
  238. lock(handle_map->lock);
  239. if (!handle_map->map ||
  240. handle_map->fd_size < INIT_HANDLE_MAP_SIZE)
  241. new_size = INIT_HANDLE_MAP_SIZE;
  242. if (!handle_map->map)
  243. goto extend;
  244. if (handle_map->fd_top != FD_NULL)
  245. do {
  246. ++fd;
  247. if (fd == handle_map->fd_size) {
  248. new_size = handle_map->fd_size < new_size ? new_size :
  249. handle_map->fd_size * 2;
  250. extend:
  251. if (!__enlarge_handle_map(handle_map, new_size)) {
  252. ret = -ENOMEM;
  253. goto out;
  254. }
  255. }
  256. } while (handle_map->fd_top != FD_NULL &&
  257. fd <= handle_map->fd_top &&
  258. HANDLE_ALLOCATED(handle_map->map[fd]));
  259. if (handle_map->fd_top == FD_NULL ||
  260. fd > handle_map->fd_top)
  261. handle_map->fd_top = fd;
  262. ret = __set_new_fd_handle(&handle_map->map[fd], fd, hdl, flags);
  263. if (ret < 0) {
  264. if (fd == handle_map->fd_top)
  265. handle_map->fd_top = fd ? fd - 1 : FD_NULL;
  266. } else
  267. ret = fd;
  268. out:
  269. unlock(handle_map->lock);
  270. return ret;
  271. }
  272. int set_new_fd_handle_by_fd (FDTYPE fd, struct shim_handle * hdl, int flags,
  273. struct shim_handle_map * handle_map)
  274. {
  275. int new_size = 0;
  276. int ret = 0;
  277. if (!handle_map && !(handle_map = get_cur_handle_map(NULL)))
  278. return -EBADF;
  279. lock(handle_map->lock);
  280. if (!handle_map->map ||
  281. handle_map->fd_size < INIT_HANDLE_MAP_SIZE)
  282. new_size = INIT_HANDLE_MAP_SIZE;
  283. if (!handle_map->map)
  284. goto extend;
  285. if (fd >= handle_map->fd_size) {
  286. new_size = handle_map->fd_size < new_size ? new_size :
  287. handle_map->fd_size;
  288. extend:
  289. while (new_size <= fd)
  290. new_size *= 2;
  291. if (!__enlarge_handle_map(handle_map, new_size)) {
  292. ret = -ENOMEM;
  293. goto out;
  294. }
  295. }
  296. if (handle_map->fd_top != FD_NULL &&
  297. fd <= handle_map->fd_top &&
  298. HANDLE_ALLOCATED(handle_map->map[fd])) {
  299. ret = -EBADF;
  300. goto out;
  301. }
  302. if (handle_map->fd_top == FD_NULL ||
  303. fd > handle_map->fd_top)
  304. handle_map->fd_top = fd;
  305. struct shim_fd_handle * new_handle = handle_map->map[fd];
  306. if (!new_handle) {
  307. new_handle = malloc(sizeof(struct shim_fd_handle));
  308. if (!new_handle) {
  309. ret = -ENOMEM;
  310. goto out;
  311. }
  312. handle_map->map[fd] = new_handle;
  313. }
  314. ret = __set_new_fd_handle(&handle_map->map[fd], fd, hdl, flags);
  315. if (ret < 0) {
  316. if (fd == handle_map->fd_top)
  317. handle_map->fd_top = fd ? fd - 1 : FD_NULL;
  318. } else
  319. ret = fd;
  320. out:
  321. unlock(handle_map->lock);
  322. return fd;
  323. }
  324. void flush_handle (struct shim_handle * hdl)
  325. {
  326. if (hdl->fs && hdl->fs->fs_ops &&
  327. hdl->fs->fs_ops->flush)
  328. hdl->fs->fs_ops->flush(hdl);
  329. }
  330. static inline __attribute__((unused))
  331. const char * __handle_name (struct shim_handle * hdl)
  332. {
  333. if (!qstrempty(&hdl->path))
  334. return qstrgetstr(&hdl->path);
  335. if (!qstrempty(&hdl->uri))
  336. return qstrgetstr(&hdl->uri);
  337. if (hdl->fs_type[0])
  338. return hdl->fs_type;
  339. return "(unknown)";
  340. }
  341. void open_handle (struct shim_handle * hdl)
  342. {
  343. get_handle(hdl);
  344. #ifdef DEBUG_REF
  345. int opened = REF_INC(hdl->opened);
  346. debug("open handle %p(%s) (opened = %d)\n", hdl, __handle_name(hdl),
  347. opened);
  348. #else
  349. REF_INC(hdl->opened);
  350. #endif
  351. }
  352. void close_handle (struct shim_handle * hdl)
  353. {
  354. int opened = REF_DEC(hdl->opened);
  355. #ifdef DEBUG_REF
  356. debug("close handle %p(%s) (opened = %d)\n", hdl, __handle_name(hdl),
  357. opened);
  358. #endif
  359. if (!opened) {
  360. if (hdl->type == TYPE_DIR) {
  361. struct shim_dir_handle * dir = &hdl->info.dir;
  362. if (dir->dot) {
  363. put_dentry(dir->dot);
  364. dir->dot = NULL;
  365. }
  366. if (dir->dotdot) {
  367. put_dentry(dir->dotdot);
  368. dir->dotdot = NULL;
  369. }
  370. while (dir->ptr && *dir->ptr) {
  371. struct shim_dentry * dent = *dir->ptr;
  372. put_dentry(dent);
  373. *(dir->ptr++) = NULL;
  374. }
  375. } else {
  376. if (hdl->fs && hdl->fs->fs_ops &&
  377. hdl->fs->fs_ops->close)
  378. hdl->fs->fs_ops->close(hdl);
  379. }
  380. }
  381. put_handle(hdl);
  382. }
  383. void get_handle (struct shim_handle * hdl)
  384. {
  385. #ifdef DEBUG_REF
  386. int ref_count = REF_INC(hdl->ref_count);
  387. debug("get handle %p(%s) (ref_count = %d)\n", hdl, __handle_name(hdl),
  388. ref_count);
  389. #else
  390. REF_INC(hdl->ref_count);
  391. #endif
  392. }
  393. static void destroy_handle (struct shim_handle * hdl)
  394. {
  395. destroy_lock(hdl->lock);
  396. if (MEMORY_MIGRATED(hdl))
  397. memset(hdl, 0, sizeof(struct shim_handle));
  398. else
  399. free_mem_obj_to_mgr(handle_mgr, hdl);
  400. }
  401. void put_handle (struct shim_handle * hdl)
  402. {
  403. int ref_count = REF_DEC(hdl->ref_count);
  404. #ifdef DEBUG_REF
  405. debug("put handle %p(%s) (ref_count = %d)\n", hdl, __handle_name(hdl),
  406. ref_count);
  407. #endif
  408. if (!ref_count) {
  409. if (hdl->fs && hdl->fs->fs_ops &&
  410. hdl->fs->fs_ops->hput)
  411. hdl->fs->fs_ops->hput(hdl);
  412. qstrfree(&hdl->path);
  413. qstrfree(&hdl->uri);
  414. if (hdl->pal_handle)
  415. DkObjectClose(hdl->pal_handle);
  416. if (hdl->dentry)
  417. put_dentry(hdl->dentry);
  418. if (hdl->fs)
  419. put_mount(hdl->fs);
  420. destroy_handle(hdl);
  421. }
  422. }
  423. size_t get_file_size (struct shim_handle * hdl)
  424. {
  425. if (!hdl->fs || !hdl->fs->fs_ops)
  426. return -EINVAL;
  427. if (hdl->fs->fs_ops->poll)
  428. return hdl->fs->fs_ops->poll(hdl, FS_POLL_SZ);
  429. if (hdl->fs->fs_ops->hstat) {
  430. struct stat stat;
  431. int ret = hdl->fs->fs_ops->hstat(hdl, &stat);
  432. if (ret < 0)
  433. return ret;
  434. return stat.st_size;
  435. }
  436. return 0;
  437. }
  438. void dup_fd_handle (struct shim_handle_map * map,
  439. const struct shim_fd_handle * old,
  440. struct shim_fd_handle * new)
  441. {
  442. struct shim_handle * replaced = NULL;
  443. lock(map->lock);
  444. if (old->vfd != FD_NULL) {
  445. open_handle(old->handle);
  446. replaced = new->handle;
  447. new->handle = old->handle;
  448. }
  449. unlock(map->lock);
  450. if (replaced)
  451. close_handle(replaced);
  452. }
  453. static struct shim_handle_map * get_new_handle_map (FDTYPE size)
  454. {
  455. struct shim_handle_map * handle_map =
  456. malloc(sizeof(struct shim_handle_map));
  457. if (handle_map == NULL)
  458. return NULL;
  459. memset(handle_map, 0, sizeof(struct shim_handle_map));
  460. handle_map->map = malloc(sizeof(struct shim_fd_handle) * size);
  461. if (handle_map->map == NULL) {
  462. free(handle_map);
  463. return NULL;
  464. }
  465. memset(handle_map->map, 0,
  466. sizeof(struct shim_fd_handle) * size);
  467. handle_map->fd_top = FD_NULL;
  468. handle_map->fd_size = size;
  469. create_lock(handle_map->lock);
  470. return handle_map;
  471. }
  472. static struct shim_handle_map * __enlarge_handle_map
  473. (struct shim_handle_map * map, FDTYPE size)
  474. {
  475. if (size <= map->fd_size)
  476. return NULL;
  477. struct shim_fd_handle ** old_map = map->map;
  478. map->map = malloc(sizeof(struct shim_fd_handle *) * size);
  479. if (map->map == NULL) {
  480. map->map = old_map;
  481. return NULL;
  482. }
  483. size_t copy_size = sizeof(struct shim_fd_handle *) * map->fd_size;
  484. map->fd_size = size;
  485. if (old_map && copy_size)
  486. memcpy(map->map, old_map, copy_size);
  487. memset(&map->map[map->fd_size], 0,
  488. (sizeof(struct shim_fd_handle *) * size) - copy_size);
  489. if (old_map)
  490. free(old_map);
  491. return map;
  492. }
  493. int dup_handle_map (struct shim_handle_map ** new,
  494. struct shim_handle_map * old_map)
  495. {
  496. lock(old_map->lock);
  497. /* allocate a new handle mapping with the same size as
  498. the old one */
  499. struct shim_handle_map * new_map =
  500. get_new_handle_map(old_map->fd_size);
  501. new_map->fd_top = old_map->fd_top;
  502. if (old_map->fd_top == FD_NULL)
  503. goto done;
  504. for (int i = 0 ; i <= old_map->fd_top ; i++) {
  505. struct shim_fd_handle * fd_old = old_map->map[i];
  506. struct shim_fd_handle * fd_new;
  507. /* now we go through the handle map and reassign each
  508. of them being allocated */
  509. if (HANDLE_ALLOCATED(fd_old)) {
  510. /* first, get the handle to prevent it from being deleted */
  511. struct shim_handle * hdl = fd_old->handle;
  512. open_handle(hdl);
  513. /* DP: I assume we really need a deep copy of the handle map? */
  514. fd_new = malloc(sizeof(struct shim_fd_handle));
  515. new_map->map[i] = fd_new;
  516. fd_new->vfd = fd_old->vfd;
  517. fd_new->handle = hdl;
  518. fd_new->flags = fd_old->flags;
  519. }
  520. }
  521. done:
  522. unlock(old_map->lock);
  523. *new = new_map;
  524. return 0;
  525. }
  526. void get_handle_map (struct shim_handle_map * map)
  527. {
  528. REF_INC(map->ref_count);
  529. }
  530. void put_handle_map (struct shim_handle_map * map)
  531. {
  532. int ref_count = REF_DEC(map->ref_count);
  533. if (!ref_count) {
  534. if (map->fd_top == FD_NULL)
  535. goto done;
  536. for (int i = 0 ; i <= map->fd_top ; i++) {
  537. if (!map->map[i])
  538. continue;
  539. if (map->map[i]->vfd != FD_NULL) {
  540. struct shim_handle * handle = map->map[i]->handle;
  541. if (handle)
  542. close_handle(handle);
  543. }
  544. free(map->map[i]);
  545. }
  546. done:
  547. destroy_lock(map->lock);
  548. free(map->map);
  549. free(map);
  550. }
  551. }
  552. int flush_handle_map (struct shim_handle_map * map)
  553. {
  554. get_handle_map(map);
  555. lock(map->lock);
  556. if (map->fd_top == FD_NULL)
  557. goto done;
  558. /* now we go through the handle map and flush each handle */
  559. for (int i = 0 ; i <= map->fd_top ; i++) {
  560. if (!HANDLE_ALLOCATED(map->map[i]))
  561. continue;
  562. struct shim_handle * handle = map->map[i]->handle;
  563. if (handle)
  564. flush_handle(handle);
  565. }
  566. done:
  567. unlock(map->lock);
  568. put_handle_map(map);
  569. return 0;
  570. }
  571. int walk_handle_map (int (*callback) (struct shim_fd_handle *,
  572. struct shim_handle_map *, void *),
  573. struct shim_handle_map * map, void * arg)
  574. {
  575. int ret = 0;
  576. lock(map->lock);
  577. if (map->fd_top == FD_NULL)
  578. goto done;
  579. for (int i = 0 ; i <= map->fd_top ; i++) {
  580. if (!HANDLE_ALLOCATED(map->map[i]))
  581. continue;
  582. if ((ret = (*callback) (map->map[i], map, arg)) < 0)
  583. break;
  584. }
  585. done:
  586. unlock(map->lock);
  587. return ret;
  588. }
  589. BEGIN_CP_FUNC(handle)
  590. {
  591. assert(size == sizeof(struct shim_handle));
  592. struct shim_handle * hdl = (struct shim_handle *) obj;
  593. struct shim_handle * new_hdl = NULL;
  594. ptr_t off = GET_FROM_CP_MAP(obj);
  595. if (!off) {
  596. off = ADD_CP_OFFSET(sizeof(struct shim_handle));
  597. ADD_TO_CP_MAP(obj, off);
  598. new_hdl = (struct shim_handle *) (base + off);
  599. lock(hdl->lock);
  600. struct shim_mount * fs = hdl->fs;
  601. *new_hdl = *hdl;
  602. if (fs && fs->fs_ops && fs->fs_ops->checkout)
  603. fs->fs_ops->checkout(new_hdl);
  604. new_hdl->dentry = NULL;
  605. REF_SET(new_hdl->opened, 0);
  606. REF_SET(new_hdl->ref_count, 0);
  607. clear_lock(new_hdl->lock);
  608. DO_CP_IN_MEMBER(qstr, new_hdl, path);
  609. DO_CP_IN_MEMBER(qstr, new_hdl, uri);
  610. if (fs && hdl->dentry) {
  611. DO_CP_MEMBER(mount, hdl, new_hdl, fs);
  612. } else {
  613. new_hdl->fs = NULL;
  614. }
  615. if (hdl->dentry)
  616. DO_CP_MEMBER(dentry, hdl, new_hdl, dentry);
  617. if (new_hdl->pal_handle) {
  618. struct shim_palhdl_entry * entry;
  619. DO_CP(palhdl, hdl->pal_handle, &entry);
  620. entry->uri = &new_hdl->uri;
  621. entry->phandle = &new_hdl->pal_handle;
  622. }
  623. unlock(hdl->lock);
  624. ADD_CP_FUNC_ENTRY(off);
  625. } else {
  626. new_hdl = (struct shim_handle *) (base + off);
  627. }
  628. if (objp)
  629. *objp = (void *) new_hdl;
  630. }
  631. END_CP_FUNC(handle)
  632. BEGIN_RS_FUNC(handle)
  633. {
  634. struct shim_handle * hdl = (void *) (base + GET_CP_FUNC_ENTRY());
  635. CP_REBASE(hdl->fs);
  636. CP_REBASE(hdl->dentry);
  637. create_lock(hdl->lock);
  638. if (!hdl->fs) {
  639. assert(hdl->fs_type);
  640. search_builtin_fs(hdl->fs_type, &hdl->fs);
  641. if (!hdl->fs)
  642. return -EINVAL;
  643. }
  644. if (hdl->fs && hdl->fs->fs_ops &&
  645. hdl->fs->fs_ops->checkin)
  646. hdl->fs->fs_ops->checkin(hdl);
  647. DEBUG_RS("path=%s,type=%s,uri=%s,flags=%03o",
  648. qstrgetstr(&hdl->path), hdl->fs_type, qstrgetstr(&hdl->uri),
  649. hdl->flags);
  650. }
  651. END_RS_FUNC(handle)
  652. BEGIN_CP_FUNC(fd_handle)
  653. {
  654. assert(size == sizeof(struct shim_fd_handle));
  655. struct shim_fd_handle * fdhdl = (struct shim_fd_handle *) obj;
  656. struct shim_fd_handle * new_fdhdl = NULL;
  657. ptr_t off = ADD_CP_OFFSET(sizeof(struct shim_fd_handle));
  658. new_fdhdl = (struct shim_fd_handle *) (base + off);
  659. memcpy(new_fdhdl, fdhdl, sizeof(struct shim_fd_handle));
  660. DO_CP(handle, fdhdl->handle, &new_fdhdl->handle);
  661. ADD_CP_FUNC_ENTRY(off);
  662. if (objp)
  663. *objp = (void *) new_fdhdl;
  664. }
  665. END_CP_FUNC_NO_RS(fd_handle)
  666. BEGIN_CP_FUNC(handle_map)
  667. {
  668. assert(size >= sizeof(struct shim_handle_map));
  669. struct shim_handle_map * handle_map = (struct shim_handle_map *) obj;
  670. struct shim_handle_map * new_handle_map = NULL;
  671. struct shim_fd_handle ** ptr_array;
  672. lock(handle_map->lock);
  673. int fd_size = handle_map->fd_top != FD_NULL ?
  674. handle_map->fd_top + 1 : 0;
  675. size = sizeof(struct shim_handle_map) +
  676. (sizeof(struct shim_fd_handle *) * fd_size);
  677. ptr_t off = GET_FROM_CP_MAP(obj);
  678. if (!off) {
  679. off = ADD_CP_OFFSET(size);
  680. new_handle_map = (struct shim_handle_map *) (base + off);
  681. memcpy(new_handle_map, handle_map,
  682. sizeof(struct shim_handle_map));
  683. ptr_array = (void *) new_handle_map + sizeof(struct shim_handle_map);
  684. new_handle_map->fd_size = fd_size;
  685. new_handle_map->map = fd_size ? ptr_array : NULL;
  686. REF_SET(new_handle_map->ref_count, 0);
  687. clear_lock(new_handle_map->lock);
  688. for (int i = 0 ; i < fd_size ; i++) {
  689. if (HANDLE_ALLOCATED(handle_map->map[i]))
  690. DO_CP(fd_handle, handle_map->map[i], &ptr_array[i]);
  691. else
  692. ptr_array[i] = NULL;
  693. }
  694. ADD_CP_FUNC_ENTRY(off);
  695. } else {
  696. new_handle_map = (struct shim_handle_map *) (base + off);
  697. }
  698. unlock(handle_map->lock);
  699. if (objp)
  700. *objp = (void *) new_handle_map;
  701. }
  702. END_CP_FUNC(handle_map)
  703. BEGIN_RS_FUNC(handle_map)
  704. {
  705. struct shim_handle_map * handle_map = (void *) (base + GET_CP_FUNC_ENTRY());
  706. CP_REBASE(handle_map->map);
  707. assert(handle_map->map);
  708. DEBUG_RS("size=%d,top=%d", handle_map->fd_size, handle_map->fd_top);
  709. create_lock(handle_map->lock);
  710. lock(handle_map->lock);
  711. if (handle_map->fd_top != FD_NULL)
  712. for (int i = 0 ; i <= handle_map->fd_top ; i++) {
  713. CP_REBASE(handle_map->map[i]);
  714. if (HANDLE_ALLOCATED(handle_map->map[i])) {
  715. CP_REBASE(handle_map->map[i]->handle);
  716. struct shim_handle * hdl = handle_map->map[i]->handle;
  717. assert(hdl);
  718. open_handle(hdl);
  719. DEBUG_RS("[%d]%s", i, qstrempty(&hdl->uri) ? hdl->fs_type :
  720. qstrgetstr(&hdl->uri));
  721. }
  722. }
  723. unlock(handle_map->lock);
  724. }
  725. END_RS_FUNC(handle_map)