mirror of
https://github.com/clearlinux/graphene.git
synced 2026-09-06 22:01:29 +00:00
Inside `struct shim_handle` `opened` reference counter is used incorrectly. Additionally at this moment it guards the same resource (handle) as `ref_counter`, making it obsolete. This patch removes `opened` counter and moves `close_handle` logic into `put_handle`.
444 lines
13 KiB
C
444 lines
13 KiB
C
/* Copyright (C) 2014 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 Lesser 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 Lesser General Public License for more details.
|
|
|
|
You should have received a copy of the GNU Lesser General Public License
|
|
along with this program. If not, see <http://www.gnu.org/licenses/>. */
|
|
|
|
/*
|
|
* shim_handle.h
|
|
*
|
|
* Definitions of types and functions for file/handle bookkeeping.
|
|
*/
|
|
|
|
#ifndef _SHIM_HANDLE_H_
|
|
#define _SHIM_HANDLE_H_
|
|
|
|
#include <stdalign.h>
|
|
|
|
#include <shim_types.h>
|
|
#include <shim_defs.h>
|
|
#include <shim_sysv.h>
|
|
|
|
#include <pal.h>
|
|
#include <list.h>
|
|
|
|
#include <linux/shm.h>
|
|
#include <linux/in.h>
|
|
#include <linux/in6.h>
|
|
#include <linux/un.h>
|
|
|
|
#include <asm/fcntl.h>
|
|
#include <asm/resource.h>
|
|
|
|
/* start definition of shim handle */
|
|
enum shim_handle_type {
|
|
TYPE_FILE,
|
|
TYPE_DEV,
|
|
TYPE_PIPE,
|
|
TYPE_SOCK,
|
|
TYPE_DIR,
|
|
TYPE_SHM,
|
|
TYPE_SEM,
|
|
TYPE_MSG,
|
|
TYPE_FUTEX,
|
|
TYPE_STR,
|
|
TYPE_EPOLL,
|
|
};
|
|
|
|
struct shim_handle;
|
|
struct shim_thread;
|
|
struct shim_vma;
|
|
|
|
enum shim_file_type {
|
|
FILE_UNKNOWN,
|
|
FILE_REGULAR,
|
|
FILE_DIR,
|
|
FILE_DEV,
|
|
FILE_TTY,
|
|
};
|
|
|
|
struct shim_file_data {
|
|
struct shim_lock lock;
|
|
struct atomic_int version;
|
|
bool queried;
|
|
enum shim_file_type type;
|
|
mode_t mode;
|
|
struct atomic_int size;
|
|
struct shim_qstr host_uri;
|
|
unsigned long atime;
|
|
unsigned long mtime;
|
|
unsigned long ctime;
|
|
unsigned long nlink;
|
|
};
|
|
|
|
struct shim_file_handle {
|
|
unsigned int version;
|
|
struct shim_file_data * data;
|
|
|
|
enum shim_file_type type;
|
|
off_t size;
|
|
off_t marker;
|
|
|
|
enum { FILEBUF_MAP, FILEBUF_NONE } buf_type;
|
|
size_t mapsize;
|
|
off_t mapoffset;
|
|
void * mapbuf;
|
|
};
|
|
|
|
#define FILE_HANDLE_DATA(hdl) ((hdl)->info.file.data)
|
|
#define FILE_DENTRY_DATA(dent) ((struct shim_file_data*)(dent)->data)
|
|
|
|
struct shim_dev_ops {
|
|
/* open: provide a filename relative to the mount point and flags,
|
|
modify the shim handle */
|
|
int (*open) (struct shim_handle * hdl, const char * name, int flags);
|
|
|
|
/* close: clean up the file state inside the handle */
|
|
int (*close) (struct shim_handle * hdl);
|
|
|
|
/* read: the content from the file opened as handle */
|
|
ssize_t (*read) (struct shim_handle * hdl, void * buf, size_t count);
|
|
|
|
/* write: the content from the file opened as handle */
|
|
ssize_t (*write) (struct shim_handle * hdl, const void * buf, size_t count);
|
|
|
|
/* flush: flush out user buffer */
|
|
int (*flush) (struct shim_handle * hdl);
|
|
|
|
/* seek: the content from the file opened as handle */
|
|
off_t (*seek) (struct shim_handle * hdl, off_t offset, int wence);
|
|
|
|
int (*truncate) (struct shim_handle * hdl, uint64_t len);
|
|
|
|
int (*mode) (const char * name, mode_t * mode);
|
|
|
|
/* stat, hstat: get status of the file */
|
|
int (*stat) (const char * name, struct stat * buf);
|
|
int (*hstat) (struct shim_handle * hdl, struct stat * buf);
|
|
};
|
|
|
|
struct shim_dev_handle {
|
|
struct shim_dev_ops dev_ops;
|
|
};
|
|
|
|
struct shim_pipe_handle {
|
|
#if USE_SIMPLE_PIPE == 1
|
|
struct shim_handle * pair;
|
|
#else
|
|
IDTYPE pipeid;
|
|
#endif
|
|
};
|
|
|
|
#define SOCK_STREAM 1
|
|
#define SOCK_DGRAM 2
|
|
#define SOCK_NONBLOCK 04000
|
|
#define SOCK_CLOEXEC 02000000
|
|
|
|
#define SOL_TCP 6
|
|
|
|
#define PF_LOCAL 1
|
|
#define PF_UNIX PF_LOCAL
|
|
#define PF_FILE PF_LOCAL
|
|
#define PF_INET 2
|
|
#define PF_INET6 10
|
|
|
|
#define AF_UNIX PF_UNIX
|
|
#define AF_INET PF_INET
|
|
#define AF_INET6 PF_INET6
|
|
|
|
enum shim_sock_state {
|
|
SOCK_CREATED,
|
|
SOCK_BOUND,
|
|
SOCK_CONNECTED,
|
|
SOCK_BOUNDCONNECTED,
|
|
SOCK_LISTENED,
|
|
SOCK_ACCEPTED,
|
|
SOCK_SHUTDOWN,
|
|
};
|
|
|
|
struct shim_unix_data {
|
|
unsigned int pipeid;
|
|
};
|
|
|
|
struct shim_sock_handle {
|
|
int domain;
|
|
int sock_type;
|
|
int protocol;
|
|
int error;
|
|
|
|
enum shim_sock_state sock_state;
|
|
|
|
union shim_sock_addr {
|
|
// INET addr
|
|
struct {
|
|
struct addr_inet {
|
|
unsigned short port;
|
|
unsigned short ext_port;
|
|
union {
|
|
struct in_addr v4;
|
|
struct in6_addr v6;
|
|
} addr;
|
|
} bind, conn;
|
|
} in;
|
|
// UNIX addr
|
|
struct addr_unix {
|
|
struct shim_dentry * dentry;
|
|
unsigned int pipeid;
|
|
struct shim_unix_data * data;
|
|
} un;
|
|
} addr;
|
|
|
|
struct shim_sock_option {
|
|
struct shim_sock_option * next;
|
|
int level;
|
|
int optname;
|
|
int optlen;
|
|
char optval[];
|
|
} * pending_options;
|
|
};
|
|
|
|
struct shim_dirent {
|
|
struct shim_dirent * next;
|
|
unsigned long ino; /* Inode number */
|
|
unsigned char type;
|
|
char name[]; /* File name (null-terminated) */
|
|
};
|
|
|
|
#define SHIM_DIRENT_SIZE offsetof(struct shim_dirent, name)
|
|
#define SHIM_DIRENT_ALIGNMENT alignof(struct shim_dirent)
|
|
/* Size of struct shim_dirent instance together with alignment,
|
|
* which might be different depending on the length of the name field */
|
|
#define SHIM_DIRENT_ALIGNED_SIZE(len) ( \
|
|
(SHIM_DIRENT_SIZE \
|
|
+ (len) \
|
|
+ SHIM_DIRENT_ALIGNMENT - 1) \
|
|
/ SHIM_DIRENT_ALIGNMENT * SHIM_DIRENT_ALIGNMENT)
|
|
|
|
struct shim_dir_handle {
|
|
int offset;
|
|
struct shim_dentry * dotdot;
|
|
struct shim_dentry * dot;
|
|
struct shim_dentry ** buf;
|
|
struct shim_dentry ** ptr;
|
|
};
|
|
|
|
struct shim_shm_handle {
|
|
/* XXX: need to implement */
|
|
void * __reserved;
|
|
};
|
|
|
|
struct msg_type;
|
|
struct msg_item;
|
|
struct msg_client;
|
|
|
|
#define MAX_SYSV_CLIENTS 32
|
|
|
|
DEFINE_LIST(shim_msg_handle);
|
|
struct shim_msg_handle {
|
|
unsigned long msqkey; /* msg queue key from user */
|
|
IDTYPE msqid; /* msg queue identifier */
|
|
bool owned; /* owned by current process */
|
|
struct shim_ipc_info * owner;
|
|
LEASETYPE lease;
|
|
int perm; /* access permissions */
|
|
bool deleted; /* marking the queue deleted */
|
|
int nmsgs; /* number of msgs */
|
|
int currentsize; /* current size in bytes */
|
|
struct msg_qobj * queue;
|
|
int queuesize;
|
|
int queueused;
|
|
struct msg_qobj * freed;
|
|
PAL_HANDLE event; /* event for waiting */
|
|
int ntypes;
|
|
int maxtypes;
|
|
struct msg_type * types;
|
|
struct sysv_score scores[MAX_SYSV_CLIENTS];
|
|
LIST_TYPE(shim_msg_handle) list;
|
|
LIST_TYPE(shim_msg_handle) key_hlist;
|
|
LIST_TYPE(shim_msg_handle) qid_hlist;
|
|
};
|
|
|
|
struct sem_objs;
|
|
|
|
DEFINE_LIST(shim_sem_handle);
|
|
struct shim_sem_handle {
|
|
unsigned long semkey;
|
|
IDTYPE semid;
|
|
bool owned;
|
|
struct shim_ipc_info * owner;
|
|
LEASETYPE lease;
|
|
int perm;
|
|
bool deleted;
|
|
PAL_HANDLE event;
|
|
int nsems;
|
|
struct sem_obj * sems;
|
|
int nreqs;
|
|
struct sysv_score scores[MAX_SYSV_CLIENTS];
|
|
LISTP_TYPE(sem_ops) migrated;
|
|
LIST_TYPE(shim_sem_handle) list;
|
|
LIST_TYPE(shim_sem_handle) key_hlist;
|
|
LIST_TYPE(shim_sem_handle) sid_hlist;
|
|
};
|
|
DEFINE_LIST(futex_waiter);
|
|
DEFINE_LISTP(futex_waiter);
|
|
DEFINE_LIST(shim_futex_handle);
|
|
struct shim_futex_handle {
|
|
int * uaddr;
|
|
LISTP_TYPE(futex_waiter) waiters;
|
|
struct shim_vma * vma;
|
|
LIST_TYPE(shim_futex_handle) list;
|
|
};
|
|
|
|
struct shim_str_data {
|
|
REFTYPE ref_count;
|
|
char * str;
|
|
off_t len;
|
|
size_t buf_size;
|
|
bool dirty;
|
|
int (*update) (struct shim_handle * hdl);
|
|
int (*modify) (struct shim_handle * hdl);
|
|
};
|
|
|
|
struct shim_str_handle {
|
|
struct shim_str_data * data; /* inode is stored in dentry, too.
|
|
store pointer here for efficiency */
|
|
char * ptr;
|
|
};
|
|
|
|
DEFINE_LIST(shim_epoll_fd);
|
|
DEFINE_LISTP(shim_epoll_fd);
|
|
struct shim_epoll_handle {
|
|
int maxfds;
|
|
int nfds;
|
|
LISTP_TYPE(shim_epoll_fd) fds; /* this list contains all the
|
|
* shim_epoll_fd objects in correspondence
|
|
* with the registered handles. */
|
|
FDTYPE * pal_fds;
|
|
PAL_HANDLE * pal_handles;
|
|
int npals;
|
|
int nread;
|
|
int nwaiters;
|
|
AEVENTTYPE event;
|
|
};
|
|
|
|
struct shim_mount;
|
|
struct shim_qstr;
|
|
struct shim_dentry;
|
|
|
|
/* The epolls list links to the back field of the shim_epoll_fd structure
|
|
*/
|
|
struct shim_handle {
|
|
enum shim_handle_type type;
|
|
|
|
REFTYPE ref_count;
|
|
|
|
char fs_type[8];
|
|
struct shim_mount * fs;
|
|
struct shim_qstr path;
|
|
struct shim_dentry * dentry;
|
|
|
|
/* If this handle is registered for any epoll handle, this list contains
|
|
* a shim_epoll_fd object in correspondence with the epoll handle. */
|
|
LISTP_TYPE(shim_epoll_fd) epolls;
|
|
|
|
struct shim_qstr uri; /* URI representing this handle, it is not
|
|
* necessary to be set. */
|
|
|
|
PAL_HANDLE pal_handle;
|
|
|
|
union {
|
|
struct shim_file_handle file;
|
|
struct shim_dev_handle dev;
|
|
struct shim_pipe_handle pipe;
|
|
struct shim_sock_handle sock;
|
|
struct shim_shm_handle shm;
|
|
struct shim_msg_handle msg;
|
|
struct shim_sem_handle sem;
|
|
struct shim_futex_handle futex;
|
|
struct shim_str_handle str;
|
|
struct shim_epoll_handle epoll;
|
|
} info;
|
|
|
|
struct shim_dir_handle dir_info;
|
|
|
|
int flags;
|
|
int acc_mode;
|
|
IDTYPE owner;
|
|
struct shim_lock lock;
|
|
};
|
|
|
|
/* allocating / manage handle */
|
|
struct shim_handle * get_new_handle (void);
|
|
void flush_handle (struct shim_handle * hdl);
|
|
void get_handle (struct shim_handle * hdl);
|
|
void put_handle (struct shim_handle * hdl);
|
|
|
|
/* file descriptor table */
|
|
struct shim_fd_handle {
|
|
FDTYPE vfd; /* virtual file descriptor */
|
|
int flags; /* file descriptor flags, only FD_CLOEXEC */
|
|
|
|
struct shim_handle * handle;
|
|
};
|
|
|
|
struct shim_handle_map {
|
|
/* the top of created file descriptors */
|
|
FDTYPE fd_size;
|
|
FDTYPE fd_top;
|
|
|
|
/* refrence count and lock */
|
|
REFTYPE ref_count;
|
|
struct shim_lock lock;
|
|
|
|
/* An array of file descriptor belong to this mapping */
|
|
struct shim_fd_handle ** map;
|
|
};
|
|
|
|
/* allocating file descriptors */
|
|
#define FD_NULL ((FDTYPE)-1)
|
|
#define HANDLE_ALLOCATED(fd_handle) ((fd_handle) && (fd_handle)->vfd != FD_NULL)
|
|
|
|
struct shim_handle * __get_fd_handle (FDTYPE fd, int * flags,
|
|
struct shim_handle_map * map);
|
|
struct shim_handle * get_fd_handle (FDTYPE fd, int * flags,
|
|
struct shim_handle_map * map);
|
|
int set_new_fd_handle (struct shim_handle * hdl, int flags,
|
|
struct shim_handle_map * map);
|
|
int set_new_fd_handle_by_fd (FDTYPE fd, struct shim_handle * hdl,
|
|
int flags, struct shim_handle_map * map);
|
|
struct shim_handle *
|
|
__detach_fd_handle (struct shim_fd_handle * fd, int * flags,
|
|
struct shim_handle_map * map);
|
|
struct shim_handle * detach_fd_handle (FDTYPE fd, int * flags,
|
|
struct shim_handle_map * map);
|
|
|
|
/* manage handle mapping */
|
|
int dup_handle_map (struct shim_handle_map ** new_map,
|
|
struct shim_handle_map * old_map);
|
|
int flush_handle_map (struct shim_handle_map * map);
|
|
void get_handle_map (struct shim_handle_map * map);
|
|
void put_handle_map (struct shim_handle_map * map);
|
|
int walk_handle_map (int (*callback) (struct shim_fd_handle *,
|
|
struct shim_handle_map *),
|
|
struct shim_handle_map * map);
|
|
|
|
int init_handle (void);
|
|
int init_important_handles (void);
|
|
|
|
off_t get_file_size (struct shim_handle * file);
|
|
|
|
int do_handle_read (struct shim_handle * hdl, void * buf, int count);
|
|
int do_handle_write (struct shim_handle * hdl, const void * buf, int count);
|
|
|
|
#endif /* _SHIM_HANDLE_H_ */
|