/* -*- mode:c; c-file-style:"k&r"; c-basic-offset: 4; tab-width:4; indent-tabs-mode:nil; mode:auto-fill; fill-column:78; -*- */
/* vim: set ts=4 sw=4 et tw=78 fo=cqt wm=0: */
/* Copyright (C) 2014 OSCAR lab, Stony Brook University
This file is part of Graphene Library OS.
Graphene Library OS is free software: you can redistribute it and/or
modify it under the terms of the GNU General Public License
as published by the Free Software Foundation, either version 3 of the
License, or (at your option) any later version.
Graphene Library OS is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see . */
/*
* shim_handle.c
*
* This file contains codes to maintain bookkeeping for handles in library OS.
*/
#include
#include
#include
#include
#include
#include
#include
#include
static LOCKTYPE handle_mgr_lock;
#define HANDLE_MGR_ALLOC 32
#define system_lock() lock(handle_mgr_lock)
#define system_unlock() unlock(handle_mgr_lock)
#define PAGE_SIZE allocsize
#define OBJ_TYPE struct shim_handle
#include
static MEM_MGR handle_mgr = NULL;
#define INIT_HANDLE_MAP_SIZE 32
//#define DEBUG_REF
static inline int init_tty_handle (struct shim_handle * hdl, bool write)
{
struct shim_dentry * dent = NULL;
int ret;
if ((ret = path_lookupat(NULL, "/dev/tty", LOOKUP_OPEN, &dent)) < 0)
return ret;
int flags = (write ? O_WRONLY : O_RDONLY)|O_APPEND;
struct shim_mount * fs = dent->fs;
ret = fs->d_ops->open(hdl, dent, flags);
if (ret < 0)
return ret;
set_handle_fs(hdl, fs);
hdl->dentry = dent;
hdl->flags = O_RDWR|O_APPEND|0100000;
int size;
char * path = dentry_get_path(dent, true, &size);
if (path)
qstrsetstr(&hdl->path, path, size);
else
qstrsetstr(&hdl->path, "/dev/tty", 8);
return 0;
}
static inline int init_exec_handle (struct shim_thread * thread)
{
if (!PAL_CB(executable))
return 0;
struct shim_handle * exec = get_new_handle();
if (!exec)
return -ENOMEM;
set_handle_fs(exec, &chroot_builtin_fs);
qstrsetstr(&exec->uri, PAL_CB(executable), strlen(PAL_CB(executable)));
exec->type = TYPE_FILE;
exec->flags = O_RDONLY;
exec->acc_mode = MAY_READ;
lock(thread->lock);
thread->exec = exec;
unlock(thread->lock);
return 0;
}
static struct shim_handle_map * get_new_handle_map (FDTYPE size);
PAL_HANDLE shim_stdio = NULL;
static int __set_new_fd_handle(struct shim_fd_handle ** fdhdl, FDTYPE fd,
struct shim_handle * hdl, int flags);
static struct shim_handle_map * __enlarge_handle_map
(struct shim_handle_map * map, FDTYPE size);
int init_handle (void)
{
create_lock(handle_mgr_lock);
handle_mgr = create_mem_mgr(init_align_up(HANDLE_MGR_ALLOC));
if (!handle_mgr)
return -ENOMEM;
return 0;
}
int init_important_handles (void)
{
struct shim_thread * thread = get_cur_thread();
if (thread->handle_map)
goto done;
struct shim_handle_map * handle_map = get_cur_handle_map(thread);
if (!handle_map) {
handle_map = get_new_handle_map(INIT_HANDLE_MAP_SIZE);
if (!handle_map)
return -ENOMEM;
set_handle_map(thread, handle_map);
}
lock(handle_map->lock);
if (handle_map->fd_size < 3) {
if (!__enlarge_handle_map(handle_map, INIT_HANDLE_MAP_SIZE)) {
unlock(handle_map->lock);
return -ENOMEM;
}
}
struct shim_handle * hdl = NULL;
int ret;
for (int fd = 0 ; fd < 3 ; fd++)
if (!HANDLE_ALLOCATED(handle_map->map[fd])) {
if (!hdl) {
hdl = get_new_handle();
if (!hdl)
return -ENOMEM;
if ((ret = init_tty_handle(hdl, fd)) < 0) {
put_handle(hdl);
return ret;
}
} else {
get_handle(hdl);
}
__set_new_fd_handle(&handle_map->map[fd], fd, hdl, 0);
put_handle(hdl);
if (fd != 1)
hdl = NULL;
} else {
if (fd == 1)
hdl = handle_map->map[fd]->handle;
}
if (handle_map->fd_top == FD_NULL || handle_map->fd_top < 2)
handle_map->fd_top = 2;
unlock(handle_map->lock);
done:
init_exec_handle(thread);
return 0;
}
struct shim_handle * __get_fd_handle (FDTYPE fd, int * flags,
struct shim_handle_map * map)
{
struct shim_fd_handle * fd_handle = NULL;
if (map->fd_top != FD_NULL &&
fd <= map->fd_top) {
fd_handle = map->map[fd];
if (!HANDLE_ALLOCATED(fd_handle))
return NULL;
if (flags)
*flags = fd_handle->flags;
return fd_handle->handle;
}
return NULL;
}
struct shim_handle * get_fd_handle (FDTYPE fd, int * flags,
struct shim_handle_map * map)
{
if (!map)
map = get_cur_handle_map(NULL);
struct shim_handle * hdl = NULL;
lock(map->lock);
if ((hdl = __get_fd_handle(fd, flags, map)))
get_handle(hdl);
unlock(map->lock);
return hdl;
}
struct shim_handle *
__detach_fd_handle (struct shim_fd_handle * fd, int * flags,
struct shim_handle_map * map)
{
struct shim_handle * handle = NULL;
if (HANDLE_ALLOCATED(fd)) {
int vfd = fd->vfd;
handle = fd->handle;
if (flags)
*flags = fd->flags;
fd->vfd = FD_NULL;
fd->handle = NULL;
fd->flags = 0;
if (vfd == map->fd_top)
do {
map->fd_top = vfd ? vfd - 1 : FD_NULL;
vfd--;
} while (vfd >= 0 &&
!HANDLE_ALLOCATED(map->map[vfd]));
}
return handle;
}
struct shim_handle * detach_fd_handle (FDTYPE fd, int * flags,
struct shim_handle_map * handle_map)
{
struct shim_handle * handle = NULL;
if (!handle_map && !(handle_map = get_cur_handle_map(NULL)))
return NULL;
lock(handle_map->lock);
if (fd < handle_map->fd_size)
handle = __detach_fd_handle(handle_map->map[fd], flags,
handle_map);
unlock(handle_map->lock);
return handle;
}
struct shim_handle * get_new_handle (void)
{
struct shim_handle * new_handle =
get_mem_obj_from_mgr_enlarge(handle_mgr,
size_align_up(HANDLE_MGR_ALLOC));
if (!new_handle)
return NULL;
memset(new_handle, 0, sizeof(struct shim_handle));
REF_SET(new_handle->ref_count, 1);
create_lock(new_handle->lock);
new_handle->owner = cur_process.vmid;
return new_handle;
}
static int __set_new_fd_handle(struct shim_fd_handle ** fdhdl, FDTYPE fd,
struct shim_handle * hdl, int flags)
{
struct shim_fd_handle * new_handle = *fdhdl;
if (!new_handle) {
new_handle = malloc(sizeof(struct shim_fd_handle));
if (!new_handle)
return -ENOMEM;
*fdhdl = new_handle;
}
new_handle->vfd = fd;
new_handle->flags = flags;
open_handle(hdl);
new_handle->handle = hdl;
return 0;
}
int set_new_fd_handle (struct shim_handle * hdl, int flags,
struct shim_handle_map * handle_map)
{
FDTYPE fd = 0;
int new_size = 0;
int ret = 0;
if (!handle_map && !(handle_map = get_cur_handle_map(NULL)))
return -EBADF;
lock(handle_map->lock);
if (!handle_map->map ||
handle_map->fd_size < INIT_HANDLE_MAP_SIZE)
new_size = INIT_HANDLE_MAP_SIZE;
if (!handle_map->map)
goto extend;
if (handle_map->fd_top != FD_NULL)
do {
++fd;
if (fd == handle_map->fd_size) {
new_size = handle_map->fd_size < new_size ? new_size :
handle_map->fd_size * 2;
extend:
if (!__enlarge_handle_map(handle_map, new_size)) {
ret = -ENOMEM;
goto out;
}
}
} while (handle_map->fd_top != FD_NULL &&
fd <= handle_map->fd_top &&
HANDLE_ALLOCATED(handle_map->map[fd]));
if (handle_map->fd_top == FD_NULL ||
fd > handle_map->fd_top)
handle_map->fd_top = fd;
ret = __set_new_fd_handle(&handle_map->map[fd], fd, hdl, flags);
if (ret < 0) {
if (fd == handle_map->fd_top)
handle_map->fd_top = fd ? fd - 1 : FD_NULL;
} else
ret = fd;
out:
unlock(handle_map->lock);
return ret;
}
int set_new_fd_handle_by_fd (FDTYPE fd, struct shim_handle * hdl, int flags,
struct shim_handle_map * handle_map)
{
int new_size = 0;
int ret = 0;
if (!handle_map && !(handle_map = get_cur_handle_map(NULL)))
return -EBADF;
lock(handle_map->lock);
if (!handle_map->map ||
handle_map->fd_size < INIT_HANDLE_MAP_SIZE)
new_size = INIT_HANDLE_MAP_SIZE;
if (!handle_map->map)
goto extend;
if (fd >= handle_map->fd_size) {
new_size = handle_map->fd_size < new_size ? new_size :
handle_map->fd_size;
extend:
while (new_size <= fd)
new_size *= 2;
if (!__enlarge_handle_map(handle_map, new_size)) {
ret = -ENOMEM;
goto out;
}
}
if (handle_map->fd_top != FD_NULL &&
fd <= handle_map->fd_top &&
HANDLE_ALLOCATED(handle_map->map[fd])) {
ret = -EBADF;
goto out;
}
if (handle_map->fd_top == FD_NULL ||
fd > handle_map->fd_top)
handle_map->fd_top = fd;
struct shim_fd_handle * new_handle = handle_map->map[fd];
if (!new_handle) {
new_handle = malloc(sizeof(struct shim_fd_handle));
if (!new_handle) {
ret = -ENOMEM;
goto out;
}
handle_map->map[fd] = new_handle;
}
ret = __set_new_fd_handle(&handle_map->map[fd], fd, hdl, flags);
if (ret < 0) {
if (fd == handle_map->fd_top)
handle_map->fd_top = fd ? fd - 1 : FD_NULL;
} else
ret = fd;
out:
unlock(handle_map->lock);
return fd;
}
void flush_handle (struct shim_handle * hdl)
{
if (hdl->fs && hdl->fs->fs_ops &&
hdl->fs->fs_ops->flush)
hdl->fs->fs_ops->flush(hdl);
}
static inline __attribute__((unused))
const char * __handle_name (struct shim_handle * hdl)
{
if (!qstrempty(&hdl->path))
return qstrgetstr(&hdl->path);
if (!qstrempty(&hdl->uri))
return qstrgetstr(&hdl->uri);
if (hdl->fs_type[0])
return hdl->fs_type;
return "(unknown)";
}
void open_handle (struct shim_handle * hdl)
{
get_handle(hdl);
#ifdef DEBUG_REF
int opened = REF_INC(hdl->opened);
debug("open handle %p(%s) (opened = %d)\n", hdl, __handle_name(hdl),
opened);
#else
REF_INC(hdl->opened);
#endif
}
void close_handle (struct shim_handle * hdl)
{
int opened = REF_DEC(hdl->opened);
#ifdef DEBUG_REF
debug("close handle %p(%s) (opened = %d)\n", hdl, __handle_name(hdl),
opened);
#endif
if (!opened) {
if (hdl->type == TYPE_DIR) {
struct shim_dir_handle * dir = &hdl->info.dir;
if (dir->dot) {
put_dentry(dir->dot);
dir->dot = NULL;
}
if (dir->dotdot) {
put_dentry(dir->dotdot);
dir->dotdot = NULL;
}
while (*dir->ptr) {
struct shim_dentry * dent = *dir->ptr;
put_dentry(dent);
*(dir->ptr++) = NULL;
}
} else {
if (hdl->fs && hdl->fs->fs_ops &&
hdl->fs->fs_ops->close)
hdl->fs->fs_ops->close(hdl);
}
}
put_handle(hdl);
}
void get_handle (struct shim_handle * hdl)
{
#ifdef DEBUG_REF
int ref_count = REF_INC(hdl->ref_count);
debug("get handle %p(%s) (ref_count = %d)\n", hdl, __handle_name(hdl),
ref_count);
#else
REF_INC(hdl->ref_count);
#endif
}
static void destroy_handle (struct shim_handle * hdl)
{
destroy_lock(hdl->lock);
if (MEMORY_MIGRATED(hdl))
memset(hdl, 0, sizeof(struct shim_handle));
else
free_mem_obj_to_mgr(handle_mgr, hdl);
}
void put_handle (struct shim_handle * hdl)
{
int ref_count = REF_DEC(hdl->ref_count);
#ifdef DEBUG_REF
debug("put handle %p(%s) (ref_count = %d)\n", hdl, __handle_name(hdl),
ref_count);
#endif
if (!ref_count) {
if (hdl->fs && hdl->fs->fs_ops &&
hdl->fs->fs_ops->hput)
hdl->fs->fs_ops->hput(hdl);
qstrfree(&hdl->path);
qstrfree(&hdl->uri);
if (hdl->pal_handle)
DkObjectClose(hdl->pal_handle);
if (hdl->dentry)
put_dentry(hdl->dentry);
if (hdl->fs)
put_mount(hdl->fs);
destroy_handle(hdl);
}
}
size_t get_file_size (struct shim_handle * hdl)
{
if (!hdl->fs || !hdl->fs->fs_ops)
return -EINVAL;
if (hdl->fs->fs_ops->poll)
return hdl->fs->fs_ops->poll(hdl, FS_POLL_SZ);
if (hdl->fs->fs_ops->hstat) {
struct stat stat;
int ret = hdl->fs->fs_ops->hstat(hdl, &stat);
if (ret < 0)
return ret;
return stat.st_size;
}
return 0;
}
void dup_fd_handle (struct shim_handle_map * map,
const struct shim_fd_handle * old,
struct shim_fd_handle * new)
{
struct shim_handle * replaced = NULL;
lock(map->lock);
if (old->vfd != FD_NULL) {
open_handle(old->handle);
replaced = new->handle;
new->handle = old->handle;
}
unlock(map->lock);
if (replaced)
close_handle(replaced);
}
static struct shim_handle_map * get_new_handle_map (FDTYPE size)
{
struct shim_handle_map * handle_map =
malloc(sizeof(struct shim_handle_map));
if (handle_map == NULL)
return NULL;
memset(handle_map, 0, sizeof(struct shim_handle_map));
handle_map->map = malloc(sizeof(struct shim_fd_handle) * size);
if (handle_map->map == NULL) {
free(handle_map);
return NULL;
}
memset(handle_map->map, 0,
sizeof(struct shim_fd_handle) * size);
handle_map->fd_top = FD_NULL;
handle_map->fd_size = size;
create_lock(handle_map->lock);
return handle_map;
}
static struct shim_handle_map * __enlarge_handle_map
(struct shim_handle_map * map, FDTYPE size)
{
if (size <= map->fd_size)
return NULL;
struct shim_fd_handle ** old_map = map->map;
map->map = malloc(sizeof(struct shim_fd_handle *) * size);
if (map->map == NULL) {
map->map = old_map;
return NULL;
}
size_t copy_size = sizeof(struct shim_fd_handle *) * map->fd_size;
map->fd_size = size;
if (old_map && copy_size)
memcpy(map->map, old_map, copy_size);
memset(&map->map[map->fd_size], 0,
(sizeof(struct shim_fd_handle *) * size) - copy_size);
if (old_map)
free(old_map);
return map;
}
int dup_handle_map (struct shim_handle_map ** new,
struct shim_handle_map * old_map)
{
lock(old_map->lock);
/* allocate a new handle mapping with the same size as
the old one */
struct shim_handle_map * new_map =
get_new_handle_map(old_map->fd_size);
new_map->fd_top = old_map->fd_top;
if (old_map->fd_top == FD_NULL)
goto done;
for (int i = 0 ; i <= old_map->fd_top ; i++) {
struct shim_fd_handle * fd_old = old_map->map[i];
struct shim_fd_handle * fd_new;
/* now we go through the handle map and reassign each
of them being allocated */
if (HANDLE_ALLOCATED(fd_old)) {
/* first, get the handle to prevent it from being deleted */
struct shim_handle * hdl = fd_old->handle;
open_handle(hdl);
/* DP: I assume we really need a deep copy of the handle map? */
fd_new = malloc(sizeof(struct shim_fd_handle));
new_map->map[i] = fd_new;
fd_new->vfd = fd_old->vfd;
fd_new->handle = hdl;
fd_new->flags = fd_old->flags;
}
}
done:
unlock(old_map->lock);
*new = new_map;
return 0;
}
void get_handle_map (struct shim_handle_map * map)
{
REF_INC(map->ref_count);
}
void put_handle_map (struct shim_handle_map * map)
{
int ref_count = REF_DEC(map->ref_count);
if (!ref_count) {
if (map->fd_top == FD_NULL)
goto done;
for (int i = 0 ; i <= map->fd_top ; i++) {
if (!map->map[i])
continue;
if (map->map[i]->vfd != FD_NULL) {
struct shim_handle * handle = map->map[i]->handle;
if (handle)
close_handle(handle);
}
free(map->map[i]);
}
done:
destroy_lock(map->lock);
free(map->map);
free(map);
}
}
int flush_handle_map (struct shim_handle_map * map)
{
get_handle_map(map);
lock(map->lock);
if (map->fd_top == FD_NULL)
goto done;
/* now we go through the handle map and flush each handle */
for (int i = 0 ; i <= map->fd_top ; i++) {
if (!HANDLE_ALLOCATED(map->map[i]))
continue;
struct shim_handle * handle = map->map[i]->handle;
if (handle)
flush_handle(handle);
}
done:
unlock(map->lock);
put_handle_map(map);
return 0;
}
int walk_handle_map (int (*callback) (struct shim_fd_handle *,
struct shim_handle_map *, void *),
struct shim_handle_map * map, void * arg)
{
int ret = 0;
lock(map->lock);
if (map->fd_top == FD_NULL)
goto done;
for (int i = 0 ; i <= map->fd_top ; i++) {
if (!HANDLE_ALLOCATED(map->map[i]))
continue;
if ((ret = (*callback) (map->map[i], map, arg)) < 0)
break;
}
done:
unlock(map->lock);
return ret;
}
DEFINE_MIGRATE_FUNC(handle)
MIGRATE_FUNC_BODY(handle)
{
assert(size == sizeof(struct shim_handle));
struct shim_handle * hdl = (struct shim_handle *) obj;
struct shim_handle * new_hdl = NULL;
lock(hdl->lock);
struct shim_mount * fs = hdl->fs, * new_fs = NULL;
if (fs && fs->mount_point)
__DO_MIGRATE(mount, fs, &new_fs, 0);
unsigned long off = ADD_TO_MIGRATE_MAP(obj, *offset,
sizeof(struct shim_handle));
if (ENTRY_JUST_CREATED(off)) {
off = ADD_OFFSET(sizeof(struct shim_handle));
if (!dry) {
new_hdl = (struct shim_handle *) (base + off);
memcpy(new_hdl, hdl, sizeof(struct shim_handle));
if (fs && fs->fs_ops && fs->fs_ops->checkout)
fs->fs_ops->checkout(new_hdl);
new_hdl->dentry = NULL;
new_hdl->fs = new_fs;
REF_SET(new_hdl->opened, 0);
REF_SET(new_hdl->ref_count, 0);
clear_lock(new_hdl->lock);
}
DO_MIGRATE_IN_MEMBER(qstr, hdl, new_hdl, path, false);
DO_MIGRATE_IN_MEMBER(qstr, hdl, new_hdl, uri, false);
ADD_FUNC_ENTRY(off);
ADD_ENTRY(SIZE, sizeof(struct shim_handle));
ADD_ENTRY(PALHDL, new_hdl->pal_handle ?
*offset + offsetof(struct shim_handle, pal_handle) : 0);
} else if (!dry) {
new_hdl = (struct shim_handle *) (base + off);
}
if (new_hdl && objp)
*objp = (void *) new_hdl;
if (new_hdl)
assert(new_hdl->uri.len < 1024);
unlock(hdl->lock);
}
END_MIGRATE_FUNC
DEFINE_PROFILE_CATAGORY(inside_resume_handle, resume_func);
DEFINE_PROFILE_INTERVAL(dentry_lookup_for_handle, inside_resume_handle);
RESUME_FUNC_BODY(handle)
{
unsigned long off = GET_FUNC_ENTRY();
assert((size_t) GET_ENTRY(SIZE) == sizeof(struct shim_handle));
GET_ENTRY(PALHDL);
BEGIN_PROFILE_INTERVAL();
struct shim_handle * hdl = (struct shim_handle *) (base + off);
RESUME_REBASE(hdl->fs);
create_lock(hdl->lock);
if (!qstrempty(&hdl->path)) {
UPDATE_PROFILE_INTERVAL();
int ret = path_lookupat(NULL, qstrgetstr(&hdl->path), LOOKUP_OPEN,
&hdl->dentry);
if (ret < 0)
return -EACCES;
get_dentry(hdl->dentry);
SAVE_PROFILE_INTERVAL(dentry_lookup_for_handle);
}
if (!hdl->fs) {
if (hdl->dentry) {
set_handle_fs(hdl, hdl->dentry->fs);
} else {
struct shim_mount * fs = NULL;
assert(hdl->fs_type);
search_builtin_fs(hdl->fs_type, &fs);
if (fs)
set_handle_fs(hdl, fs);
}
}
if (hdl->fs && hdl->fs->fs_ops &&
hdl->fs->fs_ops->checkin)
hdl->fs->fs_ops->checkin(hdl);
#ifdef DEBUG_RESUME
debug("handle: path=%s,fs_type=%s,uri=%s,flags=%03o\n",
qstrgetstr(&hdl->path), hdl->fs_type, qstrgetstr(&hdl->uri),
hdl->flags);
#endif
}
END_RESUME_FUNC
DEFINE_MIGRATE_FUNC(fd_handle)
MIGRATE_FUNC_BODY(fd_handle)
{
assert(size == sizeof(struct shim_fd_handle));
struct shim_fd_handle * fdhdl = (struct shim_fd_handle *) obj;
struct shim_fd_handle * new_fdhdl = NULL;
ADD_OFFSET(sizeof(struct shim_fd_handle));
ADD_FUNC_ENTRY(*offset);
ADD_ENTRY(SIZE, sizeof(struct shim_fd_handle));
if (!dry) {
new_fdhdl = (struct shim_fd_handle *) (base + *offset);
memcpy(new_fdhdl, fdhdl, sizeof(struct shim_fd_handle));
}
if (new_fdhdl && objp)
*objp = (void *) new_fdhdl;
struct shim_handle ** phdl = dry ? NULL : &(new_fdhdl->handle);
struct shim_handle * hdl = fdhdl->handle;
DO_MIGRATE_IF_RECURSIVE(handle, hdl, phdl, recursive);
}
END_MIGRATE_FUNC
RESUME_FUNC_BODY(fd_handle)
{
GET_FUNC_ENTRY();
assert((size_t) GET_ENTRY(SIZE) == sizeof(struct shim_fd_handle));
}
END_RESUME_FUNC
DEFINE_MIGRATE_FUNC(handle_map)
MIGRATE_FUNC_BODY(handle_map)
{
assert(size >= sizeof(struct shim_handle_map));
struct shim_handle_map * handle_map = (struct shim_handle_map *) obj;
struct shim_handle_map * new_handle_map = NULL;
struct shim_fd_handle ** ptr_array;
lock(handle_map->lock);
int fd_size = handle_map->fd_top != FD_NULL ?
handle_map->fd_top + 1 : 0;
size = sizeof(struct shim_handle_map) +
(sizeof(struct shim_fd_handle *) * fd_size);
unsigned long off = ADD_TO_MIGRATE_MAP(obj, *offset, size);
if (ENTRY_JUST_CREATED(off)) {
ADD_OFFSET(size);
ADD_FUNC_ENTRY(*offset);
ADD_ENTRY(SIZE, size);
if (!dry) {
new_handle_map = (struct shim_handle_map *) (base + *offset);
memcpy(new_handle_map, handle_map,
sizeof(struct shim_handle_map));
ptr_array = (void *) new_handle_map +
sizeof(struct shim_handle_map);
new_handle_map->fd_size = fd_size;
new_handle_map->map = fd_size ? ptr_array : NULL;
REF_SET(new_handle_map->ref_count, 0);
clear_lock(new_handle_map->lock);
}
for (int i = 0 ; i < fd_size ; i++) {
if (HANDLE_ALLOCATED(handle_map->map[i])) {
struct shim_fd_handle ** new_hdl = dry ? NULL :
&(ptr_array[i]);
__DO_MIGRATE(fd_handle, handle_map->map[i],
new_hdl, 1);
} else if (!dry)
ptr_array[i] = NULL;
}
} else if (!dry)
new_handle_map = (struct shim_handle_map *) (base + off);
unlock(handle_map->lock);
if (new_handle_map && objp)
*objp = (void *) new_handle_map;
}
END_MIGRATE_FUNC
RESUME_FUNC_BODY(handle_map)
{
unsigned long off = GET_FUNC_ENTRY();
assert((size_t) GET_ENTRY(SIZE) >= sizeof(struct shim_handle_map));
struct shim_handle_map * handle_map =
(struct shim_handle_map *) (base + off);
RESUME_REBASE(handle_map->map);
assert(handle_map->map);
#ifdef DEBUG_RESUME
debug("handle_map: size=%d,top=%d\n", handle_map->fd_size,
handle_map->fd_top);
#endif
create_lock(handle_map->lock);
lock(handle_map->lock);
if (handle_map->fd_top != FD_NULL)
for (int i = 0 ; i <= handle_map->fd_top ; i++) {
RESUME_REBASE(handle_map->map[i]);
if (HANDLE_ALLOCATED(handle_map->map[i])) {
RESUME_REBASE(handle_map->map[i]->handle);
struct shim_handle * hdl = handle_map->map[i]->handle;
assert(hdl);
open_handle(hdl);
#ifdef DEBUG_RESUME
debug("handle_map[%d]: %s\n", i,
!qstrempty(&hdl->uri) ? qstrgetstr(&hdl->uri) :
hdl->fs_type);
#endif
}
}
unlock(handle_map->lock);
}
END_RESUME_FUNC